unity基础学习之基础语义

SubShader

一个Shader有多个SubShader。一个SubShader可理解为一个Shader的一个渲染方案。即SubShader是为了针对不同的渲染情况而编写的。每个Shader至少1个SubShader、理论可以无限多个,但往往两三个就足够。
一个时刻只会选取一个SubShader进行渲染,具体SubShader的选取规则包括:
从上到下选取
SubShader的标签、Pass的标签
是否符合当前的“Unity渲染路径”
是否符合当前的ReplacementTag
SubShader是否和当前的GPU兼容

按此规则第一个被选取的SubShader将会用于渲染,未被选取的SubShader在这次渲染将被忽略。

Shader "ShaderLab Tutorials/TestShader" {
    SubShader
    {
        //...
    }
}

SubShader的Tag


Shader "ShaderLab Tutorials/TestShader" {
    SubShader
    {
        Tags { "Queue"="Geometry+10" "RenderType"="Opaque" }
        //...
    }
}

shader内部可以有标签(Tags)的定义。Tag指定了这个SubShader的渲染顺序(时机),以及其他的一些设置。

"RenderType"标签。Unity可以运行时替换符合特定RenderType的所有Shader。Camera.RenderWithShader或Camera.SetReplacementShader配合使用。Unity内置的RenderType包括:
"Opaque":绝大部分不透明的物体都使用这个;
"Transparent":绝大部分透明的物体、包括粒子特效都使用这个;
"Background":天空盒都使用这个;
"Overlay":GUI、镜头光晕都使用这个;
用户也可以定义任意自己的RenderType这个标签所取的值。
应注意,Camera.RenderWithShader或Camera.SetReplacementShader不要求标签只能是RenderType,RenderType只是Unity内部用于Replace的一个标签而已,你也可以自定义自己全新的标签用于Replace。
比如,你为自己的ShaderA.SubShaderA1(会被Unity选取到的SubShader,常为Shader文件中的第一个SubShader)增加Tag为"Distort"="On",然后将"Distort"作为参数replacementTag传给函数。此时,作为replacementShader实参的ShaderB.SubShaderB1中若有也有一模一样的"Distort"="On",则此SubShaderB1将代替SubShaderA1用于本次渲染。
具体可参考Rendering with Replaced Shaders
"Queue"标签。定义渲染顺序。预制的值为
"Background"。值为1000。比如用于天空盒。
"Geometry"。值为2000。大部分物体在这个队列。不透明的物体也在这里。这个队列内部的物体的渲染顺序会有进一步的优化(应该是从近到远,early-z test可以剔除不需经过FS处理的片元)。其他队列的物体都是按空间位置的从远到近进行渲染。
"AlphaTest"。值为2450。已进行AlphaTest的物体在这个队列。
"Transparent"。值为3000。透明物体。
"Overlay"。值为4000。比如镜头光晕。
用户可以定义任意值,比如"Queue"="Geometry+10"
"ForceNoShadowCasting",值为"true"时,表示不接受阴影。
"IgnoreProjector",值为"true"时,表示不接受Projector组件的投影。
另,关于渲染队列和Batch的非官方经验总结是,一帧的渲染队列的生成,依次决定于每个渲染物体的:

Shader的RenderType tag,
Renderer.SortingLayerID,
Renderer.SortingOrder,
Material.renderQueue(默认值为Shader里的"Queue",
Transform.z(ViewSpace)(默认为按z值从前到后,但当Queue是“Transparent”的时候,按z值从后到前)。
这个渲染队列决定了之后(可能有dirty flag的机制?)渲染器再依次遍历这个渲染队列,“同一种”材质的渲染物体合到一个Batch里。

Pass

一个SubShader(渲染方案)是由一个个Pass块来执行的。每个Pass都会消耗对应的一个DrawCall。在满足渲染效果的情况下尽可能地减少Pass的数量。

Shader "ShaderLab Tutorials/TestShader" {
    SubShader {
        Pass
        {
            //...
        }
    }
}

Pass的Tag

Shader "ShaderLab Tutorials/TestShader" {
    SubShader {
        Pass
        {
            Tags{ "LightMode"="ForwardBase" }
            //...
        }
    }
}
shader有
自己专属的Tag类似,Pass也有Pass专属的Tag。
其中最重要Tag是 "LightMode",指定Pass和Unity的哪一种渲染路径(“Rendering Path”)搭配使用。除最重要的ForwardBase、ForwardAdd外,这里需额外提醒的Tag取值可包括:

Always,永远都渲染,但不处理光照
ShadowCaster,用于渲染产生阴影的物体
ShadowCollector,用于收集物体阴影到屏幕坐标Buff里。
其他渲染路径相关的Tag详见下面章节“Unity渲染路径种类”。
具体所有Tag取值,可参考ShaderLab syntax: Pass Tags。

FallBack

Shader "ShaderLab Tutorials/TestShader"{
    SubShader { Pass {} }

    FallBack "Diffuse" // "Diffuse"即Unity预制的固有Shader
    // FallBack Off //将关闭FallBack
}
当本Shader的所有SubShader都不支持当前显卡,就会使用FallBack语句指定的另一个Shader。FallBack最好指定Unity自己预制的Shader实现,因其一般能够在当前所有显卡运行。

Shader中的数据类型

有3种基本数值类型:float、half和fixed。
这3种基本数值类型可以再组成vector和matrix,比如half3是由3个half组成、float4x4是由16个float组成。

float:32位高精度浮点数。
half:16位中精度浮点数。范围是[-6万, +6万],能精确到十进制的小数点后3.3位。
fixed:11位低精度浮点数。范围是[-2, 2],精度是1/256。

Properties

Properties {
_Color (“Color”, Color) = (1,1,1,1)
_MainTex (“Albedo (RGB)”, 2D) = “white” {}
//光滑度
_Glossiness (“Smoothness”, Range(0,1)) = 0.5
//金属光泽
_Metallic (“Metallic”, Range(0,1)) = 0.0
}

    在Properties{}中定义着色器属性,在这里定义的属性将被作为输入提供给所有的子着色器。每一条属性的定义的语法是这样的:
	_Name("Display Name", type) = defaultValue[{options}]

	_Name - 属性的名字,简单说就是变量名,在之后整个Shader代码中将使用这个名字来获取该属性的内容
	Display Name - 这个字符串将显示在Unity的材质编辑器中作为Shader的使用者可读的内容

	type - 这个属性的类型,可能的type所表示的内容有以下几种:
		Color - 一种颜色,由RGBA(红绿蓝和透明度)四个量来定义;
		2D - 一张2的阶数大小(256512之类)的贴图。这张贴图将在采样后被转为对应基于模型UV的每个像素的颜色,最终被显示出来;
		Rect - 一个非2阶数大小的贴图;
		Cube - 即Cube map texture(立方体纹理),简单说就是6张有联系的2D贴图的组合,主要用来做反射效果(比如天空盒和动态反射),
		也会被转换为对应点的采样;
		Range(min, max) - 一个介于最小值和最大值之间的浮点数,一般用来当作调整Shader某些特性的参数(比如透明度渲染的截止值可以是从01的值等);
		Float - 任意一个浮点数;
		Vector - 一个四维数;
	defaultValue 定义了这个属性的默认值,通过输入一个符合格式的默认值来指定对应属性的初始值(某些效果可能需要某些特定的参数值来达到需要的效果,虽然这些值可以在之后在进行调整,
			 但是如果默认就指定为想要的值的话就省去了一个个调整的时间,方便很多)。
	Color -01定义的rgba颜色,比如(1,1,1,1)2D/Rect/Cube - 对于贴图来说,默认值可以为一个代表默认tint颜色的字符串,可以是空字符串或者”white”,”black”,”gray”,”bump”中的一个
	Float,Range - 某个指定的浮点数
	Vector - 一个4维数,写为 (x,y,z,w)
	另外还有一个{option},它只对2D,Rect或者Cube贴图有关,在写输入时我们最少要在贴图之后写一对什么都不含的空白的{},
	当我们需要打开特定选项时可以把其写在这对花括号内。如果需要同时打开多个选项,可以使用空白分隔。
	可能的选择有ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal中的一个,这些都是OpenGL中TexGen的模式

渲染队列

unity为了解决渲染顺序的问题提供了渲染队列,索引越小越先被渲染

render queue:
	  Background:1000
	  Geometry:2000  //不透明的物体
	  AlphaTest:2450
	  Transparent:3000 //透明物体
	  Overlay:4000

在shader中使用
SubShader{
	Tags = {"Queue"="AlphaTest}
	Pass{
	     .....
	}
}

应用阶段传递模型数据给顶点着色器

struct a2v{
      float4  pos:POSOTION //模型空间中的顶点位置
      float3  normal :NORMAL //顶点法线
      float4 tagent :TAGENT   //顶点法线
      float4 color :COLOR      //顶点颜色
      float2 texcood :TEXCOODn  //顶点的纹理坐标
}

RenderType

SubShader {
Tags { “RenderType”=“Opaque” }
CGPROGRAM

ENDCG
}

//表面着色器可以被若干个标签所修饰,通过判断标签来决定硬件什么时候该调用着色器
		/*
		RendererType赋值有:
		1.Opaque:绝大部分的不透明物体渲染时使用
		2.Transparent:绝大部分的透明物体渲染时使用
		3.BackGround:天空盒
		4.Overlay:用来渲染叠加效果,镜头光晕等
		*/
		Tags { "RenderType"="Opaque" }

LOD

LOD是LevelofDetail的缩写,我们能用什么样的shader由它来决定,如果我们在Unity的QualitySetting中设定最大LOD值小于subshader所指定的值时,
则subshader不可使用
Unity的Shader制定了一组LOD值,我们在写shader的时候作为参考,方便以后对设备图形性能调整,和画质有更精确的控制

		Vertexlitkindofshaders(顶点光照类型的shader)=100
		Diffuse(漫反射)=200
		ReflectiveBumpedUnlit(凸起反射不发光)=250
		ReflectiveBumpedVertexlit(顶点反射不发光)=250
		Bumped,Specular(凸起,高光)=300
		凹凸高光=400
		Parallax(视差)=500
		ParallaxSpecular(视差高光)=600

表面着色器的Input

struct Input {
			     // 输入结构体重一般包含着色器所需要的纹理坐标,命名规范:uv + 纹理名称
				 //当使用第二纹理,命名为:uv2+纹理名称
			     float3 viewDir;//视角方向
				 float4 COLOR; //每个顶点的颜色差值
				 float4 screenPos;//屏幕坐标(使用.xy/.wh来获取屏幕2D坐标)
				 float3 worldRefl;// 世界坐标系中反射向量
				 float3 worldNormal;// 世界坐标系中法线向量
				 float2 uv_MainTex;//纹理坐标
		};

表面着色器的inout

 /*
		其作用是结构输入的uv或者附加数据,然后进行处理,最后将结构填充到输出结构体中,所以只能按照规定来写
		参数1:Input:是我们需要定义的输入结构体,可以吧所需要参与计算的数据放到这个结构体中,传入方法使用
		参数2:inout:SurfaceOutput定义输出结构体的类型,需要把方法里面得到的结果赋值给该结构体里面的成员变量即可完成着色
		SurfaceOutput的输出结果结构定义如下:
			half3 Albedo:像素的颜色
			half3 Normal:法线
			half3 Emission:自发光,不受光照影响
			half Specular:高光指数
			half Gloss:光泽度
			half Alpha:透明度
		SurfaceOutPutStandard输出结果定义如下:
			fixed3 Albedo:基础颜色
			fixed3 Normal:切线空间法线
			half Smoothness:是否光滑,0=粗糙,1=光滑
			half Metallic:是否有金属光泽,0=非金属,1=金属
			half Occlusion:遮挡(默认为1)
			fixed Alpha:透明度
	   */
		void surf (Input IN, inout SurfaceOutputStandard o) {
			// Albedo comes from a texture tinted by color
			fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
			o.Albedo = c.rgb;
			// Metallic and smoothness come from slider variables
			o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;
			o.Alpha = c.a;
		}

Tags{“LightMode” = “ForwardBase”}

只有定义了正确的LightMode才能得到一些Unity的内置光照变量

可以选的值如下:
ForwardBase,ForwardAdd,Deferred ,Legacy Vertex Lit,VertexLMRGBM,VertexLM,Legacy Defferred,PrepassBase,PrepassFinal,Always,ShadowCaster,MotionVectors

ForwardBase://用于正向渲染中,该Pass会计算环境光、最重要的平行光、逐顶点/SH光源和Lightmaps光照贴图
ForwardAdd://用于前向渲染。该Pass会计算额外的逐像素光源,每一个Pass对应一个光源
Deferred ://用于延迟渲染。该Pass会渲染G缓冲(G-buffer)
Legacy Vertex Lit://顶点渲染路径
Vertex(Vertex)://当对象未设置光照时,用于旧版Vertex Lit渲染;所有顶点光都被应用。
VertexLMRGBM://当对象被光照时,用于传统的Vertex Lit渲染;在光照图是RGBM编码的平台上(PC和控制台)。
VertexLM://当对象被光照时,用于传统的Vertex Lit渲染;在光照图是双LDR编码的平台上(移动平台)。
Legacy Defferred (light prepass)//延迟顶点渲染路径
PrepassBase://在旧版Deferred Lighting中使用,该Pass会渲染法线和高光反射的指数部分。
PrepassFinal://在旧版Deferred Lighting中使用,该Pass通过合并纹理、光照和自发光来渲染得到最后的颜色。其他特殊的光照模式 :
Always://始终渲染;不会计算任何光照效果。
ShadowCaster://将对象深度渲染到阴影贴图或深度纹理中。
MotionVectors://用于计算每个对象的运动矢量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值