如何防止Texture_2D大于viewport被缩放到openGL的viewport

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

本文关键字:viewport 缩放 openGL 大于 何防止 Texture 2D      更新时间:2023-10-16

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

基本上我有一个在GL中显示2D图像的VBO,但是,由于我的视口是800x600,图像是1024x1024,因此图像正在按比例缩小以适应视口。我在谷歌上搜索了很长时间关于这个问题,我所能找到的都是关于这个的参考资料,比如NeHe教程,他们说这会发生,但没有解释为什么以及如何防止它发生。我想我找到了一个论坛,说有可能预防,但同样没有细节。

所以,我很好奇,这是怎么做到的?我刚刚学习GL,所以在这个领域我几乎是一个全新的新手。如果有帮助的话,我正在制作一款2D游戏,我试图使用这个VBO来显示关卡的背景图像,所以当你左右上下移动摄像机时,你实际上是在滚动背景图像。任何帮助将非常感激和感谢。:)

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

好的,所以在一些更多的谷歌搜索后,我发现的唯一解决方案是暂时调整视口至少是你的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);

唯一的问题是,这似乎是一个重大的黑客。这是官方或可接受的解决方案吗?

把纹理想象成橡胶片。纹理的左下角(不是像素)在(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投影矩阵并不是一些不可触及的神圣数据。实际上,你应该随时修改它,使事情变得更容易。变换矩阵很便宜。这同样适用于视口。它们只是一组寄存器(在着色器方面,它们被称为制服),几乎可以自由设置。

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

例如,绘制一个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状态改变。

注意:如果投影矩阵更复杂,这可能会变得更复杂。