question about color composing using GLSL

hello everyone,

i’m writing a shader program that composes several colors.

to be more clear, i’m rendering several things with different colors and these things can be overlapping on the screen, i want to apply a weighted average on their colors if they are overlapping.

what i want to do is to generate fragments during the fragment shader containing the color (the colors are added up by the blending function later) and the weight (the weights are also added up by the blending function) in the alpha channel.

and during the next pass i divide the color with the weight to have the final color.

the equation looks like this:

(weight1color1+weight2color2+…)/(weight1+weight2+weight3…)

my question is, how to store the output of the pass 1, because the color may be saturated if my fragment buffer supports only 8 bit for each color channel.

is there a way to format the fragment buffer, such that each color channel is a 32 float?

or should i save the result on a texture map and access it during the next pass?

thanks.

You should use rgba16f or rgba32f texture in FBO and disable color clamping. In that case fragment output will not be clamped.
Fragment output is always 32bit float, but depending on target surface type result can be saturated and reduced to specific number of bits.

thank you.

i saw your old thread about rgba32f texture map.

the problem is, when i used readpixels to read back the data,

i got GL_INVALID_OPERATION error

this is how i did it:

the texture map is GL_RGBA32F

glReadPixels( 0,0,50,50, GL_RGBA, GL_FLOAT, data);

i’m using the qt opengl library. that library doesn’t allow me to set the data type of the texture map.

i’m wondering what if i mix the use of GL_RGBA32F and GL_UNSIGNED_SHORT, what’s gonna happen. could this be the problem?

can i find an example code somewhere?

thank you so much.

after further test,

i realized that if i use fbo, the glreadpixels fails.

if i read from the frame buffer. it works.

i used these three functions to turn off color clamping:

glClampColorARB( GL_CLAMP_VERTEX_COLOR_ARB  , GL_FALSE );

glClampColorARB( GL_CLAMP_FRAGMENT_COLOR_ARB, GL_FALSE );
glClampColorARB( GL_CLAMP_READ_COLOR_ARB , GL_FALSE );

the clamping is off. but the color is scaled to the [0,1] range.

like you said “but depending on target surface type result can be saturated and reduced to specific number of bits.”

the clamping is off. but the color is scaled to the [0,1] range.

Of course it is. The default framebuffer is not, and cannot be floating-point.

OpenGL defines several circumstances under which glReadPixels will cause a GL_INVALID_OPERATION error.

So, first question: are you binding the FBO to the GL_DRAW_FRAMEBUFFER, or just GL_FRAMEBUFFER? If it’s the latter, you need to bind it to GL_READ_FRAMEBUFFER in order to get reading.

Second question: what is the glReadBuffer set to? You need to make sure it is set to the proper attachment point.

Third question: assuming the above are fine, is the attachment actually a floating-point texture or renderbuffer?

Fourth question: is the FBO framebuffer complete?

thank you very much for your reply.
but i can’t make this thing right.
please help:

this is my current code:

GLuint fbo;
glGenFramebuffers(1, &fbo);

glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);

GLuint depthbuffer;
glGenRenderbuffers(1, &depthbuffer);

glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);

glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, rect().width(),rect().height());

glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuffer);

GLuint img;
glGenTextures(1, &img);
glBindTexture(GL_TEXTURE_2D, img);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, rect().width(),rect().height(), 0, GL_RGBA, GL_FLOAT, NULL);

glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, img, 0);

// GL_INVALID_ENUM
GLenum kkkk = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);

…draw stuff here

glReadBuffer(GL_COLOR_ATTACHMENT0);

GLfloat *data=new GLfloat[4*rect().width()*rect().height()];

glReadPixels(	0,0,rect().width(),rect().height(),                    GL_RGBA,                     GL_FLOAT, data);

i got a GL_FRAMEBUFFER_UNSUPPORTED error when i checked the status.

i know this is caused by incorrect image format.

but the reason i want to do this is to use the GL_RGBA32F format.

can you help me ? thank you so much.

i got a GL_FRAMEBUFFER_UNSUPPORTED error when i checked the status.

i know this is caused by incorrect image format.

And what happens if you don’t bind a depth buffer to the FBO?

Also, try setting the GL_TEXTURE_MIN_FILTER to GL_LINEAR or GL_NEAREST. Or set the available mipmap levels (GL_TEXTURE_BASE_LEVEL and GL_TEXTURE_MAX_LEVEL).

…draw stuff here

The framebuffer that gets rendered to is the GL_DRAW_FRAMEBUFFER. The one you read from is the GL_READ_FRAMEBUFFER. So before you draw with this FBO, it needs to be bound to the the GL_DRAW_FRAMEBUFFER.

thank you so much for your reply. i will try to make some modification.

but i don’t fully understand GL_READ_FRAMEBUFFER and GL_DRAW_FRAMEBUFFER

i don’t know which to bind now.

bind to draw buffer and read from the read buffer?

thank you so much. i will let you know if things work.

but i don’t fully understand GL_READ_FRAMEBUFFER and GL_DRAW_FRAMEBUFFER

i don’t know which to bind now.

You want to render to the framebuffer, so you bind to the draw framebuffer. You want to read from the framebuffer, so you bind to the read framebuffer.

There’s nothing that says you can’t bind to both. In fact, there’s even a token for it: GL_FRAMEBUFFER. Binding to that binds the FBO to both the draw and the read.

thank you.

i have solved the incompleteness problem. the reason was that i didn’t set up the texture parameters.

because the only tutorial i found didn’t do that either

http://www.gamedev.net/reference/articles/article2331.asp

but i’m still confused at framebuffer, read framebuffer, and draw framebuffer.

the thing i want to do is drawing something on some buffer. and read it back. but i need the gl_RGBA32F format. i have tried the framebuffer, which worked, only the color is clamped to [0,1].

but i’m not sure about the read buffer and the draw buffer. i will try to search some documents.

i’m sorry to bother you with my newbie questions. but there are not too many documents online.

oh, i see, so you meant that i bind to draw buffer first, and draw and bind to read_buffer before read?

like this?

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);

draw something…

glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);

read back here???

cause i thought read buffer and draw buffer are two different buffers. like two different memory spaces. so if i draw on the draw buffer, i must read the draw buffer.

thank god! i have solved everything.

thank you so much for your kind replies.

guess what, i saw (2.000,0.0,0.0) read back from the buffer. that is exactly what i want.

thank you again.

i will diffidently write a tutorial somewhere to help save people’s time.

thank you.