1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3
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.
8
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.
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20 // GL_RSURF.C: surface-related refresh code
21 #include <assert.h>
22
23 #include "gl_local.h"
24
25 static vec3_t modelorg; // relative to viewpoint
26
27 msurface_t *r_alpha_surfaces;
28
29 #define DYNAMIC_LIGHT_WIDTH 128
30 #define DYNAMIC_LIGHT_HEIGHT 128
31
32 #define LIGHTMAP_BYTES 4
33
34 #define BLOCK_WIDTH 128
35 #define BLOCK_HEIGHT 128
36
37 #define MAX_LIGHTMAPS 128
38
39 int c_visible_lightmaps;
40 int c_visible_textures;
41
42 #define GL_LIGHTMAP_FORMAT GL_RGBA
43
44 typedef struct
45 {
46 int internal_format;
47 int current_lightmap_texture;
48
49 msurface_t *lightmap_surfaces[MAX_LIGHTMAPS];
50
51 int allocated[BLOCK_WIDTH];
52
53 // the lightmap texture data needs to be kept in
54 // main memory so texsubimage can update properly
55 byte lightmap_buffer[4*BLOCK_WIDTH*BLOCK_HEIGHT];
56 } gllightmapstate_t;
57
58 static gllightmapstate_t gl_lms;
59
60
61 static void LM_InitBlock( void );
62 static void LM_UploadBlock( qboolean dynamic );
63 static qboolean LM_AllocBlock (int w, int h, int *x, int *y);
64
65 extern void R_SetCacheState( msurface_t *surf );
66 extern void R_BuildLightMap (msurface_t *surf, byte *dest, int stride);
67
68 /*
69 =============================================================
70
71 BRUSH MODELS
72
73 =============================================================
74 */
75
76 /*
77 ===============
78 R_TextureAnimation
79
80 Returns the proper texture for a given time and base texture
81 ===============
82 */
R_TextureAnimation(mtexinfo_t * tex)83 image_t *R_TextureAnimation (mtexinfo_t *tex)
84 {
85 int c;
86
87 if (!tex->next)
88 return tex->image;
89
90 c = currententity->frame % tex->numframes;
91 while (c)
92 {
93 tex = tex->next;
94 c--;
95 }
96
97 return tex->image;
98 }
99
100 #if 0
101 /*
102 =================
103 WaterWarpPolyVerts
104
105 Mangles the x and y coordinates in a copy of the poly
106 so that any drawing routine can be water warped
107 =================
108 */
109 glpoly_t *WaterWarpPolyVerts (glpoly_t *p)
110 {
111 int i;
112 float *v, *nv;
113 static byte buffer[1024];
114 glpoly_t *out;
115
116 out = (glpoly_t *)buffer;
117
118 out->numverts = p->numverts;
119 v = p->verts[0];
120 nv = out->verts[0];
121 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE, nv+=VERTEXSIZE)
122 {
123 nv[0] = v[0] + 4*sin(v[1]*0.05+r_newrefdef.time)*sin(v[2]*0.05+r_newrefdef.time);
124 nv[1] = v[1] + 4*sin(v[0]*0.05+r_newrefdef.time)*sin(v[2]*0.05+r_newrefdef.time);
125
126 nv[2] = v[2];
127 nv[3] = v[3];
128 nv[4] = v[4];
129 nv[5] = v[5];
130 nv[6] = v[6];
131 }
132
133 return out;
134 }
135
136 /*
137 ================
138 DrawGLWaterPoly
139
140 Warp the vertex coordinates
141 ================
142 */
143 void DrawGLWaterPoly (glpoly_t *p)
144 {
145 int i;
146 float *v;
147
148 p = WaterWarpPolyVerts (p);
149 qglBegin (GL_TRIANGLE_FAN);
150 v = p->verts[0];
151 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
152 {
153 qglTexCoord2f (v[3], v[4]);
154 qglVertex3fv (v);
155 }
156 qglEnd ();
157 }
158 void DrawGLWaterPolyLightmap (glpoly_t *p)
159 {
160 int i;
161 float *v;
162
163 p = WaterWarpPolyVerts (p);
164 qglBegin (GL_TRIANGLE_FAN);
165 v = p->verts[0];
166 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
167 {
168 qglTexCoord2f (v[5], v[6]);
169 qglVertex3fv (v);
170 }
171 qglEnd ();
172 }
173 #endif
174
175 /*
176 ================
177 DrawGLPoly
178 ================
179 */
DrawGLPoly(glpoly_t * p)180 void DrawGLPoly (glpoly_t *p)
181 {
182 int i;
183 float *v;
184
185 qglBegin (GL_POLYGON);
186 v = p->verts[0];
187 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
188 {
189 qglTexCoord2f (v[3], v[4]);
190 qglVertex3fv (v);
191 }
192 qglEnd ();
193 }
194
195 //============
196 //PGM
197 /*
198 ================
199 DrawGLFlowingPoly -- version of DrawGLPoly that handles scrolling texture
200 ================
201 */
DrawGLFlowingPoly(msurface_t * fa)202 void DrawGLFlowingPoly (msurface_t *fa)
203 {
204 int i;
205 float *v;
206 glpoly_t *p;
207 float scroll;
208
209 p = fa->polys;
210
211 scroll = -64 * ( (r_newrefdef.time / 40.0) - (int)(r_newrefdef.time / 40.0) );
212 if(scroll == 0.0)
213 scroll = -64.0;
214
215 qglBegin (GL_POLYGON);
216 v = p->verts[0];
217 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
218 {
219 qglTexCoord2f ((v[3] + scroll), v[4]);
220 qglVertex3fv (v);
221 }
222 qglEnd ();
223 }
224 //PGM
225 //============
226
227 /*
228 ** R_DrawTriangleOutlines
229 */
R_DrawTriangleOutlines(void)230 void R_DrawTriangleOutlines (void)
231 {
232 int i, j;
233 glpoly_t *p;
234
235 if (!gl_showtris->value)
236 return;
237
238 qglDisable (GL_TEXTURE_2D);
239 qglDisable (GL_DEPTH_TEST);
240 qglColor4f (1,1,1,1);
241
242 for (i=0 ; i<MAX_LIGHTMAPS ; i++)
243 {
244 msurface_t *surf;
245
246 for ( surf = gl_lms.lightmap_surfaces[i]; surf != 0; surf = surf->lightmapchain )
247 {
248 p = surf->polys;
249 for ( ; p ; p=p->chain)
250 {
251 for (j=2 ; j<p->numverts ; j++ )
252 {
253 qglBegin (GL_LINE_STRIP);
254 qglVertex3fv (p->verts[0]);
255 qglVertex3fv (p->verts[j-1]);
256 qglVertex3fv (p->verts[j]);
257 qglVertex3fv (p->verts[0]);
258 qglEnd ();
259 }
260 }
261 }
262 }
263
264 qglEnable (GL_DEPTH_TEST);
265 qglEnable (GL_TEXTURE_2D);
266 }
267
268 /*
269 ** DrawGLPolyChain
270 */
DrawGLPolyChain(glpoly_t * p,float soffset,float toffset)271 void DrawGLPolyChain( glpoly_t *p, float soffset, float toffset )
272 {
273 if ( soffset == 0 && toffset == 0 )
274 {
275 for ( ; p != 0; p = p->chain )
276 {
277 float *v;
278 int j;
279
280 /* There is a crash somewheres around old line 282.
281 * I am trying to find a workaround.
282 * -- Phil Brown
283 */
284 v = p->verts[0];
285 if(v==NULL){
286 fprintf(stderr,"BUGFIX: DrawGLPolyChain: v==NULL\n");
287 return;
288 }
289 qglBegin (GL_POLYGON);
290 for (j=0 ; j<p->numverts ; j++, v+= VERTEXSIZE)
291 {
292 qglTexCoord2f (v[5], v[6] );
293 qglVertex3fv (v);
294 }
295 qglEnd ();
296 }
297 }
298 else
299 {
300 for ( ; p != 0; p = p->chain )
301 {
302 float *v;
303 int j;
304
305 qglBegin (GL_POLYGON);
306 v = p->verts[0];
307 for (j=0 ; j<p->numverts ; j++, v+= VERTEXSIZE)
308 {
309 qglTexCoord2f (v[5] - soffset, v[6] - toffset );
310 qglVertex3fv (v);
311 }
312 qglEnd ();
313 }
314 }
315 }
316
317 /*
318 ** R_BlendLightMaps
319 **
320 ** This routine takes all the given light mapped surfaces in the world and
321 ** blends them into the framebuffer.
322 */
R_BlendLightmaps(void)323 void R_BlendLightmaps (void)
324 {
325 int i;
326 msurface_t *surf, *newdrawsurf = 0;
327
328 // don't bother if we're set to fullbright
329 if (r_fullbright->value)
330 return;
331 if (!r_worldmodel->lightdata)
332 return;
333
334 // don't bother writing Z
335 qglDepthMask( 0 );
336
337 /*
338 ** set the appropriate blending mode unless we're only looking at the
339 ** lightmaps.
340 */
341 if (!gl_lightmap->value)
342 {
343 qglEnable (GL_BLEND);
344
345 if ( gl_saturatelighting->value )
346 {
347 qglBlendFunc( GL_ONE, GL_ONE );
348 }
349 else
350 {
351 if ( gl_monolightmap->string[0] != '0' )
352 {
353 switch ( toupper( gl_monolightmap->string[0] ) )
354 {
355 case 'I':
356 qglBlendFunc (GL_ZERO, GL_SRC_COLOR );
357 break;
358 case 'L':
359 qglBlendFunc (GL_ZERO, GL_SRC_COLOR );
360 break;
361 case 'A':
362 default:
363 qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
364 break;
365 }
366 }
367 else
368 {
369 qglBlendFunc (GL_ZERO, GL_SRC_COLOR );
370 }
371 }
372 }
373
374 if ( currentmodel == r_worldmodel )
375 c_visible_lightmaps = 0;
376
377 /*
378 ** render static lightmaps first
379 */
380 for ( i = 1; i < MAX_LIGHTMAPS; i++ )
381 {
382 if ( gl_lms.lightmap_surfaces[i] )
383 {
384 if (currentmodel == r_worldmodel)
385 c_visible_lightmaps++;
386 GL_Bind( gl_state.lightmap_textures + i);
387
388 for ( surf = gl_lms.lightmap_surfaces[i]; surf != 0; surf = surf->lightmapchain )
389 {
390 if ( surf->polys )
391 DrawGLPolyChain( surf->polys, 0, 0 );
392 }
393 }
394 }
395
396 /*
397 ** render dynamic lightmaps
398 */
399 if ( gl_dynamic->value )
400 {
401 LM_InitBlock();
402
403 GL_Bind( gl_state.lightmap_textures+0 );
404
405 if (currentmodel == r_worldmodel)
406 c_visible_lightmaps++;
407
408 newdrawsurf = gl_lms.lightmap_surfaces[0];
409
410 for ( surf = gl_lms.lightmap_surfaces[0]; surf != 0; surf = surf->lightmapchain )
411 {
412 int smax, tmax;
413 byte *base;
414
415 smax = (surf->extents[0]>>4)+1;
416 tmax = (surf->extents[1]>>4)+1;
417
418 if ( LM_AllocBlock( smax, tmax, &surf->dlight_s, &surf->dlight_t ) )
419 {
420 base = gl_lms.lightmap_buffer;
421 base += ( surf->dlight_t * BLOCK_WIDTH + surf->dlight_s ) * LIGHTMAP_BYTES;
422
423 R_BuildLightMap (surf, base, BLOCK_WIDTH*LIGHTMAP_BYTES);
424 }
425 else
426 {
427 msurface_t *drawsurf;
428
429 // upload what we have so far
430 LM_UploadBlock( true );
431
432 // draw all surfaces that use this lightmap
433 for ( drawsurf = newdrawsurf; drawsurf != surf; drawsurf = drawsurf->lightmapchain )
434 {
435 if ( drawsurf->polys )
436 DrawGLPolyChain( drawsurf->polys,
437 ( drawsurf->light_s - drawsurf->dlight_s ) * ( 1.0 / 128.0 ),
438 ( drawsurf->light_t - drawsurf->dlight_t ) * ( 1.0 / 128.0 ) );
439 }
440
441 newdrawsurf = drawsurf;
442
443 // clear the block
444 LM_InitBlock();
445
446 // try uploading the block now
447 if ( !LM_AllocBlock( smax, tmax, &surf->dlight_s, &surf->dlight_t ) )
448 {
449 ri.Sys_Error( ERR_FATAL, "Consecutive calls to LM_AllocBlock(%d,%d) failed (dynamic)\n", smax, tmax );
450 }
451
452 base = gl_lms.lightmap_buffer;
453 base += ( surf->dlight_t * BLOCK_WIDTH + surf->dlight_s ) * LIGHTMAP_BYTES;
454
455 R_BuildLightMap (surf, base, BLOCK_WIDTH*LIGHTMAP_BYTES);
456 }
457 }
458
459 /*
460 ** draw remainder of dynamic lightmaps that haven't been uploaded yet
461 */
462 if ( newdrawsurf )
463 LM_UploadBlock( true );
464
465 for ( surf = newdrawsurf; surf != 0; surf = surf->lightmapchain )
466 {
467 if ( surf->polys )
468 DrawGLPolyChain( surf->polys, ( surf->light_s - surf->dlight_s ) * ( 1.0 / 128.0 ), ( surf->light_t - surf->dlight_t ) * ( 1.0 / 128.0 ) );
469 }
470 }
471
472 /*
473 ** restore state
474 */
475 qglDisable (GL_BLEND);
476 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
477 qglDepthMask( 1 );
478 }
479
480 /*
481 ================
482 R_RenderBrushPoly
483 ================
484 */
R_RenderBrushPoly(msurface_t * fa)485 void R_RenderBrushPoly (msurface_t *fa)
486 {
487 int maps;
488 image_t *image;
489 qboolean is_dynamic = false;
490
491 c_brush_polys++;
492
493 image = R_TextureAnimation (fa->texinfo);
494
495 if (fa->flags & SURF_DRAWTURB)
496 {
497 GL_Bind( image->texnum );
498
499 // warp texture, no lightmaps
500 GL_TexEnv( GL_MODULATE );
501 qglColor4f( gl_state.inverse_intensity,
502 gl_state.inverse_intensity,
503 gl_state.inverse_intensity,
504 1.0F );
505 EmitWaterPolys (fa);
506 GL_TexEnv( GL_REPLACE );
507
508 return;
509 }
510 else
511 {
512 GL_Bind( image->texnum );
513
514 GL_TexEnv( GL_REPLACE );
515 }
516
517 //======
518 //PGM
519 if(fa->texinfo->flags & SURF_FLOWING)
520 DrawGLFlowingPoly (fa);
521 else
522 DrawGLPoly (fa->polys);
523 //PGM
524 //======
525
526 /*
527 ** check for lightmap modification
528 */
529 for ( maps = 0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++ )
530 {
531 if ( r_newrefdef.lightstyles[fa->styles[maps]].white != fa->cached_light[maps] )
532 goto dynamic;
533 }
534
535 // dynamic this frame or dynamic previously
536 if ( ( fa->dlightframe == r_framecount ) )
537 {
538 dynamic:
539 if ( gl_dynamic->value )
540 {
541 if (!( fa->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP ) ) )
542 {
543 is_dynamic = true;
544 }
545 }
546 }
547
548 if ( is_dynamic )
549 {
550 if ( ( fa->styles[maps] >= 32 || fa->styles[maps] == 0 ) && ( fa->dlightframe != r_framecount ) )
551 {
552 unsigned temp[34*34];
553 int smax, tmax;
554
555 smax = (fa->extents[0]>>4)+1;
556 tmax = (fa->extents[1]>>4)+1;
557
558 R_BuildLightMap( fa, (void *)temp, smax*4 );
559 R_SetCacheState( fa );
560
561 GL_Bind( gl_state.lightmap_textures + fa->lightmaptexturenum );
562
563 qglTexSubImage2D( GL_TEXTURE_2D, 0,
564 fa->light_s, fa->light_t,
565 smax, tmax,
566 GL_LIGHTMAP_FORMAT,
567 GL_UNSIGNED_BYTE, temp );
568
569 fa->lightmapchain = gl_lms.lightmap_surfaces[fa->lightmaptexturenum];
570 gl_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa;
571 }
572 else
573 {
574 fa->lightmapchain = gl_lms.lightmap_surfaces[0];
575 gl_lms.lightmap_surfaces[0] = fa;
576 }
577 }
578 else
579 {
580 fa->lightmapchain = gl_lms.lightmap_surfaces[fa->lightmaptexturenum];
581 gl_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa;
582 }
583 }
584
585
586 /*
587 ================
588 R_DrawAlphaSurfaces
589
590 Draw water surfaces and windows.
591 The BSP tree is waled front to back, so unwinding the chain
592 of alpha_surfaces will draw back to front, giving proper ordering.
593 ================
594 */
R_DrawAlphaSurfaces(void)595 void R_DrawAlphaSurfaces (void)
596 {
597 msurface_t *s;
598 float intens;
599
600 //
601 // go back to the world matrix
602 //
603 qglLoadMatrixf (r_world_matrix);
604
605 qglEnable (GL_BLEND);
606 GL_TexEnv( GL_MODULATE );
607
608 // the textures are prescaled up for a better lighting range,
609 // so scale it back down
610 intens = gl_state.inverse_intensity;
611
612 for (s=r_alpha_surfaces ; s ; s=s->texturechain)
613 {
614 GL_Bind(s->texinfo->image->texnum);
615 c_brush_polys++;
616 if (s->texinfo->flags & SURF_TRANS33)
617 qglColor4f (intens,intens,intens,0.33);
618 else if (s->texinfo->flags & SURF_TRANS66)
619 qglColor4f (intens,intens,intens,0.66);
620 else
621 qglColor4f (intens,intens,intens,1);
622 if (s->flags & SURF_DRAWTURB)
623 EmitWaterPolys (s);
624 else if(s->texinfo->flags & SURF_FLOWING) // PGM 9/16/98
625 DrawGLFlowingPoly (s); // PGM
626 else
627 DrawGLPoly (s->polys);
628 }
629
630 GL_TexEnv( GL_REPLACE );
631 qglColor4f (1,1,1,1);
632 qglDisable (GL_BLEND);
633
634 r_alpha_surfaces = NULL;
635 }
636
637 /*
638 ================
639 DrawTextureChains
640 ================
641 */
DrawTextureChains(void)642 void DrawTextureChains (void)
643 {
644 int i;
645 msurface_t *s;
646 image_t *image;
647
648 c_visible_textures = 0;
649
650 // GL_TexEnv( GL_REPLACE );
651
652 if ( !qglSelectTextureSGIS && !qglActiveTextureARB )
653 {
654 for ( i = 0, image=gltextures ; i<numgltextures ; i++,image++)
655 {
656 if (!image->registration_sequence)
657 continue;
658 s = image->texturechain;
659 if (!s)
660 continue;
661 c_visible_textures++;
662
663 for ( ; s ; s=s->texturechain)
664 R_RenderBrushPoly (s);
665
666 image->texturechain = NULL;
667 }
668 }
669 else
670 {
671 for ( i = 0, image=gltextures ; i<numgltextures ; i++,image++)
672 {
673 if (!image->registration_sequence)
674 continue;
675 if (!image->texturechain)
676 continue;
677 c_visible_textures++;
678
679 for ( s = image->texturechain; s ; s=s->texturechain)
680 {
681 if ( !( s->flags & SURF_DRAWTURB ) )
682 R_RenderBrushPoly (s);
683 }
684 }
685
686 GL_EnableMultitexture( false );
687 for ( i = 0, image=gltextures ; i<numgltextures ; i++,image++)
688 {
689 if (!image->registration_sequence)
690 continue;
691 s = image->texturechain;
692 if (!s)
693 continue;
694
695 for ( ; s ; s=s->texturechain)
696 {
697 if ( s->flags & SURF_DRAWTURB )
698 R_RenderBrushPoly (s);
699 }
700
701 image->texturechain = NULL;
702 }
703 // GL_EnableMultitexture( true );
704 }
705
706 GL_TexEnv( GL_REPLACE );
707 }
708
709
GL_RenderLightmappedPoly(msurface_t * surf)710 static void GL_RenderLightmappedPoly( msurface_t *surf )
711 {
712 int i, nv = surf->polys->numverts;
713 int map;
714 float *v;
715 image_t *image = R_TextureAnimation( surf->texinfo );
716 qboolean is_dynamic = false;
717 unsigned lmtex = surf->lightmaptexturenum;
718 glpoly_t *p;
719
720 for ( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ )
721 {
722 if ( r_newrefdef.lightstyles[surf->styles[map]].white != surf->cached_light[map] )
723 goto dynamic;
724 }
725
726 // dynamic this frame or dynamic previously
727 if ( ( surf->dlightframe == r_framecount ) )
728 {
729 dynamic:
730 if ( gl_dynamic->value )
731 {
732 if ( !(surf->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP ) ) )
733 {
734 is_dynamic = true;
735 }
736 }
737 }
738
739 if ( is_dynamic )
740 {
741 unsigned temp[128*128];
742 int smax, tmax;
743
744 if ( ( surf->styles[map] >= 32 || surf->styles[map] == 0 ) && ( surf->dlightframe != r_framecount ) )
745 {
746 smax = (surf->extents[0]>>4)+1;
747 tmax = (surf->extents[1]>>4)+1;
748
749 R_BuildLightMap( surf, (void *)temp, smax*4 );
750 R_SetCacheState( surf );
751
752 GL_MBind( QGL_TEXTURE1, gl_state.lightmap_textures + surf->lightmaptexturenum );
753
754 lmtex = surf->lightmaptexturenum;
755
756 qglTexSubImage2D( GL_TEXTURE_2D, 0,
757 surf->light_s, surf->light_t,
758 smax, tmax,
759 GL_LIGHTMAP_FORMAT,
760 GL_UNSIGNED_BYTE, temp );
761
762 }
763 else
764 {
765 smax = (surf->extents[0]>>4)+1;
766 tmax = (surf->extents[1]>>4)+1;
767
768 R_BuildLightMap( surf, (void *)temp, smax*4 );
769
770 GL_MBind( QGL_TEXTURE1, gl_state.lightmap_textures + 0 );
771
772 lmtex = 0;
773
774 qglTexSubImage2D( GL_TEXTURE_2D, 0,
775 surf->light_s, surf->light_t,
776 smax, tmax,
777 GL_LIGHTMAP_FORMAT,
778 GL_UNSIGNED_BYTE, temp );
779
780 }
781
782 c_brush_polys++;
783
784 GL_MBind( QGL_TEXTURE0, image->texnum );
785 GL_MBind( QGL_TEXTURE1, gl_state.lightmap_textures + lmtex );
786
787 //==========
788 //PGM
789 if (surf->texinfo->flags & SURF_FLOWING)
790 {
791 float scroll;
792
793 scroll = -64 * ( (r_newrefdef.time / 40.0) - (int)(r_newrefdef.time / 40.0) );
794 if(scroll == 0.0)
795 scroll = -64.0;
796
797 for ( p = surf->polys; p; p = p->chain )
798 {
799 v = p->verts[0];
800 qglBegin (GL_POLYGON);
801 for (i=0 ; i< nv; i++, v+= VERTEXSIZE)
802 {
803 qglMTexCoord2fSGIS( QGL_TEXTURE0, (v[3]+scroll), v[4]);
804 qglMTexCoord2fSGIS( QGL_TEXTURE1, v[5], v[6]);
805 qglVertex3fv (v);
806 }
807 qglEnd ();
808 }
809 }
810 else
811 {
812 for ( p = surf->polys; p; p = p->chain )
813 {
814 v = p->verts[0];
815 qglBegin (GL_POLYGON);
816 for (i=0 ; i< nv; i++, v+= VERTEXSIZE)
817 {
818 qglMTexCoord2fSGIS( QGL_TEXTURE0, v[3], v[4]);
819 qglMTexCoord2fSGIS( QGL_TEXTURE1, v[5], v[6]);
820 qglVertex3fv (v);
821 }
822 qglEnd ();
823 }
824 }
825 //PGM
826 //==========
827 }
828 else
829 {
830 c_brush_polys++;
831
832 GL_MBind( QGL_TEXTURE0, image->texnum );
833 GL_MBind( QGL_TEXTURE1, gl_state.lightmap_textures + lmtex );
834
835 //==========
836 //PGM
837 if (surf->texinfo->flags & SURF_FLOWING)
838 {
839 float scroll;
840
841 scroll = -64 * ( (r_newrefdef.time / 40.0) - (int)(r_newrefdef.time / 40.0) );
842 if(scroll == 0.0)
843 scroll = -64.0;
844
845 for ( p = surf->polys; p; p = p->chain )
846 {
847 v = p->verts[0];
848 qglBegin (GL_POLYGON);
849 for (i=0 ; i< nv; i++, v+= VERTEXSIZE)
850 {
851 qglMTexCoord2fSGIS( QGL_TEXTURE0, (v[3]+scroll), v[4]);
852 qglMTexCoord2fSGIS( QGL_TEXTURE1, v[5], v[6]);
853 qglVertex3fv (v);
854 }
855 qglEnd ();
856 }
857 }
858 else
859 {
860 //PGM
861 //==========
862 for ( p = surf->polys; p; p = p->chain )
863 {
864 v = p->verts[0];
865 qglBegin (GL_POLYGON);
866 for (i=0 ; i< nv; i++, v+= VERTEXSIZE)
867 {
868 qglMTexCoord2fSGIS( QGL_TEXTURE0, v[3], v[4]);
869 qglMTexCoord2fSGIS( QGL_TEXTURE1, v[5], v[6]);
870 qglVertex3fv (v);
871 }
872 qglEnd ();
873 }
874 //==========
875 //PGM
876 }
877 //PGM
878 //==========
879 }
880 }
881
882 /*
883 =================
884 R_DrawInlineBModel
885 =================
886 */
R_DrawInlineBModel(void)887 void R_DrawInlineBModel (void)
888 {
889 int i, k;
890 cplane_t *pplane;
891 float dot;
892 msurface_t *psurf;
893 dlight_t *lt;
894
895 // calculate dynamic lighting for bmodel
896 if ( !gl_flashblend->value )
897 {
898 lt = r_newrefdef.dlights;
899 for (k=0 ; k<r_newrefdef.num_dlights ; k++, lt++)
900 {
901 R_MarkLights (lt, 1<<k, currentmodel->nodes + currentmodel->firstnode);
902 }
903 }
904
905 psurf = ¤tmodel->surfaces[currentmodel->firstmodelsurface];
906
907 if ( currententity->flags & RF_TRANSLUCENT )
908 {
909 qglEnable (GL_BLEND);
910 qglColor4f (1,1,1,0.25);
911 GL_TexEnv( GL_MODULATE );
912 }
913
914 //
915 // draw texture
916 //
917 for (i=0 ; i<currentmodel->nummodelsurfaces ; i++, psurf++)
918 {
919 // find which side of the node we are on
920 pplane = psurf->plane;
921
922 dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
923
924 // draw the polygon
925 if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
926 (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
927 {
928 if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66) )
929 { // add to the translucent chain
930 psurf->texturechain = r_alpha_surfaces;
931 r_alpha_surfaces = psurf;
932 }
933 else if ( qglMTexCoord2fSGIS && !( psurf->flags & SURF_DRAWTURB ) )
934 {
935 GL_RenderLightmappedPoly( psurf );
936 }
937 else
938 {
939 GL_EnableMultitexture( false );
940 R_RenderBrushPoly( psurf );
941 GL_EnableMultitexture( true );
942 }
943 }
944 }
945
946 if ( !(currententity->flags & RF_TRANSLUCENT) )
947 {
948 if ( !qglMTexCoord2fSGIS )
949 R_BlendLightmaps ();
950 }
951 else
952 {
953 qglDisable (GL_BLEND);
954 qglColor4f (1,1,1,1);
955 GL_TexEnv( GL_REPLACE );
956 }
957 }
958
959 /*
960 =================
961 R_DrawBrushModel
962 =================
963 */
R_DrawBrushModel(entity_t * e)964 void R_DrawBrushModel (entity_t *e)
965 {
966 vec3_t mins, maxs;
967 int i;
968 qboolean rotated;
969
970 if (currentmodel->nummodelsurfaces == 0)
971 return;
972
973 currententity = e;
974 gl_state.currenttextures[0] = gl_state.currenttextures[1] = -1;
975
976 if (e->angles[0] || e->angles[1] || e->angles[2])
977 {
978 rotated = true;
979 for (i=0 ; i<3 ; i++)
980 {
981 mins[i] = e->origin[i] - currentmodel->radius;
982 maxs[i] = e->origin[i] + currentmodel->radius;
983 }
984 }
985 else
986 {
987 rotated = false;
988 VectorAdd (e->origin, currentmodel->mins, mins);
989 VectorAdd (e->origin, currentmodel->maxs, maxs);
990 }
991
992 if (R_CullBox (mins, maxs))
993 return;
994
995 qglColor3f (1,1,1);
996 memset (gl_lms.lightmap_surfaces, 0, sizeof(gl_lms.lightmap_surfaces));
997
998 VectorSubtract (r_newrefdef.vieworg, e->origin, modelorg);
999 if (rotated)
1000 {
1001 vec3_t temp;
1002 vec3_t forward, right, up;
1003
1004 VectorCopy (modelorg, temp);
1005 AngleVectors (e->angles, forward, right, up);
1006 modelorg[0] = DotProduct (temp, forward);
1007 modelorg[1] = -DotProduct (temp, right);
1008 modelorg[2] = DotProduct (temp, up);
1009 }
1010
1011 qglPushMatrix ();
1012 e->angles[0] = -e->angles[0]; // stupid quake bug
1013 e->angles[2] = -e->angles[2]; // stupid quake bug
1014 R_RotateForEntity (e);
1015 e->angles[0] = -e->angles[0]; // stupid quake bug
1016 e->angles[2] = -e->angles[2]; // stupid quake bug
1017
1018 GL_EnableMultitexture( true );
1019 GL_SelectTexture( QGL_TEXTURE0);
1020 GL_TexEnv( GL_REPLACE );
1021 GL_SelectTexture( QGL_TEXTURE1);
1022 GL_TexEnv( GL_MODULATE );
1023
1024 R_DrawInlineBModel ();
1025 GL_EnableMultitexture( false );
1026
1027 qglPopMatrix ();
1028 }
1029
1030 /*
1031 =============================================================
1032
1033 WORLD MODEL
1034
1035 =============================================================
1036 */
1037
1038 /*
1039 ================
1040 R_RecursiveWorldNode
1041 ================
1042 */
R_RecursiveWorldNode(mnode_t * node)1043 void R_RecursiveWorldNode (mnode_t *node)
1044 {
1045 int c, side, sidebit;
1046 cplane_t *plane;
1047 msurface_t *surf, **mark;
1048 mleaf_t *pleaf;
1049 float dot;
1050 image_t *image;
1051
1052 if (node->contents == CONTENTS_SOLID)
1053 return; // solid
1054
1055 if (node->visframe != r_visframecount)
1056 return;
1057 if (R_CullBox (node->minmaxs, node->minmaxs+3))
1058 return;
1059
1060 // if a leaf node, draw stuff
1061 if (node->contents != -1)
1062 {
1063 pleaf = (mleaf_t *)node;
1064
1065 // check for door connected areas
1066 if (r_newrefdef.areabits)
1067 {
1068 if (! (r_newrefdef.areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) )
1069 return; // not visible
1070 }
1071
1072 mark = pleaf->firstmarksurface;
1073 c = pleaf->nummarksurfaces;
1074
1075 if (c)
1076 {
1077 do
1078 {
1079 (*mark)->visframe = r_framecount;
1080 mark++;
1081 } while (--c);
1082 }
1083
1084 return;
1085 }
1086
1087 // node is just a decision point, so go down the apropriate sides
1088
1089 // find which side of the node we are on
1090 plane = node->plane;
1091
1092 switch (plane->type)
1093 {
1094 case PLANE_X:
1095 dot = modelorg[0] - plane->dist;
1096 break;
1097 case PLANE_Y:
1098 dot = modelorg[1] - plane->dist;
1099 break;
1100 case PLANE_Z:
1101 dot = modelorg[2] - plane->dist;
1102 break;
1103 default:
1104 dot = DotProduct (modelorg, plane->normal) - plane->dist;
1105 break;
1106 }
1107
1108 if (dot >= 0)
1109 {
1110 side = 0;
1111 sidebit = 0;
1112 }
1113 else
1114 {
1115 side = 1;
1116 sidebit = SURF_PLANEBACK;
1117 }
1118
1119 // recurse down the children, front side first
1120 R_RecursiveWorldNode (node->children[side]);
1121
1122 // draw stuff
1123 for ( c = node->numsurfaces, surf = r_worldmodel->surfaces + node->firstsurface; c ; c--, surf++)
1124 {
1125 if (surf->visframe != r_framecount)
1126 continue;
1127
1128 if ( (surf->flags & SURF_PLANEBACK) != sidebit )
1129 continue; // wrong side
1130
1131 if (surf->texinfo->flags & SURF_SKY)
1132 { // just adds to visible sky bounds
1133 R_AddSkySurface (surf);
1134 }
1135 else if (surf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
1136 { // add to the translucent chain
1137 surf->texturechain = r_alpha_surfaces;
1138 r_alpha_surfaces = surf;
1139 }
1140 else
1141 {
1142 if ( qglMTexCoord2fSGIS && !( surf->flags & SURF_DRAWTURB ) )
1143 {
1144 GL_RenderLightmappedPoly( surf );
1145 }
1146 else
1147 {
1148 // the polygon is visible, so add it to the texture
1149 // sorted chain
1150 // FIXME: this is a hack for animation
1151 image = R_TextureAnimation (surf->texinfo);
1152 surf->texturechain = image->texturechain;
1153 image->texturechain = surf;
1154 }
1155 }
1156 }
1157
1158 // recurse down the back side
1159 R_RecursiveWorldNode (node->children[!side]);
1160 /*
1161 for ( ; c ; c--, surf++)
1162 {
1163 if (surf->visframe != r_framecount)
1164 continue;
1165
1166 if ( (surf->flags & SURF_PLANEBACK) != sidebit )
1167 continue; // wrong side
1168
1169 if (surf->texinfo->flags & SURF_SKY)
1170 { // just adds to visible sky bounds
1171 R_AddSkySurface (surf);
1172 }
1173 else if (surf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
1174 { // add to the translucent chain
1175 // surf->texturechain = alpha_surfaces;
1176 // alpha_surfaces = surf;
1177 }
1178 else
1179 {
1180 if ( qglMTexCoord2fSGIS && !( surf->flags & SURF_DRAWTURB ) )
1181 {
1182 GL_RenderLightmappedPoly( surf );
1183 }
1184 else
1185 {
1186 // the polygon is visible, so add it to the texture
1187 // sorted chain
1188 // FIXME: this is a hack for animation
1189 image = R_TextureAnimation (surf->texinfo);
1190 surf->texturechain = image->texturechain;
1191 image->texturechain = surf;
1192 }
1193 }
1194 }
1195 */
1196 }
1197
1198
1199 /*
1200 =============
1201 R_DrawWorld
1202 =============
1203 */
R_DrawWorld(void)1204 void R_DrawWorld (void)
1205 {
1206 entity_t ent;
1207
1208 if (!r_drawworld->value)
1209 return;
1210
1211 if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
1212 return;
1213
1214 currentmodel = r_worldmodel;
1215
1216 VectorCopy (r_newrefdef.vieworg, modelorg);
1217
1218 // auto cycle the world frame for texture animation
1219 memset (&ent, 0, sizeof(ent));
1220 ent.frame = (int)(r_newrefdef.time*2);
1221 currententity = &ent;
1222
1223 gl_state.currenttextures[0] = gl_state.currenttextures[1] = -1;
1224
1225 qglColor3f (1,1,1);
1226 memset (gl_lms.lightmap_surfaces, 0, sizeof(gl_lms.lightmap_surfaces));
1227 R_ClearSkyBox ();
1228
1229 if ( qglMTexCoord2fSGIS )
1230 {
1231 GL_EnableMultitexture( true );
1232
1233 GL_SelectTexture( QGL_TEXTURE0);
1234 GL_TexEnv( GL_REPLACE );
1235 GL_SelectTexture( QGL_TEXTURE1);
1236
1237 if ( gl_lightmap->value )
1238 GL_TexEnv( GL_REPLACE );
1239 else
1240 GL_TexEnv( GL_MODULATE );
1241
1242 R_RecursiveWorldNode (r_worldmodel->nodes);
1243
1244 GL_EnableMultitexture( false );
1245 }
1246 else
1247 {
1248 R_RecursiveWorldNode (r_worldmodel->nodes);
1249 }
1250
1251 /*
1252 ** theoretically nothing should happen in the next two functions
1253 ** if multitexture is enabled
1254 */
1255 DrawTextureChains ();
1256 R_BlendLightmaps ();
1257
1258 R_DrawSkyBox ();
1259
1260 R_DrawTriangleOutlines ();
1261 }
1262
1263
1264 /*
1265 ===============
1266 R_MarkLeaves
1267
1268 Mark the leaves and nodes that are in the PVS for the current
1269 cluster
1270 ===============
1271 */
R_MarkLeaves(void)1272 void R_MarkLeaves (void)
1273 {
1274 byte *vis;
1275 byte fatvis[MAX_MAP_LEAFS/8];
1276 mnode_t *node;
1277 int i, c;
1278 mleaf_t *leaf;
1279 int cluster;
1280
1281 if (r_oldviewcluster == r_viewcluster && r_oldviewcluster2 == r_viewcluster2 && !r_novis->value && r_viewcluster != -1)
1282 return;
1283
1284 // development aid to let you run around and see exactly where
1285 // the pvs ends
1286 if (gl_lockpvs->value)
1287 return;
1288
1289 r_visframecount++;
1290 r_oldviewcluster = r_viewcluster;
1291 r_oldviewcluster2 = r_viewcluster2;
1292
1293 if (r_novis->value || r_viewcluster == -1 || !r_worldmodel->vis)
1294 {
1295 // mark everything
1296 for (i=0 ; i<r_worldmodel->numleafs ; i++)
1297 r_worldmodel->leafs[i].visframe = r_visframecount;
1298 for (i=0 ; i<r_worldmodel->numnodes ; i++)
1299 r_worldmodel->nodes[i].visframe = r_visframecount;
1300 return;
1301 }
1302
1303 vis = Mod_ClusterPVS (r_viewcluster, r_worldmodel);
1304 // may have to combine two clusters because of solid water boundaries
1305 if (r_viewcluster2 != r_viewcluster)
1306 {
1307 memcpy (fatvis, vis, (r_worldmodel->numleafs+7)/8);
1308 vis = Mod_ClusterPVS (r_viewcluster2, r_worldmodel);
1309 c = (r_worldmodel->numleafs+31)/32;
1310 for (i=0 ; i<c ; i++)
1311 ((int *)fatvis)[i] |= ((int *)vis)[i];
1312 vis = fatvis;
1313 }
1314
1315 for (i=0,leaf=r_worldmodel->leafs ; i<r_worldmodel->numleafs ; i++, leaf++)
1316 {
1317 cluster = leaf->cluster;
1318 if (cluster == -1)
1319 continue;
1320 if (vis[cluster>>3] & (1<<(cluster&7)))
1321 {
1322 node = (mnode_t *)leaf;
1323 do
1324 {
1325 if (node->visframe == r_visframecount)
1326 break;
1327 node->visframe = r_visframecount;
1328 node = node->parent;
1329 } while (node);
1330 }
1331 }
1332
1333 #if 0
1334 for (i=0 ; i<r_worldmodel->vis->numclusters ; i++)
1335 {
1336 if (vis[i>>3] & (1<<(i&7)))
1337 {
1338 node = (mnode_t *)&r_worldmodel->leafs[i]; // FIXME: cluster
1339 do
1340 {
1341 if (node->visframe == r_visframecount)
1342 break;
1343 node->visframe = r_visframecount;
1344 node = node->parent;
1345 } while (node);
1346 }
1347 }
1348 #endif
1349 }
1350
1351
1352
1353 /*
1354 =============================================================================
1355
1356 LIGHTMAP ALLOCATION
1357
1358 =============================================================================
1359 */
1360
LM_InitBlock(void)1361 static void LM_InitBlock( void )
1362 {
1363 memset( gl_lms.allocated, 0, sizeof( gl_lms.allocated ) );
1364 }
1365
LM_UploadBlock(qboolean dynamic)1366 static void LM_UploadBlock( qboolean dynamic )
1367 {
1368 int texture;
1369 int height = 0;
1370
1371 if ( dynamic )
1372 {
1373 texture = 0;
1374 }
1375 else
1376 {
1377 texture = gl_lms.current_lightmap_texture;
1378 }
1379
1380 GL_Bind( gl_state.lightmap_textures + texture );
1381 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1382 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1383
1384 if ( dynamic )
1385 {
1386 int i;
1387
1388 for ( i = 0; i < BLOCK_WIDTH; i++ )
1389 {
1390 if ( gl_lms.allocated[i] > height )
1391 height = gl_lms.allocated[i];
1392 }
1393
1394 qglTexSubImage2D( GL_TEXTURE_2D,
1395 0,
1396 0, 0,
1397 BLOCK_WIDTH, height,
1398 GL_LIGHTMAP_FORMAT,
1399 GL_UNSIGNED_BYTE,
1400 gl_lms.lightmap_buffer );
1401 }
1402 else
1403 {
1404 qglTexImage2D( GL_TEXTURE_2D,
1405 0,
1406 gl_lms.internal_format,
1407 BLOCK_WIDTH, BLOCK_HEIGHT,
1408 0,
1409 GL_LIGHTMAP_FORMAT,
1410 GL_UNSIGNED_BYTE,
1411 gl_lms.lightmap_buffer );
1412 if ( ++gl_lms.current_lightmap_texture == MAX_LIGHTMAPS )
1413 ri.Sys_Error( ERR_DROP, "LM_UploadBlock() - MAX_LIGHTMAPS exceeded\n" );
1414 }
1415 }
1416
1417 // returns a texture number and the position inside it
LM_AllocBlock(int w,int h,int * x,int * y)1418 static qboolean LM_AllocBlock (int w, int h, int *x, int *y)
1419 {
1420 int i, j;
1421 int best, best2;
1422
1423 best = BLOCK_HEIGHT;
1424
1425 for (i=0 ; i<BLOCK_WIDTH-w ; i++)
1426 {
1427 best2 = 0;
1428
1429 for (j=0 ; j<w ; j++)
1430 {
1431 if (gl_lms.allocated[i+j] >= best)
1432 break;
1433 if (gl_lms.allocated[i+j] > best2)
1434 best2 = gl_lms.allocated[i+j];
1435 }
1436 if (j == w)
1437 { // this is a valid spot
1438 *x = i;
1439 *y = best = best2;
1440 }
1441 }
1442
1443 if (best + h > BLOCK_HEIGHT)
1444 return false;
1445
1446 for (i=0 ; i<w ; i++)
1447 gl_lms.allocated[*x + i] = best + h;
1448
1449 return true;
1450 }
1451
1452 /*
1453 ================
1454 GL_BuildPolygonFromSurface
1455 ================
1456 */
GL_BuildPolygonFromSurface(msurface_t * fa)1457 void GL_BuildPolygonFromSurface(msurface_t *fa)
1458 {
1459 int i, lindex, lnumverts;
1460 medge_t *pedges, *r_pedge;
1461 int vertpage;
1462 float *vec;
1463 float s, t;
1464 glpoly_t *poly;
1465 vec3_t total;
1466
1467 // reconstruct the polygon
1468 pedges = currentmodel->edges;
1469 lnumverts = fa->numedges;
1470 vertpage = 0;
1471
1472 VectorClear (total);
1473 //
1474 // draw texture
1475 //
1476 poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float));
1477 poly->next = fa->polys;
1478 poly->flags = fa->flags;
1479 fa->polys = poly;
1480 poly->numverts = lnumverts;
1481
1482 for (i=0 ; i<lnumverts ; i++)
1483 {
1484 lindex = currentmodel->surfedges[fa->firstedge + i];
1485
1486 if (lindex > 0)
1487 {
1488 r_pedge = &pedges[lindex];
1489 vec = currentmodel->vertexes[r_pedge->v[0]].position;
1490 }
1491 else
1492 {
1493 r_pedge = &pedges[-lindex];
1494 vec = currentmodel->vertexes[r_pedge->v[1]].position;
1495 }
1496 s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
1497 s /= fa->texinfo->image->width;
1498
1499 t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
1500 t /= fa->texinfo->image->height;
1501
1502 VectorAdd (total, vec, total);
1503 VectorCopy (vec, poly->verts[i]);
1504 poly->verts[i][3] = s;
1505 poly->verts[i][4] = t;
1506
1507 //
1508 // lightmap texture coordinates
1509 //
1510 s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
1511 s -= fa->texturemins[0];
1512 s += fa->light_s*16;
1513 s += 8;
1514 s /= BLOCK_WIDTH*16; //fa->texinfo->texture->width;
1515
1516 t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
1517 t -= fa->texturemins[1];
1518 t += fa->light_t*16;
1519 t += 8;
1520 t /= BLOCK_HEIGHT*16; //fa->texinfo->texture->height;
1521
1522 poly->verts[i][5] = s;
1523 poly->verts[i][6] = t;
1524 }
1525
1526 poly->numverts = lnumverts;
1527
1528 }
1529
1530 /*
1531 ========================
1532 GL_CreateSurfaceLightmap
1533 ========================
1534 */
GL_CreateSurfaceLightmap(msurface_t * surf)1535 void GL_CreateSurfaceLightmap (msurface_t *surf)
1536 {
1537 int smax, tmax;
1538 byte *base;
1539
1540 if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB))
1541 return;
1542
1543 smax = (surf->extents[0]>>4)+1;
1544 tmax = (surf->extents[1]>>4)+1;
1545
1546 if ( !LM_AllocBlock( smax, tmax, &surf->light_s, &surf->light_t ) )
1547 {
1548 LM_UploadBlock( false );
1549 LM_InitBlock();
1550 if ( !LM_AllocBlock( smax, tmax, &surf->light_s, &surf->light_t ) )
1551 {
1552 ri.Sys_Error( ERR_FATAL, "Consecutive calls to LM_AllocBlock(%d,%d) failed\n", smax, tmax );
1553 }
1554 }
1555
1556 surf->lightmaptexturenum = gl_lms.current_lightmap_texture;
1557
1558 base = gl_lms.lightmap_buffer;
1559 base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * LIGHTMAP_BYTES;
1560
1561 R_SetCacheState( surf );
1562 R_BuildLightMap (surf, base, BLOCK_WIDTH*LIGHTMAP_BYTES);
1563 }
1564
1565
1566 /*
1567 ==================
1568 GL_BeginBuildingLightmaps
1569
1570 ==================
1571 */
GL_BeginBuildingLightmaps(model_t * m)1572 void GL_BeginBuildingLightmaps (model_t *m)
1573 {
1574 static lightstyle_t lightstyles[MAX_LIGHTSTYLES];
1575 int i;
1576 unsigned dummy[128*128];
1577
1578 memset( gl_lms.allocated, 0, sizeof(gl_lms.allocated) );
1579
1580 r_framecount = 1; // no dlightcache
1581
1582 GL_EnableMultitexture( true );
1583 GL_SelectTexture( QGL_TEXTURE1);
1584
1585 /*
1586 ** setup the base lightstyles so the lightmaps won't have to be regenerated
1587 ** the first time they're seen
1588 */
1589 for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
1590 {
1591 lightstyles[i].rgb[0] = 1;
1592 lightstyles[i].rgb[1] = 1;
1593 lightstyles[i].rgb[2] = 1;
1594 lightstyles[i].white = 3;
1595 }
1596 r_newrefdef.lightstyles = lightstyles;
1597
1598 if (!gl_state.lightmap_textures)
1599 {
1600 gl_state.lightmap_textures = TEXNUM_LIGHTMAPS;
1601 // gl_state.lightmap_textures = gl_state.texture_extension_number;
1602 // gl_state.texture_extension_number = gl_state.lightmap_textures + MAX_LIGHTMAPS;
1603 }
1604
1605 gl_lms.current_lightmap_texture = 1;
1606
1607 /*
1608 ** if mono lightmaps are enabled and we want to use alpha
1609 ** blending (a,1-a) then we're likely running on a 3DLabs
1610 ** Permedia2. In a perfect world we'd use a GL_ALPHA lightmap
1611 ** in order to conserve space and maximize bandwidth, however
1612 ** this isn't a perfect world.
1613 **
1614 ** So we have to use alpha lightmaps, but stored in GL_RGBA format,
1615 ** which means we only get 1/16th the color resolution we should when
1616 ** using alpha lightmaps. If we find another board that supports
1617 ** only alpha lightmaps but that can at least support the GL_ALPHA
1618 ** format then we should change this code to use real alpha maps.
1619 */
1620 if ( toupper( gl_monolightmap->string[0] ) == 'A' )
1621 {
1622 gl_lms.internal_format = gl_tex_alpha_format;
1623 }
1624 /*
1625 ** try to do hacked colored lighting with a blended texture
1626 */
1627 else if ( toupper( gl_monolightmap->string[0] ) == 'C' )
1628 {
1629 gl_lms.internal_format = gl_tex_alpha_format;
1630 }
1631 else if ( toupper( gl_monolightmap->string[0] ) == 'I' )
1632 {
1633 gl_lms.internal_format = GL_INTENSITY8;
1634 }
1635 else if ( toupper( gl_monolightmap->string[0] ) == 'L' )
1636 {
1637 gl_lms.internal_format = GL_LUMINANCE8;
1638 }
1639 else
1640 {
1641 gl_lms.internal_format = gl_tex_solid_format;
1642 }
1643
1644 /*
1645 ** initialize the dynamic lightmap texture
1646 */
1647 GL_Bind( gl_state.lightmap_textures + 0 );
1648 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1649 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1650 qglTexImage2D( GL_TEXTURE_2D,
1651 0,
1652 gl_lms.internal_format,
1653 BLOCK_WIDTH, BLOCK_HEIGHT,
1654 0,
1655 GL_LIGHTMAP_FORMAT,
1656 GL_UNSIGNED_BYTE,
1657 dummy );
1658 }
1659
1660 /*
1661 =======================
1662 GL_EndBuildingLightmaps
1663 =======================
1664 */
GL_EndBuildingLightmaps(void)1665 void GL_EndBuildingLightmaps (void)
1666 {
1667 LM_UploadBlock( false );
1668 GL_EnableMultitexture( false );
1669 }
1670
1671