LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: Moocow9m on April 25, 2016, 17:34:18

Title: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Moocow9m on April 25, 2016, 17:34:18
I have colored pixel 1,1 with 0.0f 0.0f 1.0f 1.0f (blue) and i got the same response as white. Can someone tell me what I did wrong?
Code:
        GL11.glReadBuffer(GL11.GL_FRONT);
        ByteBuffer rgb = BufferUtils.createByteBuffer(3);
        glReadPixels(X, Y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, rgb);
        System.out.println((rgb.get(0) & 0xFF) + ", " + (rgb.get(1) & 0xFF) + ", " + (rgb.get(2) & 0xFF));
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Kai on April 25, 2016, 19:12:45
Can you show some more of your code, where you render things?
Also keep in mind that when using double-buffering then the GL_BACK buffer is the one being rendered to, before you call glfwSwapBuffers().
Also, are you maybe rendering to a Framebuffer Object?
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Moocow9m on April 25, 2016, 19:18:55
Code: (whole loop beware)

    private void loop() {
        GL.createCapabilities();
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, 600, 600, 0, 1, -1);
        glMatrixMode(GL_MODELVIEW);
        ArrayList<Shape> shapes = new ArrayList<>();
        Shape shape = new Shape();
        Color color = new Color();
        color.setColor(0.0f, 0.0f, 0.0f, 1.0f);
        shape.setShape(7, 20.0f, 15.0f, 100.0f, 100.0f, color);
        shapes.add(shape);
        Points temp;
        square.setUp();
        while (glfwWindowShouldClose(window) == GLFW_FALSE) {
            sync(60);
            frameTrack++;
            glfwPollEvents();
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            glClear(GL_COLOR_BUFFER_BIT);
            switch (togglePage) {
                case "login":
                    drawShape(shapes);
                    if (usernameOn) {
                        glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
                    } else {
                        glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
                    }
                    Username.draw();
                    if (connectError != null) {
                        glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
                        temp = drawString(connectError, 260, 260);
                        temp.draw();
                    }
                    glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
                    login.draw();
                    temp = drawString(username, 260, 300);
                    temp.draw();
                    if (passwordOn) {
                        glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
                    } else {
                        glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
                    }
                    Password.draw();
                    glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
                    String passwordTemp = "";
                    for (int i = 0; i < password.length(); i++) {
                        passwordTemp = passwordTemp + "*";
                    }
                    temp = drawString(passwordTemp, 260, 340);
                    temp.draw();
                    if ((mouseX >= 251 && mouseX <= 350) && mouseY >= 348 && mouseY <= 366) {
                        glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
                    } else {
                        glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
                    }
                    Login.draw();
                    glColor3f(0.0f, 0.0f, 1.0f);
                    GL11.glBegin(GL11.GL_POINTS);
                    GL11.glVertex2f(1, 1);
                    GL11.glEnd();
                    new boardCreate().read(1, 1);
                    break;
                case "conectionInfo":
                    if ((mouseX >= 251 && mouseX <= 350) && mouseY >= 348 && mouseY <= 366) {
                        glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
                    } else {
                        glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
                    }
                    Login.draw();
                    glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
                    conectionInfo.draw();

                    if (hostOn) {
                        glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
                    } else {
                        glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
                    }
                    Username.draw();
                    glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
                    temp = drawString(host, 260, 300);
                    temp.draw();
                    if (portOn) {
                        glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
                    } else {
                        glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
                    }
                    Password.draw();
                    temp = drawString(Port + "", 260, 340);
                    temp.draw();
                    break;
                default:
                    glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
                    square.draw();
                    break;
            }
            glfwSwapBuffers(window);
            new boardCreate().read(1, 1);
        }
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Kai on April 25, 2016, 19:21:17
And when/where do you make the glReadPixels call there? I mean it's clearly your glClearColor which you read.
Also beware that glReadPixels takes "window coordinates". They have their Y axis point downwards.
So the y co-ordinate 0 is at the top of the window.
<-- wrong. See further post.
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Moocow9m on April 25, 2016, 19:25:14
 new boardCreate().read(1, 1);
And I know about the 0,0 being in the top corner. The whole thing is a 600x600 window.
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Kai on April 25, 2016, 19:27:59
Okay, that looks about right then. The only thing I can think of now is that the pixel (1, 1) (the second pixel along +X and the second along +Y) does not contain that color, but the clearcolor. Are you absolutely sure that your rendered output at pixel (1, 1) is not the clear color (white)? Can you maybe post an image of the render result?
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Moocow9m on April 25, 2016, 19:32:58
glColor3f(0.0f, 0.0f, 1.0f);
                    GL11.glBegin(GL11.GL_POINTS);
                    GL11.glVertex2f(1, 1);
                    GL11.glEnd();
In code and I will send a pic in ~8min.
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Kai on April 25, 2016, 19:41:29
Okay, I was wrong. Window coordinates in OpenGL have their origin at the bottom-left...
So you could either switch the top and bottom arguments of glOrtho or use glReadPixels(1, height-2, ...)
Also noted here: https://www.opengl.org/sdk/docs/man/html/glReadPixels.xhtml
Quotex, y
Specify the window coordinates of the first pixel that is read from the frame buffer. This location is the lower left corner of a rectangular block of pixels.
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Moocow9m on April 25, 2016, 19:43:41
Here (I cropped it to make it easier to see)
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Moocow9m on April 25, 2016, 19:45:24
Quote from: Kai on April 25, 2016, 19:41:29
Okay, I was wrong. Window coordinates in OpenGL have their origin at the bottom-left...
So you could either switch the top and bottom arguments of glOrtho or use glReadPixels(1, height-2, ...)
Also noted here: https://www.opengl.org/sdk/docs/man/html/glReadPixels.xhtml
Quotex, y
Specify the window coordinates of the first pixel that is read from the frame buffer. This location is the lower left corner of a rectangular block of pixels.
The project relies on 0,0 being top-Left though... And it works...
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Kai on April 25, 2016, 19:46:43
Quote from: Moocow9m on April 25, 2016, 19:45:24
The project relies on 0,0 being top-Left though...
Quote from: Kai on April 25, 2016, 19:41:29
or use glReadPixels(1, height-2, ...)

This is also possible, if supported by your driver: https://www.opengl.org/registry/specs/ARB/clip_control.txt
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Moocow9m on April 25, 2016, 19:52:45
Quote from: Kai on April 25, 2016, 19:46:43
Quote from: Moocow9m on April 25, 2016, 19:45:24
The project relies on 0,0 being top-Left though...
Quote from: Kai on April 25, 2016, 19:41:29
or use glReadPixels(1, height-2, ...)

This is also possible, if supported by your driver: https://www.opengl.org/registry/specs/ARB/clip_control.txt
glReadPixels(X, Y - 2, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, rgb); gave 0,0,0...
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Kai on April 25, 2016, 19:53:54
Quote from: Moocow9m on April 25, 2016, 19:52:45
glReadPixels(X, Y - 2, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, rgb); gave 0,0,0...
Not Y - 2 .... height-2, where height is the height in pixels of your viewport.

Generally: your glReadPixels(X, Y, ...) becomes: glReadPixels(X, height-Y-1, ...)
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Moocow9m on April 25, 2016, 19:59:57
Quote from: Kai on April 25, 2016, 19:53:54
Quote from: Moocow9m on April 25, 2016, 19:52:45
glReadPixels(X, Y - 2, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, rgb); gave 0,0,0...
Not Y - 2 .... height-2, where height is the height in pixels of your viewport.

Generally: your glReadPixels(X, Y, ...) becomes: glReadPixels(X, height-Y-1, ...)
height-Y-1 == 1-1-1.... They all equal 1 in this situation and -3 is not displayed....
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Kai on April 25, 2016, 20:02:21
Quote from: Moocow9m on April 25, 2016, 19:59:57
height-Y-1 == 1-1-1....
No. "height" is the height of your viewport/render area. Your window is NOT 1 pixel in height. According to your code it is 600 Pixels.
So please understand that glReadPixels(1, 1, ...) translates to glReadPixels(1, height-1-1, ...) = glReadPixels(1, height-2) = glReadPixels(1, 600-2,...) = glReadPixels(1, 598, ...)
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Moocow9m on April 25, 2016, 20:05:34
Ok. Now returning 255,255,255 again though... glReadPixels(X, 600-Y-1, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, rgb);
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Kai on April 25, 2016, 20:16:57
I see. The general problem here is that rasterizing a point at (1, 1) does not lead to the pixel (1, height-2) being rendered to, due to OpenGL's point rasterization rules. Rendering (1, 1) will fill pixel (1, height-1).
And likewise (0, 0) does not fill pixel (0, height-1), but no pixel at all.
This is because (0, 0) does not denote the top-left pixel but rather the top-left corner of the viewport, which is the top-left corner of the top-left pixel. It is NOT the CENTER of the pixel.
If you want to make absolutely sure that the pixel is hit when rasterizing a point with GL_POINTS, then you must use glVertex2f(0.5f, 0.5f) or in your case glVertex2f(1.5f, 1.5f), that is, add a 0.5f offset to the position, which is just the half-size of a pixel. The former would hit pixel (0, height-1) and the latter would hit pixel (1, height-2)

(I just tested it with a demo program myself):

import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.*;
import java.nio.ByteBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.opengl.GL;
public class ForumDemo {
    public static void main(String[] args) {
        int width = 600;
        int height = 600;
        glfwInit();
        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
        long window = glfwCreateWindow(width, height, "", NULL, NULL);
        GLFWKeyCallback keyCallback;
        glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() {
            public void invoke(long window, int key, int scancode, int action, int mods) {
                if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE)
                    glfwSetWindowShouldClose(window, true);
            }
        });
        glfwMakeContextCurrent(window);
        GL.createCapabilities();
        glClearColor(1, 1, 1, 1);
        while (!glfwWindowShouldClose(window)) {
            glClear(GL_COLOR_BUFFER_BIT);
            glViewport(0, 0, width, height);
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            glOrtho(0, width, height, 0, -1, +1);
            glColor3f(0.0f, 0.0f, 1.0f);
            glBegin(GL_POINTS);
            glVertex2f(1.5f, 1.5f); // <- make sure pixel (1, height-1-1) is rendered to
            glEnd();
            glfwSwapBuffers(window);
            glReadBuffer(GL_FRONT);
            ByteBuffer rgb = BufferUtils.createByteBuffer(3);
            glReadPixels(1, height-1-1, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, rgb);
            System.out.println((rgb.get(0) & 0xFF) + ", " + (rgb.get(1) & 0xFF) + ", " + (rgb.get(2) & 0xFF));
            glfwPollEvents();
        }
    }
}
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Moocow9m on April 25, 2016, 20:26:07
Just to make sure, add .5 to all points if I want to read them?
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Kai on April 25, 2016, 20:37:49
Quote from: Moocow9m on April 25, 2016, 20:26:07
Just to make sure, add .5 to all points if I want to read them?
Yes, but I would rather do the translation as part of the projection matrix. You can do the following right after glOrtho():
glTranslatef(0.5f, 0.5f, 0);
Since you are setting up a pixel-perfect projection anyway, this will not hurt.
Afterwards, when you glVertex2f(x, y) with integer coordinates then this will correctly hit the corresponding pixel.
So: no need to add a 0.5f offset to each vertex.
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Moocow9m on April 25, 2016, 20:45:14
Quote from: Kai on April 25, 2016, 20:37:49
Quote from: Moocow9m on April 25, 2016, 20:26:07
Just to make sure, add .5 to all points if I want to read them?
Yes, but I would rather do the translation as part of the projection matrix. You can do the following right after glOrtho():
glTranslatef(0.5f, 0.5f, 0);
Since you are setting up a pixel-perfect projection anyway, this will not hurt.
Afterwards, when you glVertex2f(x, y) with integer coordinates then this will correctly hit the corresponding pixel.
So: no need to add a 0.5f offset to each vertex.
So not in the while loop?
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Kai on April 25, 2016, 20:46:57
Correct. :) Not in the while loop. Just once directly after glOrtho().
Title: Re: LWJGL 3 glReadPixles always reports 255 255 255 255
Post by: Moocow9m on April 25, 2016, 21:04:48
Thanks I will try when I get home in ~2 hours.