From f1f4c47b1c94c56f8e483b5005e2426da0ace628 Mon Sep 17 00:00:00 2001 From: Alexandre Coirier Date: Thu, 28 May 2026 01:27:15 +0200 Subject: [PATCH] wip: Postprocess --- Assets/_Content/Settings/PC_Renderer.asset | 10 +- .../Shaders/EnkiBillal/EnkiBiIlal.shadergraph | 4 +- .../EnkiBillal/Include/EnkiBiIlal.hlsl | 83 ++--- .../EnkiBillalFullscreen.shadergraph | 87 ++--- .../Include/EnkiBillalFullscreen.hlsl | 338 +++++++++++++----- 5 files changed, 331 insertions(+), 191 deletions(-) diff --git a/Assets/_Content/Settings/PC_Renderer.asset b/Assets/_Content/Settings/PC_Renderer.asset index f54b8b39..cad6f411 100644 --- a/Assets/_Content/Settings/PC_Renderer.asset +++ b/Assets/_Content/Settings/PC_Renderer.asset @@ -12,10 +12,10 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: b00045f12942b46c698459096c89274e, type: 3} m_Name: EnkiBillal m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.FullScreenPassRendererFeature - m_Active: 0 - injectionPoint: 550 + m_Active: 1 + injectionPoint: 450 fetchColorBuffer: 1 - requirements: 0 + requirements: 3 passMaterial: {fileID: 2100000, guid: 14d54f1b8620b4f469a8f7cbb0f38746, type: 2} passIndex: 0 bindDepthStencilAttachment: 0 @@ -231,6 +231,7 @@ MonoBehaviour: probeSamplingDebugTexture: {fileID: 2800000, guid: 24ec0e140fb444a44ab96ee80844e18e, type: 3} probeVolumeBlendStatesCS: {fileID: 7200000, guid: b9a23f869c4fd45f19c5ada54dd82176, type: 3} m_RendererFeatures: + - {fileID: -7768931065263243598} - {fileID: 7833122117494664109} - {fileID: -2180735518627098448} - {fileID: -684188129942751669} @@ -240,8 +241,7 @@ MonoBehaviour: - {fileID: -5009354820807464973} - {fileID: -693333259539726544} - {fileID: 8901923127885692829} - - {fileID: -7768931065263243598} - m_RendererFeatureMap: ad6b866f10d7b46cb090278f9978bce14b363953854681f6c54395c2873af7daf70a34b8254019c33a6973a737837b71f367e1c754327bba30bf2bea12c960f69dff759febfb897bb2be7c925b362f94 + m_RendererFeatureMap: b2be7c925b362f94ad6b866f10d7b46cb090278f9978bce14b363953854681f6c54395c2873af7daf70a34b8254019c33a6973a737837b71f367e1c754327bba30bf2bea12c960f69dff759febfb897b m_UseNativeRenderPass: 1 xrSystemData: {fileID: 0} postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} diff --git a/Assets/_Content/Shaders/EnkiBillal/EnkiBiIlal.shadergraph b/Assets/_Content/Shaders/EnkiBillal/EnkiBiIlal.shadergraph index 3e694070..7bd198cb 100644 --- a/Assets/_Content/Shaders/EnkiBillal/EnkiBiIlal.shadergraph +++ b/Assets/_Content/Shaders/EnkiBillal/EnkiBiIlal.shadergraph @@ -2810,7 +2810,7 @@ "m_SerializedTexture": "", "m_Guid": "" }, - "m_DefaultType": 0 + "m_DefaultType": 3 } { @@ -3025,7 +3025,7 @@ "m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot", "m_ObjectId": "87fe166e94ba4efc8795b3e169e213e8", "m_Id": 0, - "m_DisplayName": "UseVertexColor", + "m_DisplayName": "VertexColor", "m_SlotType": 1, "m_Hidden": false, "m_ShaderOutputName": "Out", diff --git a/Assets/_Content/Shaders/EnkiBillal/Include/EnkiBiIlal.hlsl b/Assets/_Content/Shaders/EnkiBillal/Include/EnkiBiIlal.hlsl index 22036f27..347c9ee2 100644 --- a/Assets/_Content/Shaders/EnkiBillal/Include/EnkiBiIlal.hlsl +++ b/Assets/_Content/Shaders/EnkiBillal/Include/EnkiBiIlal.hlsl @@ -345,6 +345,46 @@ void EnkiBillal_float // float stripes = WorldStripes(); + + // Test + + //float test = ValueNoise3D(PositionWS, 40); + //float test = PerlinNoise3D(PositionWS, 40); + //float test = PerlinNoise3DLOD(PositionWS, 100, 3.5); + //float test = SimplexNoise3D(PositionWS, 40); + //float test = WorleyNoise3D(PositionWS, 40, 1); + //float id; + //float test = VoronoiNoise3D(PositionWS, 10, 1, .05, id); + //float test = FBMNoise3D(PositionWS, 10, 2, 2, .5); + //float test = RidgedNoise3D(PositionWS, 10, 2, 2, .5); + + /*float3 pWS = scaledPositionOS; + float n0 = PerlinNoise3D(pWS, 2); + float distort = WorldDistort(pWS + n0 * .2, NormalWS, 1, TriplanarBlend); + float3 p = pWS + n0 * 2 + distort * smoothstep(.5, .7, n0) * .06; + float grad = 0; + float cell = 0; + VoronoiNoise3D_float(p, 2, 1, 1, grad, cell); + + + float3 v = cell * .8;// * (grad + distort * .1); + v += smoothstep(.05, .02, grad) * smoothstep(.4, .7, n0) * 2; + float3 c = Color * lerp(.9, 1, v);*/ + + // Output + + //Output = 1; + //if (Step > 0 ) Output *= Color; + //if (Step > 1 ) Output *= grainAtten; + //if (Step > 2 ) Output *= dirtAtten; + //if (Step > 3 ) Output *= shadowAtten; + //if (Step > 4 ) Output = lerp(Output, Output * .1, stripes * .8); + + Output = Color; + + //Output = PerlinColor3D(PositionWS, 5); + //Output = smoothstep(.97, .93, ao); + // Mask if (Mask2[0].w == 1) @@ -359,13 +399,13 @@ void EnkiBillal_float } else { - float Active = Mask0[0].w + Mask1[0].w;// + Mask2[0].w; + float Active = Mask0[0].w + Mask1[0].w; // + Mask2[0].w; if (Active > 0) { float mask = saturate( SampleProjectionMask(PositionWS, Mask0) + - SampleProjectionMask(PositionWS, Mask1)// + + SampleProjectionMask(PositionWS, Mask1) // + //SampleProjectionMask(PositionWS, Mask2) ); @@ -376,45 +416,6 @@ void EnkiBillal_float Alpha = (MaskID == 1) ? 0 : 1; } } - - // Test - - //float test = ValueNoise3D(PositionWS, 40); - //float test = PerlinNoise3D(PositionWS, 40); - //float test = PerlinNoise3DLOD(PositionWS, 100, 3.5); - //float test = SimplexNoise3D(PositionWS, 40); - //float test = WorleyNoise3D(PositionWS, 40, 1); - //float id; - //float test = VoronoiNoise3D(PositionWS, 10, 1, .05, id); - //float test = FBMNoise3D(PositionWS, 10, 2, 2, .5); - //float test = RidgedNoise3D(PositionWS, 10, 2, 2, .5); - - float3 pWS = scaledPositionOS; - float n0 = PerlinNoise3D(pWS, 2); - float distort = WorldDistort(pWS + n0 * .2, NormalWS, 1, TriplanarBlend); - float3 p = pWS + n0 * 2 + distort * smoothstep(.5, .7, n0) * .06; - float grad = 0; - float cell = 0; - VoronoiNoise3D_float(p, 2, 1, 1, grad, cell); - - - float3 v = cell * .8;// * (grad + distort * .1); - v += smoothstep(.05, .02, grad) * smoothstep(.4, .7, n0) * 2; - float3 c = Color * lerp(.9, 1, v); - - // Output - - //Output = 1; - //if (Step > 0 ) Output *= Color; - //if (Step > 1 ) Output *= grainAtten; - //if (Step > 2 ) Output *= dirtAtten; - //if (Step > 3 ) Output *= shadowAtten; - //if (Step > 4 ) Output = lerp(Output, Output * .1, stripes * .8); - - Output = c; - - //Output = PerlinColor3D(PositionWS, 5); - //Output = smoothstep(.97, .93, ao); } #endif diff --git a/Assets/_Content/Shaders/Postprocess/EnkiBillalFullscreen.shadergraph b/Assets/_Content/Shaders/Postprocess/EnkiBillalFullscreen.shadergraph index fb9fa79e..95fe9b53 100644 --- a/Assets/_Content/Shaders/Postprocess/EnkiBillalFullscreen.shadergraph +++ b/Assets/_Content/Shaders/Postprocess/EnkiBillalFullscreen.shadergraph @@ -61,20 +61,6 @@ }, "m_SlotId": 0 } - }, - { - "m_OutputSlot": { - "m_Node": { - "m_Id": "c5cee5deced342b7ba5119bc3e0a4eeb" - }, - "m_SlotId": 0 - }, - "m_InputSlot": { - "m_Node": { - "m_Id": "a7bb6da6110b4bd2a09bff6b04958011" - }, - "m_SlotId": 2 - } } ], "m_VertexContext": { @@ -140,22 +126,6 @@ "m_Labels": [] } -{ - "m_SGVersion": 0, - "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", - "m_ObjectId": "131be3abda9f406597ba5042775c2409", - "m_Id": 2, - "m_DisplayName": "New", - "m_SlotType": 0, - "m_Hidden": false, - "m_ShaderOutputName": "New", - "m_StageCapability": 3, - "m_Value": 0.0, - "m_DefaultValue": 0.0, - "m_Labels": [], - "m_LiteralMode": false -} - { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.ScreenPositionNode", @@ -343,10 +313,10 @@ "m_Expanded": true, "m_Position": { "serializedVersion": "2", - "x": -387.0, - "y": 200.00003051757813, + "x": -386.0, + "y": 200.0, "width": 262.0, - "height": 94.0 + "height": 118.0 } }, "m_Slots": [ @@ -354,10 +324,7 @@ "m_Id": "0b966ce7ec254b9f915ef10fd00be2c7" }, { - "m_Id": "f840ccb65a474f4c999bc6357918f904" - }, - { - "m_Id": "131be3abda9f406597ba5042775c2409" + "m_Id": "ac0e1d2a956f4c42b1e39254cb5ee817" } ], "synonyms": [ @@ -378,6 +345,29 @@ "m_FunctionBody": "Enter function body here..." } +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", + "m_ObjectId": "ac0e1d2a956f4c42b1e39254cb5ee817", + "m_Id": 1, + "m_DisplayName": "Output", + "m_SlotType": 1, + "m_Hidden": false, + "m_ShaderOutputName": "Output", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "m_Labels": [] +} + { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", @@ -547,26 +537,3 @@ ] } -{ - "m_SGVersion": 0, - "m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot", - "m_ObjectId": "f840ccb65a474f4c999bc6357918f904", - "m_Id": 1, - "m_DisplayName": "Output", - "m_SlotType": 1, - "m_Hidden": false, - "m_ShaderOutputName": "Output", - "m_StageCapability": 3, - "m_Value": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "m_DefaultValue": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "m_Labels": [] -} - diff --git a/Assets/_Content/Shaders/Postprocess/Include/EnkiBillalFullscreen.hlsl b/Assets/_Content/Shaders/Postprocess/Include/EnkiBillalFullscreen.hlsl index 81307d30..0d86692a 100644 --- a/Assets/_Content/Shaders/Postprocess/Include/EnkiBillalFullscreen.hlsl +++ b/Assets/_Content/Shaders/Postprocess/Include/EnkiBillalFullscreen.hlsl @@ -1,5 +1,6 @@ #ifndef ENKI_BILLAL_FULLSCREEN_INCLUDED #define ENKI_BILLAL_FULLSCREEN_INCLUDED + #include "Assets/_Content/Shaders/Include/Noises.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTexture.hlsl" #include "Assets/_Content/Shaders/Postprocess/Include/BlurFullscreen.hlsl" @@ -7,125 +8,296 @@ TEXTURE2D_X(_BlurredTexture); SAMPLER(sampler_BlurredTexture); -// ─── OUTLINE ──────────────────────────────────────────────────────────────── -// Width is expressed as a fraction of screen height. -// Both depth discontinuities and normal discontinuities contribute. - -float ComputeOutline(float2 uv, float outlineWidthPx, float depthThreshold, float normalThreshold) +float2 RotateUV(float2 UV, float2 Pivot, float Angle) { - // Pixel size in UV space, scaled by desired width - float2 texel = outlineWidthPx / float2(_ScreenParams.x, _ScreenParams.y); + float s = sin(Angle); + float c = cos(Angle); - // ── Sample depth at 4 neighbours (Roberts Cross pattern) ──────────────── - float d0 = LinearEyeDepth(SampleSceneDepth(uv + float2(texel.x, texel.y)), _ZBufferParams); - float d1 = LinearEyeDepth(SampleSceneDepth(uv + float2(-texel.x, texel.y)), _ZBufferParams); - float d2 = LinearEyeDepth(SampleSceneDepth(uv + float2(texel.x, -texel.y)), _ZBufferParams); - float d3 = LinearEyeDepth(SampleSceneDepth(uv + float2(-texel.x, -texel.y)), _ZBufferParams); + UV -= Pivot; - // Roberts Cross gradient magnitude on depth - float depthEdge = sqrt(pow(d0 - d3, 2) + pow(d1 - d2, 2)); - - // Normalise by depth so far geometry doesn't get thick outlines - float dCenter = LinearEyeDepth(SampleSceneDepth(uv), _ZBufferParams); - depthEdge /= (dCenter + 1e-4); - - // ── Sample normals at the same 4 neighbours ────────────────────────────── - float3 n0 = SampleSceneNormals(uv + float2(texel.x, texel.y)); - float3 n1 = SampleSceneNormals(uv + float2(-texel.x, texel.y)); - float3 n2 = SampleSceneNormals(uv + float2(texel.x, -texel.y)); - float3 n3 = SampleSceneNormals(uv + float2(-texel.x, -texel.y)); - - // Dot-product difference: 0 = identical normals, 1 = orthogonal / flipped - float normalEdge = 0; - normalEdge += 1.0 - saturate(dot(n0, n3)); - normalEdge += 1.0 - saturate(dot(n1, n2)); - normalEdge *= 0.5; - - // ── Combine and threshold ──────────────────────────────────────────────── - float edge = max( - step(depthThreshold, depthEdge), - step(normalThreshold, normalEdge) + float2 rotated = float2( + UV.x * c - UV.y * s, + UV.x * s + UV.y * c ); - return edge; + return rotated + Pivot; +} + +float WorldDistort(float3 PositionWS, float3 NormalWS, float Angle, float TriplanarBlend) +{ + float StripesScale = 60; + + // Octahedral face normals (4 faces + 3 world axes) + float3 octaFaceNormals[7] = + { + normalize(float3(1, 1, 1)), + normalize(float3(-1, 1, 1)), + normalize(float3(1, -1, 1)), + normalize(float3(-1, -1, 1)), + float3(1, 0, 0), + float3(0, 1, 0), + float3(0, 0, 1) + }; + + // Octahedral blending mask + float sharpness = Remap(0, 1, 1, 16, smoothstep(0, .9, TriplanarBlend)); + float octaMask[7]; + float hardMax = -1; + int hardIdx = 0; + for (int i = 0; i < 7; i++) + { + float d = abs(dot(NormalWS, octaFaceNormals[i])); + octaMask[i] = pow(saturate(d), sharpness); + if (d > hardMax) + { + hardMax = d; + hardIdx = i; + } + } + float maskSum = 0; + for (int i = 0; i < 7; i++) + maskSum += octaMask[i]; + for (int i = 0; i < 7; i++) + octaMask[i] /= max(maskSum, 0.0001); + float hardFactor = smoothstep(.9, 1, TriplanarBlend); + for (int i = 0; i < 7; i++) + { + float hard = (i == hardIdx) ? 1.0 : 0.0; + octaMask[i] = lerp(octaMask[i], hard, hardFactor); + } + + // Patern + float stripes = 0; + + [unroll] + for (int i = 0; i < 7; i++) + { + float3 n = octaFaceNormals[i]; + + float3 up = abs(n.y) < 0.999 ? float3(0, 1, 0) : float3(1, 0, 0); + float3 tangent = normalize(cross(up, n)); + float3 bitangent = normalize(cross(n, tangent)); + + float angle = i / 7.0 * PI; + + float2 p = RotateUV(float2(dot(PositionWS, tangent), dot(PositionWS, bitangent)), 0, angle) * StripesScale; + + float stripe = cos(p.x); + + stripes += stripe * octaMask[i]; + } + + return stripes; +} + +float Hash21(float2 p) +{ + p = frac(p * float2(123.34, 456.21)); + p += dot(p, p + 45.32); + return frac(p.x * p.y); +} + +void GetBasisFromNormal(float3 n, out float3 tangent, out float3 bitangent) +{ + float3 up = abs(n.y) < 0.999 ? float3(0, 1, 0) : float3(1, 0, 0); + tangent = normalize(cross(up, n)); + bitangent = normalize(cross(n, tangent)); +} + +float BipyramidHatch(float3 PositionWS, float3 NormalWS, float Angle, float Scale, float Width) +{ + float3 faceNormals[7] = + { + normalize(float3(1, 1, 1)), + normalize(float3(-1, 1, 1)), + normalize(float3(1, -1, 1)), + normalize(float3(-1, -1, 1)), + + float3(1, 0, 0), + float3(0, 1, 0), + float3(0, 0, 1) + }; + + float hatchSum = 0; + float weightSum = 0; + + float projectionBlend = 32.0; + float hardBlend = 0.85; + + [unroll] + for (int i = 0; i < 7; i++) + { + float3 n = faceNormals[i]; + + float w = saturate(abs(dot(NormalWS, n))); + w = pow(w, projectionBlend); + + float hard = step(0.999, w); + w = lerp(w, hard, hardBlend); + + float3 tangent; + float3 bitangent; + GetBasisFromNormal(n, tangent, bitangent); + + float2 p = float2(dot(PositionWS, tangent), dot(PositionWS, bitangent)); + p = RotateUV(p, 0, Angle); + + float lines = abs(frac(p.x * Scale) - 0.5); + float hatch = smoothstep(Width, Width * 0.65, lines); + + hatchSum += hatch * w; + weightSum += w; + } + + return hatchSum / max(weightSum, 0.0001); +} + +float ComputeOutline(float2 uv, float2 texel, float depthMeters, float3 normalWS, float3 positionWS) +{ + // DEPTH OUTLINE + + float depthL = LinearEyeDepth(SampleSceneDepth(uv + float2(-texel.x, 0)), _ZBufferParams); + float depthR = LinearEyeDepth(SampleSceneDepth(uv + float2(texel.x, 0)), _ZBufferParams); + float depthD = LinearEyeDepth(SampleSceneDepth(uv + float2(0, -texel.y)), _ZBufferParams); + float depthU = LinearEyeDepth(SampleSceneDepth(uv + float2(0, texel.y)), _ZBufferParams); + + float depthDiff = + max(abs(depthMeters - depthL), abs(depthMeters - depthR)) + + max(abs(depthMeters - depthD), abs(depthMeters - depthU)); + + float viewFacing = abs(dot(normalWS, normalize(_WorldSpaceCameraPos - positionWS))); + float grazingMask = smoothstep(0.08, 0.35, viewFacing); + + float depthThreshold = max(0.01, depthMeters * 0.03); + float depthOutline = smoothstep(depthThreshold, depthThreshold * 3.0, depthDiff); + depthOutline *= grazingMask; + + // NORMAL OUTLINE + + float3 normalL = normalize(SampleSceneNormals(uv + float2(-texel.x, 0))); + float3 normalR = normalize(SampleSceneNormals(uv + float2(texel.x, 0))); + float3 normalD = normalize(SampleSceneNormals(uv + float2(0, -texel.y))); + float3 normalU = normalize(SampleSceneNormals(uv + float2(0, texel.y))); + + float normalDiff = + distance(normalWS, normalL) + + distance(normalWS, normalR) + + distance(normalWS, normalD) + + distance(normalWS, normalU); + + float normalOutline = smoothstep(0.6, 0.8, normalDiff); + + return saturate(normalOutline + depthOutline); } void EnkiBillalFullscreen_float ( float2 UV, - float Test, out float3 Output ) { - float2 screenUV = UV; - // DEPTH - float rawDepth = SampleSceneDepth(screenUV); - float depthMeters = LinearEyeDepth(rawDepth, _ZBufferParams); // linear eye-space depth in metres - float depth01 = Linear01Depth(rawDepth, _ZBufferParams); // normalised linear depth [0..1] + float rawDepth = SampleSceneDepth(UV); + float depthMeters = LinearEyeDepth(rawDepth, _ZBufferParams); + float depth01 = Linear01Depth(rawDepth, _ZBufferParams); // POSITION WORLD SPACE - // Remap depth for non-reversed-Z platforms before reconstruction float depthForReconstruct = rawDepth; #if !UNITY_REVERSED_Z depthForReconstruct = lerp(UNITY_NEAR_CLIP_VALUE, 1.0, rawDepth); #endif - // ComputeWorldSpacePosition handles perspective divide and platform differences - float3 positionWS = ComputeWorldSpacePosition(screenUV, depthForReconstruct, UNITY_MATRIX_I_VP); + float3 positionWS = ComputeWorldSpacePosition(UV, depthForReconstruct, UNITY_MATRIX_I_VP); // NORMAL WORLD SPACE - // Requires DepthNormals PrePass to be enabled in the URP Renderer - float3 normalWS = SampleSceneNormals(screenUV); + float3 normalWS = normalize(SampleSceneNormals(UV)); // SCENE COLOR - float3 originColor = SampleSceneColor(screenUV); - - float3 sceneColorBlurred = SAMPLE_TEXTURE2D_X(_BlurredTexture, sampler_BlurredTexture, screenUV).rgb; - - float greyscale = (originColor.x + originColor.y + originColor.z); - float greyscaleBlurred = (sceneColorBlurred.x + sceneColorBlurred.y + sceneColorBlurred.z); - - float hilightMask = smoothstep(.7, 1, greyscale); - hilightMask = lerp(hilightMask, smoothstep(.7, 1, greyscaleBlurred), .5); - hilightMask *= pow(smoothstep(3, 20, depthMeters), 2); - - float offsetMask = hilightMask; - float3 offset3D = PerlinColor3D(positionWS * float3(1, 6, 1), 1); - offset3D = smoothstep(.45, .55, offset3D); - - float3 offsetUV = offset3D * offsetMask * .4 / depthMeters; - - float3 sceneColor = SampleSceneColor(screenUV + offsetUV); - sceneColor = lerp(sceneColor, sceneColorBlurred, hilightMask); - sceneColor = lerp(sceneColor, originColor, .5); - sceneColor = lerp(sceneColor * .5, sceneColor * 1, hilightMask); - - //float3 sceneColor = SAMPLE_TEXTURE2D_X(_CameraOpaqueTexture, sampler_PointClamp, screenUV).rgb; + float3 sceneColor = SampleSceneColor(UV); + + // SETTINGS + + float outlineAtten = smoothstep(3, 30, depthMeters); + + float thicknessNoise = (PerlinNoise3D(positionWS, 1.7) - .4) * 18; + thicknessNoise *= sqrt(1 - outlineAtten); + float thicknessRaw = lerp(thicknessNoise, 1, outlineAtten); + float thicknessA = floor(thicknessRaw); + float thicknessB = thicknessA + 1; + float thicknessBlend = frac(thicknessRaw); + + float2 texelA = (thicknessA / _ScreenParams.y * 1080) / _ScreenParams.xy; + float2 texelB = (thicknessB / _ScreenParams.y * 1080) / _ScreenParams.xy; + // OUTLINE - float OutlineWidthPx = max(PerlinNoise3D(positionWS, 1) * 3 - 1, 0); - float OutlineDepthThreshold = .03; - float OutlineNormalThreshold = .35; - float OutlineColor = float3(0, 0, 0); + float2 uvA = UV; + float2 uvB = UV; - // Width is normalised to screen height so it stays consistent at any resolution. - float widthInPixels = OutlineWidthPx * (_ScreenParams.y / 1080.0); + float outlineA = ComputeOutline(uvA, texelA, depthMeters, normalWS, positionWS); + float outlineB = ComputeOutline(uvB, texelB, depthMeters, normalWS, positionWS); - float outline = ComputeOutline(screenUV, widthInPixels, OutlineDepthThreshold, OutlineNormalThreshold); - sceneColor = lerp(sceneColor, OutlineColor, outline); + float outline = lerp(outlineA, outlineB, thicknessBlend); + + // COLOR (WIP) + + float3 pWS = positionWS; //scaledPositionOS; + float n0 = PerlinNoise3D(pWS, 2); + float distort = WorldDistort(pWS + n0 * .2, normalWS, 1, .1); + float3 p = pWS + n0 * 2 + distort * smoothstep(.5, .7, n0) * .06; + float grad = 0; + float cell = 0; + VoronoiNoise3D_float(p, 2, 1, 1, grad, cell); + + + float3 v = cell * .8; // * (grad + distort * .1); + v += smoothstep(.05, .02, grad) * smoothstep(.4, .7, n0) * 2; + float3 c = sceneColor * lerp(.9, 1, v); + + // DIRT + + float dirtNoise0 = PerlinNoise3D(positionWS, 30); + float dirtNoise1 = PerlinNoise3D(positionWS, 5); + + float dirt0 = smoothstep(.2, .22, dirtNoise0); + float dirt1 = saturate(smoothstep(.01, .02, abs(dot(dirtNoise0, dirtNoise1) - .4)) + dirtNoise1 + outlineAtten); + + c *= dirt0 * dirt1; + + // SHADOW + + float sceneLuminance = dot(sceneColor, float3(.299, .587, .114)); + + float hatchAtten = smoothstep(15, 1, depthMeters); + + float hatchMask = smoothstep(.012, .004, sceneLuminance) * hatchAtten; + + float hatchWidth = lerp(.025, .18, hatchMask) * hatchAtten; + + float hatchNoise = PerlinNoise3D(positionWS, .85); + float hatchLayerMask = smoothstep(.35, .75, hatchNoise); + + float hatch0 = BipyramidHatch(positionWS, normalWS, .35, 28, hatchWidth); + float hatch1 = BipyramidHatch(positionWS + 13.7, normalWS, 1.75, 21, hatchWidth * .85); + + float hatch2 = BipyramidHatch(positionWS + 31.3, normalWS, 2.45, 26, hatchWidth * .9); + float hatch3 = BipyramidHatch(positionWS + 47.9, normalWS, .95, 19, hatchWidth * .8); + + float hatchesA = saturate(hatch0 + hatch1 * .45); + float hatchesB = saturate(hatch2 + hatch3 * .45); + + float hatches = saturate(hatchesA + hatchesB * hatchLayerMask * .55); + + c = lerp(c, float3(0, 0, 0), hatches * hatchMask * .3); // OUTPUT - - Output = sceneColor; //BlurSceneColor(screenUV, .1); - //Output = offsetMask; - //Output = hilightMask; //BlurSceneColor(screenUV, .1); - //Output = lerp(originColor, sceneColorBlurred, smoothstep(3, 20, depthMeters)); + Output = lerp(c, float3(0.0, 0.0, 0.0), outline); + //Output = hatchMask; } #endif \ No newline at end of file