11 transvert_t *transvert;
12 transpoly_t *transpoly;
13 rendertranspoly_t *rendertranspoly;
17 wallvertcolor_t *wallvertcolor;
32 cvar_t r_multitexture = {0, "r_multitexture", "1"};
33 cvar_t r_skyquality = {CVAR_SAVE, "r_skyquality", "2"};
34 cvar_t r_mergesky = {CVAR_SAVE, "r_mergesky", "0"};
35 cvar_t gl_transpolytris = {0, "gl_transpolytris", "0"};
37 static char skyworldname[1024];
38 static rtexture_t *mergeskytexture;
39 static rtexture_t *solidskytexture, *solidskytexture_half;
40 static rtexture_t *alphaskytexture, *alphaskytexture_half;
41 static qboolean skyavailable_quake;
42 static qboolean skyavailable_box;
44 static void R_BuildSky (int scrollupper, int scrolllower);
46 typedef struct translistitem_s
49 struct translistitem_s *next;
53 translistitem translist[MAX_TRANSPOLYS];
54 translistitem *currenttranslist;
56 translistitem *translisthash[4096];
58 float transviewdist; // distance of view origin along the view normal
60 float transreciptable[256];
62 static void gl_poly_start(void)
65 transvert = qmalloc(MAX_TRANSVERTS * sizeof(transvert_t));
66 transpoly = qmalloc(MAX_TRANSPOLYS * sizeof(transpoly_t));
67 rendertranspoly = qmalloc(MAX_TRANSPOLYS * sizeof(rendertranspoly_t));
68 transpolyindex = qmalloc(MAX_TRANSPOLYS * sizeof(int));
69 transvertindex = qmalloc(MAX_TRANSVERTS * sizeof(int));
70 wallvert = qmalloc(MAX_WALLVERTS * sizeof(wallvert_t));
71 wallvertcolor = qmalloc(MAX_WALLVERTS * sizeof(wallvertcolor_t));
72 wallpoly = qmalloc(MAX_WALLPOLYS * sizeof(wallpoly_t));
73 skyvert = qmalloc(MAX_SKYVERTS * sizeof(skyvert_t));
74 skypoly = qmalloc(MAX_SKYPOLYS * sizeof(skypoly_t));
75 transreciptable[0] = 0.0f;
76 for (i = 1;i < 256;i++)
77 transreciptable[i] = 1.0f / i;
80 static void gl_poly_shutdown(void)
84 qfree(rendertranspoly);
85 qfree(transpolyindex);
86 qfree(transvertindex);
94 static void gl_poly_newmap(void)
96 skyavailable_box = false;
97 skyavailable_quake = false;
98 if (!strcmp(skyworldname, cl.worldmodel->name))
99 skyavailable_quake = true;
102 void GL_Poly_Init(void)
104 Cmd_AddCommand ("loadsky", &LoadSky_f);
105 Cvar_RegisterVariable (&r_multitexture);
106 Cvar_RegisterVariable (&r_skyquality);
107 Cvar_RegisterVariable (&r_mergesky);
108 Cvar_RegisterVariable (&gl_transpolytris);
109 R_RegisterModule("GL_Poly", gl_poly_start, gl_poly_shutdown, gl_poly_newmap);
112 void transpolyclear(void)
114 currenttranspoly = currenttransvert = 0;
115 currenttranslist = translist;
116 memset(translisthash, 0, sizeof(translisthash));
117 transviewdist = DotProduct(r_origin, vpn);
120 // transpolybegin and transpolyvert are #define macros
122 void transpolyend(void)
124 float center, d, maxdist;
127 if (currenttranspoly >= MAX_TRANSPOLYS || currenttransvert >= MAX_TRANSVERTS)
129 if (transpoly[currenttranspoly].verts < 3) // skip invalid polygons
131 currenttransvert = transpoly[currenttranspoly].firstvert; // reset vert pointer
135 maxdist = -1000000000000000.0f; // eh, it's definitely behind it, so...
136 for (i = 0,v = &transvert[transpoly[currenttranspoly].firstvert];i < transpoly[currenttranspoly].verts;i++, v++)
138 d = DotProduct(v->v, vpn);
143 maxdist -= transviewdist;
144 if (maxdist < 4.0f) // behind view
146 currenttransvert = transpoly[currenttranspoly].firstvert; // reset vert pointer
149 center *= transreciptable[transpoly[currenttranspoly].verts];
150 center -= transviewdist;
151 i = bound(0, (int) center, 4095);
152 currenttranslist->next = translisthash[i];
153 currenttranslist->poly = transpoly + currenttranspoly;
154 translisthash[i] = currenttranslist;
159 void transpolyparticle(vec3_t org, vec3_t right, vec3_t up, vec_t scale, unsigned short texnum, unsigned short transpolytype, int ir, int ig, int ib, float alphaf, float s1, float t1, float s2, float t2)
161 float center, scale2;
167 center = DotProduct(org, vpn) - transviewdist;
168 if (center < 4.0f || currenttranspoly >= MAX_TRANSPOLYS || (currenttransvert + 4) > MAX_TRANSVERTS)
171 p = transpoly + (currenttranspoly++);
172 v = transvert + currenttransvert;
180 ir = bound(0, ir, 255);
181 ig = bound(0, ig, 255);
182 ib = bound(0, ib, 255);
195 alphaf += 8388608.0f;
196 i = *((long *)&alphaf) & 0x007FFFFF;
201 center += 8388608.0f;
202 i = *((long *)¢er) & 0x007FFFFF;
204 i = bound(0, i, 4095);
205 currenttranslist->next = translisthash[i];
206 currenttranslist->poly = p;
207 translisthash[i] = currenttranslist++;
209 p->texnum = p->fogtexnum = texnum;
211 p->transpolytype = transpolytype;
212 p->firstvert = currenttransvert;
214 currenttransvert += 4;
216 scale2 = scale * -0.5f;
217 corner[0] = org[0] + (up[0] + right[0]) * scale2;
218 corner[1] = org[1] + (up[1] + right[1]) * scale2;
219 corner[2] = org[2] + (up[2] + right[2]) * scale2;
236 v->v[0] = corner[0] + up[0] * scale;
237 v->v[1] = corner[1] + up[1] * scale;
238 v->v[2] = corner[2] + up[2] * scale;
246 v->v[0] = corner[0] + (up[0] + right[0]) * scale;
247 v->v[1] = corner[1] + (up[1] + right[1]) * scale;
248 v->v[2] = corner[2] + (up[2] + right[2]) * scale;
256 v->v[0] = corner[0] + right[0] * scale;
257 v->v[1] = corner[1] + right[1] * scale;
258 v->v[2] = corner[2] + right[2] * scale;
262 void transpolyrender(void)
264 int i, j, k, l, tpolytype, texnum, transvertindices, alpha, currentrendertranspoly;
265 byte fogr, fogg, fogb;
268 rendertranspoly_t *r, *rend;
273 if (currenttranspoly < 1)
276 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
278 // glShadeModel(GL_SMOOTH);
279 glDepthMask(0); // disable zbuffer updates
281 // set up the vertex array
282 glInterleavedArrays(GL_T2F_C4UB_V3F, sizeof(transvert[0]), transvert);
284 currentrendertranspoly = 0;
285 transvertindices = 0;
286 fogr = (byte) bound(0, (int) (fogcolor[0] * 255.0f), 255);
287 fogg = (byte) bound(0, (int) (fogcolor[1] * 255.0f), 255);
288 fogb = (byte) bound(0, (int) (fogcolor[2] * 255.0f), 255);
289 if (gl_transpolytris.value)
291 int glowtexnum, fogtexnum;
292 for (i = 4095;i >= 0;i--)
294 item = translisthash[i];
299 glowtexnum = p->glowtexnum;
300 fogtexnum = p->fogtexnum;
302 #define POLYTOTRI(pfirstvert, ptexnum, ptranspolytype) \
304 r = &rendertranspoly[currentrendertranspoly++];\
306 r->type = ptranspolytype;\
309 transvertindex[transvertindices] = l;\
310 transvertindex[transvertindices + 1] = l + 1;\
311 transvertindex[transvertindices + 2] = l + 2;\
312 transvertindex[transvertindices + 3] = l;\
313 transvertindex[transvertindices + 4] = l + 2;\
314 transvertindex[transvertindices + 5] = l + 3;\
315 transvertindices += 6;\
318 else if (p->verts == 3)\
320 transvertindex[transvertindices] = l;\
321 transvertindex[transvertindices + 1] = l + 1;\
322 transvertindex[transvertindices + 2] = l + 2;\
323 transvertindices += 3;\
328 for (j = l + p->verts, k = l + 2;k < j;k++)\
330 transvertindex[transvertindices] = l;\
331 transvertindex[transvertindices + 1] = k - 1;\
332 transvertindex[transvertindices + 2] = k;\
333 transvertindices += 3;\
335 r->indices = (p->verts - 2) * 3;\
338 POLYTOTRI(p->firstvert, p->texnum, p->transpolytype)
342 // make another poly for glow effect
343 if (currenttranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS)
345 memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts);
346 POLYTOTRI(currenttransvert, p->glowtexnum, TPOLYTYPE_ADD)
347 for (j = 0;j < p->verts;j++)
349 transvert[currenttransvert].r = transvert[currenttransvert].g = transvert[currenttransvert].b = 255;
357 // make another poly for fog
358 if (currenttranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS)
360 memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts);
361 POLYTOTRI(currenttransvert, p->fogtexnum, TPOLYTYPE_ALPHA)
362 for (j = 0, k = p->firstvert;j < p->verts;j++, k++)
364 transvert[currenttransvert].r = fogr;
365 transvert[currenttransvert].g = fogg;
366 transvert[currenttransvert].b = fogb;
367 VectorSubtract(transvert[currenttransvert].v, r_origin, diff);
368 alpha = transvert[currenttransvert].a * exp(fogdensity / DotProduct(diff, diff));
369 transvert[currenttransvert].a = (byte) bound(0, alpha, 255);
379 for (i = 4095;i >= 0;i--)
381 item = translisthash[i];
388 r = &rendertranspoly[currentrendertranspoly++];
390 r->type = p->transpolytype;
391 r->indices = p->verts;
393 for (j = l + p->verts, k = l;k < j;k++)
394 transvertindex[transvertindices++] = k;
398 // make another poly for glow effect
399 if (currentrendertranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS)
401 l = currenttransvert;
402 r = &rendertranspoly[currentrendertranspoly++];
403 r->tex = p->glowtexnum;
404 r->type = TPOLYTYPE_ADD;
405 r->indices = p->verts;
407 memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts);
408 for (j = 0;j < p->verts;j++)
410 transvert[currenttransvert].r = transvert[currenttransvert].g = transvert[currenttransvert].b = 255;
411 transvertindex[transvertindices++] = currenttransvert++;
417 // make another poly for fog
418 if (currentrendertranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS)
420 l = currenttransvert;
421 r = &rendertranspoly[currentrendertranspoly++];
422 r->tex = p->fogtexnum;
423 r->type = TPOLYTYPE_ALPHA;
424 r->indices = p->verts;
426 memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts);
427 for (j = 0;j < p->verts;j++)
429 transvert[currenttransvert].r = fogr;
430 transvert[currenttransvert].g = fogg;
431 transvert[currenttransvert].b = fogb;
432 VectorSubtract(transvert[currenttransvert].v, r_origin, diff);
433 alpha = transvert[currenttransvert].a * exp(fogdensity / DotProduct(diff, diff));
434 transvert[currenttransvert].a = (byte) bound(0, alpha, 255);
435 transvertindex[transvertindices++] = currenttransvert++;
443 GL_LockArray(0, currenttransvert);
445 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
446 tpolytype = TPOLYTYPE_ALPHA;
448 transvertindices = 0;
450 rend = r + currentrendertranspoly;
453 if (texnum != r->tex)
456 glBindTexture(GL_TEXTURE_2D, texnum);
458 if (tpolytype != r->type)
461 if (tpolytype == TPOLYTYPE_ADD) // additive
462 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
464 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
466 k = transvertindices;
467 if (gl_transpolytris.value)
470 transvertindices += r->indices, r++;
471 while (r < rend && r->tex == texnum && r->type == tpolytype);
472 glDrawElements(GL_TRIANGLES, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]);
479 transvertindices += 4, r++;
480 while (r < rend && r->indices == 4 && r->tex == texnum && r->type == tpolytype);
481 glDrawElements(GL_QUADS, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]);
483 else if (r->indices == 3)
486 transvertindices += 3, r++;
487 while (r < rend && r->indices == 3 && r->tex == texnum && r->type == tpolytype);
488 glDrawElements(GL_TRIANGLES, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]);
492 transvertindices += r->indices, r++;
493 glDrawElements(GL_POLYGON, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]);
500 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
501 glDepthMask(1); // enable zbuffer updates
505 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
506 glDisableClientState(GL_COLOR_ARRAY);
507 glDisableClientState(GL_VERTEX_ARRAY);
511 void wallpolyclear(void)
514 r_multitexture.value = 0;
515 currentwallpoly = currentwallvert = 0;
518 // render walls and fullbrights, but not fog
519 void wallpolyrender1(void)
521 int i, j, texnum, lighttexnum;
524 wallvertcolor_t *vertcolor;
527 if (currentwallpoly < 1)
529 c_brush_polys += currentwallpoly;
531 //Con_DPrintf("wallpolyrender: %i polys %i vertices\n", currentwallpoly, currentwallvert);
533 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
534 // glShadeModel(GL_FLAT);
535 // make sure zbuffer is enabled
536 glEnable(GL_DEPTH_TEST);
537 // glDisable(GL_ALPHA_TEST);
540 if (r_fullbright.value) // LordHavoc: easy to do fullbright...
542 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
544 for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
546 if (p->texnum != texnum)
549 glBindTexture(GL_TEXTURE_2D, texnum);
551 vert = &wallvert[p->firstvert];
553 for (j=0 ; j<p->numverts ; j++, vert++)
555 glTexCoord2f (vert->vert[3], vert->vert[4]);
556 glVertex3fv (vert->vert);
561 else if (r_multitexture.value)
563 if (gl_combine.value)
565 qglActiveTexture(GL_TEXTURE0_ARB);
566 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
567 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
568 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
569 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
570 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
571 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
572 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
573 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
574 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
575 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
576 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
577 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_TEXTURE);
578 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
579 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
580 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
581 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0);
582 glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0);
583 glEnable(GL_TEXTURE_2D);
584 qglActiveTexture(GL_TEXTURE1_ARB);
585 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
586 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
587 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
588 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
589 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
590 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
591 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
592 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
593 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
594 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
595 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
596 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_TEXTURE);
597 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
598 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
599 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
600 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 4.0);
601 glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0);
602 glEnable(GL_TEXTURE_2D);
606 qglActiveTexture(GL_TEXTURE0_ARB);
607 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
608 glEnable(GL_TEXTURE_2D);
609 qglActiveTexture(GL_TEXTURE1_ARB);
610 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
611 glEnable(GL_TEXTURE_2D);
615 for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
617 if (p->texnum != texnum)
620 qglActiveTexture(GL_TEXTURE0_ARB);
621 glBindTexture(GL_TEXTURE_2D, texnum);
622 qglActiveTexture(GL_TEXTURE1_ARB);
624 if (p->lighttexnum != lighttexnum)
626 lighttexnum = p->lighttexnum;
627 glBindTexture(GL_TEXTURE_2D, lighttexnum);
629 vert = &wallvert[p->firstvert];
631 for (j=0 ; j<p->numverts ; j++, vert++)
633 qglMultiTexCoord2f(GL_TEXTURE0_ARB, vert->vert[3], vert->vert[4]); // texture
634 qglMultiTexCoord2f(GL_TEXTURE1_ARB, vert->vert[5], vert->vert[6]); // lightmap
635 glVertex3fv (vert->vert);
640 qglActiveTexture(GL_TEXTURE1_ARB);
641 glDisable(GL_TEXTURE_2D);
642 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
643 qglActiveTexture(GL_TEXTURE0_ARB);
644 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
648 // first do the textures
649 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
651 for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
653 if (p->texnum != texnum)
656 glBindTexture(GL_TEXTURE_2D, texnum);
658 vert = &wallvert[p->firstvert];
660 for (j=0 ; j<p->numverts ; j++, vert++)
662 glTexCoord2f (vert->vert[3], vert->vert[4]);
663 glVertex3fv (vert->vert);
667 // then modulate using the lightmaps
668 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
669 glBlendFunc(GL_ZERO, GL_SRC_COLOR);
672 for (i = 0,p = wallpoly;i < currentwallpoly;i++, p++)
674 if (p->lighttexnum != texnum)
676 texnum = p->lighttexnum;
677 glBindTexture(GL_TEXTURE_2D, texnum);
679 vert = &wallvert[p->firstvert];
681 for (j=0 ; j<p->numverts ; j++, vert++)
683 glTexCoord2f (vert->vert[5], vert->vert[6]);
684 glVertex3fv (vert->vert);
689 // switch to additive mode settings
691 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
692 glBlendFunc(GL_ONE, GL_ONE);
694 // glDisable(GL_ALPHA_TEST);
695 // glShadeModel(GL_SMOOTH);
696 // render vertex lit overlays ontop
698 for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
702 for (j = 0,vertcolor = &wallvertcolor[p->firstvert];j < p->numverts;j++, vertcolor++)
703 if (vertcolor->r || vertcolor->g || vertcolor->b)
708 if (p->texnum != texnum)
711 glBindTexture(GL_TEXTURE_2D, texnum);
714 for (j = 0,vert = &wallvert[p->firstvert], vertcolor = &wallvertcolor[p->firstvert];j < p->numverts;j++, vert++, vertcolor++)
716 // would be 2fv, but windoze Matrox G200 and probably G400 drivers don't support that (dumb...)
717 glTexCoord2f(vert->vert[3], vert->vert[4]);
718 // again, vector version isn't supported I think
719 glColor3ub(vertcolor->r, vertcolor->g, vertcolor->b);
720 glVertex3fv(vert->vert);
724 // render glow textures
725 // glShadeModel(GL_FLAT);
727 glColor3f(0.5,0.5,0.5);
731 for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
735 if (p->glowtexnum != texnum)
737 texnum = p->glowtexnum;
738 glBindTexture(GL_TEXTURE_2D, texnum);
740 vert = &wallvert[p->firstvert];
742 for (j=0 ; j<p->numverts ; j++, vert++)
744 glTexCoord2f (vert->vert[3], vert->vert[4]);
745 glVertex3fv (vert->vert);
750 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
751 // glDisable(GL_ALPHA_TEST);
752 // glShadeModel(GL_SMOOTH);
758 void wallpolyrender2(void)
762 if (currentwallpoly < 1)
766 int i, j, alpha, fogr, fogg, fogb;
770 glEnable(GL_DEPTH_TEST);
772 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
773 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
775 // glShadeModel(GL_SMOOTH);
776 glDisable(GL_TEXTURE_2D);
777 fogr = (byte) bound(0, (int) (fogcolor[0] * 255.0f), 255);
778 fogg = (byte) bound(0, (int) (fogcolor[1] * 255.0f), 255);
779 fogb = (byte) bound(0, (int) (fogcolor[2] * 255.0f), 255);
780 for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
782 vert = &wallvert[p->firstvert];
784 for (j=0 ; j<p->numverts ; j++, vert++)
786 VectorSubtract(vert->vert, r_origin, diff);
787 alpha = 255.0f * exp(fogdensity/DotProduct(diff,diff));
788 alpha = bound(0, alpha, 255);
789 glColor4ub(fogr, fogg, fogb, (byte) alpha);
790 glVertex3fv (vert->vert);
794 glEnable(GL_TEXTURE_2D);
801 static int skyrendersphere;
802 static int skyrenderbox;
803 static int skyrenderglquakepolys;
804 static int skyrendertwolayers;
805 static int skyrendercombine;
807 void skypolyclear(void)
809 currentskypoly = currentskyvert = 0;
810 skyrendersphere = false;
811 skyrenderbox = false;
812 skyrenderglquakepolys = false;
813 skyrendertwolayers = false;
814 skyrendercombine = false;
815 if (r_skyquality.value >= 1 && !fogenabled)
817 if (skyavailable_box)
819 else if (skyavailable_quake)
821 switch((int) r_skyquality.value)
824 skyrenderglquakepolys = true;
827 skyrenderglquakepolys = true;
828 skyrendertwolayers = true;
829 if (gl_combine.value)
830 skyrendercombine = true;
833 skyrendersphere = true;
837 skyrendersphere = true;
838 skyrendertwolayers = true;
839 if (gl_combine.value)
840 skyrendercombine = true;
845 if (r_mergesky.value && (skyrenderglquakepolys || skyrendersphere))
847 skyrendertwolayers = false;
848 skyrendercombine = false;
849 // R_BuildSky((int) (cl.time * 8.0), (int) (cl.time * 16.0));
850 // R_BuildSky((int) (cl.time * -8.0), 0);
851 R_BuildSky(0, (int) (cl.time * 8.0));
856 static void R_Sky(void);
858 void skypolyrender(void)
863 float length, speedscale;
868 if (currentskypoly < 1)
870 // glDisable(GL_ALPHA_TEST);
872 // make sure zbuffer is enabled
873 glEnable(GL_DEPTH_TEST);
875 glVertexPointer(3, GL_FLOAT, sizeof(skyvert_t), &skyvert[0].v[0]);
876 glEnableClientState(GL_VERTEX_ARRAY);
877 GL_LockArray(0, currentskyvert);
878 speedscale = cl.time * (8.0/128.0);
879 speedscale -= (int)speedscale;
880 for (vert = skyvert, j = 0;j < currentskyvert;j++, vert++)
882 VectorSubtract (vert->v, r_origin, dir);
883 // flatten the sphere
886 // LordHavoc: fast version
887 number = DotProduct(dir, dir);
888 *((long *)&y) = 0x5f3759df - ((* (long *) &number) >> 1);
889 length = 3.0f * (y * (1.5f - (number * 0.5f * y * y)));
890 // LordHavoc: slow version
891 //length = 3.0f / sqrt(DotProduct(dir, dir));
893 vert->tex2[0] = speedscale + (vert->tex[0] = speedscale + dir[0] * length);
894 vert->tex2[1] = speedscale + (vert->tex[1] = speedscale + dir[1] * length);
898 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
900 if (skyrenderglquakepolys)
902 glTexCoordPointer(2, GL_FLOAT, sizeof(skyvert_t), &skyvert[0].tex[0]);
903 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
905 if (skyrendercombine)
908 glBindTexture(GL_TEXTURE_2D, R_GetTexture(lighthalf ? solidskytexture_half : solidskytexture));
910 // set up the second texcoord array
911 // switch texcoord array selector to TMU 1
912 qglClientActiveTexture(GL_TEXTURE1_ARB);
913 glTexCoordPointer(2, GL_FLOAT, sizeof(skyvert_t), &skyvert[0].tex2[0]);
914 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
916 // render both layers as one pass using GL_ARB_texture_env_combine
917 // TMU 0 is already selected, the TMU 0 texcoord array is already
918 // set up, the texture is bound, and texturing is already enabled,
919 // so just set up COMBINE
921 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
923 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
924 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
925 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
926 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
927 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
928 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
929 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
931 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
932 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
933 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
934 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_TEXTURE);
935 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
936 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
937 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
939 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0);
940 glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0);
943 qglActiveTexture(GL_TEXTURE1_ARB);
945 glBindTexture(GL_TEXTURE_2D, R_GetTexture(lighthalf ? alphaskytexture_half : alphaskytexture));
947 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
949 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
950 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
951 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
952 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
953 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
954 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
955 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
957 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
958 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
959 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
960 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_TEXTURE);
961 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
962 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
963 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
965 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0);
966 glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0);
967 glEnable(GL_TEXTURE_2D);
970 for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
971 glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
973 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
974 glDisable(GL_TEXTURE_2D);
975 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
976 qglActiveTexture(GL_TEXTURE0_ARB);
977 // switch texcoord array selector back to TMU 0
978 qglClientActiveTexture(GL_TEXTURE0_ARB);
979 // the TMU 0 texcoord array is disabled by the code below
983 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
984 if (r_mergesky.value)
985 glBindTexture(GL_TEXTURE_2D, R_GetTexture(mergeskytexture)); // both layers in one texture
987 glBindTexture(GL_TEXTURE_2D, R_GetTexture(solidskytexture)); // upper clouds
989 glColor3f(0.5f, 0.5f, 0.5f);
991 glColor3f(1.0f,1.0f,1.0f);
992 glEnable(GL_TEXTURE_2D);
993 GL_LockArray(0, currentskyvert);
994 for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
995 glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
997 if (skyrendertwolayers)
1001 glBindTexture(GL_TEXTURE_2D, R_GetTexture(alphaskytexture)); // lower clouds
1002 // switch to lower clouds texcoord array
1003 glTexCoordPointer(2, GL_FLOAT, sizeof(skyvert_t), &skyvert[0].tex2[0]);
1004 for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
1005 glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
1007 glDisable(GL_BLEND);
1011 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1015 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1016 glDisable(GL_TEXTURE_2D);
1017 // note: this color is not seen if skyrendersphere or skyrenderbox is on
1018 glColor3fv(fogcolor);
1019 for (i = 0, p = &skypoly[0];i < currentskypoly;i++, p++)
1020 glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
1022 glEnable(GL_TEXTURE_2D);
1025 glDisableClientState(GL_VERTEX_ARRAY);
1030 static char skyname[256];
1037 static char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
1038 static rtexture_t *skyboxside[6];
1039 int R_SetSkyBox(char *sky)
1045 if (strcmp(sky, skyname) == 0) // no change
1048 if (strlen(sky) > 1000)
1050 Con_Printf ("sky name too long (%i, max is 1000)\n", strlen(sky));
1054 skyboxside[0] = skyboxside[1] = skyboxside[2] = skyboxside[3] = skyboxside[4] = skyboxside[5] = NULL;
1055 skyavailable_box = false;
1061 for (i = 0;i < 6;i++)
1063 sprintf (name, "env/%s%s", sky, suf[i]);
1064 if (!(image_rgba = loadimagepixels(name, false, 0, 0)))
1066 sprintf (name, "gfx/env/%s%s", sky, suf[i]);
1067 if (!(image_rgba = loadimagepixels(name, false, 0, 0)))
1069 Con_Printf ("Couldn't load env/%s%s or gfx/env/%s%s\n", sky, suf[i], sky, suf[i]);
1073 skyboxside[i] = R_LoadTexture(va("skyboxside%d", i), image_width, image_height, image_rgba, TEXF_RGBA | TEXF_PRECACHE);
1077 if (skyboxside[0] || skyboxside[1] || skyboxside[2] || skyboxside[3] || skyboxside[4] || skyboxside[5])
1079 skyavailable_box = true;
1080 strcpy(skyname, sky);
1086 // LordHavoc: added LoadSky console command
1087 void LoadSky_f (void)
1093 Con_Printf("current sky: %s\n", skyname);
1095 Con_Printf("no skybox has been set\n");
1098 if (R_SetSkyBox(Cmd_Argv(1)))
1101 Con_Printf("skybox set to %s\n", skyname);
1103 Con_Printf("skybox disabled\n");
1106 Con_Printf("failed to load skybox %s\n", Cmd_Argv(1));
1109 Con_Printf("usage: loadsky skyname\n");
1114 #define R_SkyBoxPolyVec(s,t,x,y,z) \
1115 glTexCoord2f((s) * (254.0f/256.0f) + (1.0f/256.0f), (t) * (254.0f/256.0f) + (1.0f/256.0f));\
1116 glVertex3f((x) * 1024.0 + r_origin[0], (y) * 1024.0 + r_origin[1], (z) * 1024.0 + r_origin[2]);
1118 static void R_SkyBox(void)
1120 glDisable(GL_DEPTH_TEST);
1122 glDisable (GL_BLEND);
1123 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1125 glColor3f(0.5,0.5,0.5);
1128 glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[3])); // front
1130 R_SkyBoxPolyVec(1, 0, 1, -1, 1);
1131 R_SkyBoxPolyVec(1, 1, 1, -1, -1);
1132 R_SkyBoxPolyVec(0, 1, 1, 1, -1);
1133 R_SkyBoxPolyVec(0, 0, 1, 1, 1);
1135 glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[1])); // back
1137 R_SkyBoxPolyVec(1, 0, -1, 1, 1);
1138 R_SkyBoxPolyVec(1, 1, -1, 1, -1);
1139 R_SkyBoxPolyVec(0, 1, -1, -1, -1);
1140 R_SkyBoxPolyVec(0, 0, -1, -1, 1);
1142 glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[0])); // right
1144 R_SkyBoxPolyVec(1, 0, 1, 1, 1);
1145 R_SkyBoxPolyVec(1, 1, 1, 1, -1);
1146 R_SkyBoxPolyVec(0, 1, -1, 1, -1);
1147 R_SkyBoxPolyVec(0, 0, -1, 1, 1);
1149 glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[2])); // left
1151 R_SkyBoxPolyVec(1, 0, -1, -1, 1);
1152 R_SkyBoxPolyVec(1, 1, -1, -1, -1);
1153 R_SkyBoxPolyVec(0, 1, 1, -1, -1);
1154 R_SkyBoxPolyVec(0, 0, 1, -1, 1);
1156 glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[4])); // up
1158 R_SkyBoxPolyVec(1, 0, 1, -1, 1);
1159 R_SkyBoxPolyVec(1, 1, 1, 1, 1);
1160 R_SkyBoxPolyVec(0, 1, -1, 1, 1);
1161 R_SkyBoxPolyVec(0, 0, -1, -1, 1);
1163 glBindTexture(GL_TEXTURE_2D, R_GetTexture(skyboxside[5])); // down
1165 R_SkyBoxPolyVec(1, 0, 1, 1, -1);
1166 R_SkyBoxPolyVec(1, 1, 1, -1, -1);
1167 R_SkyBoxPolyVec(0, 1, -1, -1, -1);
1168 R_SkyBoxPolyVec(0, 0, -1, 1, -1);
1171 glEnable (GL_DEPTH_TEST);
1175 static float skysphere[33*33*5];
1176 static int skysphereindices[32*32*6];
1177 static void skyspherecalc(float *sphere, float dx, float dy, float dz)
1179 float a, b, x, ax, ay, v[3], length;
1181 for (a = 0;a <= 1;a += (1.0 / 32.0))
1183 ax = cos(a * M_PI * 2);
1184 ay = -sin(a * M_PI * 2);
1185 for (b = 0;b <= 1;b += (1.0 / 32.0))
1187 x = cos(b * M_PI * 2);
1190 v[2] = -sin(b * M_PI * 2) * dz;
1191 length = 3.0f / sqrt(v[0]*v[0]+v[1]*v[1]+(v[2]*v[2]*9));
1192 *sphere++ = v[0] * length;
1193 *sphere++ = v[1] * length;
1199 index = skysphereindices;
1200 for (j = 0;j < 32;j++)
1202 for (i = 0;i < 32;i++)
1204 *index++ = j * 33 + i;
1205 *index++ = j * 33 + i + 1;
1206 *index++ = (j + 1) * 33 + i;
1208 *index++ = j * 33 + i + 1;
1209 *index++ = (j + 1) * 33 + i + 1;
1210 *index++ = (j + 1) * 33 + i;
1216 static void skyspherearrays(float *vert, float *tex, float *tex2, float *source, float s, float s2)
1223 for (i = 0;i < (33*33);i++)
1225 *t++ = source[0] + s;
1226 *t++ = source[1] + s;
1227 *t2++ = source[0] + s2;
1228 *t2++ = source[1] + s2;
1229 *v++ = source[2] + r_origin[0];
1230 *v++ = source[3] + r_origin[1];
1231 *v++ = source[4] + r_origin[2];
1237 static void R_SkySphere(void)
1239 float speedscale, speedscale2;
1240 float vert[33*33*4], tex[33*33*2], tex2[33*33*2];
1241 static qboolean skysphereinitialized = false;
1242 if (!skysphereinitialized)
1244 skysphereinitialized = true;
1245 skyspherecalc(skysphere, 1024, 1024, 1024 / 3);
1247 glDisable(GL_DEPTH_TEST);
1249 glDisable (GL_BLEND);
1250 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1251 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1253 glColor3f(0.5,0.5,0.5);
1256 speedscale = cl.time*8.0/128.0;
1257 speedscale -= (int)speedscale;
1258 speedscale2 = cl.time*16.0/128.0;
1259 speedscale2 -= (int)speedscale2;
1260 skyspherearrays(vert, tex, tex2, skysphere, speedscale, speedscale2);
1261 glVertexPointer(3, GL_FLOAT, sizeof(float) * 4, vert);
1262 glEnableClientState(GL_VERTEX_ARRAY);
1263 // do not lock the texcoord array, because it will be switched
1264 GL_LockArray(0, 32*32*6);
1265 glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, tex);
1266 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1267 if (r_mergesky.value)
1269 glBindTexture(GL_TEXTURE_2D, R_GetTexture(mergeskytexture)); // both layers in one texture
1270 glDrawElements(GL_TRIANGLES, 32*32*6, GL_UNSIGNED_INT, &skysphereindices[0]);
1274 // LordHavoc: note that this combine operation does not use the color,
1275 // so it has to use alternate textures in lighthalf mode
1276 if (skyrendercombine)
1279 glBindTexture(GL_TEXTURE_2D, R_GetTexture(lighthalf ? solidskytexture_half : solidskytexture));
1281 // set up the second texcoord array
1282 // switch texcoord array selector to TMU 1
1283 qglClientActiveTexture(GL_TEXTURE1_ARB);
1284 glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, tex2);
1285 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1288 // render both layers as one pass using GL_ARB_texture_env_combine
1289 // TMU 0 is already selected, the TMU 0 texcoord array is already
1290 // set up, the texture is bound, and texturing is already enabled,
1291 // so just set up COMBINE
1293 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1295 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
1296 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
1297 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
1298 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
1299 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1300 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
1301 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
1303 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
1304 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
1305 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
1306 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_TEXTURE);
1307 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
1308 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
1309 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
1311 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0);
1312 glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0);
1315 qglActiveTexture(GL_TEXTURE1_ARB);
1317 glBindTexture(GL_TEXTURE_2D, R_GetTexture(lighthalf ? alphaskytexture_half : alphaskytexture));
1319 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1321 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
1322 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
1323 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
1324 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
1325 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1326 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
1327 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
1329 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
1330 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
1331 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
1332 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, GL_TEXTURE);
1333 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
1334 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
1335 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, GL_SRC_ALPHA);
1337 glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0);
1338 glTexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1.0);
1339 glEnable(GL_TEXTURE_2D);
1342 glDrawElements(GL_TRIANGLES, 32*32*6, GL_UNSIGNED_INT, &skysphereindices[0]);
1344 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1345 glDisable(GL_TEXTURE_2D);
1346 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1347 qglActiveTexture(GL_TEXTURE0_ARB);
1348 // switch texcoord array selector back to TMU 0
1349 qglClientActiveTexture(GL_TEXTURE0_ARB);
1350 // the TMU 0 texcoord array is disabled by the code below
1354 glBindTexture(GL_TEXTURE_2D, R_GetTexture(solidskytexture)); // upper clouds
1355 glDrawElements(GL_TRIANGLES, 32*32*6, GL_UNSIGNED_INT, &skysphereindices[0]);
1357 if (skyrendertwolayers)
1359 glEnable (GL_BLEND);
1360 glBindTexture(GL_TEXTURE_2D, R_GetTexture(alphaskytexture)); // lower clouds
1361 glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, tex2);
1362 glDrawElements(GL_TRIANGLES, 32*32*6, GL_UNSIGNED_INT, &skysphereindices[0]);
1363 glDisable (GL_BLEND);
1367 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1369 glDisableClientState(GL_VERTEX_ARRAY);
1370 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1372 glEnable (GL_DEPTH_TEST);
1376 static void R_Sky(void)
1378 if (!r_render.value)
1380 if (skyrendersphere)
1382 else if (skyrenderbox)
1386 //===============================================================
1388 static byte skyupperlayerpixels[128*128*4];
1389 static byte skylowerlayerpixels[128*128*4];
1390 static byte skymergedpixels[128*128*4];
1392 static void R_BuildSky (int scrollupper, int scrolllower)
1394 int x, y, ux, uy, lx, ly;
1396 m = skymergedpixels;
1397 for (y = 0;y < 128;y++)
1399 uy = (y + scrollupper) & 127;
1400 ly = (y + scrolllower) & 127;
1401 for (x = 0;x < 128;x++)
1403 ux = (x + scrollupper) & 127;
1404 lx = (x + scrolllower) & 127;
1405 u = &skyupperlayerpixels[(uy * 128 + ux) * 4];
1406 l = &skylowerlayerpixels[(ly * 128 + lx) * 4];
1410 *((int *)m) = *((int *)l);
1413 m[0] = ((((int) l[0] - (int) u[0]) * (int) l[3]) >> 8) + (int) u[0];
1414 m[1] = ((((int) l[1] - (int) u[1]) * (int) l[3]) >> 8) + (int) u[1];
1415 m[2] = ((((int) l[2] - (int) u[2]) * (int) l[3]) >> 8) + (int) u[2];
1420 *((int *)m) = *((int *)u);
1424 // FIXME: implement generated texture callbacks to speed this up? (skip identifier lookup, CRC, memcpy, etc)
1425 if (mergeskytexture)
1427 glBindTexture(GL_TEXTURE_2D, R_GetTexture(mergeskytexture));
1428 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, 128, GL_RGBA, GL_UNSIGNED_BYTE, skymergedpixels);
1431 mergeskytexture = R_LoadTexture("mergedskytexture", 128, 128, skymergedpixels, TEXF_RGBA | TEXF_ALWAYSPRECACHE);
1438 A sky texture is 256*128, with the right side being a masked overlay
1441 void R_InitSky (byte *src, int bytesperpixel)
1444 unsigned trans[128*128];
1452 strcpy(skyworldname, loadmodel->name);
1453 if (bytesperpixel == 4)
1455 for (i = 0;i < 128;i++)
1456 for (j = 0;j < 128;j++)
1457 trans[(i*128) + j] = src[i*256+j+128];
1461 // make an average value for the back to avoid
1462 // a fringe on the top level
1464 for (i=0 ; i<128 ; i++)
1466 for (j=0 ; j<128 ; j++)
1468 p = src[i*256 + j + 128];
1469 rgba = &d_8to24table[p];
1470 trans[(i*128) + j] = *rgba;
1471 r += ((byte *)rgba)[0];
1472 g += ((byte *)rgba)[1];
1473 b += ((byte *)rgba)[2];
1477 ((byte *)&transpix)[0] = r/(128*128);
1478 ((byte *)&transpix)[1] = g/(128*128);
1479 ((byte *)&transpix)[2] = b/(128*128);
1480 ((byte *)&transpix)[3] = 0;
1483 memcpy(skyupperlayerpixels, trans, 128*128*4);
1485 solidskytexture = R_LoadTexture ("sky_solidtexture", 128, 128, (byte *) trans, TEXF_RGBA | TEXF_PRECACHE);
1486 for (i = 0;i < 128*128;i++)
1488 ((byte *)&trans[i])[0] >>= 1;
1489 ((byte *)&trans[i])[1] >>= 1;
1490 ((byte *)&trans[i])[2] >>= 1;
1492 solidskytexture_half = R_LoadTexture ("sky_solidtexture_half", 128, 128, (byte *) trans, TEXF_RGBA | TEXF_PRECACHE);
1494 if (bytesperpixel == 4)
1496 for (i = 0;i < 128;i++)
1497 for (j = 0;j < 128;j++)
1498 trans[(i*128) + j] = src[i*256+j];
1502 for (i=0 ; i<128 ; i++)
1504 for (j=0 ; j<128 ; j++)
1508 trans[(i*128) + j] = transpix;
1510 trans[(i*128) + j] = d_8to24table[p];
1515 memcpy(skylowerlayerpixels, trans, 128*128*4);
1517 alphaskytexture = R_LoadTexture ("sky_alphatexture", 128, 128, (byte *) trans, TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
1518 for (i = 0;i < 128*128;i++)
1520 ((byte *)&trans[i])[0] >>= 1;
1521 ((byte *)&trans[i])[1] >>= 1;
1522 ((byte *)&trans[i])[2] >>= 1;
1524 alphaskytexture_half = R_LoadTexture ("sky_alphatexture_half", 128, 128, (byte *) trans, TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);