Java 三维阴影的实现思想

Java 三维阴影的实现思想,java,3d,shadow,java-3d,Java,3d,Shadow,Java 3d,假设您的眼睛位于对象A上的曲面点P1中,并且有一个目标对象B,并且在对象B后面有一个点光源 问题:如果我因为物体B而看不见光,那么我看着光源说“我在阴影中”对吗?。然后我将对象A的那个点标记为“A上B的一个阴影点” 如果这是真的,那么我们可以在a的表面上建立一个“阴影几何体”(黑色)对象,然后由于光、B、a等的运动而不断改变它实时?假设一个球体(a)有1000个顶点,而另一个球体(B)也有1000个顶点,那么这是否意味着100万次比较?(是阴影,O(N^2)(时间)复杂性?)。我不确定其复杂性

假设您的眼睛位于对象A上的曲面点P1中,并且有一个目标对象B,并且在对象B后面有一个点光源

问题:如果我因为物体B而看不见光,那么我看着光源说“我在阴影中”对吗?。然后我将对象A的那个点标记为“A上B的一个阴影点”

如果这是真的,那么我们可以在a的表面上建立一个“阴影几何体”(黑色)对象,然后由于光、B、a等的运动而不断改变它实时?假设一个球体(a)有1000个顶点,而另一个球体(B)也有1000个顶点,那么这是否意味着100万次比较?(是阴影,O(N^2)(时间)复杂性?)。我不确定其复杂性,因为改变P1(眼睛)也会改变B的可见点(P1和光源点之间)。二阶阴影和更高阶阴影(例如灯光在两个对象之间多次反射)如何

我现在正在使用java-3D,但它没有影子功能,所以我考虑转移到其他与java兼容的库

谢谢

编辑:我需要在移动摄影机以生成阴影时禁用“摄影机”。我该怎么做?这会严重降低性能吗

新想法:java3D内置了碰撞检测功能。我将创建从灯光到目标多边形顶点的线(不可见),然后检查来自另一个对象的碰撞。如果发生碰撞,则添加该顶点corrd。添加到阴影列表,但这仅适用于点光源:(

任何为java3d提供真正的shade库的人都会很有帮助。

java3D中非常小的示例Geomlib阴影/光线跟踪将是最好的 也许是光线追踪的例子

我知道这有点难,但至少有一百人可以尝试


谢谢。

阴影可能是3D图形编程中最复杂的主题,有很多方法,但最好的选择应该根据任务要求确定。您所讨论的算法是实现从聚光灯光源到平面上阴影的最简单方法。它不应该在CPU上完成,而应该是如果您已经使用GPU进行三维渲染

基本上,该方法是渲染同一对象两次:一次从摄影机视点渲染,一次从光源视点渲染。您需要准备模型视图矩阵以在这两个视图之间进行转换。从光源视点渲染对象后,您将获得深度贴图,其中每个点都离光源最近。然后对于正常渲染的每个像素,您应该将其3D坐标转换为上一个视图,并对照相应的深度值进行检查。这本质上为您提供了一种方法,可以告诉您哪些像素被阴影覆盖

对性能的影响来自于两次渲染同一对象。如果您的任务没有假定阴影投射解决方案具有很高的可扩展性,那么这可能是一种可行的方法

若干相关问题:


基本上是的,你的方法会产生阴影。但是逐点进行是不可行的(对于实时性而言),除非是在GPU上进行。我不熟悉API今天提供的内容,但我相信最近的任何引擎都会提供一些开箱即用的阴影


你的“新想法”是在仍然使用CPU进行渲染的日子里阴影是如何实现的。如果多边形的数量不是太大(或者你可以通过对体积进行分组等有效地拒绝整束)这可以用相当少的CPU功率来完成。

在vanilla Java上进行3D阴影渲染永远不会有效率。您最好使用为充分利用图形卡的全部功能而编写的图形库,如OpenGL或DirectX。当您使用Canvas时(来自您提供的屏幕截图),您甚至可以使用JNI从本机代码绘制画布。因此,您可以使用graphial库中的所有技术,只需稍加修改,就可以直接从本机代码绘制画布。与编写自己的3D引擎相比,要使画布正常工作,所需的工作非常少

关于AWT本机访问的Wiki链接:
文档:

您的方法可以总结如下:

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
    }
 }
这似乎快了很多……但仍然存在两个问题:

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

    • 为了找到灯光可见的所有点,请在那里放置一个摄影机并渲染整个场景!深度测试将拒绝不可见点
    • 若要使此结果稍后可访问,请将其另存为纹理,并在实际渲染阶段使用该纹理进行查找


    这项技术被称为阴影贴图,从光线中可见像素的纹理被称为阴影贴图。有关更详细的解释,请参阅示例。

    当然可以。这将在CPU上花费一些成本,但在GPU的时代,这是完全可能的。OpenGL和Java3D应该能够做到这一点。T他的技术早已广为人知。我知道java3D是一个线程化的实现,但它有改进吗