From 45bff1c2dd893d329c86aa043661187b86da6609 Mon Sep 17 00:00:00 2001 From: havoc Date: Sat, 24 Aug 2002 07:14:15 +0000 Subject: [PATCH] detail texturing added (although with just one generated texture applied to everything) detail texturing makes use of up to 3 texture units if you have combine detail texturing added to effects options menu (r_detailtextures cvar) surfvertex_t now has another set of texcoords, for detail texturing Mod_BrushStartup and Mod_BrushShutdown functions added to alloc/free the detail texture r_multitexture cvar renamed to r_textureunits, so you can limit number of texture units enabled for testing, rather than just as a yes/no kind of option gl_combine is forced to 0 if r_textureunits is less than 2 (this is purely for consistency, not of any importance) split up the wall rendering into two kinds - vertex lit with optional transparency, and opaque lightmapped with no support for transparency R_Mesh_Draw_GetBuffer now takes a wantoverbrights parameter, if false it will not use the 4x overbright (even if combine is enabled), this is useful to improve the color precision of anything which does not need overbright fixed crosshair brightness (it was unintentionally adjusting the alpha using m.colorscale just like the RGB portion of the color) sprites only use overbright if they are lit (normal unlit sprites are rendered without overbright) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2282 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_particles.c | 2 +- gl_backend.c | 23 +- gl_backend.h | 2 +- gl_models.c | 2 +- gl_rmain.c | 8 +- gl_rsurf.c | 860 ++++++++++++++++++++----------------------------- menu.c | 19 +- model_brush.c | 71 +++- model_brush.h | 4 + model_shared.c | 5 + r_crosshairs.c | 4 +- r_explosion.c | 2 +- r_light.c | 2 +- r_sky.c | 16 +- r_sprites.c | 2 +- render.h | 5 +- 16 files changed, 483 insertions(+), 544 deletions(-) diff --git a/cl_particles.c b/cl_particles.c index 90d0de16..fd4bade2 100644 --- a/cl_particles.c +++ b/cl_particles.c @@ -1291,7 +1291,7 @@ void R_DrawParticles (void) m.numtriangles = 2; m.numverts = 4; m.tex[0] = R_GetTexture(particlefonttexture); - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { m.index[0] = 0; m.index[1] = 1; diff --git a/gl_backend.c b/gl_backend.c index 0cc530dc..e9723234 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -746,7 +746,7 @@ void GL_DrawRangeElements(int firstvert, int endvert, int indexcount, GLuint *in // GL 1.1 but not using vertex arrays - 3dfx glquake minigl driver // feed it manually qglBegin(GL_TRIANGLES); - if (r_multitexture.integer) + if (mesh_texture[1]) // if the mesh uses multiple textures { // the minigl doesn't have this (because it does not have ARB_multitexture) for (i = 0;i < indexcount;i++) @@ -1240,7 +1240,7 @@ void R_Mesh_Draw(const rmeshinfo_t *m) // allocates space in geometry buffers, and fills in pointers to the buffers in passsed struct // (this is used for very high speed rendering, no copying) -int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m) +int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m, int wantoverbright) { // these are static because gcc runs out of virtual registers otherwise int i, j, overbright; @@ -1343,7 +1343,7 @@ int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m) { if (m->tex[0]) { - overbright = gl_combine.integer; + overbright = wantoverbright && gl_combine.integer; if (overbright) scaler *= 0.25f; } @@ -1456,15 +1456,22 @@ void SCR_UpdateScreen (void) R_TimeReport("finish"); - if (gl_combine.integer && !gl_combine_extension) - Cvar_SetValue("gl_combine", 0); + if (r_textureunits.integer > gl_textureunits) + Cvar_SetValueQuick(&r_textureunits, gl_textureunits); + if (r_textureunits.integer < 1) + Cvar_SetValueQuick(&r_textureunits, 1); + + if (gl_combine.integer && (!gl_combine_extension || r_textureunits.integer < 2)) + Cvar_SetValueQuick(&gl_combine, 0); + + // lighting scale + overbrightscale = 1.0f / (float) (1 << v_overbrightbits.integer); + // lightmaps only lightscalebit = v_overbrightbits.integer; - if (gl_combine.integer && r_multitexture.integer) + if (gl_combine.integer && r_textureunits.integer > 1) lightscalebit += 2; - lightscale = 1.0f / (float) (1 << lightscalebit); - overbrightscale = 1.0f / (float) (1 << v_overbrightbits.integer); R_TimeReport("setup"); diff --git a/gl_backend.h b/gl_backend.h index e7183ad0..01dc1060 100644 --- a/gl_backend.h +++ b/gl_backend.h @@ -83,7 +83,7 @@ void R_Mesh_DrawPolygon(rmeshinfo_t *m, int numverts); // allocates space in geometry buffers, and fills in pointers to the buffers in passsed struct // (this is used for very high speed rendering, no copying) // (only valid between R_Mesh_Start and R_Mesh_Finish) -int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m); +int R_Mesh_Draw_GetBuffer(rmeshbufferinfo_t *m, int wantoverbright); // saves a section of the rendered frame to a .tga file qboolean SCR_ScreenShot(char *filename, int x, int y, int width, int height); diff --git a/gl_models.c b/gl_models.c index 02f9e349..e5852f9b 100644 --- a/gl_models.c +++ b/gl_models.c @@ -482,7 +482,7 @@ void R_DrawQ1Q2AliasModel (float fog) bufmesh.numverts = model->numverts; bufmesh.tex[0] = R_GetTexture(skinframe->merged); - R_Mesh_Draw_GetBuffer(&bufmesh); + R_Mesh_Draw_GetBuffer(&bufmesh, true); aliasvert = bufmesh.vertex; aliasvertcolor = bufmesh.color; diff --git a/gl_rmain.c b/gl_rmain.c index a8c8d056..226de362 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -67,7 +67,7 @@ cvar_t gl_fogblue = {0, "gl_fogblue","0.3"}; cvar_t gl_fogstart = {0, "gl_fogstart", "0"}; cvar_t gl_fogend = {0, "gl_fogend","0"}; -cvar_t r_multitexture = {0, "r_multitexture", "1"}; +cvar_t r_textureunits = {0, "r_textureunits", "32"}; /* ==================== @@ -240,7 +240,7 @@ void GL_Main_Init(void) Cvar_RegisterVariable (&r_wateralpha); Cvar_RegisterVariable (&r_dynamic); Cvar_RegisterVariable (&r_fullbright); - Cvar_RegisterVariable (&r_multitexture); + Cvar_RegisterVariable (&r_textureunits); if (gamemode == GAME_NEHAHRA) Cvar_SetValue("r_fullbrights", 0); R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap); @@ -505,8 +505,6 @@ static void R_SetupFrame (void) if (r_ambient.value != 0) Cvar_Set ("r_ambient", "0"); } - if (r_multitexture.integer && gl_textureunits < 2) - Cvar_SetValue("r_multitexture", 0); r_framecount++; @@ -538,7 +536,7 @@ static void R_BlendView(void) m.depthdisable = true; // magic m.numtriangles = 1; m.numverts = 3; - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { m.index[0] = 0; m.index[1] = 1; diff --git a/gl_rsurf.c b/gl_rsurf.c index 47597c2a..9fe860b5 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -34,6 +34,7 @@ cvar_t r_dlightmap = {CVAR_SAVE, "r_dlightmap", "1"}; cvar_t r_drawportals = {0, "r_drawportals", "0"}; cvar_t r_testvis = {0, "r_testvis", "0"}; cvar_t r_floatbuildlightmap = {0, "r_floatbuildlightmap", "0"}; +cvar_t r_detailtextures = {CVAR_SAVE, "r_detailtextures", "1"}; static int dlightdivtable[32768]; @@ -657,7 +658,7 @@ static void RSurfShader_Sky(msurface_t *firstsurf) { m.numtriangles = mesh->numtriangles; m.numverts = mesh->numverts; - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { cr = fogcolor[0] * m.colorscale; cg = fogcolor[1] * m.colorscale; @@ -768,7 +769,7 @@ static void RSurfShader_Water_Pass_Base(msurface_t *surf) { m.numtriangles = mesh->numtriangles; m.numverts = mesh->numverts; - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, true)) { base[0] = base[1] = base[2] = 1.0f * m.colorscale; memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); @@ -798,7 +799,7 @@ static void RSurfShader_Water_Pass_Base(msurface_t *surf) { m.numtriangles = mesh->numtriangles; m.numverts = mesh->numverts; - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, true)) { cl = m.colorscale; memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); @@ -874,7 +875,7 @@ static void RSurfShader_Water_Pass_Fog(msurface_t *surf) { m.numtriangles = mesh->numtriangles; m.numverts = mesh->numverts; - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { VectorScale(fogcolor, m.colorscale, base); memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); @@ -909,11 +910,13 @@ static void RSurfShader_Water(msurface_t *firstsurf) RSurfShader_Water_Pass_Fog(surf); } -static void RSurfShader_Wall_Pass_BaseMTex(msurface_t *surf) +static void RSurfShader_Wall_Pass_BaseVertex(msurface_t *surf) { - int i; + int i, size3; surfvertex_t *v; - float *outv, *outc, *outst, *outuv, cl, ca, diff[3]; + float *outv, *outc, *outst, cl, ca, diff[3]; + float base[3], scale, f; + qbyte *lm; surfmesh_t *mesh; rmeshbufferinfo_t m; memset(&m, 0, sizeof(m)); @@ -938,96 +941,116 @@ static void RSurfShader_Wall_Pass_BaseMTex(msurface_t *surf) m.depthwrite = false; m.depthdisable = false; m.tex[0] = R_GetTexture(surf->currenttexture->texture); - m.tex[1] = R_GetTexture(surf->lightmaptexture); + + size3 = ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3; + + base[0] = base[1] = base[2] = currentrenderentity->effects & EF_FULLBRIGHT ? 2.0f : r_ambient.value * (1.0f / 64.0f); + ca = currentrenderentity->alpha; for (mesh = surf->mesh;mesh;mesh = mesh->chain) { m.numtriangles = mesh->numtriangles; m.numverts = mesh->numverts; - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, true)) { - cl = (float) (1 << lightscalebit) * m.colorscale; + cl = m.colorscale; memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); - if (fogenabled) + + if (currentrenderentity->effects & EF_FULLBRIGHT) { - if (softwaretransform_complexity) - { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) - { - softwaretransform(v->v, outv); - outv[3] = 1; - VectorSubtract(outv, r_origin, diff); - outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - outuv[0] = v->uv[0]; - outuv[1] = v->uv[1]; - } - } - else + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) - { - VectorCopy(v->v, outv); - outv[3] = 1; - VectorSubtract(outv, r_origin, diff); - outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - outuv[0] = v->uv[0]; - outuv[1] = v->uv[1]; - } + softwaretransform(v->v, outv); + outv[3] = 1; + VectorSubtract(outv, r_origin, diff); + outc[0] = outc[1] = outc[2] = 2.0f * cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; } } else { - if (softwaretransform_complexity) + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) - { - softwaretransform(v->v, outv); - outv[3] = 1; - outc[0] = outc[1] = outc[2] = cl; - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - outuv[0] = v->uv[0]; - outuv[1] = v->uv[1]; - } + softwaretransform(v->v, outv); + outv[3] = 1; + VectorCopy(base, outc); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; } - else + + if (surf->dlightframe == r_framecount) + RSurf_LightSeparate(surf->dlightbits, m.numverts, m.vertex, m.color); + + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color;i < m.numverts;i++, v++, outv += 4, outc += 4) { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) + if (surf->styles[0] != 255) + { + lm = surf->samples + v->lightmapoffset; + scale = d_lightstylevalue[surf->styles[0]] * (1.0f / 32768.0f); + VectorMA(outc, scale, lm, outc); + if (surf->styles[1] != 255) + { + lm += size3; + scale = d_lightstylevalue[surf->styles[1]] * (1.0f / 32768.0f); + VectorMA(outc, scale, lm, outc); + if (surf->styles[2] != 255) + { + lm += size3; + scale = d_lightstylevalue[surf->styles[2]] * (1.0f / 32768.0f); + VectorMA(outc, scale, lm, outc); + if (surf->styles[3] != 255) + { + lm += size3; + scale = d_lightstylevalue[surf->styles[3]] * (1.0f / 32768.0f); + VectorMA(outc, scale, lm, outc); + } + } + } + } + if (fogenabled) { - VectorCopy(v->v, outv); - outv[3] = 1; - outc[0] = outc[1] = outc[2] = cl; - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - outuv[0] = v->uv[0]; - outuv[1] = v->uv[1]; + VectorSubtract(outv, r_origin, diff); + f = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); + VectorScale(outc, f, outc); } + else + VectorScale(outc, cl, outc); } } } } } -static void RSurfShader_Wall_Pass_BaseTexture(msurface_t *surf) +static void RSurfShader_Wall_Pass_BaseFullbright(msurface_t *surf) { int i; surfvertex_t *v; - float *outv, *outc, *outst, cl, ca; + float *outv, *outc, *outst, cl, ca, diff[3]; surfmesh_t *mesh; rmeshbufferinfo_t m; memset(&m, 0, sizeof(m)); - m.transparent = false; - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; + if (currentrenderentity->effects & EF_ADDITIVE) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + } + else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1) + { + m.transparent = true; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; + } + else + { + m.transparent = false; + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ZERO; + } m.depthwrite = false; m.depthdisable = false; m.tex[0] = R_GetTexture(surf->currenttexture->texture); @@ -1037,372 +1060,267 @@ static void RSurfShader_Wall_Pass_BaseTexture(msurface_t *surf) m.numtriangles = mesh->numtriangles; m.numverts = mesh->numverts; - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { - cl = (float) (1 << lightscalebit) * m.colorscale; + cl = m.colorscale; memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); - if (softwaretransform_complexity) + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) + softwaretransform(v->v, outv); + outv[3] = 1; + if (fogenabled) { - softwaretransform(v->v, outv); - outv[3] = 1; - outc[0] = outc[1] = outc[2] = cl; - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; + VectorSubtract(outv, r_origin, diff); + outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); } - } - else - { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) - { - VectorCopy(v->v, outv); - outv[3] = 1; + else outc[0] = outc[1] = outc[2] = cl; - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - } + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; } } } } -static void RSurfShader_Wall_Pass_BaseLightmap(msurface_t *surf) +static void RSurfShader_Wall_Pass_Glow(msurface_t *surf) { int i; surfvertex_t *v; - float *outv, *outc, *outuv, cl, ca, diff[3]; + float *outv, *outc, *outst, cl, ca, diff[3]; surfmesh_t *mesh; rmeshbufferinfo_t m; memset(&m, 0, sizeof(m)); - m.transparent = false; - m.blendfunc1 = GL_ZERO; - m.blendfunc2 = GL_SRC_COLOR; - m.depthwrite = false; - m.depthdisable = false; - m.tex[0] = R_GetTexture(surf->lightmaptexture); + m.transparent = currentrenderentity->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + m.tex[0] = R_GetTexture(surf->currenttexture->glowtexture); ca = currentrenderentity->alpha; for (mesh = surf->mesh;mesh;mesh = mesh->chain) { m.numtriangles = mesh->numtriangles; m.numverts = mesh->numverts; - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { - cl = (float) (1 << lightscalebit) * m.colorscale; + cl = m.colorscale; memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); - if (fogenabled) + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) { - if (softwaretransform_complexity) - { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outuv = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outuv += 2) - { - softwaretransform(v->v, outv); - outv[3] = 1; - VectorSubtract(outv, r_origin, diff); - outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); - outc[3] = ca; - outuv[0] = v->uv[0]; - outuv[1] = v->uv[1]; - } - } - else - { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outuv = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outuv += 2) - { - VectorCopy(v->v, outv); - outv[3] = 1; - VectorSubtract(outv, r_origin, diff); - outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); - outc[3] = ca; - outuv[0] = v->uv[0]; - outuv[1] = v->uv[1]; - } - } - } - else - { - if (softwaretransform_complexity) + softwaretransform(v->v, outv); + outv[3] = 1; + if (fogenabled) { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outuv = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outuv += 2) - { - softwaretransform(v->v, outv); - outv[3] = 1; - outc[0] = outc[1] = outc[2] = cl; - outc[3] = ca; - outuv[0] = v->uv[0]; - outuv[1] = v->uv[1]; - } + VectorSubtract(outv, r_origin, diff); + outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); } else - { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outuv = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outuv += 2) - { - VectorCopy(v->v, outv); - outv[3] = 1; - outc[0] = outc[1] = outc[2] = cl; - outc[3] = ca; - outuv[0] = v->uv[0]; - outuv[1] = v->uv[1]; - } - } + outc[0] = outc[1] = outc[2] = cl; + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; } } } } -static void RSurfShader_Wall_Pass_BaseVertex(msurface_t *surf) +static void RSurfShader_Wall_Pass_Fog(msurface_t *surf) { - int i, size3; + int i; surfvertex_t *v; - float *outv, *outc, *outst, cl, ca, diff[3]; - float base[3], scale, f; - qbyte *lm; + float *outv, *outc, *outst, cl, ca, diff[3], f; surfmesh_t *mesh; rmeshbufferinfo_t m; memset(&m, 0, sizeof(m)); - if (currentrenderentity->effects & EF_ADDITIVE) - { - m.transparent = true; - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; - } - else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1) - { - m.transparent = true; - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - } - else + m.transparent = currentrenderentity->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; + ca = currentrenderentity->alpha; + for (mesh = surf->mesh;mesh;mesh = mesh->chain) { - m.transparent = false; - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; + m.numtriangles = mesh->numtriangles; + m.numverts = mesh->numverts; + + if (R_Mesh_Draw_GetBuffer(&m, false)) + { + cl = m.colorscale; + memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + VectorSubtract(outv, r_origin, diff); + f = cl * exp(fogdensity/DotProduct(diff, diff)); + VectorScale(fogcolor, f, outc); + outc[3] = ca; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + } + } } +} + +static void RSurfShader_OpaqueWall_Pass_TripleTexCombine(msurface_t *surf) +{ + int i; + surfvertex_t *v; + float *outv, *outc, *outst, *outuv, *outab, cl; + surfmesh_t *mesh; + rmeshbufferinfo_t m; + memset(&m, 0, sizeof(m)); + m.transparent = false; + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ZERO; m.depthwrite = false; m.depthdisable = false; m.tex[0] = R_GetTexture(surf->currenttexture->texture); - - size3 = ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3; - - base[0] = base[1] = base[2] = currentrenderentity->effects & EF_FULLBRIGHT ? 2.0f : r_ambient.value * (1.0f / 64.0f); - - ca = currentrenderentity->alpha; + m.texrgbscale[0] = 1.0f; + m.tex[1] = R_GetTexture(surf->lightmaptexture); + m.texrgbscale[1] = 4.0f; + m.tex[2] = R_GetTexture(surf->currenttexture->detailtexture); + m.texrgbscale[2] = 2.0f; for (mesh = surf->mesh;mesh;mesh = mesh->chain) { m.numtriangles = mesh->numtriangles; m.numverts = mesh->numverts; - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { - cl = m.colorscale; + cl = (float) (1 << lightscalebit) * m.colorscale; memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); - - if (currentrenderentity->effects & EF_FULLBRIGHT) + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1], outab = m.texcoords[2];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2, outab += 2) { - if (softwaretransform_complexity) - { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) - { - softwaretransform(v->v, outv); - outv[3] = 1; - VectorSubtract(outv, r_origin, diff); - outc[0] = outc[1] = outc[2] = 2.0f * cl * (1 - exp(fogdensity/DotProduct(diff, diff))); - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - } - } - else - { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) - { - VectorCopy(v->v, outv); - outv[3] = 1; - VectorSubtract(outv, r_origin, diff); - outc[0] = outc[1] = outc[2] = 2.0f * cl * (1 - exp(fogdensity/DotProduct(diff, diff))); - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - } - } + softwaretransform(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = cl; + outc[3] = 1; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + outuv[0] = v->uv[0]; + outuv[1] = v->uv[1]; + outab[0] = v->ab[0]; + outab[1] = v->ab[1]; } - else - { - if (softwaretransform_complexity) - { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) - { - softwaretransform(v->v, outv); - outv[3] = 1; - VectorCopy(base, outc); - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - } - } - else - { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) - { - VectorCopy(v->v, outv); - outv[3] = 1; - VectorCopy(base, outc); - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - } - } - - if (surf->dlightframe == r_framecount) - RSurf_LightSeparate(surf->dlightbits, m.numverts, m.vertex, m.color); + } + } +} - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color;i < m.numverts;i++, v++, outv += 4, outc += 4) - { - if (surf->styles[0] != 255) - { - lm = surf->samples + v->lightmapoffset; - scale = d_lightstylevalue[surf->styles[0]] * (1.0f / 32768.0f); - VectorMA(outc, scale, lm, outc); - if (surf->styles[1] != 255) - { - lm += size3; - scale = d_lightstylevalue[surf->styles[1]] * (1.0f / 32768.0f); - VectorMA(outc, scale, lm, outc); - if (surf->styles[2] != 255) - { - lm += size3; - scale = d_lightstylevalue[surf->styles[2]] * (1.0f / 32768.0f); - VectorMA(outc, scale, lm, outc); - if (surf->styles[3] != 255) - { - lm += size3; - scale = d_lightstylevalue[surf->styles[3]] * (1.0f / 32768.0f); - VectorMA(outc, scale, lm, outc); - } - } - } - } - if (fogenabled) - { - VectorSubtract(outv, r_origin, diff); - f = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); - VectorScale(outc, f, outc); - } - else - VectorScale(outc, cl, outc); - } +static void RSurfShader_OpaqueWall_Pass_BaseMTex(msurface_t *surf) +{ + int i; + surfvertex_t *v; + float *outv, *outc, *outst, *outuv, cl; + surfmesh_t *mesh; + rmeshbufferinfo_t m; + memset(&m, 0, sizeof(m)); + m.transparent = false; + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ZERO; + m.depthwrite = false; + m.depthdisable = false; + m.tex[0] = R_GetTexture(surf->currenttexture->texture); + m.tex[1] = R_GetTexture(surf->lightmaptexture); + for (mesh = surf->mesh;mesh;mesh = mesh->chain) + { + m.numtriangles = mesh->numtriangles; + m.numverts = mesh->numverts; + + if (R_Mesh_Draw_GetBuffer(&m, true)) + { + cl = (float) (1 << lightscalebit) * m.colorscale; + memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2) + { + softwaretransform(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = cl; + outc[3] = 1; + outst[0] = v->st[0]; + outst[1] = v->st[1]; + outuv[0] = v->uv[0]; + outuv[1] = v->uv[1]; } } } } -static void RSurfShader_Wall_Pass_BaseFullbright(msurface_t *surf) +static void RSurfShader_OpaqueWall_Pass_BaseTexture(msurface_t *surf) { int i; surfvertex_t *v; - float *outv, *outc, *outst, cl, ca, diff[3]; + float *outv, *outc, *outst, cl; surfmesh_t *mesh; rmeshbufferinfo_t m; memset(&m, 0, sizeof(m)); - if (currentrenderentity->effects & EF_ADDITIVE) - { - m.transparent = true; - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; - } - else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1) - { - m.transparent = true; - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - } - else - { - m.transparent = false; - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; - } + m.transparent = false; + m.blendfunc1 = GL_ONE; + m.blendfunc2 = GL_ZERO; m.depthwrite = false; m.depthdisable = false; m.tex[0] = R_GetTexture(surf->currenttexture->texture); - ca = currentrenderentity->alpha; for (mesh = surf->mesh;mesh;mesh = mesh->chain) { m.numtriangles = mesh->numtriangles; m.numverts = mesh->numverts; - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { - cl = m.colorscale; + cl = (float) (1 << lightscalebit) * m.colorscale; memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); - if (fogenabled) + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) { - if (softwaretransform_complexity) - { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) - { - softwaretransform(v->v, outv); - outv[3] = 1; - VectorSubtract(outv, r_origin, diff); - outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - } - } - else - { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) - { - VectorCopy(v->v, outv); - outv[3] = 1; - VectorSubtract(outv, r_origin, diff); - outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - } - } + softwaretransform(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = cl; + outc[3] = 1; + outst[0] = v->st[0]; + outst[1] = v->st[1]; } - else + } + } +} + +static void RSurfShader_OpaqueWall_Pass_BaseLightmap(msurface_t *surf) +{ + int i; + surfvertex_t *v; + float *outv, *outc, *outuv, cl; + surfmesh_t *mesh; + rmeshbufferinfo_t m; + memset(&m, 0, sizeof(m)); + m.transparent = false; + m.blendfunc1 = GL_ZERO; + m.blendfunc2 = GL_SRC_COLOR; + m.depthwrite = false; + m.depthdisable = false; + m.tex[0] = R_GetTexture(surf->lightmaptexture); + for (mesh = surf->mesh;mesh;mesh = mesh->chain) + { + m.numtriangles = mesh->numtriangles; + m.numverts = mesh->numverts; + + if (R_Mesh_Draw_GetBuffer(&m, true)) + { + cl = (float) (1 << lightscalebit) * m.colorscale; + memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outuv = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outuv += 2) { - if (softwaretransform_complexity) - { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) - { - softwaretransform(v->v, outv); - outv[3] = 1; - outc[0] = outc[1] = outc[2] = cl; - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - } - } - else - { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) - { - VectorCopy(v->v, outv); - outv[3] = 1; - outc[0] = outc[1] = outc[2] = cl; - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - } - } + softwaretransform(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = cl; + outc[3] = 1; + outuv[0] = v->uv[0]; + outuv[1] = v->uv[1]; } } } } -static void RSurfShader_Wall_Pass_Light(msurface_t *surf) +static void RSurfShader_OpaqueWall_Pass_Light(msurface_t *surf) { int i; surfvertex_t *v; - float *outv, *outc, *outst, cl, ca, diff[3], f; + float *outv, *outc, *outst, cl; surfmesh_t *mesh; rmeshbufferinfo_t m; @@ -1412,28 +1330,12 @@ static void RSurfShader_Wall_Pass_Light(msurface_t *surf) return; memset(&m, 0, sizeof(m)); - if (currentrenderentity->effects & EF_ADDITIVE) - { - m.transparent = true; - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; - } - else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1) - { - m.transparent = true; - m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; - } - else - { - m.transparent = false; - m.blendfunc1 = GL_ONE; - m.blendfunc2 = GL_ZERO; - } + m.transparent = false; + m.blendfunc1 = GL_SRC_ALPHA; + m.blendfunc2 = GL_ONE; m.depthwrite = false; m.depthdisable = false; m.tex[0] = R_GetTexture(surf->currenttexture->texture); - ca = currentrenderentity->alpha; for (mesh = surf->mesh;mesh;mesh = mesh->chain) { if (RSurf_LightCheck(surf->dlightbits, mesh)) @@ -1441,7 +1343,7 @@ static void RSurfShader_Wall_Pass_Light(msurface_t *surf) m.numtriangles = mesh->numtriangles; m.numverts = mesh->numverts; - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, true)) { cl = m.colorscale; memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); @@ -1450,21 +1352,12 @@ static void RSurfShader_Wall_Pass_Light(msurface_t *surf) softwaretransform(v->v, outv); outv[3] = 1; VectorClear(outc); - outc[3] = ca; + outc[3] = 1; outst[0] = v->st[0]; outst[1] = v->st[1]; } RSurf_LightSeparate(surf->dlightbits, m.numverts, m.vertex, m.color); - if (fogenabled) - { - for (i = 0, outv = m.vertex, outc = m.color;i < m.numverts;i++, outv += 4, outc += 4) - { - VectorSubtract(outv, r_origin, diff); - f = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); - VectorScale(outc, f, outc); - } - } - else if (cl != 1) + if (cl != 1) for (i = 0, outc = m.color;i < m.numverts;i++, outc += 4) VectorScale(outc, cl, outc); } @@ -1472,106 +1365,102 @@ static void RSurfShader_Wall_Pass_Light(msurface_t *surf) } } -static void RSurfShader_Wall_Pass_Glow(msurface_t *surf) +static void RSurfShader_OpaqueWall_Pass_Fog(msurface_t *surf) { int i; surfvertex_t *v; - float *outv, *outc, *outst, cl, ca, diff[3]; + float *outv, *outc, cl, diff[3], fcolor[3]; surfmesh_t *mesh; rmeshbufferinfo_t m; memset(&m, 0, sizeof(m)); - m.transparent = currentrenderentity->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1; + m.transparent = false; m.blendfunc1 = GL_SRC_ALPHA; - m.blendfunc2 = GL_ONE; - m.tex[0] = R_GetTexture(surf->currenttexture->glowtexture); - ca = currentrenderentity->alpha; + m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; for (mesh = surf->mesh;mesh;mesh = mesh->chain) { m.numtriangles = mesh->numtriangles; m.numverts = mesh->numverts; - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { cl = m.colorscale; + VectorScale(fogcolor, cl, fcolor); memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); - if (fogenabled) + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color;i < m.numverts;i++, v++, outv += 4, outc += 4) { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) - { - softwaretransform(v->v, outv); - outv[3] = 1; - VectorSubtract(outv, r_origin, diff); - outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff))); - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - } + softwaretransform(v->v, outv); + outv[3] = 1; + VectorCopy(fcolor, outc); + VectorSubtract(outv, r_origin, diff); + outc[3] = exp(fogdensity/DotProduct(diff, diff)); } - else + } + } +} + +static void RSurfShader_OpaqueWall_Pass_BaseDetail(msurface_t *surf) +{ + int i; + surfvertex_t *v; + float *outv, *outc, *outst; + surfmesh_t *mesh; + rmeshbufferinfo_t m; + memset(&m, 0, sizeof(m)); + m.transparent = false; + m.blendfunc1 = GL_DST_COLOR; + m.blendfunc2 = GL_SRC_COLOR; + m.depthwrite = false; + m.depthdisable = false; + m.tex[0] = R_GetTexture(surf->currenttexture->detailtexture); + for (mesh = surf->mesh;mesh;mesh = mesh->chain) + { + m.numtriangles = mesh->numtriangles; + m.numverts = mesh->numverts; + + if (R_Mesh_Draw_GetBuffer(&m, false)) + { + memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) - { - softwaretransform(v->v, outv); - outv[3] = 1; - outc[0] = outc[1] = outc[2] = cl; - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - } + softwaretransform(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = outc[3] = 1; + outst[0] = v->ab[0]; + outst[1] = v->ab[1]; } } } } -static void RSurfShader_Wall_Pass_Fog(msurface_t *surf) +static void RSurfShader_OpaqueWall_Pass_Glow(msurface_t *surf) { int i; surfvertex_t *v; - float *outv, *outc, *outst, cl, ca, diff[3], f; + float *outv, *outc, *outst, cl; surfmesh_t *mesh; rmeshbufferinfo_t m; memset(&m, 0, sizeof(m)); - m.transparent = currentrenderentity->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1; + m.transparent = false; m.blendfunc1 = GL_SRC_ALPHA; m.blendfunc2 = GL_ONE; - ca = currentrenderentity->alpha; + m.tex[0] = R_GetTexture(surf->currenttexture->glowtexture); for (mesh = surf->mesh;mesh;mesh = mesh->chain) { m.numtriangles = mesh->numtriangles; m.numverts = mesh->numverts; - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { cl = m.colorscale; memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3])); - if (softwaretransform_complexity) - { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) - { - softwaretransform(v->v, outv); - outv[3] = 1; - VectorSubtract(outv, r_origin, diff); - f = cl * exp(fogdensity/DotProduct(diff, diff)); - VectorScale(fogcolor, f, outc); - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - } - } - else + for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) { - for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2) - { - VectorCopy(v->v, outv); - outv[3] = 1; - VectorSubtract(outv, r_origin, diff); - VectorSubtract(outv, r_origin, diff); - f = cl * exp(fogdensity/DotProduct(diff, diff)); - VectorScale(fogcolor, f, outc); - outc[3] = ca; - outst[0] = v->st[0]; - outst[1] = v->st[1]; - } + softwaretransform(v->v, outv); + outv[3] = 1; + outc[0] = outc[1] = outc[2] = cl; + outc[3] = 1; + outst[0] = v->st[0]; + outst[1] = v->st[1]; } } } @@ -1612,7 +1501,7 @@ static void RSurfShader_Wall_Vertex(msurface_t *firstsurf) static void RSurfShader_Wall_Lightmap(msurface_t *firstsurf) { msurface_t *surf; - if (r_vertexsurfaces.integer) + if (r_vertexsurfaces.integer || firstsurf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1 || currentrenderentity->effects & EF_ADDITIVE) { for (surf = firstsurf;surf;surf = surf->chain) { @@ -1626,91 +1515,53 @@ static void RSurfShader_Wall_Lightmap(msurface_t *firstsurf) for (surf = firstsurf;surf;surf = surf->chain) RSurfShader_Wall_Pass_Fog(surf); } - else if (r_multitexture.integer) + else { - if (r_dlightmap.integer) + if (r_textureunits.integer >= 2) { - for (surf = firstsurf;surf;surf = surf->chain) + if (r_textureunits.integer >= 3 && gl_combine.integer && r_detailtextures.integer) { - c_brush_polys++; - RSurfShader_Wall_Pass_BaseMTex(surf); + for (surf = firstsurf;surf;surf = surf->chain) + { + c_brush_polys++; + RSurfShader_OpaqueWall_Pass_TripleTexCombine(surf); + } } - for (surf = firstsurf;surf;surf = surf->chain) - if (surf->currenttexture->glowtexture) - RSurfShader_Wall_Pass_Glow(surf); - if (fogenabled) + else + { for (surf = firstsurf;surf;surf = surf->chain) - RSurfShader_Wall_Pass_Fog(surf); + { + c_brush_polys++; + RSurfShader_OpaqueWall_Pass_BaseMTex(surf); + } + if (r_detailtextures.integer) + for (surf = firstsurf;surf;surf = surf->chain) + RSurfShader_OpaqueWall_Pass_BaseDetail(surf); + } } else { for (surf = firstsurf;surf;surf = surf->chain) { c_brush_polys++; - RSurfShader_Wall_Pass_BaseMTex(surf); + RSurfShader_OpaqueWall_Pass_BaseTexture(surf); } for (surf = firstsurf;surf;surf = surf->chain) - if (surf->dlightframe == r_framecount) - RSurfShader_Wall_Pass_Light(surf); - for (surf = firstsurf;surf;surf = surf->chain) - if (surf->currenttexture->glowtexture) - RSurfShader_Wall_Pass_Glow(surf); - if (fogenabled) + RSurfShader_OpaqueWall_Pass_BaseLightmap(surf); + if (r_detailtextures.integer) for (surf = firstsurf;surf;surf = surf->chain) - RSurfShader_Wall_Pass_Fog(surf); - } - } - else if (firstsurf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1 || currentrenderentity->effects & EF_ADDITIVE) - { - for (surf = firstsurf;surf;surf = surf->chain) - { - c_brush_polys++; - RSurfShader_Wall_Pass_BaseVertex(surf); + RSurfShader_OpaqueWall_Pass_BaseDetail(surf); } + if (!r_dlightmap.integer) + for (surf = firstsurf;surf;surf = surf->chain) + if (surf->dlightframe == r_framecount) + RSurfShader_OpaqueWall_Pass_Light(surf); for (surf = firstsurf;surf;surf = surf->chain) if (surf->currenttexture->glowtexture) - RSurfShader_Wall_Pass_Glow(surf); + RSurfShader_OpaqueWall_Pass_Glow(surf); if (fogenabled) for (surf = firstsurf;surf;surf = surf->chain) - RSurfShader_Wall_Pass_Fog(surf); - } - else - { - if (r_dlightmap.integer) - { - for (surf = firstsurf;surf;surf = surf->chain) - { - c_brush_polys++; - RSurfShader_Wall_Pass_BaseTexture(surf); - } - for (surf = firstsurf;surf;surf = surf->chain) - RSurfShader_Wall_Pass_BaseLightmap(surf); - for (surf = firstsurf;surf;surf = surf->chain) - if (surf->currenttexture->glowtexture) - RSurfShader_Wall_Pass_Glow(surf); - if (fogenabled) - for (surf = firstsurf;surf;surf = surf->chain) - RSurfShader_Wall_Pass_Fog(surf); - } - else - { - for (surf = firstsurf;surf;surf = surf->chain) - { - c_brush_polys++; - RSurfShader_Wall_Pass_BaseTexture(surf); - } - for (surf = firstsurf;surf;surf = surf->chain) - RSurfShader_Wall_Pass_BaseLightmap(surf); - for (surf = firstsurf;surf;surf = surf->chain) - if (surf->dlightframe == r_framecount) - RSurfShader_Wall_Pass_Light(surf); - for (surf = firstsurf;surf;surf = surf->chain) - if (surf->currenttexture->glowtexture) - RSurfShader_Wall_Pass_Glow(surf); - if (fogenabled) - for (surf = firstsurf;surf;surf = surf->chain) - RSurfShader_Wall_Pass_Fog(surf); - } + RSurfShader_OpaqueWall_Pass_Fog(surf); } } @@ -2213,6 +2064,7 @@ void GL_Surf_Init(void) Cvar_RegisterVariable(&r_drawportals); Cvar_RegisterVariable(&r_testvis); Cvar_RegisterVariable(&r_floatbuildlightmap); + Cvar_RegisterVariable(&r_detailtextures); R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap); } diff --git a/menu.c b/menu.c index cdf21317..7ee7cc6b 100644 --- a/menu.c +++ b/menu.c @@ -1481,7 +1481,7 @@ void M_Options_Key (int k) } } -#define OPTIONS_EFFECTS_ITEMS 11 +#define OPTIONS_EFFECTS_ITEMS 12 int options_effects_cursor; @@ -1493,6 +1493,7 @@ void M_Menu_Options_Effects_f (void) } +extern cvar_t r_detailtextures; extern cvar_t cl_particles; extern cvar_t cl_explosions; extern cvar_t cl_stainmaps; @@ -1524,24 +1525,27 @@ void M_Menu_Options_Effects_AdjustSliders (int dir) Cvar_SetValueQuick (&cl_stainmaps, !cl_stainmaps.integer); break; case 4: - Cvar_SetValueQuick (&cl_particles_bulletimpacts, !cl_particles_bulletimpacts.integer); + Cvar_SetValueQuick (&r_detailtextures, !r_detailtextures.integer); break; case 5: - Cvar_SetValueQuick (&cl_particles_smoke, !cl_particles_smoke.integer); + Cvar_SetValueQuick (&cl_particles_bulletimpacts, !cl_particles_bulletimpacts.integer); break; case 6: - Cvar_SetValueQuick (&cl_particles_sparks, !cl_particles_sparks.integer); + Cvar_SetValueQuick (&cl_particles_smoke, !cl_particles_smoke.integer); break; case 7: - Cvar_SetValueQuick (&cl_particles_bubbles, !cl_particles_bubbles.integer); + Cvar_SetValueQuick (&cl_particles_sparks, !cl_particles_sparks.integer); break; case 8: - Cvar_SetValueQuick (&cl_particles_blood, !cl_particles_blood.integer); + Cvar_SetValueQuick (&cl_particles_bubbles, !cl_particles_bubbles.integer); break; case 9: - Cvar_SetValueQuick (&cl_particles_blood_size, bound(2, cl_particles_blood_size.value + dir * 1, 20)); + Cvar_SetValueQuick (&cl_particles_blood, !cl_particles_blood.integer); break; case 10: + Cvar_SetValueQuick (&cl_particles_blood_size, bound(2, cl_particles_blood_size.value + dir * 1, 20)); + break; + case 11: Cvar_SetValueQuick (&cl_particles_blood_alpha, bound(0.2, cl_particles_blood_alpha.value + dir * 0.1, 1)); break; } @@ -1561,6 +1565,7 @@ void M_Options_Effects_Draw (void) M_Print(16, y, " Particles");M_DrawCheckbox(220, y, cl_particles.integer);y += 8; M_Print(16, y, " Explosions");M_DrawCheckbox(220, y, cl_explosions.integer);y += 8; M_Print(16, y, " Stainmaps");M_DrawCheckbox(220, y, cl_stainmaps.integer);y += 8; + M_Print(16, y, " Detail Texturing");M_DrawCheckbox(220, y, r_detailtextures.integer);y += 8; M_Print(16, y, " Bullet Impacts");M_DrawCheckbox(220, y, cl_particles_bulletimpacts.integer);y += 8; M_Print(16, y, " Smoke");M_DrawCheckbox(220, y, cl_particles_smoke.integer);y += 8; M_Print(16, y, " Sparks");M_DrawCheckbox(220, y, cl_particles_sparks.integer);y += 8; diff --git a/model_brush.c b/model_brush.c index 5b7e7dd5..167f19d4 100644 --- a/model_brush.c +++ b/model_brush.c @@ -33,6 +33,10 @@ cvar_t r_vertexsurfacesthreshold = {CVAR_SAVE, "r_vertexsurfacesthreshold", "0"} cvar_t r_nosurftextures = {0, "r_nosurftextures", "0"}; cvar_t r_sortsurfaces = {0, "r_sortsurfaces", "0"}; +#define NUM_DETAILTEXTURES 1 +static rtexture_t *detailtextures[NUM_DETAILTEXTURES]; +static rtexturepool_t *detailtexturepool; + /* =============== Mod_BrushInit @@ -51,6 +55,55 @@ void Mod_BrushInit (void) memset(mod_novis, 0xff, sizeof(mod_novis)); } +void Mod_BrushStartup (void) +{ + int i, x, y, light; + float vc[3], vx[3], vy[3], vn[3], lightdir[3]; +#define DETAILRESOLUTION 256 + qbyte data[DETAILRESOLUTION][DETAILRESOLUTION][4], noise[DETAILRESOLUTION][DETAILRESOLUTION]; + detailtexturepool = R_AllocTexturePool(); + lightdir[0] = 0.5; + lightdir[1] = 1; + lightdir[2] = -0.25; + VectorNormalize(lightdir); + for (i = 0;i < NUM_DETAILTEXTURES;i++) + { + fractalnoise(&noise[0][0], DETAILRESOLUTION, DETAILRESOLUTION >> 4); + for (y = 0;y < DETAILRESOLUTION;y++) + { + for (x = 0;x < DETAILRESOLUTION;x++) + { + vc[0] = x; + vc[1] = y; + vc[2] = noise[y][x] * (1.0f / 32.0f); + vx[0] = x + 1; + vx[1] = y; + vx[2] = noise[y][(x + 1) % DETAILRESOLUTION] * (1.0f / 32.0f); + vy[0] = x; + vy[1] = y + 1; + vy[2] = noise[(y + 1) % DETAILRESOLUTION][x] * (1.0f / 32.0f); + VectorSubtract(vx, vc, vx); + VectorSubtract(vy, vc, vy); + CrossProduct(vx, vy, vn); + VectorNormalize(vn); + light = 128 - DotProduct(vn, lightdir) * 128; + light = bound(0, light, 255); + data[y][x][0] = data[y][x][1] = data[y][x][2] = light; + data[y][x][3] = 255; + } + } + detailtextures[i] = R_LoadTexture(detailtexturepool, va("detailtexture%i", i), DETAILRESOLUTION, DETAILRESOLUTION, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE); + } +} + +void Mod_BrushShutdown (void) +{ + int i; + for (i = 0;i < NUM_DETAILTEXTURES;i++) + R_FreeTexture(detailtextures[i]); + R_FreeTexturePool(&detailtexturepool); +} + /* =============== Mod_PointInLeaf @@ -353,6 +406,8 @@ static void Mod_LoadTextures (lump_t *l) if (!R_TextureHasAlpha(tx->texture)) tx->flags |= SURF_CLIPSOLID; } + + tx->detailtexture = detailtextures[i % NUM_DETAILTEXTURES]; } // sequence the animations @@ -1064,6 +1119,9 @@ void Mod_GenerateVertexLitMesh (msurface_t *surf) s = DotProduct (out->v, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]; t = DotProduct (out->v, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]; + out->ab[0] = s * (1.0f / 16.0f); + out->ab[1] = t * (1.0f / 16.0f); + out->st[0] = s / surf->texinfo->texture->width; out->st[1] = t / surf->texinfo->texture->height; @@ -1129,6 +1187,9 @@ void Mod_GenerateLightmappedMesh (msurface_t *surf) s = DotProduct (out->v, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]; t = DotProduct (out->v, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]; + out->ab[0] = s * (1.0f / 16.0f); + out->ab[1] = t * (1.0f / 16.0f); + out->st[0] = s / surf->texinfo->texture->width; out->st[1] = t / surf->texinfo->texture->height; @@ -1151,7 +1212,7 @@ void Mod_GenerateLightmappedMesh (msurface_t *surf) void Mod_GenerateVertexMesh (msurface_t *surf) { int i, *index; - float *in; + float *in, s, t; surfvertex_t *out; surfmesh_t *mesh; @@ -1176,8 +1237,12 @@ void Mod_GenerateVertexMesh (msurface_t *surf) for (i = 0, in = surf->poly_verts, out = mesh->vertex;i < mesh->numverts;i++, in += 3, out++) { VectorCopy (in, out->v); - out->st[0] = (DotProduct (out->v, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]) / surf->texinfo->texture->width; - out->st[1] = (DotProduct (out->v, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]) / surf->texinfo->texture->height; + s = (DotProduct (out->v, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]); + t = (DotProduct (out->v, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]); + out->st[0] = s / surf->texinfo->texture->width; + out->st[1] = t / surf->texinfo->texture->height; + out->ab[0] = s * (1.0f / 16.0f); + out->ab[1] = t * (1.0f / 16.0f); } } diff --git a/model_brush.h b/model_brush.h index 30296c1b..05d81058 100644 --- a/model_brush.h +++ b/model_brush.h @@ -70,6 +70,8 @@ typedef struct texture_s rtexture_t *glowtexture; // alpha texture (used for fogging), NULL if opaque rtexture_t *fogtexture; + // detail texture (usually not used if transparent) + rtexture_t *detailtexture; // total frames in sequence and alternate sequence int anim_total[2]; @@ -116,6 +118,8 @@ typedef struct surfvertex_s float st[2]; // lightmap coordinates float uv[2]; + // detail texture coordinates + float ab[2]; } surfvertex_t; diff --git a/model_shared.c b/model_shared.c index 01e1e46b..adbe9348 100644 --- a/model_shared.c +++ b/model_shared.c @@ -66,6 +66,9 @@ void Mod_SetupNoTexture(void) r_notexture = R_LoadTexture(r_notexturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP); } +extern void Mod_BrushStartup (void); +extern void Mod_BrushShutdown (void); + static void mod_start(void) { int i; @@ -74,6 +77,7 @@ static void mod_start(void) Mod_UnloadModel(&mod_known[i]); Mod_SetupNoTexture(); + Mod_BrushStartup(); } static void mod_shutdown(void) @@ -84,6 +88,7 @@ static void mod_shutdown(void) Mod_UnloadModel(&mod_known[i]); R_FreeTexturePool(&r_notexturepool); + Mod_BrushShutdown(); } static void mod_newmap(void) diff --git a/r_crosshairs.c b/r_crosshairs.c index 7bb57789..158734b0 100644 --- a/r_crosshairs.c +++ b/r_crosshairs.c @@ -173,7 +173,7 @@ void R_DrawCrosshairSprite(rtexture_t *texture, vec3_t origin, vec_t scale, floa m.numtriangles = 2; m.numverts = 4; m.tex[0] = R_GetTexture(texture); - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { m.index[0] = 0; m.index[1] = 1; @@ -184,7 +184,7 @@ void R_DrawCrosshairSprite(rtexture_t *texture, vec3_t origin, vec_t scale, floa m.color[0] = m.color[4] = m.color[8] = m.color[12] = cr * m.colorscale; m.color[1] = m.color[5] = m.color[9] = m.color[13] = cg * m.colorscale; m.color[2] = m.color[6] = m.color[10] = m.color[14] = cb * m.colorscale; - m.color[3] = m.color[7] = m.color[11] = m.color[15] = ca * m.colorscale; + m.color[3] = m.color[7] = m.color[11] = m.color[15] = ca; m.texcoords[0][0] = 0; m.texcoords[0][1] = 0; m.texcoords[0][2] = 0; diff --git a/r_explosion.c b/r_explosion.c index e679ec8c..3f8daa4b 100644 --- a/r_explosion.c +++ b/r_explosion.c @@ -186,7 +186,7 @@ void R_DrawExplosion(explosion_t *e) m.numtriangles = EXPLOSIONTRIS; m.numverts = EXPLOSIONVERTS; m.tex[0] = R_GetTexture(explosiontexture); - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { memcpy(m.index, explosiontris, m.numtriangles * sizeof(int[3])); for (i = 0, v = m.vertex;i < m.numverts;i++, v += 4) diff --git a/r_light.c b/r_light.c index 8d4be018..da977bf0 100644 --- a/r_light.c +++ b/r_light.c @@ -154,7 +154,7 @@ void R_DrawCoronas(void) { // trace to a point just barely closer to the eye VectorSubtract(rd->origin, vpn, diff); - if (CL_TraceLine(r_origin, diff, NULL, NULL, 0, true) == 1 && R_Mesh_Draw_GetBuffer(&m)) + if (CL_TraceLine(r_origin, diff, NULL, NULL, 0, true) == 1 && R_Mesh_Draw_GetBuffer(&m, false)) { scale = m.colorscale * (1.0f / 131072.0f); if (fogenabled) diff --git a/r_sky.c b/r_sky.c index 3e9d9bf5..497d7f71 100644 --- a/r_sky.c +++ b/r_sky.c @@ -171,7 +171,7 @@ static void R_SkyBox(void) m.numtriangles = 2; m.numverts = 4; m.tex[0] = R_GetTexture(skyboxside[3]); // front - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { memcpy(m.index, skyboxindex, sizeof(int[6])); m.color[0] = m.color[4] = m.color[8] = m.color[12] = m.colorscale; @@ -184,7 +184,7 @@ static void R_SkyBox(void) R_SkyBoxPolyVec(3, 0, 0, 1, 1, 1); } m.tex[0] = R_GetTexture(skyboxside[1]); // back - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { memcpy(m.index, skyboxindex, sizeof(int[6])); m.color[0] = m.color[4] = m.color[8] = m.color[12] = m.colorscale; @@ -197,7 +197,7 @@ static void R_SkyBox(void) R_SkyBoxPolyVec(3, 0, 0, -1, -1, 1); } m.tex[0] = R_GetTexture(skyboxside[0]); // right - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { memcpy(m.index, skyboxindex, sizeof(int[6])); m.color[0] = m.color[4] = m.color[8] = m.color[12] = m.colorscale; @@ -210,7 +210,7 @@ static void R_SkyBox(void) R_SkyBoxPolyVec(3, 0, 0, -1, 1, 1); } m.tex[0] = R_GetTexture(skyboxside[2]); // left - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { memcpy(m.index, skyboxindex, sizeof(int[6])); m.color[0] = m.color[4] = m.color[8] = m.color[12] = m.colorscale; @@ -223,7 +223,7 @@ static void R_SkyBox(void) R_SkyBoxPolyVec(3, 0, 0, 1, -1, 1); } m.tex[0] = R_GetTexture(skyboxside[4]); // up - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { memcpy(m.index, skyboxindex, sizeof(int[6])); m.color[0] = m.color[4] = m.color[8] = m.color[12] = m.colorscale; @@ -236,7 +236,7 @@ static void R_SkyBox(void) R_SkyBoxPolyVec(3, 0, 0, -1, -1, 1); } m.tex[0] = R_GetTexture(skyboxside[5]); // down - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { memcpy(m.index, skyboxindex, sizeof(int[6])); m.color[0] = m.color[4] = m.color[8] = m.color[12] = m.colorscale; @@ -341,7 +341,7 @@ static void R_SkySphere(void) m.numtriangles = skygridx*skygridy*2; m.numverts = skygridx1*skygridy1; m.tex[0] = R_GetTexture(solidskytexture); - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { memcpy(m.index, skysphereindices, m.numtriangles * sizeof(int[3])); skyspherearrays(m.vertex, m.texcoords[0], m.color, skysphere, speedscale, m.colorscale); @@ -349,7 +349,7 @@ static void R_SkySphere(void) m.blendfunc1 = GL_SRC_ALPHA; m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA; m.tex[0] = R_GetTexture(alphaskytexture); - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, false)) { memcpy(m.index, skysphereindices, m.numtriangles * sizeof(int[3])); skyspherearrays(m.vertex, m.texcoords[0], m.color, skysphere, speedscale2, m.colorscale); diff --git a/r_sprites.c b/r_sprites.c index 6e732ec2..f6ca3a4a 100644 --- a/r_sprites.c +++ b/r_sprites.c @@ -92,7 +92,7 @@ static void GL_DrawSpriteImage (int fog, mspriteframe_t *frame, int texture, vec m.numtriangles = 2; m.numverts = 4; m.tex[0] = texture; - if (R_Mesh_Draw_GetBuffer(&m)) + if (R_Mesh_Draw_GetBuffer(&m, !(currentrenderentity->model->flags & EF_FULLBRIGHT || currentrenderentity->effects & EF_FULLBRIGHT))) { m.index[0] = 0; m.index[1] = 1; diff --git a/render.h b/render.h index cecb01c0..16c158bc 100644 --- a/render.h +++ b/render.h @@ -65,6 +65,9 @@ extern float *aliasvertcolor; // vis stuff extern cvar_t r_novis; +// detail texture stuff +extern cvar_t r_detailtextures; + #define TOP_RANGE 16 // soldier uniform colors #define BOTTOM_RANGE 96 @@ -156,7 +159,7 @@ void R_DrawSpriteModel (void); extern cvar_t r_render; #include "image.h" -extern cvar_t r_multitexture; +extern cvar_t r_textureunits; extern cvar_t gl_dither; // FIXME: this should live in the backend only -- 2.39.2