port from perforce
This commit is contained in:
783
hgplus/sdfparticles/test.hlsl
Normal file
783
hgplus/sdfparticles/test.hlsl
Normal file
@@ -0,0 +1,783 @@
|
||||
struct ParticleState
|
||||
{
|
||||
float3 oldPosition;
|
||||
float3 currentPosition;
|
||||
float3 velocity;
|
||||
float3 tangent;
|
||||
float opacity;
|
||||
float size;
|
||||
};//56 bytes
|
||||
|
||||
#define PI 3.14159265
|
||||
|
||||
#define SDF_SIMILARITY 64.0 // try 0.2 for fractal flames, you can also go up to 64
|
||||
#define TANGENT_SPEED 8.0 // increase to add more chaos
|
||||
#define GRADIENT_SPEED 64.0
|
||||
#define SDF_SPEED 1.0
|
||||
|
||||
float rand(float x, inout float seed)
|
||||
{
|
||||
seed = frac(sin(dot(float2(x, seed), float2(12.9898, 78.233))) * 43758.5453);
|
||||
return seed;
|
||||
}
|
||||
|
||||
cbuffer _0 : register(b0)
|
||||
{
|
||||
float demoTime;
|
||||
float deltaTime;
|
||||
float dummy1;
|
||||
float dummy2;
|
||||
};
|
||||
|
||||
RWStructuredBuffer<ParticleState> particles:register(u0);
|
||||
StructuredBuffer<ParticleState> drawParticles:register(t0);
|
||||
|
||||
void initParticle(int idx)
|
||||
{
|
||||
float seed = idx;
|
||||
particles[idx].currentPosition =
|
||||
particles[idx].oldPosition = rand(idx, seed) * 12 * float3(rand(idx, seed) * 2 - 1, rand(idx, seed) * 2 - 1, rand(idx, seed) * 2 - 1) + float3(0, -24, -24);
|
||||
particles[idx].tangent = rand(idx, seed) * normalize(float3(rand(idx, seed) * 2 - 1, rand(idx, seed) * 2 - 1, rand(idx, seed) * 2 - 1));
|
||||
particles[idx].velocity = rand(idx, seed) * normalize(float3(rand(idx, seed) * 2 - 1, rand(idx, seed) * 2 - 1, rand(idx, seed) * 2 - 1));
|
||||
particles[idx].size = 2 * rand(idx, seed);
|
||||
particles[idx].opacity = 1.0;
|
||||
}
|
||||
|
||||
[numthreads(16, 16, 1)]
|
||||
void init(int3 id:SV_DispatchThreadID)
|
||||
{
|
||||
int idx = 1024 * id.y + id.x;
|
||||
initParticle(idx);
|
||||
}
|
||||
|
||||
float3 fusion(float x) {
|
||||
float t = saturate(x);
|
||||
return saturate(float3(sqrt(t), t*t*t, max(sin(3.1415*1.75*t), pow(t, 12.0))));
|
||||
}
|
||||
|
||||
float3 project(float3 v)
|
||||
{
|
||||
return float3(v.x / 1.6, v.y, (1 - v.z) / 10.0f) / -v.z;
|
||||
}
|
||||
|
||||
float3 h2r(float h, float s, float v){ return lerp(saturate((abs(frac(h + float3(1, 2, 3) / 3) * 6 - 3) - 1)), 1, s)*v; }
|
||||
|
||||
float sdSphere(float3 p, float s)
|
||||
{
|
||||
return length(p) - s;
|
||||
}
|
||||
|
||||
float sdTorus(float3 p, float2 t)
|
||||
{
|
||||
float2 q = float2(length(p.xz) - t.x, p.y);
|
||||
return length(q) - t.y;
|
||||
}
|
||||
|
||||
float sdCapsule(float3 p, float3 a, float3 b, float r)
|
||||
{
|
||||
float3 pa = p - a, ba = b - a;
|
||||
float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
|
||||
return length(pa - ba*h) - r;
|
||||
}
|
||||
|
||||
float lengthN(float2 v, float n)
|
||||
{
|
||||
v = pow(v, n);
|
||||
return pow(v.x + v.y, 1.0 / n);
|
||||
}
|
||||
|
||||
float sdTorus82(float3 p, float2 t)
|
||||
{
|
||||
float2 q = float2(lengthN(p.xz, 2) - t.x, p.y);
|
||||
return lengthN(q, 8) - t.y;
|
||||
}
|
||||
|
||||
float opRep(float3 p, float3 c)
|
||||
{
|
||||
float3 q = sign(p) * fmod(p, c) - 0.5*c;
|
||||
return sdTorus82(q, float2(1.0, 0.5));
|
||||
}
|
||||
|
||||
void rX(inout float3 p, float a)
|
||||
{
|
||||
float c, s; float3 q = p;
|
||||
c = cos(a); s = sin(a);
|
||||
p.y = c * q.y - s * q.z;
|
||||
p.z = s * q.y + c * q.z;
|
||||
}
|
||||
|
||||
float sdBox(float3 p, float3 b)
|
||||
{
|
||||
float3 d = abs(p) - b;
|
||||
return min(max(d.x, max(d.y, d.z)), 0.0) + length(max(d, 0.0));
|
||||
}
|
||||
|
||||
float f1(float3 p)
|
||||
{
|
||||
p.z += 24.0;
|
||||
p.x += sin(demoTime * SDF_SPEED * 0.5) * 4;
|
||||
p.y += cos(demoTime * SDF_SPEED * 1.5) * 2;
|
||||
float d = opRep(p, float3(5.0, 5.0, 5.0));
|
||||
d = max(d, sdBox(p, float3(9.0, 8.0, 9.0)));
|
||||
return d;
|
||||
}
|
||||
|
||||
float menger(float3 p)
|
||||
{
|
||||
float d = sdBox(p, float3(1.0, 1.0, 1.0));
|
||||
|
||||
float s = 1.0;
|
||||
for (int m = 0; m<8; m++)
|
||||
{
|
||||
float3 a = sign(p) * fmod(p*s, 2.0) - 1.0;
|
||||
s *= 3.0;
|
||||
float3 r = abs(1.0 - 3.0*abs(a));
|
||||
|
||||
float da = max(r.x, r.y);
|
||||
float db = max(r.y, r.z);
|
||||
float dc = max(r.z, r.x);
|
||||
float c = (min(da, min(db, dc)) - 1.0) / s;
|
||||
|
||||
d = max(d, c);
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
static const float fd = 0.763;
|
||||
static const float fu = 10.0;
|
||||
static const float fs = 1.0;
|
||||
static const float3 fc = float3(0, 0, 0);
|
||||
static const float ff = -0.50000;
|
||||
static const float3 cs = float3(0.80800, 0.80800, 1.16700);
|
||||
|
||||
float dE(float3 p)
|
||||
{
|
||||
float dEfactor = 1.;
|
||||
//int fractal_iterations = 12;
|
||||
for (int i = 0; i<12; i++) {
|
||||
//box folding
|
||||
p = 2.*clamp(p, -cs, cs) - p;
|
||||
//inversion
|
||||
float k = max(fs / dot(p, p), 1.);
|
||||
p *= k;
|
||||
dEfactor *= k;
|
||||
//julia seed
|
||||
p += fc;
|
||||
}
|
||||
//call basic shape and scale its DE
|
||||
//need to adjust fractal_distancemult with non zero julia seed
|
||||
float rxy = length(p.xy) - fu;
|
||||
//distance from pos to the pseudo kleinian basic shape ...
|
||||
return (fd*max(rxy, abs(length(p.xy)*p.z) / sqrt(dot(p, p))) / abs(dEfactor));
|
||||
}
|
||||
|
||||
float f(float3 p)
|
||||
{
|
||||
p.z += 4.0;
|
||||
p.x += sin(demoTime * SDF_SPEED * 0.5) * 4;
|
||||
p.y += cos(demoTime * SDF_SPEED * 1.5) * 0.5;
|
||||
return dE(p);
|
||||
}
|
||||
|
||||
[numthreads(16, 16, 1)]
|
||||
void update(int3 id:SV_DispatchThreadID)
|
||||
{
|
||||
int idx = 1024 * id.y + id.x;
|
||||
float3 p = particles[idx].currentPosition;
|
||||
float2 e = float2(1, 0) * 0.001;
|
||||
float d = f(p);
|
||||
if (d > 90 || p.y > 30)
|
||||
{
|
||||
initParticle(idx);
|
||||
}
|
||||
|
||||
float3 v = -normalize(float3(f(p + e.xyy) - f(p - e.xyy), f(p + e.yxy) - f(p - e.yxy), f(p + e.yyx) - f(p - e.yyx)));
|
||||
v = lerp(particles[idx].velocity, v, saturate(deltaTime * SDF_SIMILARITY));
|
||||
v = lerp(float3(0, 1, 0), v, 0.99);
|
||||
float3 t = cross(particles[idx].tangent, v);
|
||||
particles[idx].oldPosition = particles[idx].currentPosition;
|
||||
particles[idx].currentPosition += (TANGENT_SPEED * t / (1 + pow(abs(d), 0.5)) + GRADIENT_SPEED * v * d * (0.5 + 0.5 * step(0, -d))) * deltaTime;
|
||||
particles[idx].velocity = v;
|
||||
particles[idx].opacity = d;
|
||||
}
|
||||
|
||||
struct _2
|
||||
{
|
||||
float3 pos1 : TEXCOORD0;
|
||||
float3 pos2 : TEXCOORD1;
|
||||
float3 dir : TEXCOORD2;
|
||||
float opacity : OPACITY;
|
||||
float size : SIZE;
|
||||
};
|
||||
|
||||
struct _3
|
||||
{
|
||||
float4 pos : SV_POSITION;
|
||||
float opacity : OPACITY;
|
||||
float hue : HUE;
|
||||
};
|
||||
|
||||
void pvs(uint id : SV_VertexID, out _2 o)
|
||||
{
|
||||
ParticleState particle = drawParticles[id];
|
||||
o.pos1 = particle.oldPosition;
|
||||
o.pos2 = particle.currentPosition;
|
||||
o.dir = particle.velocity;
|
||||
o.opacity = particle.opacity;
|
||||
o.size = particle.size;
|
||||
}
|
||||
|
||||
float particleSize(float z)
|
||||
{
|
||||
return 0.01f / -z;
|
||||
}
|
||||
|
||||
[maxvertexcount(18)]
|
||||
void pgs(point _2 input[1], inout TriangleStream<_3> o)
|
||||
{
|
||||
_2 p = input[0];
|
||||
|
||||
float s1 = particleSize(p.pos1.z) * p.size;
|
||||
float s2 = particleSize(p.pos2.z) * p.size;
|
||||
|
||||
float3 p1 = project(p.pos1);
|
||||
float3 p2 = project(p.pos2);
|
||||
float2 d = normalize(project(p.dir).xy);
|
||||
|
||||
float2 pr = float2(-d.y, d.x);
|
||||
//p1.xy -= d * s1 * 0.5;
|
||||
//p2.xy += d * s2 * 0.5;
|
||||
|
||||
_3 r;
|
||||
float l = distance(p1.xy, p2.xy);
|
||||
|
||||
if (l > 0.1)
|
||||
return;
|
||||
r.opacity = l * p.opacity;
|
||||
r.hue = p.opacity;
|
||||
|
||||
r.pos = float4(p1.xy - d * s1, p1.z, 1.0); o.Append(r);
|
||||
r.pos = float4(p1.xy + pr * s1, p1.z, 1.0); o.Append(r);
|
||||
r.pos = float4(p1.xy - pr * s1, p1.z, 1.0); o.Append(r);
|
||||
o.RestartStrip();
|
||||
|
||||
r.pos = float4(p1.xy - pr * s1, p1.z, 1.0); o.Append(r);
|
||||
r.pos = float4(p1, 1.0); o.Append(r);
|
||||
r.pos = float4(p2.xy - pr * s2, p2.z, 1.0); o.Append(r);
|
||||
o.RestartStrip();
|
||||
|
||||
r.pos = float4(p1, 1.0); o.Append(r);
|
||||
r.pos = float4(p2, 1.0); o.Append(r);
|
||||
r.pos = float4(p2.xy - pr * s2, p2.z, 1.0); o.Append(r);
|
||||
o.RestartStrip();
|
||||
|
||||
r.pos = float4(p1, 1.0); o.Append(r);
|
||||
r.pos = float4(p2.xy + pr * s2, p2.z, 1.0); o.Append(r);
|
||||
r.pos = float4(p2, 1.0); o.Append(r);
|
||||
o.RestartStrip();
|
||||
|
||||
r.pos = float4(p1, 1.0); o.Append(r);
|
||||
r.pos = float4(p1.xy + pr * s1, p1.z, 1.0); o.Append(r);
|
||||
r.pos = float4(p2.xy + pr * s2, p2.z, 1.0); o.Append(r);
|
||||
o.RestartStrip();
|
||||
|
||||
r.pos = float4(p2.xy + d * s2, p2.z, 1.0); o.Append(r);
|
||||
r.pos = float4(p2.xy - pr * s2, p2.z, 1.0); o.Append(r);
|
||||
r.pos = float4(p2.xy + pr * s2, p2.z, 1.0); o.Append(r);
|
||||
o.RestartStrip();
|
||||
}
|
||||
|
||||
float4 pps(_3 i) : SV_Target
|
||||
{
|
||||
float intensity = 1.0 / (max(0, i.opacity) + 64);
|
||||
float3 color = 100*fusion(i.hue*50);//h2r(abs(i.hue) / 8 + demoTime * 0.1, 0.6, 1.0);
|
||||
return float4(color, intensity);
|
||||
}
|
||||
|
||||
float3 intersect(float3 ro, float3 rd)
|
||||
{
|
||||
float maxd = 70.0;
|
||||
float precis = 0.001;
|
||||
float h = precis*2.0;
|
||||
float t = 0.0;
|
||||
float d = 0.0;
|
||||
float j = 0.0;
|
||||
for (int i = 0; i < 90; i++)
|
||||
{
|
||||
if (abs(h)<precis || t>maxd) continue;//break;
|
||||
t += h;
|
||||
float res = f(ro + rd*t);
|
||||
h = res/*.x*/;
|
||||
j = i;
|
||||
//d = res.y;
|
||||
}
|
||||
|
||||
float m = (t>maxd) ? -1.0 : 1.0;
|
||||
return float3(t, m, j / 90.0f);
|
||||
}
|
||||
|
||||
void rvs(uint id : SV_VertexID, out float2 q : QUAD, out float4 svPos : SV_POSITION)
|
||||
{
|
||||
if (id == 0)
|
||||
svPos = float4(-1.0, -1.0, 0.0, 1.0);
|
||||
else if (id == 1)
|
||||
svPos = float4(-1.0, 1.0, 0.0, 1.0);
|
||||
else if (id == 2)
|
||||
svPos = float4(1.0, -1.0, 0.0, 1.0);
|
||||
else
|
||||
svPos = float4(1.0, 1.0, 0.0, 1.0);
|
||||
|
||||
q = svPos.xy;
|
||||
}
|
||||
|
||||
float4 rps(float2 p : QUAD) : SV_Target
|
||||
{
|
||||
float an = sin(-0.25 + 0.31416*demoTime);
|
||||
|
||||
float3 ro = float3(0, 0, 0);
|
||||
float3 rd = normalize(float3(p.x * 1.6, p.y, -1.0));
|
||||
|
||||
// raymarch
|
||||
float3 rm = intersect(ro, rd);
|
||||
if (rm.y > 0)
|
||||
{
|
||||
return float4(rm.z, rm.z, rm.z, 0.2);
|
||||
}
|
||||
|
||||
return float4(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
//---
|
||||
// Postprocessing computer shaders
|
||||
//---
|
||||
|
||||
RWTexture2D<float4> out0:register(u0);
|
||||
SamplerState sampler0 : register(s0);
|
||||
Texture2D tex0: register(t0);
|
||||
Texture2D tex1: register(t1);
|
||||
Texture2D tex2: register(t2);
|
||||
Texture2D tex3: register(t3);
|
||||
Texture2D tex4: register(t4);
|
||||
Texture2D tex5: register(t5);
|
||||
Texture2D tex6: register(t6);
|
||||
Texture2D tex7: register(t7);
|
||||
|
||||
static uint rndSeed = 0;
|
||||
|
||||
void setRndSeed(uint seed) {
|
||||
rndSeed = seed;
|
||||
}
|
||||
|
||||
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 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 mod(float x, float y) {
|
||||
return x - y * floor(x / y);
|
||||
}
|
||||
|
||||
float2 mod(float2 x, float2 y) {
|
||||
return x - y * floor(x / y);
|
||||
}
|
||||
|
||||
float3 mod(float3 x, float3 y) {
|
||||
return x - y * floor(x / y);
|
||||
}
|
||||
|
||||
float2 mod(float2 x, float y) {
|
||||
return x - y * floor(x / y);
|
||||
}
|
||||
|
||||
float3 mod(float3 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);
|
||||
}
|
||||
|
||||
//---
|
||||
// Radial and circumferential blur
|
||||
//---
|
||||
static const float rcfMipmapFactor = 1.5;
|
||||
static const float rcfStepFactor = 5;
|
||||
static const float rcfStrengthRadial = 50;
|
||||
static const float rcfStrengthCircumferential = 50;
|
||||
static const float rcfRadius = 15;
|
||||
static const float2 rcfCenter = {0.5, 0.5};
|
||||
|
||||
float rcfRadialFalloff(float radius, float amount) {
|
||||
return radius * (1 + amount*radius*0.01);
|
||||
}
|
||||
|
||||
float4 rcfBlur(float2 tc, float2 resolution, float strength, float circumFerentialStrength) {
|
||||
// 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, strength);
|
||||
float stepSize = abs(delta - distortedDelta) * rcfStepFactor;
|
||||
|
||||
float radius = rcfRadius;
|
||||
// Circumferential blur
|
||||
if (circumFerentialStrength > 0) {
|
||||
d = float2(d.y, -d.x);
|
||||
stepSize *= circumFerentialStrength;
|
||||
radius = floor(rcfRadius * circumFerentialStrength);
|
||||
}
|
||||
|
||||
// Early exit
|
||||
if (radius <= 0.5) {// || stepSize <= 1/resolution.x) {
|
||||
return tex0.SampleLevel(sampler0, tc, 0);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
return a / sqrt(twoSigmaSquared * PI);
|
||||
}
|
||||
|
||||
[numthreads(16, 16, 1)] void csRadialBlur(int3 id:SV_DispatchThreadID) {
|
||||
float2 resolution;
|
||||
out0.GetDimensions(resolution.x, resolution.y);
|
||||
|
||||
float2 tc = (id.xy + 0.5) / resolution;
|
||||
|
||||
out0[id.xy] = rcfBlur(tc, resolution, rcfStrengthRadial, 0);
|
||||
}
|
||||
|
||||
[numthreads(16, 16, 1)] void csCircumferentialBlur(int3 id:SV_DispatchThreadID) {
|
||||
float2 resolution;
|
||||
out0.GetDimensions(resolution.x, resolution.y);
|
||||
|
||||
float2 tc = (id.xy + 0.5) / resolution;
|
||||
|
||||
out0[id.xy] = rcfBlur(tc, resolution, rcfStrengthCircumferential, 1);
|
||||
}
|
||||
|
||||
//---
|
||||
// Sensor dirt
|
||||
//---
|
||||
|
||||
[numthreads(16, 16, 1)] void csSensorDirt(int3 id:SV_DispatchThreadID) {
|
||||
float2 tc = id.xy + .5;
|
||||
}
|
||||
|
||||
//---
|
||||
// Lens dirt
|
||||
//---
|
||||
static const float ldMinRadius = 0.025;
|
||||
static const float ldMaxRadius = 0.075;
|
||||
static const float ldCellWidth = 3*ldMaxRadius;
|
||||
static const float ldBorderWidthHalf = 0.00125;
|
||||
static const float ldSeed = 3;
|
||||
static const float ldNumLayers = 4;
|
||||
|
||||
[numthreads(16, 16, 1)] void csLensDirt(int3 id:SV_DispatchThreadID) {
|
||||
float2 resolution;
|
||||
out0.GetDimensions(resolution.x, resolution.y);
|
||||
|
||||
float2 tc = (id.xy + 0.5) / resolution;
|
||||
tc *= float2(resolution.x/resolution.y, 1);
|
||||
//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) * resolution.x;
|
||||
|
||||
// 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);
|
||||
float d = length(p);
|
||||
|
||||
// Random color
|
||||
a += (float4(rnd(), rnd(), rnd(), 1) + 0.5) * (smoothstep(r, r - ldBorderWidthHalf * 2, d) + 0.25 * 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);
|
||||
out0[id.xy] = float4(a.xyz / ldNumLayers, 1);
|
||||
}
|
||||
|
||||
//---
|
||||
// Blur
|
||||
//---
|
||||
static const float bRadius = 160;
|
||||
static const float bSigma = bRadius / 3.5;
|
||||
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 = exp(-i*i/bTwoSigmaSquared);
|
||||
a += tex0.SampleLevel(sampler0, i * d + tc, mipLevel) * weight;
|
||||
}
|
||||
|
||||
out0[id.xy] = a / sqrt(bTwoSigmaSquared * PI);
|
||||
}
|
||||
|
||||
[numthreads(16, 16, 1)] void csBlurH(int3 id:SV_DispatchThreadID) { bBlur(id, float2(1,0)); }
|
||||
[numthreads(16, 16, 1)] void csBlurV(int3 id:SV_DispatchThreadID) { bBlur(id, float2(0,1)); }
|
||||
|
||||
//---
|
||||
// Streaks
|
||||
//---
|
||||
static const float stRadius = 160;
|
||||
|
||||
[numthreads(16, 16, 1)] 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);
|
||||
}
|
||||
|
||||
//---
|
||||
// Distort Chroma
|
||||
//---
|
||||
static const float dcStrength = 10.0;
|
||||
|
||||
static const float2 dcCenter = {0.5, 0.5};
|
||||
static const int dcSamples = 12;
|
||||
|
||||
float dcRadialFalloff(float radius, float amount) {
|
||||
return radius * (1 + amount*radius*0.01);
|
||||
}
|
||||
|
||||
float4 dcSample(float2 tc, float amount, float2 resolution) {
|
||||
// Direction from cdCenter to the current tc, aspect ratio corrected
|
||||
float2 d = (tc - dcCenter) * float2(resolution.x/resolution.y, 1);
|
||||
float radius = length(d);
|
||||
d /= radius == 0 ? d : radius;
|
||||
return tex0.SampleLevel(sampler0, dcCenter + d * dcRadialFalloff(radius, amount) / float2(resolution.x/resolution.y, 1), 0);
|
||||
}
|
||||
|
||||
[numthreads(16, 16, 1)] void csDistortChroma(int3 id:SV_DispatchThreadID) {
|
||||
float2 resolution;
|
||||
out0.GetDimensions(resolution.x, resolution.y);
|
||||
|
||||
float2 tc = (id.xy + 0.5) / resolution;
|
||||
|
||||
float4 original = tex0.SampleLevel(sampler0, tc, 0);
|
||||
if (dcStrength == 0) {
|
||||
out0[id.xy] = original;
|
||||
return;
|
||||
}
|
||||
|
||||
// Accumulate along spectrum
|
||||
float4 a = 0;
|
||||
for (int i = 1; i <= dcSamples; ++i) {
|
||||
float lambda = 0.4f * (i/float(dcSamples+1)) + 0.35f;
|
||||
float4 w = float4(pulse(0.65, 0.1, lambda), pulse(0.55, 0.1, lambda), pulse(0.45, 0.1, lambda), 0.25) * 4.0;
|
||||
a += w * dcSample(tc, -(i-1)/float(dcSamples) * dcStrength , resolution);
|
||||
}
|
||||
|
||||
a /= dcSamples;
|
||||
|
||||
out0[id.xy] = lerp(original, a, saturate(dcStrength));
|
||||
}
|
||||
|
||||
//---
|
||||
// Ghosts
|
||||
//---
|
||||
float4 ghRainbow(float angle) {
|
||||
return float4(sin(angle), sin(angle + 3.1415*2.0/3.0), sin(angle + 3.1415*4.0/3.0), 1) * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
[numthreads(16, 16, 1)] void csGhosts(int3 id:SV_DispatchThreadID) {
|
||||
float2 resolution;
|
||||
out0.GetDimensions(resolution.x, resolution.y);
|
||||
|
||||
float2 tc = (id.xy + 0.5) / resolution;
|
||||
tc = 1 - tc;
|
||||
float2 texelSize = 1 / resolution;
|
||||
float2 aspectCorrection = float2(resolution.x/resolution.y, 1);
|
||||
|
||||
float2 direction = (0.5 - tc) * 2;
|
||||
float4 a = 0;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
float2 sc0 = 1 - frac(tc + direction * i * 0.2);
|
||||
float2 sc1 = 1 - frac(tc + direction * i * 0.1999);
|
||||
float r = length((sc0 - 0.5) * aspectCorrection);
|
||||
a += max(0, tex0.SampleLevel(sampler0, sc0, 0) - 0.125) * lerp(1, ghRainbow(r*20), 1.5*r);
|
||||
a += max(0, tex1.SampleLevel(sampler0, sc0, 0) - 0.125) * lerp(1, ghRainbow(r*15+i), 1.5*r);
|
||||
}
|
||||
|
||||
out0[id.xy] = float4(a.xyz/5, 1);
|
||||
}
|
||||
|
||||
|
||||
//---
|
||||
// Merge
|
||||
//---
|
||||
float3 saturation(float3 color, float saturation) {
|
||||
return lerp(dot(color, float3(0.2126, 0.7152, 0.0722)), color, saturation);
|
||||
}
|
||||
|
||||
float3 liftGammaGain(float3 color, float3 lift, float3 gamma, float3 gain) {
|
||||
return pow(saturate(gain*color + lift*(-gain*color + 1)), 1/gamma);
|
||||
}
|
||||
|
||||
float3 uncharted2ToneMapping(float3 c) {
|
||||
float A = 0.15;
|
||||
float B = 0.50;
|
||||
float C = 0.10;
|
||||
float D = 0.20;
|
||||
float E = 0.02;
|
||||
float F = 0.30;
|
||||
float W = 11.2;
|
||||
|
||||
c = ((c * (A * c + C * B) + D * E) / (c * (A * c + B) + D * F)) - E / F;
|
||||
float white = ((W * (A * W + C * B) + D * E) / (W * (A * W + B) + D * F)) - E / F;
|
||||
return c / white;
|
||||
}
|
||||
|
||||
[numthreads(16, 16, 1)] void csMerge(int3 id:SV_DispatchThreadID) {
|
||||
float2 resolution;
|
||||
out0.GetDimensions(resolution.x, resolution.y);
|
||||
|
||||
float2 tc = (id.xy + 0.5) / resolution;
|
||||
|
||||
rndSeed = (id.y * 720 + id.x);// * int(time * 1000);
|
||||
float3 rndNoiseXYT = float3(rnd(), rnd(), rnd());
|
||||
|
||||
rndSeed = id.y;
|
||||
float3 rndNoiseY = float3(rnd(), rnd(), rnd());
|
||||
|
||||
|
||||
float3 base = tex0.SampleLevel(sampler0, tc, 0).xyz;
|
||||
float3 blur1 = tex1.SampleLevel(sampler0, tc, 0).xyz;
|
||||
float3 blur8 = tex2.SampleLevel(sampler0, tc, 0).xyz;
|
||||
float3 blur32 = tex3.SampleLevel(sampler0, tc, 0).xyz;
|
||||
float3 streaks = tex4.SampleLevel(sampler0, tc, 0).xyz;
|
||||
float3 lensDirt = tex5.SampleLevel(sampler0, tc, 0).xyz;
|
||||
float3 ghosts = tex6.SampleLevel(sampler0, tc, 0).xyz;
|
||||
|
||||
float3 color = base.xyz;
|
||||
|
||||
color += blur1*0.125;
|
||||
color += blur8*0.125;
|
||||
color += blur32*0.125;
|
||||
|
||||
// Streaks
|
||||
color += streaks * (lerp(1, rndNoiseY.x, 0.25)) * 0.25;// * rnd();
|
||||
|
||||
// Lens dirt
|
||||
//color += lensDirt * 0.25 * max(0, dot(tex2.SampleLevel(sampler0, frac(1-tc), 0).xyz, float3(0.299, 0.587, 0.114)) - 1.0);
|
||||
|
||||
// Ghosts
|
||||
color += ghosts * 0.125;// * ghosts * 0.25;
|
||||
|
||||
// Grain
|
||||
color *= lerp(1, rndNoiseXYT, 0.35);
|
||||
|
||||
//color = base;
|
||||
|
||||
// Tonemapping
|
||||
color = max(0, uncharted2ToneMapping(max(0, color*0.5)));
|
||||
//color *= color;
|
||||
|
||||
color = liftGammaGain(color, float3(0, 0, 0), float3(1, 1, 1), float3(1, 1, 1));
|
||||
//color = saturation(color, 1.5);
|
||||
//color = pow(color, 1/2.2);
|
||||
float4 result = float4(color, dot(color, float3(0.299, 0.587, 0.114)));
|
||||
|
||||
out0[id.xy] = result;
|
||||
}
|
||||
Reference in New Issue
Block a user