184 lines
5.4 KiB
HLSL
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;
|
|
} |