1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: r_draw24.c 902 2012-02-29 07:30:00Z wesleyjohnson $
5 //
6 // Copyright (C) 2012-2012 by DooM Legacy Team.
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; either version 2
11 // of the License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 //
19 // DESCRIPTION:
20 // 24bpp span/column drawer functions
21 //
22 // NOTE: no includes because this is included as part of r_draw.c
23 //
24 //-----------------------------------------------------------------------------
25
26
27 // ==========================================================================
28 // COLUMNS
29 // ==========================================================================
30
31 // r_data.c
32 // include: color8.to32
33
34
35 // 24bpp composite (ENABLE_DRAW24) is 8:8:8
36 // color_8.to32 color is aligned with pix24 for speed
37
38 // standard upto 128high posts column drawer
39 //
R_DrawColumn_24(void)40 void R_DrawColumn_24 (void)
41 {
42 unsigned int heightmask = dc_texheight - 1;
43 int count;
44 byte * dest; // within screen buffer
45 fixed_t frac;
46 fixed_t fracstep;
47 pixelunion32_t c32;
48
49 count = dc_yh - dc_yl+1;
50
51 // Zero length, column does not exceed a pixel.
52 if (count <= 0)
53 return;
54
55 #ifdef RANGECHECK_DRAW_LIMITS
56 if ((unsigned)dc_x >= vid.width
57 || dc_yl < 0
58 || dc_yh >= vid.height)
59 {
60 I_SoftError ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
61 return;
62 }
63 #endif
64
65 // Screen buffer destination address.
66 // Use ylookup LUT to avoid multiply with ScreenWidth.
67 dest = ylookup[dc_yl] + columnofs[dc_x];
68
69 // Determine scaling, which is the only mapping to be done.
70 fracstep = dc_iscale;
71 frac = dc_texturemid + (dc_yl-centery)*fracstep;
72
73 if( dc_texheight & heightmask )
74 {
75 // Odd size texture, use texheight
76 fixed_t texheight = dc_texheight << FRACBITS;
77 // Inner loop that does the actual texture mapping.
78 do
79 {
80 // Re-map color indices from wall texture column
81 // using a lighting/special effects LUT.
82 c32.ui32 = color8.to32[ dc_colormap[ dc_source[(frac>>FRACBITS)] ] ];
83 *(pixel24_t*)dest = c32.pix24;
84 dest += vid.ybytes;
85 frac += fracstep;
86 if( frac >= texheight )
87 frac -= texheight;
88 } while (--count);
89 }
90 else
91 {
92 // Inner loop that does the actual texture mapping.
93 do
94 {
95 // Re-map color indices from wall texture column
96 // using a lighting/special effects LUT.
97 c32.ui32 = color8.to32[ dc_colormap[ dc_source[(frac>>FRACBITS)&heightmask] ] ];
98 *(pixel24_t*)dest = c32.pix24;
99 dest += vid.ybytes;
100 frac += fracstep;
101 } while (--count);
102 }
103 }
104
105
106 // Same as R_DrawColumn_24 but wraps around 256
107 // instead of 128 for the tall sky textures (256x240)
108 //
R_DrawSkyColumn_24(void)109 void R_DrawSkyColumn_24 (void)
110 {
111 int count;
112 byte * dest; // within screen buffer
113 fixed_t frac;
114 fixed_t fracstep;
115 pixelunion32_t c32;
116
117 count = dc_yh - dc_yl+1;
118
119 // Zero length, column does not exceed a pixel.
120 if (count <= 0)
121 return;
122
123 #ifdef RANGECHECK_DRAW_LIMITS
124 if ((unsigned)dc_x >= vid.width
125 || dc_yl < 0
126 || dc_yh >= vid.height)
127 {
128 I_SoftError ("R_DrawSkyColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
129 return;
130 }
131 #endif
132
133 dest = ylookup[dc_yl] + columnofs[dc_x];
134
135 fracstep = dc_iscale;
136 frac = dc_texturemid + (dc_yl-centery)*fracstep;
137
138 do
139 {
140 c32.ui32 = color8.to32[ dc_colormap[ dc_source[(frac>>FRACBITS)&255] ] ];
141 *(pixel24_t*)dest = c32.pix24;
142 dest += vid.ybytes;
143 frac += fracstep;
144 } while (--count);
145 }
146
147
R_DrawFuzzColumn_24(void)148 void R_DrawFuzzColumn_24 (void)
149 {
150 int count;
151 byte* dest;
152
153 // Adjust borders. Low...
154 if (!dc_yl)
155 dc_yl = 1;
156
157 // .. and high.
158 if (dc_yh == rdraw_viewheight-1)
159 dc_yh = rdraw_viewheight - 2;
160
161 count = dc_yh - dc_yl;
162
163 // Zero length.
164 if (count < 0)
165 return;
166
167
168 #ifdef RANGECHECK_DRAW_LIMITS
169 if ((unsigned)dc_x >= vid.width
170 || dc_yl < 0 || dc_yh >= vid.height)
171 {
172 I_SoftError ("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
173 return;
174 }
175 #endif
176
177 // Does not work with blocky mode.
178 dest = ylookup[dc_yl] + columnofs[dc_x];
179
180 do
181 {
182 // Retrieve a pixel that is either one column left or right
183 // of the dest, dim it 8%, and write it as dest.
184 // 8bpp: *dest = reg_colormaps[6*256+dest[fuzzoffset[fuzzpos]]];
185 register pixel24_t * src = (pixel24_t*)(dest + fuzzoffset[fuzzpos]);
186 ((pixel24_t*)dest)->b = src->b - (src->b >> 3);
187 ((pixel24_t*)dest)->g = src->g - (src->g >> 3);
188 ((pixel24_t*)dest)->r = src->r - (src->r >> 3);
189
190 dest += vid.ybytes;
191 // Clamp table lookup index.
192 if (++fuzzpos == FUZZTABLE)
193 fuzzpos = 0;
194 } while (count--);
195 }
196
197
198 // To draw FF_SMOKESHADE things, sprite is an \alpha channel
R_DrawShadeColumn_24(void)199 void R_DrawShadeColumn_24(void)
200 {
201 fixed_t texheight = dc_texheight << FRACBITS; // any texture size
202 int count;
203 register byte *dest;
204 register fixed_t frac;
205 register fixed_t fracstep;
206 unsigned int alpha;
207
208 // [WDJ] Source check has been added to all the callers of colfunc().
209
210 count = dc_yh - dc_yl;
211 if (count < 0)
212 return;
213
214 #ifdef RANGECHECK_DRAW_LIMITS
215 if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
216 {
217 I_SoftError("R_DrawShadeColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
218 return;
219 }
220 #endif
221
222 // FIXME. As above.
223 dest = ylookup[dc_yl] + columnofs[dc_x];
224
225 // Looks familiar.
226 fracstep = dc_iscale;
227 frac = dc_texturemid + (dc_yl - centery) * fracstep;
228 if (texheight > 0) // hangs when texheight==0
229 {
230 // From Boom, to fix the odd frac
231 if (frac < 0)
232 while ((frac += texheight) < 0);
233 else
234 while (frac >= texheight) frac -= texheight;
235 }
236
237 do
238 {
239 // 8bpp: *dest = reg_colormaps[ LIGHTTABLE(dc_source[frac >> FRACBITS]) + (*dest) ];
240 // [WDJ] The source is a patch of alpha values, 0..255..
241 // light level values are 0..NUMCOLORMAPS-1, which is 0..32
242 // alpha = dc_source[frac >> FRACBITS] >> 3; // reduce 0..255 to 0..32
243 alpha = dc_source[frac >> FRACBITS];
244 register pixel24_t * p24 = (pixel24_t*)dest;
245 p24->b = (p24->b * alpha) >> 5;
246 p24->g = (p24->g * alpha) >> 5;
247 p24->r = (p24->r * alpha) >> 5;
248
249 dest += vid.ybytes;
250 frac += fracstep;
251 if( frac >= texheight )
252 frac -= texheight;
253 }
254 while (count--);
255 }
256
257
258 #ifdef ENABLE_DRAW_ALPHA
R_DrawAlphaColumn_24(void)259 void R_DrawAlphaColumn_24(void)
260 {
261 #if 0
262 fixed_t texheight = dc_texheight << FRACBITS; // any texture size
263 #endif
264 int count;
265 register byte *dest;
266 register fixed_t frac;
267 register fixed_t fracstep;
268 unsigned int alpha, alpha_r;
269
270 // [WDJ] Source check has been added to all the callers of colfunc().
271
272 count = dc_yh - dc_yl;
273 if (count < 0)
274 return;
275
276 #ifdef RANGECHECK_DRAW_LIMITS
277 if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
278 {
279 I_SoftError("R_DrawAlphaColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
280 return;
281 }
282 #endif
283
284 dest = ylookup[dc_yl] + columnofs[dc_x];
285 fracstep = dc_iscale;
286 frac = dc_texturemid + (dc_yl - centery) * fracstep;
287
288 #if 0
289 // [WDJ] Only draws sprite for now.
290 if (texheight > 0) // hangs when texheight==0
291 {
292 // From Boom, to fix the odd frac
293 if (frac < 0)
294 while ((frac += texheight) < 0);
295 else
296 while (frac >= texheight) frac -= texheight;
297 }
298 #endif
299
300 switch( dr_alpha_mode )
301 {
302
303 case 0: // Alpha blend
304 do
305 {
306 // [WDJ] The source is a patch of alpha values, 0..255.
307 alpha = (dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) >> 8;
308 alpha_r = 255 - alpha;
309 register pixel24_t * p24 = (pixel24_t*)dest;
310 p24->b = ((p24->b * alpha_r) + (dr_color.s.blue * alpha)) >> 8;
311 p24->g = ((p24->g * alpha_r) + (dr_color.s.green * alpha)) >> 8;
312 p24->r = ((p24->r * alpha_r) + (dr_color.s.red * alpha)) >> 8;
313
314 dest += vid.ybytes;
315 frac += fracstep;
316 #if 0
317 if( frac >= texheight )
318 frac -= texheight;
319 #endif
320 }
321 while (count--);
322 break;
323
324 case 1: // Alpha blend with constant background alpha.
325 // Caller must set dr_alpha_background at (255 - dr_alpha) or less.
326 alpha_r = dr_alpha_background;
327 do
328 {
329 // [WDJ] The source is a patch of alpha values, 0..255.
330 alpha = (dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) >> 8;
331 register pixel24_t * p24 = (pixel24_t*)dest;
332 p24->b = (((unsigned int)p24->b * alpha_r) + ((unsigned int)dr_color.s.blue * alpha)) >> 8;
333 p24->g = (((unsigned int)p24->g * alpha_r) + ((unsigned int)dr_color.s.green * alpha)) >> 8;
334 p24->r = (((unsigned int)p24->r * alpha_r) + ((unsigned int)dr_color.s.red * alpha)) >> 8;
335
336 dest += vid.ybytes;
337 frac += fracstep;
338 #if 0
339 if( frac >= texheight )
340 frac -= texheight;
341 #endif
342 }
343 while (count--);
344 break;
345
346 case 2: // Additive alpha
347 // Additive alpha
348 do
349 {
350 // [WDJ] The source is a patch of alpha values, 0..255.
351 alpha = (dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) >> 8;
352 register pixel24_t * p24 = (pixel24_t*)dest;
353 p24->b += (((unsigned int)dr_color.s.blue * alpha * (255 - p24->b))) >> 16;
354 p24->g += (((unsigned int)dr_color.s.green * alpha * (255 - p24->g))) >> 16;
355 p24->r += (((unsigned int)dr_color.s.red * alpha * (255 - p24->r))) >> 16;
356
357 dest += vid.ybytes;
358 frac += fracstep;
359 #if 0
360 if( frac >= texheight )
361 frac -= texheight;
362 #endif
363 }
364 while (count--);
365 break;
366
367 case 3: // Additive alpha, with background alpha
368 alpha_r = dr_alpha_background;
369 do
370 {
371 // [WDJ] The source is a patch of alpha values, 0..255.
372 alpha = (dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) >> 8;
373 register pixel24_t * p24 = (pixel24_t*)dest;
374 register unsigned int r,g,b;
375 b = (p24->b * alpha_r)>>8;
376 p24->b = (((unsigned int)dr_color.s.blue * alpha * (255 - b)) >> 16) + b;
377 g = (p24->g * alpha_r)>>8;
378 p24->g = (((unsigned int)dr_color.s.green * alpha * (255 - g)) >> 16) + g;
379 r = (p24->r * alpha_r)>>8;
380 p24->r = (((unsigned int)dr_color.s.red * alpha * (255 - r)) >> 16) + r;
381
382 dest += vid.ybytes;
383 frac += fracstep;
384 #if 0
385 if( frac >= texheight )
386 frac -= texheight;
387 #endif
388 }
389 while (count--);
390 break;
391
392 case 4: // Additive alpha, limit math
393 do
394 {
395 // [WDJ] The source is a patch of alpha values, 0..255.
396 alpha = (dc_source[frac >> FRACBITS] * (unsigned int)dr_alpha) >> 8;
397 register pixel24_t * p24 = (pixel24_t*)dest;
398 register unsigned int r,g,b;
399 b = (((unsigned int)dr_color.s.blue * alpha) >> 8) + p24->b;
400 p24->b = (b > 255)? 255 : b;
401 g = (((unsigned int)dr_color.s.green * alpha) >> 8) + p24->g;
402 p24->g = (g > 255)? 255 : g;
403 r = (((unsigned int)dr_color.s.red * alpha) >> 8) + p24->r;
404 p24->r = (r > 255)? 255 : r;
405
406 dest += vid.ybytes;
407 frac += fracstep;
408 #if 0
409 if( frac >= texheight )
410 frac -= texheight;
411 #endif
412 }
413 while (count--);
414 break;
415 }
416
417 }
418 #endif
419
R_DrawTranslucentColumn_24(void)420 void R_DrawTranslucentColumn_24 (void)
421 {
422 fixed_t texheight = dc_texheight << FRACBITS; // any texture size
423 int count;
424 byte* dest; // within screen buffer
425 fixed_t frac;
426 fixed_t fracstep;
427 pixelunion32_t c32;
428
429 // [WDJ] Source check has been added to all the callers of colfunc().
430
431 count = dc_yh - dc_yl;
432 if (count < 0)
433 return;
434
435 #ifdef RANGECHECK_DRAW_LIMITS
436 if ((unsigned)dc_x >= vid.width
437 || dc_yl < 0
438 || dc_yh >= vid.height)
439 {
440 I_SoftError ( "R_DrawTranslucentColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
441 return;
442 }
443
444 #endif
445
446 dest = ylookup[dc_yl] + columnofs[dc_x];
447
448 // Looks familiar.
449 fracstep = dc_iscale;
450 frac = dc_texturemid + (dc_yl-centery)*fracstep;
451 if (texheight > 0) // hangs when texheight==0
452 {
453 // From Boom, to fix the odd frac
454 if (frac < 0)
455 while ((frac += texheight) < 0);
456 else
457 while (frac >= texheight) frac -= texheight;
458 }
459
460 // 8bpp: *dest = dc_colormap[ dc_translucentmap[ (dc_source[frac >> FRACBITS] << 8) + (*dest) ]];
461 switch( dc_translucent_index )
462 {
463 case 0:
464 {
465 // alpha translucent, by dr_alpha
466 unsigned int alpha_d = dr_alpha;
467 unsigned int alpha_r = 255 - alpha_d;
468 do
469 {
470 c32.ui32 = color8.to32[dc_colormap[dc_source[frac>>FRACBITS]]];
471 // c32.ui32 = color8.to32[dc_source[frac>>FRACBITS]];
472 // alpha translucent
473 register pixel24_t * p24 = (pixel24_t*)dest;
474 p24->b = (((unsigned int)p24->b * alpha_r) + (c32.pix24.b * alpha_d)) >> 8;
475 p24->g = (((unsigned int)p24->g * alpha_r) + (c32.pix24.g * alpha_d)) >> 8;
476 p24->r = (((unsigned int)p24->r * alpha_r) + (c32.pix24.r * alpha_d)) >> 8;
477 dest += vid.ybytes;
478 frac += fracstep;
479 if( frac >= texheight )
480 frac -= texheight;
481 } while (count--);
482 }
483 break;
484 case TRANSLU_more: // 20 80 puffs, Linedef 285
485 do
486 {
487 // 25/75 translucent
488 c32.ui32 = color8.to32[dc_colormap[dc_source[frac>>FRACBITS]]];
489 // c32.ui32 = color8.to32[dc_source[frac>>FRACBITS]];
490 register uint16_t dc0, dc1, dc2; // for overlapped execution
491 register pixel24_t * p24 = (pixel24_t*)dest;
492 dc0 = p24->b;
493 p24->b = (dc0 + dc0 + dc0 + c32.pix24.b) >> 2;
494 dc1 = p24->g;
495 p24->g = (dc1 + dc1 + dc1 + c32.pix24.g) >> 2;
496 dc2 = p24->r;
497 p24->r = (dc2 + dc2 + dc2 + c32.pix24.r) >> 2;
498 dest += vid.ybytes;
499 frac += fracstep;
500 if( frac >= texheight )
501 frac -= texheight;
502 } while (count--);
503 break;
504 case TRANSLU_hi: // 10 90 blur effect, Linedef 286
505 do
506 {
507 // 15/85 translucent
508 c32.ui32 = color8.to32[dc_colormap[dc_source[frac>>FRACBITS]]];
509 // c32.ui32 = color8.to32[dc_source[frac>>FRACBITS]];
510 register uint16_t dc0, dc1, dc2; // for overlapped execution
511 register pixel24_t * p24 = (pixel24_t*)dest;
512 dc0 = p24->b;
513 p24->b = ((dc0<<3) - dc0 + c32.pix24.b) >> 3;
514 dc1 = p24->g;
515 p24->g = ((dc1<<3) - dc1 + c32.pix24.g) >> 3;
516 dc2 = p24->r;
517 p24->r = ((dc2<<3) - dc2 + c32.pix24.r) >> 3;
518 dest += vid.ybytes;
519 frac += fracstep;
520 if( frac >= texheight )
521 frac -= texheight;
522 } while (count--);
523 break;
524 case TRANSLU_med: // sprite 50 backg 50, Linedef 260, 284, 300
525 default:
526 do
527 {
528 // 50/50 translucent
529 c32.ui32 = color8.to32[dc_colormap[dc_source[frac>>FRACBITS]]];
530 // c32.ui32 = color8.to32[dc_source[frac>>FRACBITS]];
531 register uint16_t dc0, dc1, dc2; // for overlapped execution
532 register pixel24_t * p24 = (pixel24_t*)dest;
533 dc0 = p24->b;
534 p24->b = (dc0 + c32.pix24.b) >> 1;
535 dc1 = p24->g;
536 p24->g = (dc1 + c32.pix24.g) >> 1;
537 dc2 = p24->r;
538 p24->r = (dc2 + c32.pix24.r) >> 1;
539 dest += vid.ybytes;
540 frac += fracstep;
541 if( frac >= texheight )
542 frac -= texheight;
543 } while (count--);
544 break;
545 case TRANSLU_fire: // Linedef 287
546 // 50 50 but brighter for fireballs, shots
547 #define TFIRE_OPTION 1
548 do
549 {
550 // 50/50 translucent with modifications
551 register int sb = dc_source[frac>>FRACBITS];
552 #if TFIRE_OPTION==4
553 // sb = dc_translucentmap[ (sb << 8) + 80 ]; // grays 80..111; // faded
554 // sb = dc_translucentmap[ (sb << 8) + 110 ]; // grays 80..111;
555 sb = dc_translucentmap[ (sb << 8) ]; // black
556 #endif
557 c32.ui32 = color8.to32[dc_colormap[ sb ]];
558 // c32.ui32 = color8.to32[ sb ];
559 #if TFIRE_OPTION==1
560 // dark background is enhanced before avg, to give light add effect
561 register pixelunion32_t sh32;
562 sh32.ui32 = (c32.ui32 >> 1) & 0x70707070; // tint
563 // sh32.ui32 = (c32.ui32 >> 1) & 0x7F7F7F7F; // heavy
564 register uint16_t dc0, dc1, dc2; // for overlapped execution
565 register pixel24_t * p24 = (pixel24_t*)dest;
566 dc0 = p24->b;
567 p24->b = ((dc0 | sh32.pix32.b) + c32.pix24.b) >> 1;
568 dc1 = p24->g;
569 p24->g = ((dc1 | sh32.pix32.g) + c32.pix24.g) >> 1;
570 dc2 = p24->r;
571 p24->r = ((dc2 | sh32.pix32.r) + c32.pix24.r) >> 1;
572 #endif
573 #if TFIRE_OPTION==2
574 // Bright and nearly opaque
575 // additive light (not average)
576 register uint16_t dc0, dc1, dc2; // for overlapped execution
577 register pixel24_t * p24 = (pixel24_t*)dest;
578 dc0 = p24->b;
579 p24->b = (dc0 | c32.pix24.b);
580 dc1 = p24->g;
581 p24->g = (dc1 | c32.pix24.g);
582 dc2 = p24->r;
583 p24->r = (dc2 | c32.pix24.r);
584 #endif
585 dest += vid.ybytes;
586 frac += fracstep;
587 if( frac >= texheight )
588 frac -= texheight;
589 } while (count--);
590 break;
591 case TRANSLU_fx1: // Linedef 288
592 // 50 50 brighter some colors, else opaque for torches
593 // fire translucent texture
594 #define FX1_OPTION 1
595 do
596 {
597 // 50/50 translucent with modifications
598 register int sb = dc_source[frac>>FRACBITS];
599 c32.ui32 = color8.to32[dc_colormap[ sb ]];
600 // c32.ui32 = color8.to32[ sb ];
601 #if FX1_OPTION==1
602 // check translucent map for opaque, sprite vrs white bkg
603 register byte twht = dc_translucentmap[ (sb << 8) + 4 ];
604 register int tdiff = sb - twht; // any change
605 #else
606 // check translucent map for opaque, blk bkg vrs white bkg
607 register byte tblk = dc_translucentmap[ (sb << 8) ];
608 register byte twht = dc_translucentmap[ (sb << 8) + 4 ];
609 register int tdiff = tblk - twht;
610 #endif
611
612 if( tdiff > 2 || tdiff < -2 )
613 {
614 // 50/50
615 register uint16_t dc0, dc1, dc2;
616 register pixel24_t * p24 = (pixel24_t*)dest;
617 dc0 = p24->b;
618 p24->b = (dc0 + c32.pix24.b) >> 1;
619 dc1 = p24->g;
620 p24->g = (dc1 + c32.pix24.g) >> 1;
621 dc2 = p24->r;
622 p24->r = (dc2 + c32.pix24.r) >> 1;
623 }
624 else
625 {
626 *(pixel24_t*)dest = c32.pix24; // opaque
627 }
628 dest += vid.ybytes;
629 frac += fracstep;
630 if( frac >= texheight )
631 frac -= texheight;
632 } while (count--);
633 break;
634 case TRANSLU_75: // 75 25
635 do
636 {
637 // 75/25 translucent
638 c32.ui32 = color8.to32[dc_colormap[dc_source[frac>>FRACBITS]]];
639 register uint16_t dc0, dc1, dc2; // for overlapped execution
640 register pixel24_t * p24 = (pixel24_t*)dest;
641 dc0 = c32.pix24.b;
642 p24->b = (dc0 + dc0 + dc0 + p24->b) >> 2;
643 dc1 = c32.pix24.g;
644 p24->g = (dc1 + dc1 + dc1 + p24->g) >> 2;
645 dc2 = c32.pix24.r;
646 p24->r = (dc2 + dc2 + dc2 + p24->r) >> 2;
647 dest += vid.ybytes;
648 frac += fracstep;
649 if( frac >= texheight )
650 frac -= texheight;
651 } while (count--);
652 break;
653 }
654 }
655
656
657 // transparent with skin translations
658 // Although the vissprite has capability for any transparency,
659 // Called with TRANSLU_hi or TRANSLU_more, or arbitrary by thing TRANSMASK
R_DrawTranslatedTranslucentColumn_24(void)660 void R_DrawTranslatedTranslucentColumn_24(void)
661 {
662 R_DrawTranslucentColumn_24();
663 }
664
665
666 // Skin
R_DrawTranslatedColumn_24(void)667 void R_DrawTranslatedColumn_24 (void)
668 {
669 fixed_t texheight = dc_texheight << FRACBITS; // any texture size
670 int count;
671 byte* dest; // within screen buffer
672 fixed_t frac;
673 fixed_t fracstep;
674 pixelunion32_t c32;
675
676 count = dc_yh - dc_yl;
677 if (count < 0)
678 return;
679
680 #ifdef RANGECHECK_DRAW_LIMITS
681 if ((unsigned)dc_x >= vid.width
682 || dc_yl < 0
683 || dc_yh >= vid.height)
684 {
685 I_SoftError ( "R_DrawTranslatedColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
686 return;
687 }
688
689 #endif
690
691 dest = ylookup[dc_yl] + columnofs[dc_x];
692
693 // Looks familiar.
694 fracstep = dc_iscale;
695 frac = dc_texturemid + (dc_yl-centery)*fracstep;
696 if (texheight > 0) // hangs when texheight==0
697 {
698 // From Boom, to fix the odd frac
699 if (frac < 0)
700 while ((frac += texheight) < 0);
701 else
702 while (frac >= texheight) frac -= texheight;
703 }
704
705 // Here we do an additional skin re-mapping.
706 do
707 {
708 c32.ui32 = color8.to32[ dc_colormap[ dc_skintran[ dc_source[frac>>FRACBITS]]] ];
709 *(pixel24_t*)dest = c32.pix24; // opaque
710 dest += vid.ybytes;
711 frac += fracstep;
712 if( frac >= texheight )
713 frac -= texheight;
714 } while (count--);
715 }
716
717
718
719 // ==========================================================================
720 // SPANS
721 // ==========================================================================
722
R_DrawSpan_24(void)723 void R_DrawSpan_24 (void)
724 {
725 fixed_t xfrac;
726 fixed_t yfrac;
727 pixel24_t * p24;
728 int count;
729 pixelunion32_t c32;
730
731 #ifdef RANGECHECK_DRAW_LIMITS
732 if (ds_x2 < ds_x1
733 || ds_x1<0
734 || ds_x2>=vid.width
735 || (unsigned)ds_y>vid.height)
736 {
737 I_SoftError( "R_DrawSpan: %i to %i at %i", ds_x1,ds_x2,ds_y);
738 return;
739 }
740 #endif
741
742 xfrac = ds_xfrac;
743 yfrac = ds_yfrac;
744
745 p24 = (pixel24_t*)( ylookup[ds_y] + columnofs[ds_x1] );
746
747 // We do not check for zero spans here?
748 count = ds_x2 - ds_x1;
749
750 do
751 {
752 // Current texture index in u,v.
753 xfrac &= flat_imask;
754 register int spot = ((yfrac >> flatfracbits) & flat_ymask) | (xfrac >> 16);
755 // Lookup pixel from flat texture tile,
756 // re-index using light/colormap.
757 c32.ui32 = color8.to32[ ds_colormap[ds_source[spot]] ];
758 *(p24++) = c32.pix24; // opaque
759 // Next step in u,v.
760 xfrac += ds_xstep;
761 yfrac += ds_ystep;
762 } while (count--);
763 }
764
765
R_DrawTranslucentSpan_24(void)766 void R_DrawTranslucentSpan_24(void)
767 {
768 fixed_t xfrac, yfrac;
769 fixed_t xstep, ystep;
770 pixel24_t * p24;
771 unsigned int alpha_d = dr_alpha;
772 unsigned int alpha_r = 255 - alpha_d;
773 int count;
774 pixelunion32_t c32;
775
776 #ifdef RANGECHECK_DRAW_LIMITS
777 if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= rdraw_viewwidth || (unsigned) ds_y > rdraw_viewheight)
778 {
779 I_SoftError("R_DrawTranslucentSpan: %i to %i at %i\n", ds_x1, ds_x2, ds_y);
780 return;
781 }
782 #endif
783
784 xfrac = ds_xfrac & flat_imask;
785 yfrac = ds_yfrac;
786
787 p24 = (pixel24_t*)( ylookup[ds_y] + columnofs[ds_x1] );
788
789 // We do not check for zero spans here?
790 count = ds_x2 - ds_x1 + 1;
791
792 xstep = ds_xstep;
793 ystep = ds_ystep;
794
795 do
796 {
797 // Current texture index in u,v.
798 // Lookup pixel from flat texture tile,
799 xfrac &= flat_imask;
800 register int spot = ((yfrac >> flatfracbits) & flat_ymask) | (xfrac >> FRACBITS);
801 // Lookup pixel from flat texture tile,
802 // re-index using light/colormap.
803 c32.ui32 = color8.to32[ ds_colormap[ds_source[spot]] ];
804 // alpha translucent
805 p24->b = (((unsigned int)p24->b * alpha_r) + (c32.pix24.b * alpha_d)) >> 8;
806 p24->g = (((unsigned int)p24->g * alpha_r) + (c32.pix24.g * alpha_d)) >> 8;
807 p24->r = (((unsigned int)p24->r * alpha_r) + (c32.pix24.r * alpha_d)) >> 8;
808 p24 ++; // *3
809
810 // Next step in u,v.
811 xfrac += xstep;
812 yfrac += ystep;
813 xfrac &= flat_imask;
814 }
815 while (--count);
816 }
817
818
819 // Used for Legacy linetype 302, ceiling and floor of 3D fog in tagged
R_DrawFogSpan_24(void)820 void R_DrawFogSpan_24(void)
821 {
822 pixelunion32_t fogcolor;
823 unsigned int alpha_d = dr_alpha;
824 unsigned int alpha_r = (255 - alpha_d) * 0.84; // cloudy fog
825 unsigned int count;
826 pixel24_t * p24;
827
828 fogcolor.ui32 = color8.to32[ ds_colormap[ ds_source[0] ]];
829 p24 = (pixel24_t*)( ylookup[ds_y] + columnofs[ds_x1] );
830 count = ds_x2 - ds_x1 + 1;
831
832 {
833 register int fb = fogcolor.pix32.b * alpha_d;
834 register int fg = fogcolor.pix32.g * alpha_d;
835 register int fr = fogcolor.pix32.r * alpha_d;
836 while (count--)
837 {
838 p24->b = ((p24->b * alpha_r) + fb) >> 8;
839 p24->g = ((p24->g * alpha_r) + fg) >> 8;
840 p24->r = ((p24->r * alpha_r) + fr) >> 8;
841 p24 ++; // *3
842 }
843 }
844 }
845
846 //SoM: Fog wall.
847 // Used for Legacy linetype 302, walls of 3D fog in tagged
848 // Used for Legacy linetype 283, fog sheet
R_DrawFogColumn_24(void)849 void R_DrawFogColumn_24(void)
850 {
851 static pixelunion32_t fogcolor = {.ui32=0x00101010};
852 pixelunion32_t fc, fc2, fc3;
853 unsigned int alpha_d = dr_alpha;
854 unsigned int alpha_r = (255 - alpha_d) * 0.84; // cloudy fog
855 int count, fi;
856 byte * dest;
857
858 // fog_index 0.. column height
859 // always average three pixels of source texture
860 fc.ui32 = color8.to32[ dc_colormap[ dc_source[fog_index] ]];
861 fi = fog_index + 3;
862 if( fi >= fog_col_length ) fi -= fog_col_length;
863 fc2.ui32 = color8.to32[ dc_colormap[ dc_source[fi] ]];
864 fi += 3;
865 if( fi >= fog_col_length ) fi -= fog_col_length;
866 fc3.ui32 = color8.to32[ dc_colormap[ dc_source[fi] ]];
867 fc.pix32.r = ((unsigned int)fc.pix32.r + fc2.pix32.r + fc3.pix32.r) /3;
868 fc.pix32.g = ((unsigned int)fc.pix32.g + fc2.pix32.g + fc3.pix32.g) /3;
869 fc.pix32.b = ((unsigned int)fc.pix32.b + fc2.pix32.b + fc3.pix32.b) /3;
870 if( fog_init )
871 {
872 // init blur
873 fogcolor.pix32 = fc.pix32;
874 fog_init = 0;
875 }
876 else
877 {
878 // blur
879 fogcolor.pix32.r = ((((unsigned int)fogcolor.pix32.r)*31) + fc.pix32.r) >> 5;
880 fogcolor.pix32.g = ((((unsigned int)fogcolor.pix32.g)*31) + fc.pix32.g) >> 5;
881 fogcolor.pix32.b = ((((unsigned int)fogcolor.pix32.b)*31) + fc.pix32.b) >> 5;
882 }
883
884 count = dc_yh - dc_yl;
885
886 // Zero length, column does not exceed a pixel.
887 if (count < 0)
888 return;
889
890 #ifdef RANGECHECK_DRAW_LIMITS
891 // [WDJ] Draw window is actually rdraw_viewwidth and rdraw_viewheight
892 if ((unsigned) dc_x >= rdraw_viewwidth || dc_yl < 0 || dc_yh >= rdraw_viewheight)
893 {
894 I_SoftError("R_DrawFogColumn: %i to %i at %i\n", dc_yl, dc_yh, dc_x);
895 return;
896 }
897 #endif
898
899 // Framebuffer destination address.
900 // Use ylookup LUT to avoid multiply with ScreenWidth.
901 // Use columnofs LUT for subwindows?
902 dest = ylookup[dc_yl] + columnofs[dc_x];
903
904 {
905 register unsigned int fb = fogcolor.pix32.b * alpha_d;
906 register unsigned int fg = fogcolor.pix32.g * alpha_d;
907 register unsigned int fr = fogcolor.pix32.r * alpha_d;
908 do
909 {
910 register pixel24_t * p24 = (pixel24_t*)dest;
911 p24->b = ((p24->b * alpha_r) + fb) >> 8;
912 p24->g = ((p24->g * alpha_r) + fg) >> 8;
913 p24->r = ((p24->r * alpha_r) + fr) >> 8;
914 dest += vid.ybytes;
915 }
916 while (count--);
917 }
918 }
919