texture positionTexture; texture particlePositionTexture; texture normalTexture; texture densityTexture; texture diffuseTexture; texture backgroundTexture; float4x4 viewProj; float2 ddx; float2 quadddx; float3 eye; float3 eyeDir; sampler samplerPosition = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; AddressU = Clamp; AddressV = Clamp; }; sampler samplerParticlePosition = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; AddressU = Clamp; AddressV = Clamp; }; sampler samplerNormal = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; AddressU = Clamp; AddressV = Clamp; }; sampler samplerDensity = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; AddressU = Clamp; AddressV = Clamp; }; sampler samplerDiffuse = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; AddressU = Wrap; AddressV = Wrap; }; sampler samplerBackground = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; AddressU = Clamp; AddressV = Clamp; }; struct SphereInput { float4 p:position; float3 n:normal; float4 i:texcoord0; float k:texcoord1; }; struct SphereOutput { float4 q:position; float3 n:normal; float4 p:texcoord0; float4 k:texcoord1; }; struct QuadInput { float4 p:position; float2 t:texcoord0; }; struct QuadOutput { float4 p:position; float2 t:texcoord0; float4 q:texcoord1; }; struct DeferredResult { float4 position : color0; float4 normal : color1; }; struct BlurResult { float4 position : color0; float4 normal : color1; float4 density : color2; float4 particlePosition : color3; }; DeferredResult psDeferred(SphereOutput i) { DeferredResult result; result.normal = float4(i.n.xyz, 1); result.position = abs(float4(i.p.xyz, 1)); return result; } float4 psDensity(SphereOutput i) : color0 { return i.k.a; } float4 psParticlePosition(SphereOutput i) : color0 { return i.k; } void vsDeferred(SphereInput i, out SphereOutput o) { o.k.xyz = i.p.xyz * (1/0.05); o.k.a = i.k; i.p.xyz *= i.i.w; i.p.x += i.i.x; i.p.y += i.i.y; i.p.z += i.i.z; o.q = mul(i.p,viewProj); o.p = i.p; o.n = i.n; } BlurResult psBlur(QuadOutput input) { float2 SamplePos; int strength = 8; float thickness = 4; float pi4 = 3.141 * 2.0 / strength; float4 resultNormal = 0; float4 resultPosition = 0; float4 resultDensity = 0; float4 resultParticlePosition = 0; int cnt = 0; for (int i = 0; i < strength; i++) { SamplePos = input.t + ddx * thickness * float2(sin(pi4 * i), cos(pi4 * i)); resultDensity += tex2D(samplerDensity, SamplePos); resultPosition += tex2D(samplerPosition, SamplePos); resultParticlePosition += tex2D(samplerParticlePosition, SamplePos); float4 normal = tex2D(samplerNormal, SamplePos); resultNormal.a += normal.a; if (length(normal.xyz) > 0) { resultNormal.xyz += normal.xyz; cnt ++; } } resultNormal.a /= strength; if (cnt > 0) resultNormal.xyz = normalize(resultNormal.xyz / cnt); resultPosition /= strength; resultDensity /= strength; resultParticlePosition /= strength; BlurResult result; result.normal = resultNormal; result.position = resultPosition; result.density = resultDensity; result.particlePosition = resultParticlePosition; return result; } float4 psComposeDebug(QuadOutput i):color0 { float4 a = tex2D(samplerPosition, i.t); float4 b = tex2D(samplerNormal, i.t); float4 c = tex2D(samplerDensity, i.t); float4 d = tex2D(samplerParticlePosition, i.t); if (i.t.y > 0.5) { float len = length(b.xyz); if (len > 0) b.xyz /= len; if (i.t.x > 0.5) return b * a.a; if (b.a > 0) return float4(d.xyz, 1.0); return float4(1,0,0,1); } if (i.t.x > 0.5) return c; return a; } QuadOutput vsCompose(QuadInput i) { QuadOutput o; i.p.xy *= 1.0 + quadddx; o.p = i.p; o.q = i.p; o.t = i.t; return o; } float4 psCompose(QuadOutput i):color0 { float4 density = tex2D(samplerDensity, i.t); float optDensity = min(1.0, max(0, density.a - 0.1) * 10); float4 particlePosition = tex2D(samplerParticlePosition, i.t); float4 a = tex2D(samplerPosition, i.t); float4 b = tex2D(samplerNormal, i.t); float3 lightPos = float3(10,10,10); float3 lightDir = normalize(float3(1,1,0)); float3 normal = normalize(b.xyz); float3 position = a.xyz; float3 vLightDir = normalize(lightPos - position); // calc LightDirection float fDiffuse = dot(normal, vLightDir); // get diffuse float3 viewDir = normalize(a.xyz - eye); float3 vReflect = reflect(normal, lightDir); float fSpecular = dot(vReflect, normalize(viewDir)); if (fSpecular > 0) fSpecular = pow( fSpecular, 4.0) * 4; else fSpecular = 0; float fAtten = 10.0f; float LD = length(position - lightPos); fAtten *= 1.f/(0 + 1*LD + 0*LD*LD); fAtten = min(1.0f, fAtten); float lighttransfer = 0.5; float4 diffuse = (tex2D(samplerDiffuse, particlePosition.xy / 10) + tex2D(samplerDiffuse, particlePosition.xz / 10)) * 0.5; diffuse = fAtten * lerp(fDiffuse, 1.0, min(1.0, 1.0 - optDensity + lighttransfer)) * diffuse + fAtten * fSpecular; float2 tex = i.t; tex += normal.xy * optDensity * 0.05; float4 background = tex2D(samplerBackground, tex); return lerp(diffuse, background, 1.0-optDensity); } ////////////////////////////////////////////////////////////////////////////// technique Deferred { pass P0 { VertexShader = compile vs_3_0 vsDeferred(); PixelShader = compile ps_3_0 psDeferred(); } } technique Density { pass P0 { VertexShader = compile vs_3_0 vsDeferred(); PixelShader = compile ps_3_0 psDensity(); AlphaBlendEnable= TRUE; SrcBlend = ONE; DestBlend = ONE; CullMode = CCW; ZEnable = true; ZFunc = ALWAYS; ZWriteEnable = false; } } technique ParticlePosition { pass P0 { VertexShader = compile vs_3_0 vsDeferred(); PixelShader = compile ps_3_0 psParticlePosition(); AlphaBlendEnable= TRUE; SrcBlend = ONE; DestBlend = ZERO; CullMode = CCW; ZEnable = true; ZFunc = LESSEQUAL ; ZWriteEnable = true; } } technique Blur { pass P0 { VertexShader = compile vs_3_0 vsCompose(); PixelShader = compile ps_3_0 psBlur(); } } technique Compose { pass P0 { VertexShader = compile vs_3_0 vsCompose(); PixelShader = compile ps_3_0 psCompose(); } } technique ComposeDebug { pass P0 { VertexShader = compile vs_3_0 vsCompose(); PixelShader = compile ps_3_0 psComposeDebug(); } }