//----------------------------------------------------------------------------- // Globals //----------------------------------------------------------------------------- float4x4 WorldView; float4x4 WorldViewProj; float4x4 Proj; float4x4 WorldViewIT; float3 mLightPos; float3 mCameraPos; float4 mLightColor = /*float4(1.0, 1.0, 1.0, 1.0);//*/float4(0.95, 0.75, 0.6, 1.0); const float frontPlane = 0.1; float time; float3 smokeColor = float3(0.2f, 0.2f, 0.2f);//albedo float3 dustColor = float3(0.98f, 0.95f, 0.9f);//albedo float3 densityFactor = float3(1, 1, 1); //r:fire, g:smoke, b:dust float fireTemperature; float2 halfPixel; //----------------------------------------------------------------------------- // Macro definition for filtered samplers //----------------------------------------------------------------------------- #define SAMPLER_LINEAR(g_samplerMap, g_txMap); \ sampler2D g_samplerMap = sampler_state { \ Texture = ; \ MinFilter = Linear; \ MagFilter = Linear; \ MipFilter = Linear; \ AddressU = WRAP; \ AddressV = WRAP; \ }; //----------------------------------------------------------------------------- // Macro definition for filtered 3D samplers //----------------------------------------------------------------------------- #define SAMPLER_LINEAR3D(g_samplerMap, g_txMap); \ sampler3D g_samplerMap = sampler_state { \ Texture = ; \ MinFilter = Linear; \ MagFilter = Linear; \ MipFilter = Linear; \ AddressU = WRAP; \ AddressV = WRAP; \ }; //----------------------------------------------------------------------------- // Macro definition for non-filtered samplers //----------------------------------------------------------------------------- #define SAMPLER_POINT(g_samplerMap, g_txMap); \ sampler2D g_samplerMap = sampler_state { \ Texture = ; \ MinFilter = Point; \ MagFilter = Point; \ MipFilter = Point; \ AddressU = WRAP; \ AddressV = WRAP; \ }; //----------------------------------------------------------------------------- // Textures and samplers //----------------------------------------------------------------------------- texture FireAlpha; SAMPLER_LINEAR3D(FireAlphaSampler, FireAlpha); texture SmokeAlpha; SAMPLER_LINEAR3D(SmokeAlphaSampler, SmokeAlpha); texture PlanckColors; SAMPLER_LINEAR(PlanckColorsSampler, PlanckColors); texture NoiseTexture; SAMPLER_LINEAR(NoiseTextureSampler, NoiseTexture); texture gradTexture; SAMPLER_LINEAR(gradTextureSampler, gradTexture); texture phaseTexture; SAMPLER_LINEAR(PhaseSampler, phaseTexture); texture SceneDepth; SAMPLER_POINT(SceneDepthSampler, SceneDepth); struct VertexIn { float4 Position :POSITION; float4 TexCoord :TEXCOORD0; float3 TexCoord1 :TEXCOORD1; float4 Color :COLOR0; }; struct VertexOut { float4 hPosition :POSITION; float4 TexCoord :TEXCOORD0; float3 P :TEXCOORD1; float3 Q :TEXCOORD2; float r :TEXCOORD3; float4 d :TEXCOORD4; float4 position :TEXCOORD5; float4 Color :TEXCOORD6; float fire :TEXCOORD7; }; /* Vertex program for cloud rendering */ VertexOut MainVS_SBB( VertexIn IN ) { VertexOut Out; float radius = IN.TexCoord.z; float4 cPosition = mul(IN.Position, WorldView); float3 P = cPosition.xyz; float3 Q = P; float3 dirP = normalize(P); float3 up = float3(0, 1, 0); float3 right = normalize(cross(up, dirP)); up = normalize(cross(dirP, right)); Q += IN.TexCoord.x * right * radius + IN.TexCoord.y * up * radius; Out.P = P; Out.Q = Q; //move Q back float3 dirQ = normalize(Q); float x = (radius + frontPlane) * length(Q) / length(P); Q += dirQ; Out.hPosition = mul(float4(Q, 1), Proj); Out.position = Out.hPosition; Out.TexCoord.xy = IN.TexCoord.xy * 0.5 + 0.5; Out.TexCoord.zw = IN.TexCoord1.xy; Out.r = radius; Out.Color = IN.Color; Out.d = IN.TexCoord1.z; Out.fire = IN.TexCoord.w; return Out; } void CalculateFire(out float4 resultColor, out float4 resultHeat, in float3 texCoord, in float2 noiseTexCoord, in float alpha) { float a = tex3D(FireAlphaSampler, texCoord).r; a *= alpha; float T0 = fireTemperature; float T1 = 0.2; float T = T0 + T1 * a; resultColor = tex2D(PlanckColorsSampler, float2(T, 0.5)); resultColor *= a;//blending resultColor.a = 0; float2 heat = tex2D(NoiseTextureSampler, noiseTexCoord).rg; heat = heat * 2.0 - 1.0; heat *= a; resultHeat = float4(heat,0, a); } void CalculateSmoke(out float4 resultColor, out float4 resultHeat, in float4 Color, in float3 texCoord, in float alpha, in float2 phaseCoord) { resultHeat = 0; float a = alpha; a *= tex3D(SmokeAlphaSampler, texCoord).r; //perturb alpha float phase = tex2D(PhaseSampler, phaseCoord).r; //compute phase function //get the brightest color as light color from the plank texture float T0 = fireTemperature; float T = T0 + 0.2; float4 lightColor = tex2D(PlanckColorsSampler, float2(T, 0.5)); resultColor = float4((smokeColor * Color.g + dustColor * Color.b ), 1) * phase * lightColor; resultColor *= a;//blending resultColor.a = a; } void CalculateSmokeNoPhase(out float4 resultColor, out float4 resultHeat, in float4 Color, in float3 texCoord, in float alpha) { resultHeat = 0; float a = alpha; a *= tex3D(SmokeAlphaSampler, texCoord).r; //perturb alpha //get the brightest color as light color from the plank texture float T0 = fireTemperature; float T = T0 + 0.2; float4 lightColor = tex2D(PlanckColorsSampler, float2(T, 0.5)); resultColor = float4(( smokeColor * Color.g //zero if dust + dustColor * Color.b //zero if smoke ), 1) * lightColor; resultColor *= a;//blending resultColor.a = a; } float Opacity(float3 P, float3 Q, float r, float2 screenCoord, float tau) { float alpha; float d = length(Q - P); float Ql = length(Q); float fMin = frontPlane * Ql / Q.z; if(d < r) { float w = sqrt(r * r - d * d); float Ds = tex2D(SceneDepthSampler, screenCoord).a; if(Ds == 0) Ds = 1000;//farplane (needed because the distance map was cleared with 0 and not with farplane distance) float F = max(Ql - w, fMin); float B = min(Ql + w, Ds); float ds = B - F; if(ds < 0) ds = 0; alpha = 1 - exp( -tau //* (1.0 - d / r) //density is not homogeneous, it decreases linearly from particle center * pow(1.0 - d / r, 2) //density is not homogeneous, it decreases exponentaly from particle center * ds); } return alpha; } /* Fragment program for cloud rendering */ void MainPS_SBB( VertexOut In, out float4 Color :COLOR0, out float4 Heat :COLOR1) { Heat = float4(0,0,0,0); float alpha = 0; float dens = length(In.Color.rgb * densityFactor); if(dens < 0.1) discard; float tau = In.Color.a * dens; float2 screenPos = (In.position.xy / In.position.w * 0.5 + 0.5); screenPos.y = 1.0 - screenPos.y + halfPixel; alpha = Opacity(In.P, In.Q, In.r, screenPos, tau); if(alpha == 0) discard; if(In.fire == 0) { /* ////With Phase function float3 L = normalize(mLightPos - In.Q); float3 V = normalize(- In.Q); float cosW = dot(L, V); float g = 0.5; //SYMMETRY = 0 CalculateSmoke(Color, Heat, In.Color, float3(In.TexCoord.xy, time), alpha, float2(cosW * 0.5 + 0.5, g * 0.5 + 0.5)); //// */ ////Without Phase function CalculateSmokeNoPhase(Color, Heat, In.Color, float3(In.TexCoord.xy, time), alpha); //// } else CalculateFire(Color, Heat, float3(In.TexCoord.xy, time), In.TexCoord.xy, alpha); } //----------------------------------------------------------------------------- // Macro definition for Techniques //----------------------------------------------------------------------------- #define Technique(name); \ technique name \ { \ pass p0 \ { \ VertexShader = compile vs_3_0 MainVS_##name(); \ PixelShader = compile ps_3_0 MainPS_##name(); \ } \ } \ //----------------------------------------------------------------------------- // Techniques //----------------------------------------------------------------------------- Technique( SBB );