立方图/帧缓冲区问题
Cube map/ frame buffer problems
所以...我正在尝试为 BRDF 着色器过滤环境贴图,如此处所述:https://learnopengl.com/PBR/IBL/Specular-IBL。但是,我无法正确存储我的过滤结果(加载时,我得到一个充满伪像的黑色纹理。)
我认为它一定与帧缓冲区有关,因为 glCheckFramebufferStatus() 在 LOD/sides 循环中一直返回 0,但我花了几个小时试图理解为什么......我看不出问题所在。 glGetError() returns 0,我确保在循环开始之前生成帧缓冲区/渲染/缓冲区,此时一切似乎都已完成。程序的其余部分运行良好,编译我正在使用的着色器没有错误。
我是 openGL 的新手,有什么明显的我遗漏的吗?我假设问题一定出在这一部分……但它看起来应该有效吗?会不会是我在别处做错了什么?
这是代码:
if (cubeMapGenerated == false){
//Frame Buffer:
glGenFramebuffers(1, &frameBuffer);
glGenRenderbuffers(1, &renderBuffer);
glGenTextures(1, &genCubeMap);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glBindTexture(GL_TEXTURE_CUBE_MAP, genCubeMap);
for (unsigned int i = 0; i < 6; ++i)
{glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA16F, 128, 128, 0, GL_RGB, GL_FLOAT, nullptr);}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); //params
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);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_CUBE_MAP); //generate mipmaps
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width_, height_);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderBuffer);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "Framebuffer is not complete at gen. Staus: " << glCheckFramebufferStatus(GL_FRAMEBUFFER) << std::endl;
GLuint projection_location, view_location, model_location, normal_matrix_location,
specular_map_location, roughness_location;
cubeMapGen_program_->bind(); //bind irradiance sahder
projection_location = cubeMapGen_program_->uniformLocation("projection");
view_location = cubeMapGen_program_->uniformLocation("view");
model_location = cubeMapGen_program_->uniformLocation("model");
normal_matrix_location = cubeMapGen_program_->uniformLocation("normal_matrix");
specular_map_location = cubeMapGen_program_->uniformLocation("specular_map");
roughness_location =brdf_program_->uniformLocation("roughness");
glUniformMatrix4fv(projection_location, 1, GL_FALSE, e_captureProjection.data());
glUniformMatrix4fv(model_location, 1, GL_FALSE, model.data());
glUniformMatrix3fv(normal_matrix_location, 1, GL_FALSE, normal.data());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, specular_map_);
glUniform1i(specular_map_location, 0);
for (unsigned int mip = 0; mip < maxMipLevels; ++mip){//render each mip
// resize framebuffer according to mip-level size.
unsigned int mipWidth = 128 * std::pow(0.5, mip);
unsigned int mipHeight = 128 * std::pow(0.5, mip);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, mipWidth, mipHeight);
std::cout << "width: " << mipWidth << " height: " << mipHeight << std::endl;
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderBuffer);
glViewport(0, 0, mipWidth, mipHeight);
float mproughness = (float) mip / (float)(maxMipLevels - 1);
glUniform1f (roughness_location, mproughness);
for (unsigned int i = 0; i < 6; ++i)//render each side
{
glUniformMatrix4fv(view_location, 1, GL_FALSE, e_captureViews[i].data());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, genCubeMap, mip);
if(i == 0 && glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete! Map: " << mip << std::endl;}
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glVertex3f(2, -2, -2); glVertex3f(2, -2, 2); glVertex3f(2, 2, 2); //Right
glVertex3f(2, -2, -2); glVertex3f(2, 2, 2); glVertex3f(2, 2, -2);
glVertex3f(-2, -2, -2); glVertex3f(-2, 2, 2); glVertex3f(-2, -2, 2); //Left
glVertex3f(-2, -2, -2); glVertex3f(-2, 2, -2); glVertex3f(-2, 2, 2);
glVertex3f(-2, -2, 2); glVertex3f(-2, 2, 2); glVertex3f(2, 2, 2); //Front
glVertex3f(-2, -2, 2); glVertex3f(2, 2, 2); glVertex3f(2, -2, 2);
glVertex3f(-2, -2, -2); glVertex3f(2, 2, -2); glVertex3f(-2, 2, -2); //Back
glVertex3f(-2, -2, -2); glVertex3f(2, -2, -2); glVertex3f(2, 2, -2);
glVertex3f(-2, 2, -2); glVertex3f(2, 2, -2); glVertex3f(2, 2, 2); //Top
glVertex3f(-2, 2, -2); glVertex3f(2, 2, 2); glVertex3f(-2, 2, 2);
glVertex3f(-2, -2, -2); glVertex3f(2, -2, 2); glVertex3f(2, -2, -2); //Bottom
glVertex3f(-2, -2, -2); glVertex3f(-2, -2, 2); glVertex3f(2, -2, 2);
}
//std::cout << glGetError() << ", " << glCheckFramebufferStatus(GL_FRAMEBUFFER) << std::endl;
}
std::cout<<"New pre filtered map generated"<<std::endl;
cubeMapGenerated = true;
}//cubemapgen
glEnd();
我建议阅读有关 Vertex Specification and to use the state of the art way of Vertex Array Objects 的绘图。
但是,如果您将对象绘制到已弃用的 Fixed Function Pipeline style, then geometric objects are drawn by enclosing a series of vertex coordinates between glBegin
/glEnd
对中。
您必须在 glEnd
之前完成绘制序列,然后才能更改或操作帧缓冲区。
在内部循环中移动 glEnd
指令,您的代码应该可以工作
for (unsigned int mip = 0; mip < maxMipLevels; ++mip)
{
.....
for (unsigned int i = 0; i < 6; ++i)//render each side
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, genCubeMap, mip);
glBegin(GL_TRIANGLES);
glVertex3f(2, -2, -2); glVertex3f(2, -2, 2); glVertex3f(2, 2, 2);
.....
glVertex3f(-2, -2, -2); glVertex3f(-2, -2, 2); glVertex3f(2, -2, 2);
glEnd(); // <---- "end" the draw sequence
}
}
见OpenGL 3.0 API Specification; 2.6.3 GL Commands within Begin/End; page 24
或 OpenGL 4.6 API Compatibility Profile Specification; 10.7.5 Commands Allowed Between Begin and End; page 433:
The only GL commands that are allowed within any Begin/End pairs are the commands for specifying vertex coordinates, vertex colors, normal coordinates, texture coordinates, generic vertex attributes, and fog coordinates ...
所以...我正在尝试为 BRDF 着色器过滤环境贴图,如此处所述:https://learnopengl.com/PBR/IBL/Specular-IBL。但是,我无法正确存储我的过滤结果(加载时,我得到一个充满伪像的黑色纹理。)
我认为它一定与帧缓冲区有关,因为 glCheckFramebufferStatus() 在 LOD/sides 循环中一直返回 0,但我花了几个小时试图理解为什么......我看不出问题所在。 glGetError() returns 0,我确保在循环开始之前生成帧缓冲区/渲染/缓冲区,此时一切似乎都已完成。程序的其余部分运行良好,编译我正在使用的着色器没有错误。
我是 openGL 的新手,有什么明显的我遗漏的吗?我假设问题一定出在这一部分……但它看起来应该有效吗?会不会是我在别处做错了什么?
这是代码:
if (cubeMapGenerated == false){
//Frame Buffer:
glGenFramebuffers(1, &frameBuffer);
glGenRenderbuffers(1, &renderBuffer);
glGenTextures(1, &genCubeMap);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glBindTexture(GL_TEXTURE_CUBE_MAP, genCubeMap);
for (unsigned int i = 0; i < 6; ++i)
{glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA16F, 128, 128, 0, GL_RGB, GL_FLOAT, nullptr);}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); //params
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);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_CUBE_MAP); //generate mipmaps
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width_, height_);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderBuffer);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "Framebuffer is not complete at gen. Staus: " << glCheckFramebufferStatus(GL_FRAMEBUFFER) << std::endl;
GLuint projection_location, view_location, model_location, normal_matrix_location,
specular_map_location, roughness_location;
cubeMapGen_program_->bind(); //bind irradiance sahder
projection_location = cubeMapGen_program_->uniformLocation("projection");
view_location = cubeMapGen_program_->uniformLocation("view");
model_location = cubeMapGen_program_->uniformLocation("model");
normal_matrix_location = cubeMapGen_program_->uniformLocation("normal_matrix");
specular_map_location = cubeMapGen_program_->uniformLocation("specular_map");
roughness_location =brdf_program_->uniformLocation("roughness");
glUniformMatrix4fv(projection_location, 1, GL_FALSE, e_captureProjection.data());
glUniformMatrix4fv(model_location, 1, GL_FALSE, model.data());
glUniformMatrix3fv(normal_matrix_location, 1, GL_FALSE, normal.data());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, specular_map_);
glUniform1i(specular_map_location, 0);
for (unsigned int mip = 0; mip < maxMipLevels; ++mip){//render each mip
// resize framebuffer according to mip-level size.
unsigned int mipWidth = 128 * std::pow(0.5, mip);
unsigned int mipHeight = 128 * std::pow(0.5, mip);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, mipWidth, mipHeight);
std::cout << "width: " << mipWidth << " height: " << mipHeight << std::endl;
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderBuffer);
glViewport(0, 0, mipWidth, mipHeight);
float mproughness = (float) mip / (float)(maxMipLevels - 1);
glUniform1f (roughness_location, mproughness);
for (unsigned int i = 0; i < 6; ++i)//render each side
{
glUniformMatrix4fv(view_location, 1, GL_FALSE, e_captureViews[i].data());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, genCubeMap, mip);
if(i == 0 && glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete! Map: " << mip << std::endl;}
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glVertex3f(2, -2, -2); glVertex3f(2, -2, 2); glVertex3f(2, 2, 2); //Right
glVertex3f(2, -2, -2); glVertex3f(2, 2, 2); glVertex3f(2, 2, -2);
glVertex3f(-2, -2, -2); glVertex3f(-2, 2, 2); glVertex3f(-2, -2, 2); //Left
glVertex3f(-2, -2, -2); glVertex3f(-2, 2, -2); glVertex3f(-2, 2, 2);
glVertex3f(-2, -2, 2); glVertex3f(-2, 2, 2); glVertex3f(2, 2, 2); //Front
glVertex3f(-2, -2, 2); glVertex3f(2, 2, 2); glVertex3f(2, -2, 2);
glVertex3f(-2, -2, -2); glVertex3f(2, 2, -2); glVertex3f(-2, 2, -2); //Back
glVertex3f(-2, -2, -2); glVertex3f(2, -2, -2); glVertex3f(2, 2, -2);
glVertex3f(-2, 2, -2); glVertex3f(2, 2, -2); glVertex3f(2, 2, 2); //Top
glVertex3f(-2, 2, -2); glVertex3f(2, 2, 2); glVertex3f(-2, 2, 2);
glVertex3f(-2, -2, -2); glVertex3f(2, -2, 2); glVertex3f(2, -2, -2); //Bottom
glVertex3f(-2, -2, -2); glVertex3f(-2, -2, 2); glVertex3f(2, -2, 2);
}
//std::cout << glGetError() << ", " << glCheckFramebufferStatus(GL_FRAMEBUFFER) << std::endl;
}
std::cout<<"New pre filtered map generated"<<std::endl;
cubeMapGenerated = true;
}//cubemapgen
glEnd();
我建议阅读有关 Vertex Specification and to use the state of the art way of Vertex Array Objects 的绘图。
但是,如果您将对象绘制到已弃用的 Fixed Function Pipeline style, then geometric objects are drawn by enclosing a series of vertex coordinates between glBegin
/glEnd
对中。
您必须在 glEnd
之前完成绘制序列,然后才能更改或操作帧缓冲区。
在内部循环中移动 glEnd
指令,您的代码应该可以工作
for (unsigned int mip = 0; mip < maxMipLevels; ++mip)
{
.....
for (unsigned int i = 0; i < 6; ++i)//render each side
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, genCubeMap, mip);
glBegin(GL_TRIANGLES);
glVertex3f(2, -2, -2); glVertex3f(2, -2, 2); glVertex3f(2, 2, 2);
.....
glVertex3f(-2, -2, -2); glVertex3f(-2, -2, 2); glVertex3f(2, -2, 2);
glEnd(); // <---- "end" the draw sequence
}
}
见OpenGL 3.0 API Specification; 2.6.3 GL Commands within Begin/End; page 24
或 OpenGL 4.6 API Compatibility Profile Specification; 10.7.5 Commands Allowed Between Begin and End; page 433:
The only GL commands that are allowed within any Begin/End pairs are the commands for specifying vertex coordinates, vertex colors, normal coordinates, texture coordinates, generic vertex attributes, and fog coordinates ...