【问题标题】:Wrapping texture co-ordinates on a variable-size quad?在可变大小的四边形上包装纹理坐标?
【发布时间】:2014-08-21 21:14:38
【问题描述】:

这是我的情况:我需要在屏幕上为我的游戏 Gui 绘制一个矩形。我真的不在乎这个矩形有多大或可能有多大,我希望能够处理任何情况。我现在的做法是存储一个仅包含一个非常基本的四边形的单个 VAO,然后我使用制服重新绘制这个四边形,以每次修改它在屏幕上的大小和位置。

VAO 包含 4 个vec4 顶点:

0, 0, 0, 0;
1, 0, 1, 0;
0, 1, 0, 1;
1, 1, 1, 1;

然后我把它画成GL_TRIANGLE_STRIP。每个顶点的 XY 是它的位置,ZW 是它的纹理坐标*。我将当前正在绘制的 gui 元素的矩形传递为uniform vec4,它像这样偏移顶点着色器中的顶点位置:

vertex.xy *= guiRect.zw;
vertex.xy += guiRect.xy;

然后我将顶点从屏幕像素坐标转换为 OpenGL NDC 坐标:

gl_Position = vec4(((vertex.xy / screenSize) * 2) -1, 0, 1);

这会将范围从[0, screenWidth | screenHeight] 更改为[-1, 1]


当我想做纹理包装时,我的问题就出现了。当我想拉伸纹理时,只需传递vTexCoord = vertex.zw; 就可以了,但不适用于包装。理想情况下,我想修改纹理坐标,使屏幕上的 1 个像素等于 gui 纹理中的 1 个纹素。在这个阶段,超越[0, 1] 的纹理坐标很好,实际上正是我正在寻找的。​​p>

我计划为我的 gui 纹理实现纹理图集,但管理适当子纹理的偏移和边界将在片段着色器中处理 - 就顶点着色器而言,我们的四边形使用一个实体纹理使用[0, 1] 坐标,并相应地换行。

*注意:我知道这种特殊的顶点格式对于这种特殊情况不一定有用,我可以使用vec2 vertices 代替。为方便起见,我对所有 2D 渲染都使用相同的顶点格式,而其他对象(即文本)实际上确实需要那些 ZW 组件。我以后可能会改变它。

TL/DR:给定屏幕大小、纹理大小和四边形的位置/大小,如何在顶点着色器中计算纹理坐标,使像素和纹素为 1: 1 封信函,带包装?

【问题讨论】:

  • 你甚至需要每个顶点的纹理坐标吗?您可以通过每个片段在世界空间中的位置来计算每个片段的纹理坐标。
  • 确实,在这一点上,这主要是出于懒惰,我在其他地方使用了相同的 Vertex2D 格式,它确实需要每个顶点的 texcoords。我可能会在未来某个时候更改此代码以使用vec2,但现在没有必要。

标签: c++ opengl user-interface textures glsl


【解决方案1】:

这是非常简单的数学运算:您只需要以某种方式关联这两个空间。你已经制定了一个允许你这样做的规则:一个窗口空间像素映射到一个纹素。 假设我们同时拥有vec2 screenSizevec2 texSize,它们是以像素/纹素为单位的非标准化尺寸。

我不能 100% 确定您到底想实现什么。缺少一些东西:您实际上没有指定纹理的来源。它应该总是在四边形的左下角吗?或者它应该只是在视口的左下角吗?我会在这里假设后者,但对于第一种情况应该很容易调整。

我们现在需要的是 x 和 y 中的 [-1,1]^2 NDC 到 s 和 t 的映射。让我们首先将其映射到 [0,1]^2。如果我们有,我们可以简单地将坐标乘以screenSize/texSize 以获得所需的效果。所以最后,你得到了

vec2 texcoords = ((gl_Position.xy * 0.5) + 0.5) * screenSize/texSize;

你当然已经隐式计算了(gl_Position.xy * 0.5) + 0.5) * screenSize,所以可以改为:

vec2 texcoords = vertex.xy / texSize;

【讨论】:

  • 非常感谢!我确实忘记提及它,但是是的,我确实希望纹理的原点位于四边形的左下角。要进行调整,我是否只需使用texcoords += gl_Position.xy;
  • @HaydnV.Harach:差不多。 texcoords 在 [0,1] 空间中,gl_Position 在 [-1,1] 中,因此您必须对此进行更正。但你可以简单地早点考虑到这一点。实际上,您已经计算过了。您可以使用以下操作序列:vertex.xy *= guiRect.zw; vec2 texcoords = vertex.xy / texSize; vertex.xy += guiRect.xy;。请注意,在这两个步骤“中间”,您的原点正是您想要的位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多