123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698 |
- /*
- Copyright (C) 1996-1997 Id Software, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- // r_surf.c: surface-related refresh code
- #include "quakedef.h"
- int skytexturenum;
- #ifndef GL_RGBA4
- #define GL_RGBA4 0
- #endif
- int lightmap_bytes; // 1, 2, or 4
- int lightmap_textures;
- unsigned blocklights[18*18];
- #define BLOCK_WIDTH 128
- #define BLOCK_HEIGHT 128
- #define MAX_LIGHTMAPS 64
- int active_lightmaps;
- typedef struct glRect_s {
- unsigned char l,t,w,h;
- } glRect_t;
- glpoly_t *lightmap_polys[MAX_LIGHTMAPS];
- qboolean lightmap_modified[MAX_LIGHTMAPS];
- glRect_t lightmap_rectchange[MAX_LIGHTMAPS];
- int allocated[MAX_LIGHTMAPS][BLOCK_WIDTH];
- // the lightmap texture data needs to be kept in
- // main memory so texsubimage can update properly
- byte lightmaps[4*MAX_LIGHTMAPS*BLOCK_WIDTH*BLOCK_HEIGHT];
- // For gl_texsort 0
- msurface_t *skychain = NULL;
- msurface_t *waterchain = NULL;
- void R_RenderDynamicLightmaps (msurface_t *fa);
- /*
- ===============
- R_AddDynamicLights
- ===============
- */
- void R_AddDynamicLights (msurface_t *surf)
- {
- int lnum;
- int sd, td;
- float dist, rad, minlight;
- vec3_t impact, local;
- int s, t;
- int i;
- int smax, tmax;
- mtexinfo_t *tex;
- smax = (surf->extents[0]>>4)+1;
- tmax = (surf->extents[1]>>4)+1;
- tex = surf->texinfo;
- for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
- {
- if ( !(surf->dlightbits & (1<<lnum) ) )
- continue; // not lit by this light
- rad = cl_dlights[lnum].radius;
- dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
- surf->plane->dist;
- rad -= fabs(dist);
- minlight = cl_dlights[lnum].minlight;
- if (rad < minlight)
- continue;
- minlight = rad - minlight;
- for (i=0 ; i<3 ; i++)
- {
- impact[i] = cl_dlights[lnum].origin[i] -
- surf->plane->normal[i]*dist;
- }
- local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
- local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
- local[0] -= surf->texturemins[0];
- local[1] -= surf->texturemins[1];
-
- for (t = 0 ; t<tmax ; t++)
- {
- td = local[1] - t*16;
- if (td < 0)
- td = -td;
- for (s=0 ; s<smax ; s++)
- {
- sd = local[0] - s*16;
- if (sd < 0)
- sd = -sd;
- if (sd > td)
- dist = sd + (td>>1);
- else
- dist = td + (sd>>1);
- if (dist < minlight)
- blocklights[t*smax + s] += (rad - dist)*256;
- }
- }
- }
- }
- /*
- ===============
- R_BuildLightMap
- Combine and scale multiple lightmaps into the 8.8 format in blocklights
- ===============
- */
- void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
- {
- int smax, tmax;
- int t;
- int i, j, size;
- byte *lightmap;
- unsigned scale;
- int maps;
- unsigned *bl;
- surf->cached_dlight = (surf->dlightframe == r_framecount);
- smax = (surf->extents[0]>>4)+1;
- tmax = (surf->extents[1]>>4)+1;
- size = smax*tmax;
- lightmap = surf->samples;
- // set to full bright if no light data
- if (/* r_fullbright.value || */ !cl.worldmodel->lightdata)
- {
- for (i=0 ; i<size ; i++)
- blocklights[i] = 255*256;
- goto store;
- }
- // clear to no light
- for (i=0 ; i<size ; i++)
- blocklights[i] = 0;
- // add all the lightmaps
- if (lightmap)
- for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
- maps++)
- {
- scale = d_lightstylevalue[surf->styles[maps]];
- surf->cached_light[maps] = scale; // 8.8 fraction
- for (i=0 ; i<size ; i++)
- blocklights[i] += lightmap[i] * scale;
- lightmap += size; // skip to next lightmap
- }
- // add all the dynamic lights
- if (surf->dlightframe == r_framecount)
- R_AddDynamicLights (surf);
- // bound, invert, and shift
- store:
- switch (gl_lightmap_format)
- {
- case GL_RGBA:
- stride -= (smax<<2);
- bl = blocklights;
- for (i=0 ; i<tmax ; i++, dest += stride)
- {
- for (j=0 ; j<smax ; j++)
- {
- t = *bl++;
- t >>= 7;
- if (t > 255)
- t = 255;
- dest[3] = 255-t;
- dest += 4;
- }
- }
- break;
- case GL_ALPHA:
- case GL_LUMINANCE:
- case GL_INTENSITY:
- bl = blocklights;
- for (i=0 ; i<tmax ; i++, dest += stride)
- {
- for (j=0 ; j<smax ; j++)
- {
- t = *bl++;
- t >>= 7;
- if (t > 255)
- t = 255;
- dest[j] = 255-t;
- }
- }
- break;
- default:
- Sys_Error ("Bad lightmap format");
- }
- }
- /*
- ===============
- R_TextureAnimation
- Returns the proper texture for a given time and base texture
- ===============
- */
- texture_t *R_TextureAnimation (texture_t *base)
- {
- int reletive;
- int count;
- if (currententity->frame)
- {
- if (base->alternate_anims)
- base = base->alternate_anims;
- }
-
- if (!base->anim_total)
- return base;
- reletive = (int)(cl.time*10) % base->anim_total;
- count = 0;
- while (base->anim_min > reletive || base->anim_max <= reletive)
- {
- base = base->anim_next;
- if (!base)
- Sys_Error ("R_TextureAnimation: broken cycle");
- if (++count > 100)
- Sys_Error ("R_TextureAnimation: infinite cycle");
- }
- return base;
- }
- /*
- =============================================================
- BRUSH MODELS
- =============================================================
- */
- extern int solidskytexture;
- extern int alphaskytexture;
- extern float speedscale; // for top sky and bottom sky
- void DrawGLWaterPoly (glpoly_t *p);
- void DrawGLWaterPolyLightmap (glpoly_t *p);
- #ifdef _WIN32
- lpMTexFUNC qglMTexCoord2fSGIS = NULL;
- lpSelTexFUNC qglSelectTextureSGIS = NULL;
- #endif
- qboolean mtexenabled = false;
- void GL_SelectTexture (GLenum target);
- void GL_DisableMultitexture(void)
- {
- if (mtexenabled) {
- glDisable(GL_TEXTURE_2D);
- GL_SelectTexture(TEXTURE0_SGIS);
- mtexenabled = false;
- }
- }
- void GL_EnableMultitexture(void)
- {
- if (gl_mtexable) {
- GL_SelectTexture(TEXTURE1_SGIS);
- glEnable(GL_TEXTURE_2D);
- mtexenabled = true;
- }
- }
- #ifndef _WIN32
- /*
- ================
- R_DrawSequentialPoly
- Systems that have fast state and texture changes can
- just do everything as it passes with no need to sort
- ================
- */
- void R_DrawSequentialPoly (msurface_t *s)
- {
- glpoly_t *p;
- float *v;
- int i;
- texture_t *t;
- //
- // normal lightmaped poly
- //
- // if ((!(s->flags & (SURF_DRAWSKY|SURF_DRAWTURB)))
- // && ((r_viewleaf->contents!=CONTENTS_EMPTY && (s->flags & SURF_UNDERWATER)) ||
- // (r_viewleaf->contents==CONTENTS_EMPTY && !(s->flags & SURF_UNDERWATER))))
- if (0)
- {
- p = s->polys;
- t = R_TextureAnimation (s->texinfo->texture);
- GL_Bind (t->gl_texturenum);
- glBegin (GL_POLYGON);
- v = p->verts[0];
- for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
- {
- glTexCoord2f (v[3], v[4]);
- glVertex3fv (v);
- }
- glEnd ();
- GL_Bind (lightmap_textures + s->lightmaptexturenum);
- glEnable (GL_BLEND);
- glBegin (GL_POLYGON);
- v = p->verts[0];
- for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
- {
- glTexCoord2f (v[5], v[6]);
- glVertex3fv (v);
- }
- glEnd ();
- glDisable (GL_BLEND);
- return;
- }
- //
- // subdivided water surface warp
- //
- if (s->flags & SURF_DRAWTURB)
- {
- GL_Bind (s->texinfo->texture->gl_texturenum);
- EmitWaterPolys (s);
- return;
- }
- //
- // subdivided sky warp
- //
- if (s->flags & SURF_DRAWSKY)
- {
- GL_Bind (solidskytexture);
- speedscale = realtime*8;
- speedscale -= (int)speedscale;
- EmitSkyPolys (s);
- glEnable (GL_BLEND);
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- GL_Bind (alphaskytexture);
- speedscale = realtime*16;
- speedscale -= (int)speedscale;
- EmitSkyPolys (s);
- if (gl_lightmap_format == GL_LUMINANCE)
- glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
- glDisable (GL_BLEND);
- }
- //
- // underwater warped with lightmap
- //
- p = s->polys;
- t = R_TextureAnimation (s->texinfo->texture);
- GL_Bind (t->gl_texturenum);
- DrawGLWaterPoly (p);
- GL_Bind (lightmap_textures + s->lightmaptexturenum);
- glEnable (GL_BLEND);
- DrawGLWaterPolyLightmap (p);
- glDisable (GL_BLEND);
- }
- #else
- /*
- ================
- R_DrawSequentialPoly
- Systems that have fast state and texture changes can
- just do everything as it passes with no need to sort
- ================
- */
- void R_DrawSequentialPoly (msurface_t *s)
- {
- glpoly_t *p;
- float *v;
- int i;
- texture_t *t;
- vec3_t nv, dir;
- float ss, ss2, length;
- float s1, t1;
- glRect_t *theRect;
- //
- // normal lightmaped poly
- //
- if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) )
- {
- R_RenderDynamicLightmaps (s);
- if (gl_mtexable) {
- p = s->polys;
- t = R_TextureAnimation (s->texinfo->texture);
- // Binds world to texture env 0
- GL_SelectTexture(TEXTURE0_SGIS);
- GL_Bind (t->gl_texturenum);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- // Binds lightmap to texenv 1
- GL_EnableMultitexture(); // Same as SelectTexture (TEXTURE1)
- GL_Bind (lightmap_textures + s->lightmaptexturenum);
- i = s->lightmaptexturenum;
- if (lightmap_modified[i])
- {
- lightmap_modified[i] = false;
- theRect = &lightmap_rectchange[i];
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t,
- BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
- lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
- theRect->l = BLOCK_WIDTH;
- theRect->t = BLOCK_HEIGHT;
- theRect->h = 0;
- theRect->w = 0;
- }
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
- glBegin(GL_POLYGON);
- v = p->verts[0];
- for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
- {
- qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]);
- qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]);
- glVertex3fv (v);
- }
- glEnd ();
- return;
- } else {
- p = s->polys;
- t = R_TextureAnimation (s->texinfo->texture);
- GL_Bind (t->gl_texturenum);
- glBegin (GL_POLYGON);
- v = p->verts[0];
- for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
- {
- glTexCoord2f (v[3], v[4]);
- glVertex3fv (v);
- }
- glEnd ();
- GL_Bind (lightmap_textures + s->lightmaptexturenum);
- glEnable (GL_BLEND);
- glBegin (GL_POLYGON);
- v = p->verts[0];
- for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
- {
- glTexCoord2f (v[5], v[6]);
- glVertex3fv (v);
- }
- glEnd ();
- glDisable (GL_BLEND);
- }
- return;
- }
- //
- // subdivided water surface warp
- //
- if (s->flags & SURF_DRAWTURB)
- {
- GL_DisableMultitexture();
- GL_Bind (s->texinfo->texture->gl_texturenum);
- EmitWaterPolys (s);
- return;
- }
- //
- // subdivided sky warp
- //
- if (s->flags & SURF_DRAWSKY)
- {
- GL_DisableMultitexture();
- GL_Bind (solidskytexture);
- speedscale = realtime*8;
- speedscale -= (int)speedscale & ~127;
- EmitSkyPolys (s);
- glEnable (GL_BLEND);
- GL_Bind (alphaskytexture);
- speedscale = realtime*16;
- speedscale -= (int)speedscale & ~127;
- EmitSkyPolys (s);
- glDisable (GL_BLEND);
- return;
- }
- //
- // underwater warped with lightmap
- //
- R_RenderDynamicLightmaps (s);
- if (gl_mtexable) {
- p = s->polys;
- t = R_TextureAnimation (s->texinfo->texture);
- GL_SelectTexture(TEXTURE0_SGIS);
- GL_Bind (t->gl_texturenum);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- GL_EnableMultitexture();
- GL_Bind (lightmap_textures + s->lightmaptexturenum);
- i = s->lightmaptexturenum;
- if (lightmap_modified[i])
- {
- lightmap_modified[i] = false;
- theRect = &lightmap_rectchange[i];
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t,
- BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
- lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
- theRect->l = BLOCK_WIDTH;
- theRect->t = BLOCK_HEIGHT;
- theRect->h = 0;
- theRect->w = 0;
- }
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
- glBegin (GL_TRIANGLE_FAN);
- v = p->verts[0];
- for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
- {
- qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]);
- qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]);
- nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
- nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
- nv[2] = v[2];
- glVertex3fv (nv);
- }
- glEnd ();
- } else {
- p = s->polys;
- t = R_TextureAnimation (s->texinfo->texture);
- GL_Bind (t->gl_texturenum);
- DrawGLWaterPoly (p);
- GL_Bind (lightmap_textures + s->lightmaptexturenum);
- glEnable (GL_BLEND);
- DrawGLWaterPolyLightmap (p);
- glDisable (GL_BLEND);
- }
- }
- #endif
- /*
- ================
- DrawGLWaterPoly
- Warp the vertex coordinates
- ================
- */
- void DrawGLWaterPoly (glpoly_t *p)
- {
- int i;
- float *v;
- vec3_t nv;
- GL_DisableMultitexture();
- glBegin (GL_TRIANGLE_FAN);
- v = p->verts[0];
- for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
- {
- glTexCoord2f (v[3], v[4]);
- nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
- nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
- nv[2] = v[2];
- glVertex3fv (nv);
- }
- glEnd ();
- }
- void DrawGLWaterPolyLightmap (glpoly_t *p)
- {
- int i;
- float *v;
- vec3_t nv;
- GL_DisableMultitexture();
- glBegin (GL_TRIANGLE_FAN);
- v = p->verts[0];
- for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
- {
- glTexCoord2f (v[5], v[6]);
- nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
- nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
- nv[2] = v[2];
- glVertex3fv (nv);
- }
- glEnd ();
- }
- /*
- ================
- DrawGLPoly
- ================
- */
- void DrawGLPoly (glpoly_t *p)
- {
- int i;
- float *v;
- glBegin (GL_POLYGON);
- v = p->verts[0];
- for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
- {
- glTexCoord2f (v[3], v[4]);
- glVertex3fv (v);
- }
- glEnd ();
- }
- /*
- ================
- R_BlendLightmaps
- ================
- */
- void R_BlendLightmaps (void)
- {
- int i, j;
- glpoly_t *p;
- float *v;
- glRect_t *theRect;
- #if 0
- if (r_fullbright.value)
- return;
- #endif
- if (!gl_texsort.value)
- return;
- glDepthMask (0); // don't bother writing Z
- if (gl_lightmap_format == GL_LUMINANCE)
- glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
- else if (gl_lightmap_format == GL_INTENSITY)
- {
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glColor4f (0,0,0,1);
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- if (!r_lightmap.value)
- {
- glEnable (GL_BLEND);
- }
- for (i=0 ; i<MAX_LIGHTMAPS ; i++)
- {
- p = lightmap_polys[i];
- if (!p)
- continue;
- GL_Bind(lightmap_textures+i);
- if (lightmap_modified[i])
- {
- lightmap_modified[i] = false;
- theRect = &lightmap_rectchange[i];
- // theRect->l = 0;
- // theRect->t = 0;
- // theRect->w = BLOCK_WIDTH;
- // theRect->h = BLOCK_HEIGHT;
- // glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
- // , BLOCK_WIDTH, BLOCK_HEIGHT, 0,
- // gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes);
- // glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
- // , BLOCK_WIDTH, theRect->h, 0,
- // gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+(i*BLOCK_HEIGHT+theRect->t)*BLOCK_WIDTH*lightmap_bytes);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t,
- BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
- lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
- theRect->l = BLOCK_WIDTH;
- theRect->t = BLOCK_HEIGHT;
- theRect->h = 0;
- theRect->w = 0;
- }
- for ( ; p ; p=p->chain)
- {
- // if (p->flags & SURF_UNDERWATER)
- // DrawGLWaterPolyLightmap (p);
- if (((r_viewleaf->contents==CONTENTS_EMPTY && (p->flags & SURF_UNDERWATER)) ||
- (r_viewleaf->contents!=CONTENTS_EMPTY && !(p->flags & SURF_UNDERWATER)))
- && !(p->flags & SURF_DONTWARP))
- DrawGLWaterPolyLightmap (p);
- else
- {
- glBegin (GL_POLYGON);
- v = p->verts[0];
- for (j=0 ; j<p->numverts ; j++, v+= VERTEXSIZE)
- {
- glTexCoord2f (v[5], v[6]);
- glVertex3fv (v);
- }
- glEnd ();
- }
- }
- }
- glDisable (GL_BLEND);
- if (gl_lightmap_format == GL_LUMINANCE)
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- else if (gl_lightmap_format == GL_INTENSITY)
- {
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glColor4f (1,1,1,1);
- }
- glDepthMask (1); // back to normal Z buffering
- }
- /*
- ================
- R_RenderBrushPoly
- ================
- */
- void R_RenderBrushPoly (msurface_t *fa)
- {
- texture_t *t;
- byte *base;
- int maps;
- glRect_t *theRect;
- int smax, tmax;
- c_brush_polys++;
- if (fa->flags & SURF_DRAWSKY)
- { // warp texture, no lightmaps
- EmitBothSkyLayers (fa);
- return;
- }
-
- t = R_TextureAnimation (fa->texinfo->texture);
- GL_Bind (t->gl_texturenum);
- if (fa->flags & SURF_DRAWTURB)
- { // warp texture, no lightmaps
- EmitWaterPolys (fa);
- return;
- }
- if (((r_viewleaf->contents==CONTENTS_EMPTY && (fa->flags & SURF_UNDERWATER)) ||
- (r_viewleaf->contents!=CONTENTS_EMPTY && !(fa->flags & SURF_UNDERWATER)))
- && !(fa->flags & SURF_DONTWARP))
- DrawGLWaterPoly (fa->polys);
- else
- DrawGLPoly (fa->polys);
- // add the poly to the proper lightmap chain
- fa->polys->chain = lightmap_polys[fa->lightmaptexturenum];
- lightmap_polys[fa->lightmaptexturenum] = fa->polys;
- // check for lightmap modification
- for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ;
- maps++)
- if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps])
- goto dynamic;
- if (fa->dlightframe == r_framecount // dynamic this frame
- || fa->cached_dlight) // dynamic previously
- {
- dynamic:
- if (r_dynamic.value)
- {
- lightmap_modified[fa->lightmaptexturenum] = true;
- theRect = &lightmap_rectchange[fa->lightmaptexturenum];
- if (fa->light_t < theRect->t) {
- if (theRect->h)
- theRect->h += theRect->t - fa->light_t;
- theRect->t = fa->light_t;
- }
- if (fa->light_s < theRect->l) {
- if (theRect->w)
- theRect->w += theRect->l - fa->light_s;
- theRect->l = fa->light_s;
- }
- smax = (fa->extents[0]>>4)+1;
- tmax = (fa->extents[1]>>4)+1;
- if ((theRect->w + theRect->l) < (fa->light_s + smax))
- theRect->w = (fa->light_s-theRect->l)+smax;
- if ((theRect->h + theRect->t) < (fa->light_t + tmax))
- theRect->h = (fa->light_t-theRect->t)+tmax;
- base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
- base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes;
- R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes);
- }
- }
- }
- /*
- ================
- R_RenderDynamicLightmaps
- Multitexture
- ================
- */
- void R_RenderDynamicLightmaps (msurface_t *fa)
- {
- byte *base;
- int maps;
- glRect_t *theRect;
- int smax, tmax;
- c_brush_polys++;
- if (fa->flags & ( SURF_DRAWSKY | SURF_DRAWTURB) )
- return;
-
- fa->polys->chain = lightmap_polys[fa->lightmaptexturenum];
- lightmap_polys[fa->lightmaptexturenum] = fa->polys;
- // check for lightmap modification
- for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ;
- maps++)
- if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps])
- goto dynamic;
- if (fa->dlightframe == r_framecount // dynamic this frame
- || fa->cached_dlight) // dynamic previously
- {
- dynamic:
- if (r_dynamic.value)
- {
- lightmap_modified[fa->lightmaptexturenum] = true;
- theRect = &lightmap_rectchange[fa->lightmaptexturenum];
- if (fa->light_t < theRect->t) {
- if (theRect->h)
- theRect->h += theRect->t - fa->light_t;
- theRect->t = fa->light_t;
- }
- if (fa->light_s < theRect->l) {
- if (theRect->w)
- theRect->w += theRect->l - fa->light_s;
- theRect->l = fa->light_s;
- }
- smax = (fa->extents[0]>>4)+1;
- tmax = (fa->extents[1]>>4)+1;
- if ((theRect->w + theRect->l) < (fa->light_s + smax))
- theRect->w = (fa->light_s-theRect->l)+smax;
- if ((theRect->h + theRect->t) < (fa->light_t + tmax))
- theRect->h = (fa->light_t-theRect->t)+tmax;
- base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
- base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes;
- R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes);
- }
- }
- }
- /*
- ================
- R_MirrorChain
- ================
- */
- void R_MirrorChain (msurface_t *s)
- {
- if (mirror)
- return;
- mirror = true;
- mirror_plane = s->plane;
- }
- #if 0
- /*
- ================
- R_DrawWaterSurfaces
- ================
- */
- void R_DrawWaterSurfaces (void)
- {
- int i;
- msurface_t *s;
- texture_t *t;
- if (r_wateralpha.value == 1.0)
- return;
- //
- // go back to the world matrix
- //
- glLoadMatrixf (r_world_matrix);
- glEnable (GL_BLEND);
- glColor4f (1,1,1,r_wateralpha.value);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- for (i=0 ; i<cl.worldmodel->numtextures ; i++)
- {
- t = cl.worldmodel->textures[i];
- if (!t)
- continue;
- s = t->texturechain;
- if (!s)
- continue;
- if ( !(s->flags & SURF_DRAWTURB) )
- continue;
- // set modulate mode explicitly
- GL_Bind (t->gl_texturenum);
- for ( ; s ; s=s->texturechain)
- R_RenderBrushPoly (s);
- t->texturechain = NULL;
- }
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glColor4f (1,1,1,1);
- glDisable (GL_BLEND);
- }
- #else
- /*
- ================
- R_DrawWaterSurfaces
- ================
- */
- void R_DrawWaterSurfaces (void)
- {
- int i;
- msurface_t *s;
- texture_t *t;
- if (r_wateralpha.value == 1.0 && gl_texsort.value)
- return;
- //
- // go back to the world matrix
- //
- glLoadMatrixf (r_world_matrix);
- if (r_wateralpha.value < 1.0) {
- glEnable (GL_BLEND);
- glColor4f (1,1,1,r_wateralpha.value);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- }
- if (!gl_texsort.value) {
- if (!waterchain)
- return;
- for ( s = waterchain ; s ; s=s->texturechain) {
- GL_Bind (s->texinfo->texture->gl_texturenum);
- EmitWaterPolys (s);
- }
-
- waterchain = NULL;
- } else {
- for (i=0 ; i<cl.worldmodel->numtextures ; i++)
- {
- t = cl.worldmodel->textures[i];
- if (!t)
- continue;
- s = t->texturechain;
- if (!s)
- continue;
- if ( !(s->flags & SURF_DRAWTURB ) )
- continue;
- // set modulate mode explicitly
-
- GL_Bind (t->gl_texturenum);
- for ( ; s ; s=s->texturechain)
- EmitWaterPolys (s);
-
- t->texturechain = NULL;
- }
- }
- if (r_wateralpha.value < 1.0) {
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glColor4f (1,1,1,1);
- glDisable (GL_BLEND);
- }
- }
- #endif
- /*
- ================
- DrawTextureChains
- ================
- */
- void DrawTextureChains (void)
- {
- int i;
- msurface_t *s;
- texture_t *t;
- if (!gl_texsort.value) {
- GL_DisableMultitexture();
- if (skychain) {
- R_DrawSkyChain(skychain);
- skychain = NULL;
- }
- return;
- }
- for (i=0 ; i<cl.worldmodel->numtextures ; i++)
- {
- t = cl.worldmodel->textures[i];
- if (!t)
- continue;
- s = t->texturechain;
- if (!s)
- continue;
- if (i == skytexturenum)
- R_DrawSkyChain (s);
- else if (i == mirrortexturenum && r_mirroralpha.value != 1.0)
- {
- R_MirrorChain (s);
- continue;
- }
- else
- {
- if ((s->flags & SURF_DRAWTURB) && r_wateralpha.value != 1.0)
- continue; // draw translucent water later
- for ( ; s ; s=s->texturechain)
- R_RenderBrushPoly (s);
- }
- t->texturechain = NULL;
- }
- }
- /*
- =================
- R_DrawBrushModel
- =================
- */
- void R_DrawBrushModel (entity_t *e)
- {
- int i;
- int k;
- vec3_t mins, maxs;
- msurface_t *psurf;
- float dot;
- mplane_t *pplane;
- model_t *clmodel;
- qboolean rotated;
- currententity = e;
- currenttexture = -1;
- clmodel = e->model;
- if (e->angles[0] || e->angles[1] || e->angles[2])
- {
- rotated = true;
- for (i=0 ; i<3 ; i++)
- {
- mins[i] = e->origin[i] - clmodel->radius;
- maxs[i] = e->origin[i] + clmodel->radius;
- }
- }
- else
- {
- rotated = false;
- VectorAdd (e->origin, clmodel->mins, mins);
- VectorAdd (e->origin, clmodel->maxs, maxs);
- }
- if (R_CullBox (mins, maxs))
- return;
- glColor3f (1,1,1);
- memset (lightmap_polys, 0, sizeof(lightmap_polys));
- VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
- if (rotated)
- {
- vec3_t temp;
- vec3_t forward, right, up;
- VectorCopy (modelorg, temp);
- AngleVectors (e->angles, forward, right, up);
- modelorg[0] = DotProduct (temp, forward);
- modelorg[1] = -DotProduct (temp, right);
- modelorg[2] = DotProduct (temp, up);
- }
- psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
- // calculate dynamic lighting for bmodel if it's not an
- // instanced model
- if (clmodel->firstmodelsurface != 0 && !gl_flashblend.value)
- {
- for (k=0 ; k<MAX_DLIGHTS ; k++)
- {
- if ((cl_dlights[k].die < cl.time) ||
- (!cl_dlights[k].radius))
- continue;
- R_MarkLights (&cl_dlights[k], 1<<k,
- clmodel->nodes + clmodel->hulls[0].firstclipnode);
- }
- }
- glPushMatrix ();
- e->angles[0] = -e->angles[0]; // stupid quake bug
- R_RotateForEntity (e);
- e->angles[0] = -e->angles[0]; // stupid quake bug
- //
- // draw texture
- //
- for (i=0 ; i<clmodel->nummodelsurfaces ; i++, psurf++)
- {
- // find which side of the node we are on
- pplane = psurf->plane;
- dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
- // draw the polygon
- if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
- (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
- {
- if (gl_texsort.value)
- R_RenderBrushPoly (psurf);
- else
- R_DrawSequentialPoly (psurf);
- }
- }
- R_BlendLightmaps ();
- glPopMatrix ();
- }
- /*
- =============================================================
- WORLD MODEL
- =============================================================
- */
- /*
- ================
- R_RecursiveWorldNode
- ================
- */
- void R_RecursiveWorldNode (mnode_t *node)
- {
- int c, side;
- mplane_t *plane;
- msurface_t *surf, **mark;
- mleaf_t *pleaf;
- double dot;
- if (node->contents == CONTENTS_SOLID)
- return; // solid
- if (node->visframe != r_visframecount)
- return;
- if (R_CullBox (node->minmaxs, node->minmaxs+3))
- return;
-
- // if a leaf node, draw stuff
- if (node->contents < 0)
- {
- pleaf = (mleaf_t *)node;
- mark = pleaf->firstmarksurface;
- c = pleaf->nummarksurfaces;
- if (c)
- {
- do
- {
- (*mark)->visframe = r_framecount;
- mark++;
- } while (--c);
- }
- // deal with model fragments in this leaf
- if (pleaf->efrags)
- R_StoreEfrags (&pleaf->efrags);
- return;
- }
- // node is just a decision point, so go down the apropriate sides
- // find which side of the node we are on
- plane = node->plane;
- switch (plane->type)
- {
- case PLANE_X:
- dot = modelorg[0] - plane->dist;
- break;
- case PLANE_Y:
- dot = modelorg[1] - plane->dist;
- break;
- case PLANE_Z:
- dot = modelorg[2] - plane->dist;
- break;
- default:
- dot = DotProduct (modelorg, plane->normal) - plane->dist;
- break;
- }
- if (dot >= 0)
- side = 0;
- else
- side = 1;
- // recurse down the children, front side first
- R_RecursiveWorldNode (node->children[side]);
- // draw stuff
- c = node->numsurfaces;
- if (c)
- {
- surf = cl.worldmodel->surfaces + node->firstsurface;
- if (dot < 0 -BACKFACE_EPSILON)
- side = SURF_PLANEBACK;
- else if (dot > BACKFACE_EPSILON)
- side = 0;
- {
- for ( ; c ; c--, surf++)
- {
- if (surf->visframe != r_framecount)
- continue;
- // don't backface underwater surfaces, because they warp
- // if ( !(surf->flags & SURF_UNDERWATER) && ( (dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) )
- // continue; // wrong side
- if ( !(((r_viewleaf->contents==CONTENTS_EMPTY && (surf->flags & SURF_UNDERWATER)) ||
- (r_viewleaf->contents!=CONTENTS_EMPTY && !(surf->flags & SURF_UNDERWATER)))
- && !(surf->flags & SURF_DONTWARP)) && ( (dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) )
- continue; // wrong side
- // if sorting by texture, just store it out
- if (gl_texsort.value)
- {
- if (!mirror
- || surf->texinfo->texture != cl.worldmodel->textures[mirrortexturenum])
- {
- surf->texturechain = surf->texinfo->texture->texturechain;
- surf->texinfo->texture->texturechain = surf;
- }
- } else if (surf->flags & SURF_DRAWSKY) {
- surf->texturechain = skychain;
- skychain = surf;
- } else if (surf->flags & SURF_DRAWTURB) {
- surf->texturechain = waterchain;
- waterchain = surf;
- } else
- R_DrawSequentialPoly (surf);
- }
- }
- }
- // recurse down the back side
- R_RecursiveWorldNode (node->children[!side]);
- }
- /*
- =============
- R_DrawWorld
- =============
- */
- void R_DrawWorld (void)
- {
- entity_t ent;
- memset (&ent, 0, sizeof(ent));
- ent.model = cl.worldmodel;
- VectorCopy (r_refdef.vieworg, modelorg);
- currententity = &ent;
- currenttexture = -1;
- glColor3f (1,1,1);
- memset (lightmap_polys, 0, sizeof(lightmap_polys));
- #ifdef QUAKE2
- R_ClearSkyBox ();
- #endif
- R_RecursiveWorldNode (cl.worldmodel->nodes);
- DrawTextureChains ();
- R_BlendLightmaps ();
- #ifdef QUAKE2
- R_DrawSkyBox ();
- #endif
- }
- /*
- ===============
- R_MarkLeaves
- ===============
- */
- void R_MarkLeaves (void)
- {
- byte *vis;
- mnode_t *node;
- int i;
- byte solid[4096];
- if (r_oldviewleaf == r_viewleaf && !r_novis.value)
- return;
-
- if (mirror)
- return;
- r_visframecount++;
- r_oldviewleaf = r_viewleaf;
- if (r_novis.value)
- {
- vis = solid;
- memset (solid, 0xff, (cl.worldmodel->numleafs+7)>>3);
- }
- else
- vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
-
- for (i=0 ; i<cl.worldmodel->numleafs ; i++)
- {
- if (vis[i>>3] & (1<<(i&7)))
- {
- node = (mnode_t *)&cl.worldmodel->leafs[i+1];
- do
- {
- if (node->visframe == r_visframecount)
- break;
- node->visframe = r_visframecount;
- node = node->parent;
- } while (node);
- }
- }
- }
- /*
- =============================================================================
- LIGHTMAP ALLOCATION
- =============================================================================
- */
- // returns a texture number and the position inside it
- int AllocBlock (int w, int h, int *x, int *y)
- {
- int i, j;
- int best, best2;
- int texnum;
- for (texnum=0 ; texnum<MAX_LIGHTMAPS ; texnum++)
- {
- best = BLOCK_HEIGHT;
- for (i=0 ; i<BLOCK_WIDTH-w ; i++)
- {
- best2 = 0;
- for (j=0 ; j<w ; j++)
- {
- if (allocated[texnum][i+j] >= best)
- break;
- if (allocated[texnum][i+j] > best2)
- best2 = allocated[texnum][i+j];
- }
- if (j == w)
- { // this is a valid spot
- *x = i;
- *y = best = best2;
- }
- }
- if (best + h > BLOCK_HEIGHT)
- continue;
- for (i=0 ; i<w ; i++)
- allocated[texnum][*x + i] = best + h;
- return texnum;
- }
- Sys_Error ("AllocBlock: full");
- return 0;
- }
- mvertex_t *r_pcurrentvertbase;
- model_t *currentmodel;
- int nColinElim;
- /*
- ================
- BuildSurfaceDisplayList
- ================
- */
- void BuildSurfaceDisplayList (msurface_t *fa)
- {
- int i, lindex, lnumverts;
- medge_t *pedges, *r_pedge;
- int vertpage;
- float *vec;
- float s, t;
- glpoly_t *poly;
- // reconstruct the polygon
- pedges = currentmodel->edges;
- lnumverts = fa->numedges;
- vertpage = 0;
- //
- // draw texture
- //
- poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float));
- poly->next = fa->polys;
- poly->flags = fa->flags;
- fa->polys = poly;
- poly->numverts = lnumverts;
- for (i=0 ; i<lnumverts ; i++)
- {
- lindex = currentmodel->surfedges[fa->firstedge + i];
- if (lindex > 0)
- {
- r_pedge = &pedges[lindex];
- vec = r_pcurrentvertbase[r_pedge->v[0]].position;
- }
- else
- {
- r_pedge = &pedges[-lindex];
- vec = r_pcurrentvertbase[r_pedge->v[1]].position;
- }
- s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
- s /= fa->texinfo->texture->width;
- t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
- t /= fa->texinfo->texture->height;
- VectorCopy (vec, poly->verts[i]);
- poly->verts[i][3] = s;
- poly->verts[i][4] = t;
- //
- // lightmap texture coordinates
- //
- s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
- s -= fa->texturemins[0];
- s += fa->light_s*16;
- s += 8;
- s /= BLOCK_WIDTH*16; //fa->texinfo->texture->width;
- t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
- t -= fa->texturemins[1];
- t += fa->light_t*16;
- t += 8;
- t /= BLOCK_HEIGHT*16; //fa->texinfo->texture->height;
- poly->verts[i][5] = s;
- poly->verts[i][6] = t;
- }
- //
- // remove co-linear points - Ed
- //
- if (!gl_keeptjunctions.value && !(fa->flags & SURF_UNDERWATER) )
- {
- for (i = 0 ; i < lnumverts ; ++i)
- {
- vec3_t v1, v2;
- float *prev, *this, *next;
- prev = poly->verts[(i + lnumverts - 1) % lnumverts];
- this = poly->verts[i];
- next = poly->verts[(i + 1) % lnumverts];
- VectorSubtract( this, prev, v1 );
- VectorNormalize( v1 );
- VectorSubtract( next, prev, v2 );
- VectorNormalize( v2 );
- // skip co-linear points
- #define COLINEAR_EPSILON 0.001
- if ((fabs( v1[0] - v2[0] ) <= COLINEAR_EPSILON) &&
- (fabs( v1[1] - v2[1] ) <= COLINEAR_EPSILON) &&
- (fabs( v1[2] - v2[2] ) <= COLINEAR_EPSILON))
- {
- int j;
- for (j = i + 1; j < lnumverts; ++j)
- {
- int k;
- for (k = 0; k < VERTEXSIZE; ++k)
- poly->verts[j - 1][k] = poly->verts[j][k];
- }
- --lnumverts;
- ++nColinElim;
- // retry next vertex next time, which is now current vertex
- --i;
- }
- }
- }
- poly->numverts = lnumverts;
- }
- /*
- ========================
- GL_CreateSurfaceLightmap
- ========================
- */
- void GL_CreateSurfaceLightmap (msurface_t *surf)
- {
- int smax, tmax;
- byte *base;
- if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB))
- return;
- smax = (surf->extents[0]>>4)+1;
- tmax = (surf->extents[1]>>4)+1;
- surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t);
- base = lightmaps + surf->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
- base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes;
- R_BuildLightMap (surf, base, BLOCK_WIDTH*lightmap_bytes);
- }
- /*
- ==================
- GL_BuildLightmaps
- Builds the lightmap texture
- with all the surfaces from all brush models
- ==================
- */
- void GL_BuildLightmaps (void)
- {
- int i, j;
- model_t *m;
- memset (allocated, 0, sizeof(allocated));
- r_framecount = 1; // no dlightcache
- if (!lightmap_textures)
- {
- lightmap_textures = texture_extension_number;
- texture_extension_number += MAX_LIGHTMAPS;
- }
- gl_lightmap_format = GL_LUMINANCE;
- if (COM_CheckParm ("-lm_1"))
- gl_lightmap_format = GL_LUMINANCE;
- if (COM_CheckParm ("-lm_a"))
- gl_lightmap_format = GL_ALPHA;
- if (COM_CheckParm ("-lm_i"))
- gl_lightmap_format = GL_INTENSITY;
- if (COM_CheckParm ("-lm_2"))
- gl_lightmap_format = GL_RGBA4;
- if (COM_CheckParm ("-lm_4"))
- gl_lightmap_format = GL_RGBA;
- switch (gl_lightmap_format)
- {
- case GL_RGBA:
- lightmap_bytes = 4;
- break;
- case GL_RGBA4:
- lightmap_bytes = 2;
- break;
- case GL_LUMINANCE:
- case GL_INTENSITY:
- case GL_ALPHA:
- lightmap_bytes = 1;
- break;
- }
- for (j=1 ; j<MAX_MODELS ; j++)
- {
- m = cl.model_precache[j];
- if (!m)
- break;
- if (m->name[0] == '*')
- continue;
- r_pcurrentvertbase = m->vertexes;
- currentmodel = m;
- for (i=0 ; i<m->numsurfaces ; i++)
- {
- GL_CreateSurfaceLightmap (m->surfaces + i);
- if ( m->surfaces[i].flags & SURF_DRAWTURB )
- continue;
- #ifndef QUAKE2
- if ( m->surfaces[i].flags & SURF_DRAWSKY )
- continue;
- #endif
- BuildSurfaceDisplayList (m->surfaces + i);
- }
- }
- if (!gl_texsort.value)
- GL_SelectTexture(TEXTURE1_SGIS);
- //
- // upload all lightmaps that were filled
- //
- for (i=0 ; i<MAX_LIGHTMAPS ; i++)
- {
- if (!allocated[i][0])
- break; // no more used
- lightmap_modified[i] = false;
- lightmap_rectchange[i].l = BLOCK_WIDTH;
- lightmap_rectchange[i].t = BLOCK_HEIGHT;
- lightmap_rectchange[i].w = 0;
- lightmap_rectchange[i].h = 0;
- GL_Bind(lightmap_textures + i);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
- , BLOCK_WIDTH, BLOCK_HEIGHT, 0,
- gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes);
- }
- if (!gl_texsort.value)
- GL_SelectTexture(TEXTURE0_SGIS);
- }
|