opti : shaders rework test
This commit is contained in:
@@ -1,11 +1,89 @@
|
||||
#ifndef STRIPES_INCLUDED
|
||||
#define STRIPES_INCLUDED
|
||||
|
||||
// Returns a value in [0, 1)
|
||||
/*
|
||||
STRIPES - MEDIUM VERSION
|
||||
|
||||
Goal:
|
||||
Reduce the GPU cost of the procedural stripe pattern.
|
||||
|
||||
Changes from the original version:
|
||||
- Removed the dynamic loop over the full stripe count.
|
||||
Original behavior: evaluate every stripe from 0 to Count.
|
||||
New behavior: evaluate only 6 nearby stripe candidates.
|
||||
- Clamped Count to 32 to prevent expensive high-count cases.
|
||||
- Kept Van der Corput distribution to preserve stable pseudo-random variation.
|
||||
- Kept the two distortion paths to preserve part of the organic look.
|
||||
- Visual result is an approximation of the original, but much cheaper.
|
||||
*/
|
||||
|
||||
float VanDerCorput(uint index)
|
||||
{
|
||||
// Reverse bits of the integer and scale to [0,1]
|
||||
return (float) reversebits(index) * 2.3283064365386963e-10;
|
||||
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);
|
||||
|
||||
/*
|
||||
Same progressive reveal logic as the original shader.
|
||||
|
||||
Original:
|
||||
saturate(density * stripeCount - vdc * stripeCount)
|
||||
|
||||
Equivalent simplified form:
|
||||
saturate((density - vdc) * stripeCount)
|
||||
*/
|
||||
float localProgress = saturate((density - vdc) * stripeCount);
|
||||
|
||||
if (localProgress <= 0.0001)
|
||||
return 0.0;
|
||||
|
||||
/*
|
||||
Keep the original two distortion paths.
|
||||
Each stripe chooses one path based on its pseudo-random value.
|
||||
*/
|
||||
float wrappedX = vdc >= 0.5 ? wrappedXB : wrappedXA;
|
||||
|
||||
/*
|
||||
Keep the original thickness variation.
|
||||
This prevents the stripes from looking too uniform.
|
||||
*/
|
||||
float thickness = vdc < 0.3 ? 1.0 : (vdc < 0.6 ? 1.8 : 2.6);
|
||||
thickness *= saturate(thicknessInput);
|
||||
|
||||
float stripeCenterX = ((float)index + 0.5) / (float)stripeCount;
|
||||
|
||||
float stripDistanceX = abs(wrappedX - stripeCenterX);
|
||||
stripDistanceX = min(stripDistanceX, 1.0 - stripDistanceX);
|
||||
|
||||
float stepX = (1.0 / (float)stripeCount) * localProgress * thickness * 0.5;
|
||||
float stepY = localProgress * 0.5 - 0.01;
|
||||
|
||||
/*
|
||||
Soft edges are kept from the original shader.
|
||||
If more performance is needed, these smoothstep calls can be replaced
|
||||
with step calls, but the result will look harsher.
|
||||
*/
|
||||
float widthMask = 1.0 - smoothstep(stepX - 0.01, stepX, stripDistanceX);
|
||||
float heightMask = 1.0 - smoothstep(stepY - 0.05, stepY, stripDistanceY);
|
||||
|
||||
return widthMask * heightMask;
|
||||
}
|
||||
|
||||
void Stripes_float(
|
||||
@@ -21,48 +99,78 @@ void Stripes_float(
|
||||
{
|
||||
float density = saturate(Density);
|
||||
float offset = frac(Offset);
|
||||
float distortionAmplitude = DistortionAmplitude * .1;
|
||||
uint stripeCount = max((uint) round(Count), 1u);
|
||||
|
||||
/*
|
||||
Intentional clamp.
|
||||
Above 32 stripes, the cost increases while the visual gain is usually limited,
|
||||
especially on distant objects or in a strongly stylized render.
|
||||
*/
|
||||
uint stripeCount = max((uint)round(Count), 1u);
|
||||
stripeCount = min(stripeCount, 32u);
|
||||
|
||||
float distortionAmplitude = DistortionAmplitude * 0.1;
|
||||
|
||||
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);
|
||||
uv.x = frac(uv.x + offset);
|
||||
|
||||
float stripeMax = 0;
|
||||
|
||||
for (uint i = 0u; i < stripeCount; i++)
|
||||
/*
|
||||
The two distortion paths are computed once and reused for all nearby candidates.
|
||||
*/
|
||||
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;
|
||||
|
||||
/*
|
||||
Find the nearest stripe indices for both distortion paths.
|
||||
Original shader tested every stripe.
|
||||
Medium version tests only base - 1, base, base + 1 for A and B.
|
||||
*/
|
||||
int baseA = (int)floor(wrappedXA * sc);
|
||||
int baseB = (int)floor(wrappedXB * sc);
|
||||
|
||||
float stripeMax = 0.0;
|
||||
|
||||
[unroll]
|
||||
for (int k = -1; k <= 1; k++)
|
||||
{
|
||||
float vdc = VanDerCorput(i);
|
||||
bool usesSecondDistortion = vdc >= .5;
|
||||
uint idxA = (uint)WrapIndex(baseA + k, sc);
|
||||
uint idxB = (uint)WrapIndex(baseB + k, sc);
|
||||
|
||||
float thickness = vdc < .3 ? 1 : (vdc < .6 ? 1.8 : 2.6);
|
||||
thickness *= saturate(Thickness);
|
||||
|
||||
float wrappedX = usesSecondDistortion ? uvB.x : uvA.x;
|
||||
stripeMax = max(
|
||||
stripeMax,
|
||||
EvalStripeCandidate(
|
||||
idxA,
|
||||
stripeCount,
|
||||
wrappedXA,
|
||||
wrappedXB,
|
||||
stripDistanceY,
|
||||
density,
|
||||
Thickness
|
||||
)
|
||||
);
|
||||
|
||||
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);
|
||||
stripeMax = max(
|
||||
stripeMax,
|
||||
EvalStripeCandidate(
|
||||
idxB,
|
||||
stripeCount,
|
||||
wrappedXA,
|
||||
wrappedXB,
|
||||
stripDistanceY,
|
||||
density,
|
||||
Thickness
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Stripes = stripeMax;
|
||||
|
||||
Reference in New Issue
Block a user