You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

GLSL中能否将着色器变量同时声明为输入与输出以避免重命名?

回答

很遗憾,直接把同一个变量同时声明为inout是行不通的——GLSL的语法规则不允许全局变量同时拥有inout这两个互斥的存储限定符,而且如果你在全局作用域里分别声明in uint xy;out uint xy;,编译器会直接报重定义错误,因为同一个作用域里不能有同名变量。

不过,你有两种更简洁的方式来避免重命名的麻烦,让代码看起来更清爽:

1. 使用接口块(推荐方案)

接口块是GLSL里用来组织着色器间传递数据的好工具,它能让你在顶点着色器和几何着色器之间用统一的结构来传递数据,成员名字完全一致,相当于用一个“容器”来打包所有要传递的变量,不用一个个单独声明in/out

修改后的顶点着色器代码如下:

#version 330 core
layout (location = 0) in uint xy;
layout (location = 1) in uint znt;

// 定义输出接口块,名字可以自定义,比如这里叫VertexData
out VertexData {
    uint xy;
    uint znt;
} vs_out;

void main() {
    vs_out.xy = xy;
    vs_out.znt = znt;
}

然后在你的几何着色器里,用同名的接口块来接收数据:

#version 330 core
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;

// 同名的输入接口块,和顶点着色器的输出块对应
in VertexData {
    uint xy;
    uint znt;
} gs_in[];

void main() {
    // 举个例子,转发第一个顶点的数据
    gl_Position = /* 你的位置计算逻辑 */;
    // 访问接口块里的变量
    // 这里可以根据需要处理gs_in[gl_InvocationID].xy等数据
    EmitVertex();
    EndPrimitive();
}

这种方式的优势很明显:如果后续需要传递更多变量,只需要在接口块里添加成员即可,不用单独声明一堆in/out变量,代码结构更清晰。

2. 接受轻量重命名(简单直接)

如果你不想引入接口块,那继续用当前的重命名方式其实也完全没问题——这种输入变量名+out_前缀的写法是GLSL开发里的常规操作,编译器处理起来没有任何性能损耗,而且代码可读性也不差。

总结下来,虽然不能直接让同一个变量同时作为输入和输出,但用接口块可以很好地解决重命名的繁琐问题,推荐你尝试这种方案。

内容的提问来源于stack exchange,提问作者Mr. Smith

火山引擎 最新活动