Files
Ipseity-Demo/Assets/_Content/Shaders/EnkiBillal/Include/EnkiBiIlal.hlsl
T

238 lines
5.0 KiB
HLSL

#ifndef ENKI_BILLAL_INCLUDED
#define ENKI_BILLAL_INCLUDED
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "Assets/_Content/Shaders/Include/Noises.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/AmbientOcclusion.hlsl"
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;
}
float3 GetScale(float3 PivotWS)
{
return float3
(
length(TransformObjectToWorld(float3(1, 0, 0)) - PivotWS),
length(TransformObjectToWorld(float3(0, 1, 0)) - PivotWS),
length(TransformObjectToWorld(float3(0, 0, 1)) - PivotWS)
);
}
float GetShadow(float3 PositionWS)
{
float4 shadowCoord = TransformWorldToShadowCoord(PositionWS);
Light mainLight = GetMainLight(shadowCoord);
float shadow = 1 - mainLight.shadowAttenuation;
#if defined(_ADDITIONAL_LIGHTS)
uint lightsCount = GetAdditionalLightsCount();
[loop]
for (uint i = 0; i < lightsCount; i++)
{
Light light = GetAdditionalLight(i, PositionWS);
shadow = max(shadow, 1 - light.shadowAttenuation);
}
#endif
return saturate(shadow);
}
float4 SampleBombedTexture
(
UnityTexture2D Tex,
float2 UV
)
{
const float cellBlend = 4;
float2 cell = floor(UV);
float2 local = frac(UV);
float4 result = 0;
float weightSum = 0;
[unroll]
for (int y = 0; y < 2; y++)
{
[unroll]
for (int x = 0; x < 2; x++)
{
float2 currentCell = cell + float2(x, y);
float2 randomOffset = (Hash2D(currentCell) - .5) * .35;
float randomAngle = Hash1From2D(currentCell) * TWO_PI;
float2 center = float2(x, y) + randomOffset;
float2 delta = local - center;
float weight =
pow(saturate(1 - abs(delta.x)), cellBlend) *
pow(saturate(1 - abs(delta.y)), cellBlend);
float2 sampleUV = UV + randomOffset;
sampleUV = RotateUV
(
sampleUV,
currentCell + .5,
randomAngle
);
result += Tex.tex.Sample
(
Tex.samplerstate,
sampleUV
) * weight;
weightSum += weight;
}
}
return result / max(weightSum, 1e-5);
}
struct ProjectionData
{
float2 uv[7];
float mask[7];
};
ProjectionData GetProjections
(
float3 PositionOS,
float3 NormalOS,
float Blend
)
{
ProjectionData data;
float3 normal = normalize(NormalOS);
float3 projectionNormals[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 sharpness = lerp(2, 32, saturate(Blend));
float maskSum = 0;
[unroll]
for (int i = 0; i < 7; i++)
{
float3 n = projectionNormals[i];
float d = abs(dot(normal, n));
data.mask[i] = pow(saturate(d), sharpness);
maskSum += data.mask[i];
float3 up = abs(n.y) < .999
? float3(0, 1, 0)
: float3(1, 0, 0);
float3 tangent = normalize(cross(up, n));
float3 bitangent = normalize(cross(n, tangent));
data.uv[i] = float2
(
dot(PositionOS, tangent),
dot(PositionOS, bitangent)
);
}
maskSum = max(maskSum, 1e-5);
[unroll]
for (int i = 0; i < 7; i++)
data.mask[i] /= maskSum;
return data;
}
void EnkiBillal_float
(
float4 Color,
UnityTexture2D DetailTex,
float2 ScreenUV,
float3 PositionWS,
float3 NormalWS,
float ProjectionsBlend,
out float3 Output
)
{
// Common
float depth = length(PositionWS - _WorldSpaceCameraPos.xyz);
float3 pivotWS = TransformObjectToWorld(float3(0, 0, 0));
float3 scale = GetScale(pivotWS);
float3 positionOS = TransformWorldToObject(PositionWS) * scale;
float3 normalOS = normalize(TransformWorldToObjectDir(NormalWS));
//float ao = GetScreenSpaceAmbientOcclusion(ScreenUV).directAmbientOcclusion;
// Shadow
float shadow = GetShadow(PositionWS);
float shadowAtten = Remap(1, 0, .6, 1, shadow);
// Detail
float4 detail = 0;
ProjectionData projections = GetProjections
(
positionOS,
normalOS,
ProjectionsBlend
);
float totalMask = 0;
[unroll]
for (int i = 0; i < 7; i++)
{
float mask = projections.mask[i];
detail += SampleBombedTexture
(
DetailTex,
projections.uv[i]
) * mask;
totalMask += mask;
}
detail /= max(totalMask, 1e-5);
// Output
Output = Color.rgb;
Output = lerp(Color.rgb, Color.rgb * detail.rgb, detail.a);
//Output *= shadowAtten;
}
#endif