纹理飞溅超过 5 个纹理

Texture splatting more than 5 textures

我正在寻找一种在一块地形中存储超过 5 个不同纹理的解决方案,但我只找到了该解决方案的一部分。我必须将我所有的纹理 (512x512) 打包到一个大纹理 (8192x8192) 中,然后在着色器中我必须使用来自 splat 纹理的 r、g、b 值计算纹理 id。但是如何根据 r、g、b 值计算此 id。什么是公式?

所以你得到了地图(左 texture/image),其中 ID 的 表面类型存储在每个地形段中。比起您拥有具有 16x16=256 纹理的纹理图集(右纹理),并希望为地形着色(下图)生成组合纹素。

  1. 贴图纹理

    您没有指定其格式和编码,但我怀疑这是您要求的。所以你有 256 个纹理,这意味着你需要 8bit 每个 ID。如果您使用 32bit RGBA 整数格式,您最多可以存储 4 个 ID's.

  2. encoding/decoding

    如果您需要更多,那么可以使用更多贴图纹理,或者喜欢地图集中的纹理数量。例如,对于 5 个 ID,你有 floor(32/5)=6 bits/ID 所以你需要在你的图集中有最大 64 个纹理(但仍然有 2 个备用位,所以一个 ID 可以仍然使用 256 或两个 ID 的 可以使用 128 纹理。)

    当然,您需要对地图纹理进行整数采样,以防万一,请参阅:

    • Precise control over texture bits in GLSL

    而不是浮动 r,g,b 值。 5 IDs GPU decoding from r8g8b8a8 format 的整数数学方程可能看起来像这样(未经测试只是说明性的) :

    uniform usampler2D tex;
    uvec4 a=texture(tex, ...); // fetch 4x8 bits
    uint b=0; // construct 32 bit int
    b|=uint(a.r);
    b|=uint(a.g)<<8;
    b|=uint(a.b)<<16;
    b|=uint(a.a)<<32;
    uint ID1=(b    )&0x3F; // decode ID's
    uint ID2=(b>> 6)&0x3F;
    uint ID3=(b>>12)&0x3F;
    uint ID4=(b>>18)&0x3F;
    uint ID5=(b>>24)&0x3F;
    

    和类似的CPU编码:

    uint a=0; // construct 32 bit int
    a|=(ID1&0x3F);
    a|=(ID2&0x3F)<< 6;
    a|=(ID3&0x3F)<<12;
    a|=(ID4&0x3F)<<18;
    a|=(ID5&0x3F)<<24;
    map_texture_data[...]=a;
    

    代码未经过测试,因此可能会出现反向 RGBA 顺序或错误假定的 uint 位宽(它们应与 rem-ed 值匹配。