3D影子实施理念

时间:2012-08-27 11:04:14

标签: java 3d shadow java-3d

让我们假设你的眼睛在物体A的表面点P1,并且有一个目标物体B,并且在物体B后面有一个点光源。

问题:如果我看光源并说“我在阴影中”,如果由于物体B我看不到光线,我是对的吗?然后我将对象A的那个点标记为“A上B的阴影点之一”。

enter image description here

如果这是真的,那么我们可以在A的表面上构建一个“阴影几何”(黑色)对象,然后由于光,B,A等的运动而不断地改变它...... in实时?让我们说球体(A)有1000个顶点而其他球体(B)也有1000个顶点,那么这意味着1个百万的比较吗? (是阴影,O(N ^ 2)(时间)复杂性?)。我不确定复杂性,因为改变P1(眼睛)也会改变B的观察点(P1和光源点之间)。那么二阶阴影和更高的阴影(例如两次物体之间多次反射的光线)?

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

感谢。

编辑:我需要在移动相机时禁用“相机”来构建阴影。我怎样才能做到这一点?这会严重降低性能吗?

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

任何为java3d提供真正阴影库的人都会非常有帮助。

java3D中非常小的样本Geomlib阴影/光线跟踪将是最好的 光线跟踪的例子可能吗?

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

感谢。

4 个答案:

答案 0 :(得分:3)

阴影可能是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?

答案 1 :(得分:2)

您的方法可以概括为:

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. 如何在渲染过程中快速访问它们以进行查找?
  3. 有一个棘手的部分:

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

    此技术称为阴影贴图,具有从灯光可见像素的纹理称为阴影贴图。有关更详细的说明,请参阅Wikipedia article

答案 2 :(得分:1)

基本上是的,你的方法会产生阴影。但是,除非在GPU上完成,否则逐点执行并不是可行的性能(实时)。我不熟悉今天的API提供的内容,但我确信任何最近的引擎都会提供开箱即用的阴影。

你的'新想法'是在使用CPU完成渲染的日子里实现阴影 的方式。如果多边形的数量不是太大(或者你可以通过分组卷等来有效地拒绝整个束),那么可以用相当小的CPU功率来完成。

答案 3 :(得分:1)

vanilla 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