我的着色器中有一个sampler2DShadow,我想用它来实现阴影贴图。我的阴影纹理具有良好的初始化器,GL_TEXTURE_COMPARE_MODE设置为GL_COMPARE_R_TO_TEXTURE,GL_TEXTURE_COMPARE_FUNC设置为GL_LEQUAL(意味着如果我的坐标的r值小于或等于纹理中获取的深度值,则比较应返回1)。此纹理绑定到以光空间坐标呈现的FBO的GL_DEPTH_ATTACHMENT。
我应该在最终片段着色器中给出texture2D函数的坐标是什么?我目前有一个
在vec4中光滑light_vert_pos
在我的片段着色器中设置,该着色器由函数
在顶点着色器中定义light_vert_pos = light_projection_camera_matrix * modelview * in_Vertex;
我认为我可以将我的灯光乘以值
的Texture2D(阴影贴图,(light_vert_pos.xyz)/light_vert_pos.w)
但这似乎不起作用。由于light_vert_pos只在后投影坐标中(用于创建它的矩阵是我用来在FBO中创建深度缓冲区的矩阵),我应该手动将3 x / y / z变量钳制到[0,1]吗? / p>
答案 0 :(得分:2)
您没有说明如何生成深度值。所以我假设您通过使用法线投影渲染三角形来生成深度值。也就是说,您将几何体转换为相机空间,将其转换为投影空间,并让光栅化管道正常处理事物。
为了使阴影贴图起作用,您的纹理坐标必须与光栅化器的坐标相匹配。
顶点着色器的输出是剪辑空间。从那里,您获得透视分割,然后是视口变换。后者使用glViewport和glDepthRange中的值来计算窗口空间XYZ。窗口空间Z是写入深度缓冲区的深度值。
请注意,这一切都在深度传递期间:生成阴影贴图的深度值。
但是,您可以采取一些快捷方式。如果你的glViewport范围被设置为与纹理相同的大小(通常是这样做的话),那么你可以忽略视口变换。您仍然需要在深度传递中使用的glDepthRange。
在片段着色器中,您可以执行透视分割,将坐标放在标准化设备坐标(NDC)空间中。所有方向的空间都是[-1,1]。你的纹理坐标是[0,1],所以你需要将X和Y除以2并将它们加0.5:
vec3 ndc_space_values = light_vert_pos.xyz / light_vert_pos.w
vec3 texCoords;
texCoords.xy = ndc_space_values.xy * 0.5 + 0.5;
要计算Z值,您需要知道用于glDepthRange
的近和远值。
texCoords.z = ((f-n) * 0.5) * ndc_space_values.z + ((n+f) * 0.5);
其中n
和f
是glDepthRange near和far值。你当然可以预先计算其中一些并将它们作为制服传递给你。或者,如果您使用默认范围near = 0和far = 1,则得到
texCoords.z = ndc_space_values.z * 0.5 + 0.5;
以某种方式看起来很熟悉。
<强>除了:强>
由于您使用in
而不是varying
定义了输入,因此您必须使用GLSL 1.30或更高版本。那你为什么要使用texture2D
(这是一个旧函数)而不是texture
?