这里学习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);
唯一的问题是,这些似乎是一个主要的黑客。这是官方还是可接受的解决方案?
答案 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)