// 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 out0 : register(u0); RWBuffer 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; }