首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Opengl 3.3+使用阴影贴图时阴影不正确

Opengl 3.3+使用阴影贴图时阴影不正确
EN

Stack Overflow用户
提问于 2013-07-03 04:30:56
回答 1查看 1.8K关注 0票数 1

我正在尝试使用OpenGL 3.3+在我的景观编辑器上实现阴影贴图。通过几个教程,我设法让我的代码编译并运行,但除了我的景观网格的后排(最小的z)之外,整个景观都在阴影中。

我目前使用与相机相同的投影、视图和模型矩阵(负z距离相机最远)。

我的投影、视图和模型矩阵的初始化(来自LWJGL矩阵教程):

代码语言:javascript
复制
modelPos = new Vector3f(0f, 0f, -20f);
modelAngle = new Vector3f(15f, 0f, 0f);
modelScale = new Vector3f(1f, 1f, 1f);
cameraPos = new Vector3f(-50f, 0f, -120f);

projectionMatrix = new Matrix4f();

float fieldOfView = 120f;
float aspectRatio = (float)width / (float)height;
float near_plane = 0.01f;
float far_plane = 100f;

float y_scale = DepthMatrixUtility.coTangent(DepthMatrixUtility.degreesToRadians(fieldOfView / 2f));
float x_scale = y_scale / aspectRatio;
float frustum_length = far_plane - near_plane;

projectionMatrix.m00 = x_scale;
projectionMatrix.m11 = y_scale;
projectionMatrix.m22 = -((far_plane + near_plane) / frustum_length);
projectionMatrix.m23 = -1;
projectionMatrix.m32 = -((2 * near_plane * far_plane) / frustum_length);

显示场景时绑定我的矩阵:

代码语言:javascript
复制
Matrix4f.translate(cameraPos, viewMatrix, viewMatrix);
Matrix4f.scale(modelScale, modelMatrix, modelMatrix);
Matrix4f.translate(modelPos, modelMatrix, modelMatrix);

Matrix4f.rotate(DepthMatrixUtility.degreesToRadians(modelAngle.z), new Vector3f(0, 0, 1), modelMatrix, modelMatrix);
Matrix4f.rotate(DepthMatrixUtility.degreesToRadians(modelAngle.y), new Vector3f(0, 1, 0), modelMatrix, modelMatrix);
Matrix4f.rotate(DepthMatrixUtility.degreesToRadians(modelAngle.x), new Vector3f(1, 0, 0), modelMatrix, modelMatrix);

matrix = new Matrix4f();
Matrix4f.mul(matrix, projectionMatrix, matrix);
Matrix4f.mul(matrix, viewMatrix, matrix);
Matrix4f.mul(matrix, modelMatrix, matrix);

matrix.store(matrix44Buffer);
matrix44Buffer.flip();

matrixLocation = GL20.glGetUniformLocation(pId, "matrix");
GL20.glUniformMatrix4(matrixLocation, false, matrix44Buffer);

我已经测试了我的FBO在碎片着色器中存储颜色,高度贴图显示正确(我绘制FBO纹理到我的屏幕角落的一个小方块),并随着我改变高度贴图而更新。

然后我修改了我的FBO,在第一次遍历时存储纹理的深度:

代码语言:javascript
复制
depthTexture = GL11.glGenTextures();

GL11.glBindTexture(GL11.GL_TEXTURE_2D, depthTexture);

GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_DEPTH_COMPONENT, Window.getScreenWidth(), Window.getScreenHeight(), 0, GL11.GL_DEPTH_COMPONENT, GL11.GL_UNSIGNED_BYTE, (ByteBuffer)null);

GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_NEAREST);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);

GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);

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

GL11.glDrawBuffer(GL11.GL_NONE);
GL11.glReadBuffer(GL11.GL_NONE);

GL32.glFramebufferTexture(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, depthTexture, 0);

verifyFBO();

我的顶点着色器用于第一个过程(创建阴影贴图):

代码语言:javascript
复制
#version 330 core

uniform mat4 matrix;

in vec4 in_Position;

void main(void)
{
gl_Position = matrix * in_Position;
}

我的第一个过程的片段着色器:

代码语言:javascript
复制
#version 330 core

layout(location = 0) out float fragmentdepth;

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

我的偏差矩阵:

代码语言:javascript
复制
[0.5f, 0.0f, 0.0f, 0.0f]
[0.0f, 0.5f, 0.0f, 0.0f]
[0.0f, 0.0f, 0.5f, 0.0f]
[0.5f, 0.5f, 0.5f, 1.0f]

第二个过程的顶点着色器(使用阴影贴图渲染场景):

代码语言:javascript
复制
void main(void)
{
    gl_Position = matrix * in_Position;
    ShadowCoord = biasMatrix * lightMatrix * in_Position;
}

我的第二个过程的片段着色器:

代码语言:javascript
复制
if (texture(shadowMap, ShadowCoord.xy).z  <  ShadowCoord.z)
{
    vec4 colour = 0.5 * out_Colour;
    out_Colour = new vec4(colour[0], colour[1], colour[2], 1.0f);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-07-03 08:45:01

在用lightMatrix转换in_Position之后,结果还没有投影到屏幕上。

通过除以w分量来应用实际的透视投影。

透视分割将为您提供[-1,1]范围内的纹理坐标和深度。此时,您可以使用biasMatrix将它们转换为[0,1]范围。

所以你不应该用biasMatrix相乘,然后在你的着色器中的行之前

代码语言:javascript
复制
if (texture(shadowMap, ShadowCoord.xy).z  <  ShadowCoord.z)

添加

代码语言:javascript
复制
ShadowCoord.xyz /= ShadowCoord.w;
ShadowCoord = biasMatrix * ShadowCoord;

您正在显示的biasMatrix内容应该转置存储在内存中。如果犹豫不决,请将矩阵乘积替换为

代码语言:javascript
复制
ShadowCoord.xyz = ShadowCoord.xyz * .5f + float3(.5f);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17435327

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档