Unity Shader 一句话带过(简单点学那么复杂干啥)

前言:

这篇文章主要的内容是渲染相关的知识,是最基本的常用的知识,以unity 的shader 脚本为例,结合图形渲染流程记录各个部分,个人接触shader已有几年的时间,从最初的无从下手,到现在随便添油加醋,深知初学者的不易


理解流程:

下面是一个在网上找到基本的渲染流程图

Unity Shader 一句话带过(简单点学那么复杂干啥)_第1张图片


大体的功能分类:应用阶段,几何阶段,光栅化阶段

应用阶段:渲染数据准备,以及传入GPU渲染接口

几何阶段:顶点着色器,曲面细分着色器,几何着色器、//可以控制的逻辑,常用的就是顶点函数,曲面细分函数和几何函数在个别平台不支持

光栅化阶段:像素着色器

其实就是对应的unity shader模板中的顶点函数和片元函数

//Unity 中的Surface shader是对像素着色器的封装


unity shader脚本模板注释:

Shader "Unlit/NewUnlitShader"
{

	//属性会序列化到unity编辑器,没什么用,给界面调试人员看的,我是很少用到,只有在写完之后给别人提供参数接口的时候才会声明在Properties代码块中
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
	//实际的着色器代码
    SubShader
    {
		//标签,表示这渲染前的条件和背景,就像你要定义一个变量必须得告诉编译器是什么类型的
		//这个就是告诉着色器,该物体是不是透明的,在哪个渲染队列,等等,还有好几种标签
        Tags { "RenderType"="Opaque" }
	    //组件LOD:会根据相机的距离,选择不同的网格模型,输送到渲染端
		//shader中的LOD标签:根据不同的距离选择不同的subshader作为着色器
        LOD 100
		//注意:渲染流程中一种东西叫缓冲区,简单点理解就是集合,特别注重的是颜色缓冲(存颜色的列表),深度缓冲(存深度值的列表),
		//可以理解为各个列表之间数据都是一一对应的 ,实际上我也没有看过源码
		//然后该物体渲染的时候,可以理解为photoshop 图层之间的关系,一层覆盖一层,最终需要的一个列表

		//深度测试:	 根据什么条件把深度的值,要把颜色覆盖到缓冲区种
		ZTest  value	 //value = Less,value = LEqual  等   
		//深度写入 :  根据value的值,确定是否把顶点的深度值写入深度缓冲区, 当我们需要获取相机画面深度图的时候,就是获取深度缓冲区列表的值
		ZWrite	 value  //是否开启深度写入
		
		//透明写入(其实叫透明混合,就是定义  当前的透明值和缓冲区中的值一种缓冲方式)
		Blend  value //a b
		 //透明测试: 根据透明的值比较 ,需不需要覆盖缓冲区,
		AlphaTest

	    //正面,背面剔除,就是告诉着色器只计算正面还是背面,还是双面渲染,通常在着色器中,双面渲染是需要渲染两次的,也就是两个pass,一个渲染正面一个渲染背面
		Cull back/front
		//注意点:正面是 三角面法线的方向(面法线的方向是根据三角形三个顶点的法线,求出来的),背面是三角面法线相反的方向, 误区就是: 眼睛所看到的正面和背面有可能是错的

		//渲染通道,数据都是在pass代码块中进行操作的
		//就是一些数据的计算,无非就是那几个,模型的:顶点颜色,顶点位置,uv,贴图,
																     //环境的:光的方向和强度,	(就是光照模型,通常都不用写,用默认的就行)
        Pass
        {
			//程序起始标签,没什么用,就是编译器会识别这个把标签包裹的代码进行转换
            CGPROGRAM
			//声明的顶点函数,在流程中几何阶段中的,shader模板中隐藏一个曲面细分函数,因为曲面细分不是所有平台都通用,所有官方没写到模板里
            #pragma vertex vert
		   //片元函数:是光栅化阶段中的一个函数,主要是处理片元的颜色,
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog
			//包含基础顶点函数库,正常来说都可以在这个脚本中定义,为了通用就把共用的提出了
            #include "UnityCG.cginc"
			//应用数据,就是从cpu,发来的结构体数据,meshrender 发送来的,这个结构体就是存储的模型的那几种数据
            struct appdata
            {
				//顶点位置,局部坐标,POSITION:顶点的语义,表示这个vertex是顶点的数据
                float4 vertex : POSITION;
				//顶点的uv坐标,TEXCOORD0:表示坐标存在TEXCOORD0这贴图中,好像一共最多有8张,Texcoord7
                float2 uv : TEXCOORD0;
            };
			//这个是顶点函数的返回值,像素函数的形参,结构体重的字段可以随便定义,就是如果没有赋值会报警告
            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };
		    //这些可以理解为程序的成员变量  ,Properties代码块中的有规则的对应
            sampler2D _MainTex;
            float4 _MainTex_ST;
			//顶点函数
            v2f vert (appdata v)
            {
                v2f o;
				//局部转裁剪位置
                o.vertex = UnityObjectToClipPos(v.vertex);
				//变换uv
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                //雾
				UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }
			//像素函数	 ,后面的那个语义,标识着返回值是系统使使用
            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
			//结束标签
            ENDCG
        }
    }
}

注:物体的渲染顺序是 背景 -> 不透明的物体 -> 透明的物体,这个可以 配合着那几个测试阶段方便理解,然后可以使用unity的frame debug查看渲染的状态,以及渲染的顺序

结语:

个人感觉着色器写牛不牛,全靠美术功底,反正我的美术水平是0,着色器这块的水平估计也就到这了,用了近十年的unity,越来越讨厌这个平台,感觉学Unity就像学一些官方封装好的API,所以最近一直有转虚幻的想法,希望可以有机会跳到虚幻

你可能感兴趣的:(shader学习记录,unity,游戏引擎)