]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - gl_rsurf.c
reimplemented rtlight portal culling (used for compiled rtlights, and can be used...
[xonotic/darkplaces.git] / gl_rsurf.c
index 9bfd27e0b296c6fe026843d992a263d3c52dc91c..13b197a4ca1f790cbecc2478917ec5f506a5a4ba 100644 (file)
@@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 #include "r_shadow.h"
+#include "portals.h"
 
 #define MAX_LIGHTMAP_SIZE 256
 
@@ -469,7 +470,7 @@ static void R_DrawSurfaceList(const entity_render_t *ent, texture_t *texture, in
                                R_Sky();
                }
                // LordHavoc: HalfLife maps have freaky skypolys...
-               if (!ent->model->brush.ishlbsp)
+               //if (!ent->model->brush.ishlbsp)
                {
                        R_Mesh_Matrix(&ent->matrix);
                        GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
@@ -1593,7 +1594,7 @@ void R_WorldVisibility(void)
                return;
 
        // if possible find the leaf the view origin is in
-       viewleaf = model->brushq1.PointInLeaf ? model->brushq1.PointInLeaf(model, r_vieworigin) : NULL;
+       viewleaf = model->brush.PointInLeaf ? model->brush.PointInLeaf(model, r_vieworigin) : NULL;
        // if possible fetch the visible cluster bits
        if (model->brush.FatPVS)
                model->brush.FatPVS(model, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
@@ -1700,9 +1701,9 @@ typedef struct r_q1bsp_getlightinfo_s
        model_t *model;
        vec3_t relativelightorigin;
        float lightradius;
-       int *outclusterlist;
-       qbyte *outclusterpvs;
-       int outnumclusters;
+       int *outleaflist;
+       qbyte *outleafpvs;
+       int outnumleafs;
        int *outsurfacelist;
        qbyte *outsurfacepvs;
        int outnumsurfaces;
@@ -1742,12 +1743,13 @@ void R_Q1BSP_RecursiveGetLightInfo(r_q1bsp_getlightinfo_t *info, mnode_t *node)
                info->outmaxs[0] = max(info->outmaxs[0], leaf->maxs[0]);
                info->outmaxs[1] = max(info->outmaxs[1], leaf->maxs[1]);
                info->outmaxs[2] = max(info->outmaxs[2], leaf->maxs[2]);
-               if (info->outclusterpvs)
+               if (info->outleafpvs)
                {
-                       if (!CHECKPVSBIT(info->outclusterpvs, leaf->clusterindex))
+                       int leafindex = leaf - info->model->brush.data_leafs;
+                       if (!CHECKPVSBIT(info->outleafpvs, leafindex))
                        {
-                               SETPVSBIT(info->outclusterpvs, leaf->clusterindex);
-                               info->outclusterlist[info->outnumclusters++] = leaf->clusterindex;
+                               SETPVSBIT(info->outleafpvs, leafindex);
+                               info->outleaflist[info->outnumleafs++] = leafindex;
                        }
                }
                if (info->outsurfacepvs)
@@ -1770,7 +1772,7 @@ void R_Q1BSP_RecursiveGetLightInfo(r_q1bsp_getlightinfo_t *info, mnode_t *node)
                                                        v[0] = info->model->brush.shadowmesh->vertex3f + e[0] * 3;
                                                        v[1] = info->model->brush.shadowmesh->vertex3f + e[1] * 3;
                                                        v[2] = info->model->brush.shadowmesh->vertex3f + e[2] * 3;
-                                                       if (info->lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && info->lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && info->lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && info->lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && info->lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && info->lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+                                                       if (PointInfrontOfTriangle(info->relativelightorigin, v[0], v[1], v[2]) && info->lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && info->lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && info->lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && info->lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && info->lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && info->lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
                                                        {
                                                                SETPVSBIT(info->outsurfacepvs, surfaceindex);
                                                                info->outsurfacelist[info->outnumsurfaces++] = surfaceindex;
@@ -1784,53 +1786,66 @@ void R_Q1BSP_RecursiveGetLightInfo(r_q1bsp_getlightinfo_t *info, mnode_t *node)
        }
 }
 
-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)
+void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, qbyte *outleafpvs, int *outnumleafspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer)
 {
        r_q1bsp_getlightinfo_t info;
+       VectorCopy(relativelightorigin, info.relativelightorigin);
+       info.lightradius = lightradius;
+       info.lightmins[0] = info.relativelightorigin[0] - info.lightradius;
+       info.lightmins[1] = info.relativelightorigin[1] - info.lightradius;
+       info.lightmins[2] = info.relativelightorigin[2] - info.lightradius;
+       info.lightmaxs[0] = info.relativelightorigin[0] + info.lightradius;
+       info.lightmaxs[1] = info.relativelightorigin[1] + info.lightradius;
+       info.lightmaxs[2] = info.relativelightorigin[2] + info.lightradius;
        if (ent->model == NULL)
        {
                VectorCopy(info.lightmins, outmins);
                VectorCopy(info.lightmaxs, outmaxs);
-               *outnumclusterspointer = 0;
+               *outnumleafspointer = 0;
                *outnumsurfacespointer = 0;
                return;
        }
        info.model = ent->model;
-       VectorCopy(relativelightorigin, info.relativelightorigin);
-       info.lightradius = lightradius;
-       info.outclusterlist = outclusterlist;
-       info.outclusterpvs = outclusterpvs;
-       info.outnumclusters = 0;
+       info.outleaflist = outleaflist;
+       info.outleafpvs = outleafpvs;
+       info.outnumleafs = 0;
        info.outsurfacelist = outsurfacelist;
        info.outsurfacepvs = outsurfacepvs;
        info.outnumsurfaces = 0;
-       info.lightmins[0] = info.relativelightorigin[0] - lightradius;
-       info.lightmins[1] = info.relativelightorigin[1] - lightradius;
-       info.lightmins[2] = info.relativelightorigin[2] - lightradius;
-       info.lightmaxs[0] = info.relativelightorigin[0] + lightradius;
-       info.lightmaxs[1] = info.relativelightorigin[1] + lightradius;
-       info.lightmaxs[2] = info.relativelightorigin[2] + lightradius;
        VectorCopy(info.relativelightorigin, info.outmins);
        VectorCopy(info.relativelightorigin, info.outmaxs);
-       memset(outclusterpvs, 0, info.model->brush.num_pvsclusterbytes);
+       memset(outleafpvs, 0, (info.model->brush.num_leafs + 7) >> 3);
        memset(outsurfacepvs, 0, (info.model->nummodelsurfaces + 7) >> 3);
        if (info.model->brush.GetPVS)
                info.pvs = info.model->brush.GetPVS(info.model, info.relativelightorigin);
        else
                info.pvs = NULL;
        R_UpdateAllTextureInfo(ent);
-       // use BSP recursion as lights are often small
-       R_Q1BSP_RecursiveGetLightInfo(&info, info.model->brush.data_nodes);
+       if (r_shadow_compilingrtlight)
+       {
+               // use portal recursion for exact light volume culling, and exact surface checking
+               Portal_Visibility(info.model, info.relativelightorigin, info.outleaflist, info.outleafpvs, &info.outnumleafs, info.outsurfacelist, info.outsurfacepvs, &info.outnumsurfaces, NULL, 0, true, info.lightmins, info.lightmaxs, info.outmins, info.outmaxs);
+       }
+       else if (r_shadow_realtime_dlight_portalculling.integer)
+       {
+               // use portal recursion for exact light volume culling, but not the expensive exact surface checking
+               Portal_Visibility(info.model, info.relativelightorigin, info.outleaflist, info.outleafpvs, &info.outnumleafs, info.outsurfacelist, info.outsurfacepvs, &info.outnumsurfaces, NULL, 0, r_shadow_realtime_dlight_portalculling.integer >= 2, info.lightmins, info.lightmaxs, info.outmins, info.outmaxs);
+       }
+       else
+       {
+               // use BSP recursion as lights are often small
+               R_Q1BSP_RecursiveGetLightInfo(&info, info.model->brush.data_nodes);
+       }
 
        // limit combined leaf box to light boundaries
-       outmins[0] = max(info.outmins[0], info.lightmins[0]);
-       outmins[1] = max(info.outmins[1], info.lightmins[1]);
-       outmins[2] = max(info.outmins[2], info.lightmins[2]);
-       outmaxs[0] = min(info.outmaxs[0], info.lightmaxs[0]);
-       outmaxs[1] = min(info.outmaxs[1], info.lightmaxs[1]);
-       outmaxs[2] = min(info.outmaxs[2], info.lightmaxs[2]);
-
-       *outnumclusterspointer = info.outnumclusters;
+       outmins[0] = max(info.outmins[0] - 1, info.lightmins[0]);
+       outmins[1] = max(info.outmins[1] - 1, info.lightmins[1]);
+       outmins[2] = max(info.outmins[2] - 1, info.lightmins[2]);
+       outmaxs[0] = min(info.outmaxs[0] + 1, info.lightmaxs[0]);
+       outmaxs[1] = min(info.outmaxs[1] + 1, info.lightmaxs[1]);
+       outmaxs[2] = min(info.outmaxs[2] + 1, info.lightmaxs[2]);
+
+       *outnumleafspointer = info.outnumleafs;
        *outnumsurfacespointer = info.outnumsurfaces;
 }
 
@@ -1858,7 +1873,7 @@ void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin,
        }
 }
 
-void R_Q1BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int numsurfaces, const int *surfacelist)
+void R_Q1BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int numsurfaces, const int *surfacelist, int visiblelighting)
 {
        model_t *model = ent->model;
        msurface_t *surface;
@@ -1879,7 +1894,27 @@ 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->basematerialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL)
+                               {
+#if 1
+                                       int tri;
+                                       int *e;
+                                       float *lightmins, *lightmaxs, *v[3], *vertex3f;
+                                       e = surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle;
+                                       vertex3f = surface->groupmesh->data_vertex3f;
+                                       lightmins = r_shadow_compilingrtlight->cullmins;
+                                       lightmaxs = r_shadow_compilingrtlight->cullmaxs;
+                                       for (tri = 0;tri < surface->num_triangles;tri++, e += 3)
+                                       {
+                                               v[0] = vertex3f + e[0] * 3;
+                                               v[1] = vertex3f + e[1] * 3;
+                                               v[2] = vertex3f + e[2] * 3;
+                                               if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+                                                       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->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, 1, e);
+                                       }
+#else
                                        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->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+#endif
+                               }
                        }
                        else if (ent != r_refdef.worldentity || r_worldsurfacevisible[surfacelist[surfacelistindex]])
                        {
@@ -1889,7 +1924,7 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t
                                {
                                        if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
                                                qglDisable(GL_CULL_FACE);
-                                       R_Shadow_RenderLighting(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle), surface->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, t->skin.gloss, lightcubemap, ambientscale, diffusescale, specularscale);
+                                       R_Shadow_RenderLighting(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle), surface->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, NULL, NULL, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, NULL, NULL, t->skin.nmap, t->skin.gloss, lightcubemap, ambientscale, diffusescale, specularscale, visiblelighting);
                                        if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
                                                qglEnable(GL_CULL_FACE);
                                }