Add toon shader with outline for pose icon stage
Cel-shaded white body with tinted shadow band plus inverted-hull clip-space outline (constant screen width, works in deferred via SRPDefaultUnlit). Key light added to the Pose Icon scene, material wired to the Paintman. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ed1d171ed3
commit
2de153d8fe
5 files changed
+340
-14
No files matched your search
@@ -0,0 +1,141 @@
|
||||
// Minimal cel/toon shader with an inverted-hull outline for the Pose Icon stage
|
||||
// (icon screenshots of the staged Paintman). Deliberately NOT a URP/Lit clone:
|
||||
// the stage is a controlled studio setup, so main-light cel banding + ambient is
|
||||
// all the lighting it needs. Outline runs as a second pass (SRPDefaultUnlit, so
|
||||
// URP renders it without a Render Feature); width is screen-space (pixel-ish)
|
||||
// and distance-independent for consistent icon thickness.
|
||||
Shader "Custom/PoseIconToon"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[MainTexture] _BaseMap("Albedo", 2D) = "white" {}
|
||||
[MainColor] _BaseColor("Color", Color) = (1,1,1,1)
|
||||
|
||||
[Header(Toon Shading)]
|
||||
_ShadeThreshold("Shade Threshold", Range(0.0, 1.0)) = 0.5
|
||||
_ShadeSoftness("Shade Softness", Range(0.001, 0.5)) = 0.05
|
||||
_ShadowTint("Shadow Tint", Color) = (0.55, 0.5, 0.65, 1)
|
||||
|
||||
[Header(Outline)]
|
||||
_OutlineColor("Outline Color", Color) = (0.1, 0.08, 0.2, 1)
|
||||
_OutlineWidth("Outline Width (px at 1080p)", Range(0.0, 20.0)) = 6.0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "Queue" = "Geometry" }
|
||||
|
||||
HLSLINCLUDE
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
|
||||
CBUFFER_START(UnityPerMaterial)
|
||||
float4 _BaseMap_ST;
|
||||
half4 _BaseColor;
|
||||
half _ShadeThreshold;
|
||||
half _ShadeSoftness;
|
||||
half4 _ShadowTint;
|
||||
half4 _OutlineColor;
|
||||
half _OutlineWidth;
|
||||
CBUFFER_END
|
||||
ENDHLSL
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "ToonForward"
|
||||
// UniversalForwardOnly (not UniversalForward): drawn by BOTH the Forward and the
|
||||
// Deferred renderer (the deferred path only picks up ForwardOnly/SRPDefaultUnlit
|
||||
// passes for materials without a GBuffer pass - plain UniversalForward is skipped).
|
||||
Tags { "LightMode" = "UniversalForwardOnly" }
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma vertex ToonVertex
|
||||
#pragma fragment ToonFragment
|
||||
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
|
||||
|
||||
TEXTURE2D(_BaseMap);
|
||||
SAMPLER(sampler_BaseMap);
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float4 positionOS : POSITION;
|
||||
float3 normalOS : NORMAL;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float3 normalWS : TEXCOORD1;
|
||||
};
|
||||
|
||||
Varyings ToonVertex(Attributes input)
|
||||
{
|
||||
Varyings output;
|
||||
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
|
||||
output.normalWS = TransformObjectToWorldNormal(input.normalOS);
|
||||
output.uv = TRANSFORM_TEX(input.uv, _BaseMap);
|
||||
return output;
|
||||
}
|
||||
|
||||
half4 ToonFragment(Varyings input) : SV_Target
|
||||
{
|
||||
half4 albedo = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv) * _BaseColor;
|
||||
|
||||
Light mainLight = GetMainLight();
|
||||
half ndl = dot(normalize(input.normalWS), mainLight.direction) * 0.5h + 0.5h;
|
||||
half lit = smoothstep(_ShadeThreshold - _ShadeSoftness, _ShadeThreshold + _ShadeSoftness, ndl);
|
||||
|
||||
half3 litColor = albedo.rgb * mainLight.color;
|
||||
half3 shadeColor = albedo.rgb * _ShadowTint.rgb;
|
||||
half3 ambient = albedo.rgb * SampleSH(input.normalWS) * 0.25h;
|
||||
|
||||
return half4(lerp(shadeColor, litColor, lit) + ambient, albedo.a);
|
||||
}
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Outline"
|
||||
Tags { "LightMode" = "SRPDefaultUnlit" }
|
||||
Cull Front
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma vertex OutlineVertex
|
||||
#pragma fragment OutlineFragment
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float4 positionOS : POSITION;
|
||||
float3 normalOS : NORMAL;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
};
|
||||
|
||||
Varyings OutlineVertex(Attributes input)
|
||||
{
|
||||
Varyings output;
|
||||
output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
|
||||
|
||||
// Extrude in clip space: constant on-screen width regardless of distance.
|
||||
float3 normalWS = TransformObjectToWorldNormal(input.normalOS);
|
||||
float3 normalCS = normalize(mul((float3x3)UNITY_MATRIX_VP, normalWS).xyz);
|
||||
float2 offset = normalCS.xy * _OutlineWidth * 2.0 / 1080.0 * output.positionCS.w;
|
||||
offset.x *= _ScreenParams.y / _ScreenParams.x; // keep width uniform on non-square aspect
|
||||
output.positionCS.xy += offset;
|
||||
return output;
|
||||
}
|
||||
|
||||
half4 OutlineFragment(Varyings input) : SV_Target
|
||||
{
|
||||
return _OutlineColor;
|
||||
}
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4feab3af8d45cb545a6f4f9b7bdb6f2d
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user