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