[3255] | 1 |
|
---|
| 2 | //-----------------------------------------------------------------------------
|
---|
| 3 | // Globals
|
---|
| 4 | //-----------------------------------------------------------------------------
|
---|
| 5 |
|
---|
| 6 | float4x4 WorldView;
|
---|
| 7 | float4x4 WorldViewProj;
|
---|
| 8 | float4x4 Proj;
|
---|
| 9 | float4x4 WorldViewIT;
|
---|
| 10 |
|
---|
| 11 |
|
---|
| 12 | float3 mLightPos;
|
---|
| 13 | float3 mCameraPos;
|
---|
| 14 | float4 mLightColor = /*float4(1.0, 1.0, 1.0, 1.0);//*/float4(0.95, 0.75, 0.6, 1.0);
|
---|
| 15 | const float frontPlane = 0.1;
|
---|
| 16 | float time;
|
---|
| 17 | float3 smokeColor = float3(0.2f, 0.2f, 0.2f);//albedo
|
---|
| 18 | float3 dustColor = float3(0.98f, 0.95f, 0.9f);//albedo
|
---|
| 19 | float3 densityFactor = float3(1, 1, 1); //r:fire, g:smoke, b:dust
|
---|
| 20 |
|
---|
| 21 | float fireTemperature;
|
---|
| 22 | float2 halfPixel;
|
---|
| 23 |
|
---|
| 24 | //-----------------------------------------------------------------------------
|
---|
| 25 | // Macro definition for filtered samplers
|
---|
| 26 | //-----------------------------------------------------------------------------
|
---|
| 27 | #define SAMPLER_LINEAR(g_samplerMap, g_txMap); \
|
---|
| 28 | sampler2D g_samplerMap = sampler_state { \
|
---|
| 29 | Texture = <g_txMap>; \
|
---|
| 30 | MinFilter = Linear; \
|
---|
| 31 | MagFilter = Linear; \
|
---|
| 32 | MipFilter = Linear; \
|
---|
| 33 | AddressU = WRAP; \
|
---|
| 34 | AddressV = WRAP; \
|
---|
| 35 | };
|
---|
| 36 |
|
---|
| 37 | //-----------------------------------------------------------------------------
|
---|
| 38 | // Macro definition for filtered 3D samplers
|
---|
| 39 | //-----------------------------------------------------------------------------
|
---|
| 40 | #define SAMPLER_LINEAR3D(g_samplerMap, g_txMap); \
|
---|
| 41 | sampler3D g_samplerMap = sampler_state { \
|
---|
| 42 | Texture = <g_txMap>; \
|
---|
| 43 | MinFilter = Linear; \
|
---|
| 44 | MagFilter = Linear; \
|
---|
| 45 | MipFilter = Linear; \
|
---|
| 46 | AddressU = WRAP; \
|
---|
| 47 | AddressV = WRAP; \
|
---|
| 48 | };
|
---|
| 49 |
|
---|
| 50 | //-----------------------------------------------------------------------------
|
---|
| 51 | // Macro definition for non-filtered samplers
|
---|
| 52 | //-----------------------------------------------------------------------------
|
---|
| 53 | #define SAMPLER_POINT(g_samplerMap, g_txMap); \
|
---|
| 54 | sampler2D g_samplerMap = sampler_state { \
|
---|
| 55 | Texture = <g_txMap>; \
|
---|
| 56 | MinFilter = Point; \
|
---|
| 57 | MagFilter = Point; \
|
---|
| 58 | MipFilter = Point; \
|
---|
| 59 | AddressU = WRAP; \
|
---|
| 60 | AddressV = WRAP; \
|
---|
| 61 | };
|
---|
| 62 |
|
---|
| 63 | //-----------------------------------------------------------------------------
|
---|
| 64 | // Textures and samplers
|
---|
| 65 | //-----------------------------------------------------------------------------
|
---|
| 66 | texture FireAlpha;
|
---|
| 67 | SAMPLER_LINEAR3D(FireAlphaSampler, FireAlpha);
|
---|
| 68 | texture SmokeAlpha;
|
---|
| 69 | SAMPLER_LINEAR3D(SmokeAlphaSampler, SmokeAlpha);
|
---|
| 70 | texture PlanckColors;
|
---|
| 71 | SAMPLER_LINEAR(PlanckColorsSampler, PlanckColors);
|
---|
| 72 | texture NoiseTexture;
|
---|
| 73 | SAMPLER_LINEAR(NoiseTextureSampler, NoiseTexture);
|
---|
| 74 | texture gradTexture;
|
---|
| 75 | SAMPLER_LINEAR(gradTextureSampler, gradTexture);
|
---|
| 76 | texture phaseTexture;
|
---|
| 77 | SAMPLER_LINEAR(PhaseSampler, phaseTexture);
|
---|
| 78 | texture SceneDepth;
|
---|
| 79 | SAMPLER_POINT(SceneDepthSampler, SceneDepth);
|
---|
| 80 |
|
---|
| 81 |
|
---|
| 82 |
|
---|
| 83 |
|
---|
| 84 | struct VertexIn
|
---|
| 85 | {
|
---|
| 86 | float4 Position :POSITION;
|
---|
| 87 | float4 TexCoord :TEXCOORD0;
|
---|
| 88 | float3 TexCoord1 :TEXCOORD1;
|
---|
| 89 | float4 Color :COLOR0;
|
---|
| 90 | };
|
---|
| 91 |
|
---|
| 92 | struct VertexOut
|
---|
| 93 | {
|
---|
| 94 | float4 hPosition :POSITION;
|
---|
| 95 | float4 TexCoord :TEXCOORD0;
|
---|
| 96 | float3 P :TEXCOORD1;
|
---|
| 97 | float3 Q :TEXCOORD2;
|
---|
| 98 | float r :TEXCOORD3;
|
---|
| 99 | float4 d :TEXCOORD4;
|
---|
| 100 | float4 position :TEXCOORD5;
|
---|
| 101 | float4 Color :TEXCOORD6;
|
---|
| 102 | float fire :TEXCOORD7;
|
---|
| 103 | };
|
---|
| 104 |
|
---|
| 105 |
|
---|
| 106 | /*
|
---|
| 107 | Vertex program for cloud rendering
|
---|
| 108 | */
|
---|
| 109 | VertexOut MainVS_SBB( VertexIn IN )
|
---|
| 110 | {
|
---|
| 111 | VertexOut Out;
|
---|
| 112 |
|
---|
| 113 | float radius = IN.TexCoord.z;
|
---|
| 114 |
|
---|
| 115 | float4 cPosition = mul(IN.Position, WorldView);
|
---|
| 116 | float3 P = cPosition.xyz;
|
---|
| 117 | float3 Q = P;
|
---|
| 118 | float3 dirP = normalize(P);
|
---|
| 119 | float3 up = float3(0, 1, 0);
|
---|
| 120 | float3 right = normalize(cross(up, dirP));
|
---|
| 121 | up = normalize(cross(dirP, right));
|
---|
| 122 | Q += IN.TexCoord.x * right * radius + IN.TexCoord.y * up * radius;
|
---|
| 123 | Out.P = P;
|
---|
| 124 | Out.Q = Q;
|
---|
| 125 |
|
---|
| 126 | //move Q back
|
---|
| 127 | float3 dirQ = normalize(Q);
|
---|
| 128 | float x = (radius + frontPlane) * length(Q) / length(P);
|
---|
| 129 | Q += dirQ;
|
---|
| 130 |
|
---|
| 131 | Out.hPosition = mul(float4(Q, 1), Proj);
|
---|
| 132 |
|
---|
| 133 | Out.position = Out.hPosition;
|
---|
| 134 | Out.TexCoord.xy = IN.TexCoord.xy * 0.5 + 0.5;
|
---|
| 135 | Out.TexCoord.zw = IN.TexCoord1.xy;
|
---|
| 136 | Out.r = radius;
|
---|
| 137 | Out.Color = IN.Color;
|
---|
| 138 | Out.d = IN.TexCoord1.z;
|
---|
| 139 | Out.fire = IN.TexCoord.w;
|
---|
| 140 |
|
---|
| 141 | return Out;
|
---|
| 142 |
|
---|
| 143 | }
|
---|
| 144 |
|
---|
| 145 | void CalculateFire(out float4 resultColor,
|
---|
| 146 | out float4 resultHeat,
|
---|
| 147 | in float3 texCoord,
|
---|
| 148 | in float2 noiseTexCoord,
|
---|
| 149 | in float alpha)
|
---|
| 150 | {
|
---|
| 151 | float a = tex3D(FireAlphaSampler, texCoord).r;
|
---|
| 152 | a *= alpha;
|
---|
| 153 | float T0 = fireTemperature;
|
---|
| 154 | float T1 = 0.2;
|
---|
| 155 | float T = T0 + T1 * a;
|
---|
| 156 | resultColor = tex2D(PlanckColorsSampler, float2(T, 0.5));
|
---|
| 157 | resultColor *= a;//blending
|
---|
| 158 | resultColor.a = 0;
|
---|
| 159 |
|
---|
| 160 | float2 heat = tex2D(NoiseTextureSampler, noiseTexCoord).rg;
|
---|
| 161 | heat = heat * 2.0 - 1.0;
|
---|
| 162 | heat *= a;
|
---|
| 163 | resultHeat = float4(heat,0, a);
|
---|
| 164 | }
|
---|
| 165 |
|
---|
| 166 | void CalculateSmoke(out float4 resultColor,
|
---|
| 167 | out float4 resultHeat,
|
---|
| 168 | in float4 Color,
|
---|
| 169 | in float3 texCoord,
|
---|
| 170 | in float alpha,
|
---|
| 171 | in float2 phaseCoord)
|
---|
| 172 | {
|
---|
| 173 | resultHeat = 0;
|
---|
| 174 |
|
---|
| 175 | float a = alpha;
|
---|
| 176 | a *= tex3D(SmokeAlphaSampler, texCoord).r; //perturb alpha
|
---|
| 177 | float phase = tex2D(PhaseSampler, phaseCoord).r; //compute phase function
|
---|
| 178 | //get the brightest color as light color from the plank texture
|
---|
| 179 | float T0 = fireTemperature;
|
---|
| 180 | float T = T0 + 0.2;
|
---|
| 181 | float4 lightColor = tex2D(PlanckColorsSampler, float2(T, 0.5));
|
---|
| 182 |
|
---|
| 183 | resultColor = float4((smokeColor * Color.g + dustColor * Color.b ), 1) * phase * lightColor;
|
---|
| 184 | resultColor *= a;//blending
|
---|
| 185 | resultColor.a = a;
|
---|
| 186 | }
|
---|
| 187 |
|
---|
| 188 | void CalculateSmokeNoPhase(out float4 resultColor,
|
---|
| 189 | out float4 resultHeat,
|
---|
| 190 | in float4 Color,
|
---|
| 191 | in float3 texCoord,
|
---|
| 192 | in float alpha)
|
---|
| 193 | {
|
---|
| 194 | resultHeat = 0;
|
---|
| 195 |
|
---|
| 196 | float a = alpha;
|
---|
| 197 | a *= tex3D(SmokeAlphaSampler, texCoord).r; //perturb alpha
|
---|
| 198 | //get the brightest color as light color from the plank texture
|
---|
| 199 | float T0 = fireTemperature;
|
---|
| 200 | float T = T0 + 0.2;
|
---|
| 201 | float4 lightColor = tex2D(PlanckColorsSampler, float2(T, 0.5));
|
---|
| 202 |
|
---|
| 203 | resultColor = float4((
|
---|
| 204 | smokeColor * Color.g //zero if dust
|
---|
| 205 | + dustColor * Color.b //zero if smoke
|
---|
| 206 | ), 1)
|
---|
| 207 | * lightColor;
|
---|
| 208 | resultColor *= a;//blending
|
---|
| 209 | resultColor.a = a;
|
---|
| 210 | }
|
---|
| 211 |
|
---|
| 212 | float Opacity(float3 P, float3 Q, float r, float2 screenCoord, float tau)
|
---|
| 213 | {
|
---|
| 214 | float alpha;
|
---|
| 215 |
|
---|
| 216 | float d = length(Q - P);
|
---|
| 217 | float Ql = length(Q);
|
---|
| 218 | float fMin = frontPlane * Ql / Q.z;
|
---|
| 219 | if(d < r)
|
---|
| 220 | {
|
---|
| 221 | float w = sqrt(r * r - d * d);
|
---|
| 222 | float Ds = tex2D(SceneDepthSampler, screenCoord).a;
|
---|
| 223 | if(Ds == 0) Ds = 1000;//farplane (needed because the distance map was cleared with 0 and not with farplane distance)
|
---|
| 224 | float F = max(Ql - w, fMin);
|
---|
| 225 | float B = min(Ql + w, Ds);
|
---|
| 226 | float ds = B - F;
|
---|
| 227 | if(ds < 0) ds = 0;
|
---|
| 228 | alpha = 1 - exp( -tau
|
---|
| 229 | //* (1.0 - d / r) //density is not homogeneous, it decreases linearly from particle center
|
---|
| 230 | * pow(1.0 - d / r, 2) //density is not homogeneous, it decreases exponentaly from particle center
|
---|
| 231 | * ds);
|
---|
| 232 | }
|
---|
| 233 | return alpha;
|
---|
| 234 | }
|
---|
| 235 |
|
---|
| 236 | /*
|
---|
| 237 | Fragment program for cloud rendering
|
---|
| 238 | */
|
---|
| 239 | void MainPS_SBB( VertexOut In,
|
---|
| 240 | out float4 Color :COLOR0,
|
---|
| 241 | out float4 Heat :COLOR1)
|
---|
| 242 | {
|
---|
| 243 | Heat = float4(0,0,0,0);
|
---|
| 244 |
|
---|
| 245 | float alpha = 0;
|
---|
| 246 |
|
---|
| 247 | float dens = length(In.Color.rgb * densityFactor);
|
---|
| 248 | if(dens < 0.1)
|
---|
| 249 | discard;
|
---|
| 250 |
|
---|
| 251 | float tau = In.Color.a * dens;
|
---|
| 252 | float2 screenPos = (In.position.xy / In.position.w * 0.5 + 0.5);
|
---|
| 253 | screenPos.y = 1.0 - screenPos.y + halfPixel;
|
---|
| 254 |
|
---|
| 255 | alpha = Opacity(In.P, In.Q, In.r, screenPos, tau);
|
---|
| 256 |
|
---|
| 257 | if(alpha == 0)
|
---|
| 258 | discard;
|
---|
| 259 |
|
---|
| 260 | if(In.fire == 0)
|
---|
| 261 | {
|
---|
| 262 | /*
|
---|
| 263 | ////With Phase function
|
---|
| 264 | float3 L = normalize(mLightPos - In.Q);
|
---|
| 265 | float3 V = normalize(- In.Q);
|
---|
| 266 | float cosW = dot(L, V);
|
---|
| 267 | float g = 0.5; //SYMMETRY = 0
|
---|
| 268 | CalculateSmoke(Color,
|
---|
| 269 | Heat,
|
---|
| 270 | In.Color,
|
---|
| 271 | float3(In.TexCoord.xy, time),
|
---|
| 272 | alpha,
|
---|
| 273 | float2(cosW * 0.5 + 0.5, g * 0.5 + 0.5));
|
---|
| 274 | //// */
|
---|
| 275 |
|
---|
| 276 | ////Without Phase function
|
---|
| 277 | CalculateSmokeNoPhase(Color,
|
---|
| 278 | Heat,
|
---|
| 279 | In.Color,
|
---|
| 280 | float3(In.TexCoord.xy, time),
|
---|
| 281 | alpha);
|
---|
| 282 | ////
|
---|
| 283 | }
|
---|
| 284 | else
|
---|
| 285 | CalculateFire(Color, Heat, float3(In.TexCoord.xy, time), In.TexCoord.xy, alpha);
|
---|
| 286 |
|
---|
| 287 |
|
---|
| 288 | }
|
---|
| 289 |
|
---|
| 290 |
|
---|
| 291 | //-----------------------------------------------------------------------------
|
---|
| 292 | // Macro definition for Techniques
|
---|
| 293 | //-----------------------------------------------------------------------------
|
---|
| 294 | #define Technique(name); \
|
---|
| 295 | technique name \
|
---|
| 296 | { \
|
---|
| 297 | pass p0 \
|
---|
| 298 | { \
|
---|
| 299 | VertexShader = compile vs_3_0 MainVS_##name(); \
|
---|
| 300 | PixelShader = compile ps_3_0 MainPS_##name(); \
|
---|
| 301 | } \
|
---|
| 302 | } \
|
---|
| 303 |
|
---|
| 304 | //-----------------------------------------------------------------------------
|
---|
| 305 | // Techniques
|
---|
| 306 | //-----------------------------------------------------------------------------
|
---|
| 307 | Technique( SBB );
|
---|