我正在尝试使用两个使用 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;
}