You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用布局在几何着色器中传递顶点属性的问题排查

问题分析:几何着色器传递顶点属性失败的原因

你遇到的问题出在两个关键错误上,下面逐一说明:

原着色器代码

顶点着色器

#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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 11:30:59