Sign in to follow this  
maluh13

Changing color using a shader

Recommended Posts

Hello

I am writing a deferred shader and as one of the first steps, to get familiar with GLSL and using shaders and the framebuffer I am trying to change the color of a mesh through a shader.
I have it linked to one of the buffers by calling glDrawBuffers with an array that holds the attachement and then binding the texture to my framebuffer:
[code]

glReadBuffer(GL_NONE);
GLint color_loc = glGetFragDataLocation(pass_prog,"out_Color");
GLenum draws [1];
draws[color_loc] = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1, draws);

glBindTexture(GL_TEXTURE_2D, diffuseTexture);
glFramebufferTexture(GL_FRAMEBUFFER, draws[color_loc], diffuseTexture, 0);
[/code]


i have an out_Color variable in my fragment shader (otherwise it wouldn't even compile), but I can't manage to change the color of the mesh by setting it through that variable inside the shader.
Does anyone has any idea why and could explain that to me?

Thanks

Share this post


Link to post
Share on other sites
Please give more information on what else you're doing. What do you mean 'change the color' of the mesh? What color is it now? What does your shader look like? What result do you get?

Share this post


Link to post
Share on other sites
[quote name='karwosts' timestamp='1298526663' post='4778304']
Please give more information on what else you're doing. What do you mean 'change the color' of the mesh? What color is it now? What does your shader look like? What result do you get?
[/quote]


Vertex Shader:

[code]

#version 330


uniform mat4x4 u_Model;
uniform mat4x4 u_View;
uniform mat4x4 u_Persp;
uniform mat4x4 u_InvTrans;

in vec3 Position;
in vec3 Normal;

out vec3 fs_Normal;
out vec4 fs_Position;
//out vec4 fs_Color;

void main(void) {
fs_Normal = (u_InvTrans*vec4(Normal,0.0f)).xyz;
vec4 world = u_Model * vec4(Position, 1.0);
vec4 camera = u_View * world;
fs_Position = camera;
gl_Position = u_Persp * camera;
//fs_Color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
[/code]

Fragment shader:

[code]

#version 330

uniform float u_Far;

in vec3 fs_Normal;
in vec4 fs_Position;

out vec4 out_Normal;
out vec4 out_Position;
out vec4 out_Color;

void main(void)
{
out_Normal = vec4(normalize(fs_Normal),0.0f);
out_Position = vec4(fs_Position.xyz,1.0f); //Tuck position into 0 1 range
out_Color = vec4(1.0f, 0.0f, 0.0f, 0.5f);//first three diffuse, last specular
}
[/code]
The shaders do a few other things to get the depth, normal and position textures, which are working.

By change the color I mean sort of like set a diffuse color to the mesh. The mesh is now gray and I am trying to make it look red, or blue, or something.

The result is the mesh being gray.

Share this post


Link to post
Share on other sites
If your shader is outputting a static red as shown above, then you probably not compiling and checking errors from the compiler correct. Instead of setting color, set the position of the vertices to be statically (0,0,0) so that no mesh is drawn, see if the mesh still draws(it shouldnt).

Share this post


Link to post
Share on other sites
You need to post your whole of opengl related to your framebuffer, otherwise it's hard to help you. I don't even know if you have created a framebuffer or not.

Have you checked for opengl errors? Framebuffer completeness?

Also you should[b]n't[/b] bind your texture to a sampler and as a rendertarget at the same time, I believe it's undefined behaviour.


Edit: Changed 'should' to 'shouldn't' (bad typo!).

Share this post


Link to post
Share on other sites
[quote name='dpadam450' timestamp='1298530079' post='4778320']
If your shader is outputting a static red as shown above, then you probably not compiling and checking errors from the compiler correct. Instead of setting color, set the position of the vertices to be statically (0,0,0) so that no mesh is drawn, see if the mesh still draws(it shouldnt).
[/quote]

Ok, I changed gl_Position to (0,0,0) in the vertex shader and it doesn't draw it. But in the fragment shader it does nothing. I thought one couldn't change the position in the fragment shader...

Share this post


Link to post
Share on other sites
[quote name='karwosts' timestamp='1298530312' post='4778321']
You need to post your whole of opengl related to your framebuffer, otherwise it's hard to help you. I don't even know if you have created a framebuffer or not.

Have you checked for opengl errors? Framebuffer completeness?

Also you should bind your texture to a sampler and as a rendertarget at the same time, I believe it's undefined behaviour.
[/quote]

The frame buffer is created, and I have checked for completeness and openGL errors. And as I said, the normal, depth and position buffers are working.

[code]


glActiveTexture(GL_TEXTURE0);

glGenTextures(1, &depthTexture);
glGenTextures(1, &normalTexture);
glGenTextures(1, &positionTexture);

//DEPTH TEXTURE
glBindTexture(GL_TEXTURE_2D, depthTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, w, h, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);

//NORMAL TEXTURE
glBindTexture(GL_TEXTURE_2D, normalTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB32F , w, h, 0, GL_RGBA, GL_FLOAT,0);

//POSITION TEXTURE
glBindTexture(GL_TEXTURE_2D, positionTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB32F , w, h, 0, GL_RGBA, GL_FLOAT,0);

//DIFFUSE TEXTURE
glBindTexture(GL_TEXTURE_2D, diffuseTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB32F , w, h, 0, GL_RGBA, GL_FLOAT,0);

// create a framebuffer object
glGenFramebuffers(1, &FBO);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);

// Instruct openGL that we won't bind a color texture with the currently binded FBO
glReadBuffer(GL_NONE);
GLint normal_loc = glGetFragDataLocation(pass_prog,"out_Normal");
GLint position_loc = glGetFragDataLocation(pass_prog,"out_Position");
GLint color_loc = glGetFragDataLocation(pass_prog,"out_Color");
GLenum draws [3];
draws[normal_loc] = GL_COLOR_ATTACHMENT0;
draws[position_loc] = GL_COLOR_ATTACHMENT1;
draws[color_loc] = GL_COLOR_ATTACHMENT2;
glDrawBuffers(3, draws);

glBindTexture(GL_TEXTURE_2D, depthTexture);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0);
glBindTexture(GL_TEXTURE_2D, normalTexture);
glFramebufferTexture(GL_FRAMEBUFFER, draws[normal_loc], normalTexture, 0);
glBindTexture(GL_TEXTURE_2D, positionTexture);
glFramebufferTexture(GL_FRAMEBUFFER, draws[position_loc], positionTexture, 0);
glBindTexture(GL_TEXTURE_2D, diffuseTexture);
glFramebufferTexture(GL_FRAMEBUFFER, draws[color_loc], diffuseTexture, 0);


// check FBO status
FBOstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(FBOstatus != GL_FRAMEBUFFER_COMPLETE) {
printf("GL_FRAMEBUFFER_COMPLETE failed, CANNOT use FBO\n");
checkFramebufferStatus(FBOstatus);
}


// switch back to window-system-provided framebuffer
glClear(GL_DEPTH_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}

[/code]


I am not sure what you call a sampler, but I think the diffuseTexture would be the render target, right?

Share this post


Link to post
Share on other sites
For the sampler I meant the glBindTexture, you don't need to bind diffuseTexture to GL_TEXTURE_2D to use it as a framebuffer texture. Seems you unbind it before you render though, so I guess that's ok.

If it was still bound to glBindTexture at the same time you were rendering to it I think it would fail. But that doesn't seem like your problem.

Share this post


Link to post
Share on other sites
[quote name='karwosts' timestamp='1298531796' post='4778330']
For the sampler I meant the glBindTexture, you don't need to bind diffuseTexture to GL_TEXTURE_2D to use it as a framebuffer texture. Seems you unbind it before you render though, so I guess that's ok.

If it was still bound to glBindTexture at the same time you were rendering to it I think it would fail. But that doesn't seem like your problem.
[/quote]

Ok. One option discarded. Cool.

But, it is possible, right? To set the color in a shader.
I've heard one can do the diffuse color modulated by the ambient factor in the fixed function pipeline although I am not sure how exactly. But I feel it should also be done in the shader.

Share this post


Link to post
Share on other sites
Yeah anything should be possible, but I still don't really get your whole flow. You're drawing a mesh into a framebuffer, what do you do with it then? Do you draw the framebuffer as a fullscreen quad? You haven't put up any drawing code.

Share this post


Link to post
Share on other sites
[quote name='karwosts' timestamp='1298532261' post='4778332']
Yeah anything should be possible, but I still don't really get your whole flow. You're drawing a mesh into a framebuffer, what do you do with it then? Do you draw the framebuffer as a fullscreen quad? You haven't put up any drawing code.
[/quote]

Basically, yes.
As part of the full screen quad rendering I also do the light computations, so it is a little more involved than just drawing the full screen quad.
In the quad shader, I am retrieving information from the different rendertargets and combining them or showing them separated, depending on what I want. Diffuse always shows up gray, and when I change diffuse to be another color within this second shader, it works, so my equations are fine. This has led me to believe that there must be a problem with how I am writing to that texture, since all the other textures are giving me the correct output.

[code]


void draw_street() {
FARP = 100.0f;
NEARP = 1.0f;


glUseProgram(pass_prog);
glBindVertexArray(device_street.vertex_array);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, device_street.vbo_indices);

mat4 model = get_street_world();
mat4 view = cam.get_view();
mat4 persp = perspective(45.0f,1.0f,NEARP,FARP);
mat4 inverse_transposed = transpose(inverse(view*model));

glUniform1f(glGetUniformLocation(pass_prog, "u_Far"), FARP);
glUniformMatrix4fv(glGetUniformLocation(pass_prog,"u_Model"),1,GL_FALSE,&model[0][0]);
glUniformMatrix4fv(glGetUniformLocation(pass_prog,"u_View"),1,GL_FALSE,&view[0][0]);
glUniformMatrix4fv(glGetUniformLocation(pass_prog,"u_Persp"),1,GL_FALSE,&persp[0][0]);
glUniformMatrix4fv(glGetUniformLocation(pass_prog,"u_InvTrans") ,1,GL_FALSE,&inverse_transposed[0][0]);

glDrawElements(GL_TRIANGLES, device_street.num_indices, GL_UNSIGNED_SHORT,0);

glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
}


void draw_quad() {
glUseProgram(ssao_prog);

glBindVertexArray(device_quad.vertex_array);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, device_quad.vbo_indices);

glEnable(GL_TEXTURE_2D);

mat4 persp = perspective(45.0f,1.0f,NEARP,FARP);
glUniform1i(glGetUniformLocation(ssao_prog, "u_ScreenHeight"), height);
glUniform1i(glGetUniformLocation(ssao_prog, "u_ScreenWidth"), width);
glUniform1f(glGetUniformLocation(ssao_prog, "u_Far"), FARP);
glUniform1f(glGetUniformLocation(ssao_prog, "u_Near"), NEARP);
glUniform1i(glGetUniformLocation(ssao_prog, "u_OcclusionType"), occlusion_type);
glUniform1i(glGetUniformLocation(ssao_prog, "u_DisplayType"), display_type);
glUniformMatrix4fv(glGetUniformLocation(ssao_prog, "u_Persp"),1, GL_FALSE, &persp[0][0] );

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, depthTexture);
glUniform1i(glGetUniformLocation(ssao_prog, "u_Depthtex"),0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, normalTexture);
glUniform1i(glGetUniformLocation(ssao_prog, "u_Normaltex"),1);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, positionTexture);
glUniform1i(glGetUniformLocation(ssao_prog, "u_Positiontex"),2);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, diffuseTexture);
glUniform1i(glGetUniformLocation(ssao_prog, "u_Diffusetex"),3);
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, random_scalar_tex);
glUniform1i(glGetUniformLocation(ssao_prog, "u_RandomScalartex"),4);



glColor4f(1.0f, 0.0f,0.0f,1.0f);
glDrawElements(GL_TRIANGLES, device_quad.num_indices, GL_UNSIGNED_SHORT,0);

glBindVertexArray(0);
}


[/code]


Those 2 methods are called from the display function.

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