标签:
Surface Shader:
(1)必须放在SubShdader块,不能放在Pass内部;
(2)#pragma sufrace surfaceFunction lightModel [optionalparams]
(3)格式
CG规定了声明为表面着色器的方法(就是我们这里的surf)的参数类型和名字,因此我们没有权利决定surf的输入输出参数的类型,只能按照规定写。这个规定就是第一个参数是一个Input结构,第二个参数是一个inout的SurfaceOutput结构。
struct SurfaceOutput {
half3 Albedo; //像素的颜色
half3 Normal; //像素的法向值
half3 Emission; //像素的发散颜色
half Specular; //像素的镜面高光
half Gloss; //像素的发光强度
half Alpha; //像素的透明度
};
sampler2D就是GLSL中的2D贴图的类型,相应的,还有sampler1D,sampler3d,samplerCube等等格式。而具体地想知道像素与坐标的对应关系,以及获取这些数据,我们总不能一次一次去自己计算内存地址或者偏移,因此可以通过sampler2D来对贴图进 行操作。
在CG程序中,我们有这样的约定,在一个贴图变量(在我们例子中是_MainTex)之前加上uv两个字母,就代表提取它的uv值(其实就是两个代表贴图上点的二维坐标 )。
Input 这个输入结构通常拥有着色器需要的所有纹理坐标(texture coordinates)。纹理坐标(Texturecoordinates)必须被命名为“uv”后接纹理(texture)名字。(或者uv2开始,使用第二纹理坐标集)。
可以在输入结构中根据自己的需要,可选附加这样的一些候选值:
float3 viewDir - 视图方向( view direction)值。为了计算视差效果(Parallax effects),边缘光照(rim lighting)等,需要包含视图方向( view direction)值。
float4 with COLOR semantic -每个顶点(per-vertex)颜色的插值。
float4 screenPos - 屏幕空间中的位置。 为了反射效果,需要包含屏幕空间中的位置信息。比如在Dark Unity中所使用的 WetStreet着色器。
float3 worldPos - 世界空间中的位置。
float3 worldRefl - 世界空间中的反射向量。如果表面着色器(surface shader)不写入法线(o.Normal)参数,将包含这个参数。 请参考这个例子:Reflect-Diffuse 着色器。
float3 worldNormal - 世界空间中的法线向量(normal vector)。如果表面着色器(surface shader)不写入法线(o.Normal)参数,将包含这个参数。
float3 worldRefl; INTERNAL_DATA - 世界空间中的反射向量。如果表面着色器(surface shader)不写入法线(o.Normal)参数,将包含这个参数。为了获得基于每个顶点法线贴图( per-pixel normal map)的反射向量(reflection vector)需要使用世界反射向量(WorldReflectionVector (IN, o.Normal))。
float3 worldNormal; INTERNAL_DATA -世界空间中的法线向量(normal vector)。如果表面着色器(surface shader)不写入法线(o.Normal)参数,将包含这个参数。为了获得基于每个顶点法线贴图( per-pixel normal map)的法线向量(normal vector)需要使用世界法线向量(WorldNormalVector (IN, o.Normal))。
vertex shader modifier:Surface Shader还可以单独指定一个vertex shader,用于做一些运算,vertex函数拥有固定的输入参数 inout appdata_full
。下面的例子通过vertex shader对顶点在发现方向上做了一些偏移:
#pragma surface surf Lambert vertex:vert void vert (inout appdata_full v) { v.vertex.xyz += v.normal * _Amount; }
也可在vertex shader中计算自定义变量(Input中的这些变量不能以uv开头,否则会出错),这个计算结果会逐像素的传递到surface shader, 如下:
Shader "James/Surface/CustomData" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Lambert vertex:vert sampler2D _MainTex; struct Input { float2 uv_MainTex; float3 customColor; // 自定义数据 }; void vert(inout appdata_full, out Input o) { UNITY_INITIALIZE_OUTPUT(Input, o); o.customColor = abs(v.normal); // 在vs中计算自定义数据 } void surf (Input IN, inout SurfaceOutput o) { clip(frac((IN.worldPos.y + IN.worldPos.z * 0.1) * 5) - 0.5); o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb; o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); } ENDCG } FallBack "Diffuse" }
final color modifier: 编译指令为finalcolor:functionName,函数接收三个参数 Input IN, SurfaceOutput o, inout fixed4 color
final color会影响渲染的最终颜色,它在所有的计算的最后进行影响,比如lightmap、lightprobe等产生的颜色也会受此函数影响。
final color可以用来实现fog,fog只影响渲染的rgb,而不影响alpha,fog的原理是让物体在最终的rgb和fog.color之间根据距离进行过度。
Shader "James/Surface Shader/Final Color Fog Liner" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Lambert finalcolor:mycolor vertex:myvert sampler2D _MainTex; uniform half4 unity_FogColor; uniform half4 unity_FogStart; uniform half4 unity_FogEnd; struct Input { float2 uv_MainTex; half fog; }; // 顶点着色函数 void myvert (inout appdata_full v, out Input data) { UNITY_INITIALIZE_OUTPUT(Input,data); float pos = length(mul (UNITY_MATRIX_MV, v.vertex).xyz); float diff = unity_FogEnd.x - unity_FogStart.x; float invDiff = 1.0f / diff; data.fog = clamp ((unity_FogEnd.x - pos) * invDiff, 0.0, 1.0); } // final color处理函数 void mycolor (Input IN, SurfaceOutput o, inout fixed4 color) { fixed3 fogColor = unity_FogColor.rgb; #ifdef UNITY_PASS_FORWARDADD fogColor = 0; #endif color.rgb = lerp (fogColor, color.rgb, IN.fog); } void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }
uniform:用于指定变量的数据初始化方式。 Uniform inputs,表示一些与三维渲染有关的离散信息数据,这些数据通常由应用程序传入,并通常不会随着图元信息的变化而变化,如材质对光的反射信息、运动矩阵等。Uniform 修辞一个参数,表示该参数的值由外部应用程序初始化并传入。
使用Uniform 修辞的变量,除了数据来源不同外,与其他变量是完全一样的。需要注意的一点是:uniform 修辞的变量的值是从外部传入的,所以在Cg 程序(顶点程序和片段程序)中通常使用uniform 参数修辞函数形参,不容许声明一个用uniform 修辞的局部变量!
标签:
原文地址:http://www.cnblogs.com/sifenkesi/p/4678254.html