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 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); }