着色器将 uint8 转换为浮动,并将其重新解释回 uint

Posted

技术标签:

【中文标题】着色器将 uint8 转换为浮动,并将其重新解释回 uint【英文标题】:Shaders casting uint8 to float, and reinterpretting it back to uint 【发布时间】:2019-11-17 09:03:46 【问题描述】:

我有一个顶点属性被我的着色器非常奇怪地咀嚼。它以(uint8)1 的形式上传到VBO,但是当片段着色器看到它时,它被解释为106535321600x3F800000,你们中的一些人可能会将其识别为浮点中1.0f 的位模式。

我不知道为什么?我可以确认它以 1 (0x00000001) 的形式上传到 VBO。

顶点属性定义为:

struct Vertex
    ...
    glm::u8vec4 c2; // attribute with problems
;
// not-normalized
glVertexAttribPointer(aColor2, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, c2));

虽然着色器具有与该属性绑定的属性

glBindAttribLocation(programID, aColor2, "c2");

顶点着色器非常顺利地通过属性:

#version 330
in lowp uvec4 c2; // <-- this value is uploaded to the VBO as 0x00, 0x00, 0x00, 0x01;
flat out lowp uvec4 indices;

void main()
    indices = c2;

最后片段着色器得到了它:

flat in lowp uvec4 indices; // <-- this value is now 0, 0, 0, 0x3F800000
out lowp vec4 fragColor;
void main()
    fragColor = vec4(indices) / 256.0;

根据我的着色器检查器,indices 变化将顶点着色器作为 0x3F800000 用于 indices.w,所以那里发生了一些奇怪的事情?这可能是什么原因造成的?

【问题讨论】:

【参考方案1】:

如果顶点属性的类型是整数,那么你必须使用glVertexAttribIPointer而不是glVertexAttribPointer(关注I)。见glVertexAttribPointer

glVertexAttribPointer 中指定的类型是源缓冲区中数据的类型,并没有指定着色器中的目标属性类型。如果使用glVertexAttribPointer,那么shader程序中属性的类型就假设为浮点数,转换成整数数据。 如果您使用glVertexAttribIPointer,那么这些值将保留为整数值。

【讨论】:

哦,那是被****了......我永远不会怀疑100年后,谢谢 @AnneQuinn 我第一次使用积分属性时遇到了同样的问题。不客气。

以上是关于着色器将 uint8 转换为浮动,并将其重新解释回 uint的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中浮动的 Uint8 数组 [重复]

将 datetime 转换为 Unix 时间戳并将其转换回 python

将 Sampler2D 与着色器一起使用的问题

c_cpp 将IP地址转换为整数并将其转换回c

如何在 ARM NEON 中将 uint8x8_t 加载到 float32x4 中?

C ++将字符串转换为无符号字符并将其转换回以获取字符串