我创建了一个framebuffer对象来渲染场景作为深度值来渲染阴影贴图,在场景初始化和所有着色器编译之后,我添加了定向光并使用以下代码创建FBO:
glGenFramebuffers(1, &depthMapFBO);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glGenTextures(1, &depthMap);
glBindTexture(GL_TEXTURE_2D, depthMap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
glDrawBuffers(1, GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
然后在渲染循环中,我使用深度着色器渲染生成的帧缓冲区上的场景,然后在取消绑定FBO后在屏幕上再次渲染场景,这是代码:
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glClear(GL_DEPTH_BUFFER_BIT);
double delta = GetCurrentTime() - firstFrame;
glm::mat4 lightSpaceProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, -10.0f, 10.0f);
glm::mat4 lightSpaceView = glm::lookAt(-sun->direction, glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
lightSpaceMatrix = lightSpaceProjection * lightSpaceView;
directDepthShader.use();
GLuint lsm = glGetUniformLocation(directDepthShader.getProgramID(), "lightSpaceMatrix");
glUniformMatrix4fv(lsm, 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix));
for (mesh_it it = phongMeshes.begin(); it != phongMeshes.end(); it++) {
it->get()->renderDepth(directDepthShader, delta);
}
glCullFace(GL_BACK);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
在渲染循环之前调用的第一个函数和生成的FBO并且有一个ID,但问题是渲染函数忽略了它,虽然我用它的ID绑定它不是负数甚至不是零,如果我删除创建和调整帧缓冲区的代码在渲染结果中没有任何变化,我在那个问题上待了一个星期!!
编辑:
深度的顶点着色器:
#version 300 es
precision mediump float;
layout (location = 0) in vec3 position;
layout (location = 4) in ivec4 BoneIDs;
layout (location = 5) in vec4 Weights;
const int MAX_BONES = 100;
uniform mat4 model;
uniform bool skinned;
uniform mat4 gBones[MAX_BONES];
uniform mat4 lightSpaceMatrix;
void main(){
vec4 nPos;
if(skinned){
mat4 BoneTransform = gBones[BoneIDs[0]] * Weights[0];
BoneTransform += gBones[BoneIDs[1]] * Weights[1];
BoneTransform += gBones[BoneIDs[2]] * Weights[2];
BoneTransform += gBones[BoneIDs[3]] * Weights[3];
nPos=BoneTransform * vec4(position, 1.0);
}
else
nPos = vec4(position, 1.0);
gl_Position = lightSpaceMatrix * model * nPos;
}
使用深度着色器程序每个网格的renderDepth()
:
void Mesh::renderDepth(Shader& shader, double& delta) {
if (isSkinned) {
glUniform1i(glGetUniformLocation(shader.getProgramID(), "skinned"), 1);
vector<Matrix4f> Transforms;
BoneTransform(delta, Transforms);
for (uint j = 0; j < Transforms.size(); j++) {
Transforms[j] = Transforms[j].Transpose();
GLuint bonesLoc = glGetUniformLocation(shader.getProgramID(), (const GLchar*) ("gBones[" + ToString(j) + "]").c_str());
glUniformMatrix4fv(bonesLoc, 1, GL_FALSE, (const GLfloat*) Transforms[j]);
}
}
for (uint i = 0; i < m_Entries.size(); i++) {
glUniformMatrix4fv(glGetUniformLocation(shader.getProgramID(), "model"), 1, GL_FALSE, glm::value_ptr(m_Entries[i].matrix));
glBindVertexArray(m_Entries[i].m_VAO);
glDrawElements(GL_TRIANGLES, m_Entries[i].NumIndices, GL_UNSIGNED_INT, NULL);
glBindVertexArray(0);
}
}