Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 8 of 8

Thread: Encoding id picking into a 16b red component texture

  1. #1
    Intern Contributor
    Join Date
    Dec 2011
    Posts
    59

    Encoding id picking into a 16b red component texture

    So, I am trying to perform picking through id, that is before each drawArray a specific uniform variable will be set and written in the red component

    IDs are signed short

    But this is not working, and I don't know why

    Code :
    private void initRenderingTargets(GL3 gl3, int width, int height) {
     
            textures = new int[2];
            fbo = new int[1];
     
            gl3.glGenTextures(2, textures, 0);
            gl3.glGenFramebuffers(1, fbo, 0);
            /**
             * Depth.
             */
            gl3.glBindTexture(GL3.GL_TEXTURE_RECTANGLE, textures[depth]);
     
            gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_WRAP_S, GL3.GL_CLAMP_TO_EDGE);
            gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_WRAP_T, GL3.GL_CLAMP_TO_EDGE);
            gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_MIN_FILTER, GL3.GL_NEAREST);
            gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_MAG_FILTER, GL3.GL_NEAREST);
     
            gl3.glTexImage2D(GL3.GL_TEXTURE_RECTANGLE, 0, GL3.GL_DEPTH_COMPONENT32F, width, height, 0, GL3.GL_DEPTH_COMPONENT, GL3.GL_FLOAT, null);
            /**
             * IDs.
             */
            gl3.glBindTexture(GL3.GL_TEXTURE_RECTANGLE, textures[id]);
     
            gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_WRAP_S, GL3.GL_CLAMP_TO_EDGE);
            gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_WRAP_T, GL3.GL_CLAMP_TO_EDGE);
            gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_MIN_FILTER, GL3.GL_NEAREST);
            gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_MAG_FILTER, GL3.GL_NEAREST);
     
            gl3.glTexImage2D(GL3.GL_TEXTURE_RECTANGLE, 0, GL3.GL_R16I, width, height, 0, GL3.GL_RED_INTEGER, GL3.GL_SHORT, null);
            /**
             * FBO.
             */
            gl3.glBindFramebuffer(GL3.GL_FRAMEBUFFER, fbo[0]);
            gl3.glFramebufferTexture2D(GL3.GL_FRAMEBUFFER, GL3.GL_DEPTH_ATTACHMENT, GL3.GL_TEXTURE_RECTANGLE, textures[depth], 0);
            gl3.glFramebufferTexture2D(GL3.GL_FRAMEBUFFER, GL3.GL_COLOR_ATTACHMENT0, GL3.GL_TEXTURE_RECTANGLE, textures[id], 0);
     
            gl3.glBindFramebuffer(GL3.GL_FRAMEBUFFER, 0);
        }
     
     public void pick(GL3 gl3) {
            System.out.println("pick");
     
            gl3.glBindFramebuffer(GL3.GL_FRAMEBUFFER, fbo[0]);
            Vec4 clear = EC_GUI.main.getGlViewer().getClearColor();
            gl3.glClearColor(clear.x, clear.y, clear.z, clear.w);
            gl3.glClear(GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT);
            gl3.glDrawBuffer(GL3.GL_COLOR_ATTACHMENT0);
            {
                pickModel.bind(gl3);
                {
                    for (EC_Mesh mesh : EC_GUI.main.getList().getMeshes()) {
                        System.out.println("id " + mesh.getId());
                        gl3.glUniform1i(pickModel.getIdUL(), (int) mesh.getId());
    //                    gl3.glUniform1i(pickModel.getIdUL(), 1);
     
                        mesh.render(gl3);
                    }
                }
                pickModel.unbind(gl3);
            }
            gl3.glBindFramebuffer(GL3.GL_FRAMEBUFFER, 0);
        }
     
        public void read(GL3 gl3) {
     
            gl3.glBindFramebuffer(GL3.GL_FRAMEBUFFER, fbo[0]);
            {
                gl3.glReadBuffer(GL3.GL_COLOR_ATTACHMENT0);
     
                FloatBuffer pixel = FloatBuffer.allocate(4);
                ShortBuffer p = ShortBuffer.allocate(2);
                Vec2i point = EC_GUI.main.getGlViewer().getViewPole().getStartingPoint();
     
                gl3.glReadPixels(point.x, point.y, 1, 1, GL3.GL_RED_INTEGER, GL3.GL_SHORT, p);
     
                System.out.println("pixel id "+p.get(0));
                System.out.println("pixel id "+(short)p.get(0));
            }
            gl3.glBindFramebuffer(GL3.GL_FRAMEBUFFER, 0);
        }

    Important lines

    gl3.glTexImage2D(GL3.GL_TEXTURE_RECTANGLE, 0, GL3.GL_R16I, width, height, 0, GL3.GL_RED_INTEGER, GL3.GL_SHORT, null);

    and

    gl3.glReadPixels(point.x, point.y, 1, 1, GL3.GL_RED_INTEGER, GL3.GL_SHORT, p);



    VS:

    Code :
    #version 330
     
    layout (location = 0) in vec3 position;
     
    uniform mat4 modelToWorldMatrix;
     
    layout(std140) uniform GlobalMatrices {
        mat4 worldToCameraMatrix;
        mat4 cameraToClipMatrix;
    };
     
    void main() {
     
        gl_Position = cameraToClipMatrix * (worldToCameraMatrix * vec4(position, 1.0));
    }

    FS:

    Code :
    #version 330
     
    uniform int id;
     
    out vec4 outputColor;
     
    void main() {
     
        outputColor = vec4(id, 0, 0, 1);
    }

    Im reading always the same value (32767)

    What is wrong, guys?
    Last edited by elect; 02-10-2014 at 08:09 AM.

  2. #2
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,117
    You fragment shader says your are writing to a floating point texture (vec4) but you texture is integer. AFAIK the result is undefined. Try ivec4

  3. #3
    Intern Contributor
    Join Date
    Dec 2011
    Posts
    59
    Thanks tonyo, I tried that but unfortunately it returns still the same wrong value

  4. #4
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,117
    What colour are you using to clear? Try reading back the whole buffer and looking at what is in it both before and after your mesh render. Why are use using GL_TEXTURE_RECTANGLE and not GL_TEXTURE_2D?

  5. #5
    Advanced Member Frequent Contributor arekkusu's Avatar
    Join Date
    Nov 2003
    Posts
    781
    The clear is also wrong. It is undefined to use glClearColor on integer framebuffers. Use glClearBufferiv instead (or glClearColorIiEXT, back in GL2.)

  6. #6
    Intern Contributor
    Join Date
    Dec 2011
    Posts
    59
    Quote Originally Posted by tonyo_au View Post
    What colour are you using to clear? Try reading back the whole buffer and looking at what is in it both before and after your mesh render. Why are use using GL_TEXTURE_RECTANGLE and not GL_TEXTURE_2D?
    Exacty white, (1,1,1,1). Yeah, I can try to look inside it, once retrieved which is the fastest way to look at it?

    If I have to be honest I don't know why I am using GL_TEXTURE_RECTANGLE, I guess a relict of the past... Why should I use GL_TEXTURE_2D?

    Quote Originally Posted by arekkusu View Post
    The clear is also wrong. It is undefined to use glClearColor on integer framebuffers. Use glClearBufferiv instead (or glClearColorIiEXT, back in GL2.)
    Ok, so rendering like this

    gl3.glClearBufferiv(GL3.GL_COLOR, GL3.GL_COLOR_ATTACHMENT0, new int[]{1, 0, 0, 0}, 0);
    gl3.glDrawBuffer(GL3.GL_COLOR_ATTACHMENT0);
    Reading

    ShortBuffer p = ShortBuffer.allocate(2);

    Vec2i point = EC_GUI.main.getGlViewer().getViewPole().getStartin gPoint();

    int realY = EC_GUI.main.getGlViewer().getGlWindow().getHeight( ) - point.y - 1;

    gl3.glReadPixels(point.x, realY, 1, 1, GL3.GL_RED_INTEGER, GL3.GL_SHORT, p);

    EC_GUI.main.getGlViewer().getList().selectionById( (short) p.get(0));
    System.out.println("pixel id "+p.get(0));
    Init

    gl3.glTexImage2D(GL3.GL_TEXTURE_RECTANGLE, 0, GL3.GL_R16I, width, height, 0, GL3.GL_RED_INTEGER, GL3.GL_SHORT, null);
    FS

    #version 330

    uniform int id;

    out vec4 outputColor;

    void main() {

    outputColor = ivec4(id, 0, 0, 1);
    //outputColor = vec4(3, id, 2, 1);
    }
    I get error 1281, INVALID_VALUE (not in the init, but after the rendering+pick)

  7. #7
    Intern Contributor
    Join Date
    Dec 2011
    Posts
    59
    The rendering was wrong, I read that the second parameter in glClearBufferiv should be the i-th buffer specified by glDrawBuffer(s)

    so this is the new rendering

    gl3.glDrawBuffer(GL3.GL_COLOR_ATTACHMENT0);
    // Vec4 clear = EC_GUI.main.getGlViewer().getClearColor();
    // gl3.glClearColor(clear.x, clear.y, clear.z, clear.w);
    // gl3.glClear(GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT);
    gl3.glClearBufferiv(GL3.GL_COLOR, 0, new int[]{0, 0, 0, 0}, 0);

  8. #8
    Intern Contributor
    Join Date
    Dec 2011
    Posts
    59
    I got it working if I switch to int

    init

    Code :
            gl3.glTexImage2D(GL3.GL_TEXTURE_RECTANGLE, 0, GL3.GL_R32I, width, height, 0, GL3.GL_RED_INTEGER, GL3.GL_INT, null);

    render

    Code :
    gl3.glDrawBuffer(GL3.GL_COLOR_ATTACHMENT0);
                Vec4 clear = EC_GUI.main.getGlViewer().getClearColor();
                gl3.glClearColor(2, clear.y, clear.z, clear.w);
                gl3.glClear(GL3.GL_COLOR_BUFFER_

    pick

    Code :
                gl3.glReadPixels(point.x, realY, 1, 1, GL3.GL_RED_INTEGER, GL3.GL_INT, pixel);

    I also changed the FS, although this does not seem to have any effect (vec4 -> ivec4)

    Code :
        outputColor = ivec4(id, 0, 0, 1);

    However I am doing some test to see what is written inside my GL_COLOR_ATTACHMENT0 before I render something (basically I click on empty space, where I am sure nothing has been rendered there)

    If I have

    Code :
                gl3.glDrawBuffer(GL3.GL_COLOR_ATTACHMENT0);
                gl3.glClearBufferiv(GL3.GL_COLOR, 0, new int[]{0, 0, 0, 0}, 0);
    gl3.glClear(GL3.GL_DEPTH_BUFFER_BIT);

    I get

    pixel id 0.0


    If I have

    Code :
                gl3.glDrawBuffer(GL3.GL_COLOR_ATTACHMENT0);
                gl3.glClearBufferiv(GL3.GL_COLOR, 0, new int[]{1, 0, 0, 0}, 0);
    gl3.glClear(GL3.GL_DEPTH_BUFFER_BIT);

    I get

    pixel id 1.4E-45


    If I have

    Code :
                gl3.glDrawBuffer(GL3.GL_COLOR_ATTACHMENT0);
                gl3.glClearBufferiv(GL3.GL_COLOR, 0, new int[]{2, 0, 0, 0}, 0);
    gl3.glClear(GL3.GL_DEPTH_BUFFER_BIT);

    I get

    pixel id 2.8E-45

    Instead if I have

    Code :
    gl3.glDrawBuffer(GL3.GL_COLOR_ATTACHMENT0);
                Vec4 clear = EC_GUI.main.getGlViewer().getClearColor();
                gl3.glClearColor(0, clear.y, clear.z, clear.w);
                gl3.glClear(GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT);

    pixel id 0.0

    Code :
    gl3.glDrawBuffer(GL3.GL_COLOR_ATTACHMENT0);
                Vec4 clear = EC_GUI.main.getGlViewer().getClearColor();
                gl3.glClearColor(1, clear.y, clear.z, clear.w);
                gl3.glClear(GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT);

    pixel id 1.0

    Code :
    gl3.glDrawBuffer(GL3.GL_COLOR_ATTACHMENT0);
                Vec4 clear = EC_GUI.main.getGlViewer().getClearColor();
                gl3.glClearColor(2, clear.y, clear.z, clear.w);
                gl3.glClear(GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT);

    pixel id 2.0

    Wut? Isn't clearColor supposed to clamp [0,1]? >.>

    Ps: changing the other component other than the red one does have no effect as expected.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •