我可以将 R8G8B8A8 放入 UBO 中,并将其用作 vec4 吗?

Can I put a R8G8B8A8 in a UBO, and use it as a vec4?

我尝试优化工作计算着色器。它的目的是创建一个图像:找到合适的颜色(使用一个小调色板),然后调用 imageStore(image, ivec2, vec4).

这里是代码:

struct Entry
{
    *some other data*
    uint rgb;
};

layout(binding = 0) uniform SConfiguration
{
    Entry materials[MATERIAL_COUNT];
} configuration;

void main()
{
    Entry material = configuration.materials[currentMaterialId];

    float r = (material.rgb >> 16) / 255.;
    float g = ((material.rgb & G_MASK) >> 8) / 255.;
    float b = (material.rgb & B_MASK) / 255.;

    imageStore(outImage, ivec2(gl_GlobalInvocationID.xy), vec4(r, g, b, 0.0));
}

我想 clean/optimize 一点,因为这种颜色转换在着色器中看起来 bad/useless(应该预先计算)。我的问题是:

Is it possible to directly pack a vec4(r, g, b, 0.0) inside the UBO, using 4 bytes (like a R8G8B8A8) ?

无法直接将其表示为 4 个单字节值;着色器中没有合适的数据类型可让您将其声明为字节类型。

但是,您认为您为什么需要这样做?只需将它作为 4 个浮点数上传 - 它是统一的,所以你不会复制它数千次,所以额外的大小在实践中不太可能成为问题。

可以直接做吗?号

但是 GLSL 确实有许多 packing/unpacking 标准化值的函数。在您的情况下,您可以将值作为单个 uint uniform 传递,然后使用 unpackUnorm4x8 将其转换为 vec4。所以你的代码变成:

    vec4 color = unpackUnorm4x8(material.rgb);

当然,这是内存与性能的权衡。因此,如果内存不是问题,您可能应该直接传递 vec4 ()。