我正在尝试使用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;
设置framebuffer / renderbuffer / texture:
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;
}
我承认,在理解整个过程时,我觉得自己有点过头了,并且已经从各种来源拼凑出来。问题似乎很简单,但我无法弄明白。
以下是图片:
未轮换:
旋转的:
编辑:
将shadowmap片段着色器更改为:
#version 150 core
layout(location=0) out float fragmentdepth;
void main(void) {
fragmentdepth = gl_FragCoord.z;
}
答案 0 :(得分:1)
在你的代码中,有一些事情让我感到奇怪。
首先,如果有着色器,为什么要使用glTexGen
?使用片段着色器可以更轻松地完成glTexGen
所有内容。
然后生成阴影贴图,并且生成的阴影贴图不是您想要的阴影贴图。首先,您不要在阴影贴图中设置“颜色”。事实上,在渲染阴影贴图时,首先不需要对纹理进行采样或写入“颜色”组件。实际放置在阴影贴图中的是距光线的距离,即距原点(点光源)或任意平面(方向光)的距离。生成的图片是深度图,几乎在所有几何体上都有渐变(除了与投影平面平行的面)。在你的“阴影贴图”中你得到了纯色。 这是错误的!原因是,您只需设置一些常量颜色(每个对象),而不是发出每个片段的距离。那么,你也会遇到面部剔除的问题;你的阴影贴图看起来不像它应该是多维数据集。
嗯,在到达世界空间后的照明着色器中,您会转换为逆视图空间?为什么他的noodlenes的名字你这样做?这就是你额外轮换的来源。您应该按inverse(lightprojection * lightview)
转换它。
嗯,然后是风格的挑剔。我很惊讶这些着色器编译完毕。 in
和out
说明符已在更高版本的GLSL中引入,替换 varying
说明符。你不应该把它们混在一起(如果我没弄错的话 - 我要重新阅读那个规范 - 你不能将它们混合在一个核心配置文件中。)
答案 1 :(得分:0)
这对我来说是令人难以置信的愚蠢,但我发现了这个问题......
当我旋转相机时,我只旋转视图矩阵,而不是模型矩阵。将旋转应用于模型矩阵也解决了问题。
感谢您的帮助和时间!指针和建议很好。