unityshader学习笔记3
表面着色器(Surface Shader)
是Unity自己创造的一种着色器代码类型.它需要的代码量很少,Unity在背后做了很多工作,但渲染的代价比较大.
它在本质上和顶点/片元着色器是一样的,当给Unity提供一个表面着色器的时候,它在背后仍旧把它转换成对应的顶点/片元着色器,它可以理解成是Unity对顶点/片元着色器的更高一层的抽象.
它存在的价值在于,Unity为我们处理了很多光照细节,使得我们不需要再操心这些”烦人的事情”.
一个非常简单的表面着色器示例代码:
Shader "Custom/SimpleSurfaceShader" { SubShader { Tags { "RenderType"="Opaque" } CGPROGRAM #pragma surface surf Lambert struct Input { float2 color : COLOR; }; void surf (Input IN, inout SurfaceOutput o) { o.Albedo = 1; } ENDCG } FallBack "Diffuse" }
表面着色器被定义在Subshader语义块中的CGPROGRAM和ENDCG之间,表面着色器不需要开发者关心使用多少个Pass、每个Pass如何渲染等问题,Unity会在背后为我们做好这些事情.
CGPROGRAM和ENDCG之间的代码是使用CG/HLSL编写的,我们需要把CG/HLSL语言嵌套在ShaderLab语言中.
顶点/片元着色器(Vertex/Fragment Shader)
Shader "Custom/SimpleVertexFragmenttShader" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag float4 vert (float4 v : POSITION) : SV_POSITION { return mul(UNITY_MATRIX_MVP, v); } fixed4 frag () : SV_Target { return fixed4(1.0, 0.0, 0.0, 1.0); } ENDCG } } }
顶点/片元着色器的代码也需要定义在CGPROGRAM和ENDCG之间,顶点/片元着色器需要写在Pass语义块内,而非SubShader内,因为我们需要自己定义每个Pass需要使用的Shader代码.可能需要编写更多的代码,但灵活性很高,更重要的是可以控制渲染的实现细节
*选择哪种UnityShader形式:
除非有明确需求必须要使用固定函数着色器(非常老的设备),否则使用表面着色器或顶点/片元着色器
如果想和各种光源打交道,使用表面着色器,需要注意性能表现.
如果光照数目非常少,使用顶点/片元着色器
如果有很多自定义渲染效果,使用顶点/片元着色器
顶点的空间变换过程
Unity内置的变换矩阵