简体   繁体   English

渲染动态立方体贴图(OpenGL)

[英]Rendering a dynamic cubemap (OpenGL)

I'm trying to render a scene 6 times and put them on the sides of a cubemap. 我正在尝试将场景渲染6次并将其放置在立方体贴图的侧面。 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. 我已经修改了先前项目中的代码,该代码实现了用于IBL和反射/折射的静态立方体贴图。 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 实际场景 实际场景

Update The big square was the result of a bug in my setViewMat function which didn't apply the stacked transformations. 更新大方块是我的setViewMat函数中的一个错误的结果,该错误未应用堆叠的转换。 It now only renders the scene, the texture is black. 现在它仅渲染场景,纹理为黑色。 I've used AMD gDEBugger to see the resulting cubemap which is just black. 我已经使用AMD gDEBugger来查看生成的立方体贴图,它只是黑色的。 So I think it's either my initial fbo binding or how I render each side in the first pass that's at fault. 所以我认为这是我最初的fbo绑定,还是我在第一遍中渲染每一面的方式都是错误的。

OK, I finally got it working. 好的,我终于可以正常工作了。 In setupFBO I shouldn't have unbound the cubemap. 在setupFBO中,我不应该取消绑定立方体贴图。 I've posted the updated pass1,2 code anyways. 无论如何,我已经发布了更新的pass1,2代码。 Though the rendering works I have trouble ordering the sides as it seems the sides are not mapped as I had anticipated, X+, X- , .... 虽然渲染工作很麻烦,但我很难对两边进行排序,因为似乎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();
    }
}

OK, I figured out the ordering by color coding each side of the cube, not sure why it is this way. 好的,我通过对多维数据集的每一边进行颜色编码来确定排序,不知道为什么会这样。

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));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM