OpenGL Shadow Mapping双重着色器

时间:2013-08-21 04:31:19

标签: java opengl glsl shadow-mapping

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

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

以下是图片:

未轮换:

enter image description here

旋转的:

enter image description here

编辑:

将shadowmap片段着色器更改为:

#version 150 core

layout(location=0) out float fragmentdepth;

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

2 个答案:

答案 0 :(得分:1)

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

首先,如果有着色器,为什么要使用glTexGen?使用片段着色器可以更轻松地完成glTexGen所有内容。

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

嗯,在到达世界空间后的照明着色器中,您会转换为逆视图空间?为什么他的noodlenes的名字你这样做?这就是你额外轮换的来源。您应该按inverse(lightprojection * lightview)转换它。

嗯,然后是风格的挑剔。我很惊讶这些着色器编译完毕。 inout说明符已在更高版本的GLSL中引入,替换 varying说明符。你不应该把它们混在一起(如果我没弄错的话 - 我要重新阅读那个规范 - 你不能将它们混合在一个核心配置文件中。)

答案 1 :(得分:0)

这对我来说是令人难以置信的愚蠢,但我发现了这个问题......

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

感谢您的帮助和时间!指针和建议很好。