0

我正在尝试使用两个使用 OpenGL 和 LWJGL 的独立且不同的着色器编写一个简单的阴影映射引擎。它专门使用 VAO/VBO。旋转相机时会出现此问题。就好像阴影旋转了相机的两倍。

我首先在原点创建一个简单的立方体,并在立方体下方创建一个 2D 平面。

[因篇幅省略代码]

然后我创建了一个“太阳”(随时间移动),它使用正交投影来创建阴影贴图。

光源投影矩阵(近为1,远为100):

lightMatrixStore.getProjectionMatrix().m00 = 1;
lightMatrixStore.getProjectionMatrix().m11 = 1;
lightMatrixStore.getProjectionMatrix().m22 = -2f/(100-1);
lightMatrixStore.getProjectionMatrix().m23 = -((100+1f)/(100-1f));
lightMatrixStore.getProjectionMatrix().m33 = 1;
lightMatrixStore.getProjectionMatrix().m32 = 0;  

设置帧缓冲区/渲染缓冲区/纹理:

depthTextureId = glGenTextures();
glBindTexture(GL_TEXTURE_2D, depthTextureId);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL14.GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 0.5f);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);

glTexImage2D(
      GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadowMapWidth, shadowMapHeight, 0,
      GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, (ByteBuffer) null
);
glBindTexture(GL_TEXTURE_2D, 0);
shadowMapWidth = 2048;
shadowMapHeight = 768*2;

rboId = glGenRenderbuffers();
glBindRenderbuffer(GL_RENDERBUFFER, rboId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, shadowMapWidth, shadowMapHeight);

fboId = glGenFramebuffers();
glBindFramebuffer(GL_FRAMEBUFFER, fboId);

glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTextureId, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

int fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (fboStatus != GL_FRAMEBUFFER_COMPLETE) {
  System.err.print("Framebuffer error " + fboStatus + " : " + gluErrorString(glGetError()));
}

阴影贴图顶点着色器:

#version 150 core

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;

in vec4 in_Position;
in vec4 in_Color;
in vec2 in_TextureCoord;

out vec4 pass_Color;
out vec2 pass_TextureCoord;

void main(void) {
  gl_Position = projectionMatrix * viewMatrix * modelMatrix * in_Position;
  pass_Color = in_Color;
  pass_TextureCoord = in_TextureCoord;
}

和阴影贴图片段着色器:

#version 150 core

uniform sampler2D texture_diffuse;

in vec4 pass_Color;
in vec2 pass_TextureCoord;

out vec4 out_Color;

void main(void) {
  out_Color = pass_Color;
}

程序从灯光的角度渲染场景并创建阴影贴图,然后第二个渲染通道执行环境光照、镜面光照和尝试的阴影。

最终顶点着色器:

#version 150 core

varying vec4 varyingVertex;
varying vec4 projectionVertex;
varying vec3 varyingNormal;
varying vec3 varyingPosition;
varying vec4 shadowCoord;

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
uniform mat4 lightViewMatrix;
uniform mat4 lightProjectionMatrix;

in vec4 in_Position;
in vec4 in_Color;
in vec2 in_TextureCoord;
in vec3 in_Normal;

out vec4 pass_Color;
out vec2 pass_TextureCoord;

void main() {
  varyingVertex = in_Position;
  varyingNormal = in_Normal;
  gl_Position = projectionMatrix * viewMatrix * modelMatrix * in_Position;
  varyingPosition = gl_Position;

  pass_Color = in_Color;
  pass_TextureCoord = in_TextureCoord;
  shadowCoord =  mat4( 0.5, 0.0, 0.0, 0.0,
                       0.0, 0.5, 0.0, 0.0,
                       0.0, 0.0, 0.5, 0.0,
                       0.5, 0.5, 0.5, 1.0) * lightProjectionMatrix * lightViewMatrix *     inverse(viewMatrix) * modelMatrix * in_Position;
}

最终片段着色器:

#version 150

uniform sampler2D ShadowMap;

varying vec4 varyingVertex;
varying vec4 projectionVertex;
varying vec3 varyingNormal;
varying vec3 varyingPosition;
varying vec4 shadowCoord;

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;

in vec4 pass_Color;
in vec2 pass_TextureCoord;

out vec4 out_Color;

void main() {
  vec3 vertexPosition = (modelMatrix * viewMatrix * varyingVertex).xyz;
  vec3 surfaceNormal = normalize((mat3(1) * varyingNormal).xyz);
  vec3 lightDirection = normalize(gl_LightSource[0].position.xyz - vertexPosition);
  float diffuseLightIntensity = max(0, dot(surfaceNormal, lightDirection));
  out_Color.rgb = diffuseLightIntensity * pass_Color.rgb;
  out_Color += gl_LightModel.ambient;
  vec3 reflectionDirection = normalize(reflect(-lightDirection, surfaceNormal));
  float specular = max(0.0, dot(surfaceNormal, reflectionDirection));
  if (diffuseLightIntensity != 0) {
    float fspecular = pow(specular, 128);
    out_Color += fspecular;
  }

  vec4 shadowCoordinateWdivide = shadowCoord / shadowCoord.w ;
  shadowCoordinateWdivide.z += 0.0005;
  float distanceFromLight = texture2D(ShadowMap,shadowCoordinateWdivide.st).z;

  float shadow = 1.0;
  if (shadowCoord.w > 0.0)
    shadow = distanceFromLight < shadowCoordinateWdivide.z ? 0.5 : 1.0 ;

  out_Color = shadow * out_Color;
}

我承认,在理解整个过程时,我觉得自己有点过头了,并且从各种来源拼凑起来。这个问题似乎很简单,但我无法弄清楚。

以下是图片:

未旋转:

在此处输入图像描述

旋转:

在此处输入图像描述

编辑:

将阴影贴图片段着色器更改为:

#version 150 core

layout(location=0) out float fragmentdepth;

void main(void) {
  fragmentdepth = gl_FragCoord.z;
}
4

2 回答 2

1

您的代码中有一些让我感到奇怪的事情。

glTexGen首先,如果有着色器,你为什么要使用?一切glTexGen都可以使用,使用片段着色器更容易完成。

然后你的阴影贴图生成,以及生成的阴影贴图不是你想要的阴影贴图。首先,您没有在阴影贴图中设置“颜色”。事实上,在渲染阴影贴图时,首先不需要对纹理进行采样或写入“颜色”组件。您在阴影贴图中实际放置的是与光的距离,即与原点(点光)或任意平面(方向光)的距离。生成的图片是深度图,几乎所有几何体(平行于投影平面的面除外)都有渐变。在你的“阴影贴图”中,你得到了纯色。这是错误的!这样做的原因是,您只需设置一些恒定的颜色(每个对象),而不是发出每个片段的距离。好吧,然后你也遇到了面部剔除问题;你的阴影贴图看起来不像它应该是的立方体。

好吧,在到达世界空间后,在您的照明着色器中,您转换为反向视图空间?你为什么以他面条的名义这样做?这就是您的额外轮换的来源。您应该将其转换为inverse(lightprojection * lightview).

好吧,然后是风格上的吹毛求疵。我对那些编译的着色器感到惊讶。inandout说明符已在 GLSL 的更高版本中引入,替换说明varying。你不应该混合它们(如果我没记错的话——我必须重新阅读规范——你不能在核心配置文件中混合它们)。

于 2013-08-21T12:02:23.590 回答
1

这对我来说非常愚蠢,但我发现了问题......

当我旋转相机时,我只旋转了视图矩阵,而不是模型矩阵。将旋转应用于模型矩阵也解决了这个问题。

感谢您的所有帮助和时间!指针和建议得到了很好的采纳。

于 2013-08-22T01:42:14.113 回答