【问题标题】:3D Shadow implementation idea3D阴影实现思路
【发布时间】:2012-08-21 20:53:26
【问题描述】:

假设您的眼睛位于对象 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 阴影库的人都会很有帮助。

java3D 中的极小样本 Geomlib 阴影/光线追踪将是最好的 可能是光线追踪示例?

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

谢谢。

【问题讨论】:

  • 当然可以。它会在 CPU 上花费一些东西,但在 GPU 的时代,这是很有可能的。 OpenGL 和 Java3D 应该能够做到。这是早已为人所知的技术。
  • 我知道 java3D 是一个线程实现,但是在多核 cpus 和 gpus 上执行时它会有所改进吗?
  • 我的猜测是多核是“是”,因为将线程分配给一个核心是有意义的。 GPU 是另一回事,因为作者必须明确写入 NVIDIA API。您会知道,因为您需要将 NVIDIA .dll 添加到 PATH。我对 GPU 的猜测是“不”。
  • 你能在你的答案中举一个光线追踪/阴影的小例子吗?

标签: java 3d shadow java-3d


【解决方案1】:

您的方法可以总结如下:

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
    }
 }

这似乎快了很多......但仍然存在两个问题:

  1. 如何找到光线可见的所有像素?
  2. 如何在渲染过程中快速访问它们以进行查找?

有一个棘手的部分:

  • 为了找到光源可见的所有点,在此处放置一个相机并渲染整个场景!深度测试会剔除不可见的点。
  • 要让此结果稍后可访问,请将其保存为纹理并在实际渲染阶段使用该纹理进行查找。

这种技术称为Shadow Mapping,具有从灯光可见的像素的纹理称为Shadow Map。有关更详细的说明,请参阅例如Wikipedia article

【讨论】:

  • (为了完整起见,请阅读 Shadow volume,这是一种过去在游戏中非常流行的不同的阴影方法)
【解决方案2】:

普通 Java 上的 3D 阴影渲染永远不会高效。您最好使用为利用图形卡的全部功能而编写的图形库,例如 OpenGL 或 DirectX。当您使用 Canvas(来自您提供的屏幕截图)时,您甚至可以使用 JNI 从本机代码绘制该 Canvas。因此,您可以使用图形库中的所有技术,只需稍作改动,直接从本机代码绘制您的 Canvas。与编写您自己的 3D 引擎相比,使其工作所需的工作量很少。

关于 AWT 原生访问的 Wiki 链接:http://en.wikipedia.org/wiki/Java_AWT_Native_Interface 文档:http://docs.oracle.com/javase/7/docs/technotes/guides/awt/AWT_Native_Interface.html

【讨论】:

    【解决方案3】:

    基本上是的,你的方法会产生阴影。但是逐点进行是不可行的性能明智(实时),除非它在 ​​GPU 上完成。我不熟悉 API 现在提供的功能,但我确信任何最近的引擎都会提供一些开箱即用的影子。

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

    【讨论】:

      【解决方案4】:

      Shadows 可能是 3D 图形编程中最复杂的主题,并且有很多方法,但应根据任务要求确定最佳选项。您正在谈论的算法是实现从聚光灯到平面的阴影的最简单方法。它不应该在 CPU 上完成,因为您已经使用 GPU 进行 3D 渲染。

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

      性能影响来自两次渲染同一个对象。如果您的任务不假设阴影投射解决方案的高可扩展性,那么它可能是一种可行的方法。

      一些相关问题:

      How Do I Create Cheap Shadows In OpenGL?

      Is there an easy way to get shadows in OpenGL?

      What is the simplest method for rendering shadows on a scene in OpenGL?

      【讨论】:

        猜你喜欢
        • 2014-10-01
        • 2014-03-13
        • 1970-01-01
        • 2013-07-28
        • 1970-01-01
        • 1970-01-01
        • 2021-10-27
        • 2013-02-20
        • 1970-01-01
        相关资源
        最近更新 更多