我遇到一个问题,即物体所投射的阴影确实远离光源。我正在使用深度图方法在太阳系仿真中渲染阴影。太阳是点光源,我想观察月球在地球上的阴影。但是由于相对于月亮与太阳之间的距离而言,月亮是一个非常小的物体,并且由于深度图的分辨率受到限制,因此在渲染深度立方体图纹理时,会忽略月亮和地球的存在。
太阳能系统深度图:
您可以看到,即使月亮的大小被夸大了,它在深度立方体图上也只留下了很小的足迹。在月球如此大的情况下,日食确实起作用,但是一旦我将月球缩小到其实际大小,就不再在深度图中进行渲染,因此不再将其用于阴影计算。我正在使用4096 X 4096纹理。有没有办法解决这个问题,还是我的方法注定要失败?任何帮助将不胜感激。
答案 0 :(得分:2)
有一个至关重要的发现:当您抬头近地时,您可能根本不在乎火星上的阴影。因此,不要使用立方体贴图对整个太阳系进行阴影贴图,而应使用平面阴影贴图仅覆盖近地区域。
使用4096x4096深度图,到月球的距离为384000 km,您可以获得每个texel约100km的分辨率,并且月亮在阴影图上将占据半径约20 texels的圆盘。
但是,有一种更好的方法。由于行星和卫星大约是球形的,并且只有少数几个,因此您可以简单地对每个片段进行射线-球形相交以计算阴影。可以计算月亮和太阳圆盘之间的交点的角区域,以获得实时的本影/半影渲染。这是一个近似着色器中阴影因子的函数:
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);
}
这里0.0
表示完整阴影,1.0
表示完全没有阴影。 light
,occluder
和fragment
是太阳,月亮和碎片在非投影空间中的位置,而light_radius
和{ occluder_radius
是太阳和月亮的半径。
对于实际尺寸,此代码为我提供了这些图像:
如果我将太阳的大小减半,我会得到: