From a6921ceb0abd7125dace5eb2b418ff1770504a44 Mon Sep 17 00:00:00 2001 From: havoc Date: Thu, 10 Mar 2005 22:11:19 +0000 Subject: [PATCH] added basematerialflags/currentmaterialflags to texture_t which completely replace the SURF_* flags and SURFRENDER_* flags eliminated the flags and plane fields from q1bsp surfaces q1bsp texture_t generation now sets supercontents (eliminating need for the SURF_SOLIDCLIP surface flag) split R_UpdateTextureInfo into two versions for updating a single texture and updating a whole entity's textures respectively, so transparency rendering can now call R_UpdateTextureInfo instead of having duplicate code git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@5080 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_rsurf.c | 219 ++++++++++++++++++++++++-------------------------- model_brush.c | 86 ++++++++++++++------ model_brush.h | 54 ++++++++----- r_light.c | 15 ++-- 4 files changed, 206 insertions(+), 168 deletions(-) diff --git a/gl_rsurf.c b/gl_rsurf.c index 8ecc23a8..57f23523 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -55,7 +55,7 @@ static int R_IntAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surface { int sdtable[256], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, smax3, red, green, blue, lit, dist2, impacts, impactt, subtract, k; unsigned int *bl; - float dist, impact[3], local[3]; + float dist, impact[3], local[3], planenormal[3], planedist; dlight_t *light; lit = false; @@ -70,7 +70,9 @@ static int R_IntAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surface continue; // not lit by this light Matrix4x4_Transform(matrix, light->origin, local); - dist = DotProduct (local, surface->plane->normal) - surface->plane->dist; + VectorCopy(surface->mesh.data_normal3f, planenormal); + planedist = DotProduct(surface->mesh.data_vertex3f, planenormal); + dist = DotProduct(local, planenormal) - planedist; // for comparisons to minimum acceptable light // compensate for LIGHTOFFSET @@ -81,17 +83,7 @@ static int R_IntAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surface if (dist2 >= maxdist) continue; - if (surface->plane->type < 3) - { - VectorCopy(local, impact); - impact[surface->plane->type] -= dist; - } - else - { - impact[0] = local[0] - surface->plane->normal[0] * dist; - impact[1] = local[1] - surface->plane->normal[1] * dist; - impact[2] = local[2] - surface->plane->normal[2] * dist; - } + VectorMA(local, -dist, planenormal, impact); impacts = DotProduct (impact, surface->texinfo->vecs[0]) + surface->texinfo->vecs[0][3] - surface->texturemins[0]; impactt = DotProduct (impact, surface->texinfo->vecs[1]) + surface->texinfo->vecs[1][3] - surface->texturemins[1]; @@ -149,7 +141,7 @@ static int R_IntAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surface static int R_FloatAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surface) { int lnum, s, t, smax, tmax, smax3, lit, impacts, impactt; - float sdtable[256], *bl, k, dist, dist2, maxdist, maxdist2, maxdist3, td1, td, red, green, blue, impact[3], local[3], subtract; + float sdtable[256], *bl, k, dist, dist2, maxdist, maxdist2, maxdist3, td1, td, red, green, blue, impact[3], local[3], subtract, planenormal[3], planedist; dlight_t *light; lit = false; @@ -164,7 +156,9 @@ static int R_FloatAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surfa continue; // not lit by this light Matrix4x4_Transform(matrix, light->origin, local); - dist = DotProduct (local, surface->plane->normal) - surface->plane->dist; + VectorCopy(surface->mesh.data_normal3f, planenormal); + planedist = DotProduct(surface->mesh.data_vertex3f, planenormal); + dist = DotProduct(local, planenormal) - planedist; // for comparisons to minimum acceptable light // compensate for LIGHTOFFSET @@ -175,17 +169,7 @@ static int R_FloatAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surfa if (dist2 >= maxdist) continue; - if (surface->plane->type < 3) - { - VectorCopy(local, impact); - impact[surface->plane->type] -= dist; - } - else - { - impact[0] = local[0] - surface->plane->normal[0] * dist; - impact[1] = local[1] - surface->plane->normal[1] * dist; - impact[2] = local[2] - surface->plane->normal[2] * dist; - } + VectorMA(local, -dist, planenormal, impact); impacts = DotProduct (impact, surface->texinfo->vecs[0]) + surface->texinfo->vecs[0][3] - surface->texturemins[0]; impactt = DotProduct (impact, surface->texinfo->vecs[1]) + surface->texinfo->vecs[1][3] - surface->texturemins[1]; @@ -708,57 +692,67 @@ static int RSurf_LightSeparate_Vertex3f_Color4f(const matrix4x4_t *matrix, const return lit; } +void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t) +{ + t->currentmaterialflags = t->basematerialflags; + t->currentalpha = ent->alpha; + if (t->basematerialflags & MATERIALFLAG_WATERALPHA) + t->currentalpha *= r_wateralpha.value; + if (ent->effects & EF_ADDITIVE) + t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT; + if (t->currentalpha < 1 || t->skin.fog != NULL) + t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT; + // we don't need to set currentframe if t->animated is false because + // it was already set up by the texture loader for non-animating + if (t->animated) + t->currentframe = t->anim_frames[ent->frame != 0][(t->anim_total[ent->frame != 0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[ent->frame != 0]) : 0]; +} + +void R_UpdateAllTextureInfo(entity_render_t *ent) +{ + int i; + if (ent->model) + for (i = 0;i < ent->model->brush.num_textures;i++) + R_UpdateTextureInfo(ent, ent->model->brush.data_textures + i); +} + static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2) { const entity_render_t *ent = calldata1; const msurface_t *surface = ent->model->brush.data_surfaces + calldata2; rmeshstate_t m; - float currentalpha; float base, colorscale; vec3_t modelorg; texture_t *texture; float args[4] = {0.05f,0,0,0.04f}; - int rendertype, turb, fullbright; + int turb, fullbright; + + texture = surface->texture; + R_UpdateTextureInfo(ent, texture); + if (texture->currentmaterialflags & MATERIALFLAG_SKY) + return; // transparent sky is too difficult R_Mesh_Matrix(&ent->matrix); Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); - texture = surface->texture; - if (texture->animated) - texture = texture->anim_frames[ent->frame != 0][(texture->anim_total[ent->frame != 0] >= 2) ? ((int) (r_refdef.time * 5.0f) % texture->anim_total[ent->frame != 0]) : 0]; - currentalpha = ent->alpha; - if (texture->flags & SURF_WATERALPHA) - currentalpha *= r_wateralpha.value; - - GL_DepthTest(!(ent->effects & EF_NODEPTHTEST)); - if (ent->effects & EF_ADDITIVE) - { - rendertype = SURFRENDER_ADD; + GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST)); + GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)); + if (texture->currentmaterialflags & MATERIALFLAG_ADD) GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); - GL_DepthMask(false); - } - else if (currentalpha < 1 || texture->skin.fog != NULL) - { - rendertype = SURFRENDER_ALPHA; + else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA) GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - GL_DepthMask(false); - } else - { - rendertype = SURFRENDER_OPAQUE; GL_BlendFunc(GL_ONE, GL_ZERO); - GL_DepthMask(!(ent->effects & EF_NODEPTHTEST)); - } - turb = (texture->flags & SURF_DRAWTURB) && r_waterscroll.value; - fullbright = !(ent->flags & RENDER_LIGHT) || (texture->flags & SURF_DRAWFULLBRIGHT) || !surface->samples; + turb = texture->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value; + fullbright = !(ent->flags & RENDER_LIGHT) || (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !surface->samples; base = fullbright ? 2.0f : r_ambient.value * (1.0f / 64.0f); - if (texture->flags & SURF_DRAWTURB) + if (texture->currentmaterialflags & MATERIALFLAG_WATER) base *= 0.5f; - if ((texture->flags & SURF_DRAWTURB) && gl_textureshader && r_watershader.value && !fogenabled && fullbright && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1) + if (texture->currentmaterialflags & MATERIALFLAG_WATER && gl_textureshader && r_watershader.value && !fogenabled && fullbright && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1) { // NVIDIA Geforce3 distortion texture shader on water - GL_Color(1, 1, 1, currentalpha); + GL_Color(1, 1, 1, texture->currentalpha); memset(&m, 0, sizeof(m)); m.pointer_vertex = surface->mesh.data_vertex3f; m.tex[0] = R_GetTexture(mod_shared_distorttexture[(int)(r_refdef.time * 16)&63]); @@ -805,7 +799,7 @@ static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata m.texrgbscale[0] = 4; colorscale *= 0.25f; } - R_FillColors(varray_color4f, surface->mesh.num_vertices, base * ent->colormod[0], base * ent->colormod[1], base * ent->colormod[2], currentalpha); + R_FillColors(varray_color4f, surface->mesh.num_vertices, base * ent->colormod[0], base * ent->colormod[1], base * ent->colormod[2], texture->currentalpha); if (!fullbright) { if (surface->dlightframe == r_framecount) @@ -836,12 +830,12 @@ static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata } } R_Mesh_State(&m); - RSurf_FoggedColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, 1, 1, 1, currentalpha, 1, surface->mesh.num_vertices, modelorg); + RSurf_FoggedColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, 1, 1, 1, texture->currentalpha, 1, surface->mesh.num_vertices, modelorg); GL_LockArrays(0, surface->mesh.num_vertices); R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i); GL_LockArrays(0, 0); } - if (fogenabled && rendertype != SURFRENDER_ADD) + if (fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD)) { memset(&m, 0, sizeof(m)); GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); @@ -859,7 +853,7 @@ static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata } } R_Mesh_State(&m); - RSurf_FogPassColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], currentalpha, 1, surface->mesh.num_vertices, modelorg); + RSurf_FogPassColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], texture->currentalpha, 1, surface->mesh.num_vertices, modelorg); GL_LockArrays(0, surface->mesh.num_vertices); R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i); GL_LockArrays(0, 0); @@ -867,64 +861,53 @@ static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata } } -void R_UpdateTextureInfo(entity_render_t *ent) -{ - int i, texframe, alttextures; - texture_t *t; - - if (!ent->model) - return; - - alttextures = ent->frame != 0; - texframe = (int)(r_refdef.time * 5.0f); - for (i = 0;i < ent->model->brush.num_textures;i++) - { - t = ent->model->brush.data_textures + i; - t->currentalpha = ent->alpha; - if (t->flags & SURF_WATERALPHA) - t->currentalpha *= r_wateralpha.value; - if (ent->effects & EF_ADDITIVE) - t->rendertype = SURFRENDER_ADD; - else if (t->currentalpha < 1 || t->skin.fog != NULL) - t->rendertype = SURFRENDER_ALPHA; - else - t->rendertype = SURFRENDER_OPAQUE; - // we don't need to set currentframe if t->animated is false because - // it was already set up by the texture loader for non-animating - if (t->animated) - t->currentframe = t->anim_frames[alttextures][(t->anim_total[alttextures] >= 2) ? (texframe % t->anim_total[alttextures]) : 0]; - } -} - void R_DrawSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, msurface_t **texturesurfacelist) { int texturesurfaceindex; vec3_t tempcenter, center, modelorg; msurface_t *surface; + qboolean dolightmap; + qboolean dobase; + qboolean doambient; + qboolean dodetail; + qboolean doglow; + qboolean dofog; rmeshstate_t m; Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); + c_faces += texturenumsurfaces; + // gl_lightmaps debugging mode skips normal texturing if (gl_lightmaps.integer) { GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); GL_DepthTest(true); + qglDisable(GL_CULL_FACE); GL_Color(1, 1, 1, 1); memset(&m, 0, sizeof(m)); for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { surface = texturesurfacelist[texturesurfaceindex]; m.tex[0] = R_GetTexture(surface->lightmaptexture); - m.pointer_vertex = surface->mesh.data_vertex3f; m.pointer_texcoord[0] = surface->mesh.data_texcoordlightmap2f; + if (surface->lightmaptexture) + { + GL_Color(1, 1, 1, 1); + m.pointer_color = NULL; + } + else + m.pointer_color = surface->mesh.data_lightmapcolor4f; + m.pointer_vertex = surface->mesh.data_vertex3f; R_Mesh_State(&m); GL_LockArrays(0, surface->mesh.num_vertices); R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i); GL_LockArrays(0, 0); } + qglEnable(GL_CULL_FACE); + return; } - else if (texture->rendertype != SURFRENDER_OPAQUE) + // transparent surfaces get sorted for later drawing + if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT) { - // transparent vertex shaded from lightmap for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { surface = texturesurfacelist[texturesurfaceindex]; @@ -934,15 +917,16 @@ void R_DrawSurfaceList(entity_render_t *ent, texture_t *texture, int texturenums Matrix4x4_Transform(&ent->matrix, tempcenter, center); R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->brush.data_surfaces); } + return; } - else if (texture->flags & SURF_LIGHTMAP) + if (texture->currentmaterialflags & MATERIALFLAG_WALL) { - qboolean dolightmap = (ent->flags & RENDER_LIGHT); - qboolean dobase = true; - qboolean doambient = r_ambient.value > 0; - qboolean dodetail = r_detailtextures.integer != 0; - qboolean doglow = texture->skin.glow != NULL; - qboolean dofog = fogenabled; + dolightmap = (ent->flags & RENDER_LIGHT); + dobase = true; + doambient = r_ambient.value > 0; + dodetail = texture->skin.detail != NULL && r_detailtextures.integer != 0; + doglow = texture->skin.glow != NULL; + dofog = fogenabled; // multitexture cases if (r_textureunits.integer >= 2 && gl_combine.integer && dobase && dolightmap) { @@ -1156,16 +1140,18 @@ void R_DrawSurfaceList(entity_render_t *ent, texture_t *texture, int texturenums GL_LockArrays(0, 0); } } + return; } - else if (texture->flags & SURF_DRAWTURB) + if (texture->currentmaterialflags & MATERIALFLAG_WATER) { for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { surface = texturesurfacelist[texturesurfaceindex]; RSurfShader_Transparent_Callback(ent, surface - ent->model->brush.data_surfaces); } + return; } - else if (texture->flags & SURF_DRAWSKY) + if (texture->currentmaterialflags & MATERIALFLAG_SKY) { if (skyrendernow) { @@ -1205,6 +1191,7 @@ void R_DrawSurfaceList(entity_render_t *ent, texture_t *texture, int texturenums } GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1); } + return; } } @@ -1248,8 +1235,8 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces) } } - R_UpdateTextureInfo(ent); - flagsmask = skysurfaces ? SURF_DRAWSKY : (SURF_DRAWTURB | SURF_LIGHTMAP); + R_UpdateAllTextureInfo(ent); + flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL); f = 0; t = NULL; numsurfacelist = 0; @@ -1266,13 +1253,12 @@ void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces) numsurfacelist = 0; } t = surface->texture; - f = t->flags & flagsmask; + f = t->currentmaterialflags & flagsmask; texture = t->currentframe; } if (f) { // add face to draw list and update lightmap if necessary - c_faces++; if (surface->cached_dlight && surface->lightmaptexture != NULL) R_BuildLightMap(ent, surface); surfacelist[numsurfacelist++] = surface; @@ -1427,7 +1413,8 @@ void R_Q1BSP_DrawSky(entity_render_t *ent) { if (ent->model == NULL) return; - R_DrawSurfaces(ent, true); + if (r_drawcollisionbrushes.integer < 2) + R_DrawSurfaces(ent, true); } void R_Q1BSP_Draw(entity_render_t *ent) @@ -1435,7 +1422,8 @@ void R_Q1BSP_Draw(entity_render_t *ent) if (ent->model == NULL) return; c_bmodels++; - R_DrawSurfaces(ent, false); + if (r_drawcollisionbrushes.integer < 2) + R_DrawSurfaces(ent, false); } void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outclusterlist, qbyte *outclusterpvs, int *outnumclusterspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer) @@ -1470,6 +1458,7 @@ void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, floa pvs = model->brush.GetPVS(model, relativelightorigin); else pvs = NULL; + R_UpdateAllTextureInfo(ent); // FIXME: use BSP recursion as lights are often small for (leafindex = 0, leaf = model->brush.data_leafs;leafindex < model->brush.num_leafs;leafindex++, leaf++) { @@ -1497,7 +1486,7 @@ void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, floa if (!CHECKPVSBIT(outsurfacepvs, surfaceindex)) { surface = model->brush.data_surfaces + surfaceindex; - if (BoxesOverlap(lightmins, lightmaxs, surface->mins, surface->maxs) && (surface->texture->flags & SURF_LIGHTMAP) && !surface->texture->skin.fog) + if (BoxesOverlap(lightmins, lightmaxs, surface->mins, surface->maxs) && ((surface->texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL) && !surface->texture->skin.fog) { for (triangleindex = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;triangleindex < surface->mesh.num_triangles;triangleindex++, t++, e += 3) { @@ -1557,7 +1546,8 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t if (r_drawcollisionbrushes.integer < 2) { R_Mesh_Matrix(&ent->matrix); - R_UpdateTextureInfo(ent); + if (!r_shadow_compilingrtlight) + R_UpdateAllTextureInfo(ent); for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) { surface = model->brush.data_surfaces + surfacelist[surfacelistindex]; @@ -1565,14 +1555,14 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t { // if compiling an rtlight, capture the mesh t = surface->texture; - if (t->flags & SURF_LIGHTMAP && t->skin.fog == NULL) + if ((t->basematerialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL) Mod_ShadowMesh_AddMesh(r_shadow_mempool, r_shadow_compilingrtlight->static_meshchain_light, surface->texture->skin.base, surface->texture->skin.gloss, surface->texture->skin.nmap, surface->mesh.data_vertex3f, surface->mesh.data_svector3f, surface->mesh.data_tvector3f, surface->mesh.data_normal3f, surface->mesh.data_texcoordtexture2f, surface->mesh.num_triangles, surface->mesh.data_element3i); } else if (ent != r_refdef.worldentity || r_worldsurfacevisible[surfacelist[surfacelistindex]]) { t = surface->texture->currentframe; // FIXME: transparent surfaces need to be lit later - if (t->flags & SURF_LIGHTMAP && t->rendertype == SURFRENDER_OPAQUE) + if ((t->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL) R_Shadow_RenderLighting(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i, surface->mesh.data_vertex3f, surface->mesh.data_svector3f, surface->mesh.data_tvector3f, surface->mesh.data_normal3f, surface->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, t->skin.gloss, lightcubemap, ambientscale, diffusescale, specularscale); } } @@ -1722,23 +1712,25 @@ void R_Q3BSP_DrawFace_TransparentCallback(const void *voident, int surfacenumber void R_Q3BSP_DrawFaceList(entity_render_t *ent, texture_t *t, int texturenumsurfaces, msurface_t **texturesurfacelist) { int i, texturesurfaceindex; + vec3_t modelorg; msurface_t *surface; qboolean dolightmap; qboolean dobase; qboolean doambient; + qboolean dodetail; qboolean doglow; qboolean dofog; rmeshstate_t m; - if (!texturenumsurfaces) - return; + Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg); c_faces += texturenumsurfaces; // gl_lightmaps debugging mode skips normal texturing if (gl_lightmaps.integer) { + GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); GL_DepthTest(true); - GL_BlendFunc(GL_ONE, GL_ZERO); qglDisable(GL_CULL_FACE); + GL_Color(1, 1, 1, 1); memset(&m, 0, sizeof(m)); for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++) { @@ -1827,6 +1819,7 @@ void R_Q3BSP_DrawFaceList(entity_render_t *ent, texture_t *t, int texturenumsurf dolightmap = (ent->flags & RENDER_LIGHT); dobase = true; doambient = r_ambient.value > 0; + dodetail = t->skin.detail != NULL && r_detailtextures.integer; doglow = t->skin.glow != NULL; dofog = fogenabled; if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED) diff --git a/model_brush.c b/model_brush.c index 56a02e5c..99088440 100644 --- a/model_brush.c +++ b/model_brush.c @@ -220,7 +220,7 @@ static void Mod_Q1BSP_FindNonSolidLocation_r_Leaf(findnonsolidlocationinfo_t *in for (surfacenum = 0, mark = leaf->firstleafsurface;surfacenum < leaf->numleafsurfaces;surfacenum++, mark++) { surface = info->model->brush.data_surfaces + *mark; - if (surface->flags & SURF_SOLIDCLIP) + if (surface->texture->supercontents & SUPERCONTENTS_SOLID) { for (k = 0;k < surface->mesh.num_triangles;k++) { @@ -790,7 +790,7 @@ loc0: surface = r_refdef.worldmodel->brush.data_surfaces + node->firstsurface; for (i = 0;i < node->numsurfaces;i++, surface++) { - if (!(surface->texture->flags & SURF_LIGHTMAP) || !surface->samples) + if (!(surface->texture->basematerialflags & MATERIALFLAG_WALL) || !surface->samples) continue; // no lightmaps ds = (int) (x * surface->texinfo->vecs[0][0] + y * surface->texinfo->vecs[0][1] + mid * surface->texinfo->vecs[0][2] + surface->texinfo->vecs[0][3]) - surface->texturemins[0]; @@ -1010,9 +1010,16 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l) tx->height = 16; tx->skin.base = r_notexture; if (i == loadmodel->brush.num_textures - 1) - tx->flags = SURF_DRAWTURB | SURF_LIGHTBOTHSIDES; + { + tx->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES; + tx->supercontents = SUPERCONTENTS_WATER; + } else - tx->flags = SURF_LIGHTMAP | SURF_SOLIDCLIP; + { + tx->basematerialflags |= MATERIALFLAG_WALL; + tx->supercontents = SUPERCONTENTS_SOLID; + } + tx->basematerialflags = 0; tx->currentframe = tx; } @@ -1131,22 +1138,37 @@ static void Mod_Q1BSP_LoadTextures(lump_t *l) tx->skin.base = r_notexture; } + tx->basematerialflags = 0; if (tx->name[0] == '*') { // turb does not block movement - tx->flags = SURF_DRAWTURB | SURF_LIGHTBOTHSIDES; + tx->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_LIGHTBOTHSIDES; // LordHavoc: some turbulent textures should be fullbright and solid if (!strncmp(tx->name,"*lava",5) || !strncmp(tx->name,"*teleport",9) || !strncmp(tx->name,"*rift",5)) // Scourge of Armagon texture - tx->flags |= SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA; + tx->basematerialflags |= MATERIALFLAG_FULLBRIGHT; + else + tx->basematerialflags |= MATERIALFLAG_WATERALPHA; + if (!strncmp(tx->name, "*lava", 5)) + tx->supercontents = SUPERCONTENTS_LAVA; + else if (!strncmp(tx->name, "*slime", 6)) + tx->supercontents = SUPERCONTENTS_SLIME; else - tx->flags |= SURF_WATERALPHA; + tx->supercontents = SUPERCONTENTS_WATER; } else if (tx->name[0] == 's' && tx->name[1] == 'k' && tx->name[2] == 'y') - tx->flags = SURF_DRAWSKY | SURF_SOLIDCLIP; + { + tx->supercontents = SUPERCONTENTS_SKY; + tx->basematerialflags |= MATERIALFLAG_SKY; + } else - tx->flags = SURF_LIGHTMAP | SURF_SOLIDCLIP; + { + tx->supercontents = SUPERCONTENTS_SOLID; + tx->basematerialflags |= MATERIALFLAG_WALL; + } + if (tx->skin.fog) + tx->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT; // start out with no animation tx->currentframe = tx; @@ -1576,7 +1598,7 @@ static void Mod_Q1BSP_LoadTexinfo(lump_t *l) { // if texture chosen is NULL or the shader needs a lightmap, // force to notexture water shader - if (out->texture == NULL || out->texture->flags & SURF_LIGHTMAP) + if (out->texture == NULL || out->texture->basematerialflags & MATERIALFLAG_WALL) out->texture = loadmodel->brush.data_textures + (loadmodel->brush.num_textures - 1); } else @@ -1784,16 +1806,15 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l) Host_Error("Mod_Q1BSP_LoadFaces: invalid texinfo index %i(model has %i texinfos)\n", i, loadmodel->brushq1.numtexinfo); surface->texinfo = loadmodel->brushq1.texinfo + i; surface->texture = surface->texinfo->texture; - surface->flags = surface->texture->flags; planenum = LittleShort(in->planenum); if ((unsigned int) planenum >= (unsigned int) loadmodel->brush.num_planes) Host_Error("Mod_Q1BSP_LoadFaces: invalid plane index %i (model has %i planes)\n", planenum, loadmodel->brush.num_planes); - if (LittleShort(in->side)) - surface->flags |= SURF_PLANEBACK; - - surface->plane = loadmodel->brush.data_planes + planenum; + //surface->flags = surface->texture->flags; + //if (LittleShort(in->side)) + // surface->flags |= SURF_PLANEBACK; + //surface->plane = loadmodel->brush.data_planes + planenum; surface->mesh.num_vertices = numedges; surface->mesh.num_triangles = numedges - 2; @@ -1880,20 +1901,17 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l) else // LordHavoc: white lighting (bsp version 29) surface->samples = loadmodel->brushq1.lightdata + (i * 3); - if (surface->texture->flags & SURF_LIGHTMAP) + if (surface->texture->basematerialflags & MATERIALFLAG_WALL) { + int i, iu, iv; + float u, v, ubase, vbase, uscale, vscale; + if (ssize > 256 || tsize > 256) Host_Error("Bad surface extents"); // stainmap for permanent marks on walls surface->stainsamples = Mem_Alloc(loadmodel->mempool, ssize * tsize * 3); // clear to white memset(surface->stainsamples, 255, ssize * tsize * 3); - } - - if (surface->texture->flags & SURF_LIGHTMAP) - { - int i, iu, iv; - float u, v, ubase, vbase, uscale, vscale; if (r_miplightmaps.integer) { @@ -3044,11 +3062,8 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer) for (j = 0, surface = &mod->brush.data_surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surface++) { // we only need to have a drawsky function if it is used(usually only on world model) - if (surface->texture->flags & SURF_DRAWSKY) + if (surface->texture->basematerialflags & MATERIALFLAG_SKY) mod->DrawSky = R_Q1BSP_DrawSky; - // LordHavoc: submodels always clip, even if water - if (i) - surface->flags |= SURF_SOLIDCLIP; // calculate bounding shapes for (k = 0, vec = surface->mesh.data_vertex3f;k < surface->mesh.num_vertices;k++, vec += 3) { @@ -3784,6 +3799,17 @@ static void Mod_Q3BSP_LoadTextures(lump_t *l) { out->surfaceparms = flags; out->textureflags = flags2; + out->basematerialflags = 0; + if (out->surfaceparms & Q3SURFACEPARM_NODRAW) + out->basematerialflags |= MATERIALFLAG_NODRAW; + else if (out->surfaceparms & Q3SURFACEPARM_SKY) + out->basematerialflags |= MATERIALFLAG_SKY; + else if (out->surfaceparms & (Q3SURFACEPARM_WATER | Q3SURFACEPARM_SLIME | Q3SURFACEPARM_LAVA)) + out->basematerialflags |= MATERIALFLAG_WATER; + else + out->basematerialflags |= MATERIALFLAG_WALL; + if (out->surfaceparms & (Q3SURFACEPARM_SLIME | Q3SURFACEPARM_WATER)) + out->basematerialflags |= MATERIALFLAG_WATERALPHA; strlcpy(out->firstpasstexturename, firstpasstexturename, sizeof(out->firstpasstexturename)); if ((flags & Q3SURFACEPARM_SKY) && sky[0]) { @@ -3813,6 +3839,12 @@ parseerror: c++; Con_DPrintf("%s: No shader found for texture \"%s\"\n", loadmodel->name, out->name); out->surfaceparms = 0; + if (out->surfaceflags & Q3SURFACEFLAG_NODRAW) + out->basematerialflags |= MATERIALFLAG_NODRAW; + else if (out->surfaceflags & Q3SURFACEFLAG_SKY) + out->basematerialflags |= MATERIALFLAG_SKY; + else + out->basematerialflags |= MATERIALFLAG_WALL; // these are defaults //if (!strncmp(out->name, "textures/skies/", 15)) // out->surfaceparms |= Q3SURFACEPARM_SKY; @@ -3825,6 +3857,8 @@ parseerror: if (!Mod_LoadSkinFrame(&out->skin, out->name, (((out->textureflags & Q3TEXTUREFLAG_NOMIPMAPS) || (out->surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (out->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true, true)) if (!Mod_LoadSkinFrame(&out->skin, out->firstpasstexturename, (((out->textureflags & Q3TEXTUREFLAG_NOMIPMAPS) || (out->surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (out->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true, true)) Con_Printf("%s: texture loading for shader \"%s\" failed (first layer \"%s\" not found either)\n", loadmodel->name, out->name, out->firstpasstexturename); + if (out->skin.fog) + out->basematerialflags |= (MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT); } if (c) Con_DPrintf("%s: %i textures missing shaders\n", loadmodel->name, c); diff --git a/model_brush.h b/model_brush.h index 011b44ba..6484ccf8 100644 --- a/model_brush.h +++ b/model_brush.h @@ -61,19 +61,31 @@ mplane_t; #define SHADERSTAGE_NORMAL 1 #define SHADERSTAGE_COUNT 2 -#define SURF_PLANEBACK 2 -#define SURF_DRAWSKY 4 -#define SURF_DRAWTURB 0x10 -#define SURF_LIGHTMAP 0x20 -#define SURF_DRAWNOALPHA 0x100 -#define SURF_DRAWFULLBRIGHT 0x200 -#define SURF_LIGHTBOTHSIDES 0x400 -#define SURF_WATERALPHA 0x4000 // this polygon's alpha is modulated by r_wateralpha -#define SURF_SOLIDCLIP 0x8000 // this polygon blocks movement - -#define SURFRENDER_OPAQUE 0 -#define SURFRENDER_ALPHA 1 -#define SURFRENDER_ADD 2 +//#define SURF_PLANEBACK 2 + +// set for anything to be transparent sorted +#define MATERIALFLAG_TRANSPARENT 1 +// use alpha blend on this material +#define MATERIALFLAG_ALPHA 2 +// use additive blend on this material +#define MATERIALFLAG_ADD 4 +// turn off depth test on this material +#define MATERIALFLAG_NODEPTHTEST 8 +// multiply alpha by r_wateralpha cvar +#define MATERIALFLAG_WATERALPHA 16 +// draw with no lighting +#define MATERIALFLAG_FULLBRIGHT 32 +// drawn as a normal lightmapped wall +#define MATERIALFLAG_WALL 64 +// swirling water effect +#define MATERIALFLAG_WATER 128 +// this surface shows the sky +// skipped if transparent +#define MATERIALFLAG_SKY 256 +// skips drawing the surface +#define MATERIALFLAG_NODRAW 512 +// probably used only on q1bsp water +#define MATERIALFLAG_LIGHTBOTHSIDES 1024 struct entity_render_s; struct texture_s; @@ -87,10 +99,12 @@ typedef struct texture_s // size unsigned int width, height; // SURF_ flags - unsigned int flags; + //unsigned int flags; - // type of rendering (SURFRENDER_ value) - int rendertype; + // base material flags + int basematerialflags; + // current material flags (updated each bmodel render) + int currentmaterialflags; // loaded the same as model skins skinframe_t skin; @@ -150,13 +164,11 @@ typedef struct msurface_s int num_firstshadowmeshtriangle; // the node plane this is on, backwards if SURF_PLANEBACK flag set - mplane_t *plane; // q1bsp + //mplane_t *plane; // q1bsp // SURF_ flags - int flags; // q1bsp + //int flags; // q1bsp // texture mapping properties used by this surface mtexinfo_t *texinfo; // q1bsp - // if lightmap settings changed, this forces update - int cached_dlight; // q1bsp // index into d_lightstylevalue array, 255 means not used (black) qbyte styles[MAXLIGHTMAPS]; // q1bsp // RGB lighting data [numstyles][height][width][3] @@ -167,6 +179,8 @@ typedef struct msurface_s int lightmaptexturestride; // q1bsp int texturemins[2]; // q1bsp int extents[2]; // q1bsp + // if lightmap settings changed, this forces update + int cached_dlight; // q1bsp // if this == r_framecount there are dynamic lights on the surface int dlightframe; // q1bsp // which dynamic lights are touching this surface diff --git a/r_light.c b/r_light.c index 7b3ed2a7..272eed2a 100644 --- a/r_light.c +++ b/r_light.c @@ -203,7 +203,7 @@ static void R_RecursiveMarkLights(entity_render_t *ent, vec3_t lightorigin, dlig if (leaf->numleafsurfaces && (i >= pvsbits || CHECKPVSBIT(pvs, i))) { int d, impacts, impactt; - float sdist, maxdist, dist2, impact[3]; + float sdist, maxdist, dist2, impact[3], planenormal[3], planedist; msurface_t *surface; // mark the polygons maxdist = light->rtlight.lightmap_cullradius2; @@ -212,11 +212,11 @@ static void R_RecursiveMarkLights(entity_render_t *ent, vec3_t lightorigin, dlig if (ent == r_refdef.worldentity && !r_worldsurfacevisible[leaf->firstleafsurface[i]]) continue; surface = ent->model->brush.data_surfaces + leaf->firstleafsurface[i]; - dist = sdist = PlaneDiff(lightorigin, surface->plane); - if (surface->flags & SURF_PLANEBACK) - dist = -dist; + VectorCopy(surface->mesh.data_normal3f, planenormal); + planedist = DotProduct(surface->mesh.data_vertex3f, surface->mesh.data_normal3f); + dist = sdist = DotProduct(lightorigin, planenormal) - planedist; - if (dist < -0.25f && !(surface->texture->flags & SURF_LIGHTBOTHSIDES)) + if (dist < -0.25f && !(surface->texture->currentmaterialflags & MATERIALFLAG_LIGHTBOTHSIDES)) continue; dist2 = dist * dist; @@ -224,10 +224,7 @@ static void R_RecursiveMarkLights(entity_render_t *ent, vec3_t lightorigin, dlig continue; VectorCopy(lightorigin, impact); - if (surface->plane->type >= 3) - VectorMA(impact, -sdist, surface->plane->normal, impact); - else - impact[surface->plane->type] -= sdist; + VectorMA(impact, -sdist, planenormal, impact); impacts = DotProduct (impact, surface->texinfo->vecs[0]) + surface->texinfo->vecs[0][3] - surface->texturemins[0]; -- 2.39.2