Render To Texture Using OpenGL is not working but normal rendering works just fine

Posted by Franky Rivera on Game Development See other posts from Game Development or by Franky Rivera
Published on 2014-08-20T12:48:48Z Indexed on 2014/08/20 16:37 UTC
Read the original article Hit count: 313

Filed under:
|
|
|

things I initialize at the beginning of the program I realize not all of these pertain to my issue I just copy and pasted what I had //overall initialized

//things openGL related I initialize earlier on in the project

glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );

glClearDepth( 1.0f );
glEnable(GL_ALPHA_TEST);

glEnable( GL_STENCIL_TEST );

glEnable(GL_DEPTH_TEST);
glDepthFunc( GL_LEQUAL );

glEnable(GL_CULL_FACE);
glFrontFace( GL_CCW );

glEnable(GL_COLOR_MATERIAL);

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );

//we also initialize our shader programs
//(i added some shader program functions for definitions)

//this enum list is else where in code
//i figured it would help show you guys more about my
//shader compile creation function right under this enum list VVVVVV
/*enum eSHADER_ATTRIB_LOCATION
{ 
    VERTEX_ATTRIB = 0, 
    NORMAL_ATTRIB = 2,
    COLOR_ATTRIB,
    COLOR2_ATTRIB,
    FOG_COORD,
    TEXTURE_COORD_ATTRIB0 = 8,
    TEXTURE_COORD_ATTRIB1,
    TEXTURE_COORD_ATTRIB2,
    TEXTURE_COORD_ATTRIB3,
    TEXTURE_COORD_ATTRIB4,
    TEXTURE_COORD_ATTRIB5,
    TEXTURE_COORD_ATTRIB6,
    TEXTURE_COORD_ATTRIB7
}; */


//if we fail making our shader leave
if( !testShader.CreateShader( "SimpleShader.vp", "SimpleShader.fp", 3,
                               VERTEX_ATTRIB, "vVertexPos", 
                               NORMAL_ATTRIB,  "vNormal", 
                               TEXTURE_COORD_ATTRIB0, "vTexCoord" ) )
    return false;

if( !testScreenShader.CreateShader( "ScreenShader.vp", "ScreenShader.fp", 3,
                                    VERTEX_ATTRIB, "vVertexPos",
                                    NORMAL_ATTRIB, "vNormal",
                                    TEXTURE_COORD_ATTRIB0, "vTexCoord" ) )
    return false;

SHADER PROGRAM FUNCTIONS

bool CShaderProgram::CreateShader( const char* szVertexShaderName,
                                   const char* szFragmentShaderName, ... )
{
    //here are our handles for the openGL shaders
    int iGLVertexShaderHandle = -1, iGLFragmentShaderHandle = -1;

    //get our shader data
    char *vData = 0, *fData = 0;
    int vLength = 0, fLength = 0;

    LoadShaderFile( szVertexShaderName, &vData, &vLength );
    LoadShaderFile( szFragmentShaderName, &fData, &fLength );

    //data
    if( !vData )
        return false;

    //data
    if( !fData )
    {
        delete[] vData;
        return false;
    }

    //create both our shader objects
    iGLVertexShaderHandle = glCreateShader( GL_VERTEX_SHADER );
    iGLFragmentShaderHandle = glCreateShader( GL_FRAGMENT_SHADER );

    //well we got this far so we have dynamic data to clean up


    //load vertex shader
    glShaderSource( iGLVertexShaderHandle, 1, (const char**)(&vData), &vLength );

    //load fragment shader
    glShaderSource( iGLFragmentShaderHandle, 1, (const char**)(&fData), &fLength );

    //we are done with our data delete it
    delete[] vData;
    delete[] fData;

    //compile them both
    glCompileShader( iGLVertexShaderHandle );

    //get shader status
    int iShaderOk;
    glGetShaderiv( iGLVertexShaderHandle, GL_COMPILE_STATUS, &iShaderOk );

    if( iShaderOk == GL_FALSE )
    {
        char* buffer;

        //get what happend with our shader
        glGetShaderiv( iGLVertexShaderHandle, GL_INFO_LOG_LENGTH, &iShaderOk );
        buffer = new char[iShaderOk];
        glGetShaderInfoLog( iGLVertexShaderHandle, iShaderOk, NULL, buffer );

        //sprintf_s( buffer, "Failure Our Object For %s was not created", szFileName );
        MessageBoxA( NULL, buffer, szVertexShaderName, MB_OK );

        //delete our dynamic data
        free( buffer );

        glDeleteShader(iGLVertexShaderHandle);
        return false;
    }

    glCompileShader( iGLFragmentShaderHandle );

    //get shader status
    glGetShaderiv( iGLFragmentShaderHandle, GL_COMPILE_STATUS, &iShaderOk );

    if( iShaderOk == GL_FALSE )
    {
        char* buffer;

        //get what happend with our shader
        glGetShaderiv( iGLFragmentShaderHandle, GL_INFO_LOG_LENGTH, &iShaderOk );
        buffer = new char[iShaderOk];
        glGetShaderInfoLog( iGLFragmentShaderHandle, iShaderOk, NULL, buffer );

        //sprintf_s( buffer, "Failure Our Object For %s was not created", szFileName );
        MessageBoxA( NULL, buffer, szFragmentShaderName, MB_OK );

        //delete our dynamic data
        free( buffer );

        glDeleteShader(iGLFragmentShaderHandle);
        return false;
    }

    //lets check to see if the fragment shader compiled
    int iCompiled = 0;
    glGetShaderiv( iGLVertexShaderHandle, GL_COMPILE_STATUS, &iCompiled );

    if( !iCompiled )
    {
        //this shader did not compile leave
        return false;
    }

    //lets check to see if the fragment shader compiled
    glGetShaderiv( iGLFragmentShaderHandle, GL_COMPILE_STATUS, &iCompiled );

    if( !iCompiled )
    {
        char* buffer;

        //get what happend with our shader
        glGetShaderiv( iGLFragmentShaderHandle, GL_INFO_LOG_LENGTH, &iShaderOk );
        buffer = new char[iShaderOk];
        glGetShaderInfoLog( iGLFragmentShaderHandle, iShaderOk, NULL, buffer );

        //sprintf_s( buffer, "Failure Our Object For %s was not created", szFileName );
        MessageBoxA( NULL, buffer, szFragmentShaderName, MB_OK );

        //delete our dynamic data
        free( buffer );

        glDeleteShader(iGLFragmentShaderHandle);
        return false;
    }

    //make our new shader program
    m_iShaderProgramHandle = glCreateProgram();

    glAttachShader( m_iShaderProgramHandle, iGLVertexShaderHandle );
    glAttachShader( m_iShaderProgramHandle, iGLFragmentShaderHandle );

    glLinkProgram( m_iShaderProgramHandle );

    int iLinked = 0;
    glGetProgramiv( m_iShaderProgramHandle, GL_LINK_STATUS, &iLinked );

    if( !iLinked )
    {
        //we didn't link
        return false;
    }

    //NOW LETS CREATE ALL OUR HANDLES TO OUR PROPER LIKING

    //start from this parameter
    va_list parseList;
    va_start( parseList, szFragmentShaderName );

    //read in number of variables if any
    unsigned uiNum = 0;
    uiNum = va_arg( parseList, unsigned );

    //for loop through our attribute pairs
    int enumType = 0;
    for( unsigned x = 0; x < uiNum; ++x )
    {
        //specify our attribute locations
        enumType = va_arg( parseList, int );
        char* name = va_arg( parseList, char* );
        glBindAttribLocation( m_iShaderProgramHandle, enumType, name );
    }

    //end our list parsing
    va_end( parseList );

    //relink specify
    //we have custom specified our attribute locations
    glLinkProgram( m_iShaderProgramHandle );

    //fill our handles
    InitializeHandles( );

    //everything went great
    return true;
}

void CShaderProgram::InitializeHandles( void )
{
    m_uihMVP = glGetUniformLocation( m_iShaderProgramHandle, "mMVP" );

    m_uihWorld = glGetUniformLocation( m_iShaderProgramHandle, "mWorld" );

    m_uihView = glGetUniformLocation( m_iShaderProgramHandle, "mView" );

    m_uihProjection = glGetUniformLocation( m_iShaderProgramHandle, "mProjection" );

    /////////////////////////////////////////////////////////////////////////////////
    //texture handles

    m_uihDiffuseMap = glGetUniformLocation( m_iShaderProgramHandle, "diffuseMap" );
    if( m_uihDiffuseMap != -1 )
    {
        //store what texture index this handle will be in the shader
        glUniform1i( m_uihDiffuseMap, RM_DIFFUSE+GL_TEXTURE0 ); (0)+
    }

    m_uihNormalMap = glGetUniformLocation( m_iShaderProgramHandle, "normalMap" );
    if( m_uihNormalMap != -1 )
    {   
        //store what texture index this handle will be in the shader
        glUniform1i( m_uihNormalMap, RM_NORMAL+GL_TEXTURE0  ); (1)+
    }
}

void CShaderProgram::SetDiffuseMap( const unsigned& uihDiffuseMap )
{                     (0)+
    glActiveTexture( RM_DIFFUSE+GL_TEXTURE0 );
    glBindTexture( GL_TEXTURE_2D, uihDiffuseMap );
}

void CShaderProgram::SetNormalMap( const unsigned& uihNormalMap )
{                      (1)+
    glActiveTexture( RM_NORMAL+GL_TEXTURE0 );
    glBindTexture( GL_TEXTURE_2D, uihNormalMap );
}

//MY 2 TEST SHADERS also my math order is correct it pertains to my matrix ordering in my math library once again i've tested the basic rendering. rendering to the screen works fine ----------------------------------------SIMPLE SHADER-------------------------------------

//vertex shader looks like this

#version 330

in vec3 vVertexPos;
in vec3 vNormal;
in vec2 vTexCoord;

uniform mat4 mWorld;     // Model Matrix
uniform mat4 mView;  // Camera View Matrix
uniform mat4 mProjection;// Camera Projection Matrix

out vec2 vTexCoordVary; // Texture coord to the fragment program
out vec3 vNormalColor;

void main( void )
{
    //pass the texture coordinate
    vTexCoordVary = vTexCoord;
    vNormalColor = vNormal;

    //calculate our model view projection matrix
    mat4 mMVP = (( mWorld  * mView ) * mProjection );

    //result our position
    gl_Position = vec4( vVertexPos, 1 ) * mMVP;
}

//fragment shader looks like this

#version 330

in vec2 vTexCoordVary;
in vec3 vNormalColor;

uniform sampler2D diffuseMap;
uniform sampler2D normalMap;

out vec4 fragColor[2];

void main( void )
{
    //CORRECT
    fragColor[0] = texture( normalMap, vTexCoordVary );
    fragColor[1] = vec4( vNormalColor, 1.0 );
};

----------------------------------------SCREEN SHADER-------------------------------------

//vertext shader looks like this

#version 330

in vec3 vVertexPos; // This is the position of the vertex coming in
in vec2 vTexCoord; // This is the texture coordinate....

out vec2 vTexCoordVary; // Texture coord to the fragment program

void main( void )
{
    vTexCoordVary = vTexCoord;

    //set our position
    gl_Position = vec4( vVertexPos.xyz, 1.0f );
}

//fragment shader looks like this

#version 330

in vec2 vTexCoordVary;  // Incoming "varying" texture coordinate

uniform sampler2D diffuseMap;//the tile detail texture
uniform sampler2D normalMap; //the normal map from earlier

out vec4 vTheColorOfThePixel;

void main( void )
{

    //CORRECT
    vTheColorOfThePixel = texture( normalMap, vTexCoordVary );
};

.Class RenderTarget Main Functions

//here is my render targets create function
bool CRenderTarget::Create( const unsigned uiNumTextures,
                            unsigned uiWidth,
                            unsigned uiHeight,
                            int iInternalFormat,
                            bool bDepthWanted )
{
    if( uiNumTextures <= 0 )
        return false;

    //generate our variables
    glGenFramebuffers(1, &m_uifboHandle);

    // Initialize FBO
    glBindFramebuffer(GL_FRAMEBUFFER, m_uifboHandle);

    m_uiNumTextures = uiNumTextures;

    if( bDepthWanted )
        m_uiNumTextures += 1; 

    m_uiTextureHandle = new unsigned int[uiNumTextures];
    glGenTextures( uiNumTextures, m_uiTextureHandle );

    for( unsigned x = 0; x < uiNumTextures-1; ++x )
    {
        glBindTexture( GL_TEXTURE_2D, m_uiTextureHandle[x]);

        // Reserve space for our 2D render target
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glTexImage2D(GL_TEXTURE_2D, 0, iInternalFormat, uiWidth, uiHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + x, GL_TEXTURE_2D, m_uiTextureHandle[x], 0); 
    }

    //if we need one for depth testing
    if( bDepthWanted )
    {
        glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_uiTextureHandle[uiNumTextures-1], 0);
        glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_uiTextureHandle[uiNumTextures-1], 0);*/
        // Must attach texture to framebuffer. Has Stencil and depth
        glBindRenderbuffer(GL_RENDERBUFFER, m_uiTextureHandle[uiNumTextures-1]);
        glRenderbufferStorage(GL_RENDERBUFFER, /*GL_DEPTH_STENCIL*/GL_DEPTH24_STENCIL8, TEXTURE_WIDTH, TEXTURE_HEIGHT );
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_uiTextureHandle[uiNumTextures-1]);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_uiTextureHandle[uiNumTextures-1]);
    }

    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    //everything went fine
    return true;
}

void CRenderTarget::Bind(   const int& iTargetAttachmentLoc,
                            const unsigned& uiWhichTexture,
                            const bool bBindFrameBuffer )
{
    if( bBindFrameBuffer )
        glBindFramebuffer( GL_FRAMEBUFFER, m_uifboHandle );

    if( uiWhichTexture < m_uiNumTextures )
        glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + iTargetAttachmentLoc, m_uiTextureHandle[uiWhichTexture], 0);    
}

void CRenderTarget::UnBind( void )
{
    //default our binding
    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
}

//this is all in a test project so here's my straight forward rendering function for testing

this render function does basic rendering steps keep in mind i have already tested my textures i have already tested my box thats being rendered all basic rendering works fine its just when i try to render to a texture then display it in a render surface that it does not work. Also I have tested my render surface it is bound exactly to the screen coordinate space

void TestRenderSteps( void )
{
    //Clear the color and the depth
    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    //bind the shader program
    glUseProgram( testShader.m_iShaderProgramHandle );

    //1) grab the vertex buffer related to our rendering
    glBindBuffer( GL_ARRAY_BUFFER, CVertexBufferManager::GetInstance()->GetPositionNormalTexBuffer().GetBufferHandle() );

    //2) how our stream will be split here ( 4 bytes position, ..ext ) 
    CVertexBufferManager::GetInstance()->GetPositionNormalTexBuffer().MapVertexStride();

    //3) set the index buffer if needed
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, CIndexBuffer::GetInstance()->GetBufferHandle() );

    //send the needed information into the shader
    testShader.SetWorldMatrix( boxPosition );
    testShader.SetViewMatrix( Static_Camera.GetView( ) );
    testShader.SetProjectionMatrix( Static_Camera.GetProjection( ) );

    testShader.SetDiffuseMap( iTextureID );
    testShader.SetNormalMap( iTextureID2 );

    GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
    glDrawBuffers(2, buffers);

    //bind to our render target
    //RM_DIFFUSE, RM_NORMAL are enums (0 && 1)
    renderTarget.Bind( RM_DIFFUSE, 1, true );
    renderTarget.Bind( RM_NORMAL, 1, false); //false because buffer is already bound

    //i clear here just to clear the texture to make it a default value of white
    //by doing this i can see if what im rendering to my screen is just drawing to the screen
    //or if its my render target defaulted
    glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    //i have this box object which i draw
    testBox.Draw();

    //the draw call looks like this 
    //my normal rendering works just fine so i know this draw is fine
    // glDrawElementsBaseVertex( m_sides[x].GetPrimitiveType(),
    //                           m_sides[x].GetPrimitiveCount() * 3,
    //                           GL_UNSIGNED_INT,
    //                           BUFFER_OFFSET(sizeof(unsigned int) * m_sides[x].GetStartIndex()),
    //                           m_sides[x].GetStartVertex( ) );

    //we unbind the target back to default
    renderTarget.UnBind();

    //i stop mapping my vertex format
    CVertexBufferManager::GetInstance()->GetPositionNormalTexBuffer().UnMapVertexStride();

    //i go back to default in using no shader program
    glUseProgram( 0 );

    //now that everything is drawn to the textures
    //lets draw our screen surface and pass it our 2 filled out textures

    //NOW RENDER THE TEXTURES WE COLLECTED TO THE SCREEN QUAD
    //bind the shader program
    glUseProgram( testScreenShader.m_iShaderProgramHandle );

    //1) grab the vertex buffer related to our rendering
    glBindBuffer( GL_ARRAY_BUFFER, CVertexBufferManager::GetInstance()->GetPositionTexBuffer().GetBufferHandle() );

    //2) how our stream will be split here
    CVertexBufferManager::GetInstance()->GetPositionTexBuffer().MapVertexStride();

    //3) set the index buffer if needed
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, CIndexBuffer::GetInstance()->GetBufferHandle() );

    //pass our 2 filled out textures (in the shader im just using the diffuse
    //i wanted to see if i was rendering anything before i started getting into other techniques
    testScreenShader.SetDiffuseMap( renderTarget.GetTextureHandle(0) );  //SetDiffuseMap definitions in shader program class
    testScreenShader.SetNormalMap( renderTarget.GetTextureHandle(1) );   //SetNormalMap definitions in shader program class

    //DO the draw call drawing our screen rectangle
    glDrawElementsBaseVertex( m_ScreenRect.GetPrimitiveType(),
                              m_ScreenRect.GetPrimitiveCount() * 3,
                              GL_UNSIGNED_INT,
                              BUFFER_OFFSET(sizeof(unsigned int) * m_ScreenRect.GetStartIndex()),
                              m_ScreenRect.GetStartVertex( ) );*/

    //unbind our vertex mapping
    CVertexBufferManager::GetInstance()->GetPositionTexBuffer().UnMapVertexStride();

    //default to no shader program
    glUseProgram( 0 );
}

Last words:

1) I can render my box just fine

2) i can render my screen rect just fine

3) I cannot render my box into a texture then display it into my screen rect

4) This entire project is just a test project I made to test different rendering practices. So excuse any "ugly-ish" unclean code. This was made just on a fly run through when I was trying new test cases.

© Game Development or respective owner

Related posts about opengl

Related posts about c++