赞
踩
1.卡通渲染
- //卡通渲染
- //轮廓线渲染原理:渲染物体背面后向外拓展
- //轮廓线弃用方案:根据视线与物体法线的夹角大小判断轮廓。理由:应用于正方体等规整物体上时效果极差
- Shader "MyToon/Toon-Fragment" {
- Properties {
- _MainTex ("MainTex", 2D) = "white" {}
- _Ramp ("Ramp Texture", 2D) = "white" {}
- _Tooniness ("Tooniness", Range(0.1,20)) = 4
- _Outline ("Outline", Range(0,0.1)) = 0.01
- }
-
- SubShader {
- Tags { "RenderType"="Opaque" }
- LOD 200
-
- //下面是渲染背面的pass
- Pass {
- Tags { "LightMode"="ForwardBase" }
-
- Cull Front//剔除正面
- Lighting Off
- ZWrite On
-
- CGPROGRAM
-
- #pragma vertex vert
- #pragma fragment frag
-
- #pragma multi_compile_fwdbase
-
- #include "UnityCG.cginc"
-
- float _Outline;
-
- struct a2v
- {
- float4 vertex : POSITION;
- float3 normal : NORMAL;
- };
-
- struct v2f
- {
- float4 pos : POSITION;
- };
-
- v2f vert (a2v v)
- {
- v2f o;
-
- float4 pos = mul( UNITY_MATRIX_MV, v.vertex); //顶点位置从模型空间转换到观察空间(摄像机空间)
- float3 normal = mul(v.normal, (float3x3)UNITY_MATRIX_T_MV);//将法线(向量)从模型空间变换到观察空间。
- normal.z = -0.5;//Z方向的值扁平化(使其是一个较小的定值),防止喧宾夺主,挡住正面的渲染结果(不能关闭深度写入来解决)
- //将法线与顶点转到观察空间也是为了这一步的扁平化。否则不需要(根据法线与视线夹角的那个方法)
-
- pos = pos + float4(normalize(normal),0) * _Outline;//v.vertex沿着v.normal的方向扩展_Outline倍
- o.pos = mul(UNITY_MATRIX_P, pos);//把新的位置转换到投影坐标系中
-
- return o;
- }
-
- float4 frag(v2f i) : COLOR
- {
- return float4(0, 0, 0, 1); //将背面渲染成黑色就返回
- }
-
- ENDCG
- }
-
- Pass {
- Tags { "LightMode"="ForwardBase" }
-
- Cull Back
- Lighting On
-
- CGPROGRAM
-
- #pragma vertex vert
- #pragma fragment frag
-
- #pragma multi_compile_fwdbase
-
- #include "UnityCG.cginc"
- #include "Lighting.cginc"
- #include "AutoLight.cginc"
- #include "UnityShaderVariables.cginc"
-
- sampler2D _MainTex;
- sampler2D _Ramp;
-
- float4 _MainTex_ST;
-
- float _Tooniness;
-
- struct a2v {
- float4 vertex : POSITION;//语义POSITION指模型空间下的顶点位置
- float3 normal :NORMAL;//语义指模型空间下法线
- float4 texcoord:TEXCOORD0;
- };
-
- struct v2f {
- float4 pos : SV_POSITION;// SV_POSITION指裁剪空间下定点位置
- float3 WorldNormal:TEXCOORD0;
- float3 WorldPos : TEXCOORD1;
- float2 uv:TEXCOORD2;//用于存储纹理坐标
- };
-
- v2f vert(a2v v) {
- v2f f;
-
- f.WorldNormal= UnityObjectToWorldNormal(v.normal);//法线世界化
- //f.WorldNormal = normalize(mul(unity_ObjectToWorld, v.normal));
-
- f.WorldPos = mul(unity_ObjectToWorld, v.vertex);//点坐标世界化
- //点坐标世界化,是方便通过世界坐标下的点作为一些内置函数的参数,获取光照方向,视线方向等
-
- f.pos = UnityObjectToClipPos(v.vertex);//点坐标片元化
-
- f.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
- //f.uv=v.texcoord.xy*_MainTex_ST.xy+_MainTex_ST.zw;
- //_MainTex_ST.xy对纹理进行缩放,_MainTex_ST.zw对纹理偏移
-
- return f;
- }
-
- float4 frag(v2f f) : COLOR
- {
-
- fixed3 lightDir = normalize(UnityWorldSpaceLightDir(f.WorldPos));
-
- fixed3 worldNormal=normalize(f.WorldNormal);
-
- fixed3 albedo =tex2D(_MainTex,f.uv).rgb;
- albedo.rgb = (floor(albedo.rgb*_Tooniness)/_Tooniness);//合并颜色
- fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT * albedo;
-
- fixed halfLambert =dot( worldNormal,lightDir)*0.5+0.5;//半兰伯特
- fixed3 diffuseColor=tex2D(_Ramp,fixed2(halfLambert,halfLambert)).rgb;
- //让半兰伯特的取值范围映射在(0,1),用其数值构建一套纹理坐标,并用这套坐标对渐变纹理采样。
- fixed3 diffuse=diffuseColor*_LightColor0.rgb;
-
- return fixed4(ambient + diffuse , 1);
-
- }
-
- ENDCG
- }
-
- Pass {
- Tags { "LightMode"="ForwardAdd" }
-
- Cull Back
- Lighting On
- Blend One One
-
- CGPROGRAM
-
- #pragma vertex vert
- #pragma fragment frag
-
- #pragma multi_compile_fwdadd
-
- #include "UnityCG.cginc"
- #include "Lighting.cginc"
- #include "AutoLight.cginc"
- #include "UnityShaderVariables.cginc"
-
-
- sampler2D _MainTex;
- sampler2D _Ramp;
-
- float4 _MainTex_ST;
-
- float _Tooniness;
-
- struct a2v
- {
- float4 vertex : POSITION;
- float3 normal : NORMAL;
- float4 texcoord : TEXCOORD0;
- float4 tangent : TANGENT;
- };
-
- struct v2f
- {
- float4 pos : POSITION;
- float2 uv : TEXCOORD0;
- float3 normal : TEXCOORD1;
- half3 lightDir : TEXCOORD2;
- LIGHTING_COORDS(3,4)
- };
-
- v2f vert (a2v v)
- {
- v2f o;
-
- //Transform the vertex to projection space
- o.pos = UnityObjectToClipPos( v.vertex);
- o.normal = mul((float3x3)unity_ObjectToWorld, SCALED_NORMAL);
- o.lightDir = WorldSpaceLightDir( v.vertex );
- //Get the UV coordinates
- o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
-
- // pass lighting information to pixel shader
- TRANSFER_VERTEX_TO_FRAGMENT(o);
- return o;
- }
-
- float4 frag(v2f i) : COLOR
- {
- //Get the color of the pixel from the texture
- float4 c = tex2D (_MainTex, i.uv);
- //Merge the colours
- c.rgb = (floor(c.rgb*_Tooniness)/_Tooniness);
-
- //Based on the ambient light
- float3 lightColor = float3(0,0,0);
-
- //Work out this distance of the light
- float atten = LIGHT_ATTENUATION(i);
- //Angle to the light
- float diff = dot (normalize(i.normal), normalize(i.lightDir));
- diff = diff * 0.5 + 0.5;
- //Perform our toon light mapping
- diff = tex2D(_Ramp, float2(diff, 0.5));
- //Update the colour
- lightColor += _LightColor0.rgb * (diff * atten);
- //Product the final color
- c.rgb = lightColor * c.rgb * 2;
- return c;
- }
-
- ENDCG
- }
- }
- FallBack "Diffuse"
- }

2.溶解
- Shader "Unlit/Melt"
- {
- Properties{
- _MainTex("Base(rgb)", 2D) = "white"{}
- _NoiseMap("NoiseMap", 2D) = "white"{}//噪声贴图
- _MeltThreshold("MeltThreshold", Range(0, 1)) = 0//烧毁闸值
-
- _EdgeLength("EdgeLength",Range(0, 0.3))=0.1
-
- _EdgeColorStart("EdgeColorStart", Color) = (1,1,1,1)
- _EdgeColorEnd("EdgeColorEnd", Color) = (0,0,0,0)
- //_Erode("Erode", Range(0.0, 1.0)) = 0.98
- //_ErodeThreshold("ErodeThreshold", Range(0.0, 1.0)) = 0.71
- }
-
-
- SubShader{
-
- CGINCLUDE
-
- #include "Lighting.cginc"
- #include "UnityCG.cginc"
- #include "AutoLight.cginc"
-
- sampler2D _MainTex;
- float4 _MainTex_ST;
- sampler2D _NoiseMap;
- float _MeltThreshold;//消融阈值
-
- float _EdgeLength;
-
- //消融边缘起始颜色
- fixed4 _EdgeColorStart;
- //最终颜色
- fixed4 _EdgeColorEnd;
- 控制侵蚀程度
- //float _Erode;
- //控制侵蚀颜色阈值
- //float _ErodeThreshold;
-
- struct a2v{
- float4 vertex : POSITION;
- float3 normal : NORMAL;
- float4 texcoord : TEXCOORD0;
- };
-
- struct v2f{
- float4 pos : SV_POSITION;
- float3 worldNormal : TEXCOORD0;
- float3 worldPos : TEXCOORD1;
- float2 uv : TEXCOORD2;
- SHADOW_COORDS(3)
- };
-
- v2f vert(a2v v){
- v2f o;
- o.pos = UnityObjectToClipPos(v.vertex);
- o.worldNormal = UnityObjectToWorldNormal(v.normal);
- o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
- o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
- TRANSFER_SHADOW(o);
- return o;
- }
-
- fixed4 frag(v2f i) : SV_Target{
-
- fixed3 melt = tex2D(_NoiseMap, i.uv).rgb;//melt意味溶解
- //使用噪声图采样
-
- clip(melt.r - _MeltThreshold);
- //采样阈值与设定阈值比较,小于设定的阈值就裁剪掉该片元
- //如何理解:clip函数相当于返回一个裁剪后的部分可见模型。而哪些地方裁剪哪些不,完全取决于噪声贴图(与主图共用uv)与闸值的比较
-
- //常规光照计算部分
- fixed3 albedo = tex2D(_MainTex, i.uv).rgb;
- fixed3 worldNormal = normalize(i.worldNormal);
- fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
- fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
- fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, -worldLightDir));
- fixed3 lightColor = diffuse + ambient;
-
- //下面处理边缘的烧融部分
- float result =1- (melt.r - _MeltThreshold);
- //melt.r - _MeltThreshold得到了未被裁剪的剩余部分。即半透明中(半黑)更可见的部分
- //注意剩余部分对应的噪声贴图不均。(白色为1,黑色为0.介于之间为半透明)
- //1-剩余部分 即得到透明值(噪声图黑色含量值)。0为不透明,反之更透明。
-
- if(result > (1-_EdgeLength)){//1-_EdgeLength是不会出现烧融的部分,即“内陆”。
- //result 大于1-_EdgeLength的部分即为烧融边界
-
- fixed4 edgeColor=lerp(_EdgeColorStart,_EdgeColorEnd,(result-(1-_EdgeLength))/_EdgeLength);
- //result-(1-_EdgeLength))/_EdgeLength是将烧融部分规范到(0,1)
- //lerp(a,b,f):线性插值函数,返回值为(1-f)*a+b*f
-
- return edgeColor;
- }
-
- //直接返回光照后颜色
- return fixed4(lightColor, 1);
- }
-
- ENDCG
-
- //为了看见整个模型的消融过程,我选择关闭了剔除
- Pass{
-
- Tags{ "RenderType" = "Opaque"}
- Cull off
- CGPROGRAM
-
- #pragma vertex vert
- #pragma fragment frag
-
- ENDCG
- }
- }
-
- FallBack Off
- }

3.透视
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。