Opengl:渲染到立方体贴图?
Opengl : Render To Cubemap?
我正在尝试将 3d 场景渲染到立方体贴图,但立方体贴图仅渲染天空盒,这是我的 RenderToCubemap 函数:
GLuint RenderToCubemap(glm::vec3 position, float resolution, float nearPlane, float farPlane)
{
unsigned int CM_FBO;
unsigned int textureID;
glGenFramebuffers(1, &CM_FBO);
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
for (unsigned int i = 0; i < 6; i++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, resolution, resolution, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
// attach depth texture as FBO's depth buffer
glBindFramebuffer(GL_FRAMEBUFFER, CM_FBO);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glm::mat4 shadowProj = glm::perspective(glm::radians(90.0f), (float)resolution / (float)resolution, nearPlane, farPlane);
std::vector<glm::mat4> shadowTransforms;
shadowTransforms.push_back(shadowProj * glm::lookAt(position, position + glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(position, position + glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(position, position + glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(position, position + glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(position, position + glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(position, position + glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
// Render scene to cubemap
// --------------------------------
glViewport(0, 0, (int)resolution, (int)resolution);
glBindFramebuffer(GL_FRAMEBUFFER, CM_FBO);
Camera capture_cam;
capture_cam.temp_cam = true;
capture_cam.projectionMatrix = shadowProj;
capture_cam.transform.Position = position;
for (size_t i = 0; i < 6; i++)
{
capture_cam.viewMatrix = shadowTransforms[i];
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, textureID, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
RenderScene(capture_cam);
}
return textureID;
}
RenderScene 函数:
void RenderScene(Camera& cam)
{
glm::mat4 proj = cam.GetProjectionMatrix();
glm::mat4 view = cam.GetViewMatrix();
glm::vec3 viewPos = cam.transform.Position;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Shader* shader = &materials.main_shader;
shader ->use();
shader ->SetMat4("projection", proj);
shader ->SetMat4("view", view);
shader ->SetVec3("CamPos", viewPos);
// Render all meshs
// ----------------------------------------------------
for (size_t i = 0; i < Meshs.size(); i++)
{
if (Meshs[i].Material == nullptr)
continue;
Meshs[i].Material->setShaderProperties(shader);
shader->SetMat4("model", Meshs[i].Transform);
Meshs[i]->Draw();
}
// render skybox
// ----------------------------------------------------
glDepthFunc(GL_LEQUAL); // change depth function so depth test passes when values are equal to depth buffer's content
Shader* bg = &materials.background;
bg->use();
bg->SetMat4("view", view);
bg->SetMat4("projection", proj);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);
renderCube();
glDepthFunc(GL_LESS); // set depth function back to default
}
我正在使用 RenderScene 进行主渲染并且它可以工作,但是当我在 renderToCubemap 中使用它时它只显示天空盒。
任何帮助或更正?
我已将“shadowTransforms”替换为:
std::vector<glm::mat4> shadowTransforms;
shadowTransforms.push_back(glm::lookAt(position, position + glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(glm::lookAt(position, position + glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(glm::lookAt(position, position + glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)));
shadowTransforms.push_back(glm::lookAt(position, position + glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)));
shadowTransforms.push_back(glm::lookAt(position, position + glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(glm::lookAt(position, position + glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
我还添加了一个深度缓冲区:
unsigned int m_CubemapDepthRBO;
glGenRenderbuffers(1, &m_CubemapDepthRBO);
glBindRenderbuffer(GL_RENDERBUFFER, m_CubemapDepthRBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, (int)resolution, (int)resolution);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_CubemapDepthRBO);
现在工作正常,感谢 Nicole Polas 和 Rabbid76 的快速回复。
我正在尝试将 3d 场景渲染到立方体贴图,但立方体贴图仅渲染天空盒,这是我的 RenderToCubemap 函数:
GLuint RenderToCubemap(glm::vec3 position, float resolution, float nearPlane, float farPlane)
{
unsigned int CM_FBO;
unsigned int textureID;
glGenFramebuffers(1, &CM_FBO);
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
for (unsigned int i = 0; i < 6; i++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, resolution, resolution, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
// attach depth texture as FBO's depth buffer
glBindFramebuffer(GL_FRAMEBUFFER, CM_FBO);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glm::mat4 shadowProj = glm::perspective(glm::radians(90.0f), (float)resolution / (float)resolution, nearPlane, farPlane);
std::vector<glm::mat4> shadowTransforms;
shadowTransforms.push_back(shadowProj * glm::lookAt(position, position + glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(position, position + glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(position, position + glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(position, position + glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(position, position + glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(position, position + glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
// Render scene to cubemap
// --------------------------------
glViewport(0, 0, (int)resolution, (int)resolution);
glBindFramebuffer(GL_FRAMEBUFFER, CM_FBO);
Camera capture_cam;
capture_cam.temp_cam = true;
capture_cam.projectionMatrix = shadowProj;
capture_cam.transform.Position = position;
for (size_t i = 0; i < 6; i++)
{
capture_cam.viewMatrix = shadowTransforms[i];
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, textureID, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
RenderScene(capture_cam);
}
return textureID;
}
RenderScene 函数:
void RenderScene(Camera& cam)
{
glm::mat4 proj = cam.GetProjectionMatrix();
glm::mat4 view = cam.GetViewMatrix();
glm::vec3 viewPos = cam.transform.Position;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Shader* shader = &materials.main_shader;
shader ->use();
shader ->SetMat4("projection", proj);
shader ->SetMat4("view", view);
shader ->SetVec3("CamPos", viewPos);
// Render all meshs
// ----------------------------------------------------
for (size_t i = 0; i < Meshs.size(); i++)
{
if (Meshs[i].Material == nullptr)
continue;
Meshs[i].Material->setShaderProperties(shader);
shader->SetMat4("model", Meshs[i].Transform);
Meshs[i]->Draw();
}
// render skybox
// ----------------------------------------------------
glDepthFunc(GL_LEQUAL); // change depth function so depth test passes when values are equal to depth buffer's content
Shader* bg = &materials.background;
bg->use();
bg->SetMat4("view", view);
bg->SetMat4("projection", proj);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, envCubemap);
renderCube();
glDepthFunc(GL_LESS); // set depth function back to default
}
我正在使用 RenderScene 进行主渲染并且它可以工作,但是当我在 renderToCubemap 中使用它时它只显示天空盒。
任何帮助或更正?
我已将“shadowTransforms”替换为:
std::vector<glm::mat4> shadowTransforms;
shadowTransforms.push_back(glm::lookAt(position, position + glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(glm::lookAt(position, position + glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(glm::lookAt(position, position + glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)));
shadowTransforms.push_back(glm::lookAt(position, position + glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)));
shadowTransforms.push_back(glm::lookAt(position, position + glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(glm::lookAt(position, position + glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
我还添加了一个深度缓冲区:
unsigned int m_CubemapDepthRBO;
glGenRenderbuffers(1, &m_CubemapDepthRBO);
glBindRenderbuffer(GL_RENDERBUFFER, m_CubemapDepthRBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, (int)resolution, (int)resolution);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_CubemapDepthRBO);
现在工作正常,感谢 Nicole Polas 和 Rabbid76 的快速回复。