Geometry Shader中需顶点着色器显式输出法线(如out vec3 vNormal),几何着色器以in vec3 vNormal[]接收;生成法线可视化线段时,对每个输入顶点发射两个顶点:起点为原位置,终点沿归一化法线方向延伸,须确保空间一致性且max_vertices足够。

Geometry Shader 里怎么接收顶点并输出法线方向
几何着色器不能直接读取顶点着色器的输出变量(比如 normal),必须显式传递。你得在顶点着色器里把世界空间法线(或视图空间)用 out 变量传给几何着色器,且类型要匹配:几何着色器输入必须是 in vec3 normal[](数组,因为一个图元有多个顶点)。常见错误是只传了位置没传法线,或者忘了加 [] 导致编译失败。
关键点:
- 顶点着色器中用
out vec3 vNormal;,并在main()里赋值(建议转到世界空间:vNormal = normalize(mat3(model) * aNormal);) - 几何着色器声明输入为
in vec3 vNormal[];,对应layout(triangles) in;或layout(lines) in; - 若用
glVertexAttribPointer传了法线,但顶点着色器没转发,几何着色器收不到——它只收前一级着色器明确out的东西
用 Geometry Shader 生成毛发线段的实际写法
毛发本质是沿法线方向延伸的短线段。几何着色器对每个输入图元(比如一个三角形)发射多条线段(layout(line_strip, max_vertices = 2) out;),每条线段两个顶点:起点在原始顶点位置,终点 = 起点 + 法线 × 长度。
典型结构:
立即学习“C++免费学习笔记(深入)”;
layout(triangles) in;
layout(line_strip, max_vertices = 2) out;
<p>in vec3 vNormal[];
in vec3 vPosition[];</p><p>void main() {
for (int i = 0; i < 3; i++) { // 对三角形每个顶点生成一根毛
vec3 pos = vPosition[i];
vec3 norm = normalize(vNormal[i]);
float len = 0.05; // 毛长,可随顶点属性或 uniform 控制</p><pre class="brush:php;toolbar:false;"> gl_Position = gl_in[i].gl_Position;
EmitVertex();
gl_Position = gl_in[i].gl_Position + vec4(norm * len, 0.0);
EmitVertex();
EndPrimitive();
}}
注意:gl_in[i].gl_Position 是裁剪空间坐标,直接加法线会错——必须确保 vNormal 和 vPosition 在同一空间(推荐全用世界空间,再由顶点着色器统一乘 projection * view)。
为什么毛发看起来断断续续或朝向混乱
根本原因通常是法线未归一化、空间不一致,或几何着色器未正确处理图元拓扑。常见现象和解法:
- 毛发长度随视角缩放:用了视图空间法线但没在顶点着色器中用
mat3(view)转换,导致法线被非均匀缩放 - 毛发从面中心射出而非顶点:误把
gl_in[0].gl_Position当作整个图元中心,实际应遍历i = 0..2 - 部分毛发消失:
max_vertices设太小(如设为 2 但循环 3 次 × 2 点 = 6 点,超出限制则静默截断) - 线段不显示:确认启用了
glEnable(GL_PROGRAM_POINT_SIZE)?不,那是点;毛发是线,要确保glLineWidth()有效(注意 macOS / WebGL 不支持)且深度测试/剔除没误杀
性能和替代方案的现实约束
Geometry Shader 每个输入图元都触发一次调用,生成大量新顶点(1 个三角形 → 3 根毛 × 2 点 = 6 点),GPU 压力陡增。10 万三角形模型可能瞬时产生百万级线段,在中低端 GPU 上帧率骤降。
更可行的做法:
- 只对 selected mesh 或 low-poly proxy 使用 GS 生成毛发,高模用纹理法线+曲面细分替代
- 改用
glDrawArraysInstanced+ 顶点着色器:把毛发偏移逻辑移到 VS,用gl_InstanceID索引毛发样本,避免 GS 分支和发射开销 - 真正生产级毛发系统(如 TressFX)完全绕过 GS,用 compute shader + 附加纹理存储毛发曲线,VS 只做采样渲染
Geometry Shader 做毛发适合教学或简单演示,一旦需要密度、碰撞、动画,它立刻成为瓶颈。别等卡成幻灯片才回头重构。


















