-
Notifications
You must be signed in to change notification settings - Fork 0
/
radiosity_fx.v3
475 lines (393 loc) · 15.1 KB
/
radiosity_fx.v3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
#define MAP_SIZE 512
#define SHADOWMAP_SIZE 256
#define EPSILON 0.00005f
// nota: convenciones de las variables
// las globales para efectos empiezan con g_ luego viene el tipo y el nombre de la variable
// m = matrices
// v = vector
// f = float
// tx = textura
// sam = samplers
float4x4 g_mWorldView;
float4x4 g_mProj;
texture g_txScene; // textura para la escena
texture g_txShadow; // textura para el shadow map
float3 g_vLightPos; // posicion de la luz (en World Space) = pto que representa patch emisor Bj
float3 g_vLightDir; // Direcion de la luz (en World Space) = normal al patch Bj
float4x4 g_mObjWorld; // matrix world del objeto
float g_fIL = 1.0f; // Intensidad luminosa del patch actual
texture g_txRMap; // Mapa de Radiance
texture g_txGMap; // Mapa de Radiance
texture g_txBMap; // Mapa de Radiance
// Cada texel esta relacionado con un vertice
// el valor del mismo representa la cantidad de luz acumulada en ese patch
texture g_txRayT; // Mapa de Intersecciones
float g_fTime = 0;
int ondas = 0;
int g_iCanal = 0;
sampler2D g_samScene =
sampler_state
{
Texture = <g_txScene>;
MinFilter = Point;
MagFilter = Linear;
MipFilter = Linear;
};
sampler2D g_samShadow =
sampler_state
{
Texture = <g_txShadow>;
MinFilter = Point;
MagFilter = Point;
MipFilter = NONE;
AddressU = Clamp;
AddressV = Clamp;
};
sampler2D g_samRMap =
sampler_state
{
Texture = <g_txRMap>;
MinFilter = POINT;
MagFilter = POINT;
MipFilter = NONE;
AddressU = Clamp;
AddressV = Clamp;
};
sampler2D g_samGMap =
sampler_state
{
Texture = <g_txGMap>;
MinFilter = POINT;
MagFilter = POINT;
MipFilter = NONE;
AddressU = Clamp;
AddressV = Clamp;
};
sampler2D g_samBMap =
sampler_state
{
Texture = <g_txBMap>;
MinFilter = POINT;
MagFilter = POINT;
MipFilter = NONE;
AddressU = Clamp;
AddressV = Clamp;
};
sampler2D g_samRayT =
sampler_state
{
Texture = <g_txRayT>;
MinFilter = Point;
MagFilter = Point;
MipFilter = NONE;
};
//-----------------------------------------------------------------------------
// Vertex Shader para dibujar la escena pp dicha
//-----------------------------------------------------------------------------
void VertScene( float4 iPos : POSITION,
float3 iNormal : NORMAL,
float2 iTex : TEXCOORD0,
float2 iId : TEXCOORD1,
float2 iId2 : TEXCOORD2,
float2 iId3 : TEXCOORD3,
out float4 oPos : POSITION,
out float4 Diffuse : COLOR0,
out float2 Tex : TEXCOORD0,
out float2 Id : TEXCOORD1)
{
// tx ondas
/*
if(ondas!=-1)
{
float a0 = 4*g_fTime;
float r;
if(ondas>=2)
{
// pared de atras
float k = 3.1415/20.0;
r = (sin(a0+k*iPos.x)+sin(a0+k*iPos.y))*1;
}
else
{
// resto
float k = 3.1415*0.5;
r = (sin(a0+k*iPos.x) + sin(a0+k*iPos.z))*0.1;
}
iPos += float4(iNormal,0)*r;
}*/
// transformo al view space
float4 vPos = mul( iPos, g_mWorldView );
// y ahora a screen space
oPos = mul( vPos, g_mProj );
// obtengo el valor de radiance asociado al vertice
// (ojo que la textura tiene un formato D3DFMT_R32F,
// con lo cual el valor es un float32 en el canal R
Diffuse.r = tex2Dlod( g_samRMap, float4(iId/MAP_SIZE,0,0)).r;
Diffuse.g = tex2Dlod( g_samGMap, float4(iId/MAP_SIZE,0,0)).r;
Diffuse.b = tex2Dlod( g_samBMap, float4(iId/MAP_SIZE,0,0)).r;
Diffuse.a = 1;
/*
Diffuse.r += tex2Dlod( g_samRMap, float4(iId2/MAP_SIZE,0,0)).r*0.1;
Diffuse.g += tex2Dlod( g_samGMap, float4(iId2/MAP_SIZE,0,0)).r*0.1;
Diffuse.b += tex2Dlod( g_samBMap, float4(iId2/MAP_SIZE,0,0)).r*0.1;
Diffuse.r += tex2Dlod( g_samRMap, float4(iId3/MAP_SIZE,0,0)).r*0.1;
Diffuse.g += tex2Dlod( g_samGMap, float4(iId3/MAP_SIZE,0,0)).r*0.1;
Diffuse.b += tex2Dlod( g_samBMap, float4(iId3/MAP_SIZE,0,0)).r*0.1;
*/
// propago coordenadas de textura y Id
Tex = iTex;
Id = iId;
}
//-----------------------------------------------------------------------------
// Pixel Shader para dibujar la escena
//-----------------------------------------------------------------------------
float4 PixScene( float4 Diffuse : COLOR0,
float2 Tex : TEXCOORD0,
float4 vId : TEXCOORD1) : COLOR
{
return tex2D( g_samScene, Tex )*Diffuse;
}
//-----------------------------------------------------------------------------
// Vertex y Pixel Shader para dibujar la flechita que representa el rayo de luz
//-----------------------------------------------------------------------------
void VertFlecha( float4 iPos : POSITION,
float3 iNormal : NORMAL,
out float4 oPos : POSITION)
{
oPos = mul( iPos, g_mWorldView );
oPos = mul( oPos, g_mProj );
}
float4 PixFlecha( float4 vPos : TEXCOORD1 ) : COLOR
{
return float4(1,1,0,0);
}
//-----------------------------------------------------------------------------
// Vertex Shader que implementa un shadow map. Lo necesito para calcular
// el valor de la funcion de visibilidad de la ecuacion de radiosity
//-----------------------------------------------------------------------------
void VertShadow( float4 Pos : POSITION,
float3 Normal : NORMAL,
out float4 oPos : POSITION,
out float2 Depth : TEXCOORD0 )
{
// transformacion estandard
oPos = mul( Pos, g_mWorldView );
oPos = mul( oPos, g_mProj );
// devuelvo: profundidad = z/w
Depth.xy = oPos.zw;
}
//-----------------------------------------------------------------------------
// Pixel Shader para el shadow map, dibuja la "profundidad"
//-----------------------------------------------------------------------------
void PixShadow( float2 Depth : TEXCOORD0,out float4 Color : COLOR )
{
Color = Depth.x / Depth.y;
}
//-----------------------------------------------------------------------------
// Vertex Shader para procesar cada vertice. Calcula la ecuacion de radiosity
//-----------------------------------------------------------------------------
void VertMapR( float4 Pos : POSITION,
float3 iNormal : NORMAL,
float2 iId : TEXCOORD1,
out float Diffuse : COLOR0,
out float4 oPos : POSITION,
out float2 oId : TEXCOORD1 )
{
float I = 0; // intensidad de flujo de luz
// nota: todos los calculos se realizan en el World Space
// Necesito la posicion del vertice real (en World Space)
// para ello multiplico por la matrix World asociada al objeto
// vPos = pos real del vertice en el World
float4 vPos = mul( Pos, g_mObjWorld);
// nota: para acelerar podria ya tener calculada la normal x el objworld
iNormal = normalize(mul( iNormal, g_mObjWorld));
float3 vRayo_ij = normalize( float3( vPos - g_vLightPos ) );
// vRayo_ij es el vector que va desde la posicion del patch Bj (que representa una luz)
// hasta el vertice actual, que estoy calulando que es el patch Bi
// verifico que el vertice este del lado correcto del hemisferio y calculo el form factor
if(dot( vRayo_ij, g_vLightDir)>0.01)
{
// ecuacion de Radiosity
// (j es la superficie emisora y i es la que esta recibiendo la luz)
// Bi = Ei + ri Sum (Bj * Fij)
// Bi = Radiosidad de la superficie i
// Ei = Emision superficie i
// ri = reflectividad de la sup i
// Bj = Radiosidad de la superficie j
// Fij = Form factor de la superficie j relativa a la superficie i
// se consideran que la superficies i es lo suf. pequeña, y la j es un infenitesimo.
// hay que verlo como un punto.
// en nuestro caso en el primer paso:
// Ei = 0 para todos las superficies, menos para la primer luz
// luego, Ei sale de la textura que usamos para almacenar la radiosidad
// ri = 1 y a otra cosa
// Bi = text2d(indice2d(i),g_txRMap)
// y el form factor se calcula asi:
// si vRayo_ij es el vector que une el pto en la superficie i con la superficie emisora j
// Fij = cos(an_i)*(an_j)/(pi*||vRayo_ij||)*Vij
// an_i = angulo entre la normal de la superficie i y el vector vRayo_ij (an_j = idem j)
// Vij es un factor de visibilidad, que indica si la superficie j que emite la luz
// es visible desde la punto i, y por lo tanto se definie como
// Vij = 1 si j es visible desde i, o 0 caso contrario
// en nuestro caso:
// la division por pi, surge de integrar la ecuacion en el area, y lo eliminamos directamente
// (no queremos un resultado exacto, eso se usa cuando se necesita el valor exacto de
// radicion en un cierto punto)
// de la misma forma la norma de vRayo_ij es muy cara de conseguir y la vamos a desestimar
// (responde a que la intesidad de la luz decrece con el cuadrado de la distancia)
// por otra parte, como no podemos calcular todas las luces se produce que en general
// la imagen queda mas oscura de lo que deberia, y por eso multiplico por 2 la ecuacion
// con lo cual nuestro form factor simplificado queda asi (sin el factor de visibilidad)
// Fij = 2*cos(an_i)*(an_j)
// Este ff depende de la orientacion relativa de ambas superficies
float ff = saturate(4*dot(-vRayo_ij,iNormal)*dot(g_vLightDir,vRayo_ij));
// para calcular el V(i,j) tengo que acceder al shadow map
// se supone que estoy dibujando desde el pto de vista de la luz
float4 vPosLight = mul( Pos, g_mWorldView );
vPosLight = mul( vPosLight, g_mProj );
// transformo del espacio de la pantalla al espacio de la textura para poder acceder al mapa
float2 auxCoord = 0.5 * vPosLight.xy / vPosLight.w + float2( 0.5, 0.5 );
auxCoord.y = 1.0f - auxCoord.y;
// leo el shadow map pp dicho
I = (tex2Dlod( g_samShadow, float4(auxCoord,0,0)) + EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f;
// interpolacion standard bi-lineal del shadow map
/*
// auxCoord va de 0 a 1, lo multiplico x el tamaño de la textura
// la parte fraccionaria indica cuanto tengo que tomar del vecino
float2 vecino = frac( auxCoord*MAP_SIZE);
// leo 4 valores
float s0 = (tex2Dlod( g_samShadow, float4(auxCoord,0,0)) + EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f;
float s1 = (tex2Dlod( g_samShadow, float4(auxCoord+ float2(1.0/SHADOWMAP_SIZE,0),0,0))
+ EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f;
float s2 = (tex2Dlod( g_samShadow, float4(auxCoord+ float2(0,1.0/SHADOWMAP_SIZE),0,0))
+ EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f;
float s3 = (tex2Dlod( g_samShadow, float4(auxCoord+ float2(1.0/SHADOWMAP_SIZE,1.0/SHADOWMAP_SIZE),0,0))
+ EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f;
I = lerp( lerp( s0, s1, vecino.x ),lerp( s2, s3, vecino.x ),vecino.y);
*/
// penumbra
/*
float r = 10;
I = 0.25*((tex2Dlod( g_samShadow, float4(auxCoord,0,0)) + EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f);
I += 0.25*((tex2Dlod( g_samShadow, float4(auxCoord + float2((float)r/SHADOWMAP_SIZE, (float)r/SHADOWMAP_SIZE),0,0) )
+ EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f);
I += 0.25*((tex2Dlod( g_samShadow, float4(auxCoord + float2((float)r/SHADOWMAP_SIZE, 0),0,0) )
+ EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f);
I += 0.25*((tex2Dlod( g_samShadow, float4(auxCoord + float2(0, (float)r/SHADOWMAP_SIZE),0,0) )
+ EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f);
*/
/*
// anti-aliasing del shadowmap
float I2 = 0;
float r = 3;
for(int i=-r;i<=r;++i)
for(int j=-r;j<=r;++j)
I2 += (tex2Dlod( g_samShadow, float4(auxCoord + float2((float)(i*2)/SHADOWMAP_SIZE, (float)(j*2)/SHADOWMAP_SIZE),0,0) )
+ EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f;
I2 /= (2*r+1)*(2*r+1);
I = I*0.2 + I2*0.8;
*/
I*=ff;
}
// Artificio para usar una textura como una matriz para almacenar datos
// necesito que la posicion proyectada, "caiga" en la pos i,j de pantalla,
// que representa luego la textura
oPos.x = 2*iId.x/MAP_SIZE-1;
oPos.y = 1-2*iId.y/MAP_SIZE;
oPos.z = 1;
oPos.w = 1;
// Propago el id
oId = iId;
// Propago I, usando el color asociado al vertice, ademas multiplico x
// la intensidad de la luz actual
Diffuse = I*g_fIL;
}
void PixMapR( float Diffuse: COLOR0,float2 id : TEXCOORD1,out float4 Color : COLOR0 )
{
if(g_iCanal==0)
Color = tex2D( g_samRMap, id/MAP_SIZE).r + Diffuse;
else
if(g_iCanal==1)
Color = tex2D( g_samGMap, id/MAP_SIZE).r + Diffuse;
else
Color = tex2D( g_samBMap, id/MAP_SIZE).r + Diffuse;
}
//-----------------------------------------------------------------------------
// Vertex Shader que sirve para reemplazar el raytracing de los rebotes de la luz
//-----------------------------------------------------------------------------
void VertRayT( float4 iPos : POSITION,
float3 iNormal : NORMAL,
float2 iId : TEXCOORD1,
out float4 oPos : POSITION,
out float4 Diffuse : COLOR0,
out float2 oId : TEXCOORD1)
{
// transformacion estandard
float4 vPos = mul( iPos, g_mWorldView );
oPos = mul( vPos, g_mProj );
iNormal = normalize(mul( iNormal, g_mObjWorld));
float I = dot(iNormal,-g_vLightDir);
// prueba para ver que sale
Diffuse.rgb = I;
Diffuse.a = 1;
// propago el Id
oId = iId;
}
void PixRayT( float4 Diffuse : COLOR0,float2 iId : TEXCOORD1,out float4 Color : COLOR )
{
// el formato de la textura de salida es D3DFMT_G16R16
// por eso divido el id por 65535
//Color = Diffuse;
Color.rg = iId/65535.0;
Color.b = 0;
Color.a = 0;
}
//-----------------------------------------------------------------------------
// Technique: RenderScene
// Desc: Renders scene objects
//-----------------------------------------------------------------------------
technique RenderScene
{
pass p0
{
VertexShader = compile vs_3_0 VertScene();
PixelShader = compile ps_3_0 PixScene();
}
}
// ShadowMap estandard, para calcular el factor de visibilidad V(i,j)
technique RenderShadow
{
pass p0
{
VertexShader = compile vs_3_0 VertShadow();
PixelShader = compile ps_3_0 PixShadow();
}
}
// Paso del algoritmo de Radiosity. Por cada vertice, se calcula la cantidad de energia
// que entra, y se acumula con el valor anterior. Generando asi un mapa de "Radiacion"
technique RadianceMap
{
pass p0
{
VertexShader = compile vs_3_0 VertMapR();
PixelShader = compile ps_3_0 PixMapR();
}
}
// dibuja la flechita, que representa el rayo casteado
technique RenderFlecha
{
pass p0
{
VertexShader = compile vs_3_0 VertFlecha();
PixelShader = compile ps_3_0 PixFlecha();
}
}
// RayTray
technique RayTracing
{
pass p0
{
VertexShader = compile vs_3_0 VertRayT();
PixelShader = compile ps_3_0 PixRayT();
}
}