Changing color using a shader

Started by
9 comments, last by maluh13 13 years, 2 months ago
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:


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



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
Advertisement
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?
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game

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?



Vertex Shader:



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


Fragment shader:



#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
}

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

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

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 shouldn't 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!).
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game

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


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...

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.


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.




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




I am not sure what you call a sampler, but I think the diffuseTexture would be the render target, right?
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.
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game

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.


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.
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.
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game

This topic is closed to new replies.

Advertisement