diff --git a/Quake/gl_model.c b/Quake/gl_model.c index e5e6f39f..30c69881 100644 --- a/Quake/gl_model.c +++ b/Quake/gl_model.c @@ -1311,7 +1311,14 @@ static void Mod_LoadFaces (lump_t *l, qboolean bsp2) } else if (out->texinfo->texture->name[0] == '*') // warp surface { - out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED); + out->flags |= SURF_DRAWTURB; + if (out->texinfo->flags & TEX_SPECIAL) + out->flags |= SURF_DRAWTILED; + else if (out->samples && !loadmodel->haslitwater) + { + Con_DPrintf ("Map has lit water\n"); + loadmodel->haslitwater = true; + } // detect special liquid types if (!strncmp (out->texinfo->texture->name, "*lava", 5)) @@ -1322,8 +1329,13 @@ static void Mod_LoadFaces (lump_t *l, qboolean bsp2) out->flags |= SURF_DRAWTELE; else out->flags |= SURF_DRAWWATER; - Mod_PolyForUnlitSurface (out); - GL_SubdivideSurface (out); + // polys are only created for unlit water here. + // lit water is handled in BuildSurfaceDisplayList + if (out->flags & SURF_DRAWTILED) + { + Mod_PolyForUnlitSurface (out); + GL_SubdivideSurface (out); + } } else if (out->texinfo->texture->name[0] == '{') // ericw -- fence textures { diff --git a/Quake/gl_model.h b/Quake/gl_model.h index 3d8b1f73..e632c87a 100644 --- a/Quake/gl_model.h +++ b/Quake/gl_model.h @@ -484,7 +484,7 @@ typedef struct qmodel_s qboolean viswarn; // for Mod_DecompressVis() int bspversion; - + qboolean haslitwater; // // alias model // diff --git a/Quake/gl_rmain.c b/Quake/gl_rmain.c index 332ab1ec..5cd38065 100644 --- a/Quake/gl_rmain.c +++ b/Quake/gl_rmain.c @@ -64,6 +64,7 @@ cvar_t r_fullbright = {"r_fullbright","0",CVAR_NONE}; cvar_t r_lightmap = {"r_lightmap","0",CVAR_NONE}; cvar_t r_shadows = {"r_shadows","0",CVAR_ARCHIVE}; cvar_t r_wateralpha = {"r_wateralpha","1",CVAR_ARCHIVE}; +cvar_t r_litwater = {"r_litwater","1",CVAR_NONE}; cvar_t r_dynamic = {"r_dynamic","1",CVAR_ARCHIVE}; cvar_t r_novis = {"r_novis","0",CVAR_ARCHIVE}; diff --git a/Quake/gl_rmisc.c b/Quake/gl_rmisc.c index dc3dff06..0c458e33 100644 --- a/Quake/gl_rmisc.c +++ b/Quake/gl_rmisc.c @@ -176,6 +176,7 @@ void R_Init (void) Cvar_RegisterVariable (&r_shadows); Cvar_RegisterVariable (&r_wateralpha); Cvar_SetCallback (&r_wateralpha, R_SetWateralpha_f); + Cvar_RegisterVariable (&r_litwater); Cvar_RegisterVariable (&r_dynamic); Cvar_RegisterVariable (&r_novis); Cvar_RegisterVariable (&r_speeds); diff --git a/Quake/glquake.h b/Quake/glquake.h index f9da58da..86ba117a 100644 --- a/Quake/glquake.h +++ b/Quake/glquake.h @@ -139,6 +139,7 @@ extern cvar_t r_wateralpha; extern cvar_t r_lavaalpha; extern cvar_t r_telealpha; extern cvar_t r_slimealpha; +extern cvar_t r_litwater; extern cvar_t r_dynamic; extern cvar_t r_novis; extern cvar_t r_scale; diff --git a/Quake/r_brush.c b/Quake/r_brush.c index 75d5e28a..0ee701b9 100644 --- a/Quake/r_brush.c +++ b/Quake/r_brush.c @@ -784,6 +784,12 @@ void GL_CreateSurfaceLightmap (msurface_t *surf) int smax, tmax; byte *base; + if (surf->flags & SURF_DRAWTILED) + { + surf->lightmaptexturenum = -1; + return; + } + smax = (surf->extents[0]>>4)+1; tmax = (surf->extents[1]>>4)+1; @@ -803,7 +809,7 @@ void BuildSurfaceDisplayList (msurface_t *fa) int i, lindex, lnumverts; medge_t *pedges, *r_pedge; float *vec; - float s, t; + float s, t, s0, t0, sdiv, tdiv; glpoly_t *poly; // reconstruct the polygon @@ -818,6 +824,20 @@ void BuildSurfaceDisplayList (msurface_t *fa) fa->polys = poly; poly->numverts = lnumverts; + if (fa->flags & SURF_DRAWTURB) + { + // match Mod_PolyForUnlitSurface + s0 = t0 = 0.f; + sdiv = tdiv = 128.f; + } + else + { + s0 = fa->texinfo->vecs[0][3]; + t0 = fa->texinfo->vecs[1][3]; + sdiv = fa->texinfo->texture->width; + tdiv = fa->texinfo->texture->height; + } + for (i=0 ; isurfedges[fa->firstedge + i]; @@ -832,11 +852,11 @@ void BuildSurfaceDisplayList (msurface_t *fa) 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; + s = DotProduct (vec, fa->texinfo->vecs[0]) + s0; + s /= sdiv; - t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; - t /= fa->texinfo->texture->height; + t = DotProduct (vec, fa->texinfo->vecs[1]) + t0; + t /= tdiv; VectorCopy (vec, poly->verts[i]); poly->verts[i][3] = s; @@ -871,6 +891,10 @@ void BuildSurfaceDisplayList (msurface_t *fa) //johnfitz -- removed gl_keeptjunctions code poly->numverts = lnumverts; + + // support r_oldwater 1 on lit water + if (fa->flags & SURF_DRAWTURB) + GL_SubdivideSurface (fa); } /* diff --git a/Quake/r_world.c b/Quake/r_world.c index 5a2a1aae..1953d6eb 100644 --- a/Quake/r_world.c +++ b/Quake/r_world.c @@ -412,7 +412,7 @@ void R_DrawTextureChains_Multitexture (qmodel_t *model, entity_t *ent, texchain_ { t = model->textures[i]; - if (!t || !t->texturechains[chain] || t->texturechains[chain]->flags & (SURF_DRAWTILED | SURF_NOTEXTURE)) + if (!t || !t->texturechains[chain] || t->texturechains[chain]->flags & (SURF_DRAWTURB | SURF_DRAWTILED | SURF_NOTEXTURE)) continue; bound = false; @@ -541,6 +541,24 @@ float GL_WaterAlphaForEntitySurface (entity_t *ent, msurface_t *s) return entalpha; } +static GLuint r_world_program; +extern GLuint gl_bmodel_vbo; + +// uniforms used in vert shader + +// uniforms used in frag shader +static GLuint texLoc; +static GLuint LMTexLoc; +static GLuint fullbrightTexLoc; +static GLuint useFullbrightTexLoc; +static GLuint useOverbrightLoc; +static GLuint useAlphaTestLoc; +static GLuint alphaLoc; + +#define vertAttrIndex 0 +#define texCoordsAttrIndex 1 +#define LMCoordsAttrIndex 2 + /* ================ R_DrawTextureChains_Water -- johnfitz @@ -554,6 +572,7 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain glpoly_t *p; qboolean bound; float entalpha; + int lastlightmap; if (r_drawflat_cheatsafe || r_lightmap_cheatsafe) // ericw -- !r_drawworld_cheatsafe check moved to R_DrawWorld_Water () return; @@ -585,8 +604,90 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain R_EndTransparentDrawing (entalpha); } } + else if (cl.worldmodel->haslitwater && r_litwater.value && r_world_program != 0) + { + GL_UseProgramFunc (r_world_program); + + // Bind the buffers + GL_BindBuffer (GL_ARRAY_BUFFER, gl_bmodel_vbo); + GL_BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0); + + GL_EnableVertexAttribArrayFunc (vertAttrIndex); + GL_EnableVertexAttribArrayFunc (texCoordsAttrIndex); + GL_EnableVertexAttribArrayFunc (LMCoordsAttrIndex); + + GL_VertexAttribPointerFunc (vertAttrIndex, 3, GL_FLOAT, GL_FALSE, VERTEXSIZE * sizeof(float), ((float *)0)); + GL_VertexAttribPointerFunc (texCoordsAttrIndex, 2, GL_FLOAT, GL_FALSE, VERTEXSIZE * sizeof(float), ((float *)0) + 3); + GL_VertexAttribPointerFunc (LMCoordsAttrIndex, 2, GL_FLOAT, GL_FALSE, VERTEXSIZE * sizeof(float), ((float *)0) + 5); + + // Set uniforms + GL_Uniform1iFunc (texLoc, 0); + GL_Uniform1iFunc (LMTexLoc, 1); + GL_Uniform1iFunc (fullbrightTexLoc, 2); + GL_Uniform1iFunc (useFullbrightTexLoc, 0); + GL_Uniform1iFunc (useOverbrightLoc, (int)gl_overbright.value); + GL_Uniform1iFunc (useAlphaTestLoc, 0); + + for (i=0 ; inumtextures ; i++) + { + t = model->textures[i]; + + if (!t || !t->texturechains[chain] || !(t->texturechains[chain]->flags & SURF_DRAWTURB)) + continue; + + bound = false; + entalpha = 1.0f; + lastlightmap = 0; + for (s = t->texturechains[chain]; s; s = s->texturechain) + { + if (!bound) //only bind once we are sure we need this texture + { + entalpha = GL_WaterAlphaForEntitySurface (ent, s); + if (entalpha < 1.0f) + { + GL_Uniform1fFunc (alphaLoc, entalpha); + R_BeginTransparentDrawing (entalpha); + } + + GL_SelectTexture (GL_TEXTURE0); + 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; + lastlightmap = s->lightmaptexturenum; + } + + if (s->lightmaptexturenum != lastlightmap) + R_FlushBatch (); + + GL_SelectTexture (GL_TEXTURE1); + GL_Bind (lightmaps[s->lightmaptexturenum].texture); + lastlightmap = s->lightmaptexturenum; + R_BatchSurface (s); + + rs_brushpasses++; + } + R_FlushBatch (); + R_EndTransparentDrawing (entalpha); + } + + // clean up + GL_DisableVertexAttribArrayFunc (vertAttrIndex); + GL_DisableVertexAttribArrayFunc (texCoordsAttrIndex); + GL_DisableVertexAttribArrayFunc (LMCoordsAttrIndex); + GL_UseProgramFunc (0); + GL_SelectTexture (GL_TEXTURE0); + } else { + // Unlit water for (i=0 ; inumtextures ; i++) { t = model->textures[i]; @@ -680,23 +781,6 @@ void R_DrawLightmapChains (void) } } -static GLuint r_world_program; - -// uniforms used in vert shader - -// uniforms used in frag shader -static GLuint texLoc; -static GLuint LMTexLoc; -static GLuint fullbrightTexLoc; -static GLuint useFullbrightTexLoc; -static GLuint useOverbrightLoc; -static GLuint useAlphaTestLoc; -static GLuint alphaLoc; - -#define vertAttrIndex 0 -#define texCoordsAttrIndex 1 -#define LMCoordsAttrIndex 2 - /* ============= GLWorld_CreateShaders @@ -781,8 +865,6 @@ void GLWorld_CreateShaders (void) } } -extern GLuint gl_bmodel_vbo; - /* ================ R_DrawTextureChains_GLSL -- ericw @@ -837,7 +919,7 @@ void R_DrawTextureChains_GLSL (qmodel_t *model, entity_t *ent, texchain_t chain) { t = model->textures[i]; - if (!t || !t->texturechains[chain] || t->texturechains[chain]->flags & (SURF_DRAWTILED | SURF_NOTEXTURE)) + if (!t || !t->texturechains[chain] || t->texturechains[chain]->flags & (SURF_DRAWTURB | SURF_DRAWTILED | SURF_NOTEXTURE)) continue; // Enable/disable TMU 2 (fullbrights) @@ -861,7 +943,6 @@ void R_DrawTextureChains_GLSL (qmodel_t *model, entity_t *ent, texchain_t chain) { GL_SelectTexture (GL_TEXTURE0); GL_Bind ((R_TextureAnimation(t, ent != NULL ? ent->frame : 0))->gltexture); - if (t->texturechains[chain]->flags & SURF_DRAWFENCE) GL_Uniform1iFunc (useAlphaTestLoc, 1); // Flip alpha test back on