物体投射的阴影真的远离光源

问题描述 投票:2回答:1

我有一个问题,物体投射的阴影离光源很远。我正在使用深度图方法在我的太阳系模拟中渲染阴影。太阳是点光源,我想观察地球上月亮的影子。但由于月亮相对于它与太阳之间的距离是一个非常微小的物体,并且由于深度图分辨率有限,因此在渲染深度立方体贴图纹理时会忽略月球和地球的存在。

太阳系深度图:

enter image description here

你可以看到,即使夸大了月亮的大小,它也只会在深度立方体贴图上留下一小块空间。有了这个大月,日食确实有效,但是一旦我将月亮缩小到它的实际大小,它就不再在深度图中渲染,因此不再考虑阴影计算。我使用的是4096 X 4096纹理。有没有办法解决这个问题,还是我的方法注定要失败?任何帮助将非常感激。

opengl shadow
1个回答
2
投票

有一个关键的观察要做:当你近距离看地球时,你可能不关心火星上的阴影。因此,不使用立方体贴图对整个太阳系进行阴影贴图,而是使用平面阴影贴图仅覆盖近地区域。

使用4096x4096深度贴图和距离为384000 km的月球,每个纹素的分辨率为~100km,月亮将在阴影贴图上占据半径约20个像素的圆盘。

然而,有一种更好的方法。由于行星和卫星是近似球形的,并且只有少数几个,你可以简单地对每个碎片进行射线球交叉以计算阴影。可以计算月球和太阳盘之间交叉的角度区域,以获得实时的本影/半影渲染。这是一个近似着色器中阴影因子的函数:

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意味着没有阴影。 lightoccluderfragment是太阳,月亮和非射影空间中片段的位置,而light_radiusoccluder_radius是太阳和月亮的半径。

对于实际尺寸,此代码为我提供了以下图像:

如果我减少太阳的大小一半,我会得到这些:

© www.soinside.com 2019 - 2024. All rights reserved.