Unity_TA 养成记

成为一名TA大佬

  • 什么是ShaderLab?
  • Shader 变体
    • 1.什么是变体
    • 2.变体的产生
    • 3.变体数量计算
    • 4.变体查看
    • 5.减少变体
    • 6.变体在Editor中的生成过程
  • Shader Load
  • Shader预加载
  • Unity Shader入门精要
    • 渲染流水线
      • 概念流水线
      • CPU-->GPU
      • GPU流水线

什么是ShaderLab?

在图形API中有:OpenGL,DX,Vulkan等。Unity为了处理不同平台使用的Shader语言的差异,就用ShaderLab封装起来,最后根据不同平台编译成对应的着色器语言。

UnityShader 结构图:

Shader
SubShader
SubShader
SubShader
Pass
Pass
Program:Vertex
Program:Fragment
SubProgram:Variant 1
SubProgram:Variant 2

Shader 变体

1.什么是变体

官网介绍
在上面的结构图最底下的Variant就是变体部分,如下所示frag中有三个判断分支,Unity就会产生多个Shader变体。如果变体数量太多就会增加内存消耗,一般ShaderLab占用内存在30-70M左右,如果超出太多就要考虑优化变体数量。

        fixed4 frag (v2f i) : SV_Target
            {
                #if _OVERLAY_1
                	col += secCol;
                #elif _OVERLAY_2
                	col *= secCol;
                #endif
                	col *= _OtherCol;
                return col;
            }

2.变体的产生

主要是在Shader中使用了:#pragma shader_feature#pragma multi_compile起到宏的作用。不一样的是 shader_feature 没有用到的不会被包含进去, 而 multi_compile全部版本都会被包含,因此 shader_feature 适用于那些会在材质面板中直接设置的情况,但在脚本里通过DisableKeyword 和 EnableKeyword 来开启或关闭 keyword 的话就要使用 multi_compile

3.变体数量计算

Case1
#pragma multi_compile A B C
#pragma multi_compile D E
如果shader中使用了以上两个multi_compile那么不管后面是否使用到宏(A,B,C,D,E)它都会产生变体,这样计算的方法是(A,B,C)(D,E) => 32=>6。
Case2
#pragma multi_compile A B C
#pragma shader_feature D E
这里有两个shader_feature,当他们启用才会产生变体因此有以下几种组合情况:
(A+D,B+D,C+D) ,(A+E,B+E,C+E),(A+D,B+D,C+D,A+E,B+E,C+E)
Case3
#pragma multi_compile A B C
#pragma shader_feature _ D E
这里的(’_’)表示空,当D或E启用时会产生:(A,B,C,A+D,B+D,C+D) 或 (A,B,C,A+E,B+E,C+E)

4.变体查看

Unity在编辑器里提供了变体查看的方法,我们在shader中添加#pragma shader_feature_local CS_BOOL为例演示如何查看:
Unity_TA 养成记_第1张图片
1.选中shader,在inspector面板中有个Keywords,它里面包含了全局和本地的所有keword。
2.点击inspector上的Compiled code右边的倒三角,再点击弹出框内的Show按钮即可看到当前shader用到的Keyword。

5.减少变体

1.shader内剔除
我们可以在shader中使用#pragma skip_variants来剔除不想要的Keyword变体。如下所示在shader中添加#pragma skip_variants CS_BOOL后就可以屏蔽该Keyword。
Unity_TA 养成记_第2张图片

2.Build时剔除(只能用于Global )
使用以下方法剔除时发现无法把Local类型的keyword剔除掉,如果有哪位晓得方法麻烦留言指导下哈,非常感谢。

using System.Collections;
using System.Collections.Generic;
using UnityEditor.Build;
using UnityEditor.Rendering;
using UnityEngine;
using UnityEngine.Rendering;

namespace ZYF
{
    /// 
    /// 在Build时剔除shader keyword
    /// 
    public class ZYF_Test_ShaderKeywordStripping : IPreprocessShaders
    {
        public int callbackOrder => 0;

        //要剔除的keyword
        ShaderKeyword cs_bool_keyword;
        public ZYF_Test_ShaderKeywordStripping()
        {
            cs_bool_keyword = new ShaderKeyword("CS_BOOL");
        }
        public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList<ShaderCompilerData> data)
        {
            List<ShaderCompilerData> strippingList = new List<ShaderCompilerData>();
            //收集要剔除的data
            for (int i = 0, length = data.Count; i < length; i++)
            {
                if (data[i].shaderKeywordSet.IsEnabled(cs_bool_keyword))
                {
                    strippingList.Add(data[i]);
                }
            }
            //剔除收集到的data
            strippingList.ForEach(d =>
            {
                data.Remove(d);
            });
        }
    }
}

6.变体在Editor中的生成过程

Unity_TA 养成记_第3张图片

Shader Load

Shader预加载

使用ShaderVariantCollection预加载指定Shader
官方说明
ShaderVariantCollection里记录着每个shader里真正使用到的变体,它可以用来预加载shader。
1.首先进入运行模式并让摄像机看到整个场景,然后到ProjectSettings/Graphics的最下方点击Save to asset保存。
2.把保存的SVC文件放到Project Settings/Graphics 中的Preloaded Shaders中,这样就能预加载shader了,当然你可以按需求修改SVC内容。
3.还可以在代码中进行预加载(因为预加载比较耗时最好放在加载场景中执行):Shader.WarmupAllShaders(预加载所有shader) 和ShaderVariantCollection.Warmup(加载指定SVC中的shader)。

Unity Shader入门精要

书籍github

渲染流水线

概念流水线

应用阶段
几何阶段
光栅化阶段
输出渲染图元
输出屏幕空间的顶点信息

每个阶段也是一个流水线系统。
应用阶段:输出渲染所需的几何信息即渲染图元(点线面)
几何阶段:把顶点坐标变换到屏幕空间中,输出屏幕空间二维顶点坐标、每个顶点对应的深度值、着色等相关信息;
光栅化阶段:在GPU上运行,决定哪些像素被绘制,对逐顶点数据(纹理坐标、顶点颜色等)进行插值,然后逐像素处理。

CPU–>GPU

应用阶段
从硬盘加载数据到显存
设置渲染状态
调用DrawCall
定义网格渲染用啥着色器材质贴图
告诉GPU开始渲染

GPU流水线

概念阶段的几何、光栅化两个阶段开发者无法拥有绝对的控制权,其实现的载体是GPU.

光栅化阶段
几何阶段
三角形设置
三角形遍历
片元着色器
逐片元操作
顶点着色器
曲面细分着色器
几何着色器
裁剪
屏幕映射
顶点数据

顶点着色器:每个顶点都会调用一次顶点着色器,顶点与顶点之间相互独立。主要工作是坐标变换逐顶点光照。坐标变换把顶点坐标从模型空间转换到齐次裁剪空间(通过MVP变换坐标到-1~1)

你可能感兴趣的:(Unity,UnityShader)