Files
Ipseity-Demo/Assets/_Content/Shaders/Postprocess/Include/EnkiBillalFullscreen.hlsl
T

356 lines
10 KiB
HLSL

#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"
TEXTURE2D_X(_BlurredTexture);
SAMPLER(sampler_BlurredTexture);
float2 RotateUV(float2 UV, float2 Pivot, float Angle)
{
float s = sin(Angle);
float c = cos(Angle);
UV -= Pivot;
float2 rotated = float2(
UV.x * c - UV.y * s,
UV.x * s + UV.y * c
);
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 SampleSceneDepthMeter(float2 UV)
{
float rawDepth = SampleSceneDepth(UV);
#if UNITY_REVERSED_Z
bool isSky = rawDepth <= 0.00001;
rawDepth = isSky ? 0.0 : rawDepth;
#else
bool isSky = rawDepth >= 0.99999;
rawDepth = isSky ? 1.0 : rawDepth;
#endif
float depthMeters = isSky
? _ProjectionParams.z
: LinearEyeDepth(rawDepth, _ZBufferParams);
return depthMeters;
}
float ComputeOutline(float2 UV, float2 Thickness, float3 NormalWS, float3 ViewDir, float DepthAtten)
{
// DEPTH OUTLINE
float2 o = Thickness * (1 - DepthAtten);
float d0 = SampleSceneDepthMeter(UV);
float d1 = SampleSceneDepthMeter(UV + float2(-o.x,0));
float d2 = SampleSceneDepthMeter(UV + float2( o.x,0));
float d3 = SampleSceneDepthMeter(UV + float2(0,-o.y));
float d4 = SampleSceneDepthMeter(UV + float2(0, o.y));
float depthDiff = max(max(abs(d0 - d1), abs(d0 - d2)), max(abs(d0 - d3), abs(d0 - d4)));
float incidence = abs(dot(NormalWS, ViewDir));
float incidenceAtten = smoothstep(.22, .35, incidence);
float2 depthMinRange = float2(.15, 0.3);
float2 depthMaxRange = float2(0.5, 1.1);
float2 depthRange = lerp(depthMinRange, depthMaxRange, DepthAtten);
float depthOutline = smoothstep(depthRange.x, depthRange.y, depthDiff);
depthOutline *= incidenceAtten;
// NORMAL OUTLINE
o *= .5;
float3 n0 = normalize(SampleSceneNormals(UV));
float3 n1 = normalize(SampleSceneNormals(UV + float2(-o.x, 0)));
float3 n2 = normalize(SampleSceneNormals(UV + float2( o.x, 0)));
float3 n3 = normalize(SampleSceneNormals(UV + float2(0, -o.y)));
float3 n4 = normalize(SampleSceneNormals(UV + float2(0, o.y)));
float normalDiff = distance(n0, n1) + distance(n0, n2) + distance(n0, n3) + distance(n0, n4);
float normalOutline = smoothstep(0.6, 0.8, normalDiff) * smoothstep(10, 3, d0);
return saturate(depthOutline + normalOutline * .8);
//return depthOutline;
}
void EnkiBillalFullscreen_float
(
float2 UV,
out float3 Output
)
{
// INPUTS
float3 sceneColor = SampleSceneColor(UV);
float rawDepth = SampleSceneDepth(UV);
#if UNITY_REVERSED_Z
bool isSky = rawDepth <= 0.00001;
rawDepth = isSky ? 0.0 : rawDepth;
#else
bool isSky = rawDepth >= 0.99999;
rawDepth = isSky ? 1.0 : rawDepth;
#endif
float depthMeters = isSky
? _ProjectionParams.z
: LinearEyeDepth(rawDepth, _ZBufferParams);
float depthForReconstruct = rawDepth;
#if !UNITY_REVERSED_Z
depthForReconstruct = lerp(UNITY_NEAR_CLIP_VALUE, 1.0, rawDepth);
#endif
float3 positionWS = ComputeWorldSpacePosition(UV, depthForReconstruct, UNITY_MATRIX_I_VP);
float noiseAtten = pow(smoothstep(1, 10, depthMeters), 2);
float np1 = PerlinNoise3D(positionWS + floor(_Time.y * 8) * 3.7, 15) * 2 - 1;
float2 uv1 = UV + np1 * lerp(.001, .002, noiseAtten);
float3 normalWS = normalize(SampleSceneNormals(UV));
float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - positionWS);
float np2 = FBMNoise3D(positionWS + np1 * .05, .5, 1, 2, .5) * 2 - 1;
float2 uv2 = uv1 + np2 * .0;
float3 sceneColor2 = SampleSceneColor(uv2);
float np3 = PerlinNoise3D(positionWS + floor(_Time.y * 5) * 6.1, 1.5);
float2 uv3 = uv2 + np3 * lerp(.005, .008, noiseAtten);
// OUTLINE
float outlineAtten = smoothstep(3, 30, depthMeters);
float outline = 0;
float n0 = PerlinNoise3D(positionWS, 80);
[Unroll]
for (float i = 0; i < 2; i++)
{
float t = floor(cos((_Time.y + positionWS) * (4 + i * 3) * .8) * .1);
t = 0;
float n1 = PerlinNoise3D(positionWS + i * 3.3 + n0, 1.7 + 1 * .2 + t);
float2 thickness = lerp(0, 15 + i * 2, pow(n1, 2));
thickness = thickness * _ScreenParams.y / 1080 / _ScreenParams.xy;
float2 uv = uv3;
if (i == 1)
uv = uv1;
outline += ComputeOutline(uv, thickness, normalWS, viewDir, outlineAtten) * (i * .5 + 1);
}
outline /= 2.5;
// COLOR (WIP)
float3 c = sceneColor;
float3 greyscale = smoothstep(.1, .5, (sceneColor2.r + sceneColor2.g + sceneColor2.b) / 3.);
//c = lerp(sceneColor, sceneColor2, smoothstep(1, .9, (sceneColor2.r + sceneColor2.g + sceneColor2.b) / 3));
//c = (sceneColor2.r + sceneColor2.g + sceneColor2.b) / 3.;
c = lerp(c, sceneColor2, (greyscale + smoothstep(5, 35, depthMeters) * .8) * .5);
//c += sceneColor2 * greyscale * .5;
c = lerp(c, float3(.001, .002, .0015), outline);
//c = ((c + 1) * (sceneColor2 + 0));
//c = sceneColor2;
//c = smoothstep(-.1, 0, np2);
//c = greyscale;
/*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;
c *= 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 hatchLayerMask = smoothstep(.35, .75, np3 + n0);
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 = c;
//Output = sceneColor;
//Output = hatchMask;
//Output = dot(normalWS, viewDir);
}
#endif