您当前的位置: 首页 > 

VT LI

暂无认证

  • 6浏览

    0关注

    126博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

大量贴图采样限制下的渲染处理方法

VT LI 发布时间:2019-09-05 18:14:30 ,浏览量:6

因为项目中有换装系统,换装系统中有大量的可替换的脸部数据,比如眉毛,睫毛,腮红,眼影,口红等,需要十多个贴图通道。所以我们的shader中需要有十多张贴图通道

跑再android机器上时,一切都正常显示。但跑再iphone8时,就会发现材质丢失了

然后查到的报错信息是采样次数过多,机器不支持这个采样次数。iphone8是9个

基于这个问题,有两种解决方案:

第一种:

把多个贴图合并,也就是再到gpu之前先把所有贴图合并成一个贴图,然后给gpu渲染一次。

var pixels = tex.GetPixels32();
                for (int j = 0; j < pixels.Length; j++)
                {
                    if (pixels[j].a != 0)
                    {
                        if (j < colors.Length)
                        {
                            var realJ = j;
                            var newPixel = pixels[realJ] * (color * 255);
                            var curColors = colors[realJ];
                            var dstColors = Color32.Lerp(curColors, newPixel, (float)newPixel.a / 255.0f);
                            colors[realJ] = new Color32((byte)(curColors.r > 0 ? (dstColors.r) : newPixel.r),
                                (byte)(curColors.g > 0 ? (dstColors.g) : newPixel.g),
                                (byte)(curColors.b > 0 ? (dstColors.b) : newPixel.b),
                                (byte)(curColors.a > 0 ? (dstColors.a) : newPixel.a));
                        }
                    }
                }

写入shader:

var faceOtherShader = Shader.PropertyToID("_FaceOtherMap");
            bodymat.SetTexture(faceOtherShader, texture2d);

优点:这样减少了贴图数量,消耗也更少了,带宽消耗自然也更小了。

缺点:但这样做的问题是每次换装时都需要合并一次贴图,会有明显的卡顿,效果也并不是很好。

 

第二种:

分两个材质放贴图

也就是第一个做光照模型的渲染,第二个做贴图渲染

尽量让两个材质的贴图采样个数都小于9个。让光照模型材质(AvatarMat)先渲染,贴图渲染(AvatarFaceTexture)后渲染。

然后跑到iphone8上,确实不会出现材质丢失的紫色了。

但是出现了一个问题:

就是腮红,嘴唇等都会闪烁。

然后看了下这张rt的alpha通道

越白说明alpha越高,可以看到眼睛旁边和嘴巴旁边都有半透明的效果。

查找原因:

看了下shader发现

Blend SrcAlpha OneMinusSrcAlpha

混合模式只用了这个。因为这个blend方式是也会把alpha通道做混合的。

然后我们进行分析

先渲染的avatarmat中是不透明的

但后面处理的avatarfacetexture里是有透明

然后混合用Blend SrcAlpha OneMinusSrcAlpha混合公式后得到的是一个带透明的效果,因为后面在处理的face时,因为alpha是不为1的,所以frontcolor*alpha+backcolor*(1-alpha)肯定得到的是一个半透明的值。

比如:

facetexture当前像素是(0.8,0.8,0.8,0.8)avatarmat的像素是(1,1,1,1)

计算过程:(0.8,0.8,0.8,0.8)*0.8+(1,1,1,1)(1-0.8)=(0.84,0.84,0.84,0.84)

也就是最后的alpha值是0.84,所以是透明的,所以会显示背景而导致半透明区域是闪烁的。

那么解决办法也很简单,就是区分color的混合和alpha的混合。

因为blend有一种模式可以区分color和alpha的混合。

Blend SrcFactor DstFactor, SrcFactorA DstFactorA

也就是前面两个是颜色混合,后面两个是颜色混合。正是我们想要的。所以最后的混合方式是

Blend SrcAlpha OneMinusSrcAlpha,One One

问题就解决了

当然这里还要注意FaceTextureshader要做小量的深度偏移,不然会跟身体重叠比较严重,导致闪烁发生

优点:切换贴图不会卡顿,顺畅过度

缺点:贴图采样数量还是一样多,所以会产生带宽过高的问题

以后的优化点可以考虑部分贴图合并减少贴图数量。

 

关注
打赏
1649603425
查看更多评论
立即登录/注册

微信扫码登录

0.1656s