I’m using OpenGL to do some calculations: summing grayscale textures together. Typically dozens of textures are rendered on top of each other and the output is/should be the “sum” of those textures.
The method I am using now is:
clear Accum buffer
for texNum = 1 to N.
Clear frame buffer;
Render texture <texNum>;
glAccum(GL_ACCUM) to accum buffer; // Adds frame buffer to accum buffer.
end for;
// end result is in accum buffer now.
This is painfully slow, as you would expect.
What I would like to do is to render the textures on top of each other while calculating the sum. Much like in alpha blending except that I don’t calculate the “average” or whatever of each pixel but sum the pixels up instead.
Would it possible to do this with a pixel/fragment shader?
Correct me if I’m astray here, but to my knowledge, in OpenGL it is NOT possible to:
Read frame buffer pixels from a fragment shader.
Write to a buffer that is bound to a texture. (pbuffer usage).
Do I have to switch to D3D ( shivers … ? ) I doubt it’s possible with Direct3D either.
Intuitively, the algorithm is pretty straightforward:
frame buffer pixel value += texel value rendered;
Essentially the algorithm needs to read to and write from the same buffer using a fragment shader… is it possible?
The ps2.0 spec hints that I should be able to at least write to two outputs, I wonder if that would help any.
I don’t know if it is very fast, but you can use texenv with GL_ADD, if support multitexturing
for each texture
{
//Save pbuffer to texture0 unit
glActiveTextureARB(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
glBindTexture(GL_TEXTURE_2D,tex);
glCopyTexImage2D(…);
glEnable(GL_TEXTURE_2D);
//clear pbuffer
glClear(GL_COLOR_BUFFER_BIT);
//Load and enable the texture to add
glActiveTextureARB(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_ADD);
glBindTexture(GL_TEXTURE_2D,yourTexture);
glEnable(GL_TEXTURE_2D);
//Draw a quad
DrawQuad(…);
//Disable texturing
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0_ARB);
glDisable(GL_TEXTURE_2D);
}
At the end, you have the sum of the textures in the frame buffer (there may be also a problem of saturation)
[This message has been edited by Acheum (edited 06-18-2003).]
What part don’t you understand? The idea is very simple, you have two floating point textures. On every pass/draw call you use one bound as a texture and the other bound as a render target. After each pass you swap them. Here’s how it would work for accumulating two pixels in a single texel texture.
Clear both textures to 0.
Bind texture 0 as texture.
Bind texture 1 as render target.
Render sum of pixel one and texture 0
Bind texture 1 as texture.
Bind texture 0 as render target.
Render sum of pixel 2 and texture 1.
Doing this you will end up with pixel1+pixle2 in texture 1. The more general post is in my post above.
Then again, if MSDN’s OpenGL reference is outdated, could you point me to a more recent one ? I’ve been using the MSDN library for online reference so far…
One easy way to implement the ping pong is to use the front and back buffers of a double-buffered pbuffer, and use swapbuffers to perform the switch. I guess this is pretty obvious.
This would only work if SwapBuffers doesn’t copy.
If you use render to texture on a pbuffer you must release the texture before you can paint on it again. Means there’s no additional overhead binding it to either of the two buffers anyway.