PDA

View Full Version : GLSL shaders gives black textures.



kingc8
06-23-2010, 05:47 AM
Hello,

I'm having a little problem with GLSL, when I compile and use fragment and vertex shaders either in an FBO or the main screen buffer, all my textures just turn out black.

In my naivety I'm loading GLSL examples I found lying around the Internet. The only success I had was with a minimal fragment and vertex shader where the fragment shader sets the pixel to purple. -And all my textures were purple, precisely as planned.

But as for running less trivial things like this convolution filter I found here:

http://www.ozone3d.net/smf/index.php?topic=68.0

..it's just producing black textures. :-(

What are some of the false assumptions I may be under?

Thanks,

Cameron

kingc8
06-23-2010, 05:50 AM
Oh I should mention what I'm trying to achieve.

I'm trying to perform post-processing on textures, blur, bloom etc.

GL Starter
06-23-2010, 06:04 AM
I faced blackout issue when I forgot to call glActiveTexture().


For setting a texture to shader follow the below steps:
glGetUniformLocationARB( m_hProgramObject, TextureName );
glActiveTexture(GL_TEXTURE0 + nTextureID_i );
glUniform1iARB( nParamObj, nTextureID_i );

kingc8
06-23-2010, 09:48 AM
Ok, I did not have any of that code. However it's still not working, but probably because I don't understand all the parameters correctly.

I wasn't sure what "nParamObj" object was but according to another source I can use "GLint uniform_location" returned from glGetUniformLocationARB();

This is what I currently have based on what you've added:

glUseProgram(glsl_prog);

GLint uniform_location;
uniform_location = glGetUniformLocationARB( glsl_prog, "tex1");
glUniform1iARB( uniform_location, texID);
glActiveTexture(GL_TEXTURE0 + texID);
..
glBindTexture(..

and the convolution vert:

void main() {

gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();

}

finally the convolution frag:

define KERNEL_SIZE 9

uniform sampler2D tex1;

uniform float width;
uniform float height;
uniform float kernel[KERNEL_SIZE];

const float step_w = 1.0/width;
const float step_h = 1.0/height;
const vec2 offset[KERNEL_SIZE] = {
vec2(-step_w, -step_h), vec2(0.0, -step_h), vec2(step_w, -step_h),
vec2(-step_w, 0.0), vec2(0.0, 0.0), vec2(step_w, 0.0),
vec2(-step_w, step_h), vec2(0.0, step_h), vec2(step_w, step_h)
};

void main(void)
{
int i = 0;
vec4 sum = vec4(0.0);

for( i=0; i<KERNEL_SIZE; i++ )
{
vec4 tmp = texture2D(tex1, gl_TexCoord[0].st + offset[i]);
sum += tmp * kernel[i];
sum.a = 1.0;
}

gl_FragColor = sum;
}

-----

What's broken there?

Thanks,

Cameron

sgsrules
06-23-2010, 11:55 AM
You don't need to use the ARB stuff, use glGetUniformLocation and glUniform1i. Everything you have here is correct, and it sounds like your able to load your shaders properly since you could set the fragment colors to purple. but what are you doing after glBindTexture(..
?

are you setting the width and height uniforms? how are you drawing your full screen quad?

see if the shader is running properly by changing your convolution shader output from
gl_FragColor = sum;
to
gl_FragColor = vec4(1.0,0.0,0.0,1.0);

you should get an all blue screen.

kingc8
06-23-2010, 12:12 PM
I guessed the ARB stuff was a little superfluous.

By glBindTexture(.. I meant that next I draw the quad and bind a texture to it and then switch back to the main window buffer:

glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0);

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texID);

glBegin(GL_QUADS);
glColor4f(..);
glTexCoord2f(0.0, 1.0); glVertex2f(..);
glTexCoord2f(1.0, 1.0); glVertex2f(..);
glTexCoord2f(1.0, 0.0); glVertex2f(..);
glTexCoord2f(0.0, 0.0); glVertex2f(..);
glEnd();

glBindFramebuffer(GL_FRAMEBUFFER, 0); // drawing returned to the window.

kingc8
06-23-2010, 12:14 PM
And the change to the fragment shader made all the textures red (which was the right color for what you suggested! (1.0, 0.0, 0.0))

kingc8
06-23-2010, 12:17 PM
I guess this is right that it only made the textures red because I neglected to mention that I bound to the FBO before:

glUseProgram(glsl_prog);

kingc8
06-24-2010, 12:32 AM
To be clear, it's still not working correctly.

sgsrules
06-24-2010, 10:01 AM
Did I mention i was color blind? lol. are you setting your width and height uniforms? Could you post your complete code instead of just fragments? You might have a typo that you're missing and we're not seeing it because you're not posting it :P But from what you've told me your fragment shader is loading properly, and you're drawing your quad properly. Does:



gl_FragColor = texture2D(tex1, gl_TexCoord[0].st);


show you texture?

Dan Bartlett
06-24-2010, 10:22 AM
You seem to be using texID for 2 purposes. In one post you have:


glUniform1iARB( uniform_location, texID);
glActiveTexture(GL_TEXTURE0 + texID);

which is using it as the active texture unit to bind the texture to (should be a number between 0 and the max allowed texture unit), but in another post you have:


glBindTexture(GL_TEXTURE_2D, texID);

Which is reusing the same value as a texture name (ie. as returned by glGenTextures)

kingc8
06-25-2010, 01:08 AM
From sgsrules:

> are you setting your width and height uniforms?

Not explicitly I think. I'll post code to follow up and you can verify that.

gl_FragColor = texture2D(tex1, gl_TexCoord[0].st);

does not show me a texture. :-( In fact the the screen only shows the background color and no textures are drawn.

kingc8
06-25-2010, 01:12 AM
From Dan Barlett:

Are you saying:

glActiveTexture(GL_TEXTURE0 + texID);

Should in fact be:

glActiveTexture(GL_TEXTURE0);

I wasn't sure about what was being sought for that value. But from looking at the Orange book, I think you mean the latter?

kingc8
06-25-2010, 01:31 AM
This is what I have currently, I hope this isn't too terse.




perspective(zoom+90, static_cast<float>(xres/yres), 1.0f, 500.0f);

glViewport(0,0, xres, yres);

if (glsl_active == true) // if GLSL program is set and active, run it.
{
glUseProgram(glsl_prog);
// ul_set = glGetUniformLocation( glsl_prog, "jbtex1")
glUniform1i( ul_set, 0);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texName[base_tex]);
glEnable(GL_TEXTURE_2D);
}

glBindFramebuffer(GL_FRAMEBUFFER, fbo); // output to FBO

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texName[base_tex], 0);

//glClear(GL_COLOR_BUFFER_BIT); // clean up buffer

glLoadIdentity();

draw();
// stuff inside draw (this portion isn't literal. :-) )
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texName[over_lay]);
glBegin(GL_QUADS);
glColor4f(..);
glTexCoord2f(0.0, 1.0); glVertex2f(..);
glTexCoord2f(1.0, 1.0); glVertex2f(..);
glTexCoord2f(1.0, 0.0); glVertex2f(..);
glTexCoord2f(0.0, 0.0); glVertex2f(..);
glEnd();

// and literally again..

glBindFramebuffer(GL_FRAMEBUFFER, 0); // drawing returned to the window.

kingc8
06-25-2010, 01:34 AM
The:

// ul_set = glGetUniformLocation( glsl_prog, "jbtex1")

just indicates that ul_set has been defined elsewhere by the function that also loaded, compiled and linked the shader pair.

GL Starter
06-30-2010, 07:49 AM
glUniform1i( ul_set, 0);

Here setting texture parameters as 0. Need to set texture id to shader.

Please try like this.
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0+ texName[base_tex]);
glUniform1i( ul_set, texName[base_tex]);

This is working in my code.

http://www.codeproject.com/KB/openGL/GLSLShader.aspx

Dark Photon
06-30-2010, 05:43 PM
Please try like this.
glEnable(GL_TEXTURE_2D);
...
FYI, this line is useless when rendering with shaders (and invalid IIRC if you're using a core 3.x profile). It's a directive to the fixed-function pipeline's internal shader generator.

kingc8
07-01-2010, 03:58 AM
FYI, this line is useless when rendering with shaders (and invalid IIRC if you're using a core 3.x profile). It's a directive to the fixed-function pipeline's internal shader generator.

Thanks Dark, yes I have already removed that line with the understanding that the shader "renders" it moot.


Please try like this.

GLStarter, thanks I made those changes but it didn't correct the result.

To recall, I'm running a simple shader which is simply passing the pixel in the texture straight through:



uniform sampler2D jbtex1;

void main()
{
gl_FragColor = texture2D(jbtex1, gl_TexCoord[0].st);
}


I would like to ask, because I think my assumption may perhaps be wrong here but, do I (in the most simple example) only need to load one texture for a shader to process it, or do I need two textures of equal size, one to read from and one to write the result to?

Or perhaps attaching the shader to the FBO which is itself bound to the single texture?

Thanks,

Cameron