使用像素坐标的 OpenGL 子图像
Posted
技术标签:
【中文标题】使用像素坐标的 OpenGL 子图像【英文标题】:OpenGL subimages using pixel coordinates 【发布时间】:2020-09-30 01:37:32 【问题描述】:我已经完成了 learnopengl.com 上的突破系列中的几个教程,所以我有一个非常简单的 2D 渲染器。不过,我想向它添加一个子图像功能,在这里我可以为一种“源矩形”指定一个 vec4,所以如果 vec4 是(10, 10, 32, 32)
,它只会渲染一个宽度为 10、10 的矩形和高度为 32,有点像 SDL 渲染器的工作原理。
渲染器的设置方式是有一个所有精灵都使用的四边形 VAO,其中包含纹理坐标。最初,我虽然可以为每个精灵使用一个 VAO 数组,每个精灵都有不同的纹理坐标,但我希望能够在精灵被绘制之前更改源矩形,以使动画之类的事情更容易......我的第二个想法是将一个单独的统一 vec4 传递到源矩形的片段着色器中,但是我如何仅在像素坐标中渲染该部分?
【问题讨论】:
问题解决了吗? 【参考方案1】:使用Primitiv 类型GL_TRIANGLE_STRIP
或GL_TRIANGLE_FAN
来渲染一个四边形。使用整数一维顶点坐标而不是浮点顶点坐标。顶点坐标是四边形角的索引。对于GL_TRIANGLE_FAN
,它们是:
vertex 1: 0
vertex 2: 1
vertex 3: 2
vertex 4: 3
在顶点着色器中设置矩形定义(10, 10, 32, 32) 使用Uniform 类型为vec4
的变量。有了这些信息,就可以在顶点着色器中计算顶点坐标了:
in int cornerIndex;
uniform vec4 rectangle;
void main()
vec2 vertexArray[4] =
vec2[4](rectangle.xy, rectangle.zy, rectangle.zw, rectangle.xw);
vec2 vertex = vertexArray[cornerIndex];
// [...]
Vertex Shader 提供内置输入gl_VertexID
,它指定当前正在处理的顶点的索引。在这种情况下,可以使用此变量代替 cornerIndex
。请注意,顶点着色器不需要任何显式输入。
【讨论】:
【参考方案2】:我最终在顶点着色器中执行此操作。我将vec4
作为统一传递给顶点着色器,以及图像的大小,并使用以下计算:
// convert pixel coordinates to vertex coordinates
float widthPixel = 1.0f / u_imageSize.x;
float heightPixel = 1.0f / u_imageSize.y;
float startX = u_sourceRect.x, startY = u_sourceRect.y, width = u_sourceRect.z, height = u_sourceRect.w;
v_texCoords = vec2(widthPixel * startX + width * widthPixel * texPos.x, heightPixel * startY + height * heightPixel * texPos.y);
v_texCoords 是片段着色器用来映射纹理的变量。
【讨论】:
以上是关于使用像素坐标的 OpenGL 子图像的主要内容,如果未能解决你的问题,请参考以下文章
初识OpenGL (-)纹理过滤(Texture Filtering)
初识OpenGL (-)纹理过滤(Texture Filtering)