通过texture2D函数使用自动比较从阴影贴图纹理中采样数据

时间:2011-07-28 10:06:33

标签: c++ opengl shadow

我的着色器中有一个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>

1 个答案:

答案 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);

其中nf是glDepthRange near和far值。你当然可以预先计算其中一些并将它们作为制服传递给你。或者,如果您使用默认范围near = 0和far = 1,则得到

texCoords.z = ndc_space_values.z * 0.5 + 0.5;

以某种方式看起来很熟悉。

<强>除了:

由于您使用in而不是varying定义了输入,因此您必须使用GLSL 1.30或更高版本。那你为什么要使用texture2D(这是一个旧函数)而不是texture