OpenGL:如何通过vec4动态生成纹理坐标?
解决方案:通过Uniform生成纹理坐标
一、优先在顶点着色器中计算
推荐在顶点着色器里生成纹理坐标,原因有两个:
- 顶点着色器每个顶点只执行一次,计算量远小于片元着色器(片元是每个像素都要计算),性能更优;
- GPU会自动对顶点输出的纹理坐标做线性插值,最终效果和原来顶点携带纹理坐标的方式完全一致。
二、具体实现代码
1. 修改顶点着色器
利用顶点的位置坐标(范围是[-0.5, 0.5]),映射到Uniform传入的纹理坐标区间s0~s1、t0~t1:
#version 330 core layout (location = 0) in vec3 aPos; out vec2 tex_coord; uniform vec4 tex_bounds; // 对应传入的 s0, t0, s1, t1 void main() { gl_Position = vec4(aPos, 1.0); // 将顶点x坐标从[-0.5,0.5]映射到[s0,s1] float s = tex_bounds.x + (aPos.x + 0.5) * (tex_bounds.z - tex_bounds.x); // 将顶点y坐标从[-0.5,0.5]映射到[t1,t0](OpenGL纹理y轴从下到上,和顶点y方向相反) float t = tex_bounds.w + (0.5 - aPos.y) * (tex_bounds.y - tex_bounds.w); tex_coord = vec2(s, t); }
2. 片元着色器无需改动
直接使用顶点着色器传递过来的纹理坐标采样即可:
#version 330 core out vec4 frag_color; in vec2 tex_coord; uniform sampler2D texture; void main() { frag_color = texture(texture, tex_coord); }
3. CPU端Uniform传递
保持你原来的调用逻辑,注意参数顺序对应顶点着色器的tex_bounds:
glUniform4f(glGetUniformLocation(shader, "tex_bounds"), s0, t0, s1, t1);
三、纹理图集的应用方式
用这套方案渲染多个图标时,只需:
- 共用同一个仅含位置数据的顶点缓冲区;
- 对每个图标,计算它在纹理图集中的边界坐标
s0,t0,s1,t1(即图标的左上角、右下角纹理坐标); - 绑定纹理图集,设置对应
tex_bounds的Uniform,然后调用绘制接口渲染四边形即可。
这种方式能大幅减少顶点数据冗余,提升批量图标的渲染效率。
内容的提问来源于stack exchange,提问作者Prashant
相关产品推荐
相关产品推荐

