2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // r_surf.c: surface-related refresh code
25 drawsurf_t r_drawsurf
;
27 int lightleft
, sourcesstep
, blocksize
, sourcetstep
;
28 int lightdelta
, lightdeltastep
;
29 int lightright
, lightleftstep
, lightrightstep
, blockdivshift
;
30 unsigned blockdivmask
;
32 unsigned char *pbasesource
;
33 int surfrowbytes
; // used by ASM files
37 int r_numhblocks
, r_numvblocks
;
38 unsigned char *r_source
, *r_sourcemax
;
40 void R_DrawSurfaceBlock8_mip0 (void);
41 void R_DrawSurfaceBlock8_mip1 (void);
42 void R_DrawSurfaceBlock8_mip2 (void);
43 void R_DrawSurfaceBlock8_mip3 (void);
45 static void (*surfmiptable
[4])(void) = {
46 R_DrawSurfaceBlock8_mip0
,
47 R_DrawSurfaceBlock8_mip1
,
48 R_DrawSurfaceBlock8_mip2
,
49 R_DrawSurfaceBlock8_mip3
54 unsigned blocklights
[18*18];
61 void R_AddDynamicLights (void)
66 float dist
, rad
, minlight
;
73 surf
= r_drawsurf
.surf
;
74 smax
= (surf
->extents
[0]>>4)+1;
75 tmax
= (surf
->extents
[1]>>4)+1;
78 for (lnum
=0 ; lnum
<MAX_DLIGHTS
; lnum
++)
80 if ( !(surf
->dlightbits
& (1<<lnum
) ) )
81 continue; // not lit by this light
83 rad
= cl_dlights
[lnum
].radius
;
84 dist
= DotProduct (cl_dlights
[lnum
].origin
, surf
->plane
->normal
) -
87 minlight
= cl_dlights
[lnum
].minlight
;
90 minlight
= rad
- minlight
;
94 impact
[i
] = cl_dlights
[lnum
].origin
[i
] -
95 surf
->plane
->normal
[i
]*dist
;
98 local
[0] = DotProduct (impact
, tex
->vecs
[0]) + tex
->vecs
[0][3];
99 local
[1] = DotProduct (impact
, tex
->vecs
[1]) + tex
->vecs
[1][3];
101 local
[0] -= surf
->texturemins
[0];
102 local
[1] -= surf
->texturemins
[1];
104 for (t
= 0 ; t
<tmax
; t
++)
106 td
= local
[1] - t
*16;
109 for (s
=0 ; s
<smax
; s
++)
111 sd
= local
[0] - s
*16;
122 temp
= (rad
- dist
)*256;
124 if (!cl_dlights
[lnum
].dark
)
125 blocklights
[i
] += temp
;
128 if (blocklights
[i
] > temp
)
129 blocklights
[i
] -= temp
;
135 blocklights
[t
*smax
+ s
] += (rad
- dist
)*256;
146 Combine and scale multiple lightmaps into the 8.8 format in blocklights
149 void R_BuildLightMap (void)
159 surf
= r_drawsurf
.surf
;
161 smax
= (surf
->extents
[0]>>4)+1;
162 tmax
= (surf
->extents
[1]>>4)+1;
164 lightmap
= surf
->samples
;
166 if (r_fullbright
.value
|| !cl
.worldmodel
->lightdata
)
168 for (i
=0 ; i
<size
; i
++)
174 for (i
=0 ; i
<size
; i
++)
175 blocklights
[i
] = r_refdef
.ambientlight
<<8;
178 // add all the lightmaps
180 for (maps
= 0 ; maps
< MAXLIGHTMAPS
&& surf
->styles
[maps
] != 255 ;
183 scale
= r_drawsurf
.lightadj
[maps
]; // 8.8 fraction
184 for (i
=0 ; i
<size
; i
++)
185 blocklights
[i
] += lightmap
[i
] * scale
;
186 lightmap
+= size
; // skip to next lightmap
189 // add all the dynamic lights
190 if (surf
->dlightframe
== r_framecount
)
191 R_AddDynamicLights ();
193 // bound, invert, and shift
194 for (i
=0 ; i
<size
; i
++)
196 t
= (255*256 - (int)blocklights
[i
]) >> (8 - VID_CBITS
);
210 Returns the proper texture for a given time and base texture
213 texture_t
*R_TextureAnimation (texture_t
*base
)
218 if (currententity
->frame
)
220 if (base
->alternate_anims
)
221 base
= base
->alternate_anims
;
224 if (!base
->anim_total
)
227 reletive
= (int)(cl
.time
*10) % base
->anim_total
;
230 while (base
->anim_min
> reletive
|| base
->anim_max
<= reletive
)
232 base
= base
->anim_next
;
234 Sys_Error ("R_TextureAnimation: broken cycle");
236 Sys_Error ("R_TextureAnimation: infinite cycle");
248 void R_DrawSurface (void)
250 unsigned char *basetptr
;
251 int smax
, tmax
, twidth
;
253 int soffset
, basetoffset
, texwidth
;
255 unsigned char *pcolumndest
;
256 void (*pblockdrawer
)(void);
259 // calculate the lightings
262 surfrowbytes
= r_drawsurf
.rowbytes
;
264 mt
= r_drawsurf
.texture
;
266 r_source
= (byte
*)mt
+ mt
->offsets
[r_drawsurf
.surfmip
];
268 // the fractional light values should range from 0 to (VID_GRADES - 1) << 16
269 // from a source range of 0 - 255
271 texwidth
= mt
->width
>> r_drawsurf
.surfmip
;
273 blocksize
= 16 >> r_drawsurf
.surfmip
;
274 blockdivshift
= 4 - r_drawsurf
.surfmip
;
275 blockdivmask
= (1 << blockdivshift
) - 1;
277 r_lightwidth
= (r_drawsurf
.surf
->extents
[0]>>4)+1;
279 r_numhblocks
= r_drawsurf
.surfwidth
>> blockdivshift
;
280 r_numvblocks
= r_drawsurf
.surfheight
>> blockdivshift
;
282 //==============================
286 pblockdrawer
= surfmiptable
[r_drawsurf
.surfmip
];
287 // TODO: only needs to be set when there is a display settings change
288 horzblockstep
= blocksize
;
292 pblockdrawer
= R_DrawSurfaceBlock16
;
293 // TODO: only needs to be set when there is a display settings change
294 horzblockstep
= blocksize
<< 1;
297 smax
= mt
->width
>> r_drawsurf
.surfmip
;
299 tmax
= mt
->height
>> r_drawsurf
.surfmip
;
300 sourcetstep
= texwidth
;
301 r_stepback
= tmax
* twidth
;
303 r_sourcemax
= r_source
+ (tmax
* smax
);
305 soffset
= r_drawsurf
.surf
->texturemins
[0];
306 basetoffset
= r_drawsurf
.surf
->texturemins
[1];
308 // << 16 components are to guarantee positive values for %
309 soffset
= ((soffset
>> r_drawsurf
.surfmip
) + (smax
<< 16)) % smax
;
310 basetptr
= &r_source
[((((basetoffset
>> r_drawsurf
.surfmip
)
311 + (tmax
<< 16)) % tmax
) * twidth
)];
313 pcolumndest
= r_drawsurf
.surfdat
;
315 for (u
=0 ; u
<r_numhblocks
; u
++)
317 r_lightptr
= blocklights
+ u
;
319 prowdestbase
= pcolumndest
;
321 pbasesource
= basetptr
+ soffset
;
325 soffset
= soffset
+ blocksize
;
329 pcolumndest
+= horzblockstep
;
334 //=============================================================================
340 R_DrawSurfaceBlock8_mip0
343 void R_DrawSurfaceBlock8_mip0 (void)
345 int v
, i
, b
, lightstep
, lighttemp
, light
;
346 unsigned char pix
, *psource
, *prowdest
;
348 psource
= pbasesource
;
349 prowdest
= prowdestbase
;
351 for (v
=0 ; v
<r_numvblocks
; v
++)
353 // FIXME: make these locals?
354 // FIXME: use delta rather than both right and left, like ASM?
355 lightleft
= r_lightptr
[0];
356 lightright
= r_lightptr
[1];
357 r_lightptr
+= r_lightwidth
;
358 lightleftstep
= (r_lightptr
[0] - lightleft
) >> 4;
359 lightrightstep
= (r_lightptr
[1] - lightright
) >> 4;
361 for (i
=0 ; i
<16 ; i
++)
363 lighttemp
= lightleft
- lightright
;
364 lightstep
= lighttemp
>> 4;
368 for (b
=15; b
>=0; b
--)
371 prowdest
[b
] = ((unsigned char *)vid
.colormap
)
372 [(light
& 0xFF00) + pix
];
376 psource
+= sourcetstep
;
377 lightright
+= lightrightstep
;
378 lightleft
+= lightleftstep
;
379 prowdest
+= surfrowbytes
;
382 if (psource
>= r_sourcemax
)
383 psource
-= r_stepback
;
390 R_DrawSurfaceBlock8_mip1
393 void R_DrawSurfaceBlock8_mip1 (void)
395 int v
, i
, b
, lightstep
, lighttemp
, light
;
396 unsigned char pix
, *psource
, *prowdest
;
398 psource
= pbasesource
;
399 prowdest
= prowdestbase
;
401 for (v
=0 ; v
<r_numvblocks
; v
++)
403 // FIXME: make these locals?
404 // FIXME: use delta rather than both right and left, like ASM?
405 lightleft
= r_lightptr
[0];
406 lightright
= r_lightptr
[1];
407 r_lightptr
+= r_lightwidth
;
408 lightleftstep
= (r_lightptr
[0] - lightleft
) >> 3;
409 lightrightstep
= (r_lightptr
[1] - lightright
) >> 3;
411 for (i
=0 ; i
<8 ; i
++)
413 lighttemp
= lightleft
- lightright
;
414 lightstep
= lighttemp
>> 3;
421 prowdest
[b
] = ((unsigned char *)vid
.colormap
)
422 [(light
& 0xFF00) + pix
];
426 psource
+= sourcetstep
;
427 lightright
+= lightrightstep
;
428 lightleft
+= lightleftstep
;
429 prowdest
+= surfrowbytes
;
432 if (psource
>= r_sourcemax
)
433 psource
-= r_stepback
;
440 R_DrawSurfaceBlock8_mip2
443 void R_DrawSurfaceBlock8_mip2 (void)
445 int v
, i
, b
, lightstep
, lighttemp
, light
;
446 unsigned char pix
, *psource
, *prowdest
;
448 psource
= pbasesource
;
449 prowdest
= prowdestbase
;
451 for (v
=0 ; v
<r_numvblocks
; v
++)
453 // FIXME: make these locals?
454 // FIXME: use delta rather than both right and left, like ASM?
455 lightleft
= r_lightptr
[0];
456 lightright
= r_lightptr
[1];
457 r_lightptr
+= r_lightwidth
;
458 lightleftstep
= (r_lightptr
[0] - lightleft
) >> 2;
459 lightrightstep
= (r_lightptr
[1] - lightright
) >> 2;
461 for (i
=0 ; i
<4 ; i
++)
463 lighttemp
= lightleft
- lightright
;
464 lightstep
= lighttemp
>> 2;
471 prowdest
[b
] = ((unsigned char *)vid
.colormap
)
472 [(light
& 0xFF00) + pix
];
476 psource
+= sourcetstep
;
477 lightright
+= lightrightstep
;
478 lightleft
+= lightleftstep
;
479 prowdest
+= surfrowbytes
;
482 if (psource
>= r_sourcemax
)
483 psource
-= r_stepback
;
490 R_DrawSurfaceBlock8_mip3
493 void R_DrawSurfaceBlock8_mip3 (void)
495 int v
, i
, b
, lightstep
, lighttemp
, light
;
496 unsigned char pix
, *psource
, *prowdest
;
498 psource
= pbasesource
;
499 prowdest
= prowdestbase
;
501 for (v
=0 ; v
<r_numvblocks
; v
++)
503 // FIXME: make these locals?
504 // FIXME: use delta rather than both right and left, like ASM?
505 lightleft
= r_lightptr
[0];
506 lightright
= r_lightptr
[1];
507 r_lightptr
+= r_lightwidth
;
508 lightleftstep
= (r_lightptr
[0] - lightleft
) >> 1;
509 lightrightstep
= (r_lightptr
[1] - lightright
) >> 1;
511 for (i
=0 ; i
<2 ; i
++)
513 lighttemp
= lightleft
- lightright
;
514 lightstep
= lighttemp
>> 1;
521 prowdest
[b
] = ((unsigned char *)vid
.colormap
)
522 [(light
& 0xFF00) + pix
];
526 psource
+= sourcetstep
;
527 lightright
+= lightrightstep
;
528 lightleft
+= lightleftstep
;
529 prowdest
+= surfrowbytes
;
532 if (psource
>= r_sourcemax
)
533 psource
-= r_stepback
;
542 FIXME: make this work
545 void R_DrawSurfaceBlock16 (void)
548 unsigned char *psource
;
549 int lighttemp
, lightstep
, light
;
550 unsigned short *prowdest
;
552 prowdest
= (unsigned short *)prowdestbase
;
554 for (k
=0 ; k
<blocksize
; k
++)
556 unsigned short *pdest
;
560 psource
= pbasesource
;
561 lighttemp
= lightright
- lightleft
;
562 lightstep
= lighttemp
>> blockdivshift
;
567 for (b
=0; b
<blocksize
; b
++)
570 *pdest
= vid
.colormap16
[(light
& 0xFF00) + pix
];
571 psource
+= sourcesstep
;
576 pbasesource
+= sourcetstep
;
577 lightright
+= lightrightstep
;
578 lightleft
+= lightleftstep
;
579 prowdest
= (unsigned short *)((long)prowdest
+ surfrowbytes
);
582 prowdestbase
= prowdest
;
588 //============================================================================
595 void R_GenTurbTile (pixel_t
*pbasetex
, void *pdest
)
601 turb
= sintable
+ ((int)(cl
.time
*SPEED
)&(CYCLE
-1));
604 for (i
=0 ; i
<TILE_SIZE
; i
++)
606 for (j
=0 ; j
<TILE_SIZE
; j
++)
608 s
= (((j
<< 16) + turb
[i
& (CYCLE
-1)]) >> 16) & 63;
609 t
= (((i
<< 16) + turb
[j
& (CYCLE
-1)]) >> 16) & 63;
610 *pd
++ = *(pbasetex
+ (t
<<6) + s
);
621 void R_GenTurbTile16 (pixel_t
*pbasetex
, void *pdest
)
627 turb
= sintable
+ ((int)(cl
.time
*SPEED
)&(CYCLE
-1));
628 pd
= (unsigned short *)pdest
;
630 for (i
=0 ; i
<TILE_SIZE
; i
++)
632 for (j
=0 ; j
<TILE_SIZE
; j
++)
634 s
= (((j
<< 16) + turb
[i
& (CYCLE
-1)]) >> 16) & 63;
635 t
= (((i
<< 16) + turb
[j
& (CYCLE
-1)]) >> 16) & 63;
636 *pd
++ = d_8to16table
[*(pbasetex
+ (t
<<6) + s
)];
647 void R_GenTile (msurface_t
*psurf
, void *pdest
)
649 if (psurf
->flags
& SURF_DRAWTURB
)
653 R_GenTurbTile ((pixel_t
*)
654 ((byte
*)psurf
->texinfo
->texture
+ psurf
->texinfo
->texture
->offsets
[0]), pdest
);
658 R_GenTurbTile16 ((pixel_t
*)
659 ((byte
*)psurf
->texinfo
->texture
+ psurf
->texinfo
->texture
->offsets
[0]), pdest
);
662 else if (psurf
->flags
& SURF_DRAWSKY
)
666 R_GenSkyTile (pdest
);
670 R_GenSkyTile16 (pdest
);
675 Sys_Error ("Unknown tile type");