關於Unity中GrabPass截屏的使用和Shader的組織優化


GrabPass截屏

可以用來截屏,截屏后把紋理傳給下一個通道使用。

1:使用抓屏通道, GrabPass {} 或 GrabPass { “ 紋理名稱”}; 使用GrabPass {}后,可以用_GrabTexture訪問截屏的紋理
2: 后續的Pass通道使用這個抓屏;
3: 編寫案例
(1): 創建一個頂點片元着色器;
(2): 將這個着色器放到Overlay隊列
(3): 使用GrabPass通道截屏,並定義好變量來接收
(3): 設置頂點的UV坐標;
(4): 着色使用截圖的紋理

 

 

GrabPass截屏案例

1.創建好Unity工程目錄

2.創建一個平面plane和一個立方體cube,給cube一個材質red,把red拖進cube的材質屬性中

3.再創建一個平面show,豎起來放在旁邊,等下用來顯示截屏紋理

4.在resources文件夾下面創建shaders文件夾

5.打開shaders文件夾,創建一個用於頂點片元着色的shader,create---->shader---->unlit shader,重命名為GrabShader

6.打開GrabShader

第一步:先把第一行改成Shader "Custom/GrabShader",這樣才能在編輯器里面顯示這個shader

第二步:把渲染隊列拉到最高overlay

Tags { "RenderType"="Opaque" "Queue"="Overlay" }

第三步:使用截屏通道

Shader "Custom/GrabShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "Queue"="Overlay" }//把渲染隊列拉到最高overlay
        LOD 100

        //
        GrabPass {} // 截圖通道, 后面使用_GrabTexture訪問截屏紋理
        // end 
        Pass
        {
            name "ONE"

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            
            sampler2D _GrabTexture;//使用前重新聲明一下
            float4 _GrabTexture_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _GrabTexture);//使用
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_GrabTexture, i.uv);//使用
                return col;
            }
            ENDCG
        }
    }
}

7.創建一個材質GrabShader,shader屬性設置為Custom/GrabShader

8.show平面關聯材質球GrabShader

9.運行起來,Game視圖里面的plane視圖上面顯示出截屏紋理

 

 

 

常用的gcinc

系統自帶的類似於語言里面的.h文件,是庫函數,在Unity-->Edit-->Data-->CGIncludes;查看

1:cginc文件: 宏,幫助函數等,放在CGIncludes下面,開發人員可以開發自己的cginclude文件
2:常用的cginc文件:
HLSL.Support.cginc 協助多平台開發的一些宏等,自動包含
UnityShaderVarirables.cginc 全局變量,自動包含;
UnityCG.cginc 常用的幫助函數;
AutoLight.cginc 光照和陰影功能;
Lighting.cginc 表面着色器的光照模型;
TerrainEngine.cginc 地形植被的光照着色函數;

 

 

 UnityCG.gcinc常用函數

1:UnityWorldSpaceViewDir: 給定對象空間的頂點位置朝向攝像機方向的世界坐標空間方向;
2: ObjSpaceViewDir: 給定對象空間的頂點位置朝向攝像機方向的對象空間方向;
3: ParallaxOffset: 計算用於視差法線貼圖的UV偏移量;
4: Luminance: 將顏色轉為亮度;
5: DecodeLightmap: 從光照貼圖中解碼顏色;
6: float EncodeFloatRGBA(float4 rgba): 將RGBA顏色編碼為[0,1)的浮點數;
7: float4 DecodeFloatRGBA(float v): 將一個浮點數解碼為RGBA的顏色;
8: UnityWorldSpaceLightDir 給定對象空間的頂點位置到光源的世界坐標空間方向;
9: ObjSpaceLightDir: 給定對象空間的頂點位置到光源的對象空間方向;

 

 

UsePass 復用

1:編寫過的pass可以重復使用,借助UsePass “ShaderPath/PASS_NAME”
2:PASS名字要大寫;
3: Pass {
name “ONE” //不要寫到cgprogram里面
}
4: UsePass “Custom/ShaderName/ONE”

 

 

multi_compile多版本控制

1: 通過multi_compile編譯多個版本的shader;
2: #pragma multi_compile MY_multi_1 MY_multi_2;
3: #ifdef MY_multi_1 #endif
4: Shader.EnableKeyword(“ MY_multi_1”);
5: Shader.DisableKeyword(“MY_multi_2”); 控制shader編譯出不同的版本;

 

 

multi_compile多版本控制實例

1.打開shaders文件夾,創建一個用於頂點片元着色的shader,create---->shader---->unlit shader,重命名為MultiShader

2.打開MultiShader

第一步:先把第一行改成Shader "Custom/MultiShader",這樣才能在編輯器里面顯示這個shader

第二步:

Shader "Custom/MultiShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            // 定義這個的兩個開關,告訴有兩個版本的shader
            #pragma multi_compile MY_multi_1  MY_multi_2
            
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col;
                // sample the texture
                #ifdef MY_multi_1//版本1
                col = fixed4(1.0, 0.0, 0.0, 1.0);
                #endif

                #ifdef MY_multi_2//版本2
                col = fixed4(0.0, 0.0, 1.0, 1.0);
                #endif

                return col;
            }
            ENDCG
        }
    }
}

3.創建一個材質MultiShader,設置它的shader屬性為Custom/MultiShader

4.創建一個立方體cube,把材質MultiShader拖進cube

5.創建一個腳本MultiShader,掛載在立方體cube下面

打開MultiShader.cs

using UnityEngine;
using System.Collections;

public class MulShader : MonoBehaviour {

    // Use this for initialization
    void Start () {
        Shader.EnableKeyword("MY_multi_2");//打開版本2
        Shader.DisableKeyword("MY_multi_1");//關閉版本1
    }
    
    // Update is called once per frame
    void Update () {
    
    }
}

 

 

移動平台優化

1: 代碼優化:
預先計算好對應的值 sqrt(2) --> 根號2 --> 1.414..;
放心的使用向量相關操作,叉積,點擊,基本都是硬件實現,很高效;
盡量減少函數調用減少開銷;
2: 盡可能的計算放在頂點着色器中,頂點着色器的調用頻率遠低於片着色器;
3: 幾何復雜度考量:在IOS平台視口內的頂點數不要超過100K個,IOS默認的緩沖區就是就是這么大,超過這個數字,底層會做一些操作消耗更多的資源;
4: 紋理大小為 2^n次方大小, 16, 64, 128, 256, 512, 1024;
5: 使用適當的數據類型float < half < fixed; 性能
6: 盡量慎用透明效果,透明效果GPU要逐像素渲染,而且沒有了遮擋剔除的效果,會用到Blend SrcAlpha OneMinusSrcAlpha//SrcAlpha是源因子,OneMinusSrcAlpha是目標因子,產生的各個顏色和各個因子相乘,然后兩個顏色相加

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM