PDA

View Full Version : Framebuffer, logical operation, bit setting



fabien MATHIEU
05-31-2011, 02:40 AM
Hello,

I am currently trying to do a 3D rasterization. To perform that, I have a framebuffer object in which I write the result. The attachment of this framebuffer object is an 2D integer texture(GL_RGBA32UI to be exact). For this framebuffer, I enable the logical operation OR.

My glsl program computes for each fragment its depth and compute the channel and a mask in order to set the matching bit to 1. To sum up, I set a bit to 1 if a 3D pixel, or voxel, is present at the corresponding depth,normalized between 0 and 128, and at the coordinates x and y of the fragment.

My problem is that when two voxels are in the same channel, the logical operation seems to not working, and I get value which not match with I expect. If two voxels are in different channel, everythings work fine. I suspect that the logical operation is performed on the floating representation of my "colors", which lead to crazy values.

If that can help, there is my glsl frament code(vertex and geometry are standard ones) :

#version 330 compatibility

#extension GL_EXT_gpu_shader4 : enable

void main()
{
uint channel_number; // r or g or b or a
uint shift; // to shift the bit of the mask

num_image = 0x00000000u;
num_channel = uint(gl_FragCoord.z * 127u) / 32u;
bit_a_setter = uint(gl_FragCoord.z * 127u) % 32u;

uint mask = 0x00000001u << shift; // mask creation by bit shifting

uvec4 finalColor = uvec4(0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u);
finalColor[num_channel] = mask; // channel affectation

// The logical operation "or" is enabled. So, OpenGl will perform the operation between two overlaid fragments
gl_FragData[0] = finalColor;
}

Sorry, for the "old school" aspect of the glsl fragment program, I develop this only as part of tests.

Thanks,

Fabien MATHIEU

Ludovic Silvestre
06-01-2011, 01:28 AM
Hi Fabien,

Just to be sure, the logical operation OR on your framebuffer is basically a blending function using the MAX mode, right? If that's the case, you can't blend a color buffer with an integer format:

OpenGL 3.3 Core Spec - 4.1.7 Blending
Blending applies only if the color buffer has a &amp;#64257;xed-point or &amp;#64258;oating-point format. If the color buffer has an integer format, proceed to the next operation.

Ludovic

fabien MATHIEU
06-01-2011, 02:07 AM
Hi,

I am not sure to understand what you are saying that logical operation OR is a blending function using the MAX mode. The only accepted constants are the ones on this page : http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunc.xml

I use the logical operation because I only want to do a bitwise operation between two overlapping fragmenst and store the result in my texture. Moreover, how could we be sure that both functions have the same entries(intergers, fix point values or floating point values).

Moreover I found this part of the spec is weird(for my case)


OpenGL 3.3 Core Spec - 4.1.10 Logical Operation
Logical operation has no effect on a &amp;#64258;oating-point destination color buffer.
However, if logical operation is enabled, blending is still disabled.




However, if the logical operation "OR" is really assimilated is the same as a blending function, I have a little problem. Maybe I will try to work with floating texture ...

Thanks

Fabien

Ludovic Silvestre
06-01-2011, 04:56 AM
The MAX mode is to specify the blending equation, not the blending function.

I didn't know about the logical operation, as I only used blending functions, but they seem to be quite similar. In fact, the effect is the same, they mix a source color and a destination color.


Maybe I will try to work with floating texture ...
If the part of the spec you just showed is correct, I'm afraid it won't work with logical operations.

There doesn't seem to be any problem with your shader code, can you show us the log of OpenGL calls? Does your framebuffer only have that attachment? It could also be a VL bug (in that case, we should continue this topic in VL's forum).

Ludovic

fabien MATHIEU
06-01-2011, 05:50 AM
Ok, I understand better the MAX mode. However, shouldn't that be the ADD mode? Indeed, in my case, I have only one bit set per color.

ex : 4 | 2 <=> 4 + 2 = 6

Concerning the floating texture, you're right, I get exactly the same result.

I tried to change the logical operation with a blending operation. The factor is GL_ONE for both source and destination and the equation is GL_ADD. This time, I obtain a different result, but nor the good one. Before, I obtain the farthest pixel, now I obtain the nearest one.

My framebuffer have only one attachement for the moment, but later, I will probably attach more to increase the resolution of my 3D grid.

Concerninf the log of OpenGL calls, I have generated one with gDebugger, but it is pretty huge(~10Mo). Have you idea of how I can provide one with efficient way?

Thanks for your help

Fabien

fabien MATHIEU
06-01-2011, 07:03 AM
For people that interest, I am trying to do that : http://www.irit.fr/~Loic.Barthe/Publications/JGT2009_Forest_et_al.pdf

Ludovic Silvestre
06-01-2011, 07:42 AM
ex : 4 | 2 <=> 4 + 2 = 6
This is wrong, for example: 3 | 1 != 3 + 1 = 4.

The gDebugger log is an HTML page with reference to images (probably those 10Mb), so you can either copy the HTML text (without images) or just copy and paste the lines for the framebuffer creation and for the render state preparation (glEnable's, glBlend* and glLogicOp).

Ludovic

fabien MATHIEU
06-01-2011, 08:36 AM
I totally agree with your example. However, I am sure in my fragment program I will create a mask with only one bit set to 1.
So, if I do an addition or logical operation or, I got the same result. It's weird, but that work(on the paper). Of course, I would prefer doing logical OR on my values.

Concerning the log, it is attached to the current post. I tried to target the pertinent calls. I put the calls from the binding of the frambuffer to the unbinding. If you need more, don't hesitate to ask.