开发者

How to prevent Texture_2D bigger than viewport from being scaled to viewport in openGL

Total noob here learning openGL and I don't have any code to post because this is a question about a concept, not my current implementation. If code is absolutely required let me know and to my nooby shame I will post some.

Basically I have a VBO that is displaying a 2D image in GL. However, since my viewport is 800x600 and the image is 1024x1024, the image is being scaled down to fit inside the viewport. I've googled for a very long time about this issue and all I can find are references to this in things such as the NeHe tutorials where they say this will happen, but with no explanation as to why and how to prevent it from happening. I think I found one forum that said it's possible to prevent but again, no details.

So, I'm curious, how can this be done? I'm JUST learning GL so I'm pretty much a brand new baby noob in this area. If it helps, I'm making a 2D game and I'm trying to use this VBO for displaying the background image for a level, so as you move the camera left and right, up and down you're essentially scrolling this background image. Any help would be greatly appreciated and thanks. :)

P.S. Also, I realize this probably should be in a separate question but any explanation or links to explain the coordinate system for vertex/texture maps would be appreciated as well. I'm not really grasping how one is supposed to map textures from 0-1 and convert that to pixel coordinates in space.

UPDATE

Okay so after some more googling the ONLY solution I've found is to adjust the viewport temporarily to be at least the size of your 2D texture, then draw your 2D texture, then set the viewport back to the window size (or whatever it ought to be). Like so:

//Set viewport so size of the current texture - note this is using a VBO
glViewport(0, 0, 1024, 1024);
glBindTexture(GL_TEXTURE_2D, texture);

glDrawArrays(GL_QUADS, 0, 4 );

glPopAttrib();

glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindTexture(GL_TEXTURE_2D, 0);

//Set the viewport back to the window size
glViewpo开发者_JAVA技巧rt(0, 0, 800, 600);

Only thing is, these seems like a MAJOR hack. Is this the official or an acceptable solution?


Think textures as being rubber sheets. The lower left corner (not the pixel) of the texture is at (0, 0), the upper right corner is at (1, 1). When drawing a triangle to the screen – the exact position on screen doesn't matter – the texture "rubber sheet" is "cut out" according to the texture coordinates and stretched onto the triangle as specified by the texture coordinates. There is no interaction between viewport dimensions and texturing!

So say you have a texture and want to show its lower left part, to the amount that the viewport allows. Then you'd do it this way:

void display()
{
    glViewport(0, 0, viewport_width, viewport_height);
    /* ... */

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    /* By using a orthographic projection with limits matching the viewport
       we're effectively getting viewport pixel coordinates for the vertices. */
    glOrtho(0, viewport_width, 0, viewport_height, -1, 1);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    /* I'm using immediate mode here for clarity – not
       recommended for new applications, use Vertex Arrays */
    glBegin(GL_QUADS);

    glTexCoord2f(0.0f, 0.0f); glVertex2f(0, 0);
    glTexCoord2f(1.0f, 0.0f); glVertex2f(texture_width, 0.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex2f(texture_width, texture_height);
    glTexCoord2f(0.0f, 1.0f); glVertex2f(0, texture_height);

    glEnd();
}

The key is, to change the projection as one needs it. The OpenGL projection matrix is not some piece of sacred data that must not be touched. Actually you should modify it, whenever you see it neccesary to make things easier. Changing matrices is cheap. The same holds for the viewport. They are just a set of registers (in terms of shaders they are called uniforms) which are almost for free to set.


The best way to do that is to scale the vertices you are drawing to the current viewport size.

For example, to draw a 10px by 10px box(Ignore obsolete api).

glBegin( GL_QUADS );
glVertex2d(0.0                    ,0.0);
glVertex2d(10.0/viewportWidth * 2,0.0);
glVertex2d(10.0/viewportWidth * 2,10.0/viewportHeight * 2);
glVertex2d(0.0                    ,10.0/viewportHeight * 2);
glEnd();

You could do it in a shader or on the CPU.

Changing the viewport looks like yet another of those expensive OpenGL state changes.

NOTE: This could become more complicated with a more complex projection matrix.(I assume the default -1 to 1)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜