如何防止在viewGL中大于视口的Texture_2D在openGL中缩放到视口

时间:2011-09-08 00:21:29

标签: c++ opengl opengl-es

这里学习openGL的总菜鸟我没有任何代码要发布,因为这是一个关于概念的问题,而不是我当前的实现。如果绝对需要代码让我知道,我会发布一些耻辱。

基本上我有一个在GL中显示2D图像的VBO。但是,由于我的视口为800x600,图像为1024x1024,因此缩小图像以适合视口内部。我已经搜索了很长一段时间来讨论这个问题,所有我能找到的都是在NeHe教程中提到的,他们说这会发生,但没有解释为什么以及如何防止它发生。我想我找到了一个论坛,说有可能再次阻止,没有细节。

所以,我很好奇,怎么办呢?我只是学习GL所以我在这方面几乎是一个全新的婴儿菜鸟。如果它有帮助,我正在制作一个2D游戏,我正在尝试使用这个VBO来显示一个关卡的背景图像,所以当你左右移动相机时,你上下都是滚动这个背景图像。任何帮助将不胜感激,谢谢。 :)

P.S。此外,我意识到这可能应该是一个单独的问题,但任何解释或链接来解释顶点/纹理贴图的坐标系也将受到赞赏。我并没有真正理解如何将纹理从0-1映射并将其转换为空间中的像素坐标。

更新

好吧,经过一些谷歌搜索我发现的ONLY解决方案暂时将视口调整到至少是2D纹理的大小,然后绘制2D纹理,然后将视口设置回窗口大小(或无论它应该是什么)。像这样:

//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
glViewport(0, 0, 800, 600);

唯一的问题是,这些似乎是一个主要的黑客。这是官方还是可接受的解决方案?

2 个答案:

答案 0 :(得分:1)

将纹理视为橡皮布。纹理的左下角(不是像素)位于(0,0),右上角位于(1,1)。当在屏幕上绘制三角形时 - 屏幕上的确切位置无关紧要 - 纹理“橡皮布”根据纹理坐标“切出”并拉伸到纹理坐标指定的三角形上。 视口尺寸和纹理之间没有交互!

所以说你有一个纹理,并希望显示其左下部分,视口允许的数量。然后你就这样做了:

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();
}

关键是,根据需要改变投影。 OpenGL投影矩阵不是一些不能被触及的神圣数据。实际上你应该修改它,只要你看到它需要使事情变得更容易。改变矩阵很便宜。视口也是如此。它们只是一组寄存器(就着色器而言,它们被称为制服)几乎可以自由设置。

答案 1 :(得分:0)

最好的方法是将绘制的顶点缩放到当前视口大小。

例如,绘制一个10px×10px的框(忽略过时的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();

您可以在着色器或CPU上执行此操作。

更改视口看起来就像是另一个昂贵的OpenGL状态更改。

注意: 使用更复杂的投影矩阵可能会变得更复杂。(我假设默认为-1到1)