croman102's picture

ReadPixels?

What is the right way of using ReadPixels?
I want to get color of certain pixel. Can I get it in (255,0,0)(red) or (1,0,0) format? I have triad several solutions I found here but none of them works here.

Thank you.


Comments

Comment viewing options

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

Yes, you can. What have you tried so far?

For (255, 0, 0) use format: Rgb and type: UnsignedByte
For (1, 0, 0) use format: Rgb and type: Float

The manpage for glReadPixels lists all valid combinations. You can also refer to the OpenGL specification (found under "Documentation/OpenGL 4.4 Specification.pdf" in the OpenTK download.)

croman102's picture

Thank you
What should be the last parameter in that function if I want to use float?
I want to detect above which part of square is mouse hovering over. So I tough it would be a good idea to make that square with gradient texture (2 colors) and than find out where is mouse by color values on that square. After that I would re-draw the square with normal texture (dirt or something).

Thanks

the Fiddler's picture

The last parameter should be a buffer that matches the 'format, 'type', 'width' and 'height' parameters. For instance:

// 1x1 pixel with format: rgb (3 elements) and type: float
var pixel1 = new pixel[3];
GL.ReadPixels(x, y, 1, 1, PixelFormat.Rgb, PixelType.Float, pixel1);
// or
var pixel2 = new Vector3();
GL.ReadPixels(x, y, 1, 1, PixelFormat.Rgb, PixelType.Float, ref pixel2);

For multiple pixels, use an array that is big enough to hold the number of elements. E.g.:

// width x height pixels with format: bgra (4 elements) and type: double
var pixels1 = new double[width * height * 4];
GL.ReadPixels(x, y, width, height, PixelFormat.Bgra, PixelType.Double, pixels1);
// or
var pixels2 = new Vector4d[width * height];
GL.ReadPixels(x, y, width, height, PixelFormat.Bgra, PixelType.Double, pixels2);
croman102's picture

Thank you
I have tried this:

var pcolor = new Vector3();
GL.ReadPixels((int)mouseTo().X, (int)mouseTo().Y, 1, 1, PixelFormat.Rgb, PixelType.Float, ref pcolor);
System.Console.WriteLine(pcolor.X + " " + pcolor.Y + " " + pcolor.Z);

but the output is 0 0 0 . mouseTo function is working good (converting windows mouse position to opengl's).

Thank you

croman102's picture

Any idea why it doesn't work?

the Fiddler's picture

Without more information, it could be anything.

Note that reading from the default framebuffer is subject to many restrictions. Use a FBO if you need reliable results. The OpenGL specification covers this topic in more detail (see Documentation/OpenGL 4.4 Specification.pdf in the OpenTK download.)

A few suggestions:

  1. Check for errors using GL.GetError().
  2. Don't call ReadPixels on a default framebuffer that fails the pixel ownership test. This includes invisible and (partially or fully) covered windows. FBOs are not subject to this restriction.
  3. Don't call ReadPixels right after SwapBuffers. The framebuffer contents will be undefined.
  4. Use GL.ReadBuffer to set the correct readback buffer. Reading from the front buffer is not always possible.
  5. Make sure x and y are indeed what you expect and fall within the GL.Viewport. Try using GL.DrawPixels to verify.
  6. Make sure your rendering is complete. Call GL.Finish() if necessary.
croman102's picture

When I use DrawPixels I get something similar to "no-signal" picture on an old crt tv with analog signal.

var pixel2 = new Vector3();
GL.ReadPixels((int)mouseToField().X, (int)mouseToField().Y, 1, 1, PixelFormat.Rgb, PixelType.Float, ref pixel2);
GL.DrawPixels((int)mouseToField().X, (int)mouseToField().Y, PixelFormat.Rgb, PixelType.UnsignedByte, ref pixel2);

It is the same when I disable readpixels function.

croman102's picture

IT IS SOLVED!!!

this code works:

byte[] pixel2 = new byte[3];
GL.ReadPixels((int)mouseToField().X, (int)mouseToField().Y, 1, 1, PixelFormat.Rgb, PixelType.UnsignedByte, pixel2);
System.Console.WriteLine(pixel2[0] + " " + pixel2[1]+ " " + pixel2[2]);

Thank you Fiddler