GLSL顶点着色器复用方案:适配不同片段着色器的技术问询
顶点着色器复用与着色器配对问题
现有着色器情况
Vector Shader(顶点着色器)
#version 330 core layout (location = 0) in vec4 values; layout (location = 1) in vec4 rect; layout (location = 2) in int depth; layout (location = 3) in float radians; layout (location = 4) in float effect; layout (std140) uniform Matrices { mat4 projection; mat4 view; }; out vec2 texCoord; void main() { vec2 transformed = vec2(values.xy * rect.zw*.5); //scale transformed = vec2(cos(radians)*transformed.x - sin(radians)*transformed.y,sin(radians)*transformed.x + cos(radians)*transformed.y); //rotate transformed += rect.xy + rect.zw*.5; //move gl_Position = projection*view*vec4(transformed,depth,1); texCoord = vec2(values.z,values.a); }
原Fragment Shader(片段着色器)
#version 330 core out vec4 fragColor; in vec2 texCoord; uniform sampler2D sprite; void main() { vec4 text = texture(sprite,texCoord); fragColor = text; }
Paint Shader(新增片段着色器)
#version 330 core //renders a sprite in a specific color out vec4 fragColor; in vec2 texCoord; in vec4 tint; uniform sampler2D sprite; void main() { vec4 text = texture(sprite,texCoord); if (text.w ==0) { fragColor = vec4(0); } else { fragColor = tint; } }
当前为适配Paint Shader,需维护一份几乎完全相同的顶点着色器(仅新增tint输入输出逻辑),后续修改成本高。需求为:找到无需维护两份顶点着色器的方案,并确认是否可用带tint输出的顶点着色器配合原Fragment Shader。
解决方案
1. 直接复用带tint输出的顶点着色器配合原Fragment Shader
完全可行。GLSL允许顶点着色器输出的变量在片段着色器中不被引用,驱动会自动忽略未使用的输出变量,不会引发编译错误或性能问题。你可以直接用这款带tint输出的顶点着色器同时搭配原Fragment Shader和Paint Shader,无需修改原片段着色器代码。
2. 使用预处理器宏实现单份顶点着色器适配两种场景
为彻底避免维护两份代码,可在顶点着色器中加入预处理器宏,控制tint相关逻辑的启用。修改后的顶点着色器代码如下:
#version 330 core layout (location = 0) in vec4 values; layout (location = 1) in vec4 rect; layout (location = 2) in int depth; layout (location = 3) in float radians; layout (location = 4) in float effect; #ifdef ENABLE_TINT layout (location = 5) in vec4 tint_; #endif layout (std140) uniform Matrices { mat4 projection; mat4 view; }; out vec2 texCoord; #ifdef ENABLE_TINT out vec4 tint; #endif void main() { vec2 transformed = vec2(values.xy * rect.zw*.5); //scale transformed = vec2(cos(radians)*transformed.x - sin(radians)*transformed.y,sin(radians)*transformed.x + cos(radians)*transformed.y); //rotate transformed += rect.xy + rect.zw*.5; //move gl_Position = projection*view*vec4(transformed,depth,1); texCoord = vec2(values.z,values.a); #ifdef ENABLE_TINT tint = tint_; #endif }
使用方式:
- 搭配原Fragment Shader时,编译顶点着色器不定义
ENABLE_TINT宏,此时着色器会自动剔除tint相关代码,功能与原Vector Shader完全一致。 - 搭配Paint Shader时,编译顶点着色器时定义
ENABLE_TINT宏(例如在OpenGL中通过编译参数添加#define ENABLE_TINT),此时着色器会包含tint的输入输出逻辑,适配Paint Shader需求。
这样只需维护一份顶点着色器代码,后续修改仅需在一处操作即可。
内容的提问来源于stack exchange,提问作者Ruglord
相关产品推荐
相关产品推荐

