763 lines
20 KiB
HLSL
763 lines
20 KiB
HLSL
#define PI 3.14159265
|
|
#define T [numthreads(16, 16, 1)]
|
|
|
|
RWTexture2D<float4> out0:register(u0);
|
|
RWTexture2D<float4> out1:register(u1);
|
|
|
|
Texture2D tex0: register(t0);
|
|
Texture2D tex1: register(t1);
|
|
Texture2D tex2: register(t2);
|
|
Texture2D tex3: register(t3);
|
|
|
|
SamplerState sampler0 : register(s0);
|
|
|
|
static uint rndSeed = 0;
|
|
|
|
uint hash(uint x) {
|
|
return x += x << 10, x ^= x >> 6, x += x << 3, x ^= x >> 11, x += x << 15, x;
|
|
}
|
|
|
|
float rnd() {
|
|
return asfloat((rndSeed = hash(rndSeed) & 0x007fffff) | 0x3f800000) - 1;
|
|
}
|
|
|
|
float srnd() {
|
|
return asfloat((rndSeed = hash(rndSeed) & 0x007fffff) | 0x40000000) - 3;
|
|
}
|
|
|
|
float rnd(uint s) {
|
|
return asfloat((s & 0x007fffff) | 0x3f800000) - 1;
|
|
}
|
|
|
|
float srnd(uint s) {
|
|
return asfloat((s & 0x007fffff) | 0x40000000) - 3;
|
|
}
|
|
|
|
float expf(float x) {
|
|
return asfloat(int(12102203 * x + 1064866805));
|
|
}
|
|
|
|
float2 mod(float2 x, float y) {
|
|
return x - y * floor(x / y);
|
|
}
|
|
|
|
float pulse(float center, float width, float x) {
|
|
float t = abs(x - center);
|
|
if (t > width) return 0;
|
|
t /= width;
|
|
return 1 - t*t*(3 - 2 * t);
|
|
}
|
|
|
|
float fhex(float2 p, float s) {
|
|
return p = abs(p), max(p.x + p.y*0.57735, p.y*1.1547) - s;
|
|
}
|
|
|
|
//---
|
|
// Bokeh
|
|
//---
|
|
static const float bkRadius = 32;
|
|
static const float bkFocus = 1.0;
|
|
static const float bkAperature = 8;
|
|
static const float bkBorderStrength = 0;
|
|
|
|
float bkCircleOfConfusion(float depth) {
|
|
return clamp(bkAperature * abs(depth - bkFocus) / bkFocus, 1, bkRadius);
|
|
}
|
|
|
|
T void csBokehPreprocess(int3 id:SV_DispatchThreadID) {
|
|
float2 resolution;
|
|
out0.GetDimensions(resolution.x, resolution.y);
|
|
|
|
float2 tc = (id.xy) / resolution;
|
|
|
|
// Compute and premultiply CoC
|
|
float4 s = tex0.SampleLevel(sampler0, tc, 0);
|
|
float coc = bkCircleOfConfusion(s.w);
|
|
|
|
// Alternative CoC computations
|
|
//float coc = bkCircleOfConfusion(tex0.SampleLevel(sampler0, tc, 2).w);
|
|
|
|
//float4 depth = tex0.GatherAlpha(sampler0, tc);
|
|
//float coc = (
|
|
// bkCircleOfConfusion(depth.x) +
|
|
// bkCircleOfConfusion(depth.y) +
|
|
// bkCircleOfConfusion(depth.z) +
|
|
// bkCircleOfConfusion(depth.w)
|
|
// ) * 0.25;
|
|
|
|
out0[id.xy] = float4(s.xyz, 1) * coc;
|
|
}
|
|
|
|
float4 bkSample(float2 tc, float2 d, Texture2D tex) {
|
|
// Fetch reference CoC
|
|
float referenceCoc = tex.SampleLevel(sampler0, tc, 0).w;
|
|
|
|
float sigma = 0;
|
|
float4 a = 0;
|
|
for (float i = 0.5; i < bkRadius; ++i) {
|
|
// Fetch sample float4(RGB,1)*coc
|
|
float4 s = tex.SampleLevel(sampler0, d * i + tc, 0);
|
|
|
|
// Compute and accumulate weighting factor
|
|
float weight = saturate(referenceCoc - i) * (saturate(s.w - i) + bkBorderStrength * step(bkRadius,i+1));
|
|
sigma += weight;
|
|
|
|
// Accumulate weighted contribution
|
|
a += s * weight;
|
|
}
|
|
|
|
return a / sigma;
|
|
}
|
|
|
|
T void csBokehFirst(int3 id:SV_DispatchThreadID) {
|
|
float2 resolution;
|
|
out0.GetDimensions(resolution.x, resolution.y);
|
|
|
|
float2 tc = (id.xy + 0.5) / resolution;
|
|
|
|
float4 sA = bkSample(tc, float2( 0, 1) / resolution, tex0);
|
|
float4 sB = bkSample(tc, float2(-.8660254, -.5) / resolution, tex0);
|
|
|
|
out0[id.xy] = sA;
|
|
out1[id.xy] = (sA + sB) * 0.5;
|
|
}
|
|
|
|
T void csBokehSecond(int3 id:SV_DispatchThreadID) {
|
|
float2 resolution;
|
|
out0.GetDimensions(resolution.x, resolution.y);
|
|
|
|
float2 tc = (id.xy + 0.5) / resolution;
|
|
|
|
float4 sA = bkSample(tc, float2(-.8660254, -.5) / resolution, tex0);
|
|
float4 sB = bkSample(tc, float2(+.8660254, -.5) / resolution, tex1);
|
|
|
|
out0[id.xy] = (sA += sB * 2) / sA.w;
|
|
}
|
|
|
|
T void csScatterBokeh(int3 id:SV_DispatchThreadID) {
|
|
|
|
}
|
|
|
|
//---
|
|
// Radial and circumferential blur
|
|
//---
|
|
static const float rcfMipmapFactor = 1.5;
|
|
static const float rcfStepFactor = 5;
|
|
static const float rcfStrength = 100;
|
|
static const float rcfCircumFerentialStrength = 1.0;
|
|
static const float rcfRadius = 5;
|
|
static const float2 rcfCenter = {0.5, 0.5};
|
|
|
|
float rcfRadialFalloff(float radius, float amount) {
|
|
return radius * (1 + amount*radius*0.01);
|
|
}
|
|
|
|
T void csRadialCircumferentialBlur(int3 id:SV_DispatchThreadID) {
|
|
float2 resolution;
|
|
out0.GetDimensions(resolution.x, resolution.y);
|
|
|
|
float2 tc = (id.xy + 0.5) / resolution;
|
|
|
|
// Direction from rcfCenter to the current tc, aspect ratio corrected
|
|
float2 d = (tc - rcfCenter) * float2(resolution.x/resolution.y, 1);
|
|
|
|
// Compute convolution step size
|
|
float delta = length(d);
|
|
float distortedDelta = rcfRadialFalloff(delta, rcfStrength);
|
|
float stepSize = abs(delta - distortedDelta) * rcfStepFactor;
|
|
|
|
float radius = rcfRadius;
|
|
// Circumferential blur
|
|
if (rcfCircumFerentialStrength > 0) {
|
|
d = float2(d.y, -d.x);
|
|
stepSize *= rcfCircumFerentialStrength;
|
|
radius = floor(rcfRadius * rcfCircumFerentialStrength);
|
|
}
|
|
|
|
// Early exit
|
|
if (radius <= 0.5 || stepSize <= 1/resolution.x) {
|
|
out0[id.xy] = tex0.SampleLevel(sampler0, tc, 0);
|
|
return;
|
|
}
|
|
|
|
// Adjust direction
|
|
d = normalize(d) * stepSize / resolution;
|
|
|
|
// Convolution
|
|
float mipLevel = sqrt(stepSize) * rcfMipmapFactor;
|
|
float sigma = radius/2;
|
|
float twoSigmaSquared = 2 * sigma * sigma;
|
|
float4 a = 0;
|
|
for (float i = -radius; i <= radius; ++i) {
|
|
float weight = exp(-i*i/twoSigmaSquared);
|
|
a += tex0.SampleLevel(sampler0, i * d + tc, mipLevel) * weight;
|
|
}
|
|
|
|
out0[id.xy] = a / sqrt(twoSigmaSquared * PI);
|
|
}
|
|
|
|
//---
|
|
// Small lens dirt
|
|
//---
|
|
|
|
|
|
//---
|
|
// Lens dirt
|
|
//---
|
|
static const float ldMinRadius = 16;
|
|
static const float ldMaxRadius = 32;
|
|
static const float ldCellWidth = 128;
|
|
static const float ldBorderWidthHalf = 1.5;
|
|
static const float ldSeed = 2;
|
|
static const float ldNumLayers = 4;
|
|
|
|
T void csLensDirt(int3 id:SV_DispatchThreadID) {
|
|
float2 tc = id.xy + .5;
|
|
|
|
rndSeed = ldSeed;
|
|
|
|
float4 a = 0;
|
|
for (int i = 0; i < ldNumLayers; ++i) {
|
|
// Modulo repeat, find cell
|
|
float2 p = mod(tc, ldCellWidth) - ldCellWidth / 2;
|
|
float2 c = floor(tc / ldCellWidth);
|
|
|
|
// Backup seed
|
|
uint seedBackup = rndSeed;
|
|
|
|
// Modifiy seed with cell coordinates
|
|
rndSeed += c.x + c.y*ldCellWidth + i*ldCellWidth*ldCellWidth;
|
|
|
|
// Determine radius and jitter
|
|
float r = lerp(ldMinRadius, ldMaxRadius, rnd());
|
|
p += float2(srnd(), srnd()) * (ldCellWidth / 2 - r);
|
|
|
|
// Shapes
|
|
// Hexagon
|
|
//p = abs(p);
|
|
//float d = max(p.y + p.x*0.57735, p.x*1.1547);
|
|
|
|
// Circle
|
|
//float d = length(p);
|
|
|
|
// Pentagon
|
|
float phi = 0.145;
|
|
float2 n[] = {
|
|
{ sin(0*PI/5 + phi), cos(0*PI/5 + phi) },
|
|
{ sin(2*PI/5 + phi), cos(2*PI/5 + phi) },
|
|
{ sin(4*PI/5 + phi), cos(4*PI/5 + phi) },
|
|
{ sin(6*PI/5 + phi), cos(6*PI/5 + phi) },
|
|
{ sin(8*PI/5 + phi), cos(8*PI/5 + phi) }
|
|
};
|
|
// Difference between circumcircle and incircle radii
|
|
float delta = r - (1 + sqrt(5)) / 4 * r;
|
|
float d = max(max(max(max(dot(p, n[0]), dot(p, n[1])), dot(p, n[2])), dot(p, n[3])), dot(p, n[4]));
|
|
// Mix between sphere and pentagon
|
|
d = lerp(length(p), d+ delta, 0.5);
|
|
|
|
// Random color
|
|
a += (float4(rnd(), rnd(), rnd(), 1) + 0.5) * (smoothstep(r, r - ldBorderWidthHalf * 2, d) + smoothstep(ldBorderWidthHalf, 0, abs(d - r + ldBorderWidthHalf * 2)));
|
|
//a += float4(c, 0, 1)*0.1;
|
|
|
|
// Restore seed
|
|
rndSeed = seedBackup;
|
|
|
|
// Displace grid
|
|
tc += ldCellWidth / ldNumLayers;
|
|
}
|
|
|
|
out0[id.xy] = float4(a.xyz / ldNumLayers, 1);
|
|
}
|
|
|
|
//---
|
|
// Blur
|
|
//---
|
|
static const float bRadius = 160;
|
|
static const float bSigma = bRadius / 3;
|
|
static const float bTwoSigmaSquared = 2 * bSigma * bSigma;
|
|
|
|
void bBlur(int3 id, float2 direction) {
|
|
float2 resolution;
|
|
out0.GetDimensions(resolution.x, resolution.y);
|
|
|
|
float2 sourceResolution;
|
|
tex0.GetDimensions(sourceResolution.x, sourceResolution.y);
|
|
|
|
float mipLevel = log2(sourceResolution.x / resolution.x);
|
|
|
|
float2 tc = (id.xy + 0.5) / resolution;
|
|
float2 d = direction / resolution;
|
|
|
|
float4 a = 0;
|
|
for (float i = -bRadius; i <= bRadius; ++i) {
|
|
float weight = expf(-i*i/bTwoSigmaSquared);
|
|
a += tex0.SampleLevel(sampler0, i * d + tc, mipLevel) * weight;
|
|
}
|
|
|
|
out0[id.xy] = a / sqrt(bTwoSigmaSquared * PI);
|
|
}
|
|
|
|
T void csBlurH(int3 id:SV_DispatchThreadID) { bBlur(id, float2(1,0)); }
|
|
T void csBlurV(int3 id:SV_DispatchThreadID) { bBlur(id, float2(0,1)); }
|
|
|
|
//---
|
|
// Streaks
|
|
//---
|
|
static const float stRadius = 160;
|
|
|
|
T void csStreaks(int3 id:SV_DispatchThreadID) {
|
|
float2 resolution;
|
|
out0.GetDimensions(resolution.x, resolution.y);
|
|
|
|
float2 sourceResolution;
|
|
tex0.GetDimensions(sourceResolution.x, sourceResolution.y);
|
|
|
|
float mipLevel = log2(sourceResolution.x / resolution.x);
|
|
|
|
float2 tc = (id.xy + 0.5) / resolution;
|
|
float2 d = float2(1, 0) / resolution;
|
|
|
|
// Convolution with parabolic tent filter
|
|
float4 a = 0;
|
|
for (float i = -stRadius+1; i < stRadius; ++i) {
|
|
float weight = (stRadius - abs(i)) * (stRadius - abs(i));
|
|
a += tex0.SampleLevel(sampler0, i * d + tc, mipLevel) * weight;
|
|
}
|
|
|
|
out0[id.xy] = a * 1.5 / (stRadius * stRadius * stRadius);
|
|
}
|
|
|
|
//---
|
|
// Merge
|
|
//---
|
|
T void csMerge(int3 id:SV_DispatchThreadID) {
|
|
|
|
out0[id.xy] = 1;
|
|
}
|
|
|
|
|
|
/*
|
|
#define ST_NUMTHREADS_X 16
|
|
#define ST_NUMTHREADS_Y 16
|
|
|
|
#define ST_STRIDE (ST_NUMTHREADS_X + stRadius * 2)
|
|
groupshared float4 sData[ST_STRIDE * ST_NUMTHREADS_Y];
|
|
#define ST_ACCESS(X,Y) sData[clamp(X+stRadius, 0, ST_STRIDE-1) + ST_STRIDE * Y]
|
|
[numthreads(ST_NUMTHREADS_X, ST_NUMTHREADS_Y, 1)]
|
|
void csStreaksTest(int3 id:SV_DispatchThreadID, int3 gid : SV_GroupThreadID) {
|
|
float2 resolution;
|
|
|
|
tex0.GetDimensions(resolution.x, resolution.y);
|
|
float2 d = normalize(float2(1, 0)) / resolution;
|
|
|
|
float2 tc = (id.xy + 0.5) / resolution;
|
|
ST_ACCESS(gid.x, gid.y) = tex0.SampleLevel(sampler0, tc, 0);
|
|
|
|
int N = (stRadius+ST_NUMTHREADS_X-1) / ST_NUMTHREADS_X;
|
|
int M = stRadius / N;
|
|
if (gid.x < stRadius)
|
|
for (int i = 1 ; i <= N; ++i) {
|
|
ST_ACCESS(gid.x + M*i, gid.y) = tex0.SampleLevel(sampler0, tc + d * M*i, 0);
|
|
ST_ACCESS(gid.x - M*i, gid.y) = tex0.SampleLevel(sampler0, tc - d * M*i, 0);
|
|
}
|
|
|
|
GroupMemoryBarrier();
|
|
|
|
float4 color = 0;
|
|
int j = ST_STRIDE * gid.y;
|
|
////int k = gid.x;
|
|
//for (float i = 0; i < stRadius; ++i) {
|
|
// int ii = (i+k) % ST_STRIDE;
|
|
// float weight = (stRadius - abs(ii)) * (stRadius - abs(ii));
|
|
// //color += ST_ACCESS(gid.x+i, gid.y) * weight;
|
|
// color += sData[j++] * weight;
|
|
//}
|
|
|
|
for (float i = -stRadius+1; i < stRadius; ++i) {
|
|
float weight = (stRadius - abs(i)) * (stRadius - abs(i));
|
|
//color += ST_ACCESS(gid.x+i, gid.y) * weight;
|
|
color += sData[j++] * weight;
|
|
}
|
|
|
|
out0[id.xy] = color * 1.5 / (stRadius * stRadius * stRadius);
|
|
}
|
|
|
|
*/
|
|
//---
|
|
// Test 1
|
|
//---
|
|
static float3 d, p, n;
|
|
static float h, i, j, k;
|
|
static float d0, d1, d2, d3, dOut;
|
|
|
|
|
|
float ff(float3 p){
|
|
d0 = 30 - length(p);
|
|
d1 = length(p - float3(0, 1, 0)) - 0.02;
|
|
d2 = p.y;
|
|
float3 q = p;
|
|
q.x = abs(q.x) - 2;
|
|
q.y -= 1;
|
|
q.y = abs(q.y) - 0.5;
|
|
//
|
|
q.z = frac(q.z);
|
|
d3 = length(q) - 0.15;
|
|
return dOut = min(min(d0, d1), min(d2, d3));
|
|
}
|
|
|
|
T void csRaytrace(int3 id:SV_DispatchThreadID) {
|
|
//out0[id.xy] = float4(id.y % 16, id.x % 16, 0, 1)*0.1;
|
|
p = float3(0, .5, 4);
|
|
float3 q = p;
|
|
|
|
d = mul(float3x3(.002, 0, -1.279, 0, -.002, 0.719, 0, 0, 1), float3(id.xy, 1));
|
|
d = normalize(float3(d.xy, -1));
|
|
|
|
for (h = .001, i = k = 1; k + 2 > i + h; i += h)
|
|
k = ff(p), p += d*k;
|
|
|
|
float4 color = 0.25;
|
|
if (dOut == d0)
|
|
color = float4(0, 0, 0, 1); // background
|
|
if (dOut == d1)
|
|
color = float4(1, 1, 0, 1)*100; // sphere
|
|
if (dOut == d2)
|
|
color = float4(0.5, 0, 0, 1); // ground
|
|
if (dOut == d3)
|
|
color = float4(1, 1, 0, 1); // sphere
|
|
|
|
|
|
n = normalize(float3(ff(float3(h, 0, 0) + p), ff(float3(0, h, 0) + p), ff(float3(0, 0, h) + p)) - ff(p));
|
|
|
|
for (h = .1, i = j = k = 1; i < 6; i += 1)
|
|
j -= (i*h - ff(p + n*i*h)) / (k *= 2);
|
|
|
|
float depth = dot(float3(0, 0, -1), d*length(p - q));
|
|
//float coc = bkCircleOfConfusion(depth);
|
|
float4 c = float4(color.xyz * (j*0.5 + (n*0.5 + 0.5)*0.5), depth);
|
|
//c.w = 1;
|
|
out0[id.xy] = c;
|
|
}
|
|
//---- RM-
|
|
|
|
|
|
T void cs2(int3 id:SV_DispatchThreadID) {
|
|
out0[id.xy] = float4(1, id.xy / float2(1280, 720), 1);
|
|
if (abs(id.y-359.5) <= 4 && abs(id.x-639.5) <= 100)
|
|
out0[id.xy] = 1;
|
|
}
|
|
|
|
|
|
T void cs__(int3 id:SV_DispatchThreadID) {
|
|
out0[id.xy] = float4((id.xy + 0.5) / float2(1280, 720), 0, 1);
|
|
|
|
}
|
|
|
|
//---
|
|
// Test 2
|
|
//---
|
|
static const float t = 100.0;
|
|
|
|
#define VP float3(.947556,4.117568,-1.34871)
|
|
#define LP (VP+float3(0.16591,-.983647,-0.06044))
|
|
#define UP float3(0.944249,0.179789,-.275808)
|
|
|
|
//#define VP vViewPosition.xyz
|
|
//uniform float4 vViewPosition;
|
|
//#define LP (VP+vViewDirection.xyz)
|
|
//uniform float4 vViewDirection;
|
|
//#define UP (vViewUp.xyz)
|
|
//uniform float4 vViewUp;
|
|
|
|
static const float2 r = float2(1280, 720);
|
|
static const float3 viewPosition = VP;
|
|
static const float3 viewDirection = normalize(LP - VP);
|
|
static const float3 viewUp = UP;
|
|
static const float fovOffset = 0.4;
|
|
static const float lensDistortion0 = -0.125;
|
|
static const float lensDistortion1 = 0;
|
|
static const float lensDistortion2 = +0.125;
|
|
static const float lensDistortion3 = 0;
|
|
static const float cam_shake = 0;
|
|
|
|
#define uTime t
|
|
|
|
float pn(float3 p) {
|
|
p *= 1.5;
|
|
float3 i = floor(p);
|
|
float4 a = dot(i, float3(1, 57, 21)) + float4(0, 57, 21, 78);
|
|
float3 f = cos((p - i)*acos(-1.))*(-.5) + .5;
|
|
a = lerp(sin(cos(a)*a), sin(cos(1 + a)*(1 + a)), f.x);
|
|
a.xy = lerp(a.xz, a.yw, f.y);
|
|
return lerp(a.x, a.y, f.z);
|
|
}
|
|
|
|
float fpn(float3 p) {
|
|
float r;
|
|
p.xz = cos(1.) * p.xz + float2(-sin(1.), sin(1.)) * p.zx;
|
|
r = pn(p*.06125)*.5;
|
|
p.xy = cos(1.) * p.xy + float2(-sin(1.), sin(1.)) * p.yx;
|
|
r += pn(p*.125)*.25;
|
|
p.zy = cos(1.) * p.zy + float2(-sin(1.), sin(1.)) * p.yz;
|
|
r += pn(p*.25)*.125;
|
|
return r;
|
|
}
|
|
|
|
// Globals
|
|
float3 modXZ(float3 p, float m) {
|
|
return p.xz = mod(p.xz + m / 2, m) - m / 2, p;
|
|
}
|
|
|
|
float max3(float3 v) {
|
|
return max(max(v.x, v.y), v.z);
|
|
}
|
|
|
|
float fbox(float3 p, float3 b) {
|
|
float3 d = abs(p) - b;
|
|
return length(max(d, 0)) + max3(min(d, 0));
|
|
}
|
|
|
|
float fsphere(float3 p, float r) {
|
|
return length(p) - r;
|
|
}
|
|
|
|
float fblob(float3 p) {
|
|
p = abs(p);
|
|
if (p.x <= max(p.z, p.y)) p = p.yzx;
|
|
if (p.x <= max(p.z, p.y)) p = p.yzx;
|
|
|
|
float b = max(max(max(
|
|
dot(p, float3(.577, .577, .577)),
|
|
dot(p.xz, float2(.934, .357))),
|
|
dot(p.yx, float2(.526, .851))),
|
|
dot(p.xz, float2(.526, .851))
|
|
), l = length(p);
|
|
|
|
return l - 2.5 - 0.3*(2.5 / 2)* cos(min(sqrt(1.01 - b / l)*(PI / 0.25), PI));
|
|
}
|
|
|
|
float ftest(float3 p) {
|
|
#define phi (.5*(1+sqrt(5)))
|
|
float3 n0 = normalize(float3(-phi, phi - 1, 1));
|
|
float3 n1 = normalize(float3(1, -phi, phi + 1));
|
|
p = abs(p);
|
|
p -= 2 * max(0, dot(p, n0))*n0;
|
|
p -= 2 * max(0, dot(p, n1))*n1;
|
|
p = abs(p);
|
|
p -= 2 * max(0, dot(p, n0))*n0;
|
|
p -= 2 * max(0, dot(p, n1))*n1;
|
|
p = abs(p);
|
|
return p.y - 1.5;
|
|
}
|
|
|
|
float fhex(float3 p, float2 h) {
|
|
float3 q = abs(p);
|
|
return max(q.y - h.y, max(q.z*0.866025 + q.x*0.5, q.x) - h.x);
|
|
}
|
|
|
|
float3x3 rotX(float a) {
|
|
return float3x3 (1, 0, 0, 0, cos(a), -sin(a), 0, sin(a), cos(a));
|
|
}
|
|
|
|
// Hammer anfang
|
|
#define Ro(p, a) p=cos((a))*p+sin((a))*float2(p.y, -p.x)
|
|
float combine_d2(float d1, float d2, float r) {
|
|
float result;
|
|
if ((d1 < r) && (d2 < r)) {
|
|
result = (d1 - r + d2)*sqrt(0.5);
|
|
} else {
|
|
result = min(d1, d2);
|
|
}
|
|
return result;
|
|
}
|
|
float combine_d(float d1, float d2, float r) {
|
|
float result;
|
|
if ((d1 < r) && (d2 < r)) {
|
|
result = (d1 - r + d2)*sqrt(0.5);
|
|
} else {
|
|
result = min(d1, d2);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
float cylinder(float3 p, float r, float c) {
|
|
float d = length(p.xz) - r;
|
|
d = max(d, -p.y - c);
|
|
d = max(d, p.y - c);
|
|
return d;
|
|
}
|
|
|
|
float hammer(float3 p) {
|
|
//float h = box(p-float3(0,1,0),float3(2,10,3));
|
|
//if (h > 1) return h;
|
|
|
|
float S = 0.5;
|
|
|
|
p.y -= 9 * S;
|
|
float3 q = p*(1 - 1 / (0.1 + sqrt(length(p)))*0.3 / S); //bauchiger machen
|
|
float d = fbox(q, S*float3(1, 1, 1.4)) - 0.02*S;
|
|
|
|
//return d;
|
|
float2 pxy = abs(p.xy);
|
|
Ro(pxy, -PI*0.5);
|
|
d = max(d, pxy.x + .8);
|
|
d = combine_d(d, fbox(q, S*float3(0.7, 0.7, 1.75)) - 0.02*S, S*0.3);
|
|
d = combine_d2(d, cylinder(p + S*float3(0, 0.9, 0), 0.4*S, 1.6*S), S*0.1);
|
|
d = combine_d2(d, cylinder(p + S*float3(0, 6, 0), 0.5*S, 7.3*S), S*0.1);
|
|
d = combine_d2(d, cylinder(p + S*float3(0, 11.6, 0), 0.4*S, 1.7*S), S*0.1);
|
|
return d;
|
|
}
|
|
//Hammer ende
|
|
|
|
static float s, s0, s1, s2, s3;
|
|
float f(float3 p) {
|
|
// GroundPlane
|
|
s0 = min(p.y + 3, -length(p) + 100);
|
|
s1 = s2 = s3 = 100000;
|
|
|
|
//s1 = fhex(p-float3(sin(acos(-1)*4./3),0.0,cos(acos(-1)*4./3)), float2(1.5, 0.3));
|
|
//s2 = fhex(p-float3(sin(acos(-1)*2./3),0.7,cos(acos(-1)*2./3)), float2(1.5, 0.3));
|
|
//s3 = fhex(p-float3(sin(acos(-1)*0./3),1.4,cos(acos(-1)*0/3)), float2(1.5, 0.3));
|
|
|
|
s2 = fblob(p);//fblob(p);
|
|
p.yx = p.xy;
|
|
p.z += 5;
|
|
Ro(p.yz, .5);
|
|
s3 = hammer(p);
|
|
return s = min(min(s0, s1), min(s2, s3));
|
|
}
|
|
float3 skydome(float3 direction) {
|
|
direction = normalize(direction);
|
|
float3 col = 0.4 * float3(1, 0.8, 0.5)* max(0.0, +fpn(direction * 13))*3.5;
|
|
col += 0.3 * float3(0.8, 0.9, 1.0)* max(0.0, +fpn(direction * 8 + 100))*2.7;
|
|
col += float3(0.5, 0.6, 1.0)* max(0.0, fpn(direction * 20 + 20) - 0.4) * 10;
|
|
float3 p = direction;
|
|
|
|
//col += float3(1.0,0.6,0.15)* pow(max(0.0,dot(normalize(p), normalize(float3(0.0,1,-8)))),600.0)*400; //sun
|
|
col = pow(col, float3(2, 2, 2));
|
|
return col*1.8;
|
|
}
|
|
|
|
|
|
float3 G(float3 p) {
|
|
return normalize(float3(f(float3(.001, 0, 0) + p), f(float3(0, .001, 0) + p), f(float3(0, 0, .001) + p)) - f(p));
|
|
}
|
|
|
|
float2 I(float3 p, float3 d, float k, float e, float m) {
|
|
float3 q = p;
|
|
float i = 0, j = 0, l = sign(f(p));
|
|
while (i < 1 && abs(s) >= j*e&&j < m)
|
|
f(p), j += abs(s), p += l*d*s, i += k;
|
|
return float2(2 * l*max(abs(s), 0.025)*step(i, 1)*step(j, m), distance(q, p));
|
|
}
|
|
|
|
float A(float3 p, float3 d) {
|
|
float h = .5, i = 1, j = 1, k = 1;
|
|
while (i < 8)
|
|
j -= (i*h - f(p + d*i*abs(h))) / (k *= 2), i++;
|
|
return j;
|
|
}
|
|
|
|
#define R0 0.18
|
|
float fresnel(float3 d, float3 n) {
|
|
float x = 1. - abs(dot(n, d));
|
|
return R0 + (1. - R0) * x*x*x*x;
|
|
}
|
|
|
|
float4 K() {
|
|
return
|
|
//(s==s3?float4(1.0,0.8,0.3,1):
|
|
(s == s3 ? float4(1.0, 0.8, 0.3, 1) :
|
|
(s == s2 ? float4(0.8, 0.3, 0.1, 1)*1.2 :
|
|
(s == s1 ? float4(0.3, 0.6, 0.5, 1) :
|
|
(s == s0 ? float4(1, 1, 1, 1) :
|
|
(s == 10 ? float4(0, 1, 1, 1) :
|
|
float4(1, 1, 1, 1))))));
|
|
}
|
|
|
|
float4 K(float3 p, float3 d, float3 n) {
|
|
float3 l = normalize(float3(2, 20, 17) +
|
|
10 * float3(cos(t * 2), 0, sin(t * 2)) - p);
|
|
float3 l2 = normalize(float3(-10, 20, 7));
|
|
float3 l3 = normalize(float3(1, 1, 1.3));
|
|
|
|
float4 c = K();
|
|
if (s == s0) {
|
|
c *= (A(p, n)*.5 + .5);
|
|
c *= 1.3 / pow(log(length(p)), 1.3);
|
|
c += ((0.0 + 0.5*fpn(p*float3(2, 2, 2)))*1.125) + .02*fpn(p.zxy * 1000);
|
|
if (c.x > 0.5) c.x = 1 - c.x;
|
|
if (c.y > 0.5) c.y = 1 - c.y;
|
|
if (c.z > 0.5) c.z = 1 - c.z;
|
|
//c = float4(1) - c;
|
|
} else if (s == s1 || s == s2 || s == s3) {
|
|
|
|
c = c*.5 + .5;
|
|
c *= max(max(
|
|
pow(max(abs(dot(n, normalize(l - p))), 0), 248.) * 10.0,
|
|
pow(max(abs(dot(n, normalize(l2 - p))), 0), 248.) * 10.0),
|
|
pow(max(abs(dot(n, normalize(l3 - p))), 0), 648.) * 200.0);
|
|
c.xyz += skydome(reflect(d, n)) * 0.5;
|
|
} else {
|
|
c = c*dot(n, l);
|
|
}
|
|
|
|
return c;
|
|
}
|
|
|
|
float4 B(float3 p, float3 d, float3 n, float2 h) {
|
|
float4 a = float4(1, 1, 1, 1), c = float4(0, 0, 0, 0);
|
|
for (int i = 0; i < 8 && (f(p) == s1 || s == s2 || s == s3); ++i) {
|
|
float3 x = d;
|
|
a *= 1 - fresnel(d, n);
|
|
d = refract(d, n * sign(h.x), lerp(1.05, 1 / 1.05, sign(h.x) * .5 + .5));
|
|
if (dot(d, d) == 0)d = reflect(x, n), h.x *= -1.;
|
|
p -= n * h.x, h = I(p, d, 1 / 64.0, 0.005, 200), p += d*h.y;
|
|
if (h.x == 0) {
|
|
|
|
break;
|
|
}
|
|
float J = 1.0;
|
|
if (s == s3)
|
|
J = 1.0;
|
|
a *= lerp(exp(-h.y * J * 3 * (1 - K())), float4(1, 1, 1, 1), sign(h.x) * .5 + .5);
|
|
n = G(p), c += K(p, d, n) * a;
|
|
|
|
}
|
|
return c;
|
|
}
|
|
|
|
float4 R(float3 p, float3 d, float3 n, float2 h) {
|
|
float4 a = float4(1, 1, 1, 1), c = float4(0, 0, 0, 0);
|
|
for (int i = 0; i < 6 && (f(p) == s1 || s == s2 || s == s3); ++i) {
|
|
a *= fresnel(d, n);
|
|
d = reflect(d, n);
|
|
p += n * h.x, h = I(p, d, 1 / 64.0, 0.01, 200), p += d*h.y;
|
|
if (h.x == 0.0) break;
|
|
n = G(p), c += K(p, d, n) * a;
|
|
}
|
|
return c;
|
|
}
|
|
|
|
T void csTestScene(int3 id:SV_DispatchThreadID) {
|
|
float3 up = viewUp;
|
|
float3 right = -cross(viewDirection, viewUp);
|
|
float3 p = viewPosition;
|
|
float3 d = normalize(float3((id.xy + 0.5 - float2(0.5*r)) / r.y, -1.0 + fovOffset)); //fov is fixed
|
|
float r = length(d.xy);
|
|
d.xy = normalize(d.xy)*(r + r*r*lensDistortion0 + pow(r, 4)*lensDistortion1 * 2 + pow(r, 6)*lensDistortion2 * 8 + pow(r, 8)*lensDistortion3 * 16);
|
|
d.xy *= -1;
|
|
d = mul(transpose(float3x3(right, viewUp, -viewDirection)), d);
|
|
d = normalize(d);
|
|
|
|
float2 h = I(p, d, 1 / 128., 0.001, 200);
|
|
//if(h.x==0){o0=float4(.3,0.4,.8,1);return;}
|
|
p += d*h.y;
|
|
float3 n = G(p);
|
|
float4 c = K(p, d, n);
|
|
c += B(p, d, n, h);
|
|
c += R(p, d, n, h);
|
|
float depth = dot(viewDirection, d*h.y);
|
|
float coc = bkCircleOfConfusion(depth);
|
|
out0[id.xy] = float4(c.xyz, h.y);
|
|
} |