虚幻为256x16的3d转2d slice的16^3的8位lut。
SP中为128x2048的64^3的32位lut,在储存上原本应该64x4096的图被折半,R通道相对UE中基本对应,B通道将原本右半段交叉隔像素插入左半段,G通道每两像素同值。
将虚幻中256x16的贴图按SP中的存储方式填充进去,RG通道利用硬件filter插值,B通道手动采样线性插值。
首先需要考虑到转换前后的纹素大小和利用硬件filter,对应到每个slice中应从左上第一个纹素的中心位置到右下最后一个纹素的中心位置进行坐标映射。 再考虑各个通道情况。
R通道: 基本对应,只需按64^2切开就有64个slice
sliceUV = frac(uv*vec2(2048.,128.)/vec2(64));
G通道: G通道处理位移比较复杂,但是每个slice中的像素都是同值采样比较简单。可以先拿到slice的index,再进行手动的线性插值补足中间的像素。
const vec2 perSliceCenter = .5/vec2(16.,1.);
idx = floor(floor(uv.x*2048.)/64)+(uv.g*128%2)*32;
sliceHeight = idx/63*15;
BottomSlice = vec2(floor(sliceHeight)/16.,0.);
UpSlice = vec2(floor(sliceHeight+1.)/16.,0.);
SliceAlpha = frac(sliceHeight);
FinalG = mix(tex2dSample(BottomSlice+perSliceCenter,LutTex),tex2dSample(UpSlice+perSliceCenter,LutTex),SliceAlpha);
B通道: B通道每两行同值,但是我们是写入采样的还是原LUT,依旧可以利用硬件filter
sliceUV.r = frac(uv.r*2048./64.);sliceUV.g = floor(uv.g*64.)/64.;
具体实现中还有些写入的坑。这样转换后的lut虽然不能充分利用到SP的lut的存储优势,但是可以保证和虚幻中的LUT效果一致。