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是目标因子,产生的各个颜色和各个因子相乘,然后两个颜色相加

  • 相关阅读:
    【转】由浅入深表达式树(一)创建表达式
    【转】背后的故事之
    【转】背后的故事之
    【转】C#集合类型大盘点
    【转】最近用Timer踩了一个坑,分享一下避免别人继续踩
    【转】《深入理解C# 3.x的新特性》博文系列汇总
    【转】文件各种上传,离不开的表单
    【转】文件下载之断点续传(客户端与服务端的实现)
    【转】权限管理学习 一、ASP.NET Forms身份认证
    【转】C#单元测试,带你快速入门
  • 原文地址:https://www.cnblogs.com/HangZhe/p/7233065.html
Copyright © 2011-2022 走看看