本文主要是介绍GLSL中的std140注意事项,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、关于bool的注意事项
以下是笔者在学习OpenGL相关内容时遇到的问题
struct UniformBufferObject {alignas(16) igm::vec3 viewPos;alignas(4) bool useColor;
};
这是我在C++程序中声明的一个UBO,对应于着色器中的:
layout(std140, binding = 1) uniform UniformBufferObject {vec3 viewPos;bool useColor;
} ubo;
我在C++程序中给声明的UBO进行赋值,也就是
UniformBufferObject ubo;
ubo.viewPos = igm::vec3(1.0f);
ubo.useColor = false;
但是这段代码在实际运行中并不能得到正确的答案,原因就在于笔者对C++的alignas(4)用法不熟悉
首先先看GLSL中的std140布局规则(以下内容引用自LearnOpenGL)
类型 布局规则 标量,比如int和bool 每个标量的基准对齐量为N 向量 2N或者4N。这意味着vec3的基准对齐量为4N 标量或向量的数组 每个元素的基准对齐量与vec4的相同 矩阵 储存为列向量的数组,每个向量的基准对齐量与vec4的相同 结构体 等于所有元素根据规则计算后的大小,但会填充到vec4大小的倍数 std140布局规则的对齐偏移量实例
layout (std140) uniform ExampleBlock {// 基准对齐量 // 对齐偏移量float value; // 4 // 0 vec3 vector; // 16 // 16 (必须是16的倍数,所以 4->16)mat4 matrix; // 16 // 32 (列 0)// 16 // 48 (列 1)// 16 // 64 (列 2)// 16 // 80 (列 3)float values[3]; // 16 // 96 (values[0])// 16 // 112 (values[1])// 16 // 128 (values[2])bool boolean; // 4 // 144int integer; // 4 // 148 };
因此可以知道,我们的UBO占用16个字节,在我们C++的处理中确实可以让struct UniformBufferObject
对齐到16字节,通过std::cout << sizeof(UniformBufferObject) << std::endl;
得到16就是一个验证。
layout(std140, binding = 1) uniform UniformBufferObject {// 基准对齐量 // 对齐偏移量vec3 viewPos; // 16 // 0bool useColor; // 4 // 12
} ubo;
但最重要的是struct UniformBufferObject
中的alignas(4) bool useColor;
,由于bool类型在C++中只占一个字节,如果我们对useColor
进行赋值时只会对alignas(4)
对齐到的4字节的第一个字节进行赋值,后续三个字节是由C++进行随机填充的,用以下代码就可以查看ubo中的字节码
struct UniformBufferObject {alignas(16) igm::vec3 viewPos;alignas(4) bool useColor;
};UniformBufferObject ubo;
ubo.viewPos = igm::vec3(1.0f);
ubo.useColor = false;// Convert the struct pointer to char pointer
char* bytes = reinterpret_cast<char*>(&ubo);// Print bytes in hexadecimal format
std::cout << "Byte representation of ubo:" << std::endl;
for (size_t i = 0; i < sizeof(ubo); ++i) {std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(bytes[i]) << " ";
}
std::cout << std::endl;
输出结果为:
Byte representation of ubo:
00 00 ffffff80 3f 00 00 ffffff80 3f 00 00 ffffff80 3f 00 ffffffcc ffffffcc ffffffcc
可以看到对齐到四字节的bool类型最终字节码为00 ffffffcc ffffffcc ffffffcc
,也就是说,当该串字节传入GLSL时,最后四字节的表示不等于0
,因此也就不为false
,由于GLSL基于std140的解释会将bool类型的四个字节合到一起进行解释,因此我们需要对四个字节一起进行赋值,一个简单的办法就是alignas(4) bool useColor;
更改为alignas(4) int useColor;
,我们在C++中也将四个字节当作一个整体进行赋值,这样就能保证GLSL中四个字节所解释成的bool类型为正确的数值,重新运行上诉代码
输出结果为:
Byte representation of ubo:
00 00 ffffff80 3f 00 00 ffffff80 3f 00 00 ffffff80 3f 00 00 00 00
由此保证了C++中的数据与GLSL中的数据的解释一致性。
这篇关于GLSL中的std140注意事项的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!