3D Shadow的实现思路 - java

假设您的眼睛在对象A的表面点P1上,并且有目标对象B,并且在对象B后面有点光源。
问题:是对的,如果我看着光源,如果由于物体B而看不到光,则说“我在阴影中”。然后,我将对象A的该点标记为“B在A上的阴影点之一”。

如果这是真的,那么我们可以在A的表面上构建一个“阴影几何”(黑色)对象,然后由于光,B,A等的运动而不断对其进行更改吗?实时?假设一个球体(A)具有1000个顶点,其他球体(B)也具有1000个顶点,那么这意味着1百万个比较吗? (是阴影,O(N ^ 2)(时间)复杂度吗?)。我不确定复杂性,因为更改P1(眼睛)也会更改B的可见点(在P1和光源点之间)。那么二阶或更高阶的阴影(例如光在两个对象之间多次反射)又如何呢?
我现在使用的是Java-3D,但它不具有阴影功能,因此我想转向其他兼容Java的库。
谢谢。
编辑:我需要在移动照相机以建立阴影时禁用“照相机”。我怎样才能做到这一点?这会严重降低性能吗?
新思路: java3D具有内置的冲突检测功能。我将创建从光到目标多边形顶点的线(不可见),然后检查是否存在与另一个对象的碰撞。如果发生碰撞,请添加该顶点皮质。到阴影列表,但这仅适用于点光源:(。
为Java3d提供真正的阴影库的任何人都会有很大帮助。
java3D中的极小样本Geomlib阴影/光线跟踪将是最好的
光线追踪的例子吗?
我知道这有点难,但是至少可以有一百个人尝试过。
谢谢。

参考方案

您的方法可以总结如下:

foreach (point p to be shaded) {
    foreach (light) {
        if (light is visible from p)
            // p is lit by that light
        else
            // p is in shadow
    }
}

有趣的是,这就是今天在GPU 上完成实时阴影的方式。

但是,要有效地工作并非易事。渲染场景是一个简化的过程,一个接一个的三角形。如果对于每个三角形中的每个点(像素,片段),您都需要考虑其他三角形中的所有其他三角形以检查射线相交,则将非常麻烦。

那么如何有效地做到这一点呢?答:逆转该过程。

通常,场景中的灯光远少于像素。让我们利用这一事实并进行一些预处理:

// preprocess
foreach (light) {
    // find all pixels p on the scene reachable from the light
}
// then render the whole scene...
foreach (point p to be shaded) {
    foreach (light) {
        // simply look up into what was calculated before...
        if (p is visible by the light)
            // p is lit
        else
            // p is in shadow
    }
 }

这看起来要快得多……但是仍然存在两个问题:

  • 如何找到光线可见的所有像素?
  • 如何在渲染期间快速访问它们以进行查找?
  • 有一个棘手的部分:

  • 为了找到灯光可见的所有点,请在此处放置相机并渲染整个场景!深度测试将拒绝看不见的点。
  • 要在以后访问此结果,请将其另存为纹理,并在实际渲染阶段使用该纹理进行查找。
  • 此技术称为阴影贴图,并且具有从光源可见的像素的纹理称为阴影贴图。有关更详细的说明,请参见例如Wikipedia article。

    Java:线程池如何将线程映射到可运行对象 - java

    试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

    JAVA:字节码和二进制有什么区别? - java

    java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…

    java:继承 - java

    有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

    Java:BigInteger,如何通过OutputStream编写它 - java

    我想将BigInteger写入文件。做这个的最好方式是什么。当然,我想从输入流中读取(使用程序,而不是人工)。我必须使用ObjectOutputStream还是有更好的方法?目的是使用尽可能少的字节。谢谢马丁 参考方案 Java序列化(ObjectOutputStream / ObjectInputStream)是将对象序列化为八位字节序列的一种通用方法。但…

    Java DefaultSslContextFactory密钥库动态更新 - java

    我有一个使用org.restlet.engine.ssl.DefaultSslContextFactory的现有应用程序和一个在服务器启动时加载的密钥库文件。我有另一个应用程序,该应用程序创建必须添加的证书服务器运行时动态地更新到密钥库文件。为此,我在代码中创建了证书和私钥,然后将其写入到目录。该目录由bash脚本监视,该脚本检查是否有新文件,如果出现,它将…