主要参考博客:http://blog.csdn.net/mobanchengshuang?viewmode=contents
1.模型自身坐标位置与颜色的映射
Shader "Custom/RGBCube" { SubShader { Pass { CGPROGRAM #pragma vertex vert //顶点着色器入口函数声明 #pragma fragment frag // 片段着色器入口函数声明 //顶点输出结构体 struct vertexOutput { //声明结构体的成员pos,类型为float类型的4元向量,语义为SV_POSITION,col同理; float4 pos : SV_POSITION; float4 col : TEXCOORD0; }; //顶点着色器入口函数vert,与pragma第一条声明匹配,返回类型为刚刚定义的顶点输出结构体 vertexOutput vert(float4 vertexPos : POSITION) { vertexOutput output; //这里不需要struct关键字 //顶点着色器将数据写入输出结构体中。 output.pos = mul(UNITY_MATRIX_MVP, vertexPos); //mul是顶点变换函数,UNITY_MATRIX_MVP是unity的内建矩阵,vertexPos是这个函数的形参 //此行代码的作用为将形参vertexPos(本例即Cube对象的顶点向量)按照unity的内建矩阵进行顶点变换 output.col = vertexPos + float4(0.5, 0.5, 0.5, 0.0); //这行代码是实现RGB立方体的关键 //因为我们的直角坐标系原点没有在顶点上而是在cube的几何中心,故其值域为{-0,5,-0.5,-0.5,1}至{0.5,0.5,0.5,1} //但是这里接受的类型为float4,可见第四元应该是无意义的常数1 //意思是vertexPos的值域为{-0.5,-0.5,-0.5,1}至{0.5,0.5,0.5,1} //而对这个值域进行+{0.5,0.5,0.5,0}的矢量相加才能得到RGB (A恒定为1)的所有颜色区间 return output; //将输出结构体返回,进入下一个环节(简单理解为给片段着色器) //ps:更细致的环节有顶点变换-->顶点着色-->几何元的构建-->光栅化几何元 //-->片段着色-->略 } //片段着色器入口函数frag,与pragma第二条声明匹配,返回类型为float4语义为COLOR, //这里除了颜色没有其他的输出,所以没有输出结构体 float4 frag(vertexOutput input) : COLOR //此函数的形参类型为顶点着色器的输出结构体,没有语义 //原因就在于片段着色器位于顶点着色器的下一个环节,参数按照这个顺序传递 { //由于col属性已经在顶点着色器中计算,直接返回进入下一环节 //下一环节是什么这里不探讨了 return input.col; } ENDCG } } //如果以上SubShader渲染失败则回滚采用Diffuse FallBack "Diffuse" }
2.模型纹理坐标与颜色的映射
Shader "Custom/RGBCube" { SubShader { Pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct vertexOutput { float4 pos : SV_POSITION; float4 col : TEXCOORD0; }; vertexOutput vert(appdata_full input) { vertexOutput output; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); output.col = input.texcoord; return output; } float4 frag(vertexOutput input) : COLOR { return input.col; } ENDCG} } //如果以上SubShader渲染失败则回滚采用Diffuse FallBack "Diffuse" }
3.假彩色效果
Shader "Custom/RGBCube" { SubShader { Pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct vertexOutput { float4 pos : SV_POSITION; float4 col : TEXCOORD0; }; vertexOutput vert(appdata_full input) { vertexOutput output; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); output.col = float4(0.0, input.texcoord.y, 0.0, 1.0); return output; } float4 frag(vertexOutput input) : COLOR { return input.col; } ENDCG} } //如果以上SubShader渲染失败则回滚采用Diffuse FallBack "Diffuse" }
4.法向量与颜色的映射
Shader "Custom/RGBCube" { SubShader { Pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct vertexOutput { float4 pos : SV_POSITION; float4 col : TEXCOORD0; }; vertexOutput vert(appdata_full input) { vertexOutput output; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); output.col = float4((input.normal + float3(1.0, 1.0, 1.0)) / 2.0, 1.0); return output; } float4 frag(vertexOutput input) : COLOR { return input.col; } ENDCG} } //如果以上SubShader渲染失败则回滚采用Diffuse FallBack "Diffuse" }
5.裁剪效果
Shader "Custom/RGBCube" { SubShader { Pass{ Cull Off // 关掉裁剪模式,作用后面再说 CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct vertexOutput { float4 pos : SV_POSITION; //由顶点着色器输出mesh信息中的纹理坐标,这个坐标是以对象为坐标系的 float4 posInObjectCoords : TEXCOORD0; }; vertexOutput vert(appdata_full input) { vertexOutput output; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); //直接把texcoord传递给片段着色器 output.posInObjectCoords = input.texcoord; return output; } float4 frag(vertexOutput input) : COLOR { //当坐标的y值大于0.5的时候擦除片段 if (input.posInObjectCoords.y > 0.5) { discard; } //其余部分仍然按y值大小生成经度绿色球 return float4(0.0, input.posInObjectCoords.y , 0.0, 1.0); } ENDCG } } //如果以上SubShader渲染失败则回滚采用Diffuse FallBack "Diffuse" }
6.内部裁剪与外部裁剪
Shader "Custom/RGBCube" { SubShader { Pass{ Cull front // 外部剪裁,那么这个通道可以理解为是给篮球的内表面上色 CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct vertexOutput { float4 pos : SV_POSITION; //由顶点着色器输出mesh信息中的纹理坐标,这个坐标是以对象为坐标系的 float4 posInObjectCoords : TEXCOORD0; }; vertexOutput vert(appdata_full input) { vertexOutput output; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); //直接把texcoord传递给片段着色器 output.posInObjectCoords = input.texcoord; return output; } float4 frag(vertexOutput input) : COLOR { //当坐标的y值大于0.5的时候擦除片段 if (input.posInObjectCoords.y > 0.5) { discard; } //其余部分仍然按y值大小生成经度绿色球 return float4(0.0, input.posInObjectCoords.y , 0.0, 1.0); } ENDCG } Pass{ Cull back //内部剪裁,那么这个通道可以理解为是给篮球的外表面上色 CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct vertexOutput { float4 pos : SV_POSITION; //由顶点着色器输出mesh信息中的纹理坐标,这个坐标是以对象为坐标系的 float4 posInObjectCoords : TEXCOORD0; }; vertexOutput vert(appdata_full input) { vertexOutput output; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); //直接把texcoord传递给片段着色器 output.posInObjectCoords = input.texcoord; return output; } float4 frag(vertexOutput input) : COLOR { //当坐标的y值大于0.5的时候擦除片段 if (input.posInObjectCoords.y > 0.5) { discard; } //其余部分仍然按y值大小生成经度红色球 return float4(input.posInObjectCoords.y, 0.0 , 0.0, 1.0); } ENDCG } } //如果以上SubShader渲染失败则回滚采用Diffuse FallBack "Diffuse" }
7.圆角矩形
Shader "Custom/RoundRect" { Properties { //两种内容模式,图片模式 _MainTex ("Base (RGB)", 2D) = "white" {} //纯色模式 //_MainColor ("Color", COLOR) = (1,1,1,1) //圆角半径,默认为0.1 _Radius("Radius",float) = 0.1 } SubShader { Pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" //获取3个属性 并传值到CG代码段 sampler2D _MainTex; float _Radius; float4 _MainColor; struct vertexOutput { float4 pos : SV_POSITION; //由顶点着色器输出mesh信息中的纹理坐标,这个坐标是以对象为坐标系的 float4 posInObjectCoords : TEXCOORD0; }; vertexOutput vert(appdata_full input) { vertexOutput output; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); //直接把texcoord传递给片段着色器 output.posInObjectCoords = input.texcoord; return output; } //片段着色器入口函数 float4 frag(vertexOutput input) : COLOR { float4 c = tex2D(_MainTex, input.posInObjectCoords);//将图片信息按坐标转换成颜色 //float4 c=_MainColor; //纯色 //x,y两个变元,区间均为[0,1] float x = input.posInObjectCoords.x; float y = input.posInObjectCoords.y; if (x < _Radius && y < _Radius) { if (pow((x - _Radius), 2) + pow(y - _Radius, 2) > pow(_Radius, 2)) discard; } else if (x < _Radius && y > (1 - _Radius)) { if (pow((x - _Radius), 2) + pow(y - (1 - _Radius), 2) > pow(_Radius, 2)) discard; } else if (x > (1 - _Radius) && y < _Radius) { if (pow((x - (1 - _Radius)), 2) + pow(y - _Radius, 2) > pow(_Radius, 2)) discard; } else if (x > (1 - _Radius) && y > (1 - _Radius)) { if (pow((x - (1 - _Radius)), 2) + pow(y - (1 - _Radius), 2) > pow(_Radius, 2)) discard; } return c; } ENDCG } } FallBack "Diffuse" }
8.漫反射
Shader "Esfog/Diffuse" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { Pass { Tags { "RenderType"="Opaque" "LightMode"="ForwardBase"} CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" uniform sampler2D _MainTex; uniform float4 _LightColor0; struct VertexOutput { float4 pos:SV_POSITION; float2 uv_MainTex:TEXCOORD0; float3 normal:TEXCOORD1; }; VertexOutput vert(appdata_base input) { VertexOutput o; o.pos = mul(UNITY_MATRIX_MVP,input.vertex); o.uv_MainTex = input.texcoord.xy; o.normal = normalize(mul(float4(input.normal,0),_World2Object)); return o; } float4 frag(VertexOutput input):COLOR { float3 normalDir = normalize(input.normal); float3 lightDir = normalize(_WorldSpaceLightPos0.xyz); float3 Kd = tex2D(_MainTex,input.uv_MainTex).xyz; float3 diffuseReflection = Kd * _LightColor0.rgb * max(0,dot(normalDir,lightDir)); return float4(diffuseReflection,1); } ENDCG } } FallBack "Diffuse" }
9.多光源漫反射
Shader "Esfog/Diffuse" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { Pass { Tags { "RenderType"="Opaque" "LightMode"="ForwardBase"} CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" uniform sampler2D _MainTex; uniform float4 _LightColor0; struct VertexOutput { float4 pos:SV_POSITION; float2 uv_MainTex:TEXCOORD0; float3 normal:TEXCOORD1; }; VertexOutput vert(appdata_base input) { VertexOutput o; o.pos = mul(UNITY_MATRIX_MVP,input.vertex); o.uv_MainTex = input.texcoord.xy; o.normal = normalize(mul(float4(input.normal,0),_World2Object)); return o; } float4 frag(VertexOutput input):COLOR { float3 normalDir = normalize(input.normal); float3 lightDir = normalize(_WorldSpaceLightPos0.xyz); float3 Kd = tex2D(_MainTex,input.uv_MainTex).xyz; float3 diffuseReflection = Kd * _LightColor0.rgb * max(0,dot(normalDir,lightDir)); return float4(diffuseReflection,1); } ENDCG } Pass { Tags { "RenderType"="Opaque" "LightMode"="ForwardAdd"} //此通道的片段着色器输出颜色时帧缓存已经有了颜色,所以需要混合 //混合模式为1比1 Blend One One CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" uniform sampler2D _MainTex; uniform float4 _LightColor0; struct VertexOutput { float4 pos:SV_POSITION; float2 uv_MainTex:TEXCOORD0; float3 normal:TEXCOORD1; }; VertexOutput vert(appdata_base input) { VertexOutput o; o.pos = mul(UNITY_MATRIX_MVP,input.vertex); o.uv_MainTex = input.texcoord.xy; o.normal = normalize(mul(float4(input.normal,0),_World2Object)); return o; } float4 frag(VertexOutput input):COLOR { float3 normalDir = normalize(input.normal); float3 lightDir = normalize(_WorldSpaceLightPos0.xyz); float3 Kd = tex2D(_MainTex,input.uv_MainTex).xyz; float3 diffuseReflection = Kd * _LightColor0.rgb * max(0,dot(normalDir,lightDir)); return float4(diffuseReflection,1); } ENDCG } } FallBack "Diffuse" }
10.逐顶点的镜面反射