大量貼圖採樣限制下的渲染處理方法

因爲項目中有換裝系統,換裝系統中有大量的可替換的臉部數據,比如眉毛,睫毛,腮紅,眼影,口紅等,需要十多個貼圖通道。所以我們的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要做小量的深度偏移,不然會跟身體重疊比較嚴重,導致閃爍發生

優點:切換貼圖不會卡頓,順暢過度

缺點:貼圖採樣數量還是一樣多,所以會產生帶寬過高的問題

以後的優化點可以考慮部分貼圖合併減少貼圖數量。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章