Shadows cast by objects really far away from light source
我对远离光源的物体投射的阴影有疑问。我正在使用深度图方法在我的太阳系模拟中渲染阴影。太阳是点光源,我想观察月球在地球上的影子。但是由于月球相对于它与太阳之间的距离而言是一个非常小的物体,并且由于深度图分辨率有限,因此在渲染深度立方体贴图纹理时会忽略月球和地球的存在。
太阳系深度图:
你可以看到,即使月球的大小被夸大了,它也只在深度立方体图上留下了很小的足迹。有了这么大的月亮,Eclipse确实有效,但是一旦我将月亮缩小到其实际大小,它就不再呈现在深度图中,因此,不再考虑阴影计算。我正在使用 4096 X 4096 纹理。有没有办法解决这个问题,还是我的方法注定要失败?任何帮助将不胜感激。
有一个重要的观察:当你近距离观察地球时,你可能并不关心火星上的阴影。因此,不要使用立方体贴图对整个太阳系进行阴影贴图,而是使用平面阴影贴图仅覆盖近地区域。
使用 4096x4096 深度图和 384000 公里的月球距离,您可以获得每纹素约 100 公里的分辨率,并且月球将占据阴影贴图上半径约 20 纹素的圆盘。
不过,还有更好的方法。由于行星和卫星几乎是球形的,而且只有少数几个,因此您可以简单地对每个片段进行射线-球体相交来计算阴影。可以计算月球和太阳圆盘之间交点的angular面积,以获得实时的本影/半影渲染。这是一个近似着色器中阴影因子的函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | float soft_shadow(vec3 light, float light_radius, vec3 occluder, float occluder_radius, vec3 fragment) { vec3 v0 = light - fragment; vec3 v1 = occluder - fragment; float R0 = length(v0); float R1 = length(v1); float a0 = light_radius/R0; float a1 = occluder_radius/R1; float a = length(cross(v0, v1))/(R0*R1); a = smoothstep(a0 - a1, a0 + a1, a); return 1 - (1 - a)*pow(a1/a0, 2); } |
这里
对于实际尺寸,此代码为我提供了这些图像:
如果我将太阳的大小减半,我会得到这些: