假设你的眼睛在物体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阴影/光线追踪可能是最好的光线追踪示例?
我知道这有点难,但至少有一百人可以尝试。
谢谢。
阴影可能是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
}
}
这似乎快得多…但是仍然存在两个问题:
这是棘手的部分:
这种技术称为阴影映射,从光中可见像素的纹理称为阴影映射。有关更详细的解释,请参阅例如维基百科文章。
基本上是的,你的方法会产生阴影。但是一点一点地做是不可行的性能明智的(对于实时),除非是在图形处理器上做的。我不熟悉API今天提供了什么,但是我相信任何最近的引擎都会提供一些开箱即用的阴影。
你的“新想法”是如何在渲染仍然使用CPU的时代实现阴影的。如果多边形的数量不是太大(或者你可以通过分组卷等有效地拒绝整个束),它可以用相当少的CPU来完成。