Files
bluflame/hgplus/obliterator/gpu/b288.hlsl
2026-04-18 22:31:51 +02:00

184 lines
5.4 KiB
HLSL

// Shader selector
static const uint P = DEBUG_SHADER_ID;
// Random seed (global)
static uint rndSeed = 0, activeScene = 0;
// Constants
static const float PI = 3.14159265, PHI = sqrt(5)*0.5 + 0.5, INFINITY = 1000, pixelRadius = 0.001;
//[
cbuffer _1 : register(b0) {//]
float X, Y, Z, W;
//float3 viewPosition;
//float3 viewDirection;
//float3 viewUp;
//float dummy0, dummy1, dummy2;
//float dummy5;
//float dummy3;
//float dummy4;
//[
}//]
SamplerState sampler0 : register(s0);
Texture2D tex[8] : register(t0);
RWTexture2D<float4> out0 : register(u0);
RWBuffer<uint4> mcp0 : register(u1);
uint hash(uint x) {
x += x << 10, x ^= x >> 6, x += x << 3, x ^= x >> 11, x += x << 15;
return x;
}
float rnd() {
return asfloat((rndSeed = hash(rndSeed) & 0x007fffff) | 0x3f800000) - 1;
}
float smoothstepQuintic(float edge0, float edge1, float x) {
x = saturate((x - edge0) / (edge1 - edge0));
return x*x*x*(x*(x * 6 - 15) + 10);
}
//---
// Sphere tracing
//---
float fBoxNonEuclidean(float3 p, float3 b) {
float3 d = abs(p) - b;
return max(max(d.x, d.y), d.z);
}
float fLasBlob(float3 p) {
p = abs(p);
if (p.x < max(p.y, p.z)) p = p.yzx;
if (p.x < max(p.y, p.z)) p = p.yzx;
float b = max(max(max(
dot(p, normalize(float3(1, 1, 1))),
dot(p.xz, normalize(float2(PHI + 1, 1)))),
dot(p.yx, normalize(float2(1, PHI)))),
dot(p.xz, normalize(float2(1, PHI))));
float l = length(p);
return l - 1.6125 + 0.25 * (smoothstepQuintic(0.0, 0.343, sin(acos(b / l - 0.0075))));
}
float F(float3 p, int evaluateMaterial) {
return min(fLasBlob(p), -fBoxNonEuclidean(p, float3(10, 10, 10)));
}
float fMaterial(float3 p) {
return F(p, 1);
}
float f(float3 p) {
return F(p, 0);
}
float3 gradient(float3 p, float e) {
return float3(f(p + float3(e, 0, 0)), f(p + float3(0, e, 0)), f(p + float3(0, 0, e))) - float3(f(p - float3(e, 0, 0)), f(p - float3(0, e, 0)), f(p - float3(0, 0, e)));
}
float2 sphereTrace(float3 o, float3 d) {
float t = 0.0001, tmax = 30, functionSign = f(o) < 0 ? -1 : +1;
float2 intersection = { 0, INFINITY };
for (int i = 0; i < 80; ++i) {
float signedRadius = functionSign * f(d*t + o);
float radius = abs(signedRadius);
float screenSpaceError = radius / t;
if (screenSpaceError < intersection.y)
intersection = float2(t, screenSpaceError);
if (screenSpaceError < pixelRadius || t > tmax)
break;
t += signedRadius;
}
return float2(intersection.x, functionSign * max(intersection.x * intersection.y, 0.004));
}
//---
// MCP Helper
//---
void addMcpDispatch(int divisor, int enable) {
mcp0[++rndSeed] = int4((80 + divisor - 1) / divisor, (45 + divisor - 1) / divisor, 1, 1)*enable;
}
// Entry point "_0"
[numthreads(16, 16, 1)]
void _0(uint3 id:SV_DispatchThreadID){
float2 resolution, sourceResolution;
out0.GetDimensions(resolution.x, resolution.y);
tex[0].GetDimensions(sourceResolution.x, sourceResolution.y);
//float mipLevel = log2(sourceResolution.x / resolution.x);
float2 tc = (id.xy + 0.5) / resolution;
float2 sc = (tc*2 - 1) * float2(resolution.x / resolution.y, -1);
float3 w = -float3(0, 0, -1);
float3 v = float3(0, 1, 0);
float3 u = cross(v, w);
float3 o = float3(0, 0, 3);
float3 d = normalize(mul(transpose(float3x3(u, v, w)), float3(sc / 2, -0.5 / tan((.5*3.1415)*60 / 180.))));
float4 result = 1;
if (P == 0) {
// MCP
addMcpDispatch(1, activeScene == 0 ? 1 : 0); // Scene 0
addMcpDispatch(1, activeScene == 1 ? 1 : 0); // Scene 1
addMcpDispatch(1, activeScene == 2 ? 1 : 0); // Scene 2
addMcpDispatch(1, activeScene == 3 ? 1 : 0); // Scene 3
addMcpDispatch(1, activeScene == 4 ? 1 : 0); // Scene 4
addMcpDispatch(4, 1); // Streaks
addMcpDispatch(1, 1); // Blur H
addMcpDispatch(1, 1); // Blur V
addMcpDispatch(8, 1); // Blur H
addMcpDispatch(8, 1); // Blur V
addMcpDispatch(32, 1); // Blur H
addMcpDispatch(32, 1); // Blur V
addMcpDispatch(1, 1); // Merge
return;
} else if (P > 0 && P < 4) {
// Blur V (1) & Blur H (2) & Steaks (3)
float radius = 160, sigma = radius / 3.5;
float twoSigmaSquared = 2 * sigma * sigma;
float2 d = (P > 1 ? float2(1, 0) : float2(0, 1)) / resolution;
for (float i = -radius; i <= radius; ++i) {
result += tex[0].SampleLevel(sampler0, i*d + tc, 0) *
(P > 2 ? 1.5 * (radius - abs(i)) * (radius - abs(i)) / (radius * radius * radius) : exp(-i*i / twoSigmaSquared) / sqrt(twoSigmaSquared * PI));
}
} else if (P == 4) {
// Merge
rndSeed = id.y;
result = tex[0].SampleLevel(sampler0, tc, 0) +
tex[1].SampleLevel(sampler0, tc, 0) * 0.025 +
tex[2].SampleLevel(sampler0, tc, 0) * 0.025 +
tex[3].SampleLevel(sampler0, tc, 0) * 0.025 +
tex[4].SampleLevel(sampler0, tc, 0) * (lerp(1, rnd(), 0.125)) * 0.25;
// Tonemapping
result = max(0, result*0.5);
result = max(0, result * (result*1.28713 + 0.153229) / (result*(result + 3.33333) + 0.4));
//result.xyz = liftGammaGain(result.xyz, float3(0, 0, 0), float3(1, 1, 1), float3(1, 1, 1));
//color = saturation(color, 1.5);
result = pow(result, 1 / 2.2);
//result = float4(result.xyz, dot(result.xyz, float3(0.299, 0.587, 0.114)));
} else if (P == 5) {
result = frac(X) * float4(1.0, 0.111111, 0.0, 0.0) + 0.5;
} else if (P == 6) {
o.z += sin(X);
float2 st = sphereTrace(o, d);
result.xyz = normalize(gradient(d*st.x + o, 0.1))*0.5 + 0.5;
if (isnan(dot(result.xyz, result.xyz)))
result.xyz = float3(1000, 0, 0);
} else if (P == 7) {
} else if (P == 8) {
} else if (P == 9) {
}
out0[id.xy] = result;
}