Skip to content

Instantly share code, notes, and snippets.

@Glynn-Taylor
Last active April 2, 2024 02:00
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save Glynn-Taylor/b232965ed972702df133137b3295e7f2 to your computer and use it in GitHub Desktop.
Save Glynn-Taylor/b232965ed972702df133137b3295e7f2 to your computer and use it in GitHub Desktop.
Toon Terrain Tutorial
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
// Edits by Glynn Taylor. MIT license
// Includes code for splitmap by https://twitter.com/adamgryu and triplanar mapping by https://github.com/keijiro. MIT License
#ifndef TERRAIN_SPLATMAP_COMMON_CGINC_INCLUDED
#define TERRAIN_SPLATMAP_COMMON_CGINC_INCLUDED
struct Input
{
float3 localNormal : TEXCOORD0;
float3 localCoord : TEXCOORD1;
float2 tc_Control : TEXCOORD4; // Not prefixing '_Contorl' with 'uv' allows a tighter packing of interpolators, which is necessary to support directional lightmap.
UNITY_FOG_COORDS(5)
};
sampler2D _VerticalTex;
float4 _VerticalTex_ST;
sampler2D _Control;
float4 _Control_ST;
sampler2D _Splat0,_Splat1,_Splat2,_Splat3;
float4 _Splat0_ST, _Splat1_ST, _Splat2_ST, _Splat3_ST;
#ifdef _TERRAIN_NORMAL_MAP
sampler2D _Normal0, _Normal1, _Normal2, _Normal3;
#endif
void SplatmapVert(inout appdata_full v, out Input data)
{
UNITY_INITIALIZE_OUTPUT(Input, data);
data.tc_Control = TRANSFORM_TEX(v.texcoord, _Control); // Need to manually transform uv here, as we choose not to use 'uv' prefix for this texcoord.
float4 pos = UnityObjectToClipPos(v.vertex);
UNITY_TRANSFER_FOG(data, pos);
data.localNormal = v.normal.xyz;
data.localCoord = v.vertex.xyz;
#ifdef _TERRAIN_NORMAL_MAP
v.tangent.xyz = cross(v.normal, float3(0,0,1));
v.tangent.w = -1;
#endif
}
half4 SplitMap(half4 map)
{
map.r = step(0.1, map.r - map.g - map.b - map.a);
map.g = step(0.1, map.g - map.r - map.b - map.a);
map.b = step(0.1, map.b - map.g - map.r - map.a);
map.a = step(0.1, map.a - map.g - map.b - map.r);
return map;
}
#ifdef TERRAIN_STANDARD_SHADER
void SplatmapMix(Input IN, half4 defaultAlpha, out half4 splat_control, out half weight, out fixed4 mixedDiffuse, inout float3 mixedNormal)
#else
void SplatmapMix(Input IN, out half4 splat_control, out half weight, out fixed4 mixedDiffuse, inout fixed3 mixedNormal)
#endif
{
splat_control = tex2D(_Control, IN.tc_Control);
weight = dot(splat_control, half4(1,1,1,1));
#if defined(TERRAIN_SPLAT_ADDPASS)
weight = step(0.1, weight);
clip(weight == 0.0f ? -1 : 1);
#endif
// Normalize weights before lighting and restore weights in final modifier functions so that the overal
// lighting result can be correctly weighted.
splat_control /= (weight + 1e-3f);
splat_control = SplitMap(splat_control);
float2 uvSplat0 = TRANSFORM_TEX(IN.tc_Control.xy * _Splat0_ST.xy + _Splat0_ST.zw, _Splat0 );
float2 uvSplat1 = TRANSFORM_TEX(IN.tc_Control.xy * _Splat1_ST.xy + _Splat1_ST.zw, _Splat1);
float2 uvSplat2 = TRANSFORM_TEX(IN.tc_Control.xy * _Splat2_ST.xy + _Splat2_ST.zw, _Splat2);
float2 uvSplat3 = TRANSFORM_TEX(IN.tc_Control.xy * _Splat3_ST.xy + _Splat3_ST.zw, _Splat3);
mixedDiffuse = 0.0f;
mixedDiffuse += splat_control.r * tex2D(_Splat0, uvSplat0);
mixedDiffuse += splat_control.g * tex2D(_Splat1, uvSplat1);
mixedDiffuse += splat_control.b * tex2D(_Splat2, uvSplat2);
mixedDiffuse += splat_control.a * tex2D(_Splat3, uvSplat3);
}
#ifndef TERRAIN_SURFACE_OUTPUT
#define TERRAIN_SURFACE_OUTPUT SurfaceOutput
#endif
void SplatmapFinalColor(Input IN, TERRAIN_SURFACE_OUTPUT o, inout fixed4 color)
{
color *= o.Alpha;
#ifdef TERRAIN_SPLAT_ADDPASS
UNITY_APPLY_FOG_COLOR(IN.fogCoord, color, fixed4(0,0,0,0));
#else
UNITY_APPLY_FOG(IN.fogCoord, color);
#endif
}
void SplatmapFinalPrepass(Input IN, TERRAIN_SURFACE_OUTPUT o, inout fixed4 normalSpec)
{
normalSpec *= o.Alpha;
}
void SplatmapFinalGBuffer(Input IN, TERRAIN_SURFACE_OUTPUT o, inout half4 outGBuffer0, inout half4 outGBuffer1, inout half4 outGBuffer2, inout half4 emission)
{
UnityStandardDataApplyWeightToGbuffer(outGBuffer0, outGBuffer1, outGBuffer2, o.Alpha);
emission *= o.Alpha;
}
#endif // TERRAIN_SPLATMAP_COMMON_CGINC_INCLUDED
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
// Edits by Glynn Taylor. MIT license
// Includes code for splitmap by https://twitter.com/adamgryu and triplanar mapping by https://github.com/keijiro. MIT License
Shader "Hidden/ToonTerrainAdd" {
Properties {
[HideInInspector] _Control ("Control (RGBA)", 2D) = "black" {}
[HideInInspector] _Splat3 ("Layer 3 (A)", 2D) = "white" {}
[HideInInspector] _Splat2 ("Layer 2 (B)", 2D) = "white" {}
[HideInInspector] _Splat1 ("Layer 1 (G)", 2D) = "white" {}
[HideInInspector] _Splat0 ("Layer 0 (R)", 2D) = "white" {}
[HideInInspector] _Normal3 ("Normal 3 (A)", 2D) = "bump" {}
[HideInInspector] _Normal2 ("Normal 2 (B)", 2D) = "bump" {}
[HideInInspector] _Normal1 ("Normal 1 (G)", 2D) = "bump" {}
[HideInInspector] _Normal0 ("Normal 0 (R)", 2D) = "bump" {}
_VerticalTex("VerticalTex (RGB)", 2D) = "white" {}
}
CGINCLUDE
#pragma surface surf Lambert decal:add vertex:SplatmapVert finalcolor:SplatmapFinalColor finalprepass:SplatmapFinalPrepass finalgbuffer:SplatmapFinalGBuffer noinstancing decal:blend
#pragma multi_compile_fog
#define TERRAIN_SPLAT_ADDPASS
#include "ToonTerrain.cginc"
void surf(Input IN, inout SurfaceOutput o)
{
half4 splat_control;
half weight;
fixed4 mixedDiffuse;
float3 bf = normalize(abs(IN.localNormal));
bf /= dot(bf, (float3)1);
// Triplanar mapping
float2 tx = IN.localCoord.yz * _VerticalTex_ST.x;
float2 ty = IN.localCoord.zx* _VerticalTex_ST.x;
float2 tz = IN.localCoord.xy* _VerticalTex_ST.x;
// Base color
half4 cx = tex2D(_VerticalTex, tz) * bf.x;
half4 cy = tex2D(_VerticalTex, tz) * bf.y;
half4 cz = tex2D(_VerticalTex, tz) * bf.z;
half4 color = (cx + cy + cz);
SplatmapMix(IN, splat_control, weight, mixedDiffuse, o.Normal);
if (dot(IN.localNormal, fixed3(0, 1, 0)) >= 0.8)
{
o.Albedo = mixedDiffuse.rgb;
}
else {
o.Albedo = color.rgb;
}
o.Alpha = weight;
}
ENDCG
Category {
Tags {
"Queue" = "Geometry-99"
"IgnoreProjector"="True"
"RenderType" = "Opaque"
}
// TODO: Seems like "#pragma target 3.0 _TERRAIN_NORMAL_MAP" can't fallback correctly on less capable devices?
// Use two sub-shaders to simulate different features for different targets and still fallback correctly.
SubShader { // for sm3.0+ targets
CGPROGRAM
#pragma target 3.0
#pragma multi_compile __ _TERRAIN_NORMAL_MAP
ENDCG
}
SubShader { // for sm2.0 targets
CGPROGRAM
ENDCG
}
}
Fallback off
}
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
// Edits by Glynn Taylor. MIT license
// Includes code for splitmap by https://twitter.com/adamgryu and triplanar mapping by https://github.com/keijiro. MIT License
Shader "ToonTerrain" {
Properties {
[HideInInspector] _Control ("Control (RGBA)", 2D) = "red" {}
[HideInInspector] _Splat3 ("Layer 3 (A)", 2D) = "white" {}
[HideInInspector] _Splat2 ("Layer 2 (B)", 2D) = "white" {}
[HideInInspector] _Splat1 ("Layer 1 (G)", 2D) = "white" {}
[HideInInspector] _Splat0 ("Layer 0 (R)", 2D) = "white" {}
[HideInInspector] _Normal3 ("Normal 3 (A)", 2D) = "bump" {}
[HideInInspector] _Normal2 ("Normal 2 (B)", 2D) = "bump" {}
[HideInInspector] _Normal1 ("Normal 1 (G)", 2D) = "bump" {}
[HideInInspector] _Normal0 ("Normal 0 (R)", 2D) = "bump" {}
// used in fallback on old cards & base map
[HideInInspector] _MainTex ("BaseMap (RGB)", 2D) = "white" {}
[HideInInspector] _Color ("Main Color", Color) = (1,1,1,1)
_VerticalTex("VerticalTex (RGB)", 2D) = "white" {}
}
CGINCLUDE
#pragma surface surf Lambert vertex:SplatmapVert finalcolor:SplatmapFinalColor finalprepass:SplatmapFinalPrepass finalgbuffer:SplatmapFinalGBuffer noinstancing
#pragma multi_compile_fog
#include "ToonTerrain.cginc"
void surf(Input IN, inout SurfaceOutput o)
{
half4 splat_control;
half weight;
fixed4 mixedDiffuse;
float3 bf = normalize(abs(IN.localNormal));
bf /= dot(bf, (float3)1);
// Triplanar mapping
float2 tx = IN.localCoord.yz * _VerticalTex_ST.x;
float2 ty = IN.localCoord.zx* _VerticalTex_ST.x;
float2 tz = IN.localCoord.xy* _VerticalTex_ST.x;
// Base color
half4 cx = tex2D(_VerticalTex, tz) * bf.x;
half4 cy = tex2D(_VerticalTex, tz) * bf.y;
half4 cz = tex2D(_VerticalTex, tz) * bf.z;
half4 color = (cx + cy + cz);
SplatmapMix(IN, splat_control, weight, mixedDiffuse, o.Normal);
if (dot(IN.localNormal, fixed3(0, 1, 0)) >= 0.8)
{
o.Albedo = mixedDiffuse.rgb;
}
else {
o.Albedo = color.rgb;
}
o.Alpha = weight;
}
ENDCG
Category {
Tags {
"Queue" = "Geometry-99"
"RenderType" = "Opaque"
}
// TODO: Seems like "#pragma target 3.0 _TERRAIN_NORMAL_MAP" can't fallback correctly on less capable devices?
// Use two sub-shaders to simulate different features for different targets and still fallback correctly.
SubShader { // for sm3.0+ targets
CGPROGRAM
#pragma target 3.0
#pragma multi_compile __ _TERRAIN_NORMAL_MAP
ENDCG
}
SubShader { // for sm2.0 targets
CGPROGRAM
ENDCG
}
}
Dependency "AddPassShader" = "Hidden/ToonTerrainAdd"
Dependency "BaseMapShader" = "Diffuse"
Dependency "Details0" = "Hidden/TerrainEngine/Details/Vertexlit"
Dependency "Details1" = "Hidden/TerrainEngine/Details/WavingDoublePass"
Dependency "Details2" = "Hidden/TerrainEngine/Details/BillboardWavingDoublePass"
Dependency "Tree0" = "Hidden/TerrainEngine/BillboardTree"
Fallback "Diffuse"
}
@matheusconceicao113
Copy link

friend how do i remove the reflection from the terrain and soft shading?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment