Imagination PowerVR SDK Blog

Problems with rendering to FBO


#1

Hi all,
I’m having a little trouble with rendering to FBOs, with both PVRFrame and the actual device, a Sony Ericsson Satio. The first problem is that I’m unable to create a stencil-renderbuffer in PVRFrame (for glRenderbufferStorage with GL_STENCIL_INDEX8 it says "Error 500 (Invalid Enum): unknown or unsupported internal format), however on the device it works without any problems.

Here’s my code:

Code:


bool InitBackBuffers(iString& errorInfo){
   
    //Create Stencil-Renderbuffer
    glGenRenderbuffers(1, &stencilRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER,stencilRenderBuffer);
    //This line causes Problems in PVRFrame
    glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, screenwidth,screenheight);

    //Create depth-texture
    //the functions are simply some object-oriented wrappers for the gl functions
    depthTexture=new CTexture2D();
    depthTexture->Bind();
    depthTexture->SetData(0,GL_DEPTH_COMPONENT,screenwidth,screenheight,GL_UNSIGNED_INT,0);
    IPAQRenderState::SetTextureWrappingS(GL_CLAMP_TO_EDGE);
    IPAQRenderState::SetTextureWrappingT(GL_CLAMP_TO_EDGE);
    IPAQRenderState::SetTextureMagFilter(GL_NEAREST);
    IPAQRenderState::SetTextureMinFilter(GL_NEAREST);
    IPAQRenderState::BindTexture(GL_TEXTURE_2D,0);

   
    //BACKBUFFERCNT is one at the moment
    for(int i=0; i<BACKBUFFERCNT; i++){
        //gernerate color rendertarget
        renderTargets = new CTexture2D();
        renderTargets->SetData(0,GL_RGBA,screenwidth,screenheight,GL_UNSIGNED_BYTE,NULL);
        renderTargets->Bind();
        IPAQRenderState::SetTextureWrappingS(GL_CLAMP_TO_EDGE);
        IPAQRenderState::SetTextureWrappingT(GL_CLAMP_TO_EDGE);
        IPAQRenderState::SetTextureMagFilter(GL_NEAREST);
        IPAQRenderState::SetTextureMinFilter(GL_NEAREST);
        IPAQRenderState::BindTexture(GL_TEXTURE_2D,0);

        //generate framebuffer
        glGenFramebuffers(1,&framebuffers);
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffers);   

        glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture->GetGLName(),0);
        //glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_STENCIL_ATTACHMENT,GL_RENDERBUFFER,stencilRenderBuffer);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, renderTargets[0]->GetGLName(), 0);
       
        GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        if(status!=GL_FRAMEBUFFER_COMPLETE){
            if(status==GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) errorInfo.Append("FBO incomplete.n");   
            if(status==GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) errorInfo.Append("FBO incomplete_Missing.n");   
            return false;
        }
       
    }
   
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    return true;
}


void SetRenderTarget(GLint num){
    //only call gl functions if its necessary
    if(num==currFramebuffer) return;
    // -1 = default framebuffer
    if(num==-1) glBindFramebuffer(GL_FRAMEBUFFER, 0);
    else glBindFramebuffer(GL_FRAMEBUFFER, framebuffers[num]);
    currFramebuffer=num;
}



unsigned long framenum=0;

void Render(CNode** nodes, unsigned int count, CCamera& activeCam){

    framenum++;
   
    IPAQRenderState::SetClearColor(0,0,1,1);
    for(int i=BACKBUFFERCNT-1; i>=0; i--){
        SetRenderTarget(i);
        glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    }

    //Render Some test objects
   
    CRenderingEnvironment rendenv;
    rendenv.framenum=framenum;
    rendenv.ViewMat=activeCam.GetViewMatrix();   
    rendenv.ProjectionMat=activeCam.GetProjectionMatrix();
   
    TVector<Light*> lightlist;
    TVector<RenderCol> meshlist;
    TMat43 identityMatrix;
    GLfloat ambientLight[4]={0,0,0,0};
    for(int i=0; i<count; i++)
        IPAQRenderer::CollectRenderingInformation(rendenv,nodes,identityMatrix,meshlist,lightlist,ambientLight);   

   
    for(int i=0; i<meshlist.Size(); i++){
        meshlist.mesh->LoadShaderDataToGL(meshlist.submeshindex,rendenv,meshlist.modelmat);
        meshlist.mesh->LoadVertexDataToGL(rendenv,meshlist.modelmat);
        meshlist.mesh->LoadSubmeshDataToGL(meshlist.submeshindex,rendenv,meshlist.modelmat);
        meshlist.mesh->RenderSubmesh(meshlist.submeshindex,rendenv,meshlist.modelmat);
    }
   
    //Object rendering finished
   
    // A shader for rendering a textured fullscreenquad multiplied with a color
    CShaderProgram* HUDShaderProgram = IPAQShaderManager::GetHudShader();
    IPAQRenderState::UseShaderProgram(*HUDShaderProgram);   
   
    //Render To system-provided Framebuffer;
      SetRenderTarget(-1);
    glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
   
    IPAQRenderState::SetDepthTest(false);
    IPAQRenderState::SetBlendingEnabled(false);
   
    renderFullscreenQuad(renderTargets[0]);
   
    IPAQHudDrawer::DoDrawings(); 
   
    eglSwapBuffers(iEglDisplay, iEglSurface );
   
   
}



The second problem is with sampling from a depth texture. I do this by replacing the line
Code:
renderFullscreenQuad(renderTargets[0]);

with
Code:
renderFullscreenQuad(depthTexture);

Using PVRFrame I can see  a nice grayscale image of the depth of scene, however on the device the screen is just totally black. And sometimes it changes it's color to white for a short time or another strange rendering artifact occurs: some tiles of the screen get swapped randomly, eg. I can see a part of the text rendered at the top left corner rotated about 90 degrees in the middle of the screen ^^.

BTW: The engine code for PVRFrame and symbian is exactly the same, only a small "base-layer" for out- and input is different.

Thank you for your help in advance!



#2

1/ Might be an issue with your graphic card, although I doubt it.
2/ Maybe try using your depth texture only after the first swap buffer call, or make sure you call glFinish or glFlush before using it.


#3

Hi,

1. Don’t think it’s the problem, i have a rather new graphics card. My system:
  -windows 7 64 bit
  -XFX Geforce GTX275
  -Intel Quad Q9550

2. Tried it, now the screen simply stays white, but the strange tile-swapping still occurs sometimes. The screen staying white might be caused by my shader, it’s normally only used for color textures, so all calculations including texture sampling are performed with lowp precision.


#4

They say in the doc everything ends up being highp anyway on the PC Emulation.


#5

Yep, I think that's why the depth-texturing problem does not occur on the PC.
3DGamer2010-08-16 09:34:07

#6

was there any solution to the problem ? I am experiencing the same (1) !