342 lines
8.4 KiB
HLSL
342 lines
8.4 KiB
HLSL
cbuffer ParamConstants : register (b0)
|
|
{
|
|
float MaxSteps;
|
|
float StepSize;
|
|
float MinDistance;
|
|
float MaxDistance;
|
|
|
|
float Minrad;
|
|
float Scale;
|
|
float2 Fold;
|
|
|
|
float3 Clamping;
|
|
float1 __align1__;
|
|
float3 Increment;
|
|
float1 __align2__;
|
|
|
|
float4 Surface1;
|
|
float4 Surface2;
|
|
float4 Surface3;
|
|
float4 Specular;
|
|
float4 Glow;
|
|
float4 AmbientOcclusion;
|
|
float4 Background;
|
|
|
|
float2 Spec;
|
|
float AODistance;
|
|
float Fog;
|
|
|
|
float3 LightPos;
|
|
float DistToColor;
|
|
}
|
|
|
|
cbuffer TimeConstants : register (b1)
|
|
{
|
|
float globalTime;
|
|
float time;
|
|
float runTime;
|
|
float beatTime;
|
|
}
|
|
|
|
cbuffer Transforms : register(b0)
|
|
{
|
|
float4x4 CameraToClipSpace;
|
|
float4x4 ClipSpaceToCamera;
|
|
float4x4 WorldToCamera;
|
|
float4x4 CameraToWorld;
|
|
float4x4 WorldToClipSpace;
|
|
float4x4 ClipSpaceToWorld;
|
|
float4x4 ObjectToWorld;
|
|
float4x4 WorldToObject;
|
|
float4x4 ObjectToCamera;
|
|
float4x4 ObjectToClipSpace;
|
|
};
|
|
|
|
//>>> _common parameters
|
|
float4x4 objectToWorldMatrix;
|
|
float4x4 worldToCameraMatrix;
|
|
float4x4 projMatrix;
|
|
Texture2D txDiffuse;
|
|
float2 RenderTargetSize;
|
|
//<<< _common parameters
|
|
|
|
|
|
struct vsOutput
|
|
{
|
|
float4 position : SV_POSITION;
|
|
float2 texCoord : TEXCOORD;
|
|
float3 worldTViewDir : TEXCOORD1;
|
|
float3 worldTViewPos : TEXCOORD2;
|
|
};
|
|
|
|
static const float3 Quad[] =
|
|
{
|
|
float3(-1, -1, 0),
|
|
float3( 1, -1, 0),
|
|
float3( 1, 1, 0),
|
|
float3( 1, 1, 0),
|
|
float3(-1, 1, 0),
|
|
float3(-1, -1, 0),
|
|
};
|
|
|
|
|
|
Texture2D<float4> ImageA : register (t0);
|
|
sampler texSampler : register (s0);
|
|
|
|
|
|
vsOutput vsMain4(uint vertexId: SV_VertexID)
|
|
{
|
|
vsOutput output;
|
|
float4 quadPos = float4(Quad[vertexId], 1) ;
|
|
float2 texCoord = quadPos.xy*float2(0.5, -0.5) + 0.5;
|
|
output.texCoord = texCoord;
|
|
output.position = quadPos;
|
|
float4x4 ViewToWorld = ClipSpaceToWorld;// CameraToWorld ;
|
|
|
|
float4 viewTNearFragPos = float4 (texCoord.x * 2.0 - 1.0, -texCoord.y * 2.0 + 1.0, 0.0, 1.0);
|
|
float4 worldTNearFragPos = mul (viewTNearFragPos, ViewToWorld);
|
|
worldTNearFragPos /= worldTNearFragPos.w;
|
|
|
|
float4 viewTFarFragPos = float4 (texCoord.x * 2.0 - 1.0, -texCoord.y * 2.0 + 1.0, 1.0, 1.0);
|
|
float4 worldTFarFragPos = mul (viewTFarFragPos, ViewToWorld);
|
|
worldTFarFragPos /= worldTFarFragPos.w;
|
|
|
|
output.worldTViewDir = normalize (worldTFarFragPos.xyz - worldTNearFragPos.xyz);
|
|
|
|
output.worldTViewPos = worldTNearFragPos.xyz;
|
|
return output;
|
|
|
|
|
|
return output;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define mod (x, y) (x - y * floor (x / y))
|
|
#define mod ((x), (y)) ((x) - (y) * floor ((x) / (y)))
|
|
|
|
float sdBox (in float2 p, in float2 b)
|
|
{
|
|
float2 d = abs (p) - b;
|
|
return length (
|
|
max (d, float2 (0, 0))) + min (max (d.x, d.y),
|
|
0.0);
|
|
}
|
|
|
|
|
|
|
|
//>>> setup
|
|
SamplerState samLinear
|
|
{
|
|
Filter = MIN_MAG_MIP_LINEAR;
|
|
AddressU = Clamp;
|
|
AddressV = Clamp;
|
|
};
|
|
//<<< setup
|
|
|
|
//>>> declarations
|
|
struct VS_IN
|
|
{
|
|
float4 pos : POSITION;
|
|
float2 texCoord : TEXCOORD;
|
|
};
|
|
|
|
struct PS_IN
|
|
{
|
|
float4 pos : SV_POSITION;
|
|
float2 texCoord : TEXCOORD0;
|
|
float3 worldTViewPos : TEXCOORD1;
|
|
float3 worldTViewDir : TEXCOORD2;
|
|
};
|
|
//<<< declarations
|
|
|
|
static float BOX_RADIUS = 0.005;
|
|
float dBox (float3 p, float3 b)
|
|
{
|
|
return length (max (abs (p) - b + float3 (BOX_RADIUS, BOX_RADIUS, BOX_RADIUS), 0.0)) - BOX_RADIUS;
|
|
}
|
|
|
|
|
|
static int mandelBoxIterations = 7;
|
|
|
|
|
|
|
|
float dMandelbox (float3 pos)
|
|
{
|
|
float4 pN = float4 (pos, 1);
|
|
//return dStillLogo(pN);
|
|
|
|
// precomputed constants
|
|
float minRad2 = clamp (Minrad, 1.0e-9, 1.0);
|
|
float4 scale = float4 (Scale, Scale, Scale, abs (Scale)) / minRad2;
|
|
float absScalem1 = abs (Scale - 1.0);
|
|
float AbsScaleRaisedTo1mIters = pow (abs (Scale), float (1 - mandelBoxIterations));
|
|
float DIST_MULTIPLIER = StepSize;
|
|
|
|
float4 p = float4 (pos, 1);
|
|
float4 p0 = p; // p.w is the distance estimate
|
|
|
|
for (int i = 0; i < mandelBoxIterations; i++)
|
|
{
|
|
//box folding:
|
|
p.xyz = abs (1 + p.xyz) - p.xyz - abs (1.0 - p.xyz); // add;add;abs.add;abs.add (130.4%)
|
|
p.xyz = clamp (p.xyz, Clamping.x, Clamping.y) * Clamping.z - p.xyz; // min;max;mad
|
|
|
|
// sphere folding: if (r2 < minRad2) p /= minRad2; else if (r2 < 1.0) p /= r2;
|
|
float r2 = dot (p.xyz, p.xyz);
|
|
p *= clamp (max (minRad2 / r2, minRad2), Fold.x, Fold.y); // dp3,div,max.sat,mul
|
|
p.xyz += float3 (Increment.x, Increment.y, Increment.z);
|
|
// scale, translate
|
|
p = p * scale + p0;
|
|
}
|
|
float d = ((length (p.xyz) - absScalem1) / p.w - AbsScaleRaisedTo1mIters) * DIST_MULTIPLIER;
|
|
return d;
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------
|
|
float getDistance (float3 p)
|
|
{
|
|
float d=0;
|
|
// This is test shader fragment
|
|
//p.x %= 10.4;
|
|
p.y %= 0.2;
|
|
//p.z %= 3;
|
|
d=dBox(p, float3(1,1,1)*0.1);
|
|
//d = length( p - float3(0,0,0)) /4;
|
|
//d=0;
|
|
//d=1;
|
|
// Another test
|
|
|
|
|
|
return d;
|
|
|
|
//d= max(dBox( p + float3(SpherePos.x - SpherePos.y , 0,0), float3(SpherePos.y,3,3)), dLogo );
|
|
return max(d, dBox( p + float3(0,0,0), float3(2,0.5,2)) );
|
|
}
|
|
//---------------------------------------------------
|
|
|
|
// Blinn-Phong shading model with rim lighting (diffuse light bleeding to the other side).
|
|
// |normal|, |view| and |light| should be normalized.
|
|
float3 blinn_phong (float3 normal, float3 view, float3 light, float3 diffuseColor)
|
|
{
|
|
float3 halfLV = normalize (light + view);
|
|
float clampedSpecPower = max(Spec.y, 0.001);
|
|
float spe = pow (max (dot (normal, halfLV), Spec.x), clampedSpecPower);
|
|
float dif = dot (normal, light) * 0.1 + 0.15;
|
|
return dif * diffuseColor + spe * Specular.rgb;
|
|
}
|
|
|
|
float3 getNormal (float3 p, float offset)
|
|
{
|
|
float dt = .0001;
|
|
float3 n = float3 (getDistance (p + float3 (dt, 0, 0)),
|
|
getDistance (p + float3 (0, dt, 0)),
|
|
getDistance (p + float3 (0, 0, dt))) - getDistance (p);
|
|
return normalize (n);
|
|
}
|
|
|
|
float getAO (float3 aoposition, float3 aonormal, float aodistance, float aoiterations, float aofactor)
|
|
{
|
|
float ao = 0.0;
|
|
float k = aofactor;
|
|
aodistance /= aoiterations;
|
|
for (int i = 1; i < 4; i += 1)
|
|
{
|
|
ao += (i * aodistance - getDistance (aoposition + aonormal * i * aodistance)) / pow (2, i);
|
|
}
|
|
return 1.0 - k * ao;
|
|
}
|
|
|
|
static float MAX_DIST = 300;
|
|
|
|
|
|
// Compute the color at |pos|.
|
|
float3 computeColor(float3 pos)
|
|
{
|
|
float3 p = pos, p0 = p;
|
|
float trap = 1.0;
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
p.xyz = clamp (p.xyz, -1.0, 1.0) * 2.0 - p.xyz;
|
|
float r2 = dot (p.xyz, p.xyz);
|
|
p *= clamp (max (Minrad / r2, Minrad), 0.0, 1.0);
|
|
p = p * Scale + p0.xyz;
|
|
trap = min (trap, r2);
|
|
}
|
|
// |c.x|: log final distance (fractional iteration count)
|
|
// |c.y|: spherical orbit trap at (0,0,0)
|
|
float2 c = clamp (float2 (0.33 * log (dot (p, p)) - 1.0, sqrt (trap)), 0.0, 1.0);
|
|
|
|
return lerp (lerp (Surface1.xyz, Surface2.xyz, c.y), Surface3.xyz, c.x);
|
|
}
|
|
|
|
|
|
float4 psMain (vsOutput input) : SV_TARGET
|
|
{
|
|
float3 p = input.worldTViewPos;
|
|
float3 tmpP= p;
|
|
float3 dp = normalize (input.worldTViewDir);
|
|
|
|
float totalD = 0.0;
|
|
float D = 3.4e38;
|
|
D = StepSize;
|
|
float extraD = 0.0;
|
|
float lastD;
|
|
int steps;
|
|
int maxSteps = (int)(MaxSteps - 0.5);
|
|
// Simple iterator
|
|
for (steps = 0; steps < maxSteps && abs (D) > MinDistance; steps++)
|
|
{
|
|
D = getDistance (p);
|
|
p += dp * D;
|
|
}
|
|
|
|
p += totalD * dp;
|
|
|
|
|
|
// Color the surface with Blinn-Phong shading, ambient occlusion and glow.
|
|
float3 col = Background.rgb;
|
|
float a = 1;
|
|
|
|
// We've got a hit or we're not sure.
|
|
if (D < MAX_DIST)
|
|
{
|
|
float3 n = normalize (getNormal (p, D));
|
|
//n*=float3(1,1,10);
|
|
n = normalize (n);
|
|
|
|
col = computeColor(p);
|
|
//col = blinn_phong (n, -dp, LightPos, col);
|
|
col = blinn_phong (n, -dp, LightPos, col);
|
|
|
|
col = lerp (AmbientOcclusion.rgb, col, getAO (p, n, AODistance, 3, AmbientOcclusion.a));
|
|
|
|
|
|
// We've gone through all steps, but we haven't hit anything.
|
|
// Mix in the background color.
|
|
if (D > MinDistance)
|
|
{
|
|
a = 1 - clamp (log (D / MinDistance) * DistToColor, 0.0, 1.0);
|
|
col = lerp (col, Background.rgb, a);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
a = 0.5;
|
|
}
|
|
|
|
|
|
// Glow is based on the number of steps.
|
|
col = lerp (col, Glow.rgb, float (steps) / float (MaxSteps) * Glow.a);
|
|
float f = clamp (log (length (p - input.worldTViewPos) / Fog), 0, 1);
|
|
col = lerp (col, Background.rgb, f);
|
|
a *= (1 - f * Background.a);
|
|
return float4 (col, a);
|
|
}
|