sjoerd222's picture

ColorPicking: draw position specifc color. Then read back, but something is not 100% good

Hi

I'm drawing points inside a square. Coordinates range from -0.5 to 0.5. The color of the points depend on his position.
Fragment shader does this:
gl_FragColor = vec4(v_position.x+0.5, v_position.y+0.5, v_position.z+0.5, 1.0);

After rendering in backbuffer I read the buffer:

 byte[] pixel = new byte[4];
GL.ReadPixels(x, _glControl.Height - y, 1, 1, PixelFormat.Rgba, PixelType.UnsignedByte, pixel);
Vector4 point = new Vector4();
point.X = (((float)pixel[0])/255)-0.5f;
point.Y = (((float)pixel[1])/255)-0.5f;
point.Z = (((float)pixel[2])/255)-0.5f;

I want to get back the exact position of the point I clicked on.

The output is correct for position values like 0.1 and 0.2.
But for coordinate 0.15 I get 0.1509804. For 0.03 I get 03333334.

So the precision of this method is not very precies. Does anyone have an idea why this is the case? PixelFormat ? PixelType?

I expect the color on the buffer to be exactly what I specified in the shader. And I expect to read out the exact color from the buffer.
This should be possible I think. Or is OpenGL not precise enough with colors?

thx

regards,
sjoerd222


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture
Quote:

I expect the color on the buffer to be exactly what I specified in the shader. And I expect to read out the exact color from the buffer.
This should be possible I think. Or is OpenGL not precise enough with colors?

You are likely using a 32bit backbuffer that gives 8bits per color channel, i.e. 256 levels per color.

for (int i = 0; i < 256; i++)
    Console.WriteLine(((float)i) / 255);

That's the different levels you can represent, translated to floating-point values.

If you need higher precision, try rendering to a 16bpp or 32bpp floating-point texture (that 16bpp or 32bpp per channel).

Also note that floating-point numbers are not exact (Why Floating-Point Numbers May Lose Precision). You'll generally want to use range-tests instead of plain equality when working with floating-point numbers.

sjoerd222's picture

Ok. Thx for the explanation.
I will use the color index method instead.