zoukankan      html  css  js  c++  java
  • 关于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是目标因子,产生的各个颜色和各个因子相乘,然后两个颜色相加

  • 相关阅读:
    475. Heaters
    69. Sqrt(x)
    83. Remove Duplicates from Sorted List Java solutions
    206. Reverse Linked List java solutions
    100. Same Tree Java Solutions
    1. Two Sum Java Solutions
    9. Palindrome Number Java Solutions
    112. Path Sum Java Solutin
    190. Reverse Bits Java Solutin
    202. Happy Number Java Solutin
  • 原文地址:https://www.cnblogs.com/HangZhe/p/7233065.html
Copyright © 2011-2022 走看看