提问者:小点点

3D影子实现思路


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

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

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

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

谢谢。

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

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

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

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

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

谢谢。


共3个答案

匿名用户

阴影可能是3D图形编程中最复杂的话题,有很多方法,但最好的选择应该根据任务要求来确定。你说的算法是从点光源到平面上实现阴影的最简单方法。它不应该在CPU上完成,因为你已经使用GPU进行3D渲染了。

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

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

一些相关问题:

如何在OpenGL中创建廉价的阴影?

有没有一种简单的方法可以在OpenGL中获得阴影?

在OpenGL中渲染场景阴影的最简单方法是什么?

匿名用户

您的方法可以总结如下:

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. 如何使它们在渲染期间快速访问以进行查找?

这是棘手的部分:

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

这种技术称为阴影映射,从光中可见像素的纹理称为阴影映射。有关更详细的解释,请参阅例如维基百科文章。

匿名用户

基本上是的,你的方法会产生阴影。但是一点一点地做是不可行的性能明智的(对于实时),除非是在图形处理器上做的。我不熟悉API今天提供了什么,但是我相信任何最近的引擎都会提供一些开箱即用的阴影。

你的“新想法”是如何在渲染仍然使用CPU的时代实现阴影的。如果多边形的数量不是太大(或者你可以通过分组卷等有效地拒绝整个束),它可以用相当少的CPU来完成。