渲染动态立方体贴图 (OpenGL)
Rendering a dynamic cubemap (OpenGL)
我正在尝试渲染一个场景 6 次并将它们放在立方体贴图的两侧。在继续学习几何着色器之前,我想先正确地执行此操作,这样可以一次性完成此操作。
代码如下:
void Scene::setupFBO()
{
glGenTextures(1, &cubemap);
glBindTexture(GL_TEXTURE_CUBE_MAP,cubemap);
glActiveTexture(GL_TEXTURE0);
const int size = 128;
// create the fbo
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
for(int i=0;i<6;i++)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB,
size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
}
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,
GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,
GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R,
GL_CLAMP_TO_EDGE);
// create the uniform depth buffer
glGenRenderbuffers(1, &depthbuff);
glBindRenderbuffer(GL_RENDERBUFFER, depthbuff);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size, size);
//glBindRenderbuffer(GL_RENDERBUFFER, 0);
GLenum drawBufs[] = {GL_COLOR_ATTACHMENT0};
// attach it
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo);
//glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, cubemap, 0);
glDrawBuffers(1, drawBufs);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
void Scene::pass1()
{
GLuint p = glGetSubroutineIndex(program->id,GL_FRAGMENT_SHADER,"pass1");
glUniformSubroutinesuiv(GL_FRAGMENT_SHADER,1,&p);
mat4 view;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
for(int i=0;i<6;i++)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap, 0);
if(i==0) //X+
cam->Update(vec3(0),vec3(10,0,0)); // position, target
else if(i==1) //X-
cam->Update(vec3(0),vec3(-10,0,0));
else if(i==2) //Y+
cam->Update(vec3(0),vec3(0,10,0));
else if(i == 3) //....
cam->Update(vec3(0),vec3(0,-10,0));
else if(i == 4)
cam->Update(vec3(0),vec3(0,0,10));
else if(i == 5)
cam->Update(vec3(0),vec3(0,0,-10));
view = cam->getViewMat();
for(int ii=1;ii<SHAPE_COUNT;ii++){
shapes[ii]->setViewMat(view);
shapes[ii]->Draw();
}
}
}
void Scene::pass2()
{
GLuint p = glGetSubroutineIndex(program->id,GL_FRAGMENT_SHADER,"pass2");
glUniformSubroutinesuiv(GL_FRAGMENT_SHADER,1,&p);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
cam->Update(vec3(0,0,10),vec3(0));
mat4 view = cam->getViewMat();
for(int i=0;i<SHAPE_COUNT;i++){
shapes[i]->setViewMat(view);
(*shapes[i]).Draw();
}
}
void Scene::Draw(){
pass1(); // Create the cubemap
pass2(); // Draw the scene normally
}
我修改了我之前项目的代码,该项目实现了用于 IBL 和 reflection/refraction 的静态立方体贴图。
如果您认为有必要,我会提供着色器代码。
在此阶段,只会呈现乱码。
最终结果
实景
更新
大方块是我的 setViewMat 函数中的一个错误导致的,该错误没有应用堆叠转换。它现在只渲染场景,纹理是黑色的。我已经使用 AMD gDEBugger 查看生成的立方体贴图,它只是黑色的。所以我认为要么是我最初的 fbo 绑定,要么是我在第一遍中渲染每一面的方式有问题。
好的,我终于让它工作了。在 setupFBO 中,我不应该取消绑定立方体贴图。
无论如何,我已经发布了更新的 pass1,2 代码。虽然渲染工作正常,但我在订购侧面时遇到了麻烦,因为侧面似乎没有像我预期的那样映射,X+,X-,....
void Scene::pass1()
{
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
GLuint p = glGetSubroutineIndex(program->id,GL_FRAGMENT_SHADER,"pass1");
glUniformSubroutinesuiv(GL_FRAGMENT_SHADER,1,&p);
glViewport(0,0,512,512);
mat4 view, proj;
proj = glm::perspective(90.0f, 1.0f, 1.0f, 500.0f);
for(int i=0;i<6;i++)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(i==0)
view = Camera::Update(vec3(0),vec3(1,0,0),vec3(0,1,0));// pos, target, up
else if(i==1)
view = Camera::Update(vec3(0),vec3(-1,0,0),vec3(0,1,0));
else if(i==2)
view = Camera::Update(vec3(0),vec3(0,1,0),vec3(0,0,1));
else if(i == 3)
view = Camera::Update(vec3(0),vec3(0,-1,0),vec3(0,0,-1));
else if(i == 4)
view = Camera::Update(vec3(0),vec3(0,0,1),vec3(0,1,0));
else if(i == 5)
view = Camera::Update(vec3(0),vec3(0,0,-1),vec3(0,1,0));
for(int ii=1;ii<SHAPE_COUNT;ii++){
shapes[ii]->setProjMat(proj);
shapes[ii]->setViewMatAndUpdate(view); // Empties the transformation stack, pushes the new view matrix and applies all the transformations again
shapes[ii]->Draw();
//Reverts back to the original stack
shapes[ii]->setViewMatAndUpdate(cam->getViewMat());
}
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap,0);
}
}
void Scene::pass2()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLuint p = glGetSubroutineIndex(program->id,GL_FRAGMENT_SHADER,"pass2");
glUniformSubroutinesuiv(GL_FRAGMENT_SHADER,1,&p);
glViewport(0,0,Constants::Instance()->gWidth,Constants::Instance()->gHeight);
float aspectRatio = 8.0f/6.0f;
mat4 proj = cam->getProjMat();
for(int i=0;i<SHAPE_COUNT;i++){
shapes[i]->setProjMat(proj);
(*shapes[i]).Draw();
}
}
好的,我通过对立方体每一面的颜色编码找出了顺序,不知道为什么会这样。
if(i==1)
view = Camera::Update(vec3(0),vec3(1,0,0),vec3(0,1,0));
else if(i==2)
view = Camera::Update(vec3(0),vec3(-1,0,0),vec3(0,1,0));
else if(i==4)
view = Camera::Update(vec3(0),vec3(0,1,0),vec3(0,0,1));
else if(i == 3)
view = Camera::Update(vec3(0),vec3(0,-1,0),vec3(0,0,-1));
else if(i == 0)
view = Camera::Update(vec3(0),vec3(0,0,1),vec3(0,1,0));
else if(i == 5)
view = Camera::Update(vec3(0),vec3(0,0,-1),vec3(0,1,0));
我正在尝试渲染一个场景 6 次并将它们放在立方体贴图的两侧。在继续学习几何着色器之前,我想先正确地执行此操作,这样可以一次性完成此操作。 代码如下:
void Scene::setupFBO()
{
glGenTextures(1, &cubemap);
glBindTexture(GL_TEXTURE_CUBE_MAP,cubemap);
glActiveTexture(GL_TEXTURE0);
const int size = 128;
// create the fbo
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
for(int i=0;i<6;i++)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB,
size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
}
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,
GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,
GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R,
GL_CLAMP_TO_EDGE);
// create the uniform depth buffer
glGenRenderbuffers(1, &depthbuff);
glBindRenderbuffer(GL_RENDERBUFFER, depthbuff);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size, size);
//glBindRenderbuffer(GL_RENDERBUFFER, 0);
GLenum drawBufs[] = {GL_COLOR_ATTACHMENT0};
// attach it
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo);
//glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, cubemap, 0);
glDrawBuffers(1, drawBufs);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
void Scene::pass1()
{
GLuint p = glGetSubroutineIndex(program->id,GL_FRAGMENT_SHADER,"pass1");
glUniformSubroutinesuiv(GL_FRAGMENT_SHADER,1,&p);
mat4 view;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
for(int i=0;i<6;i++)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap, 0);
if(i==0) //X+
cam->Update(vec3(0),vec3(10,0,0)); // position, target
else if(i==1) //X-
cam->Update(vec3(0),vec3(-10,0,0));
else if(i==2) //Y+
cam->Update(vec3(0),vec3(0,10,0));
else if(i == 3) //....
cam->Update(vec3(0),vec3(0,-10,0));
else if(i == 4)
cam->Update(vec3(0),vec3(0,0,10));
else if(i == 5)
cam->Update(vec3(0),vec3(0,0,-10));
view = cam->getViewMat();
for(int ii=1;ii<SHAPE_COUNT;ii++){
shapes[ii]->setViewMat(view);
shapes[ii]->Draw();
}
}
}
void Scene::pass2()
{
GLuint p = glGetSubroutineIndex(program->id,GL_FRAGMENT_SHADER,"pass2");
glUniformSubroutinesuiv(GL_FRAGMENT_SHADER,1,&p);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
cam->Update(vec3(0,0,10),vec3(0));
mat4 view = cam->getViewMat();
for(int i=0;i<SHAPE_COUNT;i++){
shapes[i]->setViewMat(view);
(*shapes[i]).Draw();
}
}
void Scene::Draw(){
pass1(); // Create the cubemap
pass2(); // Draw the scene normally
}
我修改了我之前项目的代码,该项目实现了用于 IBL 和 reflection/refraction 的静态立方体贴图。 如果您认为有必要,我会提供着色器代码。 在此阶段,只会呈现乱码。
最终结果
实景
更新 大方块是我的 setViewMat 函数中的一个错误导致的,该错误没有应用堆叠转换。它现在只渲染场景,纹理是黑色的。我已经使用 AMD gDEBugger 查看生成的立方体贴图,它只是黑色的。所以我认为要么是我最初的 fbo 绑定,要么是我在第一遍中渲染每一面的方式有问题。
好的,我终于让它工作了。在 setupFBO 中,我不应该取消绑定立方体贴图。 无论如何,我已经发布了更新的 pass1,2 代码。虽然渲染工作正常,但我在订购侧面时遇到了麻烦,因为侧面似乎没有像我预期的那样映射,X+,X-,....
void Scene::pass1()
{
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
GLuint p = glGetSubroutineIndex(program->id,GL_FRAGMENT_SHADER,"pass1");
glUniformSubroutinesuiv(GL_FRAGMENT_SHADER,1,&p);
glViewport(0,0,512,512);
mat4 view, proj;
proj = glm::perspective(90.0f, 1.0f, 1.0f, 500.0f);
for(int i=0;i<6;i++)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(i==0)
view = Camera::Update(vec3(0),vec3(1,0,0),vec3(0,1,0));// pos, target, up
else if(i==1)
view = Camera::Update(vec3(0),vec3(-1,0,0),vec3(0,1,0));
else if(i==2)
view = Camera::Update(vec3(0),vec3(0,1,0),vec3(0,0,1));
else if(i == 3)
view = Camera::Update(vec3(0),vec3(0,-1,0),vec3(0,0,-1));
else if(i == 4)
view = Camera::Update(vec3(0),vec3(0,0,1),vec3(0,1,0));
else if(i == 5)
view = Camera::Update(vec3(0),vec3(0,0,-1),vec3(0,1,0));
for(int ii=1;ii<SHAPE_COUNT;ii++){
shapes[ii]->setProjMat(proj);
shapes[ii]->setViewMatAndUpdate(view); // Empties the transformation stack, pushes the new view matrix and applies all the transformations again
shapes[ii]->Draw();
//Reverts back to the original stack
shapes[ii]->setViewMatAndUpdate(cam->getViewMat());
}
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap,0);
}
}
void Scene::pass2()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLuint p = glGetSubroutineIndex(program->id,GL_FRAGMENT_SHADER,"pass2");
glUniformSubroutinesuiv(GL_FRAGMENT_SHADER,1,&p);
glViewport(0,0,Constants::Instance()->gWidth,Constants::Instance()->gHeight);
float aspectRatio = 8.0f/6.0f;
mat4 proj = cam->getProjMat();
for(int i=0;i<SHAPE_COUNT;i++){
shapes[i]->setProjMat(proj);
(*shapes[i]).Draw();
}
}
好的,我通过对立方体每一面的颜色编码找出了顺序,不知道为什么会这样。
if(i==1)
view = Camera::Update(vec3(0),vec3(1,0,0),vec3(0,1,0));
else if(i==2)
view = Camera::Update(vec3(0),vec3(-1,0,0),vec3(0,1,0));
else if(i==4)
view = Camera::Update(vec3(0),vec3(0,1,0),vec3(0,0,1));
else if(i == 3)
view = Camera::Update(vec3(0),vec3(0,-1,0),vec3(0,0,-1));
else if(i == 0)
view = Camera::Update(vec3(0),vec3(0,0,1),vec3(0,1,0));
else if(i == 5)
view = Camera::Update(vec3(0),vec3(0,0,-1),vec3(0,1,0));