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

时间:2019-05-02 07:34:12

标签: glsl vulkan compute-shader

我尝试优化一个有效的计算着色器。其目的是创建图像:找到良好的颜色(使用一个小的调色板),然后调用imageStore(image, ivec2, vec4)

  • 在uint数组中,在UniformBuffer中对颜色进行索引。
  • 此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));
}

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

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

2 个答案:

答案 0 :(得分:4)

是否可以直接这样做?不。

但是GLSL确实有许多用于打包/解包标准化值的功能。在您的情况下,您可以将值作为单个uint uniform传递,然后使用unpackUnorm4x8将其转换为vec4。因此您的代码变为:

    vec4 color = unpackUnorm4x8(material.rgb);

这当然是内存与性能的折衷。因此,如果内存不是问题,则应该直接传递vec4never use vec3)。

答案 1 :(得分:0)

  

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

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

但是,为什么您认为需要这样做?只需将其上传为4个浮动元素-这是一个统一的样式,因此就好像您没有将其复制数千次一样,因此在实践中增加大小不会成为问题。