让我们假设你的眼睛在物体A的表面点P1,并且有一个目标物体B,并且在物体B后面有一个点光源。
问题:如果我看光源并说“我在阴影中”,如果由于物体B我看不到光线,我是对的吗?然后我将对象A的那个点标记为“A上B的阴影点之一”。
如果这是真的,那么我们可以在A的表面上构建一个“阴影几何”(黑色)对象,然后由于光,B,A等的运动而不断地改变它...... in实时?让我们说球体(A)有1000个顶点而其他球体(B)也有1000个顶点,那么这意味着1个百万的比较吗? (是阴影,O(N ^ 2)(时间)复杂性?)。我不确定复杂性,因为改变P1(眼睛)也会改变B的观察点(P1和光源点之间)。那么二阶阴影和更高的阴影(例如两次物体之间多次反射的光线)?
我现在正在使用java-3D,但它没有阴影功能,所以我想转移到其他兼容java的库。
感谢。
编辑:我需要在移动相机时禁用“相机”来构建阴影。我怎样才能做到这一点?这会严重降低性能吗?
新想法: java3D具有内置的碰撞检测功能。我将创建从光到目标多边形顶点的线(不可见),然后检查来自另一个对象的碰撞。如果发生冲突,请添加该顶点corrd。到阴影列表,但这只适用于点光源:(。
任何为java3d提供真正阴影库的人都会非常有帮助。
java3D中非常小的样本Geomlib阴影/光线跟踪将是最好的 光线跟踪的例子可能吗?
我知道这有点难,但至少有一百人可以试过。
感谢。
答案 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
}
}
这似乎要快得多......但仍存在两个问题:
有一个棘手的部分:
此技术称为阴影贴图,具有从灯光可见像素的纹理称为阴影贴图。有关更详细的说明,请参阅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