I want to use a FrameBuffer to hold an ObjectID and a VertexIndex so I can read the pixel data and determine the object the mouse is over.
I have managed to do this OK for an 32bit Unsigned Integer FrameBuffer. However not all hardware is supporting the Integer frame buffer (Intel HD 4000 does not supply a 32bit buffer and even a 16bit buffer does not seem to work correctly). 16bit with a max of 65k may be too small.
I want to do the same thing using a RGB32F FrameBuffer. However, the FrameBuffer ends up with no data (all pixels are (0,0,0)). The following code snippets show my basic coding (in Pascal)
I am using NVIDEA with OpenGL4.4 and latest drivers for development.
FrameBuffer setup
// Create the FBO
glGenFramebuffers(1, @fFBOHandle);
glBindFramebuffer(GL_FRAMEBUFFER, fFBOHandle);
// Create the texture object for the primitive information buffer
glGenTextures(fColBufSize, @fColorTexture[0]);
for I := 0 to fColBufSize-1 do
Begin
glBindTexture(GL_TEXTURE_2D, fColorTexture[i]);
case aMode of
GL_RGB32F: glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB32F, SizeX, SizeY, 0, GL_RGB, GL_FLOAT, nil );
GL_RGB16F: glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB16F, SizeX, SizeY, 0, GL_RGB, GL_FLOAT, nil );
end;
glTexImage2D( GL_TEXTURE_2D, 0, aMode, SizeX, SizeY, 0, GL_RGB, GL_FLOAT, nil );
glFramebufferTexture2D (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + I, GL_TEXTURE_2D, fColorTexture[i], 0 );
fBuffer[i] := GL_COLOR_ATTACHMENT0 + I;
end;
glDrawBuffers(fColBufSize, @fBuffer[0]);
glBindTexture(GL_TEXTURE_2D, 0);
// depth
if fIncDepthBuffer then
Begin
glGenTextures(1, @fDepthBuff);
glBindTexture(GL_TEXTURE_2D, fDepthBuff);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, SizeX, SizeY, 0, GL_DEPTH_COMPONENT, GL_FLOAT, Nil);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fDepthBuff, 0);
glBindTexture(GL_TEXTURE_2D, 0);
end;
// Verify that the FBO is correct
aStatus := glCheckFramebufferStatus(GL_FRAMEBUFFER);
// Restore the default framebuffer
glReadBuffer(GL_NONE); //for older hardware
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
FrameBuffer Enable Writing (beginning of frame buffer render loop) and will end with glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
Result:=False;
if fFBOHandle = 0 then exit;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fFBOHandle);
if ClearBuffers then
Begin
for I := 0 to self.fColBufSize-1 do
glClearBufferfv(GL_COLOR,I,@BufClearColF); //all zero
if fIncDepthBuffer then
glClearBufferfv(GL_DEPTH,0,@BufClearDepthF) //1
else
glClear(GL_DEPTH_BUFFER_BIT);
End;
fIsLinked := True;
Result := True;
FrameBuffer Read Pixels
Var PixelID : array [0..2] of GLFLOAT; //3 x 4 Byte
PixelPos: array [0..2] of GLFLOAT; //3 x 4 Byte
begin
ObjID := 0;
if fFBOHandle = 0 then exit;
PixelID[0]:=0;
PixelID[1]:=0;
PixelID[2]:=0;
glBindFramebuffer(GL_READ_FRAMEBUFFER, fFBOHandle);
if fColBufSize>=1 then
Begin
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT, @PixelID[0]);
end;
if fColBufSize>=2 then
Begin
glReadBuffer(GL_COLOR_ATTACHMENT1);
glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT, @PixelPos[0]);
end;
glReadBuffer(GL_NONE);
//release frame buffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
ObjID := Trunc(PixelID[0]);
GripIndex:= Trunc(PixelID[1]);
end;
Vertex Shader
//RO_Arrow_SEL.vert
//-------LAYOUT
layout(location=0) in vec3 VertexPosition ;
layout(std140) uniform WorldUniform
{
vec3 GlobalOffset;
} World;
//----------UNIFORM
uniform mat4 ModelViewProjection;
//---------IN
//---------OUT
out float InstanceID;
void main(void)
{
InstanceID = float(gl_InstanceID);
gl_Position = ModelViewProjection * vec4((VertexPosition - World.GlobalOffset), 1.0) ;
}
Fragment Shader
//RO_Arrow_SEL.frag
///---------UNIFORM
uniform float ObjectID;
//used for selection render
//---------IN
in float InstanceID;
//---------OUT
layout (location = 0) out vec3 FragColor ;
void main(void)
{
FragColor = vec3(float(ObjectID), float(InstanceID) ,0);
}