diff --git a/Quake/common.h b/Quake/common.h index 3a510588..0fa7eda4 100644 --- a/Quake/common.h +++ b/Quake/common.h @@ -26,6 +26,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #if defined(_WIN32) #ifdef _MSC_VER +/* We use this POSIX function in image.c, in MSC it is called _getc_nolock */ +#define getc_unlocked _getc_nolock # pragma warning(disable:4244) /* 'argument' : conversion from 'type1' to 'type2', possible loss of data */ @@ -42,6 +44,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define fmin q_min #endif #endif /* _MSC_VER */ + +#ifndef _MSC_VER /* i.e., mingw */ +/* mingw doesn't have getc_unlocked, just use getc */ +#define getc_unlocked getc +#endif #endif /* _WIN32 */ #undef min diff --git a/Quake/gl_model.h b/Quake/gl_model.h index 01436269..c7526e22 100644 --- a/Quake/gl_model.h +++ b/Quake/gl_model.h @@ -74,6 +74,15 @@ typedef struct mplane_s byte pad[2]; } mplane_t; +// ericw -- each texture has two types of chains, and each surface can be a part of either or both independently. +// this is done because we draw the world, the brush models, and then parts of the world (transparent water) again, +// so we can build and clear each of the brush model chains without affecting the world chains. +typedef enum +{ + CHAINTYPE_WORLD = 0, + CHAINTYPE_MODEL = 1 +} texchaintype; + typedef struct texture_s { char name[16]; @@ -82,7 +91,7 @@ typedef struct texture_s struct gltexture_s *fullbright; //johnfitz -- fullbright mask texture struct gltexture_s *warpimage; //johnfitz -- for water animation qboolean update_warp; //johnfitz -- update warp this frame - struct msurface_s *texturechain; // for texture chains + struct msurface_s *texturechains[2]; // ericw -- CHAINTYPE_WORLD and CHAINTYPE_MODEL int anim_total; // total tenths in sequence ( 0 = no) int anim_min, anim_max; // time for this frame min <=time< max struct texture_s *anim_next; // in the animation sequence @@ -144,7 +153,7 @@ typedef struct msurface_s int light_s, light_t; // gl lightmap coordinates glpoly_t *polys; // multiple if warped - struct msurface_s *texturechain; + struct msurface_s *texturechains[2]; // ericw -- CHAINTYPE_WORLD and CHAINTYPE_MODEL mtexinfo_t *texinfo; diff --git a/Quake/gl_rmain.c b/Quake/gl_rmain.c index faf4a15e..3d1a4f87 100644 --- a/Quake/gl_rmain.c +++ b/Quake/gl_rmain.c @@ -643,7 +643,7 @@ void R_ShowTris (void) if (r_drawworld.value) { - R_DrawTextureChains_ShowTris (); + R_DrawWorld_ShowTris (); } if (r_drawentities.value) @@ -750,7 +750,7 @@ void R_RenderScene (void) R_DrawEntitiesOnList (false); //johnfitz -- false means this is the pass for nonalpha entities - R_DrawTextureChains_Water (); //johnfitz -- drawn here since they might have transparency + R_DrawWorld_Water (); //johnfitz -- drawn here since they might have transparency R_DrawEntitiesOnList (true); //johnfitz -- true means this is the pass for alpha entities diff --git a/Quake/gl_sky.c b/Quake/gl_sky.c index 587e63d6..2127371c 100644 --- a/Quake/gl_sky.c +++ b/Quake/gl_sky.c @@ -526,10 +526,10 @@ void Sky_ProcessTextureChains (void) { t = cl.worldmodel->textures[i]; - if (!t || !t->texturechain || !(t->texturechain->flags & SURF_DRAWSKY)) + if (!t || !t->texturechains[CHAINTYPE_WORLD] || !(t->texturechains[CHAINTYPE_WORLD]->flags & SURF_DRAWSKY)) continue; - for (s = t->texturechain; s; s = s->texturechain) + for (s = t->texturechains[CHAINTYPE_WORLD]; s; s = s->texturechains[CHAINTYPE_WORLD]) if (!s->culled) Sky_ProcessPoly (s->polys); } diff --git a/Quake/gl_warp.c b/Quake/gl_warp.c index bc4c328c..f02a77de 100644 --- a/Quake/gl_warp.c +++ b/Quake/gl_warp.c @@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern cvar_t r_drawflat; -cvar_t r_oldwater = {"r_oldwater", "1", CVAR_ARCHIVE}; +cvar_t r_oldwater = {"r_oldwater", "0", CVAR_ARCHIVE}; cvar_t r_waterquality = {"r_waterquality", "8", CVAR_NONE}; cvar_t r_waterwarp = {"r_waterwarp", "1", CVAR_NONE}; diff --git a/Quake/glquake.h b/Quake/glquake.h index 97818f4d..24c4c52b 100644 --- a/Quake/glquake.h +++ b/Quake/glquake.h @@ -271,7 +271,7 @@ void R_DrawAliasModel (entity_t *e); void R_DrawBrushModel (entity_t *e); void R_DrawSpriteModel (entity_t *e); -void R_DrawTextureChains_Water (void); +void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchaintype chaintype); void R_RenderDlights (void); void GL_BuildLightmaps (void); @@ -281,10 +281,10 @@ int R_LightPoint (vec3_t p); void GL_SubdivideSurface (msurface_t *fa); void R_BuildLightMap (msurface_t *surf, byte *dest, int stride); -void R_RenderDynamicLightmaps (msurface_t *fa); +void R_RenderDynamicLightmaps (msurface_t *fa, texchaintype chaintype); void R_UploadLightmap (int lmap); -void R_DrawTextureChains_ShowTris (void); +void R_DrawWorld_ShowTris (void); void R_DrawBrushModel_ShowTris (entity_t *e); void R_DrawAliasModel_ShowTris (entity_t *e); void R_DrawParticles_ShowTris (void); @@ -303,5 +303,10 @@ void Sky_LoadSkyBox (const char *name); void TexMgr_RecalcWarpImageSize (void); +void R_ClearTextureChains (qmodel_t *mod, texchaintype chaintype); +void R_ChainSurface (msurface_t *surf, texchaintype chaintype); +void R_DrawTextureChains (qmodel_t *model, entity_t *ent, texchaintype chaintype); +void R_DrawWorld_Water (); + #endif /* __GLQUAKE_H */ diff --git a/Quake/image.c b/Quake/image.c index 91c4046e..c4467c22 100644 --- a/Quake/image.c +++ b/Quake/image.c @@ -72,8 +72,8 @@ int fgetLittleShort (FILE *f) { byte b1, b2; - b1 = fgetc(f); - b2 = fgetc(f); + b1 = getc_unlocked(f); + b2 = getc_unlocked(f); return (short)(b1 + b2*256); } @@ -82,10 +82,10 @@ int fgetLittleLong (FILE *f) { byte b1, b2, b3, b4; - b1 = fgetc(f); - b2 = fgetc(f); - b3 = fgetc(f); - b4 = fgetc(f); + b1 = getc_unlocked(f); + b2 = getc_unlocked(f); + b3 = getc_unlocked(f); + b4 = getc_unlocked(f); return b1 + (b2<<8) + (b3<<16) + (b4<<24); } @@ -152,19 +152,19 @@ byte *Image_LoadTGA (FILE *fin, int *width, int *height) int realrow; //johnfitz -- fix for upside-down targas qboolean upside_down; //johnfitz -- fix for upside-down targas - targa_header.id_length = fgetc(fin); - targa_header.colormap_type = fgetc(fin); - targa_header.image_type = fgetc(fin); + targa_header.id_length = getc_unlocked(fin); + targa_header.colormap_type = getc_unlocked(fin); + targa_header.image_type = getc_unlocked(fin); targa_header.colormap_index = fgetLittleShort(fin); targa_header.colormap_length = fgetLittleShort(fin); - targa_header.colormap_size = fgetc(fin); + targa_header.colormap_size = getc_unlocked(fin); targa_header.x_origin = fgetLittleShort(fin); targa_header.y_origin = fgetLittleShort(fin); targa_header.width = fgetLittleShort(fin); targa_header.height = fgetLittleShort(fin); - targa_header.pixel_size = fgetc(fin); - targa_header.attributes = fgetc(fin); + targa_header.pixel_size = getc_unlocked(fin); + targa_header.attributes = getc_unlocked(fin); if (targa_header.image_type!=2 && targa_header.image_type!=10) Sys_Error ("Image_LoadTGA: %s is not a type 2 or type 10 targa\n", loadfilename); @@ -196,19 +196,19 @@ byte *Image_LoadTGA (FILE *fin, int *width, int *height) switch (targa_header.pixel_size) { case 24: - blue = getc(fin); - green = getc(fin); - red = getc(fin); + blue = getc_unlocked(fin); + green = getc_unlocked(fin); + red = getc_unlocked(fin); *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; *pixbuf++ = 255; break; case 32: - blue = getc(fin); - green = getc(fin); - red = getc(fin); - alphabyte = getc(fin); + blue = getc_unlocked(fin); + green = getc_unlocked(fin); + red = getc_unlocked(fin); + alphabyte = getc_unlocked(fin); *pixbuf++ = red; *pixbuf++ = green; *pixbuf++ = blue; @@ -229,23 +229,23 @@ byte *Image_LoadTGA (FILE *fin, int *width, int *height) //johnfitz for(column=0; column= 0xC0) { runlength = readbyte & 0x3F; - readbyte = fgetc(f); + readbyte = getc_unlocked(f); } else runlength = 1; diff --git a/Quake/r_brush.c b/Quake/r_brush.c index a78b287d..4c2d8f12 100644 --- a/Quake/r_brush.c +++ b/Quake/r_brush.c @@ -40,11 +40,12 @@ typedef struct glRect_s { unsigned char l,t,w,h; } glRect_t; -glpoly_t *lightmap_polys[MAX_LIGHTMAPS]; +glpoly_t *lightmap_polys_by_chaintype[2][MAX_LIGHTMAPS]; qboolean lightmap_modified[MAX_LIGHTMAPS]; glRect_t lightmap_rectchange[MAX_LIGHTMAPS]; int allocated[MAX_LIGHTMAPS][BLOCK_WIDTH]; +int last_lightmap_allocated; //ericw -- optimization: remember the index of the last lightmap AllocBlock stored a surf in // the lightmap texture data needs to be kept in // main memory so texsubimage can update properly @@ -132,6 +133,7 @@ void DrawGLTriangleFan (glpoly_t *p) ============================================================= */ +#if 0 /* ================ R_DrawSequentialPoly -- johnfitz -- rewritten @@ -492,7 +494,7 @@ fullbrights: rs_brushpasses++; } } - +#endif /* ================= R_DrawBrushModel @@ -559,12 +561,7 @@ void R_DrawBrushModel (entity_t *e) } e->angles[0] = -e->angles[0]; // stupid quake bug - // - // draw it - // - if (r_drawflat_cheatsafe) //johnfitz - glDisable(GL_TEXTURE_2D); - + R_ClearTextureChains (clmodel, CHAINTYPE_MODEL); for (i=0 ; inummodelsurfaces ; i++, psurf++) { pplane = psurf->plane; @@ -572,15 +569,17 @@ void R_DrawBrushModel (entity_t *e) if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - R_DrawSequentialPoly (psurf); + R_ChainSurface (psurf, CHAINTYPE_MODEL); rs_brushpolys++; } } - if (r_drawflat_cheatsafe) //johnfitz - glEnable(GL_TEXTURE_2D); + // + // draw it + // - GL_DisableMultitexture(); // selects TEXTURE0 + R_DrawTextureChains (clmodel, e, CHAINTYPE_MODEL); + R_DrawTextureChains_Water (clmodel, e, CHAINTYPE_MODEL); glPopMatrix (); } @@ -660,7 +659,7 @@ R_RenderDynamicLightmaps called during rendering ================ */ -void R_RenderDynamicLightmaps (msurface_t *fa) +void R_RenderDynamicLightmaps (msurface_t *fa, texchaintype chaintype) { byte *base; int maps; @@ -671,8 +670,8 @@ void R_RenderDynamicLightmaps (msurface_t *fa) return; // add to lightmap chain - fa->polys->chain = lightmap_polys[fa->lightmaptexturenum]; - lightmap_polys[fa->lightmaptexturenum] = fa->polys; + fa->polys->chain = lightmap_polys_by_chaintype[chaintype][fa->lightmaptexturenum]; + lightmap_polys_by_chaintype[chaintype][fa->lightmaptexturenum] = fa->polys; // check for lightmap modification for (maps=0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++) @@ -721,7 +720,12 @@ int AllocBlock (int w, int h, int *x, int *y) int best, best2; int texnum; - for (texnum=0 ; texnumnumtextures ; i++) + if (mod->textures[i]) + mod->textures[i]->texturechains[chaintype] = NULL; +} + +/* +=============== +R_ChainSurface -- ericw -- adds a surface to the head of the texture chain of its texture +=============== +*/ +void R_ChainSurface (msurface_t *surf, texchaintype chaintype) +{ + surf->texturechains[chaintype] = surf->texinfo->texture->texturechains[chaintype]; + surf->texinfo->texture->texturechains[chaintype] = surf; +} + + /* =============== R_MarkSurfaces -- johnfitz -- mark surfaces based on PVS and rebuild texture chains @@ -52,7 +82,7 @@ void R_MarkSurfaces (void) qboolean nearwaterportal; // clear lightmap chains - memset (lightmap_polys, 0, sizeof(lightmap_polys)); + memset (lightmap_polys_by_chaintype[CHAINTYPE_WORLD], 0, sizeof(lightmap_polys_by_chaintype[0])); // check this leaf for water portals // TODO: loop through all water surfs and use distance to leaf cullbox @@ -101,9 +131,7 @@ void R_MarkSurfaces (void) } // set all chains to null - for (i=0 ; inumtextures ; i++) - if (cl.worldmodel->textures[i]) - cl.worldmodel->textures[i]->texturechain = NULL; + R_ClearTextureChains (cl.worldmodel, CHAINTYPE_WORLD); // rebuild chains @@ -116,8 +144,7 @@ void R_MarkSurfaces (void) for (j=0, surf=&cl.worldmodel->surfaces[node->firstsurface] ; jnumsurfaces ; j++, surf++) if (surf->visframe == r_visframecount) { - surf->texturechain = surf->texinfo->texture->texturechain; - surf->texinfo->texture->texturechain = surf; + R_ChainSurface (surf, CHAINTYPE_WORLD); } #else //the old way @@ -200,19 +227,22 @@ void R_CullSurfaces (void) R_BuildLightmapChains -- johnfitz -- used for r_lightmap 1 ================ */ -void R_BuildLightmapChains (void) +void R_BuildLightmapChains (qmodel_t *model, texchaintype chaintype) { msurface_t *s; int i; + qboolean isworld; + + isworld = (model == cl.worldmodel); // clear lightmap chains (already done in r_marksurfaces, but clearing them here to be safe becuase of r_stereo) - memset (lightmap_polys, 0, sizeof(lightmap_polys)); + memset (lightmap_polys_by_chaintype[chaintype], 0, sizeof(lightmap_polys_by_chaintype[0])); // now rebuild them - s = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface]; - for (i=0 ; inummodelsurfaces ; i++, s++) - if (s->visframe == r_visframecount && !R_CullBox(s->mins, s->maxs) && !R_BackFaceCull (s)) - R_RenderDynamicLightmaps (s); + s = &model->surfaces[model->firstmodelsurface]; + for (i=0 ; inummodelsurfaces ; i++, s++) + if (!isworld || (s->visframe == r_visframecount && !R_CullBox(s->mins, s->maxs) && !R_BackFaceCull (s))) + R_RenderDynamicLightmaps (s, chaintype); } //============================================================================== @@ -221,27 +251,59 @@ void R_BuildLightmapChains (void) // //============================================================================== +/* +============= +R_BeginTransparentDrawing -- ericw +============= +*/ +static void R_BeginTransparentDrawing (float entalpha) +{ + if (entalpha < 1.0f) + { + glDepthMask (GL_FALSE); + glEnable (GL_BLEND); + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor4f (1,1,1,entalpha); + } +} + +/* +============= +R_EndTransparentDrawing -- ericw +============= +*/ +static void R_EndTransparentDrawing (float entalpha) +{ + if (entalpha < 1.0f) + { + glDepthMask (GL_TRUE); + glDisable (GL_BLEND); + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glColor3f (1, 1, 1); + } +} + /* ================ R_DrawTextureChains_ShowTris -- johnfitz ================ */ -void R_DrawTextureChains_ShowTris (void) +void R_DrawTextureChains_ShowTris (qmodel_t *model, texchaintype chaintype) { int i; msurface_t *s; texture_t *t; glpoly_t *p; - for (i=0 ; inumtextures ; i++) + for (i=0 ; inumtextures ; i++) { - t = cl.worldmodel->textures[i]; + t = model->textures[i]; if (!t) continue; - if (r_oldwater.value && t->texturechain && (t->texturechain->flags & SURF_DRAWTURB)) + if (r_oldwater.value && t->texturechains[chaintype] && (t->texturechains[chaintype]->flags & SURF_DRAWTURB)) { - for (s = t->texturechain; s; s = s->texturechain) + for (s = t->texturechains[chaintype]; s; s = s->texturechains[chaintype]) if (!s->culled) for (p = s->polys->next; p; p = p->next) { @@ -250,7 +312,7 @@ void R_DrawTextureChains_ShowTris (void) } else { - for (s = t->texturechain; s; s = s->texturechain) + for (s = t->texturechains[chaintype]; s; s = s->texturechains[chaintype]) if (!s->culled) { DrawGLTriangleFan (s->polys); @@ -264,22 +326,22 @@ void R_DrawTextureChains_ShowTris (void) R_DrawTextureChains_Drawflat -- johnfitz ================ */ -void R_DrawTextureChains_Drawflat (void) +void R_DrawTextureChains_Drawflat (qmodel_t *model, texchaintype chaintype) { int i; msurface_t *s; texture_t *t; glpoly_t *p; - for (i=0 ; inumtextures ; i++) + for (i=0 ; inumtextures ; i++) { - t = cl.worldmodel->textures[i]; + t = model->textures[i]; if (!t) continue; - if (r_oldwater.value && t->texturechain && (t->texturechain->flags & SURF_DRAWTURB)) + if (r_oldwater.value && t->texturechains[chaintype] && (t->texturechains[chaintype]->flags & SURF_DRAWTURB)) { - for (s = t->texturechain; s; s = s->texturechain) + for (s = t->texturechains[chaintype]; s; s = s->texturechains[chaintype]) if (!s->culled) for (p = s->polys->next; p; p = p->next) { @@ -291,7 +353,7 @@ void R_DrawTextureChains_Drawflat (void) } else { - for (s = t->texturechain; s; s = s->texturechain) + for (s = t->texturechains[chaintype]; s; s = s->texturechains[chaintype]) if (!s->culled) { srand((unsigned int) (uintptr_t) s->polys); @@ -310,7 +372,7 @@ void R_DrawTextureChains_Drawflat (void) R_DrawTextureChains_Glow -- johnfitz ================ */ -void R_DrawTextureChains_Glow (void) +void R_DrawTextureChains_Glow (qmodel_t *model, entity_t *ent, texchaintype chaintype) { int i; msurface_t *s; @@ -318,16 +380,16 @@ void R_DrawTextureChains_Glow (void) gltexture_t *glt; qboolean bound; - for (i=0 ; inumtextures ; i++) + for (i=0 ; inumtextures ; i++) { - t = cl.worldmodel->textures[i]; + t = model->textures[i]; - if (!t || !t->texturechain || !(glt = R_TextureAnimation(t,0)->fullbright)) + if (!t || !t->texturechains[chaintype] || !(glt = R_TextureAnimation(t, ent != NULL ? ent->frame : 0)->fullbright)) continue; bound = false; - for (s = t->texturechain; s; s = s->texturechain) + for (s = t->texturechains[chaintype]; s; s = s->texturechains[chaintype]) if (!s->culled) { if (!bound) //only bind once we are sure we need this texture @@ -346,7 +408,7 @@ void R_DrawTextureChains_Glow (void) R_DrawTextureChains_Multitexture -- johnfitz ================ */ -void R_DrawTextureChains_Multitexture (void) +void R_DrawTextureChains_Multitexture (qmodel_t *model, entity_t *ent, texchaintype chaintype) { int i, j; msurface_t *s; @@ -354,24 +416,24 @@ void R_DrawTextureChains_Multitexture (void) float *v; qboolean bound; - for (i=0 ; inumtextures ; i++) + for (i=0 ; inumtextures ; i++) { - t = cl.worldmodel->textures[i]; + t = model->textures[i]; - if (!t || !t->texturechain || t->texturechain->flags & (SURF_DRAWTILED | SURF_NOTEXTURE)) + if (!t || !t->texturechains[chaintype] || t->texturechains[chaintype]->flags & (SURF_DRAWTILED | SURF_NOTEXTURE)) continue; bound = false; - for (s = t->texturechain; s; s = s->texturechain) + for (s = t->texturechains[chaintype]; s; s = s->texturechains[chaintype]) if (!s->culled) { if (!bound) //only bind once we are sure we need this texture { - GL_Bind ((R_TextureAnimation(t,0))->gltexture); + GL_Bind ((R_TextureAnimation(t, ent != NULL ? ent->frame : 0))->gltexture); GL_EnableMultitexture(); // selects TEXTURE1 bound = true; } - R_RenderDynamicLightmaps (s); + R_RenderDynamicLightmaps (s, chaintype); GL_Bind (lightmap_textures[s->lightmaptexturenum]); R_UploadLightmap(s->lightmaptexturenum); glBegin(GL_POLYGON); @@ -396,23 +458,23 @@ R_DrawTextureChains_NoTexture -- johnfitz draws surfs whose textures were missing from the BSP ================ */ -void R_DrawTextureChains_NoTexture (void) +void R_DrawTextureChains_NoTexture (qmodel_t *model, texchaintype chaintype) { int i; msurface_t *s; texture_t *t; qboolean bound; - for (i=0 ; inumtextures ; i++) + for (i=0 ; inumtextures ; i++) { - t = cl.worldmodel->textures[i]; + t = model->textures[i]; - if (!t || !t->texturechain || !(t->texturechain->flags & SURF_NOTEXTURE)) + if (!t || !t->texturechains[chaintype] || !(t->texturechains[chaintype]->flags & SURF_NOTEXTURE)) continue; bound = false; - for (s = t->texturechain; s; s = s->texturechain) + for (s = t->texturechains[chaintype]; s; s = s->texturechains[chaintype]) if (!s->culled) { if (!bound) //only bind once we are sure we need this texture @@ -431,31 +493,31 @@ void R_DrawTextureChains_NoTexture (void) R_DrawTextureChains_TextureOnly -- johnfitz ================ */ -void R_DrawTextureChains_TextureOnly (void) +void R_DrawTextureChains_TextureOnly (qmodel_t *model, entity_t *ent, texchaintype chaintype) { int i; msurface_t *s; texture_t *t; qboolean bound; - for (i=0 ; inumtextures ; i++) + for (i=0 ; inumtextures ; i++) { - t = cl.worldmodel->textures[i]; + t = model->textures[i]; - if (!t || !t->texturechain || t->texturechain->flags & (SURF_DRAWTURB | SURF_DRAWSKY)) + if (!t || !t->texturechains[chaintype] || t->texturechains[chaintype]->flags & (SURF_DRAWTURB | SURF_DRAWSKY)) continue; bound = false; - for (s = t->texturechain; s; s = s->texturechain) + for (s = t->texturechains[chaintype]; s; s = s->texturechains[chaintype]) if (!s->culled) { if (!bound) //only bind once we are sure we need this texture { - GL_Bind ((R_TextureAnimation(t,0))->gltexture); + GL_Bind ((R_TextureAnimation(t, ent != NULL ? ent->frame : 0))->gltexture); bound = true; } - R_RenderDynamicLightmaps (s); //adds to lightmap chain + R_RenderDynamicLightmaps (s, chaintype); //adds to lightmap chain DrawGLPoly (s->polys); rs_brushpasses++; } @@ -467,34 +529,33 @@ void R_DrawTextureChains_TextureOnly (void) R_DrawTextureChains_Water -- johnfitz ================ */ -void R_DrawTextureChains_Water (void) +void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchaintype chaintype) { int i; msurface_t *s; texture_t *t; glpoly_t *p; qboolean bound; + float entalpha; - if (r_drawflat_cheatsafe || r_lightmap_cheatsafe || !r_drawworld_cheatsafe) + if (r_drawflat_cheatsafe || r_lightmap_cheatsafe) // ericw -- !r_drawworld_cheatsafe check moved to R_DrawWorld_Water () return; - if (r_wateralpha.value < 1.0) - { - glDepthMask(GL_FALSE); - glEnable (GL_BLEND); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glColor4f (1,1,1,r_wateralpha.value); - } + entalpha = (model == cl.worldmodel) ? r_wateralpha.value : + (ent == NULL) ? 1.0f : + ENTALPHA_DECODE(ent->alpha); + + R_BeginTransparentDrawing (entalpha); if (r_oldwater.value) { - for (i=0 ; inumtextures ; i++) + for (i=0 ; inumtextures ; i++) { - t = cl.worldmodel->textures[i]; - if (!t || !t->texturechain || !(t->texturechain->flags & SURF_DRAWTURB)) + t = model->textures[i]; + if (!t || !t->texturechains[chaintype] || !(t->texturechains[chaintype]->flags & SURF_DRAWTURB)) continue; bound = false; - for (s = t->texturechain; s; s = s->texturechain) + for (s = t->texturechains[chaintype]; s; s = s->texturechains[chaintype]) if (!s->culled) { if (!bound) //only bind once we are sure we need this texture @@ -512,18 +573,27 @@ void R_DrawTextureChains_Water (void) } else { - for (i=0 ; inumtextures ; i++) + for (i=0 ; inumtextures ; i++) { - t = cl.worldmodel->textures[i]; - if (!t || !t->texturechain || !(t->texturechain->flags & SURF_DRAWTURB)) + t = model->textures[i]; + if (!t || !t->texturechains[chaintype] || !(t->texturechains[chaintype]->flags & SURF_DRAWTURB)) continue; bound = false; - for (s = t->texturechain; s; s = s->texturechain) + for (s = t->texturechains[chaintype]; s; s = s->texturechains[chaintype]) if (!s->culled) { if (!bound) //only bind once we are sure we need this texture { GL_Bind (t->warpimage); + + if (model != cl.worldmodel) + { + // ericw -- this is copied from R_DrawSequentialPoly. + // If the poly is not part of the world we have to + // set this flag + t->update_warp = true; // FIXME: one frame too late! + } + bound = true; } DrawGLPoly (s->polys); @@ -532,13 +602,7 @@ void R_DrawTextureChains_Water (void) } } - if (r_wateralpha.value < 1.0) - { - glDepthMask(GL_TRUE); - glDisable (GL_BLEND); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glColor3f (1,1,1); - } + R_EndTransparentDrawing (entalpha); } /* @@ -546,21 +610,21 @@ void R_DrawTextureChains_Water (void) R_DrawTextureChains_White -- johnfitz -- draw sky and water as white polys when r_lightmap is 1 ================ */ -void R_DrawTextureChains_White (void) +void R_DrawTextureChains_White (qmodel_t *model, texchaintype chaintype) { int i; msurface_t *s; texture_t *t; glDisable (GL_TEXTURE_2D); - for (i=0 ; inumtextures ; i++) + for (i=0 ; inumtextures ; i++) { - t = cl.worldmodel->textures[i]; + t = model->textures[i]; - if (!t || !t->texturechain || !(t->texturechain->flags & SURF_DRAWTILED)) + if (!t || !t->texturechains[chaintype] || !(t->texturechains[chaintype]->flags & SURF_DRAWTILED)) continue; - for (s = t->texturechain; s; s = s->texturechain) + for (s = t->texturechains[chaintype]; s; s = s->texturechains[chaintype]) if (!s->culled) { DrawGLPoly (s->polys); @@ -575,7 +639,7 @@ void R_DrawTextureChains_White (void) R_DrawLightmapChains -- johnfitz -- R_BlendLightmaps stripped down to almost nothing ================ */ -void R_DrawLightmapChains (void) +void R_DrawLightmapChains (qmodel_t *model, texchaintype chaintype) { int i, j; glpoly_t *p; @@ -583,12 +647,12 @@ void R_DrawLightmapChains (void) for (i=0 ; ichain) + for (p = lightmap_polys_by_chaintype[chaintype][i]; p; p=p->chain) { glBegin (GL_POLYGON); v = p->verts[0]; @@ -605,51 +669,57 @@ void R_DrawLightmapChains (void) /* ============= -R_DrawWorld -- johnfitz -- rewritten +R_DrawTextureChains -- johnfitz -- rewritten + +ericw -- added model and ent params; no longer specific to the world ============= */ -void R_DrawWorld (void) +void R_DrawTextureChains (qmodel_t *model, entity_t *ent, texchaintype chaintype) { - if (!r_drawworld_cheatsafe) - return; + float entalpha; + entalpha = (ent == NULL) ? 1.0f : ENTALPHA_DECODE(ent->alpha); if (r_drawflat_cheatsafe) { glDisable (GL_TEXTURE_2D); - R_DrawTextureChains_Drawflat (); + R_DrawTextureChains_Drawflat (model, chaintype); glEnable (GL_TEXTURE_2D); return; } if (r_fullbright_cheatsafe) { - R_DrawTextureChains_TextureOnly (); + R_BeginTransparentDrawing (entalpha); + R_DrawTextureChains_TextureOnly (model, ent, chaintype); + R_EndTransparentDrawing (entalpha); goto fullbrights; } if (r_lightmap_cheatsafe) { - R_BuildLightmapChains (); + R_BuildLightmapChains (model, chaintype); if (!gl_overbright.value) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glColor3f(0.5, 0.5, 0.5); } - R_DrawLightmapChains (); + R_DrawLightmapChains (model, chaintype); if (!gl_overbright.value) { glColor3f(1,1,1); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } - R_DrawTextureChains_White (); + R_DrawTextureChains_White (model, chaintype); return; } - R_DrawTextureChains_NoTexture (); + R_BeginTransparentDrawing (entalpha); + + R_DrawTextureChains_NoTexture (model, chaintype); if (gl_overbright.value) { - if (gl_texture_env_combine && gl_mtexable) + if (gl_texture_env_combine && gl_mtexable) //case 1: texture and lightmap in one pass, overbright using texture combiners { GL_EnableMultitexture (); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); @@ -658,33 +728,37 @@ void R_DrawWorld (void) glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f); GL_DisableMultitexture (); - R_DrawTextureChains_Multitexture (); + R_DrawTextureChains_Multitexture (model, ent, chaintype); GL_EnableMultitexture (); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); GL_DisableMultitexture (); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } - else + else if (entalpha < 1) //case 2: can't do multipass if entity has alpha, so just draw the texture + { + R_DrawTextureChains_TextureOnly (model, ent, chaintype); + } + else //case 3: texture in one pass, lightmap in second pass using 2x modulation blend func, fog in third pass { //to make fog work with multipass lightmapping, need to do one pass //with no fog, one modulate pass with black fog, and one additive //pass with black geometry and normal fog Fog_DisableGFog (); - R_DrawTextureChains_TextureOnly (); + R_DrawTextureChains_TextureOnly (model, ent, chaintype); Fog_EnableGFog (); glDepthMask (GL_FALSE); glEnable (GL_BLEND); glBlendFunc (GL_DST_COLOR, GL_SRC_COLOR); //2x modulate Fog_StartAdditive (); - R_DrawLightmapChains (); + R_DrawLightmapChains (model, chaintype); Fog_StopAdditive (); if (Fog_GetDensity() > 0) { glBlendFunc(GL_ONE, GL_ONE); //add glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glColor3f(0,0,0); - R_DrawTextureChains_TextureOnly (); + R_DrawTextureChains_TextureOnly (model, ent, chaintype); glColor3f(1,1,1); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } @@ -695,34 +769,38 @@ void R_DrawWorld (void) } else { - if (gl_mtexable) + if (gl_mtexable) //case 4: texture and lightmap in one pass, regular modulation { GL_EnableMultitexture (); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); GL_DisableMultitexture (); - R_DrawTextureChains_Multitexture (); + R_DrawTextureChains_Multitexture (model, ent, chaintype); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } - else + else if (entalpha < 1) //case 5: can't do multipass if entity has alpha, so just draw the texture + { + R_DrawTextureChains_TextureOnly (model, ent, chaintype); + } + else //case 6: texture in one pass, lightmap in a second pass, fog in third pass { //to make fog work with multipass lightmapping, need to do one pass //with no fog, one modulate pass with black fog, and one additive //pass with black geometry and normal fog Fog_DisableGFog (); - R_DrawTextureChains_TextureOnly (); + R_DrawTextureChains_TextureOnly (model, ent, chaintype); Fog_EnableGFog (); glDepthMask (GL_FALSE); glEnable (GL_BLEND); glBlendFunc(GL_ZERO, GL_SRC_COLOR); //modulate Fog_StartAdditive (); - R_DrawLightmapChains (); + R_DrawLightmapChains (model, chaintype); Fog_StopAdditive (); if (Fog_GetDensity() > 0) { glBlendFunc(GL_ONE, GL_ONE); //add glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glColor3f(0,0,0); - R_DrawTextureChains_TextureOnly (); + R_DrawTextureChains_TextureOnly (model, ent, chaintype); glColor3f(1,1,1); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } @@ -732,17 +810,62 @@ void R_DrawWorld (void) } } + R_EndTransparentDrawing (entalpha); + fullbrights: if (gl_fullbrights.value) { glDepthMask (GL_FALSE); glEnable (GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f (entalpha, entalpha, entalpha); Fog_StartAdditive (); - R_DrawTextureChains_Glow (); + R_DrawTextureChains_Glow (model, ent, chaintype); Fog_StopAdditive (); + glColor3f (1, 1, 1); + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable (GL_BLEND); glDepthMask (GL_TRUE); } } + +/* +============= +R_DrawWorld -- ericw -- moved from R_DrawTextureChains, which is no longer specific to the world. +============= +*/ +void R_DrawWorld (void) +{ + if (!r_drawworld_cheatsafe) + return; + + R_DrawTextureChains(cl.worldmodel, NULL, CHAINTYPE_WORLD); +} + +/* +============= +R_DrawWorld_Water -- ericw -- moved from R_DrawTextureChains_Water, which is no longer specific to the world. +============= +*/ +void R_DrawWorld_Water (void) +{ + if (!r_drawworld_cheatsafe) + return; + + R_DrawTextureChains_Water (cl.worldmodel, NULL, CHAINTYPE_WORLD); +} + +/* +============= +R_DrawWorld_ShowTris -- ericw -- moved from R_DrawTextureChains_ShowTris, which is no longer specific to the world. +============= +*/ +void R_DrawWorld_ShowTris (void) +{ + if (!r_drawworld_cheatsafe) + return; + + R_DrawTextureChains_ShowTris (cl.worldmodel, CHAINTYPE_WORLD); +}