(怎么样)标量可以转换为另一个标量而不用GLSL转换?

时间:2012-11-28 13:57:02

标签: opengl casting glsl

(如何)可以在没有转换的情况下将标量转换为另一个标量?

这个问题中使用的“强制转换”的定义是在不改变数据本身的情况下改变对完全相同数据的解释,假设两种类型具有相同的位数。即(浮动)B00101111 == B00101111

这个问题中使用的“转换”的定义是改变数据的解释以及将所述数据重新格式化为原始值的某些数学近似,即(float)1 == 1.0

5.4.3 GLSL 4.30.6规范意味着标量float-to-int和int-to-float构造函数仅执行转换: “当构造函数用于将任何浮点类型转换为整数类型时,小数部分 浮点值被删除。“ - 第87页

棺材中的另一个钉子是5.1节上的这条线,pg。 85: “没有类型转换运算符;而是使用构造函数。”

目标是使用Buffer-Texture / Texture-Buffer和texelFetch(...)来获取float vec4s(128bit)并填充结构,例如:

struct MyStruct
{
int foo; //32bit
float bar; //32bit
int baz; //32bit
short blah; //16bit
short hmm; //16bit
} // 128bit total

...但是很难确定如何将vec4分解为二进制子块并重新构建它们以设置所述结构值。

以下理论是否有效?

MyStruct myUuberChunk = MyStruct(myVec4);

使用float vec4s(或int vec4s)背后的理由是正确的,是为了带宽性能而将所有值都放在一个128位的读取中(大多数卡有4个32位内存总线)。

2 个答案:

答案 0 :(得分:6)

  

以下理论是否有效?

没有

GLSL不允许您直接重新解释结构。虽然GLSL(3.30+)确实保证整数和浮点数是32位,但你不能只使用vec4并假装它是其他东西。

然而,OpenGL 3.3+确实允许您重新解释单个标量值。首先,您的代码应该使用整数缓冲区纹理,而不是浮点纹理。这只是为了防止texel提取逻辑在非元化值,NaN或其他浮点奇数的情况下做一些不愉快的事情。

因此,您应该使用usamplerBuffer并返回uvec4

要获得实际值,您必须进行位重新解释,由适当的库函数提供:

struct Data
{
  int first;
  float value;
  int second;
  int half1;
  int half2;
};

Data UnpackStruct(uvec4 packed)
{
  Data ret;
  ret.first = int(packed[0]); //Sign bit is preserved, per GLSL standard.
  ret.value = uintBitsToFloat(packed[1]);
  ret.second = int(packed[2]);
  ret.half1 = (packed[3] >> 16) & 0x0000FFFF;
  ret.half2 = packed[3] & 0x0000FFFF;
  return ret;
}

答案 1 :(得分:0)

您可以使用Bitwise operations解码\编码值,尤其是位移。有用的链接12