GLSL信道选择

GLSL信道选择,glsl,shader,Glsl,Shader,我有一个GLSL着色器,它从输入纹理的一个通道(例如R)读取,然后写入输出纹理中的同一通道。此频道必须由用户选择 我现在能想到的就是使用一个int统一和大量的if语句: uniform sampler2D uTexture; uniform int uChannelId; varying vec2 vUv; void main() { //read in data from texture vec4 t = texture2D(uTexture, vUv); floa

我有一个GLSL着色器,它从输入纹理的一个通道(例如R)读取,然后写入输出纹理中的同一通道。此频道必须由用户选择

我现在能想到的就是使用一个int统一和大量的if语句:

uniform sampler2D uTexture;
uniform int uChannelId;
varying vec2 vUv;

void main() {

    //read in data from texture
    vec4 t = texture2D(uTexture, vUv);
    float data;
    if (uChannelId == 0) {
        data = t.r;
    } else if (uChannelId == 1) {
        data = t.g;
    } else if (uChannelId == 2) {
        data = t.b;
    } else {
        data = t.a;
    }

    //process the data...
    float result = data * 2;  //for example

    //write out
    if (uChannelId == 0) {
        gl_FragColor = vec4(result, t.g, t.b, t.a);
    } else if (uChannelId == 1) {
        gl_FragColor = vec4(t.r, result, t.b, t.a);
    } else if (uChannelId == 2) {
        gl_FragColor = vec4(t.r, t.g, result, t.a);
    } else {
        gl_FragColor = vec4(t.r, t.g, t.b, result);
    }

}
有没有什么方法可以像查字典一样,比如
t[uChannelId]

或者我应该有4个相同着色器的不同版本,每个版本处理不同的通道,这样我就可以避免所有if语句了

最好的方法是什么


编辑:更具体地说,我使用的是WebGL(Three.js)

有这样一种方法,它和你在问题中实际写的一样简单。只需使用
t[channelId]
。引用(这来自版本3.30第5.5节,但也适用于其他版本):

数组下标语法也可以应用于向量,以提供数字索引。所以在

vec4位

pos[2]
表示pos的第三个元素,相当于pos.z。这允许将变量索引到 向量,以及访问组件的通用方法。任何整数表达式都可以用作 下标。第一个组件位于索引0处。使用常数读取或写入向量 值为负值或大于等于向量大小的整数表达式是非法的。 使用非常量表达式进行索引时,如果索引为负或更大,则行为未定义 大于或等于向量的大小

请注意,对于代码的第一部分,您可以使用它访问纹理的特定通道。您还可以使用该功能。在这种情况下,您只需要使用一个fxied通道,比如说
r
,来访问着色器中的纹理通道,并切换实际纹理通道,以便您想要访问的任何通道都变成
r


更新:由于目标平台是webgl,因此这些建议不可用。然而,一个简单的解决方案是使用
vec4
统一标准代替
uChannelID
,该标准对所选组件为1.0,对所有其他组件为0.0。假设此变量名为
uChannelSel
。第一部分可以使用
data=dot(t,uChannelSel)
,第二部分可以使用
gl\u FragColor=(vec4(1.0)-uChannelSel)*t+uChannelSel*result

我确信,着色器中的分支可能会很昂贵。然而,听起来好像在一个过程中总是同一个通道(是吗?),因此您可能会保持足够的内聚性以看到良好的性能


自从我使用GLSL已经有一段时间了,但是如果你使用的是更新的版本,也许你可以做一些位移位(>)魔术?您可以将纹理读取为int而不是vec4,然后根据要读取的通道将其移位若干位。

我尝试了t[channelId],但出现了以下错误:索引表达式必须是常量。如何解决这个常量值问题?哇,ARB_texture_swizzle功能看起来真的很有用。我现在正在使用WebGL,让我检查一下这个扩展是否可用…@skeelogy:好的,你应该提到你使用WebGL。在这种情况下,ARB_texture_swizzle不可用(iirc),矢量的[]操作符也不会帮助您(如您所见)。对不起,我没有一个好的平台解决方案。很抱歉。我已经编辑了我的问题,包括我正在使用WebGL。不管怎样,我从你那里学到了一些新东西,谢谢@我想出了另一个想法并更新了我的答案。这听起来像是值得测试的东西。我试试看它是否管用。