"Combate Unity3D ShaderLab Desenvolvimento explicar" material de desenho animado Capítulo 19

golpe

  • 法线挤出描边法: Dois Pass, 1 Passe os vértices extrudados no sentido normal como a sombra, a segunda prestação normal de Pass.
    • 优点:Simples.
    • 问题:excepções marginais, o mais longe da fractura, quanto menor for a distância a partir da câmara propenso a acidente vascular cerebral.
Shader "Tut/Shader/Toon/Outline_1"{
	properties{
		_Outline("Outline", range(0,0.2)) = 0.2
	}
	SubShader{
		Pass{
			Tags{"LightMode"="Always"}
			Cull Off
			ZWrite Off
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			
			float _Outline;

			struct v2f{
				float4 pos:SV_POSITION;
			};
			v2f vert(appdata_full v){
				v2f o;
				v.vertex.xyz += v.normal * _Outline;//顶点沿着法线方向向外挤压。
				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
				return o;
			}
			float4 frag(v2f i):COLOR{
				float4 c = 0;
				return c;
			}
			ENDCG
		}

		Pass{
			Tags("LightMode"="ForwardBase")
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			
			float4 _LightColor0;
			
			struct v2f{
				float4 pos:SV_POSITION;
			}
			v2f vert(appdata_full v){
				v2f o;
				o.pos=mul(UNITY_MATRIX_MVP, v.vertex);
				return o;
			}
			float4 frag(v2f i):COLOR{
				return float4(1,1,1,1);
			}
		}
	}
}
  • 视空间法线挤出法: Direção de extrusão do ângulo de visão normal no espaço.
    • 优点:Resolver o erro acidente vascular cerebral, menor será o maior a distância dos problemas da câmera tempos.
    • 问题:ainda não resolve o problema de acidente vascular cerebral quebrado.
//第一个Pass如下,第二个Pass和之前一样。
Pass{
	Tags{"LightMode"="Always"}
	Cull Front
	ZWrite On
	CGPROGRAM
	#pragma vertex vert
	#pragma fragment frag
	#include "UnityCG.cginc"
	float _Outline;
	struct v2f{
		float4 pos:SV_POSITION;
	}
	v2f vert (appdata_full v){
		v2f o;
		o.pos = nul(UNITY_MATRIX_MVP, v.vertex);
		float3 norm = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);//UNITY_MATRIX_IT_MV是用来专门变换normal的
		float2 offset = TransformViewToProjection(norm.xy);
		o.pos.xy += offset * o.pos.z * _Outline;//乘以o.pos.z是为了抵消透视除法带来的近大远小的效果。
		return o;
	}
	float4 frag(v2f i):COLOR{
		return 0;
	}
	ENDCG
}
  • 顶点挤出法:O vértice espaço local coordenadas como o vector de direcção ao longo da direcção de extrusão no espaço perspectiva.
    • 优点:Resolver a fractura acidente vascular cerebral.
    • 问题:Para o modelo não modelar o centro das coordenadas locais do centro, o curso será um desvio sério do modelo.
//第1个Pass使用顶点的本地坐标代替Normal作为挤出方向,第2Pass不变。
Pass{
	Tags("LightMode"="Always"}
	Cull Front
	ZWrite On
	#pragma vertex vert
	#pragma fragment frag
	#include "UnityCG.cginc"
	float _Outline;
	struct v2f{
		float4 pos:SV_POSITION;
	}
	v2f vert(appdata_full v){
		v2f o;
		o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
		float3 dir = normalize(v.vertex.xyz);
		dir = mul((float3x3)UNITY_MATRIX_IT_MV, dir);
		float2 offset = TrasformViewToProjection(dir.xy);
		o.pos.xy += offset* o.pos.z * _Outline;
		return o;
	}
	float4 frag(v2f i);COLOR{
		return 0;
	}
	ENDCG
}
  • 调和法线和顶点方向:A interpolação entre as normais de vértice e como a direcção de extrusão.
    • 优点:Aliviar o problema de derrame afastando do modelo.
v2f vert(appdata_full v){
	v2f o;
	o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
	float3 dir = normalize(v.vertex.xyz);
	float3 dir2 = v.normal;
	dir = lerp(dir, dir2, _Factor);//在顶点坐标和法线之间插值,_Factor范围是0-1。
	dir = mul((float3x3)UNITY_MATRIX_IT_MV, dir);
	float2 offset = TransformViewToProjection(dir.xy);
	offset = normalize(offset);
	o.pos.xy += offset * o.pos.z * _Outline;
	return o;
}
  • 判断顶点方向法: Quando a direção normal e a direção do ângulo de abertura de 180 graus, utilizando o processo de extrusão normal, exatamente, se o ângulo é de 0 graus em ambas as direções, completamente processo de extrusão vértice, quando o ângulo entre os dois se interpoladas de acordo com o ângulo.
    • 优点:Para os modelos mais complexos.
v2f vert(appdata_full v){
	v2f o;
	o.pos = mul(UNITY_MATRIX_MVP, v.vertex.xyz);
	float3 dir = normalize(v.vertex.xyz);
	float3 dir2 = v.normal;
	float D = dot(dir, dir2);
	D = (D/_Factor + 1) / (1 + 1 / _Factor);//把D从(-1到1)变换到(0到1)之间。
	dir = lerp(dir2, dir, D);
	dir = mul((float3x3)UNITY_MATRIX_IT_MV, dir);
	float2 offset = TransformViewToProjection(dir.xy);
	offset = normalize(offset);
	o.pos.xy += offset * o.pos.z * _Outline;
	return o;
}

coloração dos desenhos animados

  • 数学法:Intensidade de luz discreta, para conseguir um efeito de desenho animado.
Shader "Tut/Shader/Toon/Cel_1"{
	Properties{
		_Color(Main Color", color) = (1,1,1,1)
		_Outline("Thick of outline", range(0, 0.1)) = 0.02
		_Factor("Factor", range(0, 1)) = 0.5
		_ToonEffect("toon Effect", range(0, 1)) = 0.5
		_Setps("Steps of toon", range(0, 9)) = 3
	}
	SubShader{
		//对平行光强度进行卡通化(离散化)。
		Pass{
			Tags{"LightMode"="ForwardAdd"}
			CGPROGRAM
			float4 frag(v2f i):Color{
				float4 c = 1;
				float3 n = normalize(i.normal);
				float3 lightDir = normalize(i.lightDir);
				float diff = max(0, dot(n, i.lightDir));
				diff = (diff + 1) / 2;//把diff从0到1变换到0.5到1。
				diff = smoothstep(0, 1, diff);//将diff平花花。
				float toon = floor(diff * _Steps)/_Steps;//如果_Steps=10,那么diff就是以0.1为最小单位离散化。
				diff = lerp(diff, toon, _ToonEffect);//控制卡通化程度。
				c = _Color * _LightColor0 * diff;//计算最终颜色。
				return c;
			}
			ENDCG
		}
		
		//对点光源强度进行卡通化(离散化)。
		Pass{
			Tags{"LightMode"="ForwardAdd"}
			float4 frag(v2f i):COLOR{
				float4 c = 1;
				float n = normalize(i.normal);
				float3 viewDir = normalize(i.viewDir);
				float3 dist = CalLightDistance();//自己想办法计算光源的距离。
				float4 lightDir = normalize(i.lightDir);
				float atten = 1/dist;//衰减系数。
				
				//计算漫反射
				float diff = max(0, dot(n, i.lightDir));
				diff = (diff + 1)/2;
				diff = smoothstep(0, 1, diff);
				float toom = floor(diff * atten * _Steps) / _Steps;
				diff = lerp(diff, toon, _ToonEffect);
				
				//计算高光
				half3 h = normalize(lightDir + viewDir);
				float nh = max(0, dot(n, h));
				float spec = pow(nh, 32);
				float toonSpec = floor(spec*atten*2)/2;//对高光进行2元离散处理(2类似于Steps)。
				spec = lerp(spec, toonSpec, _ToonEffect);

				c = _Color * _LightColor0 * (diff + spec) * atten;
				return c;
			}
			ENDCG
		}
	}
  • 贴图法:Uma textura preparação Zhangyi Wei, difusamente reflectida a intensidade da luz é calculada, e a intensidade da luz difusa reflectida como uma nova intensidade de luz coordenadas de textura amostrado emitida a partir da textura difusa.
float4 frag(v2f i):COLOR{
	float4 c = 1;
	float3 n = normalize(i.normalize);
	float3 viewDir = normalize(i.viewDir);
	float3 dist = CalLightDistance();//自己想办法计算光源的距离。
	float3 lightDir = normalize(i.lightDir);
	float atten = 1 / dist;
	
	diff = (diff + 1) / 2;
	diff = smoothstep(0, 1, diff);
	diff = diff * atten;

	float toon = tex2D(_ToonMap, float2(diff, diff)).r;
	diff = lerp(diff, toon, _ToonEffect);
	half3 h = normalize(lightDir + viewDir);
	float nh = max(0, dot(n, h));
	float spec = pos(nh, 32.0);
	float toonSpec = floor(spec * atten * 2) / 2;
	spec = lerp(spec, toonSpec, _ToonEffect);
	c = _Color * _LightColor0 * (diff + spec);
	return c;
}
Publicado 41 artigos originais · ganhou elogios 4 · Vistas 3898

Acho que você gosta

Origin blog.csdn.net/weixin_42487874/article/details/103209127
Recomendado
Clasificación