当前位置:   article > 正文

Unity Shader入门学习(6):常用效果_unity cg front

unity cg front

1.卡通渲染

  1. //卡通渲染
  2. //轮廓线渲染原理:渲染物体背面后向外拓展
  3. //轮廓线弃用方案:根据视线与物体法线的夹角大小判断轮廓。理由:应用于正方体等规整物体上时效果极差
  4. Shader "MyToon/Toon-Fragment" {
  5. Properties {
  6. _MainTex ("MainTex", 2D) = "white" {}
  7. _Ramp ("Ramp Texture", 2D) = "white" {}
  8. _Tooniness ("Tooniness", Range(0.1,20)) = 4
  9. _Outline ("Outline", Range(0,0.1)) = 0.01
  10. }
  11. SubShader {
  12. Tags { "RenderType"="Opaque" }
  13. LOD 200
  14. //下面是渲染背面的pass
  15. Pass {
  16. Tags { "LightMode"="ForwardBase" }
  17. Cull Front//剔除正面
  18. Lighting Off
  19. ZWrite On
  20. CGPROGRAM
  21. #pragma vertex vert
  22. #pragma fragment frag
  23. #pragma multi_compile_fwdbase
  24. #include "UnityCG.cginc"
  25. float _Outline;
  26. struct a2v
  27. {
  28. float4 vertex : POSITION;
  29. float3 normal : NORMAL;
  30. };
  31. struct v2f
  32. {
  33. float4 pos : POSITION;
  34. };
  35. v2f vert (a2v v)
  36. {
  37. v2f o;
  38. float4 pos = mul( UNITY_MATRIX_MV, v.vertex); //顶点位置从模型空间转换到观察空间(摄像机空间)
  39. float3 normal = mul(v.normal, (float3x3)UNITY_MATRIX_T_MV);//将法线(向量)从模型空间变换到观察空间。
  40. normal.z = -0.5;//Z方向的值扁平化(使其是一个较小的定值),防止喧宾夺主,挡住正面的渲染结果(不能关闭深度写入来解决)
  41. //将法线与顶点转到观察空间也是为了这一步的扁平化。否则不需要(根据法线与视线夹角的那个方法)
  42. pos = pos + float4(normalize(normal),0) * _Outline;//v.vertex沿着v.normal的方向扩展_Outline倍
  43. o.pos = mul(UNITY_MATRIX_P, pos);//把新的位置转换到投影坐标系中
  44. return o;
  45. }
  46. float4 frag(v2f i) : COLOR
  47. {
  48. return float4(0, 0, 0, 1); //将背面渲染成黑色就返回
  49. }
  50. ENDCG
  51. }
  52. Pass {
  53. Tags { "LightMode"="ForwardBase" }
  54. Cull Back
  55. Lighting On
  56. CGPROGRAM
  57. #pragma vertex vert
  58. #pragma fragment frag
  59. #pragma multi_compile_fwdbase
  60. #include "UnityCG.cginc"
  61. #include "Lighting.cginc"
  62. #include "AutoLight.cginc"
  63. #include "UnityShaderVariables.cginc"
  64. sampler2D _MainTex;
  65. sampler2D _Ramp;
  66. float4 _MainTex_ST;
  67. float _Tooniness;
  68. struct a2v {
  69. float4 vertex : POSITION;//语义POSITION指模型空间下的顶点位置
  70. float3 normal :NORMAL;//语义指模型空间下法线
  71. float4 texcoord:TEXCOORD0;
  72. };
  73. struct v2f {
  74. float4 pos : SV_POSITION;// SV_POSITION指裁剪空间下定点位置
  75. float3 WorldNormal:TEXCOORD0;
  76. float3 WorldPos : TEXCOORD1;
  77. float2 uv:TEXCOORD2;//用于存储纹理坐标
  78. };
  79. v2f vert(a2v v) {
  80. v2f f;
  81. f.WorldNormal= UnityObjectToWorldNormal(v.normal);//法线世界化
  82. //f.WorldNormal = normalize(mul(unity_ObjectToWorld, v.normal));
  83. f.WorldPos = mul(unity_ObjectToWorld, v.vertex);//点坐标世界化
  84. //点坐标世界化,是方便通过世界坐标下的点作为一些内置函数的参数,获取光照方向,视线方向等
  85. f.pos = UnityObjectToClipPos(v.vertex);//点坐标片元化
  86. f.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
  87. //f.uv=v.texcoord.xy*_MainTex_ST.xy+_MainTex_ST.zw;
  88. //_MainTex_ST.xy对纹理进行缩放,_MainTex_ST.zw对纹理偏移
  89. return f;
  90. }
  91. float4 frag(v2f f) : COLOR
  92. {
  93. fixed3 lightDir = normalize(UnityWorldSpaceLightDir(f.WorldPos));
  94. fixed3 worldNormal=normalize(f.WorldNormal);
  95. fixed3 albedo =tex2D(_MainTex,f.uv).rgb;
  96. albedo.rgb = (floor(albedo.rgb*_Tooniness)/_Tooniness);//合并颜色
  97. fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT * albedo;
  98. fixed halfLambert =dot( worldNormal,lightDir)*0.5+0.5;//半兰伯特
  99. fixed3 diffuseColor=tex2D(_Ramp,fixed2(halfLambert,halfLambert)).rgb;
  100. //让半兰伯特的取值范围映射在(0,1),用其数值构建一套纹理坐标,并用这套坐标对渐变纹理采样。
  101. fixed3 diffuse=diffuseColor*_LightColor0.rgb;
  102. return fixed4(ambient + diffuse , 1);
  103. }
  104. ENDCG
  105. }
  106. Pass {
  107. Tags { "LightMode"="ForwardAdd" }
  108. Cull Back
  109. Lighting On
  110. Blend One One
  111. CGPROGRAM
  112. #pragma vertex vert
  113. #pragma fragment frag
  114. #pragma multi_compile_fwdadd
  115. #include "UnityCG.cginc"
  116. #include "Lighting.cginc"
  117. #include "AutoLight.cginc"
  118. #include "UnityShaderVariables.cginc"
  119. sampler2D _MainTex;
  120. sampler2D _Ramp;
  121. float4 _MainTex_ST;
  122. float _Tooniness;
  123. struct a2v
  124. {
  125. float4 vertex : POSITION;
  126. float3 normal : NORMAL;
  127. float4 texcoord : TEXCOORD0;
  128. float4 tangent : TANGENT;
  129. };
  130. struct v2f
  131. {
  132. float4 pos : POSITION;
  133. float2 uv : TEXCOORD0;
  134. float3 normal : TEXCOORD1;
  135. half3 lightDir : TEXCOORD2;
  136. LIGHTING_COORDS(3,4)
  137. };
  138. v2f vert (a2v v)
  139. {
  140. v2f o;
  141. //Transform the vertex to projection space
  142. o.pos = UnityObjectToClipPos( v.vertex);
  143. o.normal = mul((float3x3)unity_ObjectToWorld, SCALED_NORMAL);
  144. o.lightDir = WorldSpaceLightDir( v.vertex );
  145. //Get the UV coordinates
  146. o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
  147. // pass lighting information to pixel shader
  148. TRANSFER_VERTEX_TO_FRAGMENT(o);
  149. return o;
  150. }
  151. float4 frag(v2f i) : COLOR
  152. {
  153. //Get the color of the pixel from the texture
  154. float4 c = tex2D (_MainTex, i.uv);
  155. //Merge the colours
  156. c.rgb = (floor(c.rgb*_Tooniness)/_Tooniness);
  157. //Based on the ambient light
  158. float3 lightColor = float3(0,0,0);
  159. //Work out this distance of the light
  160. float atten = LIGHT_ATTENUATION(i);
  161. //Angle to the light
  162. float diff = dot (normalize(i.normal), normalize(i.lightDir));
  163. diff = diff * 0.5 + 0.5;
  164. //Perform our toon light mapping
  165. diff = tex2D(_Ramp, float2(diff, 0.5));
  166. //Update the colour
  167. lightColor += _LightColor0.rgb * (diff * atten);
  168. //Product the final color
  169. c.rgb = lightColor * c.rgb * 2;
  170. return c;
  171. }
  172. ENDCG
  173. }
  174. }
  175. FallBack "Diffuse"
  176. }

 

2.溶解

  1. Shader "Unlit/Melt"
  2. {
  3. Properties{
  4. _MainTex("Base(rgb)", 2D) = "white"{}
  5. _NoiseMap("NoiseMap", 2D) = "white"{}//噪声贴图
  6. _MeltThreshold("MeltThreshold", Range(0, 1)) = 0//烧毁闸值
  7. _EdgeLength("EdgeLength",Range(0, 0.3))=0.1
  8. _EdgeColorStart("EdgeColorStart", Color) = (1,1,1,1)
  9. _EdgeColorEnd("EdgeColorEnd", Color) = (0,0,0,0)
  10. //_Erode("Erode", Range(0.0, 1.0)) = 0.98
  11. //_ErodeThreshold("ErodeThreshold", Range(0.0, 1.0)) = 0.71
  12. }
  13. SubShader{
  14. CGINCLUDE
  15. #include "Lighting.cginc"
  16. #include "UnityCG.cginc"
  17. #include "AutoLight.cginc"
  18. sampler2D _MainTex;
  19. float4 _MainTex_ST;
  20. sampler2D _NoiseMap;
  21. float _MeltThreshold;//消融阈值
  22. float _EdgeLength;
  23. //消融边缘起始颜色
  24. fixed4 _EdgeColorStart;
  25. //最终颜色
  26. fixed4 _EdgeColorEnd;
  27. 控制侵蚀程度
  28. //float _Erode;
  29. //控制侵蚀颜色阈值
  30. //float _ErodeThreshold;
  31. struct a2v{
  32. float4 vertex : POSITION;
  33. float3 normal : NORMAL;
  34. float4 texcoord : TEXCOORD0;
  35. };
  36. struct v2f{
  37. float4 pos : SV_POSITION;
  38. float3 worldNormal : TEXCOORD0;
  39. float3 worldPos : TEXCOORD1;
  40. float2 uv : TEXCOORD2;
  41. SHADOW_COORDS(3)
  42. };
  43. v2f vert(a2v v){
  44. v2f o;
  45. o.pos = UnityObjectToClipPos(v.vertex);
  46. o.worldNormal = UnityObjectToWorldNormal(v.normal);
  47. o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
  48. o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
  49. TRANSFER_SHADOW(o);
  50. return o;
  51. }
  52. fixed4 frag(v2f i) : SV_Target{
  53. fixed3 melt = tex2D(_NoiseMap, i.uv).rgb;//melt意味溶解
  54. //使用噪声图采样
  55. clip(melt.r - _MeltThreshold);
  56. //采样阈值与设定阈值比较,小于设定的阈值就裁剪掉该片元
  57. //如何理解:clip函数相当于返回一个裁剪后的部分可见模型。而哪些地方裁剪哪些不,完全取决于噪声贴图(与主图共用uv)与闸值的比较
  58. //常规光照计算部分
  59. fixed3 albedo = tex2D(_MainTex, i.uv).rgb;
  60. fixed3 worldNormal = normalize(i.worldNormal);
  61. fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
  62. fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
  63. fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, -worldLightDir));
  64. fixed3 lightColor = diffuse + ambient;
  65. //下面处理边缘的烧融部分
  66. float result =1- (melt.r - _MeltThreshold);
  67. //melt.r - _MeltThreshold得到了未被裁剪的剩余部分。即半透明中(半黑)更可见的部分
  68. //注意剩余部分对应的噪声贴图不均。(白色为1,黑色为0.介于之间为半透明)
  69. //1-剩余部分 即得到透明值(噪声图黑色含量值)。0为不透明,反之更透明。
  70. if(result > (1-_EdgeLength)){//1-_EdgeLength是不会出现烧融的部分,即“内陆”。
  71. //result 大于1-_EdgeLength的部分即为烧融边界
  72. fixed4 edgeColor=lerp(_EdgeColorStart,_EdgeColorEnd,(result-(1-_EdgeLength))/_EdgeLength);
  73. //result-(1-_EdgeLength))/_EdgeLength是将烧融部分规范到(0,1)
  74. //lerp(a,b,f):线性插值函数,返回值为(1-f)*a+b*f
  75. return edgeColor;
  76. }
  77. //直接返回光照后颜色
  78. return fixed4(lightColor, 1);
  79. }
  80. ENDCG
  81. //为了看见整个模型的消融过程,我选择关闭了剔除
  82. Pass{
  83. Tags{ "RenderType" = "Opaque"}
  84. Cull off
  85. CGPROGRAM
  86. #pragma vertex vert
  87. #pragma fragment frag
  88. ENDCG
  89. }
  90. }
  91. FallBack Off
  92. }

 

3.透视

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/107828
推荐阅读
相关标签
  

闽ICP备14008679号