使用布局在几何着色器中传递顶点属性的问题排查
问题分析:几何着色器传递顶点属性失败的原因
你遇到的问题出在两个关键错误上,下面逐一说明:
原着色器代码
顶点着色器
#version 410 layout (location = 0) in vec2 pos; layout (location = 1) in vec2 size; layout (location = 2) in float rot; layout (location = 3) in vec4 color; layout (location = 0) out vec2 p; layout (location = 1) out vec2 s; layout (location = 2) out float r; layout (location = 3) out vec4 c; void main(){ gl_Position = vec4(pos,0.0,1.0); p = pos; s = size; r = rot; c = color; }
几何着色器(错误版本)
#version 410 layout (points) in; layout (triangle_strip, max_vertices = 4) out; layout (location = 0) in vec2 pos; layout (location = 1) in vec2 size; layout (location = 2) in float rot; layout (location = 3) in vec4 color; layout (location = 0) out vec2 p; layout (location = 1) out vec2 s; layout (location = 2) out float r; layout (location = 3) out vec4 c; void main() { gl_Position = gl_in[0].gl_Position + vec4(-0.2, -0.2, 0.0, 0.0); // 1:bottom-left EmitVertex(); gl_Position = gl_in[0].gl_Position + vec4( 0.2, -0.2, 0.0, 0.0); // 2:bottom-right EmitVertex(); gl_Position = gl_in[0].gl_Position + vec4(-0.2, 0.2, 0.0, 0.0); // 3:top-left EmitVertex(); gl_Position = gl_in[0].gl_Position + vec4( 0.2, 0.2, 0.0, 0.0); // 4:top-right EmitVertex(); EndPrimitive(); p = pos; s = size; r = rot; c = color; }
片段着色器
#version 410 layout (location = 0) in vec2 pos; layout (location = 1) in vec2 size; layout (location = 2) in float rot; layout (location = 3) in vec4 color; out vec4 FragColor; void main() { FragColor = color; }
错误原因与修正方案
1. 几何着色器输入变量类型错误
几何着色器的输入是整个图元的顶点属性数组,哪怕是points类型(每个图元仅1个顶点),输入变量也必须定义为数组形式。原代码中直接用单个变量vec2 pos,会导致无法正确读取顶点着色器传递的属性值。
修正:把输入变量改成数组,比如:
layout (location = 0) in vec2 pos[]; layout (location = 1) in vec2 size[]; layout (location = 2) in float rot[]; layout (location = 3) in vec4 color[];
读取时通过索引[0]获取当前点的数据,比如pos[0]。
2. 输出变量赋值时机错误
EmitVertex()会立即记录当前所有输出变量的状态来生成新顶点。原代码中在所有EmitVertex()执行完才给输出变量赋值,导致四个顶点的输出属性都是未定义的垃圾值,片段着色器无法拿到正确的color,所以显示黑色。
修正:在每次EmitVertex()之前赋值输出变量(或者在设置gl_Position后立即赋值),确保每个新顶点都携带正确的属性数据。
修正后的几何着色器
#version 410 layout (points) in; layout (triangle_strip, max_vertices = 4) out; // 修正1:输入变量改为数组 layout (location = 0) in vec2 pos[]; layout (location = 1) in vec2 size[]; layout (location = 2) in float rot[]; layout (location = 3) in vec4 color[]; layout (location = 0) out vec2 p; layout (location = 1) out vec2 s; layout (location = 2) out float r; layout (location = 3) out vec4 c; void main() { // 先取出当前点的属性值,避免重复写索引 vec2 current_pos = pos[0]; vec2 current_size = size[0]; float current_rot = rot[0]; vec4 current_color = color[0]; // 顶点1:bottom-left gl_Position = gl_in[0].gl_Position + vec4(-0.2, -0.2, 0.0, 0.0); p = current_pos; s = current_size; r = current_rot; c = current_color; EmitVertex(); // 顶点2:bottom-right gl_Position = gl_in[0].gl_Position + vec4( 0.2, -0.2, 0.0, 0.0); p = current_pos; s = current_size; r = current_rot; c = current_color; EmitVertex(); // 顶点3:top-left gl_Position = gl_in[0].gl_Position + vec4(-0.2, 0.2, 0.0, 0.0); p = current_pos; s = current_size; r = current_rot; c = current_color; EmitVertex(); // 顶点4:top-right gl_Position = gl_in[0].gl_Position + vec4( 0.2, 0.2, 0.0, 0.0); p = current_pos; s = current_size; r = current_rot; c = current_color; EmitVertex(); EndPrimitive(); }
额外说明
如果不需要在几何着色器中修改这些属性,也可以让GLSL自动匹配变量名,但显式用location绑定更可靠,避免编译器匹配错误。
内容的提问来源于stack exchange,提问作者bamia
相关产品推荐
相关产品推荐

