diff --git a/common/gl_rsurf.c b/common/gl_rsurf.c index 81fac23..7d11f6b 100644 --- a/common/gl_rsurf.c +++ b/common/gl_rsurf.c @@ -142,7 +142,8 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) int i, j, size; byte *lightmap; unsigned scale; - int maps; + int maps; + int lightadj[4]; unsigned *bl; surf->cached_dlight = (surf->dlightframe == r_framecount); @@ -153,7 +154,7 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) lightmap = surf->samples; // set to full bright if no light data - if (/* r_fullbright.value || */ !cl.worldmodel->lightdata) + if (r_fullbright.value || !cl.worldmodel->lightdata) { for (i=0 ; iflags & (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 ; inumverts ; 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 ; inumverts ; 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 @@ -461,6 +361,34 @@ void R_DrawSequentialPoly (msurface_t *s) glVertex3fv (v); } glEnd (); + + // Neal White III - 12-29-1999 - render the glow map + + if (t->flags & FLAG_HAS_GLOWMAP) + { + GL_DisableMultitexture(); + GL_Bind (t->gl_glowtexnum); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glEnable (GL_BLEND); + glBlendFunc (GL_ONE, GL_ONE); + + glBegin (GL_POLYGON); + v = p->verts[0]; + for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) + { + glTexCoord2f (v[3], v[4]); + glVertex3fv (v); + } + glEnd (); + + // restore it to Quake's default + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable (GL_BLEND); + } + // Neal White III - 12-29-1999 - END return; } else { p = s->polys; @@ -569,6 +497,44 @@ void R_DrawSequentialPoly (msurface_t *s) } glEnd (); + // Neal White III - 12-31-1999 - render the glow map + + if (t->flags & FLAG_HAS_GLOWMAP) + { + GL_DisableMultitexture(); + GL_Bind (t->gl_glowtexnum); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glEnable (GL_BLEND); + glBlendFunc (GL_ONE, GL_ONE); + + glBegin (GL_POLYGON); + v = p->verts[0]; + for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) + { + glTexCoord2f (v[3], v[4]); + + // Neal - DON'T DELETE - leaves unmoving glowmap on top + // I think this is a clue to the "underwater cracks" bug + // + //glVertex3fv (v); + + 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 (); + + // restore it to Quake's default + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable (GL_BLEND); + } + // Neal White III - 12-31-1999 - END + } else { p = s->polys; @@ -582,7 +548,6 @@ void R_DrawSequentialPoly (msurface_t *s) glDisable (GL_BLEND); } } -#endif /* diff --git a/qw_client/gl_model.c b/qw_client/gl_model.c index 7bbca98..7dcf1c7 100644 --- a/qw_client/gl_model.c +++ b/qw_client/gl_model.c @@ -345,6 +345,30 @@ void Mod_LoadTextures (lump_t *l) texture_t *altanims[10]; dmiptexlump_t *m; + // Neal White III - 12-28-1999 - OpenGL fullbright bugfix + // nwhite@softblox.com + // http://home.telefragged.com/wally/ + // + // Problem: + // + // There was a problem in the original glquake with fullbright texels. + // In the software renderer, fullbrights glow brightly in the dark. + // Essentially, the fullbrights were ignored. I've fixed it by + // adding another rendering pass and creating a new glowmap texture. + // + // Fix: + // + // When a texture with fullbright (FB) texels is loaded, a copy is made, + // then the FB pixels are cleared to black in the original texture. In + // the copy, all normal colors are cleared and only the FBs remain. When + // it comes time to render the polygons, I do an additional pass and ADD + // the glowmap on top of the current polygon. + + byte *ptexel; + qboolean hasfullbrights; + qboolean noglow = COM_CheckParm("-noglow"); + // Neal White III - 12-28-1999 - END + if (!l->filelen) { loadmodel->textures = NULL; @@ -370,25 +394,172 @@ void Mod_LoadTextures (lump_t *l) if ( (mt->width & 15) || (mt->height & 15) ) Sys_Error ("Texture %s is not 16 aligned", mt->name); + pixels = mt->width*mt->height/64*85; - tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname ); + + // Neal White III - 12-28-1999 - OpenGL fullbright bugfix + + hasfullbrights = false; + + if ((!Q_strncmp(mt->name,"sky",3)) || + (!Q_strncmp(mt->name,"*",1)) || // turbulent (liquid) + (noglow) || (! gl_mtexable)) + { + // sky has no lightmap, nor do liquids (so never needs a glowmap), + // -noglow command line parameter, or no multi-texture support + // + // hasfullbrights is already false + } + else // check this texture for fullbright texels + { + ptexel = (byte *)(mt+1); + + for (j=0 ; j= 256-32) // 32 fullbright colors + { + hasfullbrights = true; + break; + } + } + } + + if (hasfullbrights) + tx = Hunk_AllocName (sizeof(texture_t) +pixels*2, loadname ); + else + tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname ); loadmodel->textures[i] = tx; memcpy (tx->name, mt->name, sizeof(tx->name)); tx->width = mt->width; tx->height = mt->height; for (j=0 ; joffsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t); + + if (hasfullbrights) + tx->glowoffsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t) + pixels; + else + tx->glowoffsets[j] = 0; + } // the pixels immediately follow the structures memcpy ( tx+1, mt+1, pixels); + if (hasfullbrights) + { + ptexel = (byte *)(tx+1); + memcpy ( ptexel+pixels, mt+1, pixels); + } + + tx->flags = 0; if (!Q_strncmp(mt->name,"sky",3)) - R_InitSky (tx); - else { + // Neal White III - 12-30-1999 - new variable speed sky layers + + if (!Q_strncmp(mt->name,"!",1)) + tx->flags |= FLAG_FAR_SKY_STOPPED; // for non-moving stars + if (!Q_strncmp(mt->name,".",1)) + tx->flags |= FLAG_SKY_SLOWER; // sky moves at 1/2 speed + else if (!Q_strncmp(mt->name,":",1)) + tx->flags |= FLAG_SKY_FASTER; // sky moves at 2x speed + if (!Q_strncmp(mt->name,"%",1)) + tx->flags |= FLAG_SKY_TRANS; // near sky is semi-transparent + + // Neal White III - 12-30-1999 - END + + R_InitSky (tx); + } else { texture_mode = GL_LINEAR_MIPMAP_NEAREST; //_LINEAR; + + // remove glowing fullbright colors from base texture (make black) + if (hasfullbrights) + { + // SAVE THIS - for debugging + //qboolean bColorUsed[256]; + //Con_Printf ("*** Fullbright Texture: \"%s\", %dx%d, %d pixels\n", mt->name, mt->width, mt->height, pixels); + //for (j=0 ; j<256 ; j++) + // bColorUsed[j] = false; + + ptexel = (byte *)(tx+1); + + for (j=0 ; j= 256-32) // 32 fullbright colors + { + ptexel[j] = 0; // make fullbrights black + } + } + //Con_Printf ("*** Normal colors: "); + //for (j=0 ; j<256-32 ; j++) + //{ + // if (bColorUsed[j]) + // Con_Printf ("%d ", j); + //} + //Con_Printf ("\n"); + //Con_Printf ("*** Fullbrights: "); + //for (j=256-32 ; j<256 ; j++) + //{ + // if (bColorUsed[j]) + // Con_Printf ("%d ", j); + //} + //Con_Printf ("\n"); + } + //else + //{ + // Con_Printf ("*** Normal Texture: \"%s\", %d*%d\n", mt->name, mt->width, mt->height); + //} + tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(tx+1), true, false); + + // create glowmap texture (all black except for glowing fullbright colors) + if (hasfullbrights) + { +#ifdef _DEBUG + qboolean bGlowDoubleCheck = false; +#endif + char glowname[32]; + memcpy (glowname, mt->name, sizeof(mt->name)); + + glowname[16] = '\0'; + for (j=0 ; glowname[j] != '\0'; j++) + ; + glowname[j++] = '<'; + glowname[j++] = 'G'; + glowname[j++] = 'L'; + glowname[j++] = 'O'; + glowname[j++] = 'W'; + glowname[j++] = '>'; + glowname[j++] = '\0'; + + ptexel = (byte *)(tx+1) + pixels; + + for (j=0 ; jgl_glowtexnum = GL_LoadTexture (glowname, tx->width, tx->height, ptexel, true, false); + tx->flags |= FLAG_HAS_GLOWMAP; + +#ifdef _DEBUG + if (! bGlowDoubleCheck) + Con_Printf ("INTERNAL ERROR: Mod_LoadTextures - FullBright texture \"%s\" has no FullBright colors!\n", glowname); +#endif + } + + // Neal White III - 12-28-1999 - END + // texture_mode = GL_LINEAR; } } diff --git a/qw_client/gl_model.h b/qw_client/gl_model.h index 65583e3..79e7b42 100644 --- a/qw_client/gl_model.h +++ b/qw_client/gl_model.h @@ -76,6 +76,15 @@ typedef struct mplane_s byte pad[2]; } mplane_t; +// Neal White III - 12-28-1999 - new texture flags +#define FLAG_FAR_SKY_STOPPED 0x0001 // for non-moving stars +#define FLAG_SKY_SLOWER 0x0002 // sky moves at 1/2 speed +#define FLAG_SKY_FASTER 0x0004 // sky moves at 2x speed +#define FLAG_SKY_TRANS 0x0008 // near sky is semi-transparent +#define FLAG_HAS_GLOWMAP 0x0010 // used for fullbright bugfix +// Neal White III - 12-28-1999 - END + + typedef struct texture_s { char name[16]; @@ -87,6 +96,12 @@ typedef struct texture_s struct texture_s *anim_next; // in the animation sequence struct texture_s *alternate_anims; // bmodels in frmae 1 use these unsigned offsets[MIPLEVELS]; // four mip maps stored + + // Neal White III - 12-28-1999 - OpenGL fullbright bugfix + int gl_glowtexnum; + unsigned flags; // FLAG_HAS_GLOWMAP + unsigned glowoffsets[MIPLEVELS]; // four mip maps stored + // Neal White III - 12-28-1999 - END } texture_t; diff --git a/uquake/gl_model.c b/uquake/gl_model.c index 789118b..6cdb4a1 100644 --- a/uquake/gl_model.c +++ b/uquake/gl_model.c @@ -345,6 +345,30 @@ void Mod_LoadTextures (lump_t *l) texture_t *altanims[10]; dmiptexlump_t *m; + // Neal White III - 12-28-1999 - OpenGL fullbright bugfix + // nwhite@softblox.com + // http://home.telefragged.com/wally/ + // + // Problem: + // + // There was a problem in the original glquake with fullbright texels. + // In the software renderer, fullbrights glow brightly in the dark. + // Essentially, the fullbrights were ignored. I've fixed it by + // adding another rendering pass and creating a new glowmap texture. + // + // Fix: + // + // When a texture with fullbright (FB) texels is loaded, a copy is made, + // then the FB pixels are cleared to black in the original texture. In + // the copy, all normal colors are cleared and only the FBs remain. When + // it comes time to render the polygons, I do an additional pass and ADD + // the glowmap on top of the current polygon. + + byte *ptexel; + qboolean hasfullbrights; + qboolean noglow = COM_CheckParm("-noglow"); + // Neal White III - 12-28-1999 - END + if (!l->filelen) { loadmodel->textures = NULL; @@ -371,6 +395,37 @@ void Mod_LoadTextures (lump_t *l) if ( (mt->width & 15) || (mt->height & 15) ) Sys_Error ("Texture %s is not 16 aligned", mt->name); pixels = mt->width*mt->height/64*85; + + // Neal White III - 12-28-1999 - OpenGL fullbright bugfix + + hasfullbrights = false; + + if ((!Q_strncmp(mt->name,"sky",3)) || + (!Q_strncmp(mt->name,"*",1)) || // turbulent (liquid) + (noglow) || (! gl_mtexable)) + { + // sky has no lightmap, nor do liquids (so never needs a glowmap), + // -noglow command line parameter, or no multi-texture support + // + // hasfullbrights is already false + } + else // check this texture for fullbright texels + { + ptexel = (byte *)(mt+1); + + for (j=0 ; j= 256-32) // 32 fullbright colors + { + hasfullbrights = true; + break; + } + } + } + + if (hasfullbrights) + tx = Hunk_AllocName (sizeof(texture_t) +pixels*2, loadname ); + else tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname ); loadmodel->textures[i] = tx; @@ -378,17 +433,134 @@ void Mod_LoadTextures (lump_t *l) tx->width = mt->width; tx->height = mt->height; for (j=0 ; joffsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t); + if (hasfullbrights) + tx->glowoffsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t) + pixels; + else + tx->glowoffsets[j] = 0; + } // the pixels immediately follow the structures memcpy ( tx+1, mt+1, pixels); + if (hasfullbrights) + { + ptexel = (byte *)(tx+1); + memcpy ( ptexel+pixels, mt+1, pixels); + } + + tx->flags = 0; + if (!Q_strncmp(mt->name,"sky",3)) + { + // Neal White III - 12-30-1999 - new variable speed sky layers + + if (!Q_strncmp(mt->name,"!",1)) + tx->flags |= FLAG_FAR_SKY_STOPPED; // for non-moving stars + if (!Q_strncmp(mt->name,".",1)) + tx->flags |= FLAG_SKY_SLOWER; // sky moves at 1/2 speed + else if (!Q_strncmp(mt->name,":",1)) + tx->flags |= FLAG_SKY_FASTER; // sky moves at 2x speed + if (!Q_strncmp(mt->name,"%",1)) + tx->flags |= FLAG_SKY_TRANS; // near sky is semi-transparent + + // Neal White III - 12-30-1999 - END + R_InitSky (tx); + } else { texture_mode = GL_LINEAR_MIPMAP_NEAREST; //_LINEAR; + + // remove glowing fullbright colors from base texture (make black) + if (hasfullbrights) + { + // SAVE THIS - for debugging + //qboolean bColorUsed[256]; + //Con_Printf ("*** Fullbright Texture: \"%s\", %dx%d, %d pixels\n", mt->name, mt->width, mt->height, pixels); + //for (j=0 ; j<256 ; j++) + // bColorUsed[j] = false; + + ptexel = (byte *)(tx+1); + + for (j=0 ; j= 256-32) // 32 fullbright colors + { + ptexel[j] = 0; // make fullbrights black + } + } + //Con_Printf ("*** Normal colors: "); + //for (j=0 ; j<256-32 ; j++) + //{ + // if (bColorUsed[j]) + // Con_Printf ("%d ", j); + //} + //Con_Printf ("\n"); + //Con_Printf ("*** Fullbrights: "); + //for (j=256-32 ; j<256 ; j++) + //{ + // if (bColorUsed[j]) + // Con_Printf ("%d ", j); + //} + //Con_Printf ("\n"); + } + //else + //{ + // Con_Printf ("*** Normal Texture: \"%s\", %d*%d\n", mt->name, mt->width, mt->height); + //} + tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(tx+1), true, false); + // + // create glowmap texture (all black except for glowing fullbright colors) + if (hasfullbrights) + { +#ifdef _DEBUG + qboolean bGlowDoubleCheck = false; +#endif + char glowname[32]; + memcpy (glowname, mt->name, sizeof(mt->name)); + + glowname[16] = '\0'; + for (j=0 ; glowname[j] != '\0'; j++) + ; + glowname[j++] = '<'; + glowname[j++] = 'G'; + glowname[j++] = 'L'; + glowname[j++] = 'O'; + glowname[j++] = 'W'; + glowname[j++] = '>'; + glowname[j++] = '\0'; + + ptexel = (byte *)(tx+1) + pixels; + + for (j=0 ; jgl_glowtexnum = GL_LoadTexture (glowname, tx->width, tx->height, ptexel, true, false); + tx->flags |= FLAG_HAS_GLOWMAP; + +#ifdef _DEBUG + if (! bGlowDoubleCheck) + Con_Printf ("INTERNAL ERROR: Mod_LoadTextures - FullBright texture \"%s\" has no FullBright colors!\n", glowname); +#endif + } + + // Neal White III - 12-28-1999 - END + texture_mode = GL_LINEAR; } } diff --git a/uquake/gl_model.h b/uquake/gl_model.h index b203ed3..bdf09e5 100644 --- a/uquake/gl_model.h +++ b/uquake/gl_model.h @@ -73,6 +73,15 @@ typedef struct mplane_s byte pad[2]; } mplane_t; +// Neal White III - 12-28-1999 - new texture flags +#define FLAG_FAR_SKY_STOPPED 0x0001 // for non-moving stars +#define FLAG_SKY_SLOWER 0x0002 // sky moves at 1/2 speed +#define FLAG_SKY_FASTER 0x0004 // sky moves at 2x speed +#define FLAG_SKY_TRANS 0x0008 // near sky is semi-transparent +#define FLAG_HAS_GLOWMAP 0x0010 // used for fullbright bugfix +// Neal White III - 12-28-1999 - END + + typedef struct texture_s { char name[16]; @@ -84,6 +93,12 @@ typedef struct texture_s struct texture_s *anim_next; // in the animation sequence struct texture_s *alternate_anims; // bmodels in frmae 1 use these unsigned offsets[MIPLEVELS]; // four mip maps stored + // + // Neal White III - 12-28-1999 - OpenGL fullbright bugfix + int gl_glowtexnum; + unsigned flags; // FLAG_HAS_GLOWMAP + unsigned glowoffsets[MIPLEVELS]; // four mip maps stored + // Neal White III - 12-28-1999 - END } texture_t;