简体   繁体   English

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

[英]Sampling data from a shadow map texture using automatic comparison via the texture2D function

I've got a sampler2DShadow in my shader and I want to use it to implement shadow mapping. 我的着色器中有一个sampler2DShadow,我想用它来实现阴影贴图。 My shadow texture has the good initializers, with GL_TEXTURE_COMPARE_MODE set to GL_COMPARE_R_TO_TEXTURE and GL_TEXTURE_COMPARE_FUNC set to GL_LEQUAL (meaning that the comparison should return 1 if the r value of my coordinates are less or equal to the depth value fetched in the texture). 我的阴影纹理具有良好的初始化器,GL_TEXTURE_COMPARE_MODE设置为GL_COMPARE_R_TO_TEXTURE,GL_TEXTURE_COMPARE_FUNC设置为GL_LEQUAL(意味着如果我的坐标的r值小于或等于纹理中获取的深度值,则比较应返回1)。 This texture is bound to the GL_DEPTH_ATTACHMENT of a FBO rendered in light space coordinates. 此纹理绑定到在光空间坐标中渲染的FBO的GL_DEPTH_ATTACHMENT。

What coordinates should I give the texture2D function in my final fragment shader? 我应该在最终片段着色器中给出texture2D函数的坐标是什么? I currently have a 我现在有一个

smooth in vec4 light_vert_pos 光滑的vec4 light_vert_pos

set in my fragment shader that is defined in the vertex shader by the function 在我的片段着色器中设置,该着色器由函数在顶点着色器中定义

light_vert_pos = light_projection_camera_matrix*modelview*in_Vertex; light_vert_pos = light_projection_camera_matrix * modelview * in_Vertex;

I would assume I could multiply my lighting by the value 我想我可以将我的照明倍增

texture2D(shadowmap,(light_vert_pos.xyz)/light_vert_pos.w) 的Texture2D(阴影贴图,(light_vert_pos.xyz)/light_vert_pos.w)

but this does not seem to work. 但这似乎不起作用。 Since light_vert_pos is only in post projective coordinates (the matrix used to create it is the matrix I use to create the depth buffer in the FBO), should I manually clamp the 3 x/y/z variables to [0,1]? 由于light_vert_pos仅在后投影坐标中(用于创建它的矩阵是我用来在FBO中创建深度缓冲区的矩阵),我应该手动将3 x / y / z变量钳制到[0,1]吗?

You don't say how you generated your depth values. 您没有说明如何生成深度值。 So I'll assume you generated your depth values by rendering triangles using normal projection. 所以我假设您通过使用法线投影渲染三角形来生成深度值。 That is, you transform the geometry to camera space, transform it to projection space, and let the rasterization pipeline handle things from there as normal. 也就是说,您将几何体转换为相机空间,将其转换为投影空间,并让光栅化管道正常处理事物。

In order to make shadow mapping work, your texture coordinates must match what the rasterizer did. 为了使阴影贴图起作用,您的纹理坐标必须与栅格化器的作用相匹配。

The output of a vertex shader is clip-space. 顶点着色器的输出是剪辑空间。 From there, you get the perspective divide, followed by the viewport transform. 从那里,您获得透视分割,然后是视口变换。 The latter uses the values from glViewport and glDepthRange to compute the window-space XYZ. 后者使用glViewport和glDepthRange中的值来计算窗口空间XYZ。 The window-space Z is the depth value written to the depth buffer. 窗口空间Z是写入深度缓冲区的深度值。

Note that this is all during the depth pass: the generation of the depth values for the shadow map. 请注意,这是深度传递期间的全部内容:生成阴影贴图的深度值。

However, you can take some shortcuts. 但是,您可以采取一些快捷方式。 If your glViewport range was set to the same size as the texture (which is generally how it's done), then you can ignore the viewport transform. 如果你的glViewport范围被设置为与纹理相同的大小(通常是这样做的话),那么你可以忽略视口变换。 You will still need the glDepthRange you used in the depth pass. 您仍然需要在深度传递中使用的glDepthRange。

In your fragment shader, you can perform the perspective divide, which puts the coordinates in normalized device coordinate (NDC) space. 在片段着色器中,您可以执行透视分割,它将坐标放在标准化设备坐标(NDC)空间中。 That space is [-1, 1] in all directions. 所有方向的空间都是[-1,1]。 Your texture coordinates are [0, 1], so you need to divide the X and Y by two and add 0.5 to them: 你的纹理坐标是[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;

To compute the Z value, you need to know the near and far values you use for glDepthRange . 要计算Z值,您需要知道用于glDepthRange的near和far值。

texCoords.z = ((f-n) * 0.5) * ndc_space_values.z + ((n+f) * 0.5);

Where n and f are the glDepthRange near and far values. 其中nf是glDepthRange near和far值。 You can of course precompute some of these and pass them as uniforms. 你当然可以预先计算其中一些并将它们作为制服传递给你。 Or, if you use the default range of near=0 and far=1, you get 或者,如果您使用near = 0和far = 1的默认范围,则得到

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

Which looks familiar somehow. 哪个看起来很熟悉。

Aside: 在旁边:

Since you defined your inputs with in rather than varying , you have to be using GLSL 1.30 or above. 由于您使用in而不是varying来定义输入,因此必须使用GLSL 1.30或更高版本。 So why are you using texture2D (which is an old function) rather than texture ? 那么为什么你使用texture2D (这是一个旧函数)而不是texture

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM