PDA

View Full Version : Odd FBO behavior w.r.t. texturing in shaders



tzlaine
01-07-2010, 02:10 PM
I'm having a problem using texturing in fragment shaders while rendering to an FBO.

The library I'm working on does all of its rendering to FBOs, so I know the FBO rendering is working in all cases except when shaders are using texturing. Shaders that use no texturing also work fine. The problem with texturing is that I get a vec4(0.0) back, no matter what. I've verified that the texture I'm using is populated correctly (and contains no all-zero texels).

Here are the vertex shader:

void main ()
{ gl_Position = ftransform(); }


the fragment shader:

uniform sampler1D tex;
uniform mat4 matrix;
uniform vec2 circle_1;
uniform float radius_0;
uniform float radius_1;

void main ()
{
vec2 pos = (matrix * vec4 (gl_FragCoord.xy, 0.0, 1.0)).xy;

float dr = radius_1 - radius_0;
float dot_circle_1 = dot (circle_1, circle_1);
float dot_pos_circle_1 = dot (pos, circle_1);

float A = dot_circle_1 - dr * dr;
float B = -2.0 * (dot_pos_circle_1 + radius_0 * dr);
float C = dot (pos, pos) - radius_0 * radius_0;
float det = B * B - 4.0 * A * C;
det = max (det, 0.0);

float sqrt_det = sqrt (det);
/* This complicated bit of logic acts as
* "if (A < 0.0) sqrt_det = -sqrt_det", without the branch.
*/
sqrt_det *= 1.0 + 2.0 * sign (min (A, 0.0));

float t = (-B + sqrt_det) / (2.0 * A);
gl_FragColor = texture1D (tex, t);
}


and the code (boiled down from a Bugle trace):


GLuint tex1, tex2, tex3;
GLuint fb1;
GLint max_texture_size;
GLuint vert_shader, frag_shader, program;
GLint status, loc;
unsigned int pixels[600 * 350];

const GLchar* vert_text[] = { /*...*/ };
const GLchar* frag_text[] = { /*...*/ };

float matrix[16] = {
0, -52.7967, 0, 9239.42,
-90.5086, 0, 0, 27152.6,
0, 0, 1, 0,
0, 0, 0, 1
};
GLint vertices[8] = {
0, 0,
0, 350,
600, 350,
600, 0
};

glGenTextures(1, &amp;tex1);
glBindTexture(GL_TEXTURE_2D, tex1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &amp;max_texture_size);
glGenTextures(1, &amp;tex2);
glBindTexture(GL_TEXTURE_2D, tex2);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 600, 350, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glGenFramebuffersEXT(1, &amp;fb1);
glBindFramebufferEXT(GL_FRAMEBUFFER, fb1);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2, 0);
glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
glBindFramebufferEXT(GL_FRAMEBUFFER, fb1);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glViewport(0, 0, 600, 350);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 600, 0, 350, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
vert_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vert_shader, 1, vert_text, NULL);
glCompileShader(vert_shader);
glGetShaderiv(vert_shader, GL_COMPILE_STATUS, &amp;status);
frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(frag_shader, 1, frag_text, NULL);
glCompileShader(frag_shader);
glGetShaderiv(frag_shader, GL_COMPILE_STATUS, &amp;status);
program = glCreateProgram();
glAttachShader(program, vert_shader);
glAttachShader(program, frag_shader);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &amp;status);
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
glBindFramebufferEXT(GL_FRAMEBUFFER, fb1);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glViewport(0, 0, 600, 350);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 600, 0, 350, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glClientActiveTexture(GL_TEXTURE0);
glGenTextures(1, &amp;tex3);
glBindTexture(GL_TEXTURE_1D, tex3);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA8, 8192, 0, GL_RGBA, GL_UNSIGNED_BYTE, gradient_data);
glUseProgram(program);
loc = glGetUniformLocation(3, "tex");
glUniform1i(loc, 0);
loc = glGetUniformLocation(3, "matrix");
glUniformMatrix4fv(loc, 1, GL_TRUE, matrix);
loc = glGetUniformLocation(3, "circle_1");
glUniform2f(loc, 0, 0);
loc = glGetUniformLocation(3, "radius_0");
glUniform1f(loc, 0);
loc = glGetUniformLocation(3, "radius_1");
glUniform1f(loc, 16384);
glVertexPointer(2, GL_INT, 0, vertices);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_QUADS, 0, 4);
glUseProgram(0);
glDeleteTextures(1, &amp;tex3);
glPopClientAttrib();
glPopAttrib();
glBindFramebufferEXT(GL_FRAMEBUFFER, fb1);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glViewport(0, 0, 600, 350);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 600, 0, 350, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ROW_LENGTH, 600);
glReadPixels(0, 0, 600, 350, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &amp;pixels);
glGetError();
glDeleteFramebuffersEXT(1, &amp;fb1);
glDeleteTextures(1, &amp;tex2);
glDeleteTextures(1, &amp;tex1);
glDeleteShader(vert_shader);
glDeleteShader(frag_shader);
glDeleteProgram(program);
glDeleteShader(0);
glDeleteShader(0);
glDeleteProgram(0);


I know there are some extraneous calls, and I've tried to remove as much code as possible, but nothing seems to fix the all-zeros texturing problem. If I replace the last line of the fragment shader with "gl_FragColor = vec3(t, t, t, 1.0);", I get a radial gradient, dark in the center and white at the edges -- just as I expect. But when I use "t" to look up a texel, I get vec4(0.0), as I said before.

Also, while investigating this issue, I built another small test app that uses texturing in a fragment shader while rendering to an FBO with no problems, so I don't suspect a system config issue.

Any Ideas? I'm stumped.

Thanks in advance.

tzlaine
01-08-2010, 03:24 PM
Fixed. I wasn't setting the min/mag filters. Setting them not to use mipmap levels fixed the problem.