我正在尝试在游戏中实现阴影贴图。您在下面看到的着色器会为游戏地图生成正确的阴影,但在地图上四处走动的所有模型都是完全黑色的。
以下是截图:
我怀疑问题在于计算世界位置。 gl_Vertex不会以任何方式进行转换。由于地图是使用绝对世界坐标生成的,因此使用光矩阵进行的变换会产生正确的相对位置,可用于执行阴影贴图。
然而,我的3D模型都非常接近原点。因此,如果使用光矩阵明确地转换它们的坐标,它们很可能永远不会被点亮。
我想知道是否会出现这种情况,如果是的话,我该如何解决它。
这是我的顶点着色器:
#version 120
uniform mat4x4 LightMatrixValue;
varying vec4 shadowMapPosition;
varying vec3 worldPos;
void main(void)
{
vec4 modelPos = gl_Vertex;
worldPos=modelPos.xyz/modelPos.w;
vec4 lightPos = LightMatrixValue*modelPos;
shadowMapPosition = 0.5 * (lightPos.xyzw +lightPos.wwww);
gl_Position = ftransform();
}
片段着色器: 改变vec4 shadowMapPosition; 改变vec3 worldPos;
uniform sampler2D depthMap;
uniform vec4 LightPosition;
void main(void)
{
vec4 textureColour = gl_Color;
vec3 realShadowMapPosition = shadowMapPosition.xyz/shadowMapPosition.w;
float depthSm = texture2D(depthMap, realShadowMapPosition.xy).r;
if (depthSm < realShadowMapPosition.z-0.0001)
{
textureColour = vec4(0, 0, 0, 1);
}
gl_FragColor= textureColour;
}
答案 0 :(得分:1)
我在这里写这个因为它不适合上面,我希望它能解决你的问题。
为了让你一方面让你的模型有他们的模型矩阵来定位元素,另一方面你有视图和投影矩阵来改变你的模型进入屏幕空间。
为了创建阴影贴图(最简单的方法,我想你选择的那个),你可以从光源的视图渲染场景,所以你应用视图和投影光源矩阵,它会将x
,y
和z
值映射到屏幕空间。 x
和y
值用于图像中的位置,z
用于深度缓冲测试以及您在颜色缓冲区中写入的颜色(稍后用作阴影贴图) )。
对于最终渲染,您可以将此阴影贴图和灯光的视图和投影矩阵加载到着色器。对于场景中的显示,您将摄像机的视图和项目矩阵应用于顶点,对于阴影贴图查找,您应用视图和投影光到顶点的矩阵(就像你对阴影贴图的渲染一样)。将灯光视图和投影矩阵应用于顶点时,您将获得与阴影贴图通道中相同的映射,现在您只需转换x
和y
坐标到纹理坐标并查找存储的z
值,并将其与计算值进行比较。
将模型世界位置转换为屏幕空间(从灯光的角度来看)
此部分通常在顶点或几何着色器中完成:
shadowMapPosition = matLightViewProjection * modelWoldPos;
这通常在片段着色器中完成:
shadowMapPosition = shadowMapPosition / shadowMapPosition.w ;
// Add an offset to prevent self-shadowing and moiré pattern
shadowMapPosition.z += 0.0005;
//lookup the stored z value
float distanceFromLight = texture2D(depthMap,shadowMapPosition.xz).z;
现在只需将distanceFromLight
与shadowMapPosition.z
进行比较,看看对象是否在阴影中。
因此,在第二遍中,您将再次执行阴影贴图的步骤,不同之处在于您不绘制计算出的数据,而是将其与之前通过中计算的数据进行比较。