赞
踩
-
- Shader "MilkShader/14/ToonShading"
- {
- Properties
- {
- _Color("Color Tint", Color) = (1,1,1,1)
- _MainTex ("Main Tex", 2D) = "white"{}
- _Ramp("Ramp Texture", 2D) = "white"{} //漫反射渐变纹理
- _Outline("Outline", Range(0,1)) = 0.1 //轮廓线宽度
- _OutlineColor("Outline Color", Color) = (1,1,1,1)
- _Specular ("Specular", Color) = (1,1,1,1) //高光反射颜色
- _SpecularScale ("Specular Scale", Range(0, 0.1)) = 0.01 //阈值
- }
- SubShader
- {
- Tags { "RenderType"="Opaque" "Queue"="Geometry"}
- LOD 100
-
- Pass
- {
- //第一个PASS是用法线进行向外扩展,然后只渲染背面,颜色输出是边缘颜色
- NAME "OUTLINE"
- Cull Front
-
- CGPROGRAM
-
- #pragma vertex vert
- #pragma fragment frag
-
- #include "UnityCG.cginc"
-
- float _Outline;
- fixed4 _OutlineColor;
-
- struct a2v {
- float4 vertex : POSITION;
- float3 normal : NORMAL;
- };
-
- struct v2f {
- float4 pos : SV_POSITION;
- };
-
- v2f vert(a2v v){
- v2f o;
- //将顶点和法线转到视角空间下
- float4 pos = mul(UNITY_MATRIX_MV, v.vertex);
- float3 normal = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);
- //设置法线的z分量,对其归一化后在将顶点沿其方向扩张
- //设置法线z的处理是为了尽可能避免背面扩张(现在我们渲染的是背面)后的顶点挡住正面的面片.
- normal.z = -0.5;
- //在视角空间下进行的一个顶点位置偏移(向法线方向)
- pos = pos + float4(normalize(normal), 0) * _Outline;
- //再转为裁剪空间
- o.pos = mul(UNITY_MATRIX_P, pos);
- return o;
- }
- float4 frag(v2f i) : SV_Target{
- //直接输出边缘颜色
- return float4(_OutlineColor.rgb, 1);
- }
- ENDCG
- }
-
- Pass{
- //前向渲染
- Tags{"LightMode"="ForwardBase"}
-
- Cull Back
-
- CGPROGRAM
-
- #include "UnityCG.cginc"
- #include "Lighting.cginc"//漫反射、高光反射需要的
- #include "AutoLight.cginc"//这是阴影三剑客需要的头文件
- #include "UnityShaderVariables.cginc"
-
- #pragma vertex vert
- #pragma fragment frag
-
- #pragma multi_compile_fwdbase
-
- sampler2D _MainTex;
- float4 _MainTex_ST;
- fixed4 _Color;
- sampler2D _Ramp;
- fixed4 _Specular;
- fixed _SpecularScale;
-
- struct a2v {
- float4 vertex : POSITION;
- float3 normal : NORMAL;
- float4 texcoord : TEXCOORD0;
- //float4 tangent : TANGENT; 为啥例子会有tangent
- };
-
- struct v2f {
- float4 pos : POSITION;
- float2 uv : TEXCOORD0;
- float3 worldNormal : TEXCOORD1;
- float3 worldPos : TEXCOORD2;
- SHADOW_COORDS(3)
- };
-
- v2f vert (a2v v) {
- v2f o;
-
- o.pos = UnityObjectToClipPos( v.vertex);
- o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
- o.worldNormal = UnityObjectToWorldNormal(v.normal);
- o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
-
- TRANSFER_SHADOW(o);
- return o;
- }
-
- float4 frag(v2f i) :SV_Target{
- fixed3 worldNormal = normalize(i.worldNormal);
- fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
- fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
- fixed3 worldHalfDir = normalize(worldLightDir + worldViewDir);
-
- fixed4 c = tex2D (_MainTex, i.uv);
- fixed3 albedo = c.rgb * _Color.rgb;
-
- fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
- UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
-
- fixed diff = dot(worldNormal, worldLightDir);
- diff = (diff * 0.5 + 0.5) * atten; //先进行转为(0,1)范围,再乘以衰减值*阴影
- //这里的漫反射是用渐变纹理方式,diff作为纹理坐标进行采样,通过这种方式采样出的漫反射颜色是卡通化的
- fixed3 diffuse = _LightColor0.rgb * albedo * tex2D(_Ramp, float2(diff, diff)).rgb;
-
- fixed spec = dot(worldNormal, worldHalfDir);
- fixed w = fwidth(spec) * 2.0;//抗锯齿处理? 这种获取w阈值绝对值的方式很懵逼
- //下面lerp(...)是比较复杂的,先假设_SpecularScale为0.5, spec是(0,1)的一个动态数值根据halfDir和normal而变化
- // spec + _SpecularScale - 1 是将 spec从(0,1)转为(-(1-_SpecularScale), _SpecularScale),现在是(-0.5, 0.5)
- // w实际上可以直接理解为是一个动态的阈值范围, 实际上可以直接看成固定的比如:[-0.3, 0.3]
- // 此时当spec + _SpecularScale - 1 小于 -0.3(-w)时就会返回0, 在-w,w之间时就会返回0~1, 大于w时会返回1
- // 这样这个高光反射系数就不会产生突变而是渐变效果
- // 书上直接说_SpecularScale是一个阈值,而我的理解是如上,不然太难理解了..
- // 这样我们得到的高光反射颜色是一个个块状的,而不是之前那样子的 之前是pow(dot(normal, half), x)
- // 这种lerp(...) 处理 如果觉得难以理解的话 简单的做法是 直接 step(阈值, dot(...)) 当点积大于阈值时会返回1,小于阈值时会返回0
- // 但是这种做法就是导致了突变,高光部分会产生锯齿,可以想象假设 阈值时 0.5, 那么当 (0.5, 1)时直接返回1,(0,0.5)时候返回0
- // 在0.49 时候还是0, 逐渐变为0.51时突变为1, 反过来也是一样,高光颜色会直接从0,突变为有色状态,锯齿就是由于突变导致的。
- // 上面那个阈值0.5,可看成一个分界线, 当dot()在0.5(左边)时就会返回0,在0.5的右边时返回1
- // 此时下面的做法就是 将这个分界线,变成了2个! 即 -w 和 w, 虽然这2个值得获取很难理解,但是就可以直接理解为就是一个很小的常数
- // 当dot() < -w 时,返回的是0, > w时候 返回的是1, 在(-w,w)中间时返回的是0~1的数值,所以效果就是渐变,解决了抗锯齿问题
- fixed3 specular = _Specular.rgb * lerp(0,1, smoothstep(-w,w,spec + _SpecularScale - 1)) * step(0.0001, _SpecularScale);
-
- return fixed4(ambient + diffuse + specular, 1.0);
- }
-
- ENDCG
- }
- }
- Fallback "Diffuse"
- }
- Shader "MilkShader/14/Hatching"
- {
- Properties
- {
- _Color ("Color Tint", Color) = (1,1,1,1) //控制颜色
- _TileFactor ("Tile Factor", Float) = 1 //平铺系数(对纹理坐标的缩放系数<x,y都有影响>)
- //描边使用的参数
- _Outline("Outline", Range(0,1)) = 0.1
- _OutlineColor("Outline Color", Color) = (1,1,1,1)
- //六张素描纹理(逐渐增多横向线条的纹理)
- _Hatch0 ("Hatch 0", 2D) = "white"{}
- _Hatch1 ("Hatch 1", 2D) = "white"{}
- _Hatch2 ("Hatch 2", 2D) = "white"{}
- _Hatch3 ("Hatch 3", 2D) = "white"{}
- _Hatch4 ("Hatch 4", 2D) = "white"{}
- _Hatch5 ("Hatch 5", 2D) = "white"{}
- }
- SubShader
- {
- Tags { "RenderType"="Opaque" "Queue"="Geometry"}
-
- UsePass "MilkShader/14/ToonShading/OUTLINE"//使用了之前的描边PASS
-
- Pass
- {
- Tags{ "LightMode" = "ForwardBase"}
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- // make fog work
- #pragma multi_compile_fwdbase
-
- #include "UnityCG.cginc"
- #include "Lighting.cginc"
- #include "AutoLight.cginc"
- #include "UnityShaderVariables.cginc"
-
- fixed4 _Color;
- fixed _TileFactor;
- fixed _Outline;
- fixed4 _OutlineColor;
- sampler2D _Hatch0;
- sampler2D _Hatch1;
- sampler2D _Hatch2;
- sampler2D _Hatch3;
- sampler2D _Hatch4;
- sampler2D _Hatch5;
-
- struct appdata
- {
- float4 vertex : POSITION;
- float4 tangent : TANGENT;
- float2 texcoord : TEXCOORD0;
- float3 normal : NORMAL;
- };
-
- struct v2f
- {
- float4 pos : SV_POSITION;
- float2 uv : TEXCOORD0;
- fixed3 hatchWeight0 : TEXCOORD1;
- fixed3 hatchWeight1 : TEXCOORD2;
- float3 worldPos : TEXCOORD3;
- SHADOW_COORDS(4)
- };
-
- v2f vert (appdata v)
- {
- v2f o;
- o.pos = UnityObjectToClipPos(v.vertex);
-
- o.uv = v.texcoord.xy * _TileFactor;
-
- fixed3 worldNormal = normalize(UnityObjectToWorldNormal(v.normal));
- fixed3 worldLightDir = normalize(WorldSpaceLightDir(v.vertex));
- //法线和光源的点积
- fixed diff = max(0, dot(worldNormal, worldLightDir));
-
- //将diff转到[0,7]范围
- float hatchFactor = diff * 7.0;
-
- o.hatchWeight0 = fixed3(0,0,0);
- o.hatchWeight1 = fixed3(0,0,0);
- //分别判断每一个区间[0,1] [1,2] [2,3] [3,4] [4,5] [5,6] [6,7]再计算对应区间的素描纹理权重值
- //这个是固定的算法,记住是这样写就好了,如果想研究的话可以参考冯乐乐的第十四章
- //实际上就是不同的区间时会对其中1个或2个素描纹理权重进行赋值,以此在片元着色器进行使用它们来进行与相应素描颜色进行相乘
- //也就是决定在什么情况下,哪几个素描纹理产生多少影响
- // hatchWeight0.x 是 第一个素描纹理的权重, 以此类推 hatchWeight1.z 是最后一个素描纹理的权重
- // 初始化全为0是表示素描纹理完全没有任何作用
- if(hatchFactor > 6.0){
- }else if(hatchFactor > 5.0){
- o.hatchWeight0.x = hatchFactor - 5.0;
- }else if(hatchFactor > 4.0){
- o.hatchWeight0.x = hatchFactor - 4.0;
- o.hatchWeight0.y = 1 - o.hatchWeight0.x;
- }else if(hatchFactor > 3.0){
- o.hatchWeight0.y = hatchFactor - 3.0;
- o.hatchWeight0.z = 1 - o.hatchWeight0.y;
- }else if(hatchFactor > 2.0){
- o.hatchWeight0.z = hatchFactor - 2.0;
- o.hatchWeight1.x = 1 - o.hatchWeight0.z;
- }else if(hatchFactor > 1.0){
- o.hatchWeight1.x = hatchFactor - 1.0;
- o.hatchWeight1.y = 1 - o.hatchWeight1.x;
- }else{
- o.hatchWeight1.y = hatchFactor;
- o.hatchWeight1.z = 1 - o.hatchWeight1.y;
- }
-
- o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
-
- TRANSFER_SHADOW(o);
-
- return o;
- }
-
- fixed4 frag (v2f i) : SV_Target
- {
- //从不同的素描纹理采样后乘以相应的素描纹理权重值(在顶点着色器我们就已经对它们进行了一个赋值)
- fixed4 hatchTex0 = tex2D(_Hatch0, i.uv) * i.hatchWeight0.x;
- fixed4 hatchTex1 = tex2D(_Hatch1, i.uv) * i.hatchWeight0.y;
- fixed4 hatchTex2 = tex2D(_Hatch2, i.uv) * i.hatchWeight0.z;
- fixed4 hatchTex3 = tex2D(_Hatch3, i.uv) * i.hatchWeight1.x;
- fixed4 hatchTex4 = tex2D(_Hatch4, i.uv) * i.hatchWeight1.y;
- fixed4 hatchTex5 = tex2D(_Hatch5, i.uv) * i.hatchWeight1.z;
- //非素描部分的颜色是白色(如果素描的纹理权重总和越大,非素描部分越黑,否则越白)
- fixed4 whiteColor = fixed4(1,1,1,1) * (1 - i.hatchWeight0.x - i.hatchWeight0.y - i.hatchWeight0.z - i.hatchWeight1.x
- - i.hatchWeight1.y - i.hatchWeight1.z);
-
- fixed4 hatchColor = hatchTex0 + hatchTex1 + hatchTex2 + hatchTex3 + hatchTex4 + hatchTex5 + whiteColor;
-
- UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
-
- return fixed4(hatchColor.rgb * _Color.rgb * atten, 1.0);
- }
- ENDCG
- }
- }
- Fallback "Diffuse"
- }
平铺系数越大素描的线越密集,否则反之。
中秋节快乐!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。