PDA

View Full Version : FBO call surrogate



devdept
09-16-2008, 10:20 AM
Hi All,

I have the following *working* code with a line marked "this line".

Suppose the FBO is not available on some hardwares, what is the standard OpenGL surrogate for "this line"?

I discovered that Shaders can be available while FBO not on some implementations, so I wanted to try the slow way to keep shaders alive.

Thanks in advance,

Alberto


glActiveTexture(gl.TEXTURE0);

// this line
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, blurredTextureName, 0);

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, sharpTextureName);
glUseProgram(ShaderProgram);

DrawQuadOnTexture();

arekkusu
09-16-2008, 10:32 AM
Pbuffers, or glCopyTexImage2D.

devdept
09-16-2008, 01:29 PM
I probably explain me poorly I am trying to understand what the marked FBO line does and lookign for a standard OpenGL equivalent.

Any idea?

Thanks,

Alberto

You are right, it's probably the glCopyTexImage2D I need. I'll try and let you know.

devdept
09-16-2008, 01:56 PM
No, in practice the marked line determines what texture will be modified, while the line:


glBindTexture(GL_TEXTURE_2D, sharpTextureName);

determines what texture the shader keeps as source.

How can I specify the destination texture with standard OpenGL?


Thanks,

Alberto

Korval
09-16-2008, 02:20 PM
How can I specify the destination texture with standard OpenGL?

The primary purpose of FBO is to allow you to use a texture as its framebuffer. This is because before FBO, you couldn't do that.

In short, you cannot do exactly what you want with "standard" OpenGL. If you don't want to use FBO, you will have to render to the main framebuffer and use glCopyTexSubImage2D to copy the results to a texture.

devdept
09-16-2008, 02:25 PM
Sounds good, so I need to change my shaders to look for framebuffer pixel colors instead of the binded texture texel I use with FBO, right?

Korval
09-16-2008, 03:16 PM
Sounds good, so I need to change my shaders to look for framebuffer pixel colors instead of the binded texture texel I use with FBO, right?

Um, no.

Given some of the names you've chosen, it looks like you're trying to do some shader-based blurring of a texture, and capture the result of that in another texture.

To do that without FBO, you do the following:

1: Get the un-blurred texture (eg: texture 1)
2: Bind it to your shader.
3: Render to the framebuffer.
4: Copy the un-blurred texture with glCopyTexSubImage into the blurred texture (eg: texture 2)
5: You're done.

Your shader is not changed in any way.

dletozeun
09-16-2008, 03:19 PM
As far as I understand, you should not change your shaders at all since when you bind a fbo, it is like your are drawing into theframebuffer. In other words there is nothing linked to fbos in your shader you just draw into a texture instead of the framebuffer and you choose this in your application.

devdept
09-17-2008, 04:30 AM
Korval,


Thanks so much for your help.

It is step 2) that I don't know how to do.

How can I bind a texture to a shader without using FBO?


Thanks,

Alberto

devdept
09-17-2008, 05:07 AM
dletozeun,

I don't know how to explain it. The shader looks for original texture texel color and alter it in the destination texture.

I need to indicate to the shader what it the original texture and don't know how to do (always in the case FBO aren't available).

Thanks,

Alberto

dletozeun
09-17-2008, 12:20 PM
As it has been said before, without fbo it is not possible to draw to a texture, but you can read a texture giving this one to a shader as a sampler2D.

The only thing you can do is to render your data in directly in the framebuffer or an auxiliary buffer (pBuffer) and then copy buffer data to a texture using glCopyTexSubImage. Finally you can reuse this texture as input parameter to your shader for a second pass.
Re-read what Korval said, it is very clear.

So you don't specify nothing about destination buffer or texture to your shader, all is done in your application. Without fbo you have:

input_texture -> shader -> framebuffer|pbuffer - copy to texture(glCopyTexSubImage) -> output_texture

with a fbo:

input_texture -> shader -> output_texture

devdept
09-17-2008, 12:33 PM
Here is the shader code. What will it read from the texture2D() func without having a suorce texture?!?

Therefore I cannot share the same shader code. I need two diffrent shader: in case of missing FBO i will read framebuffer values, right?



void main()
{

int i;
vec4 sum = vec4(0.0);

for (i = 0; i < KernelSize; i++)
{
vec4 tmp = texture2D(BaseImage, gl_TexCoord[0].st + vec2(Offset[i], 0));
sum += tmp * KernelValue[i];
}

gl_FragColor = sum;

}

dletozeun
09-17-2008, 01:42 PM
What is BaseImage? It is a uniform sampler2D.

You affected to this sampler the texture unit ID in your application and you bound an input texture to this texture unit using glBindTexture. Source texture is not linked to a fbo!

fbo is only set to render TO texture in your case.

Please read more about framebuffer objects and GLSL shaders, It looks like you have an understanding problem about what fbo really are.

http://www.gamedev.net/reference/articles/article2331.asp
http://www.gamedev.net/reference/programming/features/fbo2/

texture2D is just a glsl function that fetches a texel at given texture coordinates in a given texture through a sampler2D. It does not read the framebuffer.

devdept
09-18-2008, 06:10 AM
dletozeun,

You said:
"As it has been said before, without fbo it is not possible to draw to a texture"

Now you say I need to bind the texture with ID 0.

Is it possible or not to use this shader unmodified without FBO?

Thanks,

Alberto

dletozeun
09-18-2008, 06:57 AM
...as an input texture. You can't draw to an output texture without a fbo but you can read one in a shader.

devdept
09-18-2008, 07:16 AM
So I need to use something like this?


glBindTexture(GL_TEXTURE_2D, sharpTextureName);
glUseProgram(ShaderProgram);

DrawQuadOnTexture();

glUseProgram(0);

glBindTexture(GL_TEXTURE_2D, blurredTextureName);

glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, textureSize, textureSize, 0);

devdept
09-18-2008, 07:21 AM
Tested and works great. Thanks a lot dletozeun for your help!

dletozeun
09-18-2008, 07:31 AM
Yes exactly. You are welcome.

devdept
09-19-2008, 08:48 AM
Hi again,

I was so happy to see everything working that the first machine I tested the code on (different from developing machine) display a empty texture (the one FBO uses as render to texture). In practice the one I specify here:

glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, blurredTextureName, 0);

Summarizing: I am drawing the model shadow on a texture, blurring the shadow image and displaying the texture under the model (in two passes, using two textures).

The machine where everything works fine is:

ATI FireGL 7200
OpenGL version 2.0.6663
Shading language 1.10

The other, where the issue is present (shaders works on this machine, I installed renderMonkey and see all shaders effects):

ATI Radeon 9550 / X1050
OpenGL version 2.1.7873
Shading language 1.20

I attach the GLIntercept output to list exaclty what I am doing.

Do you see something wrong?

Thanks,

Alberto


Shader initialization and variable loading:



glGetString(GL_VERSION)="2.1.7873 Release"
glGetString(GL_SHADING_LANGUAGE_VERSION)="1.20"
glCreateShader(GL_FRAGMENT_SHADER)=1
glCreateShader(GL_FRAGMENT_SHADER)=2
glShaderSource(1,1,0x2481c0,0x0000)
glShaderSource(2,1,0x2481c0,0x0000)
glCompileShader(1)
glCompileShader(2)
glGetShaderiv(1,GL_COMPILE_STATUS,0x415d794)
glGetShaderiv(2,GL_COMPILE_STATUS,0x415d790)
glCreateProgram()=3
glAttachShader(3,1)
glLinkProgram(3)
glCreateProgram()=4
glAttachShader(4,2)
glLinkProgram(4)
glGetProgramiv(3,GL_LINK_STATUS,0x415d78c)
glGetProgramiv(4,GL_LINK_STATUS,0x415d788)
glUseProgram(3)
glGetUniformLocation(3,"BaseImage")=38
glGetUniformLocation(3,"Offset")=19
glGetUniformLocation(3,"KernelValue")=0
glUniform1i(38,0)
glUniform1fv(19,19,[-0.035156])
glUniform1fv(0,19,[0.007935])
glUseProgram(4)
glGetUniformLocation(4,"BaseImage")=38
glGetUniformLocation(4,"Offset")=19
glGetUniformLocation(4,"KernelValue")=0
glUniform1i(38,0)
glUniform1fv(19,19,[-0.035156])
glUniform1fv(0,19,[0.007935])
glUseProgram(0)

FBO preparation, drawing on texture, shader execution and FBO cleanup:


glGenFramebuffersEXT(1,0x133bafc)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,1)
glBindTexture(GL_TEXTURE_2D,2)
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,256,256,0,GL_ BGRA,GL_UNSIGNED_BYTE,0x0000)
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_CO LOR_ATTACHMENT0_EXT,GL_TEXTURE_2D,2,0)
glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)=GL _FRAMEBUFFER_COMPLETE_EXT
glBindTexture(GL_TEXTURE_2D,0)

/* drawing begins here */

glClearColor(0.000000,0.000000,0.000000,0.000000)
glClear(GL_COLOR_BUFFER_BIT)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(-7.308236,7.308236,-7.308236,7.308236,-1000000.000000,1000000.000000)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glMultMatrixf([1.000000,0.000000,0.000000,0.000000,0.000000,1.000 000,0.000000,0.000000,0.000000,0.000000,1.000000,0 .000000,0.000000,0.000000,0.000000,1.000000])
glTranslated(-2.500000,0.000000,-1.000000)
glViewport(0,0,256,256)
glDisable(GL_CULL_FACE)
glDisable(GL_DEPTH_TEST)
glDisable(GL_BLEND)
glDisable(GL_LIGHTING)
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL)
glColor3ub(0,0,0)
glCallList(522)

/* shaders execution */

glActiveTexture(GL_TEXTURE0)
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_CO LOR_ATTACHMENT0_EXT,GL_TEXTURE_2D,3,0)
glBindTexture(GL_TEXTURE_2D,2)
glUseProgram(3)
glEnable(GL_TEXTURE_2D)
glBegin(GL_QUADS) GLSL=3 Textures[ (0,2) ]
glTexCoord2f(0.000000,0.000000)
glVertex2d(-4.808236,-7.308236)
glTexCoord2f(1.000000,0.000000)
glVertex2d(9.808236,-7.308236)
glTexCoord2f(1.000000,1.000000)
glVertex2d(9.808236,7.308236)
glTexCoord2f(0.000000,1.000000)
glVertex2d(-4.808236,7.308236)
glEnd()
glDisable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D,3)
glUseProgram(4)
glEnable(GL_TEXTURE_2D)
glBegin(GL_QUADS) GLSL=4 Textures[ (0,3) ]
glTexCoord2f(0.000000,0.000000)
glVertex2d(-4.808236,-7.308236)
glTexCoord2f(1.000000,0.000000)
glVertex2d(9.808236,-7.308236)
glTexCoord2f(1.000000,1.000000)
glVertex2d(9.808236,7.308236)
glTexCoord2f(0.000000,1.000000)
glVertex2d(-4.808236,7.308236)
glEnd()
glDisable(GL_TEXTURE_2D)
glUseProgram(0)

/* FBO cleanup */

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0)
glDeleteFramebuffersEXT(1,0x133bb0c)

dletozeun
09-19-2008, 11:44 AM
glGenFramebuffersEXT(1,0x133bafc)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,1)


What is this? o

You are binding the framebuffer object with id 1 and and generating a fbo id at the @ 0x133bafc. The generated value could be different than 1 and if you use this one to bind the fbo latter you could have problems.

Anyxay, there is a coding problem here, you store an ID and don't use it after.

kreyszig
09-19-2008, 12:49 PM
are you sure that value isn't the trace substituting the value in for him?

devdept
09-19-2008, 01:00 PM
Here is the real source code, please tell me what you think.


uint fb = 0;

fb = glGenFramebuffersEXT();

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);

glBindTexture(gl.TEXTURE_2D, sharpTextureName);

glTexImage2D(gl.TEXTURE_2D, 0, GL_RGBA, textureSize, textureSize, 0, GL_BGRA, GL_UNSIGNED_BYTE, null);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, sharpTextureName, 0);

glBindTexture(GL_TEXTURE_2D, 0);

// draws on the texture here

glActiveTexture(GL_TEXTURE0);

glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, blurredTextureName, 0);

glBindTexture(GL_TEXTURE_2D, sharpTextureName);

glUseProgram(ShaderProgram);

// executes shader here
DrawQuadOnTexture();

glUseProgram(0);


Thanks,

Alberto

kreyszig
09-19-2008, 01:23 PM
looks ok to me. I don't use glIntercept myself - can you break on gl errors? If not try bugle or glsldevil, or add some calls to glGetError, you may want to add some code to check for fbo completeness too: (not my code btw)


bool checkFramebufferStatus() {
GLenum status;
status=(GLenum)glCheckFramebufferStatusEXT(GL_FRAM EBUFFER_EXT);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
return true;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
printf("Framebuffer incomplete,incomplete attachment\n");
return false;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
printf("Unsupported framebuffer format\n");
return false;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
printf("Framebuffer incomplete,missing attachment (don't panic!)\n");
return false;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
printf("Framebuffer incomplete,attached images must have same dimensions\n");
return false;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
printf("Framebuffer incomplete,attached images must have same format\n");
return false;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
printf("Framebuffer incomplete,missing draw buffer\n");
return false;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
printf("Framebuffer incomplete,missing read buffer\n");
return false;
}
return false;
}

devdept
09-20-2008, 05:45 AM
I'll give a try to glsldevil FBO status always return OK.

Thanks,

Alberto

devdept
09-20-2008, 11:05 AM
Unfortunately glslDevil doesn't allow me to debug shaders...

In the meantime I discovered another strange thing. If I remove the marked line the render to texture stops working, while if I put it back it starts working again...

WHY?!?!

Thanks,

Alberto


fbo = gl.GenFramebuffersEXT();

glBindFramebufferEXT(gl.FRAMEBUFFER_EXT, fbo);

sharpTextureName = Viewport.GetNextTextureName();
glBindTexture(gl.TEXTURE_2D, sharpTextureName);

/* the line below */
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
/* the line above */

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureSize, textureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);

glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, sharpTextureName, 0);

// Checks FBO status
int status = gl.CheckFramebufferStatusEXT(gl.FRAMEBUFFER_EXT);

// Draws on texture
DrawShadow();

ZbuffeR
09-21-2008, 12:02 PM
You forgot to generate mipmaps.

devdept
09-21-2008, 01:19 PM
Thanks ZbuffeR,


You are completely RIGHT! I don't need mipmaps, so I will add that line.


Thanks so much again,

Alberto