2

(如何)可以将一个标量转换为另一个标量而不在 GLSL 中进行转换?

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

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

GLSL 4.30.6 规范的 5.4.3 暗示标量 float-to-int 和 int-to-float 构造函数只执行转换: “当构造函数用于将任何浮点类型转换为整数类型时,小数部分浮点值被丢弃。” - pg。87

棺材上的另一个钉子是第 5.1 节中的这条线,第 页。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 位获取中获取所有值(大多数卡有四个 32 位内存总线)。

4

2 回答 2

6

Would the following, in theory work?

No.

GLSL does not allow you to directly reinterpret structures. While GLSL (3.30+) does guarantee that integers and floats are 32-bits, you can't just take a vec4 and pretend that it's something else.

However, OpenGL 3.3+ does allow you to reinterpret individual scalar values. First, your code should use an integer buffer texture, not a floating-point one. That's just to prevent the texel fetch logic from doing something unpleasant in the case of denomralized values, NaN, or other floating-point oddities.

Thus, you should be using a usamplerBuffer and getting back a uvec4.

To get the actual values, you have to do bit reinterpretation, provided by appropriate library functions:

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;
}
于 2012-11-28T15:40:57.600 回答
0

您可以使用按位运算来解码\编码值,尤其是位移。有用的链接1 , 2

于 2012-11-28T14:14:44.913 回答