PDA

View Full Version : Encoding id picking into a 16b red component texture



elect
02-10-2014, 07:02 AM
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


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().getStartin gPoint();

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:


#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:


#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?

tonyo_au
02-10-2014, 07:09 PM
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

elect
02-10-2014, 11:51 PM
Thanks tonyo, I tried that but unfortunately it returns still the same wrong value

tonyo_au
02-11-2014, 05:10 PM
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?

arekkusu
02-11-2014, 05:20 PM
The clear is also wrong. It is undefined to use glClearColor on integer framebuffers. Use glClearBufferiv instead (or glClearColorIiEXT, back in GL2.)

elect
02-11-2014, 11:37 PM
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?


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)

elect
02-12-2014, 01:07 AM
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);

elect
02-12-2014, 01:24 AM
I got it working if I switch to int

init


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

render



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


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)


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


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


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


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


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


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


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.