Merge brush model with world model rendering.

With this, non-mtex global fog now works properly :).
This commit is contained in:
Bill Currie 2011-12-17 21:45:52 +09:00
parent a8e354536a
commit 52d9269867
6 changed files with 103 additions and 223 deletions

View file

@ -47,7 +47,6 @@ void gl_lightmap_init (void);
void GL_BuildLightmaps (struct model_s **models, int num_models); void GL_BuildLightmaps (struct model_s **models, int num_models);
void R_BlendLightmaps (void); void R_BlendLightmaps (void);
void R_CalcLightmaps (void); void R_CalcLightmaps (void);
void R_CalcAndBlendLightmaps (void); // FIXME: temporary hack
extern void (*R_BuildLightMap) (msurface_t *surf); extern void (*R_BuildLightMap) (msurface_t *surf);
#endif // __QF_GL_lightmap_h #endif // __QF_GL_lightmap_h

View file

@ -132,8 +132,6 @@ typedef struct {
typedef struct glpoly_s { typedef struct glpoly_s {
struct glpoly_s *next; struct glpoly_s *next;
struct glpoly_s *chain;
struct glpoly_s *fb_chain;
int numverts; int numverts;
int flags; // for SURF_UNDERWATER int flags; // for SURF_UNDERWATER
float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2) float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
@ -157,6 +155,7 @@ typedef struct msurface_s {
glpoly_t *polys; // multiple if warped glpoly_t *polys; // multiple if warped
instsurf_t *instsurf; ///< null if not part of world model/sub-model instsurf_t *instsurf; ///< null if not part of world model/sub-model
instsurf_t *tinst; ///< for instance models
mtexinfo_t *texinfo; mtexinfo_t *texinfo;

View file

@ -74,6 +74,7 @@ typedef struct entity_s {
vec3_t old_origin; vec3_t old_origin;
vec3_t angles; vec3_t angles;
vec_t transform[4 * 4]; vec_t transform[4 * 4];
vec_t full_transform[4 * 4];
struct model_s *model; // NULL = no model struct model_s *model; // NULL = no model
int frame; int frame;
byte *colormap; byte *colormap;

View file

@ -72,7 +72,7 @@ unsigned int blocklights[34 * 34 * 3]; //FIXME make dynamic
int allocated[MAX_LIGHTMAPS][BLOCK_WIDTH]; int allocated[MAX_LIGHTMAPS][BLOCK_WIDTH];
qboolean lightmap_modified[MAX_GLTEXTURES]; qboolean lightmap_modified[MAX_GLTEXTURES];
glpoly_t *lightmap_polys[MAX_LIGHTMAPS]; instsurf_t *lightmap_polys[MAX_LIGHTMAPS];
glRect_t lightmap_rectchange[MAX_LIGHTMAPS]; glRect_t lightmap_rectchange[MAX_LIGHTMAPS];
static int lmshift = 7; static int lmshift = 7;
@ -482,11 +482,9 @@ void
R_CalcLightmaps (void) R_CalcLightmaps (void)
{ {
int i; int i;
glpoly_t *p;
for (i = 0; i < MAX_LIGHTMAPS; i++) { for (i = 0; i < MAX_LIGHTMAPS; i++) {
p = lightmap_polys[i]; if (!lightmap_polys[i])
if (!p)
continue; continue;
if (lightmap_modified[i]) { if (lightmap_modified[i]) {
qfglBindTexture (GL_TEXTURE_2D, lightmap_textures + i); qfglBindTexture (GL_TEXTURE_2D, lightmap_textures + i);
@ -501,24 +499,30 @@ R_BlendLightmaps (void)
{ {
float *v; float *v;
int i, j; int i, j;
instsurf_t *sc;
glpoly_t *p; glpoly_t *p;
qfglDepthMask (GL_FALSE); // don't bother writing Z qfglDepthMask (GL_FALSE); // don't bother writing Z
qfglBlendFunc (lm_src_blend, lm_dest_blend); qfglBlendFunc (lm_src_blend, lm_dest_blend);
for (i = 0; i < MAX_LIGHTMAPS; i++) { for (i = 0; i < MAX_LIGHTMAPS; i++) {
p = lightmap_polys[i]; for (sc = lightmap_polys[i]; sc; sc = sc->lm_chain) {
if (!p) qfglBindTexture (GL_TEXTURE_2D, lightmap_textures + i);
continue; if (sc->transform) {
qfglBindTexture (GL_TEXTURE_2D, lightmap_textures + i); qfglPushMatrix ();
for (; p; p = p->chain) { qfglLoadMatrixf (sc->transform);
qfglBegin (GL_POLYGON);
v = p->verts[0];
for (j = 0; j < p->numverts; j++, v += VERTEXSIZE) {
qfglTexCoord2fv (&v[5]);
qfglVertex3fv (v);
} }
qfglEnd (); for (p = sc->surface->polys; p; p = p->next) {
qfglBegin (GL_POLYGON);
v = p->verts[0];
for (j = 0; j < p->numverts; j++, v += VERTEXSIZE) {
qfglTexCoord2fv (&v[5]);
qfglVertex3fv (v);
}
qfglEnd ();
}
if (sc->transform)
qfglPopMatrix ();
} }
} }
@ -619,41 +623,6 @@ gl_overbright_f (cvar_t *var)
} }
} }
void
R_CalcAndBlendLightmaps (void)
{
float *v;
int i, j;
glpoly_t *p;
qfglDepthMask (GL_FALSE); // don't bother writing Z
qfglBlendFunc (lm_src_blend, lm_dest_blend);
for (i = 0; i < MAX_LIGHTMAPS; i++) {
p = lightmap_polys[i];
if (!p)
continue;
qfglBindTexture (GL_TEXTURE_2D, lightmap_textures + i);
if (lightmap_modified[i]) {
GL_UploadLightmap (i);
lightmap_modified[i] = false;
}
for (; p; p = p->chain) {
qfglBegin (GL_POLYGON);
v = p->verts[0];
for (j = 0; j < p->numverts; j++, v += VERTEXSIZE) {
qfglTexCoord2fv (&v[5]);
qfglVertex3fv (v);
}
qfglEnd ();
}
}
// Return to normal blending --KB
qfglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
qfglDepthMask (GL_TRUE); // back to normal Z buffering
}
// LIGHTMAP ALLOCATION ======================================================== // LIGHTMAP ALLOCATION ========================================================
// returns a texture number and the position inside it // returns a texture number and the position inside it

View file

@ -220,13 +220,6 @@ R_DrawEntitiesOnList (void)
return; return;
// LordHavoc: split into 3 loops to simplify state changes // LordHavoc: split into 3 loops to simplify state changes
for (ent = r_ent_queue; ent; ent = ent->next) {
if (ent->model->type != mod_brush)
continue;
currententity = ent;
R_DrawBrushModel (currententity);
}
if (gl_mtex_active_tmus >= 2) { if (gl_mtex_active_tmus >= 2) {
qglActiveTexture (gl_mtex_enum + 1); qglActiveTexture (gl_mtex_enum + 1);

View file

@ -60,35 +60,33 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$";
int skytexturenum; int skytexturenum;
glpoly_t *fullbright_polys[MAX_GLTEXTURES];
instsurf_t *waterchain = NULL; instsurf_t *waterchain = NULL;
instsurf_t **waterchain_tail = &waterchain; instsurf_t **waterchain_tail = &waterchain;
instsurf_t *sky_chain; instsurf_t *sky_chain;
instsurf_t **sky_chain_tail; instsurf_t **sky_chain_tail;
#define CHAIN_SURF_F2B(surf,chain) \ #define CHAIN_SURF_F2B(surf,chain) \
do { \ do { \
instsurf_t *inst = (surf)->instsurf; \ instsurf_t *inst = (surf)->instsurf; \
if (!inst) inst = get_instsurf (); \ if (!inst) (surf)->tinst = inst = get_instsurf (); \
inst->surface = (surf); \ inst->surface = (surf); \
*(chain##_tail) = inst; \ *(chain##_tail) = inst; \
(chain##_tail) = &inst->tex_chain; \ (chain##_tail) = &inst->tex_chain; \
*(chain##_tail) = 0; \ *(chain##_tail) = 0; \
} while (0) } while (0)
#define CHAIN_SURF_B2F(surf,chain) \ #define CHAIN_SURF_B2F(surf,chain) \
do { \ do { \
instsurf_t *inst = (surf)->instsurf; \ instsurf_t *inst = (surf)->instsurf; \
if (!inst) inst = get_instsurf (); \ if (!inst) (surf)->tinst = inst = get_instsurf (); \
inst->surface = (surf); \ inst->surface = (surf); \
inst->tex_chain = (chain); \ inst->tex_chain = (chain); \
(chain) = inst; \ (chain) = inst; \
} while (0) } while (0)
extern int lightmap_textures; extern int lightmap_textures;
extern qboolean lightmap_modified[MAX_LIGHTMAPS]; extern qboolean lightmap_modified[MAX_LIGHTMAPS];
extern glpoly_t *lightmap_polys[MAX_LIGHTMAPS]; extern instsurf_t *lightmap_polys[MAX_LIGHTMAPS];
extern glRect_t lightmap_rectchange[MAX_LIGHTMAPS]; extern glRect_t lightmap_rectchange[MAX_LIGHTMAPS];
static texture_t **r_texture_chains; static texture_t **r_texture_chains;
@ -209,19 +207,34 @@ R_RenderFullbrights (void)
float *v; float *v;
int i, j; int i, j;
glpoly_t *p; glpoly_t *p;
instsurf_t *sc;
texture_t *tex;
for (i = 1; i < MAX_GLTEXTURES; i++) { for (i = 0; i < r_num_texture_chains; i++) {
if (!fullbright_polys[i]) if (!(tex = r_texture_chains[i]) || !tex->gl_fb_texturenum)
continue; continue;
qfglBindTexture (GL_TEXTURE_2D, i); qfglBindTexture (GL_TEXTURE_2D, tex->gl_fb_texturenum);
for (p = fullbright_polys[i]; p; p = p->fb_chain) { for (sc = tex->tex_chain; sc; sc = sc->tex_chain) {
qfglBegin (GL_POLYGON); if (sc->transform) {
for (j = 0, v = p->verts[0]; j < p->numverts; j++, v += VERTEXSIZE) qfglPushMatrix ();
{ qfglLoadMatrixf (sc->transform);
qfglTexCoord2fv (&v[3]);
qfglVertex3fv (v);
} }
qfglEnd (); if (sc->color)
qfglColor4fv (sc->color);
for (p = sc->surface->polys; p; p = p->next) {
qfglBegin (GL_POLYGON);
for (j = 0, v = p->verts[0]; j < p->numverts;
j++, v += VERTEXSIZE)
{
qfglTexCoord2fv (&v[3]);
qfglVertex3fv (v);
}
qfglEnd ();
}
if (sc->transform)
qfglPopMatrix ();
if (sc->color)
qfglColor3ubv (color_white);
} }
} }
} }
@ -291,11 +304,14 @@ R_AddToLightmapChain (msurface_t *fa)
{ {
int maps, smax, tmax; int maps, smax, tmax;
glRect_t *theRect; glRect_t *theRect;
instsurf_t *sc;
// add the poly to the proper lightmap chain // add the poly to the proper lightmap chain
if (!(sc = fa->instsurf))
sc = fa->tinst;
fa->polys->chain = lightmap_polys[fa->lightmaptexturenum]; sc->lm_chain = lightmap_polys[fa->lightmaptexturenum];
lightmap_polys[fa->lightmaptexturenum] = fa->polys; lightmap_polys[fa->lightmaptexturenum] = sc;
// check for lightmap modification // check for lightmap modification
for (maps = 0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++) for (maps = 0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++)
@ -388,8 +404,8 @@ DrawTextureChains (int disable_blend, int do_bind)
qglActiveTexture (gl_mtex_enum + 0); qglActiveTexture (gl_mtex_enum + 0);
qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
for (i = 0; i < r_worldentity.model->numtextures; i++) { for (i = 0; i < r_num_texture_chains; i++) {
tex = r_worldentity.model->textures[i]; tex = r_texture_chains[i];
if (!tex) if (!tex)
continue; continue;
qfglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum); qfglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum);
@ -410,12 +426,13 @@ DrawTextureChains (int disable_blend, int do_bind)
qfglColor4fv (s->color); qfglColor4fv (s->color);
qfglBindTexture (GL_TEXTURE_2D, lightmap_textures + qfglBindTexture (GL_TEXTURE_2D, lightmap_textures +
fa->lightmaptexturenum); fa->lightmaptexturenum);
R_RenderBrushPoly_3 (fa);
if (s->transform) if (s->transform)
qfglPopMatrix (); qfglPopMatrix ();
if (s->color && do_bind) if (s->color && do_bind)
qfglColor3ubv (color_white); qfglColor3ubv (color_white);
R_RenderBrushPoly_3 (fa);
} }
qglActiveTexture (gl_mtex_enum + 2); qglActiveTexture (gl_mtex_enum + 2);
@ -456,8 +473,8 @@ DrawTextureChains (int disable_blend, int do_bind)
} else { } else {
if (disable_blend) if (disable_blend)
qfglDisable (GL_BLEND); qfglDisable (GL_BLEND);
for (i = 0; i < r_worldentity.model->numtextures; i++) { for (i = 0; i < r_num_texture_chains; i++) {
tex = r_worldentity.model->textures[i]; tex = r_texture_chains[i];
if (!tex) if (!tex)
continue; continue;
if (do_bind) if (do_bind)
@ -498,11 +515,15 @@ clear_texture_chains (void)
tex->tex_chain = NULL; tex->tex_chain = NULL;
tex->tex_chain_tail = &tex->tex_chain; tex->tex_chain_tail = &tex->tex_chain;
release_instsurfs (); release_instsurfs ();
memset (lightmap_polys, 0, sizeof (lightmap_polys));
} }
static inline void static inline void
chain_surface (msurface_t *surf) chain_surface (msurface_t *surf, vec_t *transform, float *color)
{ {
instsurf_t *sc;
if (surf->flags & SURF_DRAWTURB) { if (surf->flags & SURF_DRAWTURB) {
CHAIN_SURF_B2F (surf, waterchain); CHAIN_SURF_B2F (surf, waterchain);
} else if (surf->flags & SURF_DRAWSKY) { } else if (surf->flags & SURF_DRAWSKY) {
@ -510,27 +531,24 @@ chain_surface (msurface_t *surf)
} else { } else {
texture_t *tex; texture_t *tex;
R_AddToLightmapChain (surf);
if (!surf->texinfo->texture->anim_total) if (!surf->texinfo->texture->anim_total)
tex = surf->texinfo->texture; tex = surf->texinfo->texture;
else else
tex = R_TextureAnimation (surf); tex = R_TextureAnimation (surf);
if (gl_fb_bmodels->int_val && tex->gl_fb_texturenum
&& !gl_mtex_fullbright) {
surf->polys->fb_chain =
fullbright_polys[tex->gl_fb_texturenum];
fullbright_polys[tex->gl_fb_texturenum] = surf->polys;
}
CHAIN_SURF_F2B (surf, tex->tex_chain); CHAIN_SURF_F2B (surf, tex->tex_chain);
R_AddToLightmapChain (surf);
} }
if (!(sc = surf->instsurf))
sc = surf->tinst;
sc->transform = transform;
sc->color = color;
} }
void void
R_DrawBrushModel (entity_t *e) R_DrawBrushModel (entity_t *e)
{ {
float dot, radius; float dot, radius;
float color[4], watercolor[4];
int i; int i;
unsigned int k; unsigned int k;
model_t *model; model_t *model;
@ -564,16 +582,6 @@ R_DrawBrushModel (entity_t *e)
return; return;
} }
VectorCopy (e->colormod, color);
VectorCopy (color, watercolor);
color[3] = e->colormod[3]; // entity alpha
qfglColor4fv (color);
if (color[3] < 1.0)
qfglDepthMask (GL_FALSE);
memset (lightmap_polys, 0, sizeof (lightmap_polys));
memset (fullbright_polys, 0, sizeof (fullbright_polys));
VectorSubtract (r_refdef.vieworg, e->origin, modelorg); VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
if (rotated) { if (rotated) {
vec3_t temp; vec3_t temp;
@ -602,16 +610,8 @@ R_DrawBrushModel (entity_t *e)
qfglPushMatrix (); qfglPushMatrix ();
R_RotateForEntity (e); R_RotateForEntity (e);
qfglGetFloatv (GL_MODELVIEW_MATRIX, e->full_transform);
// Build lightmap chains qfglPopMatrix ();
for (i = 0; i < model->nummodelsurfaces; i++, psurf++) {
if (psurf->flags & (SURF_DRAWTURB | SURF_DRAWSKY))
continue;
R_AddToLightmapChain (psurf);
}
if (gl_mtex_active_tmus >= 2)
R_CalcLightmaps ();
psurf = &model->surfaces[model->firstmodelsurface]; psurf = &model->surfaces[model->firstmodelsurface];
@ -625,97 +625,9 @@ R_DrawBrushModel (entity_t *e)
// draw the polygon // draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) {
if (psurf->flags & SURF_DRAWTURB) { chain_surface (psurf, e->full_transform, e->colormod);
qfglBindTexture (GL_TEXTURE_2D,
psurf->texinfo->texture->gl_texturenum);
if (cl_wateralpha < 1.0) {
if (color[3] >= 1.0)
qfglDepthMask (GL_FALSE);
watercolor[3] = color[3] * cl_wateralpha;
qfglColor4fv (watercolor);
EmitWaterPolys (psurf);
qfglColor4fv (color);
if (color[3] >= 1.0)
qfglDepthMask (GL_TRUE);
} else {
EmitWaterPolys (psurf);
}
} else if (psurf->flags & SURF_DRAWSKY) {
// QSG FIXME: add modelalpha support for sky brushes
CHAIN_SURF_F2B (psurf, sky_chain);
} else {
texture_t *tex;
if (!psurf->texinfo->texture->anim_total)
tex = psurf->texinfo->texture;
else
tex = R_TextureAnimation (psurf);
if (gl_mtex_active_tmus >= 2) {
if (tex->gl_fb_texturenum && gl_mtex_fullbright) {
qglActiveTexture (gl_mtex_enum + 2);
qfglEnable (GL_TEXTURE_2D);
qfglBindTexture (GL_TEXTURE_2D, tex->gl_fb_texturenum);
qglActiveTexture (gl_mtex_enum + 1);
qfglEnable (GL_TEXTURE_2D);
qfglBindTexture (GL_TEXTURE_2D, lightmap_textures +
psurf->lightmaptexturenum);
qglActiveTexture (gl_mtex_enum + 0);
qfglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum);
R_RenderBrushPoly_3 (psurf);
qglActiveTexture (gl_mtex_enum + 2);
qfglDisable (GL_TEXTURE_2D);
qglActiveTexture (gl_mtex_enum + 1);
qfglDisable (GL_TEXTURE_2D);
qglActiveTexture (gl_mtex_enum + 0);
} else {
qglActiveTexture (gl_mtex_enum + 1);
qfglEnable (GL_TEXTURE_2D);
qfglBindTexture (GL_TEXTURE_2D, lightmap_textures +
psurf->lightmaptexturenum);
qglActiveTexture (gl_mtex_enum + 0);
qfglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum);
R_RenderBrushPoly_2 (psurf);
qglActiveTexture (gl_mtex_enum + 1);
qfglDisable (GL_TEXTURE_2D);
qglActiveTexture (gl_mtex_enum + 0);
}
} else {
qfglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum);
R_RenderBrushPoly_1 (psurf);
if (tex->gl_fb_texturenum && gl_mtex_fullbright) {
psurf->polys->fb_chain =
fullbright_polys[tex->gl_fb_texturenum];
fullbright_polys[tex->gl_fb_texturenum] = psurf->polys;
}
}
}
} }
} }
if (gl_mtex_active_tmus >= 2) {
qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
} else {
R_CalcAndBlendLightmaps ();
}
if (gl_fb_bmodels->int_val && !gl_mtex_fullbright)
R_RenderFullbrights ();
qfglPopMatrix ();
if (color[3] < 1.0)
qfglDepthMask (GL_TRUE);
qfglColor3ubv (color_white);
} }
// WORLD MODEL ================================================================ // WORLD MODEL ================================================================
@ -758,7 +670,7 @@ visit_node (mnode_t *node, int side)
if (side ^ (surf->flags & SURF_PLANEBACK)) if (side ^ (surf->flags & SURF_PLANEBACK))
continue; // wrong side continue; // wrong side
chain_surface (surf); chain_surface (surf, 0, 0);
} }
} }
} }
@ -826,17 +738,14 @@ R_RecursiveWorldNode (mnode_t *node)
void void
R_DrawWorld (void) R_DrawWorld (void)
{ {
entity_t ent; entity_t worldent;
memset (&ent, 0, sizeof (ent)); memset (&worldent, 0, sizeof (worldent));
ent.model = r_worldentity.model; worldent.model = r_worldentity.model;
VectorCopy (r_refdef.vieworg, modelorg); VectorCopy (r_refdef.vieworg, modelorg);
currententity = &ent; currententity = &worldent;
memset (lightmap_polys, 0, sizeof (lightmap_polys));
memset (fullbright_polys, 0, sizeof (fullbright_polys));
sky_chain = 0; sky_chain = 0;
sky_chain_tail = &sky_chain; sky_chain_tail = &sky_chain;
@ -845,6 +754,16 @@ R_DrawWorld (void)
} }
R_RecursiveWorldNode (r_worldentity.model->nodes); R_RecursiveWorldNode (r_worldentity.model->nodes);
if (r_drawentities->int_val) {
entity_t *ent;
for (ent = r_ent_queue; ent; ent = ent->next) {
if (ent->model->type != mod_brush)
continue;
currententity = ent;
R_DrawBrushModel (currententity);
}
}
R_CalcLightmaps (); R_CalcLightmaps ();