Opengl 我的阴影贴图实现有什么问题?

Opengl 我的阴影贴图实现有什么问题?,opengl,glsl,Opengl,Glsl,我正在尝试在我的游戏中实现阴影贴图。您在下面看到的着色器会为游戏地图正确绘制阴影,但地图上的所有模型都是完全黑色的 以下是一个屏幕截图: 我怀疑问题在于对世界地位的计算。gl_顶点不会以任何方式变换。由于贴图是使用绝对世界坐标生成的,因此使用灯光矩阵的变换会产生正确的相对位置,可用于执行阴影贴图 然而,我的3D模型都非常接近原点。因此,如果使用光矩阵对它们的坐标进行简单变换,它们很可能永远不会被照亮 我想知道这是不是真的,如果是的话,我该如何解决它 这是我的顶点着色器: #version 12

我正在尝试在我的游戏中实现阴影贴图。您在下面看到的着色器会为游戏地图正确绘制阴影,但地图上的所有模型都是完全黑色的

以下是一个屏幕截图:

我怀疑问题在于对世界地位的计算。gl_顶点不会以任何方式变换。由于贴图是使用绝对世界坐标生成的,因此使用灯光矩阵的变换会产生正确的相对位置,可用于执行阴影贴图

然而,我的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阴影贴图位置; 可变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;
}
统一采样2D深度图;
均匀vec4光位;
真空总管(真空)
{
vec4纹理颜色=gl_颜色;
vec3 realShadowMapPosition=shadowMapPosition.xyz/shadowMapPosition.w;
float depthSm=texture2D(depthMap,realShadowMapPosition.xy).r;
if(深度
我在这里写这篇文章是因为它不适合上面的内容,我希望它能解决您的问题

在渲染时,一方面使用模型及其模型矩阵来定位元素,另一方面使用视图和投影矩阵将模型转换为屏幕空间

为了创建阴影贴图(最简单的方法,我猜是您选择的方法),您从光源的视图渲染场景,因此您应用光源的视图和投影矩阵,它将
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;
这通常在片段着色器中完成:

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
进行比较,查看对象是否处于阴影中


因此,在第二个过程中,您将再次执行阴影贴图的步骤,除了您不绘制计算的数据,而是将其与之前在过程中计算的数据进行比较。

首先,屏幕截图没有告诉任何事情-第二-为什么这么复杂?只需在第一次通过时从灯光角度渲染场景-由于深度测试,阴影中的曲面位置将被更接近灯光的位置覆盖!在第二步中,从眼睛的角度渲染场景,同时将顶点变换为灯光pov,以执行阴影贴图检查@在我看来,迪诺尼似乎就是这样做的。在灯光pov中有用于转换的
LightMatrixValue*modelPos
。以及相应的查找。但是,如果不知道阴影贴图是如何创建的,就很难猜出什么是错误的<代码>0.5*(lightPos.xyzw+lightPos.www)可能是问题所在。还有纹理查找中的
realShadowMapPosition.xy
。@dinony:我确实已经像t.niese指出的那样做了。就我所见,问题在于计算阴影距离本身。贴图上投射了正确的阴影,因为它前面的单位遮挡了像素。这些单位没有这样做,因为它们没有以一种能够给出它们相对于灯光位置的位置的方式进行变换。@t.niese:我使用一个额外的渲染过程来创建阴影贴图,该渲染过程仅从灯光的角度存储像素的深度。如果需要,我可以添加代码。阴影贴图的创建方式(阴影代码)始终很重要,因为这会影响sotred
z
值。为什么要这样做
0.5*(lightPos.xyzw+lightPos.wwww)
(您对此有何期望)lightPos这是从光源位置原点到顶点的向量(假设
LightMatrixValue
是阴影着色器中使用的相同矩阵)。因此,通过此计算(取决于
w
),您将点移向光源或另一个方向。不幸的是,这并没有解决我的问题。然而,它确实去掉了一个水平条,这是我用来将模型坐标“转换”到屏幕空间的丑陋破解的结果。另外,你的方法比我的漂亮多了。我想这足够考虑我的问题了: