🔒 Locked
viewport basic question [SOLVED]
Advertisement
Original Post
To be honest, I am not very clear what viewport does. I need this in relation with Framebuffer objects...But I d like to know about the basics... Consider this simple code.... -------------------------------------------------------------------- glViewport(0,0,256, 256); glBegin(GL_QUADS); glNormal3f(0.0f, 0.0f, 1.0f); /* glTexCoord2i(0, 0); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2i(511,0); glVertex3f(1.0f, -1.0f, 1.0f); glTexCoord2i(511,511); glVertex3f(1.0f, 1.0f, 1.0f); glTexCoord2i(0,511); glVertex3f(-1.0f, 1.0f, 1.0f);*/ glTexCoord2i(0, 0); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2i(255,0); glVertex3f(1.0f, -1.0f, 1.0f); glTexCoord2i(255,255); glVertex3f(1.0f, 1.0f, 1.0f); glTexCoord2i(0,255); glVertex3f(-1.0f, 1.0f, 1.0f); glEnd(); --------------------------------------------------------- Without viewport I get this texture at the middle of the screen (which is okay) The aspect ratio is 1:1, which is expected cos i am working with a 256*256 tex, and in any case, the vertex coords give a square. With the viewport, I get it in the bottom left corner( but not exactly, which might even make sense) The otherthing is that in this case, the aspect ratio seems not to be 1:1. The height is bigger! Any ideas? Cheers, Dj [Edited by - vrdhananjay on February 24, 2007 4:46:07 PM]
glViewport specifies the transformation from normalized device coordinates to window coordinates. The X,Y specify the bottom left of the viewport (not top right as in win32, and DirectX?). Width and Height specify the width and height of the viewport.
When you create the gl context the viewport x,y are initialized to 0,0 and the w,h to the dimensions of the window. If you resize the window or want to render to a smaller section of it (RTT) then you need to call glViewport.
So basically they tell OGL where inside the window to render to.
Hope that helps
When you create the gl context the viewport x,y are initialized to 0,0 and the w,h to the dimensions of the window. If you resize the window or want to render to a smaller section of it (RTT) then you need to call glViewport.
So basically they tell OGL where inside the window to render to.
Hope that helps
Hey, thanks a lot for that! That leaves me with two things, why is it not being displayed exactly on the bottom left, and 2, why is the aspect ratio changed?
Thanks,
Dhananjay
Thanks,
Dhananjay
It has to do with how you display the FBO. Presumably once you're done using the FBO you render a full screen quad with the color attachment texture, correct? If you set the viewport back to the size of the window before rendering this quad, then you're actually stretching the FBO to fit the window, which will distort it if the window and FBO aren't the same size. The simple way around this is to keep the viewport the same size when you render the full-screen quad, but possibly move it around if you want the FBO to appear at different places in the window (i.e the values (right-left) and (top-bottom) remain constant, but you can change left and bottom).
@ Zipmaster Thanks a lot for that reply of yours. I think you have more or less understood what I am trying to do. But just to clarify.
1. I attach an empty texture to the color attachment0 of a frame buffer (you were right about this)
2. I use a shader to output to the (color attachment0) Framebuffer object via glDrawpixels. Before using the shader, if I do it without the view port command , I get a only about 1/4th of the desired image. But when I use, glViewport(0,0,256,256) , with 256x256 being the size of the texture, the shader gives me the complete image, although at the bottom left of the screen (which is expected as 0,0 signifies bottom left, as clarified by nts), and distorted in terms of aspect ratio.
3. Now I want to further process this colorattachment0 of the fbo with a filter (2nd shader), after which I want to store it to the CPU memory. This I do using glReadpixels. I want the entire processed 256x256 texture to be saved. Do I need to use glViewport(0,0,256,256) again before glReadpixels to get the right texture into my cpu mem? Right now when i dont use this, it seems that its reading in a lot of 0's at the beginning which are unexpected.
Thanks,
Dhananjay
P.S. I could post the code if you like, just didnt want to throw it at you guys unasked!
1. I attach an empty texture to the color attachment0 of a frame buffer (you were right about this)
2. I use a shader to output to the (color attachment0) Framebuffer object via glDrawpixels. Before using the shader, if I do it without the view port command , I get a only about 1/4th of the desired image. But when I use, glViewport(0,0,256,256) , with 256x256 being the size of the texture, the shader gives me the complete image, although at the bottom left of the screen (which is expected as 0,0 signifies bottom left, as clarified by nts), and distorted in terms of aspect ratio.
3. Now I want to further process this colorattachment0 of the fbo with a filter (2nd shader), after which I want to store it to the CPU memory. This I do using glReadpixels. I want the entire processed 256x256 texture to be saved. Do I need to use glViewport(0,0,256,256) again before glReadpixels to get the right texture into my cpu mem? Right now when i dont use this, it seems that its reading in a lot of 0's at the beginning which are unexpected.
Thanks,
Dhananjay
P.S. I could post the code if you like, just didnt want to throw it at you guys unasked!
glReadPixels just reads the texture straight from GPU memory, so it shouldn't be affected by any transformations. As long as the viewport is always the same size as the FBO attachment you're rendering do, you shouldn't experience any problems.
However I question your use of glDrawPixels. Keep in mind that it always starts writing at the current raster position, which could give you unexpected results if the position isn't currently at the beginning of the buffer. It also means you're copying the results of the first shader to the CPU and then back to the GPU, which is a massive performance hit. Instead, set up two color attachments for the FBO. Render the results of the first shader to the first attachment, then bind it as an input and render to the second attachment. This is a simple instance of ping-ponging. Once that's done you can glReadPixels from the second attachment to get the results on the CPU.
You should go ahead and post the code anyway. Always better to be sure :)
However I question your use of glDrawPixels. Keep in mind that it always starts writing at the current raster position, which could give you unexpected results if the position isn't currently at the beginning of the buffer. It also means you're copying the results of the first shader to the CPU and then back to the GPU, which is a massive performance hit. Instead, set up two color attachments for the FBO. Render the results of the first shader to the first attachment, then bind it as an input and render to the second attachment. This is a simple instance of ping-ponging. Once that's done you can glReadPixels from the second attachment to get the results on the CPU.
You should go ahead and post the code anyway. Always better to be sure :)
Hey,
First up, thanks, that was insightful...I am pretty sure that I have my raster in the incorrect position, thats why I was only getting a fourth of the image after gldrawpixels....Actually there was a mistake on my part, I am using gldrawbuffer and not gldrawpixels...Is this allright, with reference to your comment on the gpu to cpu to gpu comment?
For the ping pong thing, I am not sure if i can use it since I need all 8 color buffers, for 8 image pairs....
Heres the code...
Would appreciate any comments!
-------
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, z);
/*bind the frame buffer*/
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,fbo);
/*bind the texture (dimension 256x256)) to the color att. 0)*/
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, texture3,0);
glPushAttrib(GL_VIEWPORT_BIT );
glViewport(0,0,256, 256);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
/*Shader 1 : subtracts 2 images*/
glUseProgramObjectARB(my_program);
glUniform1i(uni1,0);
glUniform1i(uni2,1);
glUniform1i(glGetUniformLocation(my_program, "offset"),20);
/*Do I even need this?*/
glBegin(GL_QUADS);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2i(0, 0);
glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2i(255,0);
glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2i(255,255);
glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2i(0,255);
glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
glPopAttrib();
glUseProgramObjectARB(0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
/* Shader 2: 3x3 Average Filtering SAD*/
glUseProgramObjectARB(my_program3);
glUniform1i(glGetUniformLocation(my_program3, "texUnit2"),2);
glBegin(GL_QUADS);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2i(0, 0);
glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2i(255,0);
glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2i(255,255);
glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2i(0,255);
glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
check_gl_error("End Drawing Quad");
----------
In another function, I use glreadpixels..
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, texture3,0);
CHECK_FRAMEBUFFER_STATUS();
glReadPixels(0,0,256,256, GL_RGB, GL_UNSIGNED_BYTE, texmem);
check_gl_error("GPU to CPU");
------------
The first shader goes like...
#extension GL_ARB_texture_rectangle : enable
#extension GL_ARB_draw_buffers : enable
uniform sampler2DRect myTexture1;
uniform sampler2DRect myTexture2;
uniform int offset;
const int off=4;
void main (void)
{ vec2 check=vec2(gl_TexCoord[0])+vec2(offset,0.0);
vec4 texval1 = texture2DRect(myTexture1, vec2(gl_TexCoord[0])+vec2(offset,0.0));
vec4 texval2 = texture2DRect(myTexture2, vec2(gl_TexCoord[1]));
if(gl_TexCoord[0].x>offset&&check.x<256)
{
gl_FragData[0] = abs(texval1-texval2 );
}
else
gl_FragData[0] = vec4 (100.0, 100.0, 100.0, 0.0);
}
----------
mfg,
Dhananjay
First up, thanks, that was insightful...I am pretty sure that I have my raster in the incorrect position, thats why I was only getting a fourth of the image after gldrawpixels....Actually there was a mistake on my part, I am using gldrawbuffer and not gldrawpixels...Is this allright, with reference to your comment on the gpu to cpu to gpu comment?
For the ping pong thing, I am not sure if i can use it since I need all 8 color buffers, for 8 image pairs....
Heres the code...
Would appreciate any comments!
-------
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, z);
/*bind the frame buffer*/
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,fbo);
/*bind the texture (dimension 256x256)) to the color att. 0)*/
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, texture3,0);
glPushAttrib(GL_VIEWPORT_BIT );
glViewport(0,0,256, 256);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
/*Shader 1 : subtracts 2 images*/
glUseProgramObjectARB(my_program);
glUniform1i(uni1,0);
glUniform1i(uni2,1);
glUniform1i(glGetUniformLocation(my_program, "offset"),20);
/*Do I even need this?*/
glBegin(GL_QUADS);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2i(0, 0);
glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2i(255,0);
glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2i(255,255);
glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2i(0,255);
glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
glPopAttrib();
glUseProgramObjectARB(0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
/* Shader 2: 3x3 Average Filtering SAD*/
glUseProgramObjectARB(my_program3);
glUniform1i(glGetUniformLocation(my_program3, "texUnit2"),2);
glBegin(GL_QUADS);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2i(0, 0);
glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2i(255,0);
glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2i(255,255);
glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2i(0,255);
glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
check_gl_error("End Drawing Quad");
----------
In another function, I use glreadpixels..
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, texture3,0);
CHECK_FRAMEBUFFER_STATUS();
glReadPixels(0,0,256,256, GL_RGB, GL_UNSIGNED_BYTE, texmem);
check_gl_error("GPU to CPU");
------------
The first shader goes like...
#extension GL_ARB_texture_rectangle : enable
#extension GL_ARB_draw_buffers : enable
uniform sampler2DRect myTexture1;
uniform sampler2DRect myTexture2;
uniform int offset;
const int off=4;
void main (void)
{ vec2 check=vec2(gl_TexCoord[0])+vec2(offset,0.0);
vec4 texval1 = texture2DRect(myTexture1, vec2(gl_TexCoord[0])+vec2(offset,0.0));
vec4 texval2 = texture2DRect(myTexture2, vec2(gl_TexCoord[1]));
if(gl_TexCoord[0].x>offset&&check.x<256)
{
gl_FragData[0] = abs(texval1-texval2 );
}
else
gl_FragData[0] = vec4 (100.0, 100.0, 100.0, 0.0);
}
----------
mfg,
Dhananjay
Quote:
Original post by vrdhananjay
I am pretty sure that I have my raster in the incorrect position, thats why I was only getting a fourth of the image after gldrawpixels....Actually there was a mistake on my part, I am using gldrawbuffer and not gldrawpixels...Is this allright, with reference to your comment on the gpu to cpu to gpu comment?
There's a huge difference between glDrawPixels and glDrawBuffer :) One implies that you're transferring data from the CPU to the GPU, and the other just sets the buffer you want to draw to on the next render pass. In this case you don't have to worry about raster position.
Quote:
Original post by vrdhananjay
In another function, I use glreadpixels..
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, texture3,0);
CHECK_FRAMEBUFFER_STATUS();
glReadPixels(0,0,256,256, GL_RGB, GL_UNSIGNED_BYTE, texmem);
check_gl_error("GPU to CPU");
You shouldn't be calling glFramebufferTexture2DEXT again! This will attach the texture to the FBO for a second time, and I'm not sure what the behavior is if the texture is already attached. You should just call glReadBuffer(GL_COLOR_ATTACHMENT0_EXT) and then call glReadPixels (you can also set the read buffer to a standard OpenGL buffer, like GL_FRONT or GL_BACK).
Thanks man, yeah it was totally different.
But the annoying part is that when i check the results of readpixels , I have I seem to get a lotta zeros in the beginning and a lot in the end....between non zero values there are a bunch of (equal no of) zeros. I suspect I am reading the whole screen. I dropped the rebinding!
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glViewport(0,0,256,256);
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
check_gl_error("GPU to CPU");
glReadPixels(0,0,256,256, GL_RGB, GL_UNSIGNED_BYTE, texmem);
The texture that was associated with color attachment was 256 x 256.
Then pray why am I still getting the unwanted zeros? This should be pretty standard stuff right?
Do I have to change the way the pixels are stored while using draw pixels?
But the annoying part is that when i check the results of readpixels , I have I seem to get a lotta zeros in the beginning and a lot in the end....between non zero values there are a bunch of (equal no of) zeros. I suspect I am reading the whole screen. I dropped the rebinding!
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glViewport(0,0,256,256);
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
check_gl_error("GPU to CPU");
glReadPixels(0,0,256,256, GL_RGB, GL_UNSIGNED_BYTE, texmem);
The texture that was associated with color attachment was 256 x 256.
Then pray why am I still getting the unwanted zeros? This should be pretty standard stuff right?
Do I have to change the way the pixels are stored while using draw pixels?
I forgot to mention, you should make sure that your quad fills the screen, otherwise you won't get a 1:1 texel-to-pixel mapping and that could give weird results. I notice your quad is in the range [-1,-1]-[1,1], so you should set up your projection using gluOrtho2D(-1.0, 1.0, -1.0, 1.0). You don't have to use glTranslate either, just disable the depth test. Your texture coordinates will also need to be offset by (-0.5,-0.5) in the fragment shader, to account for the discrepancy between how fragments are sampled and texels are addressed.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement