我正在寻找一种解决方案,在一块地形中存储超过5种不同的纹理,我只找到了这个解决方案的一部分。我必须将所有纹理(512x512)打包成一个大纹理(8192x8192)然后在着色器中我必须使用来自splat纹理的r,g,b值来计算纹理id。但是如何从r,g,b值计算这个id。什么是配方?
答案 0 :(得分:2)
所以你得到了地图(左纹理/图像),其中每个地形段存储了 ID 的表面类型。比你有纹理图谱(右纹理)和16x16=256
纹理,并希望为地形着色(底部图像)生成组合纹理。
地图纹理
您没有指定其格式和编码,但我怀疑这是您要求的。因此,您获得256
纹理意味着每个 ID 需要8bit
。如果您使用32bit
RGBA 整数格式,则最多可以存储4个 ID 。
<强>编码/解码强>
如果你需要更多,那么使用更多的地图纹理或更喜欢地图集中的纹理数量。例如,对于5个ID,您需要floor(32/5)=6 bits/ID
,因此您需要在地图册中添加最多64
个纹理(但仍有2个备用位,因此一个 ID 仍然可以使用{ {1}}或两个 ID 可以使用256
纹理。)
对于所有这些粗略的你需要对地图纹理进行整数采样,以防万一看:
而不是浮动128
值。 r,g,b
格式的5
ID GPU解码的整数的数学公式看起来像这样(未经测试只是说明性的):
r8g8b8a8
同样 CPU编码:
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;
未对代码进行测试,因此可能会出现反向 RGBA 顺序或错误假设的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;
位宽(它们应与重新调整的值匹配。