]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rsurf.c
added r_glsl_restart command, and modified shaderstring loading back to the old way...
[xonotic/darkplaces.git] / gl_rsurf.c
index c5abc25bed29d65f39213ea65977fe1eb4c8a300..6ba68f2ad33e419d6f40330a1c06cd5f0f4560be 100644 (file)
@@ -25,14 +25,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #define MAX_LIGHTMAP_SIZE 256
 
-cvar_t r_ambient = {0, "r_ambient", "0"};
-cvar_t r_drawportals = {0, "r_drawportals", "0"};
-cvar_t r_lockpvs = {0, "r_testpvs", "0"};
-cvar_t r_lockvisibility = {0, "r_lockvisibility", "0"};
-cvar_t r_useportalculling = {0, "r_useportalculling", "0"};
-cvar_t r_drawcollisionbrushes_polygonfactor = {0, "r_drawcollisionbrushes_polygonfactor", "-1"};
-cvar_t r_drawcollisionbrushes_polygonoffset = {0, "r_drawcollisionbrushes_polygonoffset", "0"};
-cvar_t r_q3bsp_renderskydepth = {0, "r_q3bsp_renderskydepth", "0"};
+cvar_t r_ambient = {0, "r_ambient", "0", "brighter world cheat (not allowed in multiplayer), value is 0-128"};
+cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
+cvar_t r_lockpvs = {0, "r_lockpvs", "0", "disables pvs switching, allows you to walk around and inspect what is visible from a given location in the map (anything not visible from your current location will not be drawn)"};
+cvar_t r_lockvisibility = {0, "r_lockvisibility", "0", "disables visibility updates, allows you to walk around and inspect what is visible from a given viewpoint in the map (anything offscreen at the moment this is enabled will not be drawn)"};
+cvar_t r_useportalculling = {0, "r_useportalculling", "1", "use advanced portal culling visibility method to improve performance over just Potentially Visible Set, provides an even more significant speed improvement in unvised maps"};
+cvar_t r_q3bsp_renderskydepth = {0, "r_q3bsp_renderskydepth", "0", "draws sky depth masking in q3 maps (as in q1 maps), this means for example that sky polygons can hide other things"};
 
 // flag arrays used for visibility checking on world model
 // (all other entities have no per-surface/per-leaf visibility checks)
@@ -270,9 +268,9 @@ void R_Stain (const vec3_t origin, float radius, int cr1, int cg1, int cb1, int
        R_StainNode(r_refdef.worldmodel->brush.data_nodes + r_refdef.worldmodel->brushq1.hulls[0].firstclipnode, r_refdef.worldmodel, origin, radius, fcolor);
 
        // look for embedded bmodels
-       for (n = 0;n < cl_num_brushmodel_entities;n++)
+       for (n = 0;n < cl.num_brushmodel_entities;n++)
        {
-               ent = &cl_entities[cl_brushmodel_entities[n]].render;
+               ent = &cl.entities[cl.brushmodel_entities[n]].render;
                model = ent->model;
                if (model && model->name[0] == '*')
                {
@@ -294,22 +292,22 @@ void R_Stain (const vec3_t origin, float radius, int cr1, int cg1, int cb1, int
 =============================================================
 */
 
-static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
+static void R_DrawPortal_Callback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
 {
+       const mportal_t *portal = (mportal_t *)ent;
        int i;
        float *v;
        rmeshstate_t m;
-       const mportal_t *portal = (mportal_t *)calldata1;
        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        GL_DepthMask(false);
        GL_DepthTest(true);
-       R_Mesh_Matrix(&r_identitymatrix);
+       R_Mesh_Matrix(&identitymatrix);
 
        memset(&m, 0, sizeof(m));
        m.pointer_vertex = varray_vertex3f;
        R_Mesh_State(&m);
 
-       i = calldata2;
+       i = surfacenumber;
        GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f),
                         ((i & 0x0038) >> 3) * (1.0f / 7.0f),
                         ((i & 0x01C0) >> 6) * (1.0f / 7.0f),
@@ -330,7 +328,7 @@ static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
 // LordHavoc: this is just a nice debugging tool, very slow
 static void R_DrawPortals(void)
 {
-       int i, leafnum;//, portalnum;
+       int i, leafnum;
        mportal_t *portal;
        float center[3], f;
        model_t *model = r_refdef.worldmodel;
@@ -351,8 +349,7 @@ static void R_DrawPortals(void)
                                                VectorAdd(center, portal->points[i].position, center);
                                        f = ixtable[portal->numpoints];
                                        VectorScale(center, f, center);
-                                       //R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, portal, portalnum);
-                                       R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, portal, leafnum);
+                                       R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, (entity_render_t *)portal, leafnum, r_shadow_rtlight);
                                }
                        }
                }
@@ -502,8 +499,7 @@ void R_Q1BSP_DrawSky(entity_render_t *ent)
 {
        if (ent->model == NULL)
                return;
-       if (r_drawcollisionbrushes.integer < 2)
-               R_DrawSurfaces(ent, true);
+       R_DrawSurfaces(ent, true);
 }
 
 void R_Q1BSP_Draw(entity_render_t *ent)
@@ -511,9 +507,8 @@ void R_Q1BSP_Draw(entity_render_t *ent)
        model_t *model = ent->model;
        if (model == NULL)
                return;
-       if (r_drawcollisionbrushes.integer < 2)
-               R_DrawSurfaces(ent, false);
-       if (r_drawcollisionbrushes.integer >= 1 && model->brush.num_brushes)
+       R_DrawSurfaces(ent, false);
+       if (r_showcollisionbrushes.integer && model->brush.num_brushes && !r_showtrispass)
        {
                int i;
                msurface_t *surface;
@@ -521,8 +516,8 @@ void R_Q1BSP_Draw(entity_render_t *ent)
                R_Mesh_Matrix(&ent->matrix);
                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
                GL_DepthMask(false);
-               GL_DepthTest(true);
-               qglPolygonOffset(r_drawcollisionbrushes_polygonfactor.value, r_drawcollisionbrushes_polygonoffset.value);
+               GL_DepthTest(!r_showdisabledepthtest.integer);
+               qglPolygonOffset(r_showcollisionbrushes_polygonfactor.value, r_showcollisionbrushes_polygonoffset.value);
                for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
                        if (brush->colbrushf && brush->colbrushf->numtriangles)
                                R_DrawCollisionBrush(brush->colbrushf);
@@ -572,6 +567,8 @@ void R_Q1BSP_RecursiveGetLightInfo(r_q1bsp_getlightinfo_t *info, mnode_t *node)
                        R_Q1BSP_RecursiveGetLightInfo(info, node->children[0]);
                        node = node->children[1];
                }
+               else if (sides == 0)
+                       return; // ERROR: NAN bounding box!
                else
                        node = node->children[sides - 1];
        }
@@ -603,7 +600,6 @@ void R_Q1BSP_RecursiveGetLightInfo(r_q1bsp_getlightinfo_t *info, mnode_t *node)
                                {
                                        msurface_t *surface = info->model->data_surfaces + surfaceindex;
                                        if (BoxesOverlap(info->lightmins, info->lightmaxs, surface->mins, surface->maxs))
-                                       if ((surface->texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL)
                                        {
                                                int triangleindex, t;
                                                const int *e;
@@ -705,7 +701,7 @@ void R_Q1BSP_CompileShadowVolume(entity_render_t *ent, vec3_t relativelightorigi
                texture = surface->texture;
                if ((texture->basematerialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_WALL)) != MATERIALFLAG_WALL)
                        continue;
-               if (texture->textureflags & (Q3TEXTUREFLAG_TWOSIDED | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+               if ((texture->textureflags & (Q3TEXTUREFLAG_TWOSIDED | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) || (ent->flags & RENDER_NOCULLFACE))
                        continue;
                R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, r_shadow_compilingrtlight->cullmins, r_shadow_compilingrtlight->cullmaxs, surface->mins, surface->maxs);
        }
@@ -717,7 +713,7 @@ extern float *rsurface_vertex3f;
 extern float *rsurface_svector3f;
 extern float *rsurface_tvector3f;
 extern float *rsurface_normal3f;
-extern void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg);
+extern void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents);
 
 void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist, const vec3_t lightmins, const vec3_t lightmaxs)
 {
@@ -730,8 +726,6 @@ void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin,
        // check the box in modelspace, it was already checked in worldspace
        if (!BoxesOverlap(ent->model->normalmins, ent->model->normalmaxs, lightmins, lightmaxs))
                return;
-       if (r_drawcollisionbrushes.integer >= 2)
-               return;
        R_UpdateAllTextureInfo(ent);
        if (model->brush.shadowmesh)
        {
@@ -742,7 +736,7 @@ void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin,
                        texture = surface->texture->currentframe;
                        if ((texture->currentmaterialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_WALL)) != MATERIALFLAG_WALL)
                                continue;
-                       if (texture->textureflags & (Q3TEXTUREFLAG_TWOSIDED | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+                       if ((texture->textureflags & (Q3TEXTUREFLAG_TWOSIDED | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) || (ent->flags & RENDER_NOCULLFACE))
                                continue;
                        R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, lightmins, lightmaxs, surface->mins, surface->maxs);
                }
@@ -759,7 +753,7 @@ void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin,
                        texture = surface->texture;//R_FetchAliasSkin(ent, surface->groupmesh);
                        if (texture->currentmaterialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT) || !surface->num_triangles)
                                continue;
-                       RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+                       RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
                        // identify lit faces within the bounding box
                        R_Shadow_PrepareShadowMark(surface->groupmesh->num_triangles);
                        R_Shadow_MarkVolumeFromBox(surface->num_firsttriangle, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i, relativelightorigin, lightmins, lightmaxs, surface->mins, surface->maxs);
@@ -768,9 +762,39 @@ void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin,
        }
 }
 
+static void R_Q1BSP_DrawLight_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+{
+       msurface_t *surface = ent->model->data_surfaces + surfacenumber;
+       texture_t *texture = surface->texture;
+       R_UpdateTextureInfo(ent, texture);
+       texture = texture->currentframe;
+       R_Shadow_RenderMode_Begin();
+       R_Shadow_RenderMode_ActiveLight((rtlight_t *)rtlight);
+       R_Shadow_RenderMode_Lighting(false, true);
+       R_Shadow_SetupEntityLight(ent);
+       R_Shadow_RenderSurfacesLighting(ent, texture, 1, &surface);
+       R_Shadow_RenderMode_End();
+}
+
+static void R_Q1BSP_DrawLight_TransparentBatch(const entity_render_t *ent, texture_t *texture, int batchnumsurfaces, msurface_t **batchsurfacelist)
+{
+       int batchsurfaceindex;
+       msurface_t *batchsurface;
+       vec3_t tempcenter, center;
+       for (batchsurfaceindex = 0;batchsurfaceindex < batchnumsurfaces;batchsurfaceindex++)
+       {
+               batchsurface = batchsurfacelist[batchsurfaceindex];
+               tempcenter[0] = (batchsurface->mins[0] + batchsurface->maxs[0]) * 0.5f;
+               tempcenter[1] = (batchsurface->mins[1] + batchsurface->maxs[1]) * 0.5f;
+               tempcenter[2] = (batchsurface->mins[2] + batchsurface->maxs[2]) * 0.5f;
+               Matrix4x4_Transform(&ent->matrix, tempcenter, center);
+               R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_Q1BSP_DrawLight_TransparentCallback, ent, batchsurface - ent->model->data_surfaces, r_shadow_rtlight);
+       }
+}
+
 #define RSURF_MAX_BATCHSURFACES 1024
 
-void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolorbase, float *lightcolorpants, float *lightcolorshirt, int numsurfaces, const int *surfacelist)
+void R_Q1BSP_DrawLight(entity_render_t *ent, int numsurfaces, const int *surfacelist)
 {
        model_t *model = ent->model;
        msurface_t *surface;
@@ -779,14 +803,7 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolorbase, float *light
        msurface_t *batchsurfacelist[RSURF_MAX_BATCHSURFACES];
        vec3_t modelorg;
        texture_t *tex;
-       rtexture_t *basetexture = NULL;
-       rtexture_t *glosstexture = NULL;
-       float specularscale = 0;
        qboolean skip;
-       if (r_drawcollisionbrushes.integer >= 2)
-               return;
-       if (VectorLength2(lightcolorbase) + VectorLength2(lightcolorpants) + VectorLength2(lightcolorshirt) < 0.0001)
-               return;
        R_UpdateAllTextureInfo(ent);
        Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
        tex = NULL;
@@ -803,46 +820,26 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolorbase, float *light
                {
                        if (batchnumsurfaces > 0)
                        {
-                               R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, modelorg);
+                               if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
+                                       R_Q1BSP_DrawLight_TransparentBatch(ent, texture, batchnumsurfaces, batchsurfacelist);
+                               else
+                                       R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist);
                                batchnumsurfaces = 0;
                        }
                        tex = surface->texture;
                        texture = surface->texture->currentframe;
-                       // FIXME: transparent surfaces need to be lit later
-                       skip = (texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) != MATERIALFLAG_WALL;
+                       skip = (texture->currentmaterialflags & MATERIALFLAG_SKY) != 0;
                        if (skip)
                                continue;
-                       if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
-                               qglDisable(GL_CULL_FACE);
-                       else
-                               qglEnable(GL_CULL_FACE);
-                       glosstexture = r_texture_black;
-                       specularscale = 0;
-                       if (texture->skin.gloss)
-                       {
-                               if (r_shadow_gloss.integer >= 1 && r_shadow_glossintensity.value > 0 && r_shadow_rtlight->specularscale > 0)
-                               {
-                                       glosstexture = texture->skin.gloss;
-                                       specularscale = r_shadow_rtlight->specularscale * r_shadow_glossintensity.value;
-                               }
-                       }
-                       else
-                       {
-                               if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0 && r_shadow_glossintensity.value > 0 && r_shadow_rtlight->specularscale > 0)
-                               {
-                                       glosstexture = r_texture_white;
-                                       specularscale = r_shadow_rtlight->specularscale * r_shadow_gloss2intensity.value;
-                               }
-                       }
-                       basetexture = (ent->colormap < 0 && texture->skin.merged) ? texture->skin.merged : texture->skin.base;
-                       if ((r_shadow_rtlight->ambientscale + r_shadow_rtlight->diffusescale) * (VectorLength2(lightcolorbase) + VectorLength2(lightcolorpants) + VectorLength2(lightcolorshirt)) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
-                               skip = true;
                }
                if (!skip && surface->num_triangles)
                {
                        if (batchnumsurfaces == RSURF_MAX_BATCHSURFACES)
                        {
-                               R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, modelorg);
+                               if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
+                                       R_Q1BSP_DrawLight_TransparentBatch(ent, texture, batchnumsurfaces, batchsurfacelist);
+                               else
+                                       R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist);
                                batchnumsurfaces = 0;
                        }
                        batchsurfacelist[batchnumsurfaces++] = surface;
@@ -850,12 +847,72 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolorbase, float *light
        }
        if (batchnumsurfaces > 0)
        {
-               R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, modelorg);
+               if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
+                       R_Q1BSP_DrawLight_TransparentBatch(ent, texture, batchnumsurfaces, batchsurfacelist);
+               else
+                       R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist);
                batchnumsurfaces = 0;
        }
        qglEnable(GL_CULL_FACE);
 }
 
+//Made by [515]
+void R_ReplaceWorldTexture (void)
+{
+       model_t         *m;
+       texture_t       *t;
+       int                     i;
+       const char      *r, *newt;
+       m = r_refdef.worldmodel;
+
+       if(Cmd_Argc() < 2)
+       {
+               Con_Print("r_replacemaptexture <texname> <newtexname> - replaces texture\n");
+               Con_Print("r_replacemaptexture <texname> - switch back to default texture\n");
+               return;
+       }
+       if(!cl.islocalgame || !cl.worldmodel)
+       {
+               Con_Print("This command works only in singleplayer\n");
+               return;
+       }
+       r = Cmd_Argv(1);
+       newt = Cmd_Argv(2);
+       if(!newt[0])
+               newt = r;
+       for(i=0,t=m->data_textures;i<m->num_textures;i++,t++)
+       {
+               if(t->width && !strcasecmp(t->name, r))
+               {
+                       if(Mod_LoadSkinFrame(&t->skin, (char*)newt, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, false, r_fullbrights.integer))
+                       {
+                               Con_Printf("%s replaced with %s\n", r, newt);
+                               return;
+                       }
+                       else
+                       {
+                               Con_Printf("%s was not found\n", newt);
+                               Mod_LoadSkinFrame(&t->skin, (char*)r, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, false, r_fullbrights.integer);//back to default
+                               return;
+                       }
+               }
+       }
+}
+
+//Made by [515]
+void R_ListWorldTextures (void)
+{
+       model_t         *m;
+       texture_t       *t;
+       int                     i;
+       m = r_refdef.worldmodel;
+
+       Con_Print("Worldmodel textures :\n");
+       for(i=0,t=m->data_textures;i<m->num_textures;i++,t++)
+               if(t->skin.base != r_texture_notexture)
+                       Con_Printf("%s\n", t->name);
+}
+
 #if 0
 static void gl_surf_start(void)
 {
@@ -878,10 +935,11 @@ void GL_Surf_Init(void)
        Cvar_RegisterVariable(&r_lockpvs);
        Cvar_RegisterVariable(&r_lockvisibility);
        Cvar_RegisterVariable(&r_useportalculling);
-       Cvar_RegisterVariable(&r_drawcollisionbrushes_polygonfactor);
-       Cvar_RegisterVariable(&r_drawcollisionbrushes_polygonoffset);
        Cvar_RegisterVariable(&r_q3bsp_renderskydepth);
 
+       Cmd_AddCommand ("r_replacemaptexture", R_ReplaceWorldTexture, "override a map texture for testing purposes");   // By [515]
+       Cmd_AddCommand ("r_listmaptextures", R_ListWorldTextures, "list all textures used by the current map"); // By [515]
+
        //R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap);
 }