wip : Liminal spaces + Tidy up
This commit is contained in:
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b0e29a4d5d846649904fadefb096b51
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38ed4cf9fd3c84943bc89c2db8a3832a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -3,52 +3,57 @@ Shader "Custom/ToonBilal"
|
||||
Properties
|
||||
{
|
||||
[Header(Global)]
|
||||
[Toggle] _ToonEnabled ("Enable Toon Filter", Float) = 1
|
||||
_ShaderWeight ("Shader Weight", Range(0,1)) = 1.0
|
||||
|
||||
[Header(Toon Shading)]
|
||||
_ToonSteps ("Toon Steps", Float) = 3
|
||||
_ShadowStrength ("Shadow Strength", Range(0,1)) = 0.3
|
||||
_ToonSteps ("Toon Steps", Float) = 4
|
||||
_ShadowStrength ("Shadow Strength", Range(0,1)) = 0.15
|
||||
_HighlightBoost ("Highlight Boost", Range(1,3)) = 1.6
|
||||
_HighlightThreshold ("Highlight Threshold", Range(0,1)) = 0.65
|
||||
|
||||
[Header(Pencil Outlines)]
|
||||
_OutlineThickness ("Outline Thickness", Float) = 2.0
|
||||
_OutlineThicknessVar ("Outline Thickness Variation", Range(0,1)) = 0.4
|
||||
_DepthThreshold ("Depth Outline Threshold", Range(0,0.1)) = 0.01
|
||||
_DepthThreshold ("Depth Outline Threshold", Range(0,2)) = 0.3
|
||||
_ColorThreshold ("Color Outline Threshold", Range(0,1)) = 0.2
|
||||
_DepthOutlineStrength ("Depth Outline Strength", Range(0,1)) = 1.0
|
||||
_ColorOutlineStrength ("Color Outline Strength", Range(0,1)) = 0.5
|
||||
_OutlineSoftness ("Outline Softness", Range(0,1)) = 0.6
|
||||
_OutlineColorBlend ("Outline Color From Surface", Range(0,1)) = 0.5
|
||||
_OutlineDarken ("Outline Darken Amount", Range(0,1)) = 0.7
|
||||
_OutlineDistanceFade ("Outline Distance Fade", Range(0,100)) = 30.0
|
||||
|
||||
[Header(Outline Brightness Fade)]
|
||||
_OutlineFadeStart ("Outline Fade Start", Range(0,1)) = 0.4
|
||||
_OutlineFadeEnd ("Outline Fade End", Range(0,1)) = 0.9
|
||||
_OutlineFadeStrength ("Outline Fade Strength", Range(0,1)) = 1.0
|
||||
_OutlineBrightMin ("Outline Bright Min Visibility", Range(0,1)) = 0.4
|
||||
_OutlineBrightMin ("Outline Bright Min Visibility", Range(0,1)) = 0.2
|
||||
|
||||
[Header(Hatching)]
|
||||
_HatchTex ("Hatching Texture", 2D) = "white" {}
|
||||
_HatchScale ("Hatch Scale", Float) = 0.3
|
||||
_HatchStrength ("Hatch Strength", Range(0,1)) = 0.6
|
||||
_HatchThreshold ("Hatch Shadow Threshold", Range(0,1)) = 0.5
|
||||
_CurvatureStrength ("Curvature Strength", Range(0,5)) = 1.5
|
||||
_FlatSurface ("Flat Surface Reduction", Range(0,1)) = 0.15
|
||||
_HatchStrength ("Hatch Strength", Range(0,1)) = 0.95
|
||||
_HatchThreshold ("Hatch Shadow Threshold", Range(0,1)) = 0.75
|
||||
_CurvatureStrength ("Curvature Strength", Range(0,5)) = 2.0
|
||||
_FlatSurface ("Flat Surface Reduction", Range(0,1)) = 0.3
|
||||
|
||||
[Header(Organic Hatching)]
|
||||
_HatchScale2 ("Hatch Scale Layer 2", Float) = 0.17
|
||||
_HatchScale3 ("Hatch Scale Layer 3", Float) = 0.22
|
||||
_HatchRotation ("Hatch Rotation", Range(0,3.14159)) = 0.785
|
||||
_HatchLayerBlend ("Hatch Layer Blend", Range(0,1)) = 0.5
|
||||
_HatchOrganicNoise ("Hatch Organic Noise", Range(0,1)) = 0.4
|
||||
_HatchLayerBlend ("Hatch Layer Blend", Range(0,1)) = 0.8
|
||||
_HatchOrganicNoise ("Hatch Organic Noise", Range(0,1)) = 0.5
|
||||
_HatchOrganicScale ("Hatch Organic Noise Scale", Float) = 2.0
|
||||
_HatchDensityCurve ("Hatch Density Curve", Range(0.1,5)) = 2.0
|
||||
_HatchDensityCurve ("Hatch Density Curve", Range(0.1,5)) = 1.0
|
||||
_TriplanarSharpness ("Triplanar Sharpness", Range(1,8)) = 2.0
|
||||
|
||||
[Header(Pencil Hatching)]
|
||||
_HatchColorBlend ("Hatch Color From Surface", Range(0,1)) = 0.6
|
||||
_HatchDarken ("Hatch Darken Amount", Range(0,1)) = 0.75
|
||||
_HatchColorBlend ("Hatch Color From Surface", Range(0,1)) = 0.5
|
||||
_HatchDarken ("Hatch Darken Amount", Range(0,1)) = 0.85
|
||||
_HatchGrainScale ("Hatch Grain Scale", Float) = 120.0
|
||||
_HatchGrainStrength ("Hatch Grain Strength", Range(0,1)) = 0.3
|
||||
_HatchPressure ("Hatch Pressure Variation", Range(0,1)) = 0.4
|
||||
_HatchGrainStrength ("Hatch Grain Strength", Range(0,1)) = 0.25
|
||||
_HatchPressure ("Hatch Pressure Variation", Range(0,1)) = 0.5
|
||||
|
||||
[Header(Gouache Shadow)]
|
||||
_BrushTex ("Brush Texture", 2D) = "white" {}
|
||||
@@ -72,13 +77,18 @@ Shader "Custom/ToonBilal"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
||||
|
||||
float _ToonEnabled;
|
||||
float _ShaderWeight;
|
||||
float _ToonSteps;
|
||||
float _ShadowStrength;
|
||||
float _HighlightBoost;
|
||||
float _HighlightThreshold;
|
||||
float _OutlineThickness;
|
||||
float _OutlineThicknessVar;
|
||||
float _DepthThreshold;
|
||||
@@ -88,12 +98,14 @@ Shader "Custom/ToonBilal"
|
||||
float _OutlineSoftness;
|
||||
float _OutlineColorBlend;
|
||||
float _OutlineDarken;
|
||||
float _OutlineDistanceFade;
|
||||
float _OutlineFadeStart;
|
||||
float _OutlineFadeEnd;
|
||||
float _OutlineFadeStrength;
|
||||
float _OutlineBrightMin;
|
||||
float _HatchScale;
|
||||
float _HatchScale2;
|
||||
float _HatchScale3;
|
||||
float _HatchStrength;
|
||||
float _HatchThreshold;
|
||||
float _CurvatureStrength;
|
||||
@@ -187,6 +199,12 @@ Shader "Custom/ToonBilal"
|
||||
return saturate((length(nr-n0)+length(nu-n0)+length(nl-n0)+length(nd-n0)) * _CurvatureStrength);
|
||||
}
|
||||
|
||||
// Linearizes the depth buffer — returns consistent meter values across the scene
|
||||
float LinearizeDepth(float rawDepth)
|
||||
{
|
||||
return LinearEyeDepth(rawDepth, _ZBufferParams);
|
||||
}
|
||||
|
||||
float2 RotateUV(float2 uv, float angle)
|
||||
{
|
||||
float s = sin(angle);
|
||||
@@ -194,28 +212,26 @@ Shader "Custom/ToonBilal"
|
||||
return float2(uv.x * c - uv.y * s, uv.x * s + uv.y * c);
|
||||
}
|
||||
|
||||
// ─── SATURATION ──────────────────────────────────────────
|
||||
// ─── SATURATION ─────────────────────────────────────────
|
||||
half3 AdjustSaturation(half3 col, float saturation)
|
||||
{
|
||||
float lum = dot(col, float3(0.299, 0.587, 0.114));
|
||||
return lerp(half3(lum, lum, lum), col, saturation);
|
||||
}
|
||||
|
||||
// ─── COULEUR CRAYON ───────────────────────────────────────
|
||||
// ─── PENCIL COLOR ────────────────────────────────────────
|
||||
half3 PencilColor(half3 surfaceCol, float darken, float colorBlend)
|
||||
{
|
||||
half3 darkSurface = surfaceCol * (1.0 - darken);
|
||||
return lerp(half3(0,0,0), darkSurface, colorBlend);
|
||||
}
|
||||
|
||||
// ─── GOUACHE SHADOW ───────────────────────────────────────
|
||||
// ─── GOUACHE SHADOW ──────────────────────────────────────
|
||||
half3 ApplyGouache(half3 col, float3 worldPos, float lum, float curvature)
|
||||
{
|
||||
// On est dans la zone sombre ?
|
||||
float shadowMask = 1.0 - smoothstep(0.0, _GouacheThreshold, lum);
|
||||
if (shadowMask <= 0.0) return col;
|
||||
|
||||
// Brush texture en triplanar pour coller aux surfaces
|
||||
float2 uvBrush1 = worldPos.xz * _GouacheScale;
|
||||
float2 uvBrush2 = worldPos.xy * _GouacheScale * 0.7 + float2(3.1, 7.4);
|
||||
float2 uvBrush3 = worldPos.yz * _GouacheScale * 1.3 + float2(1.7, 2.9);
|
||||
@@ -225,81 +241,130 @@ Shader "Custom/ToonBilal"
|
||||
float b3 = SAMPLE_TEXTURE2D(_BrushTex, sampler_BrushTex, uvBrush3).r;
|
||||
float brush = (b1 * 0.5 + b2 * 0.3 + b3 * 0.2);
|
||||
|
||||
// Posterize la couleur pour effet aplat gouache
|
||||
float3 gouacheCol = col;
|
||||
gouacheCol.r = floor(gouacheCol.r * _GouachePosterize) / _GouachePosterize;
|
||||
gouacheCol.g = floor(gouacheCol.g * _GouachePosterize) / _GouachePosterize;
|
||||
gouacheCol.b = floor(gouacheCol.b * _GouachePosterize) / _GouachePosterize;
|
||||
|
||||
// Boost saturation — les ombres gouache sont riches en couleur
|
||||
gouacheCol = AdjustSaturation(gouacheCol, _GouacheSaturation);
|
||||
|
||||
// La texture de brush module l'opacité de l'aplat
|
||||
// Zones où le brush est foncé = plus de gouache visible
|
||||
float brushMask = 1.0 - brush * 0.5;
|
||||
|
||||
// Résultat final gouache
|
||||
half3 result = lerp(col, gouacheCol * brushMask, shadowMask * _GouacheStrength);
|
||||
|
||||
return result;
|
||||
return lerp(col, gouacheCol * brushMask, shadowMask * _GouacheStrength);
|
||||
}
|
||||
|
||||
// ─── HACHURES TRIPLANAR ───────────────────────────────────
|
||||
float OrganicHatch(float3 worldPos, float3 worldNormal, float shadowAmount, float curvature, float2 screenUV)
|
||||
// ─── TRIPLANAR HATCHING ───────────────────────────────────
|
||||
// Normal-oriented UVs: rotates hatch UVs based on surface normal direction
|
||||
// so each face gets its own stroke orientation — anchored to world geometry
|
||||
float2 NormalOrientedUV(float3 worldPos, float3 normal, float3 tangent, float3 bitangent, float scale)
|
||||
{
|
||||
return float2(dot(worldPos, tangent), dot(worldPos, bitangent)) * scale;
|
||||
}
|
||||
|
||||
float OrganicHatch(float3 worldPos, float3 worldNormal, float shadowAmount, float curvature, float2 screenUV, float toonEdge)
|
||||
{
|
||||
float3 weights = pow(abs(worldNormal), _TriplanarSharpness);
|
||||
weights /= (weights.x + weights.y + weights.z + 0.0001);
|
||||
|
||||
float2 uvX = worldPos.yz * _HatchScale;
|
||||
// Organic deformation — world-space only
|
||||
float2 uvY = worldPos.xz * _HatchScale;
|
||||
float2 uvZ = worldPos.xy * _HatchScale;
|
||||
|
||||
float2 off = float2(
|
||||
FBM(uvY * _HatchOrganicScale),
|
||||
FBM(uvY * _HatchOrganicScale + float2(5.2, 1.3))
|
||||
) * _HatchOrganicNoise;
|
||||
|
||||
float grain = SmoothNoise(screenUV * _HatchGrainScale);
|
||||
float pressure = SmoothNoise(screenUV * _HatchGrainScale * 0.3 + float2(3.7, 8.1));
|
||||
// World-space grain and pressure — stable under camera movement
|
||||
float grain = SmoothNoise(worldPos.xz * _HatchGrainScale * 0.01);
|
||||
float pressure = SmoothNoise(worldPos.xy * _HatchGrainScale * 0.003 + float2(3.7, 8.1));
|
||||
float pressureVar = lerp(1.0, pressure * 1.5, _HatchPressure);
|
||||
|
||||
float h1X = SAMPLE_TEXTURE2D(_HatchTex, sampler_HatchTex, uvX + off).r;
|
||||
float h1Y = SAMPLE_TEXTURE2D(_HatchTex, sampler_HatchTex, uvY + off).r;
|
||||
float h1Z = SAMPLE_TEXTURE2D(_HatchTex, sampler_HatchTex, uvZ + off).r;
|
||||
// ── Layer 1: normal-oriented per face
|
||||
// Build per-face tangent frames so strokes follow surface orientation
|
||||
float3 upX = abs(worldNormal.x) > 0.9 ? float3(0,1,0) : float3(1,0,0);
|
||||
float3 tX = normalize(cross(upX, float3(1,0,0)));
|
||||
float3 bX = normalize(cross(float3(1,0,0), tX));
|
||||
|
||||
float3 upY = float3(1,0,0);
|
||||
float3 tY = normalize(cross(upY, float3(0,1,0)));
|
||||
float3 bY = normalize(cross(float3(0,1,0), tY));
|
||||
|
||||
float3 upZ = abs(worldNormal.z) > 0.9 ? float3(0,1,0) : float3(0,0,1);
|
||||
float3 tZ = normalize(cross(upZ, float3(0,0,1)));
|
||||
float3 bZ = normalize(cross(float3(0,0,1), tZ));
|
||||
|
||||
float2 uvX1 = NormalOrientedUV(worldPos, worldNormal, tX, bX, _HatchScale) + off;
|
||||
float2 uvY1 = NormalOrientedUV(worldPos, worldNormal, tY, bY, _HatchScale) + off;
|
||||
float2 uvZ1 = NormalOrientedUV(worldPos, worldNormal, tZ, bZ, _HatchScale) + off;
|
||||
|
||||
float h1X = SAMPLE_TEXTURE2D(_HatchTex, sampler_HatchTex, uvX1).r;
|
||||
float h1Y = SAMPLE_TEXTURE2D(_HatchTex, sampler_HatchTex, uvY1).r;
|
||||
float h1Z = SAMPLE_TEXTURE2D(_HatchTex, sampler_HatchTex, uvZ1).r;
|
||||
float h1 = h1X * weights.x + h1Y * weights.y + h1Z * weights.z;
|
||||
|
||||
float2 uvX2 = RotateUV(worldPos.yz * _HatchScale2, _HatchRotation) + off * 0.5;
|
||||
float2 uvY2 = RotateUV(worldPos.xz * _HatchScale2, _HatchRotation) + off * 0.5;
|
||||
float2 uvZ2 = RotateUV(worldPos.xy * _HatchScale2, _HatchRotation) + off * 0.5;
|
||||
// ── Layer 2: rotated for cross-hatching
|
||||
float2 uvX2 = RotateUV(NormalOrientedUV(worldPos, worldNormal, tX, bX, _HatchScale2), _HatchRotation) + off * 0.5;
|
||||
float2 uvY2 = RotateUV(NormalOrientedUV(worldPos, worldNormal, tY, bY, _HatchScale2), _HatchRotation) + off * 0.5;
|
||||
float2 uvZ2 = RotateUV(NormalOrientedUV(worldPos, worldNormal, tZ, bZ, _HatchScale2), _HatchRotation) + off * 0.5;
|
||||
|
||||
float h2X = SAMPLE_TEXTURE2D(_HatchTex, sampler_HatchTex, uvX2).r;
|
||||
float h2Y = SAMPLE_TEXTURE2D(_HatchTex, sampler_HatchTex, uvY2).r;
|
||||
float h2Z = SAMPLE_TEXTURE2D(_HatchTex, sampler_HatchTex, uvZ2).r;
|
||||
float h2 = h2X * weights.x + h2Y * weights.y + h2Z * weights.z;
|
||||
|
||||
float layerBlend = lerp(_HatchLayerBlend, 1.0, shadowAmount);
|
||||
float hatch = lerp(h1, min(h1, h2), layerBlend);
|
||||
// ── Layer 3: third angle for very dark/curved zones
|
||||
float angle3 = _HatchRotation * 1.7;
|
||||
float2 uvX3 = RotateUV(NormalOrientedUV(worldPos, worldNormal, tX, bX, _HatchScale3), angle3) + off * 0.3;
|
||||
float2 uvY3 = RotateUV(NormalOrientedUV(worldPos, worldNormal, tY, bY, _HatchScale3), angle3) + off * 0.3;
|
||||
float2 uvZ3 = RotateUV(NormalOrientedUV(worldPos, worldNormal, tZ, bZ, _HatchScale3), angle3) + off * 0.3;
|
||||
|
||||
float h3X = SAMPLE_TEXTURE2D(_HatchTex, sampler_HatchTex, uvX3).r;
|
||||
float h3Y = SAMPLE_TEXTURE2D(_HatchTex, sampler_HatchTex, uvY3).r;
|
||||
float h3Z = SAMPLE_TEXTURE2D(_HatchTex, sampler_HatchTex, uvZ3).r;
|
||||
float h3 = h3X * weights.x + h3Y * weights.y + h3Z * weights.z;
|
||||
|
||||
// Shadow-driven layer blending — more layers in darker/curved zones
|
||||
float darkness = 1.0 - shadowAmount;
|
||||
float blend12 = lerp(_HatchLayerBlend, 1.0, saturate(darkness * 1.5 + curvature));
|
||||
float blend3 = saturate((darkness - 0.4) * 2.0 + curvature * 0.8 + toonEdge);
|
||||
|
||||
float hatch = lerp(h1, min(h1, h2), blend12);
|
||||
hatch = lerp(hatch, min(hatch, h3), blend3);
|
||||
hatch = saturate(hatch + grain * _HatchGrainStrength);
|
||||
|
||||
float shadowMask = pow(1.0 - smoothstep(0.0, _HatchThreshold, 1.0 - shadowAmount), _HatchDensityCurve);
|
||||
float curvatureMask = lerp(_FlatSurface, 1.0, curvature);
|
||||
// Shadow mask — wider in dark zones, boosted at toon edges and curves
|
||||
float shadowMask = pow(smoothstep(_HatchThreshold, 0.0, shadowAmount), _HatchDensityCurve);
|
||||
float edgeMask = saturate(toonEdge * 2.0 + curvature);
|
||||
shadowMask = saturate(shadowMask + edgeMask * 0.6);
|
||||
|
||||
return shadowMask * curvatureMask * _HatchStrength * pressureVar * (1.0 - hatch);
|
||||
float curvatureMask = lerp(_FlatSurface, 1.0, saturate(curvature * 2.0));
|
||||
float curvatureBoost = 1.0 + curvature * 1.2;
|
||||
|
||||
// Traits noirs sur fond blanc: hatch value IS the stroke
|
||||
return shadowMask * curvatureMask * _HatchStrength * pressureVar * hatch * curvatureBoost;
|
||||
}
|
||||
|
||||
// ─── FRAGMENT ────────────────────────────────────────────
|
||||
half4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
float2 uv = input.texcoord;
|
||||
float2 uv = input.texcoord;
|
||||
half3 col = SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, uv).rgb;
|
||||
|
||||
float2 texelBase = float2(1.0 / _ScreenParams.x, 1.0 / _ScreenParams.y);
|
||||
float lum = dot(col, float3(0.299, 0.587, 0.114));
|
||||
|
||||
half3 col = SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, uv).rgb;
|
||||
float lum = dot(col, float3(0.299, 0.587, 0.114));
|
||||
// ── World space — computed early, used throughout
|
||||
float rawDepth = SampleSceneDepth(uv);
|
||||
float linDepth = LinearizeDepth(rawDepth);
|
||||
float3 worldPos = ReconstructWorldPos(uv, rawDepth);
|
||||
float3 worldNormal = SampleSceneNormals(uv);
|
||||
float curvature = ComputeCurvature(uv, texelBase);
|
||||
|
||||
// ── Outlines avec épaisseur variable
|
||||
float noiseThick = SmoothNoise(uv * 80.0);
|
||||
float thicknessVar = lerp(1.0, noiseThick * 2.0, _OutlineThicknessVar);
|
||||
float2 texelThin = texelBase * _OutlineThickness * 0.5 * thicknessVar;
|
||||
float2 texelThick = texelBase * _OutlineThickness * 1.5 * thicknessVar;
|
||||
// ── Outlines with variable thickness, fading with distance
|
||||
float distanceFade = 1.0 - saturate(linDepth / _OutlineDistanceFade);
|
||||
float noiseThick = SmoothNoise(worldPos.xz * 2.0);
|
||||
float thicknessVar = lerp(1.0, noiseThick * 2.0, _OutlineThicknessVar) * distanceFade;
|
||||
float2 texelThin = texelBase * _OutlineThickness * 0.5 * thicknessVar;
|
||||
float2 texelThick = texelBase * _OutlineThickness * 1.5 * thicknessVar;
|
||||
|
||||
half3 cn = SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, uv + float2(0, texelThin.y)).rgb;
|
||||
half3 cs = SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, uv - float2(0, texelThin.y)).rgb;
|
||||
@@ -328,55 +393,62 @@ Shader "Custom/ToonBilal"
|
||||
float colorEdge = lerp(colorEdgeInner, colorEdgeOuter * 0.5, _OutlineSoftness);
|
||||
colorEdge = step(_ColorThreshold, colorEdge) * _ColorOutlineStrength;
|
||||
|
||||
// Linearized depth outlines — consistent threshold in meters, not raw buffer
|
||||
float2 texelOutline = texelBase * _OutlineThickness * thicknessVar;
|
||||
float dn = SampleSceneDepth(uv + float2(0, texelOutline.y));
|
||||
float ds = SampleSceneDepth(uv - float2(0, texelOutline.y));
|
||||
float de = SampleSceneDepth(uv + float2(texelOutline.x, 0));
|
||||
float dw = SampleSceneDepth(uv - float2(texelOutline.x, 0));
|
||||
float depthRaw = abs(dn-ds) + abs(de-dw);
|
||||
float dn = LinearizeDepth(SampleSceneDepth(uv + float2(0, texelOutline.y)));
|
||||
float ds = LinearizeDepth(SampleSceneDepth(uv - float2(0, texelOutline.y)));
|
||||
float de = LinearizeDepth(SampleSceneDepth(uv + float2(texelOutline.x, 0)));
|
||||
float dw = LinearizeDepth(SampleSceneDepth(uv - float2(texelOutline.x, 0)));
|
||||
float depthRaw = abs(dn-ds) + abs(de-dw);
|
||||
float depthEdge = smoothstep(_DepthThreshold * 0.5, _DepthThreshold * 2.0, depthRaw) * _DepthOutlineStrength;
|
||||
depthEdge *= 1.0 - smoothstep(0.5, 0.85, brightnessForFade);
|
||||
depthEdge *= distanceFade;
|
||||
|
||||
float edge = saturate(depthEdge + colorEdge);
|
||||
|
||||
// ── Toon shading
|
||||
float toon = floor(lum * _ToonSteps) / _ToonSteps;
|
||||
toon = lerp(_ShadowStrength, 1.0, toon);
|
||||
// ── Toon shading with highlight boost (Bilal: near-white highlights)
|
||||
float toon = floor(lum * _ToonSteps) / _ToonSteps;
|
||||
toon = lerp(_ShadowStrength, 1.0, toon);
|
||||
half3 toonCol = col * toon;
|
||||
|
||||
// ── World space
|
||||
float depth = SampleSceneDepth(uv);
|
||||
float3 worldPos = ReconstructWorldPos(uv, depth);
|
||||
float3 worldNormal = ReconstructNormal(uv, texelBase);
|
||||
float curvature = ComputeCurvature(uv, texelBase);
|
||||
// Blow out highlights — bright zones go nearly white like Bilal
|
||||
float highlightMask = smoothstep(_HighlightThreshold, 1.0, lum);
|
||||
toonCol = lerp(toonCol, toonCol * _HighlightBoost, highlightMask);
|
||||
toonCol = min(toonCol, 1.2); // allow slight overexposure
|
||||
|
||||
// ── Gouache dans les zones sombres — appliqué avant les hachures
|
||||
// ── Gouache in dark areas
|
||||
toonCol = ApplyGouache(toonCol, worldPos, lum, curvature);
|
||||
|
||||
// ── Hachures par dessus la gouache
|
||||
float shadowAmount = 1.0 - lum;
|
||||
float hatchBlend = OrganicHatch(worldPos, worldNormal, shadowAmount, curvature, uv);
|
||||
// ── Hatching — fully world-space, stable under camera movement
|
||||
float3 lightDir = normalize(float3(1, -1, 1));
|
||||
float toonEdge = saturate(fwidth(floor(lum * _ToonSteps)) * 10.0);
|
||||
float hatchBoost = saturate(toonEdge + curvature * 0.5);
|
||||
float shadowAmount = saturate(dot(worldNormal, -lightDir) + hatchBoost * 0.4);
|
||||
float hatchBlend = OrganicHatch(worldPos, worldNormal, shadowAmount, curvature, uv, toonEdge);
|
||||
|
||||
// Dans les zones très sombres on réduit les hachures (la gouache prend le relais)
|
||||
float gouacheMask = 1.0 - smoothstep(0.0, _GouacheThreshold, lum);
|
||||
hatchBlend *= lerp(1.0, 1.0 - _GouacheBlend, gouacheMask);
|
||||
|
||||
// Hatch fades in bright zones — highlights stay clean
|
||||
hatchBlend *= 1.0 - highlightMask * 0.8;
|
||||
|
||||
half3 hatchCol = PencilColor(col, _HatchDarken, _HatchColorBlend);
|
||||
toonCol = lerp(toonCol, hatchCol, hatchBlend);
|
||||
|
||||
// ── Outline fade
|
||||
// ── Outline fade on bright surfaces
|
||||
float outlineFade = lerp(_OutlineBrightMin, 1.0, 1.0 - smoothstep(_OutlineFadeStart, _OutlineFadeEnd, brightnessForFade));
|
||||
outlineFade = lerp(1.0, outlineFade, _OutlineFadeStrength);
|
||||
|
||||
half3 outlineCol = PencilColor(col, _OutlineDarken, _OutlineColorBlend);
|
||||
half3 finalCol = lerp(toonCol, outlineCol, edge * outlineFade);
|
||||
half3 finalCol = lerp(toonCol, outlineCol, edge * outlineFade);
|
||||
|
||||
// ── Weight global
|
||||
finalCol = lerp(col, finalCol, _ShaderWeight);
|
||||
finalCol = lerp(col, finalCol, _ShaderWeight * _ToonEnabled);
|
||||
|
||||
return half4(finalCol, 1);
|
||||
}
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
|
||||
CustomEditor "ToonBilalEditor"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user