Shader程序的基本结构
在代码中学习吧,注释都写好了。
Shader "First Fantasy/Water/Water Diffuse" { //定义着色器属性; Properties { /* 格式:_Name("Display Name", type) = defaultValue[{options}]; { _Name - 属性的名字,变量名. Display Name - 这个字符串将显示在Unity的材质编辑器中作为Shader的使用者可读的内容 type - 这个属性的类型,可能的type所表示的内容有以下几种: Color - 一种颜色,由RGBA(红绿蓝和透明度)四个量来定义; 2D - 一张2的阶数大小(256,512之类)的贴图。这张贴图将在采样后被转为对应基于模型UV的每个像素的颜色,最终被显示出来; Rect - 一个非2阶数大小的贴图; Cube - 即Cube map texture(立方体纹理),简单说就是6张有联系的2D贴图的组合,主要用来做反射效果(比如天空盒和动态反射),也会被转换为对应点的采样; Range(min, max) - 一个介于最小值和最大值之间的浮点数,一般用来当作调整Shader某些特性的参数(比如透明度渲染的截止值可以是从0至1的值等); Float - 任意一个浮点数; Vector - 一个四维数; defaultValue -定义了这个属性的默认值。 Color - 以0~1定义的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的模式。 } */ _MainTex ("Base (RGB)", 2D) = "white" {} _MainTexColor ("Diffuse", Color) = (1,1,1,0.55) _MainTexMultiply ("Multiply", Range(0,5)) = 1 _MainTexMoveSpeedU ("U Move Speed", Range(-6,6)) = 0.5 _MainTexMoveSpeedV ("V Move Speed", Range(-6,6)) = 0.5 } SubShader { //硬件将通过判定这些标签来决定什么时候调用该着色器。; /* "Queue"="xxx" --- 指定渲染顺序队列 { Background (1000) - 最早被调用的渲染,用来渲染天空盒或者背景 Geometry (2000) - 这是默认值,用来渲染非透明物体(普通情况下,场景中的绝大多数物体应该是非透明的) AlphaTest (2450) - 用来渲染经过Alpha Test的像素,单独为AlphaTest设定一个Queue是出于对效率的考虑 Transparent (3000) - 以从后往前的顺序渲染透明物体 Overlay (4000) - 用来渲染叠加的效果,是渲染的最后阶段(比如镜头光晕等特效) (PS:我们也可以指定自己的Queue值,写成类似这样:"Queue"="Transparent+100",表示一个在Transparent之后100的Queue上进行调用。 通过调整Queue值,我们可以确保某些物体一定在另一些物体之前或者之后渲染,这个技巧有时候很有用处。) } "RenderType"="Opaque" -- 渲染非透明物体 "RenderType" = "Transparent" -- 渲染含有透明效果的物体 "IgnoreProjector"="True" -- 不被Projectors影响 "ForceNoShadowCasting"="True" -- 从不产生阴影 */ Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } ZWrite Off Alphatest Greater 0 Blend SrcAlpha OneMinusSrcAlpha //Level of Detail的缩写; /* 在Unity的Quality Settings中我们可以设定允许的最大LOD,当设定的LOD小于SubShader所指定的LOD时,这个SubShader将不可用。 Unity内建Shader定义了一组LOD的数值,我们在实现自己的Shader的时候可以将其作为参考来设定自己的LOD数值,这样在之后调整根据设备图形性能来调整画质时可以进行比较精确的控制。 { VertexLit及其系列 = 100 Decal, Reflective VertexLit = 150 Diffuse = 200 Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250 Bumped, Specular = 300 Bumped Specular = 400 Parallax = 500 Parallax Specular = 600 } */ LOD 200 //一个开始标记,表明从这里开始是一段CG程序; CGPROGRAM /* 声明了我们要写一个表面Shader,并指定了光照模型; 格式:#pragma surface surfaceFunction lightModel [optionalparams] { surface - 声明的是一个表面着色器 surfaceFunction - 着色器代码的方法的名字 lightModel - 使用的光照模型。 } */ #pragma surface surf Lambert //!!!对于这段CG程序,要想访问在Properties中所定义的变量的话,必须使用和之前变量相同的名字进行声明。; //sampler2D就是GLSL中的2D贴图的类型,相应的,还有sampler1D,sampler3D,samplerCube等等格式。; sampler2D _MainTex; fixed4 _MainTexColor; fixed _MainTexMultiply; fixed _MainTexMoveSpeedU; fixed _MainTexMoveSpeedV; struct Input { //声明了一个叫做uv_MainTex的包含两个浮点数的变量。; float2 uv_MainTex; }; /* 计算输出时Shader会多次调用surf函数,每次给入一个贴图上的点坐标,来计算输出。 第二个参数是一个可写的SurfaceOutput,SurfaceOutput是预定义的输出结构,我们的surf函数的目标就是根据输入把这个输出结构填上。 SurfaceOutput结构体的定义如下: struct SurfaceOutput { half3 Albedo; //像素的颜色 half3 Normal; //像素的法向值 half3 Emission; //像素的发散颜色 half Specular; //像素的镜面高光 half Gloss; //像素的发光强度 half Alpha; //像素的透明度 }; SurfaceOutput o - 这个就是经过表面计算函数surf处理后的输出 */ void surf (Input IN, inout SurfaceOutput o) { fixed2 MainTexMoveScrolledUV = IN.uv_MainTex; fixed MainTexMoveU = _MainTexMoveSpeedU * _Time; fixed MainTexMoveV = _MainTexMoveSpeedV * _Time; MainTexMoveScrolledUV += fixed2(MainTexMoveU, MainTexMoveV); //tex2d函数,CG程序中用来在一张贴图中对一个点进行采样的方法,返回一个float4。; half4 c = tex2D (_MainTex, MainTexMoveScrolledUV); o.Albedo = c.rgb * _MainTexColor * _MainTexMultiply; o.Alpha = _MainTexColor.a; } ENDCG } FallBack "Diffuse" }
时间: 2024-10-25 17:54:13