1.所有Unity的Shader数据的来源
先获取MaterialPropertyBlock设置的数据,再获取Render物体(Render关联的Mesh Filter中获取)的材质球设置的数据,然后从全局内建或通过程序设置的数据,最后使用默认数据。
材质对象可以获取编辑器上序列化的数据,或通过app动态改变属性(矩阵和数组只能动态写入,不能序列化)。
How property values are provided to shaders
Shader property values are found and provided to shaders from these places:
Per-Renderer values set in MaterialPropertyBlock. This is typically “per-instance” data (e.g. customized tint color for a lot of objects that all share the same material).
Values set in the Material that’s used on the rendered object.
Global shader properties, set either by Unity rendering code itself (see built-in shader variables), or from your own scripts (e.g. Shader.SetGlobalTexture).
The order of precedence is like above: per-instance data overrides everything; then Material data is used; and finally if shader property does not exist in these two places then global property value is used. Finally,
if there’s no shader property value defined anywhere, then “default” (zero for floats, black for colors, empty white texture for textures) value will be provided.
2.Unity材质Property属性和各种类型Shader之间的数据传递
1)顶点/片段着色器材质属性声明:要对应,可以不必uniform声明,也有一些预定义类似_MainTex的UV为_MainTex_ST,高动态图为{TextureName}_HDR
预定义见CG语言的定义,如UnityCG.cginc 。
顶点着色器变换到裁剪空间4D空间,还没有透视除法到NDC空间。
片段着色器是屏幕变换光栅插值后在片段各种信息下进行组合,片段着色器后会进行光照镜面高光辅助颜色叠加和雾化处理。
For example these shader properties:
_MyColor ("Some Color", Color) = (1,1,1,1)
_MyVector ("Some Vector", Vector) = (0,0,0,0)
_MyFloat ("My float", Float) = 0.5
_MyTexture ("Texture", 2D) = "white" {}
_MyCubemap ("Cubemap", CUBE) = "" {}
would be declared for access in Cg/HLSL code as:
fixed4 _MyColor; // low precision type is usually enough for colors
float4 _MyVector;
float _MyFloat;
sampler2D _MyTexture;
samplerCUBE _MyCubemap;
Cg/HLSL can also accept uniform keyword, but it is not necessary:
uniform float4 _MyColor;
2)固定管线中因为都是ShaderLab所以可以直接使用:
例如_MainTex:
Shader "Reveal Backfaces" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" { }
}
SubShader {
// Render the front-facing parts of the object.
// We use a simple white material, and apply the main texture.
Pass {
Material {
Diffuse (1,1,1,1)
}
Lighting On
SetTexture [_MainTex] {
Combine Primary * Texture
}
}
// Now we render the back-facing triangles in the most
// irritating color in the world: BRIGHT PINK!
Pass {
Color (1,0,1,1)
Cull Front
}
}
}
3)Surface着色器,会使用内建的脚本,所以不用每个材质property都使用,类似BlinnPhong可能是调用延迟的LightingBlinnPhong_PrePass:
Shader "Tessellation Sample" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_DispTex ("Disp Texture", 2D) = "gray" {}
_NormalMap ("Normalmap", 2D) = "bump" {}
_Displacement ("Displacement", Range(0, 1.0)) = 0.3
_Color ("Color", color) = (1,1,1,0)
_SpecColor ("Spec color", color) = (0.5,0.5,0.5,0.5)
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 300
CGPROGRAM
#pragma surface surf BlinnPhong addshadow fullforwardshadows vertex:disp nolightmap
#pragma target 4.6
struct appdata {
float4 vertex : POSITION;// 类型是CG/HLSL预定义的寄存器名称
float4 tangent : TANGENT;
float3 normal : NORMAL;
float2 texcoord : TEXCOORD0;
};
sampler2D _DispTex;
float _Displacement;
sampler2D _MainTex;
sampler2D _NormalMap;
fixed4 _Color;
3.光照模型的实现
除了漫反射,镜面反射,多光源,衰减计算,雾计算,还有阴影计算,阴影用:
fixed shadow = SHADOW_ATTENUATION(i);见:https://docs.unity3d.com/Manual/SL-VertexFragmentShaderExamples.html
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
// compute shadow attenuation (1.0 = fully lit, 0.0 = fully shadowed)
fixed shadow = SHADOW_ATTENUATION(i);
// darken light's illumination with shadow, keep ambient intact
fixed3 lighting = i.diff * shadow + i.ambient;
col.rgb *= lighting;
return col;
}
更多顶点/片段着色器语法和利用内建的寄存器,变量,函数,编译指定见: