[其他] Unity Toon Shading with Texture

科技 · LENH · 發表於 2016-10-06 14:06 · · 檢舉

reference the toon shading in the wiki

https://en.wikibooks.org/wiki/Cg_Programming/Unity/Toon_Shading

and add
_MainTex("Base (RGB) Trans (A)", 2D) = "white" {}

pass the uv : TEXCOORD0 from vertexInput to vertexOutput


take the texel form the uv

fixed4 col = tex2D(_MainTex, input.uv) * input.color;



Download: ToonShadeingWithTex.shader

the shader code as below:


// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'

Shader "Cg shader for toon shading with texture test" {
Properties{
_MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
_Color("Diffuse Color", Color) = (1,1,1,1)
_UnlitColor("Unlit Diffuse Color", Color) = (0.5,0.5,0.5,1)
_DiffuseThreshold("Threshold for Diffuse Colors", Range(0,1)) = 0.1
_OutlineColor("Outline Color", Color) = (0,0,0,1)
_LitOutlineThickness("Lit Outline Thickness", Range(0,1)) = 0.1
_UnlitOutlineThickness("Unlit Outline Thickness", Range(0,1)) = 0.4
_SpecColor("Specular Color", Color) = (1,1,1,1)
_Shininess("Shininess", Float) = 10
}
SubShader{
Pass{
Tags{ "LightMode" = "ForwardBase" }
// pass for ambient light and first light source

CGPROGRAM

#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc")

sampler2D _MainTex;

// User-specified properties
uniform float4 _Color;
uniform float4 _UnlitColor;
uniform float _DiffuseThreshold;
uniform float4 _OutlineColor;
uniform float _LitOutlineThickness;
uniform float _UnlitOutlineThickness;
uniform float4 _SpecColor;
uniform float _Shininess;

struct vertexInput {
fixed4 color : COLOR;
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 uv: TEXCOORD0;
};
struct vertexOutput {
fixed4 color : COLOR;
float4 pos : SV_POSITION;
float2 uv: TEXCOORD0;
float4 posWorld : TEXCOORD1;
float3 normalDir : TEXCOORD2;
};

vertexOutput vert(vertexInput input)
{
vertexOutput output;

float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object;

output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
output.color = input.color;
output.uv = input.uv;
return output;
}

float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir);

float3 viewDirection = normalize(_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation;

if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
}

// default: unlit
float3 fragmentColor = _UnlitColor.rgb;

// low priority: diffuse illumination
if (attenuation * max(0.0, dot(normalDirection, lightDirection)) >= _DiffuseThreshold)
{
fragmentColor = _LightColor0.rgb * _Color.rgb;
}

// higher priority: outline
if (dot(viewDirection, normalDirection)
< lerp(_UnlitOutlineThickness, _LitOutlineThickness, max(0.0, dot(normalDirection, lightDirection))))
{
fragmentColor = _LightColor0.rgb * _OutlineColor.rgb;
}

// highest priority: highlights
if (dot(normalDirection, lightDirection) > 0.0
// light source on the right side?
&& attenuation * pow(max(0.0, dot(reflect(-lightDirection, normalDirection), viewDirection)), _Shininess) > 0.5)
// more than half highlight intensity?
{
fragmentColor = _SpecColor.a * _LightColor0.rgb * _SpecColor.rgb + (1.0 - _SpecColor.a) * fragmentColor;
}
// final texture
fixed4 col = tex2D(_MainTex, input.uv) * input.color;
return col * float4(fragmentColor, 1.0);
}
ENDCG
}

Pass{
Tags{ "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend SrcAlpha OneMinusSrcAlpha
// blend specular highlights over framebuffer

CGPROGRAM

#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc")

sampler2D _MainTex;

// User-specified properties
uniform float4 _Color;
uniform float4 _UnlitColor;
uniform float _DiffuseThreshold;
uniform float4 _OutlineColor;
uniform float _LitOutlineThickness;
uniform float _UnlitOutlineThickness;
uniform float4 _SpecColor;
uniform float _Shininess;

struct vertexInput {
fixed4 color : COLOR;
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 uv: TEXCOORD0;
};
struct vertexOutput {
fixed4 color : COLOR;
float4 pos : SV_POSITION;
float2 uv: TEXCOORD0;
float4 posWorld : TEXCOORD1;
float3 normalDir : TEXCOORD2;
};

vertexOutput vert(vertexInput input)
{
vertexOutput output;

float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object;

output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(mul(float4(input.normal, 0.0), modelMatrixInverse).rgb);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
output.color = input.color;
output.uv = input.uv;
return output;
}

float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir);

float3 viewDirection = normalize(_WorldSpaceCameraPos - input.posWorld.rgb);
float3 lightDirection;
float attenuation;

if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
}

float4 fragmentColor = float4(0.0, 0.0, 0.0, 0.0);
if (dot(normalDirection, lightDirection) > 0.0
// light source on the right side?
&& attenuation * pow(max(0.0, dot(reflect(-lightDirection, normalDirection), viewDirection)), _Shininess) > 0.5)
// more than half highlight intensity?
{
fragmentColor = float4(_LightColor0.rgb, 1.0) * _SpecColor;
}
// final texture
fixed4 col = tex2D(_MainTex, input.uv) * input.color;
return col * fragmentColor;
}
ENDCG
}
}
Fallback "Specular"
}