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

发布于 2024-12-03 11:44:56 字数 1050 浏览 1 评论 0原文

这里是学习 openGL 的菜鸟,我没有任何代码要发布,因为这是一个关于概念的问题,而不是我当前的实现。如果绝对需要代码,请告诉我,令我羞愧的是,我会发布一些代码。

基本上我有一个在 GL 中显示 2D 图像的 VBO。但是,由于我的视口为 800x600 而图像为 1024x1024,因此图像将按比例缩小以适合视口。我已经用谷歌搜索了很长一段时间关于这个问题,我能找到的只是在 NeHe 教程等内容中对此的引用,他们说这种情况会发生,但没有解释为什么以及如何防止它发生。我想我发现一个论坛说可以预防,但同样没有详细信息。

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

PS 另外,我意识到这可能应该在一个单独的问题中,但任何解释或解释顶点/纹理贴图坐标系的链接也将受到赞赏。我并没有真正理解应该如何从 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);

唯一的问题是,这些看起来像是一个重大的黑客攻击。这是官方的还是可接受的解决方案?

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

橘香 2024-12-10 11:44:56

将纹理视为橡胶板。纹理的左下角(不是像素)位于 (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 投影矩阵并不是什么不能碰的神圣数据。实际上,只要您认为有必要使事情变得更容易,您就应该对其进行修改。改变矩阵很便宜。这同样适用于视口。它们只是一组几乎可以自由设置的寄存器(就着色器而言,它们被称为制服)。

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.

策马西风 2024-12-10 11:44:56

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

例如,绘制一个 10px x 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)

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)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文