Files
Ipseity-Demo/Assets/_Content/Shaders/EnkiBilal/Include/Stripes.hlsl
T
2026-07-09 12:27:20 +02:00

200 lines
4.9 KiB
HLSL

#ifndef STRIPES_INCLUDED
#define STRIPES_INCLUDED
/*
STRIPES - AGGRESSIVE / HEAVY HATCH VERSION
Goal:
Make the hatch pattern much stronger, darker and more visible.
Changes from the Medium version:
- Stronger width multiplier.
- Stronger final mask shaping.
- Weak strokes are boosted aggressively.
- Output saturates faster, producing a harsher graphic look.
*/
float VanDerCorput(uint index)
{
return (float)reversebits(index) * 2.3283064365386963e-10;
}
int WrapIndex(int x, int count)
{
int r = x % count;
return r < 0 ? r + count : r;
}
float EvalStripeCandidate(
uint index,
uint stripeCount,
float wrappedXA,
float wrappedXB,
float stripDistanceY,
float density,
float thicknessInput
)
{
float vdc = VanDerCorput(index);
/*
Stronger reveal than the Medium version.
This makes stripes appear earlier and more densely.
*/
float localProgress = saturate((density - vdc) * stripeCount * 1.35);
if (localProgress <= 0.0001)
return 0.0;
float wrappedX = vdc >= 0.5 ? wrappedXB : wrappedXA;
/*
Original random thickness variation, but heavily boosted.
*/
float thickness = vdc < 0.3 ? 1.0 : (vdc < 0.6 ? 1.8 : 2.6);
/*
Aggressive thickness boost.
Raise this if you want even fatter strokes.
*/
const float HATCH_WIDTH_BOOST = 2.4;
thickness *= saturate(thicknessInput) * HATCH_WIDTH_BOOST;
float stripeCenterX = ((float)index + 0.5) / (float)stripeCount;
float stripDistanceX = abs(wrappedX - stripeCenterX);
stripDistanceX = min(stripDistanceX, 1.0 - stripDistanceX);
/*
Wider X footprint = thicker hatch lines.
*/
float stepX = (1.0 / (float)stripeCount) * localProgress * thickness * 0.5;
/*
Taller Y footprint = hatch bands cover more vertical space.
*/
float stepY = localProgress * 0.65;
/*
Softer but larger edge zone.
This makes strokes bleed more into nearby pixels.
*/
float softEdgeX = 0.025;
float softEdgeY = 0.085;
float widthMask = 1.0 - smoothstep(stepX - softEdgeX, stepX, stripDistanceX);
float heightMask = 1.0 - smoothstep(stepY - softEdgeY, stepY, stripDistanceY);
return widthMask * heightMask;
}
void Stripes_float(
float2 UV,
float Density,
float Count,
float Thickness,
float Offset,
float DistortionAmplitude,
float DistortionFrequency,
out float Stripes
)
{
/*
Aggressive density boost.
Even if the material density is moderate, the shader pushes it harder.
*/
float density = saturate(Density * 1.45);
float offset = frac(Offset);
/*
Keep the optimized candidate-based approach.
Count is clamped to avoid bringing back the old expensive behavior.
*/
uint stripeCount = max((uint)round(Count), 1u);
stripeCount = min(stripeCount, 32u);
/*
Stronger distortion for a more nervous hand-drawn look.
*/
float distortionAmplitude = DistortionAmplitude * 0.16;
float2 uv = UV;
uv.x = frac(uv.x + offset);
float wrappedXA = frac(
uv.x + cos((uv.y + offset) * sin(uv.x) * DistortionFrequency + offset * 7.8)
* distortionAmplitude
);
float wrappedXB = frac(
uv.x + sin((uv.y + offset) * cos(uv.x) * DistortionFrequency + offset * 5.3)
* distortionAmplitude
);
float stripDistanceY = abs(saturate(uv.y) - 0.5);
int sc = (int)stripeCount;
int baseA = (int)floor(wrappedXA * sc);
int baseB = (int)floor(wrappedXB * sc);
float stripeMax = 0.0;
/*
Still only 6 candidates total:
- 3 around distortion A
- 3 around distortion B
So this remains much cheaper than the original full Count loop.
*/
[unroll]
for (int k = -1; k <= 1; k++)
{
uint idxA = (uint)WrapIndex(baseA + k, sc);
uint idxB = (uint)WrapIndex(baseB + k, sc);
stripeMax = max(
stripeMax,
EvalStripeCandidate(
idxA,
stripeCount,
wrappedXA,
wrappedXB,
stripDistanceY,
density,
Thickness
)
);
stripeMax = max(
stripeMax,
EvalStripeCandidate(
idxB,
stripeCount,
wrappedXA,
wrappedXB,
stripDistanceY,
density,
Thickness
)
);
}
/*
Brutal final shaping.
- smoothstep makes weak strokes become visible sooner.
- pow with low exponent pulls mid/low values upward.
- final multiplier forces a strong black graphic result downstream.
*/
stripeMax = smoothstep(0.02, 0.28, stripeMax);
const float HATCH_POWER = 0.38;
const float HATCH_FINAL_BOOST = 2.8;
Stripes = saturate(pow(stripeMax, HATCH_POWER) * HATCH_FINAL_BOOST);
}
#endif