简体   繁体   English

C++ 将 4 位 int_8t 转换为正常的 integer(32 位)

[英]C++ Bitshift 4 int_8t into a normal integer (32 bit )

I had already asked a question how to get 4 int8_t into a 32bit int, I was told that I have to cast the int8_t to a uint8_t first to pack it with bitshifting into a 32bit integer.我已经问过如何将 4 int8_t 转换为 32 位 int 的问题,有人告诉我必须先将 int8_t 转换为 uint8_t,然后通过位移将其打包为 32 位 integer。

int8_t offsetX = -10;
int8_t offsetY = 120;
int8_t offsetZ = -60;

using U = std::uint8_t;
int toShader  = (U(offsetX) << 24) | (U(offsetY) << 16) | (U(offsetZ) << 8) | (0 << 0);

std::cout << (int)(toShader >> 24) << " "<< (int)(toShader >> 16) << " " << (int)(toShader >> 8) << std::endl;

My Output is我的 Output 是

-10 -2440 -624444 -10 -2440 -624444

It's not what I expected, of course, does anyone have a solution?当然,这不是我所期望的,有没有人有解决办法?

In the shader I want to unpack the int16 later and that is only possible with a 32bit integer because glsl does not have any other data types.在着色器中,我想稍后解压 int16,这只能使用 32 位 integer,因为 glsl 没有任何其他数据类型。

 int offsetX = data[gl_InstanceID * 3 + 2] >> 24;
 int offsetY = data[gl_InstanceID * 3 + 2] >> 16 ;
 int offsetZ = data[gl_InstanceID * 3 + 2] >> 8 ;

What is written in the square bracket does not matter it is about the correct shifting of the bits or casting after the bracket.方括号中写的内容无关紧要,它是关于位的正确移动或括号后的转换。

If any of the offsets is negative, then the shift results in undefined behaviour.如果任何偏移量为负,则移位会导致未定义的行为。

Solution: Convert the offsets to an unsigned type first.解决方案:先将偏移量转换为无符号类型。

However, this brings another potential problem: If you convert to unsigned , then negative numbers will have very large values with set bits in most significant bytes, and OR operation with those bits will always result in 1 regardless of offsetX and offsetY .然而,这带来了另一个潜在问题:如果转换为unsigned ,那么负数将具有非常大的值,并且在最高有效字节中设置位,并且与这些位进行 OR 运算将始终得到 1,而不管offsetXoffsetY A solution is to convert into a small unsigned type ( std::uint8_t ), and another is to mask the unused bytes.一个解决方案是转换成一个小的无符号类型( std::uint8_t ),另一个是屏蔽未使用的字节。 Former is probably simpler:前者可能更简单:

using U = std::uint8_t;
int third  = U(offsetX) << 24u
           | U(offsetY) << 16u
           | U(offsetZ) << 8u
           | 0u         << 0u;

I think you're forgetting to mask the bits that you care about before shifting them.我认为您忘记在移动之前屏蔽您关心的位。

Perhaps this is what you're looking for:也许这就是您要找的:

int32 offsetX = (data[gl_InstanceID * 3 + 2] & 0xFF000000) >> 24;
int32 offsetY = (data[gl_InstanceID * 3 + 2] & 0x00FF0000) >> 16 ;
int32 offsetZ = (data[gl_InstanceID * 3 + 2] & 0x0000FF00) >> 8 ;
if (offsetX & 0x80) offsetX |= 0xFFFFFF00;
if (offsetY & 0x80) offsetY |= 0xFFFFFF00;
if (offsetZ & 0x80) offsetZ |= 0xFFFFFF00;

Without the bit mask, the X part will end up in offsetY , and the X and Y part in offsetZ .如果没有位掩码,X 部分将在offsetY中结束,而 X 和 Y 部分将在offsetZ中结束。

on CPU side you can use union to avoid bit shifts and bit masking and branches...在 CPU 端,您可以使用 union 来避免移位、位掩码和分支……

int8_t x,y,z,w; // your 8bit ints
int32_t i;      // your 32bit int

union my_union  // just helper union for the casting
 {
 int8_t i8[4];
 int32_t i32; 
 } a;

// 4x8bit -> 32bit
a.i8[0]=x;
a.i8[1]=y;
a.i8[2]=z;
a.i8[3]=w;
i=a.i32;

// 32bit -> 4x8bit
a.i32=i;
x=a.i8[0];
y=a.i8[1];
z=a.i8[2];
w=a.i8[3];

If you do not like unions the same can be done with pointers...如果你不喜欢联合,同样可以用指针来完成......

Beware on GLSL side is this not possible (nor unions nor pointers) and you have to use bitshifts and masks like in the other answer...当心 GLSL 方面这是不可能的(也不是联合或指针),你必须像其他答案一样使用位移和掩码......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM