1
\$\begingroup\$

Can I pack 4 grayscale textures into one channel by converting the textures into uints and packing them?

uint b1 = (t1.r * 255 & mask1) << 0;
uint b2 = (t2.r * 255 & mask2) << 8;
uint b3 = (t3.r * 255 & mask3) << 16;
uint b4 = (t4.r * 255 & mask4) << 24;
t.r = b1 | b2 | b3 | b4;

"mask#" is a uint with 1s for #th byte and 0s for all other bytes. "t#" is a grayscale texture. "t" is the texture we are packing into.

My main concern is that t.r is a float, and I'm not allowed to access the bits.

\$\endgroup\$
8
  • \$\begingroup\$ Which graphics API and shader language are you using? That may affect what your options are. \$\endgroup\$
    – Kevin Reid
    Commented Jan 18, 2023 at 22:00
  • \$\begingroup\$ can you post your shader code ? \$\endgroup\$
    – TimChang
    Commented Jan 19, 2023 at 2:33
  • \$\begingroup\$ I thought single color channel only have single byte data . so maybe no , can not save 4 byte data in a single byte. \$\endgroup\$
    – TimChang
    Commented Jan 19, 2023 at 2:36
  • \$\begingroup\$ Although t.r is float in C# , but texture still only save one byte data in one channel. \$\endgroup\$
    – TimChang
    Commented Jan 19, 2023 at 2:38
  • \$\begingroup\$ @TimChang so would it be possible to pack 2 floats into a single channel? \$\endgroup\$
    – Shiv-iwnl
    Commented Jan 19, 2023 at 3:08

2 Answers 2

0
\$\begingroup\$

maybe this work? I'm not test it.

    byte mask1 = 0;//0~4
    byte mask2 = 0;//0~4
    byte mask3 = 0;//0~4
    byte mask4 = 0;//0~4

    byte maskCombine = (byte)((mask1) & (mask2 << 2) & (mask3 << 4) & (mask4 << 6));
    Color32[] colors = new Color32[4];
    colors[0].r = maskCombine;
    Texture2D t = null;
    t.SetPixels32(colors,0);

shader:

half alpha = mask.r;
half mask1 = step(0.25 , alpha-0.75);// here get 0 or 1
half mask2 = step(0.25 , alpha-0.5);
half mask3 = step(0.25 , alpha-0.25);
half mask4 = step(0.25 , alpha);
\$\endgroup\$
0
\$\begingroup\$

Simply cast the floats to uint after multiply. float is only good to 21 bits, so use an uint32 type as the output:

uint b1 = (uint(t1.r * 255) & oxFF);
uint b2 = (uint(t2.r * 255) & 0xFF) << 8;
uint b3 = (uint(t3.r * 255) & 0xFF) << 16;
uint b4 = (uint(t4.r * 255) & oxFF) << 24;
uint packed = b1 | b2 | b3 | b4; 
Tex.rgba = packed;

If floats were used there would be round trip loss in b1 and the lsb bit of b2, by Ceil(log2(ReverseBitOrder(b1)) + Ceil(log2(b4))) bits.

Make sure you use an uncompressed format without mip maps for perfect channel recovery.

So make Tex an integer format: convert the textures to use GL_RGBA32 instead of GL_RGBA32F for OpenGL or DXGI_FORMAT_R8G8B8A8_UINT instead of DXGI_FORMAT_R8G8B8A8_UNORM for Windows depending on platform.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .