feat: House of leaves, details added to wall shader
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
#ifndef ENKI_BILAL_INCLUDED
|
||||
#define ENKI_BILAL_INCLUDED
|
||||
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
|
||||
#include "Assets/_Content/Shaders/Include/Noises.hlsl"
|
||||
#include "Assets/_Content/Shaders/Include/Details.hlsl"
|
||||
#include "Assets/_Content/Shaders/Include/Utilities.hlsl"
|
||||
//#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/AmbientOcclusion.hlsl"
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void EnkiBillal_float
|
||||
(
|
||||
float4 Color,
|
||||
UnityTexture2D DetailTexA,
|
||||
UnityTexture2D DetailTexB,
|
||||
float2 ScreenUV,
|
||||
float3 PositionWS,
|
||||
float3 NormalWS,
|
||||
float ProjectionsBlend,
|
||||
float DetailIntensityA,
|
||||
float DetailIntensityB,
|
||||
float DetailSizeA,
|
||||
float DetailSizeB,
|
||||
uint FogUse,
|
||||
float4 FogColor,
|
||||
float FogMin,
|
||||
float FogMax,
|
||||
out float3 Output,
|
||||
out float Alpha
|
||||
)
|
||||
{
|
||||
// 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 detailA = SampleProjectedDetailLOD
|
||||
(
|
||||
DetailTexA,
|
||||
positionOS,
|
||||
normalOS,
|
||||
ProjectionsBlend,
|
||||
DetailSizeA,
|
||||
depth
|
||||
|
||||
);
|
||||
|
||||
float4 detailB = SampleProjectedDetailLOD
|
||||
(
|
||||
DetailTexB,
|
||||
positionOS,
|
||||
normalOS,
|
||||
ProjectionsBlend,
|
||||
DetailSizeB,
|
||||
depth
|
||||
|
||||
);
|
||||
|
||||
float detailMaskA = smoothstep(0, .8, detailA.a);
|
||||
float detailMaskB = smoothstep(0, .8, detailB.a);
|
||||
|
||||
// Fog
|
||||
|
||||
// Output
|
||||
|
||||
Output = Color.rgb;
|
||||
Output = lerp(Output.rgb, detailA.rgb, detailMaskA * DetailIntensityA);
|
||||
Output = lerp(Output.rgb, detailB.rgb, detailMaskB * DetailIntensityB);
|
||||
|
||||
if (FogUse)
|
||||
{
|
||||
Output = lerp(Output.rgb, FogColor.rgb, smoothstep(FogMin, FogMax, depth) * FogColor.a);
|
||||
}
|
||||
|
||||
Alpha = Color.a;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 411dec433a23f2c4da8f56e83e7230da
|
||||
ShaderIncludeImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,123 @@
|
||||
#ifndef MASK_INCLUDED
|
||||
#define MASK_INCLUDED
|
||||
|
||||
float ProjectionMask(
|
||||
float3 PositionWS,
|
||||
float3 CamPositionWS,
|
||||
float3 RectPositionWS,
|
||||
float3 RectNormalWS,
|
||||
float3 RectUpWS,
|
||||
float2 RectSize,
|
||||
float Oval)
|
||||
{
|
||||
// Build the rectangle local frame
|
||||
float3 N = normalize(RectNormalWS);
|
||||
float3 U = normalize(RectUpWS);
|
||||
float3 R = normalize(cross(N, U)); // Right axis
|
||||
U = normalize(cross(R, N)); // Recompute Up orthogonally in case RectUpWS is not perfectly perpendicular to RectNormalWS
|
||||
|
||||
// Ray from camera toward the fragment
|
||||
float3 rayDir = normalize(PositionWS - CamPositionWS);
|
||||
|
||||
// Ray-plane intersection
|
||||
// Plane equation: dot(P - RectPositionWS, N) = 0
|
||||
float denom = dot(rayDir, N);
|
||||
|
||||
// Ray is parallel to the plane or facing away — no hit
|
||||
if (abs(denom) < 1e-6)
|
||||
return 0;
|
||||
|
||||
float t = dot(RectPositionWS - CamPositionWS, N) / denom;
|
||||
|
||||
// Intersection must be in front of the camera (t > 0)
|
||||
// and not beyond the fragment (t <= distance from camera to fragment)
|
||||
float tFrag = dot(PositionWS - CamPositionWS, rayDir);
|
||||
if (t < 0.0 || t > tFrag + 1e-4)
|
||||
return 0;
|
||||
|
||||
// Compute the hit point on the plane
|
||||
float3 hitPoint = CamPositionWS + rayDir * t;
|
||||
|
||||
// Project hit point into the rectangle local space
|
||||
float3 localVec = hitPoint - RectPositionWS;
|
||||
float localU = dot(localVec, R); // horizontal axis
|
||||
float localV = dot(localVec, U); // vertical axis
|
||||
|
||||
float halfW = RectSize.x * 0.5;
|
||||
float halfH = RectSize.y * 0.5;
|
||||
|
||||
// Corner radius: 0 = rectangle, min(halfW, halfH) = oval
|
||||
float radius = saturate(Oval) * min(halfW, halfH);
|
||||
|
||||
// Rounded rectangle SDF
|
||||
float2 uv = float2(localU, localV);
|
||||
float2 ext = float2(halfW, halfH);
|
||||
float2 q = abs(uv) - ext + radius;
|
||||
float sdf = length(max(q, 0.0)) - radius;
|
||||
|
||||
return sdf <= 0.0 ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
float SampleProjectionMask(float3 PositionWS, float4x4 M)
|
||||
{
|
||||
if (M[0].w == 0)
|
||||
return 0;
|
||||
|
||||
return ProjectionMask(
|
||||
PositionWS,
|
||||
M[0].xyz, // CamPositionWS
|
||||
M[1].xyz, // RectPositionWS
|
||||
M[3].xyz, // RectNormalWS
|
||||
M[2].xyz, // RectUpWS
|
||||
float2(M[2].w, M[3].w), // RectSize
|
||||
M[1].w // Shape
|
||||
);
|
||||
}
|
||||
|
||||
void Mask_float
|
||||
(
|
||||
float3 PositionWS,
|
||||
float MaskID,
|
||||
float4x4 Mask0,
|
||||
float4x4 Mask1,
|
||||
float4x4 Mask2,
|
||||
out float Alpha
|
||||
)
|
||||
{
|
||||
Alpha = 1;
|
||||
|
||||
if (Mask0[0].w == 1 && Mask1[0].w == 1 && Mask2[0].w == 1)
|
||||
{
|
||||
float mask = SampleProjectionMask(PositionWS, Mask0);
|
||||
mask += SampleProjectionMask(PositionWS, Mask1);
|
||||
mask += SampleProjectionMask(PositionWS, Mask2);
|
||||
mask = saturate(mask);
|
||||
|
||||
Alpha = (MaskID <= 1) ? 1 - mask : mask;
|
||||
}
|
||||
else if (MaskID == 0)
|
||||
{
|
||||
Alpha = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
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, Mask2)
|
||||
);
|
||||
|
||||
Alpha = (MaskID == 1) ? 1 - mask : mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
Alpha = (MaskID == 1) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f64e213049952b44ac4bed6f62cafda
|
||||
ShaderIncludeImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef STRIPES_INCLUDED
|
||||
#define STRIPES_INCLUDED
|
||||
|
||||
// Returns a value in [0, 1)
|
||||
float VanDerCorput(uint index)
|
||||
{
|
||||
// Reverse bits of the integer and scale to [0,1]
|
||||
return (float) reversebits(index) * 2.3283064365386963e-10;
|
||||
}
|
||||
|
||||
void Stripes_float(
|
||||
float2 UV,
|
||||
float Density,
|
||||
float Count,
|
||||
float Thickness,
|
||||
float Offset,
|
||||
float DistortionAmplitude,
|
||||
float DistortionFrequency,
|
||||
out float Stripes
|
||||
)
|
||||
{
|
||||
float density = saturate(Density);
|
||||
float offset = frac(Offset);
|
||||
float distortionAmplitude = DistortionAmplitude * .1;
|
||||
uint stripeCount = max((uint) round(Count), 1u);
|
||||
|
||||
float2 uv = UV;
|
||||
uv.x += offset;
|
||||
|
||||
float2 uvA = uv;
|
||||
float2 uvB = uv;
|
||||
uvA.x = frac(uvA.x + cos((uv.y + offset) * sin(uv.x) * DistortionFrequency + offset * 7.8) * distortionAmplitude);
|
||||
uvB.x = frac(uvB.x + sin((uv.y + offset) * cos(uv.x) * DistortionFrequency + offset * 5.3) * distortionAmplitude);
|
||||
|
||||
float stripDistanceY = abs(saturate(uv.y) - .5);
|
||||
|
||||
float stripeMax = 0;
|
||||
|
||||
for (uint i = 0u; i < stripeCount; i++)
|
||||
{
|
||||
float vdc = VanDerCorput(i);
|
||||
bool usesSecondDistortion = vdc >= .5;
|
||||
|
||||
float thickness = vdc < .3 ? 1 : (vdc < .6 ? 1.8 : 2.6);
|
||||
thickness *= saturate(Thickness);
|
||||
|
||||
float wrappedX = usesSecondDistortion ? uvB.x : uvA.x;
|
||||
|
||||
float localProgress = saturate(density * stripeCount - vdc * stripeCount);
|
||||
|
||||
float stripeCenterX = frac((i + .5) / stripeCount);
|
||||
float stripDistanceX = abs(wrappedX - stripeCenterX);
|
||||
stripDistanceX = min(stripDistanceX, 1.0 - stripDistanceX);
|
||||
|
||||
float stepX = (1. / stripeCount) * localProgress * thickness * .5;
|
||||
float stepY = localProgress * .5 - .01;
|
||||
|
||||
float softEdgeX = .01;
|
||||
float softEdgeY = .05;
|
||||
|
||||
float widthMask = 1 - smoothstep(stepX - softEdgeX, stepX, stripDistanceX);
|
||||
float heightMask = 1 - smoothstep(stepY - softEdgeY, stepY, stripDistanceY);
|
||||
|
||||
float stripeMask = widthMask * heightMask;
|
||||
stripeMax = max(stripeMax, stripeMask);
|
||||
}
|
||||
|
||||
Stripes = stripeMax;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e32323363e459a4fa93de6067070a10
|
||||
ShaderIncludeImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user