samedi 7 mars 2015

Rendering a dynamic cubemap (OpenGL)


I'm trying to render a scene 6 times and put them on the sides of a cubemap. I'd like to do this properly first before moving onto learning Geometry shaders which would allow this to be done in one pass. Here goes the code:



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
}


I've modified the code from my previous project that implemented a static cubemap that was used for IBL and reflection/refraction. I'll provide the shaders codes if you think it's necessary. At this stage there's only gibberish being rendered.


End result end result


The actual scene The actual scene


Update The big square was the result of a bug in my setViewMat function which didn't apply the stacked transformations. It now only renders the scene, the texture is black. I've used AMD gDEBugger to see the resulting cubemap which is just black. So I think it's either my initial fbo binding or how I render each side in the first pass that's at fault.




Aucun commentaire:

Enregistrer un commentaire