Sign in to follow this  
lightbug

Bind textures from framebuffer

Recommended Posts

Hello, like says in the title, I'm playing aroud with framebuffers, I have made a basic postprocessing effect (chromatic aberration), to do this I created a fbo, bind it like GL_FRAMEBUFFER, render every geometry and then Unbind it  (= 0) , the thing is that i want to use two framebuffers.

 

I have two classes "Deferred" and "PostProcessing"

 

The first stage consist in render the geometry, so I Bind the FBO from Deferred

 

The second stage consist in render the deferred lighting (see the shader below, actually it does nothing) Unding the FBO from deferred and Bind the one from PostProcessing.

 

the third stage consist in render with the postProcessing shader, so I Unbind the fbo from postProcessing

 

1) is this the correct way of doing this?

 

 

The problem : before create the deferred class, the postProcessing works fine (I have passing only one texture) , but now with both (deferred and PP) the display is clear always (a blue background). Maybe because I'm passing the textures in the wrong way, i don't know sad.png

 

 

Here is the Code from Renderer.cpp (the master render class)


void Renderer::Frame()	
{

    BeginDraw(ColorBrackground.x, ColorBrackground.y, ColorBrackground.z, ColorBrackground.w);

    RenderScene();
    RenderDeferred();
    RenderPostProcessing();

	EndDraw();

}

void Renderer::BeginDraw(float r, float g , float b, float a)
{

    glClearColor(r, g, b, a);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);

}

void Renderer::EndDraw()
{
    m_window->SwapBuffers();

    if(PostProcessingFX)
    m_postProcessing->UnbindFBO();

    if(DeferredRendering)
    m_deferredRender->UnbindFBO();
}



void Renderer::RenderScene()
{
    if(DeferredRendering)
    m_deferredRender->BindFBO();

    if(PostProcessingFX  && !DeferredRendering)
    m_postProcessing->BindFBO();

    ObjectsManager::GetInstance()->RenderAll();


}

void Renderer::RenderDeferred()
{

    if(!DeferredRendering)
    return;


    m_deferredRender->UnbindFBO();

    if(PostProcessingFX)
    m_postProcessing->BindFBO();    


    m_deferredRender->RenderLightingPass();


}

void Renderer::RenderPostProcessing()
{
    if(!PostProcessingFX)
    return;

    m_postProcessing->UnbindFBO();

    m_postProcessing->Render();

}



with :

 

Deferred.cpp

void Deferred::InitTextures()
{
//Get data from window
    SDL_Window* window = Renderer::GetInstance()->GetWindow()->GetSDLWindow();
    SDL_GetWindowSize(window , &width , &height);


// Create the textures
    glGenTextures(ARRAY_SIZE(m_textures), m_textures);


//Albedo
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_textures[Albedo]);

    //Properties
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, NULL);

    //Bind to the FBO
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textures[Albedo], 0);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, 0);

//Normal
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, m_textures[Normal]);

    //Properties
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, NULL);

    //Bind to the FBO
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_textures[Normal], 0);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, 0);
  


}

bool Deferred::Initialize()
{

    // Create the FBO
    glGenFramebuffers(1, &m_FBO);
    glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);

    std::cout <<  m_FBO <<std::endl;

    InitTextures();


    //Set the draw buffers
    GLenum DrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
    glDrawBuffers(ARRAY_SIZE(DrawBuffers), DrawBuffers);


    GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

    if (Status != GL_FRAMEBUFFER_COMPLETE) {
        printf("FB error, status: 0x%x\n", Status);
        return false;
    }


    glBindFramebuffer(GL_FRAMEBUFFER, 0);


    m_shader = new DeferredShader;
    m_shader->Initialize();

    return true;
}




void Deferred::RenderLightingPass()
{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);

    m_shader->Render( m_textures[Albedo] ,m_textures[Normal]);

}

And PostProcessing:

void PostProcessing::InitTextures()
{
    //Get data from window
    SDL_Window* window = Renderer::GetInstance()->GetWindow()->GetSDLWindow();
    SDL_GetWindowSize(window , &width , &height);


    // Create the textures
    glGenTextures(ARRAY_SIZE(m_textures), m_textures);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_textures[0]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, NULL);

    //Unbind texture
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, 0);
}


bool PostProcessing::Initialize()
{

    // Create the FBO
    glGenFramebuffers(1, &m_FBO);
    glBindFramebuffer(GL_FRAMEBUFFER , m_FBO);

    std::cout <<  m_FBO <<std::endl;

    InitTextures();

    //Bind to the FBO
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
                            GL_COLOR_ATTACHMENT0,
                            GL_TEXTURE_2D,
                            m_textures[0],
                            0);



    //Set the draw buffers
    GLenum DrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
    glDrawBuffers(1, DrawBuffers);



    GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

    if (Status != GL_FRAMEBUFFER_COMPLETE) {
        printf("FB error, status: 0x%x\n", Status);
        return false;
    }


    glBindFramebuffer(GL_FRAMEBUFFER, 0);


    m_shader = new ScreenShader;
    m_shader->Initialize();



    return true;


}



void PostProcessing::Render()
{
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);    

    m_shader->Render(m_textures[0]);

}

Here is my fragments shaders , In the geometry pass I use only one shader (textureshader)

 

TextureShader

#version 330

in vec2 texCoord0;
in vec3 normal0;

uniform vec4 color;
uniform sampler2D sampler;

layout (location = 0) out vec4 alb;	
layout (location = 1) out vec4 norm;	


void main()
{		
	
	alb = texture2D(sampler, texCoord0) * color;
	norm = vec4(normal0 , 0);
	
}

DeferredShader

#version 330

in vec2 texCoord0;


uniform sampler2D Albedo;
uniform sampler2D Normal;

layout (location = 0) out vec4 result;

void main()
{
	result =  texture2D( Albedo , texCoord0 );
}

PostProcessingShader

#version 330

in vec2 texCoord0;


uniform sampler2D sampler;
uniform float offset;

out vec4 result;



void main()
{
	vec4 scene;
	vec4 left;
	vec4 right;

	scene = texture2D(sampler, texCoord0);
 
	if(texCoord0.x - offset >= 0 && texCoord0.x + offset <= 1)
	{
		left = texture2D(sampler, vec2(texCoord0.x - offset , texCoord0.y) );
		right = texture2D(sampler, vec2(texCoord0.x + offset , texCoord0.y) );
	}
	else { 
	left = scene;
	right = scene;
	}
		
	
	result = vec4(left.x , scene.y , right.z , scene.z);	
	
		
}

2) if I said --> layout (location =  X ) out vec4 result; , the result color would be the ColorAttachmentX right? (in the binded FBO of course)

 

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

This is a snippet of my deferredshader.cpp:

void DeferredShader::InitQuad()
{

    vec2 vertices[] = { vec2( -1 , 1 ) ,
                        vec2(-1 , -1) ,
                        vec2(1 , -1) ,
                        vec2( 1, 1) };

    GLuint indices[] = {0 , 1 , 2 ,
                        0 , 2 , 3};

    vec2 uvs[] = { vec2( 0 , 1 ) ,
                vec2(0 , 0) ,
                vec2(1 , 0) ,
                vec2( 1, 1) };




    //positions
    glBindBuffer(GL_ARRAY_BUFFER, m_VAB[bufferPosition] );
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * 4 , //4 .... es QUAD
                    vertices ,
                    GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);


    //uvs
    glBindBuffer(GL_ARRAY_BUFFER, m_VAB[bufferUVs]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(uvs[0]) * 4 ,
                    uvs ,
                    GL_STATIC_DRAW);

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);


    //indices
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_VAB[bufferIndices]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
				sizeof(indices[0]) * 6,
				&indices[0],
				GL_STATIC_DRAW);


	//Unbind the VAO
	glBindVertexArray(0);



}



void DeferredShader::Initialize()
{
	const std::string fileName = "./Resource/Glsl/deferred";


    m_program = glCreateProgram();
	m_vertexShader = CreateShader(LoadShader(fileName + ".vs"), GL_VERTEX_SHADER);
	m_fragmentShader = CreateShader(LoadShader(fileName + ".fs"), GL_FRAGMENT_SHADER);


	glAttachShader(m_program, m_vertexShader);
	glAttachShader(m_program, m_fragmentShader);

    //set the semantic for the input
	glBindAttribLocation(m_program, 0, "position");
	glBindAttribLocation(m_program, 1, "texCoord");

	glLinkProgram(m_program);
	CheckShaderError(m_program, GL_LINK_STATUS, true, "Error linking shader program");

	glValidateProgram(m_program);
	CheckShaderError(m_program, GL_LINK_STATUS, true, "Invalid shader program");



    uniform_Alb = glGetUniformLocation(m_program, "Albedo");
    uniform_Norm = glGetUniformLocation(m_program, "Normal");


    InitQuad();

}





void DeferredShader::Render(GLuint albedo , GLuint normal)
{
    glUseProgram(m_program);


    //Bind textures

    glActiveTexture(GL_TEXTURE0);
    glUniform1i(uniform_Alb , 0);
    glBindTexture(GL_TEXTURE_2D, albedo);

    glActiveTexture(GL_TEXTURE1);
    glUniform1i(uniform_Norm , 1);
    glBindTexture(GL_TEXTURE_2D, normal);
  
	glBindVertexArray(m_VAO);

	//Draw
	glDrawElements(GL_TRIANGLES ,6 , GL_UNSIGNED_INT , 0 );


//Release resources
    glBindVertexArray(0);

	//Unbind textures
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, 0);

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, 0);

  




}

3) is necessary the "glUniform1i(...  )"?

 

4) is correct to Unbind the texture via " glActiveTexture(GL_TEXTURE X );     glBindTexture(GL_TEXTURE_2D, 0); " ??

 

 

 

 

 

sorry about :

- Put so much code

- The english laugh.png

 

Thanks in advance!

Share this post


Link to post
Share on other sites
I couldn't go through all you code but a point I noticed was that you don't detach the normal texture from color GL_COLOR_ATTACHMENT1 that can be the problem specially since you said you had no problem before deferred rendering.
just use:
 
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, 0);
and there is no need to unbind textures since you bind the texture to the right sampler and you use that sampler in you shader to access it.
so if a texture stays bound to a sampler coz you don't use it,it wont cause a problem.

and for GL_COLOR_ATTACHMENTx you can use glFragData[x] Edited by IYP

Share this post


Link to post
Share on other sites


I couldn't go through all you code but a point I noticed was that you don't detach the normal texture from color GL_COLOR_ATTACHMENT1 that can be the problem specially since you said you had no problem before deferred rendering.

 

Hi, thanks for the answer, but, why would I want detach the normal texture?, In every tutorial and example i've seen that the "glFramebufferTexture2D" is called once, in the initialization.

 

 

I fix the problem, it was (as always) a reaaaaallly stupid problem, when i called InitQuad() I forgot to call this:


glGenVertexArrays(1, &m_VAO);
glBindVertexArray(m_VAO);
glGenBuffers(3, m_VAB);

So, sometimes it gives me "Segmentation Fault".

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this