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

Eal*_*ann 2 glsl compute-shader vulkan

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

  • 颜色在 UniformBuffer 的 uint 数组中进行索引。
  • 该 UBO 中的一种颜色封装在一个 uint 中,如 {0-255, 0-255, 0-255, 0-255}。

这里是代码:

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));
}
Run Code Online (Sandbox Code Playgroud)

我想清理/优化一下,因为这种颜色转换在着色器中看起来很糟糕/无用(并且应该预先计算)。我的问题是:

  • 是否可以直接vec4(r, g, b, 0.0)在UBO内打包a,使用4个字节(如R8G8B8A8)?

Nic*_*las 6

直接做可以吗?不。

但 GLSL 确实有许多用于打包/解包标准化值的函数。在您的情况下,您可以将该值作为 single 传递uint uniform,然后用于unpackUnorm4x8将其转换为vec4. 所以你的代码变成:

    vec4 color = unpackUnorm4x8(material.rgb);
Run Code Online (Sandbox Code Playgroud)

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

  • 解包并不总是免费的,因此除非您确实需要节省空间,否则请上传 4 个浮点数。 (3认同)