]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
collision code cleanups (model->brush.TraceBox is now used for everything except...
[xonotic/darkplaces.git] / r_shadow.c
index dcb2b3a35d19e2891eb3d18da5557459e5e999e7..6362eb05aed6b42f5038e40a6afb2b6ddddd232a 100644 (file)
@@ -145,6 +145,8 @@ cvar_t r_shadow_realtime_world = {0, "r_shadow_realtime_world", "0"};
 cvar_t r_shadow_realtime_dlight = {0, "r_shadow_realtime_dlight", "0"};
 cvar_t r_shadow_visiblevolumes = {0, "r_shadow_visiblevolumes", "0"};
 cvar_t r_shadow_gloss = {0, "r_shadow_gloss", "1"};
+cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1"};
+cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.25"};
 cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1"};
 cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1"};
 cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4"};
@@ -227,6 +229,8 @@ void R_Shadow_Init(void)
        Cvar_RegisterVariable(&r_shadow_realtime_dlight);
        Cvar_RegisterVariable(&r_shadow_visiblevolumes);
        Cvar_RegisterVariable(&r_shadow_gloss);
+       Cvar_RegisterVariable(&r_shadow_glossintensity);
+       Cvar_RegisterVariable(&r_shadow_gloss2intensity);
        Cvar_RegisterVariable(&r_shadow_debuglight);
        Cvar_RegisterVariable(&r_shadow_scissor);
        Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
@@ -270,6 +274,38 @@ int *R_Shadow_ResizeShadowElements(int numtris)
        return shadowelements;
 }
 
+/*
+// readable version of some code found below
+int checkcastshadowfromedge(int t, int i)
+{
+       int *te;
+       float *v[3];
+       if (t >= trianglerange_start && t < trianglerange_end)
+       {
+               if (t < i && !trianglefacinglight[t])
+                       return true;
+               else
+                       return false;
+       }
+       else
+       {
+               if (t < 0)
+                       return true;
+               else
+               {
+                       te = inelement3i + t * 3;
+                       v[0] = invertex3f + te[0] * 3;
+                       v[1] = invertex3f + te[1] * 3;
+                       v[2] = invertex3f + te[2] * 3;
+                       if (!PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]))))
+                               return true;
+                       else
+                               return false;
+               }
+       }
+}
+*/
+
 int R_Shadow_ConstructShadowVolume(int innumvertices, int trianglerange_start, int trianglerange_end, const int *inelement3i, const int *inneighbor3i, const float *invertex3f, int *outnumvertices, int *outelement3i, float *outvertex3f, const float *relativelightorigin, float projectdistance)
 {
        int i, j, tris = 0, numfacing = 0, vr[3], t, outvertices = 0;
@@ -446,12 +482,12 @@ int R_Shadow_ConstructShadowVolume(int innumvertices, int trianglerange_start, i
                                        }
                                }
                                // output the front and back triangles
-                               outelement3i[3] = vertexremap[e[0]];
-                               outelement3i[4] = vertexremap[e[1]];
-                               outelement3i[5] = vertexremap[e[2]];
-                               outelement3i[0] = vertexremap[e[2]] + 1;
-                               outelement3i[1] = vertexremap[e[1]] + 1;
-                               outelement3i[2] = vertexremap[e[0]] + 1;
+                               outelement3i[0] = vertexremap[e[0]];
+                               outelement3i[1] = vertexremap[e[1]];
+                               outelement3i[2] = vertexremap[e[2]];
+                               outelement3i[3] = vertexremap[e[2]] + 1;
+                               outelement3i[4] = vertexremap[e[1]] + 1;
+                               outelement3i[5] = vertexremap[e[0]] + 1;
                                outelement3i += 6;
                                tris += 2;
                        }
@@ -532,7 +568,7 @@ void R_Shadow_Volume(int numverts, int numtris, const float *invertex3f, int *el
        // triangle elements and vertices...  by clever use of elements we
        // can construct the whole shadow from the unprojected vertices and
        // the projected vertices
-       if ((tris = R_Shadow_ConstructShadowVolume(numverts, 0, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, varray_vertex3f2, relativelightorigin, projectdistance)))
+       if ((tris = R_Shadow_ConstructShadowVolume(numverts, 0, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, varray_vertex3f2, relativelightorigin, r_shadow_projectdistance.value/*projectdistance*/)))
        {
                GL_VertexPointer(varray_vertex3f2);
                if (r_shadowstage == SHADOWSTAGE_STENCIL)
@@ -556,8 +592,6 @@ void R_Shadow_Volume(int numverts, int numtris, const float *invertex3f, int *el
 void R_Shadow_RenderShadowMeshVolume(shadowmesh_t *firstmesh)
 {
        shadowmesh_t *mesh;
-       rmeshstate_t m;
-       memset(&m, 0, sizeof(m));
        if (r_shadowstage == SHADOWSTAGE_STENCIL)
        {
                // increment stencil if backface is behind depthbuffer
@@ -719,21 +753,19 @@ void R_Shadow_Stage_Begin(void)
        if (r_shadow_texture3d.integer && !gl_texture3d)
                Cvar_SetValueQuick(&r_shadow_texture3d, 0);
 
-       //cl.worldmodel->numlights = min(cl.worldmodel->numlights, 1);
+       //cl.worldmodel->brushq1.numlights = min(cl.worldmodel->brushq1.numlights, 1);
        if (!r_shadow_attenuation2dtexture
         || (!r_shadow_attenuation3dtexture && r_shadow_texture3d.integer)
         || r_shadow_lightattenuationpower.value != r_shadow_attenpower
         || r_shadow_lightattenuationscale.value != r_shadow_attenscale)
                R_Shadow_MakeTextures();
 
+       memset(&m, 0, sizeof(m));
        GL_BlendFunc(GL_ONE, GL_ZERO);
        GL_DepthMask(false);
        GL_DepthTest(true);
-       GL_Color(0, 0, 0, 1);
-
-       memset(&m, 0, sizeof(m));
        R_Mesh_State_Texture(&m);
-
+       GL_Color(0, 0, 0, 1);
        qglDisable(GL_SCISSOR_TEST);
        r_shadowstage = SHADOWSTAGE_NONE;
 
@@ -761,15 +793,13 @@ void R_Shadow_LoadWorldLightsIfNeeded(void)
 void R_Shadow_Stage_ShadowVolumes(void)
 {
        rmeshstate_t m;
-
        memset(&m, 0, sizeof(m));
        R_Mesh_State_Texture(&m);
-
        GL_Color(1, 1, 1, 1);
+       qglColorMask(0, 0, 0, 0);
        GL_BlendFunc(GL_ONE, GL_ZERO);
        GL_DepthMask(false);
        GL_DepthTest(true);
-
        if (r_shadow_polygonoffset.value != 0)
        {
                qglPolygonOffset(1.0f, r_shadow_polygonoffset.value);
@@ -777,13 +807,11 @@ void R_Shadow_Stage_ShadowVolumes(void)
        }
        else
                qglDisable(GL_POLYGON_OFFSET_FILL);
-       qglColorMask(0, 0, 0, 0);
        qglDepthFunc(GL_LESS);
        qglEnable(GL_STENCIL_TEST);
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        qglStencilFunc(GL_ALWAYS, 128, 0xFF);
        r_shadowstage = SHADOWSTAGE_STENCIL;
-
        qglClear(GL_STENCIL_BUFFER_BIT);
        c_rt_clears++;
        // LordHavoc note: many shadow volumes reside entirely inside the world
@@ -798,24 +826,18 @@ void R_Shadow_Stage_ShadowVolumes(void)
 void R_Shadow_Stage_LightWithoutShadows(void)
 {
        rmeshstate_t m;
-
        memset(&m, 0, sizeof(m));
        R_Mesh_State_Texture(&m);
-
-       GL_Color(1, 1, 1, 1);
        GL_BlendFunc(GL_ONE, GL_ONE);
        GL_DepthMask(false);
        GL_DepthTest(true);
        qglDisable(GL_POLYGON_OFFSET_FILL);
-
-       //GL_DepthTest(false);
-
+       GL_Color(1, 1, 1, 1);
        qglColorMask(1, 1, 1, 1);
-       qglDepthFunc(GL_LEQUAL);
+       qglDepthFunc(GL_EQUAL);
        qglDisable(GL_STENCIL_TEST);
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        qglStencilFunc(GL_EQUAL, 128, 0xFF);
-
        r_shadowstage = SHADOWSTAGE_LIGHT;
        c_rt_lights++;
 }
@@ -823,26 +845,20 @@ void R_Shadow_Stage_LightWithoutShadows(void)
 void R_Shadow_Stage_LightWithShadows(void)
 {
        rmeshstate_t m;
-
        memset(&m, 0, sizeof(m));
        R_Mesh_State_Texture(&m);
-
-       GL_Color(1, 1, 1, 1);
        GL_BlendFunc(GL_ONE, GL_ONE);
        GL_DepthMask(false);
        GL_DepthTest(true);
        qglDisable(GL_POLYGON_OFFSET_FILL);
-
-       //GL_DepthTest(false);
-
+       GL_Color(1, 1, 1, 1);
        qglColorMask(1, 1, 1, 1);
-       qglDepthFunc(GL_LEQUAL);
+       qglDepthFunc(GL_EQUAL);
        qglEnable(GL_STENCIL_TEST);
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        // only draw light where this geometry was already rendered AND the
        // stencil is 128 (values other than this mean shadow)
        qglStencilFunc(GL_EQUAL, 128, 0xFF);
-
        r_shadowstage = SHADOWSTAGE_LIGHT;
        c_rt_lights++;
 }
@@ -850,23 +866,19 @@ void R_Shadow_Stage_LightWithShadows(void)
 void R_Shadow_Stage_End(void)
 {
        rmeshstate_t m;
-
        memset(&m, 0, sizeof(m));
        R_Mesh_State_Texture(&m);
-
-       GL_Color(1, 1, 1, 1);
        GL_BlendFunc(GL_ONE, GL_ZERO);
        GL_DepthMask(true);
        GL_DepthTest(true);
        qglDisable(GL_POLYGON_OFFSET_FILL);
-
+       GL_Color(1, 1, 1, 1);
        qglColorMask(1, 1, 1, 1);
        qglDisable(GL_SCISSOR_TEST);
        qglDepthFunc(GL_LEQUAL);
        qglDisable(GL_STENCIL_TEST);
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        qglStencilFunc(GL_ALWAYS, 128, 0xFF);
-
        r_shadowstage = SHADOWSTAGE_NONE;
 }
 
@@ -1587,16 +1599,19 @@ void R_Shadow_DiffuseLighting(int numverts, int numtriangles, const int *element
 void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elements, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const float *texcoord2f, const float *relativelightorigin, const float *relativeeyeorigin, float lightradius, const float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *glosstexture, rtexture_t *bumptexture, rtexture_t *lightcubemap)
 {
        int renders;
-       float color[3], color2[3];
+       float color[3], color2[3], colorscale;
        rmeshstate_t m;
        if (!gl_dot3arb || !gl_texturecubemap || !gl_combine.integer || !gl_stencil)
                return;
-       if (!bumptexture)
-               bumptexture = r_shadow_blankbumptexture;
        if (!glosstexture)
                glosstexture = r_shadow_blankglosstexture;
        if (r_shadow_gloss.integer >= 2 || (r_shadow_gloss.integer >= 1 && glosstexture != r_shadow_blankglosstexture))
        {
+               colorscale = r_colorscale * r_shadow_glossintensity.value;
+               if (!bumptexture)
+                       bumptexture = r_shadow_blankbumptexture;
+               if (glosstexture == r_shadow_blankglosstexture)
+                       colorscale *= r_shadow_gloss2intensity.value;
                GL_VertexPointer(vertex3f);
                GL_Color(1,1,1,1);
                if (r_shadow_texture3d.integer && r_textureunits.integer >= 2 && lightcubemap /*&& gl_support_blendsquare*/) // FIXME: detect blendsquare!
@@ -1652,7 +1667,7 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen
                        GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
                        if (lightcubemap)
                                R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter);
-                       VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value * 0.25f, color2);
+                       VectorScale(lightcolor, colorscale, color2);
                        for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
                        {
                                color[0] = bound(0, color2[0], 1);
@@ -1706,7 +1721,7 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen
                        qglColorMask(1,1,1,0);
                        GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
                        R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltoattenuationxyz);
-                       VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value * 0.25f, color2);
+                       VectorScale(lightcolor, colorscale, color2);
                        for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
                        {
                                color[0] = bound(0, color2[0], 1);
@@ -1774,7 +1789,7 @@ void R_Shadow_SpecularLighting(int numverts, int numtriangles, const int *elemen
                        GL_BlendFunc(GL_DST_ALPHA, GL_ONE);
                        if (lightcubemap)
                                R_Shadow_Transform_Vertex3f_TexCoord3f(varray_texcoord3f[1], numverts, vertex3f, matrix_modeltofilter);
-                       VectorScale(lightcolor, r_colorscale * r_shadow_lightintensityscale.value * 0.25f, color2);
+                       VectorScale(lightcolor, colorscale, color2);
                        for (renders = 0;renders < 64 && (color2[0] > 0 || color2[1] > 0 || color2[2] > 0);renders++, color2[0]--, color2[1]--, color2[2]--)
                        {
                                color[0] = bound(0, color2[0], 1);
@@ -1855,22 +1870,22 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style
        if (cl.worldmodel)
        {
                castshadowcount++;
-               i = Mod_PointContents(e->origin, cl.worldmodel);
+               i = CL_PointContents(e->origin);
                if (r_shadow_portallight.integer && i != CONTENTS_SOLID && i != CONTENTS_SKY)
                {
                        qbyte *byteleafpvs;
                        qbyte *bytesurfacepvs;
 
-                       byteleafpvs = Mem_Alloc(tempmempool, cl.worldmodel->numleafs + 1);
-                       bytesurfacepvs = Mem_Alloc(tempmempool, cl.worldmodel->numsurfaces);
+                       byteleafpvs = Mem_Alloc(tempmempool, cl.worldmodel->brushq1.numleafs + 1);
+                       bytesurfacepvs = Mem_Alloc(tempmempool, cl.worldmodel->brushq1.numsurfaces);
 
                        Portal_Visibility(cl.worldmodel, e->origin, byteleafpvs, bytesurfacepvs, NULL, 0, true, RadiusFromBoundsAndOrigin(e->mins, e->maxs, e->origin));
 
-                       for (i = 0, leaf = cl.worldmodel->leafs + 1;i < cl.worldmodel->numleafs;i++, leaf++)
+                       for (i = 0, leaf = cl.worldmodel->brushq1.leafs + 1;i < cl.worldmodel->brushq1.numleafs;i++, leaf++)
                                if (byteleafpvs[i+1] && BoxesOverlap(leaf->mins, leaf->maxs, e->mins, e->maxs))
                                        leaf->worldnodeframe = castshadowcount;
 
-                       for (i = 0, surf = cl.worldmodel->surfaces;i < cl.worldmodel->numsurfaces;i++, surf++)
+                       for (i = 0, surf = cl.worldmodel->brushq1.surfaces;i < cl.worldmodel->brushq1.numsurfaces;i++, surf++)
                                if (bytesurfacepvs[i] && BoxesOverlap(surf->poly_mins, surf->poly_maxs, e->mins, e->maxs))
                                        surf->castshadow = castshadowcount;
 
@@ -1879,16 +1894,16 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style
                }
                else
                {
-                       leaf = Mod_PointInLeaf(origin, cl.worldmodel);
-                       pvs = Mod_LeafPVS(leaf, cl.worldmodel);
-                       for (i = 0, leaf = cl.worldmodel->leafs + 1;i < cl.worldmodel->numleafs;i++, leaf++)
+                       leaf = cl.worldmodel->brushq1.PointInLeaf(cl.worldmodel, origin);
+                       pvs = cl.worldmodel->brushq1.LeafPVS(cl.worldmodel, leaf);
+                       for (i = 0, leaf = cl.worldmodel->brushq1.leafs + 1;i < cl.worldmodel->brushq1.numleafs;i++, leaf++)
                        {
                                if (pvs[i >> 3] & (1 << (i & 7)) && BoxesOverlap(leaf->mins, leaf->maxs, e->mins, e->maxs))
                                {
                                        leaf->worldnodeframe = castshadowcount;
                                        for (j = 0, mark = leaf->firstmarksurface;j < leaf->nummarksurfaces;j++, mark++)
                                        {
-                                               surf = cl.worldmodel->surfaces + *mark;
+                                               surf = cl.worldmodel->brushq1.surfaces + *mark;
                                                if (surf->castshadow != castshadowcount && BoxesOverlap(surf->poly_mins, surf->poly_maxs, e->mins, e->maxs))
                                                        surf->castshadow = castshadowcount;
                                        }
@@ -1897,11 +1912,11 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style
                }
 
                e->numleafs = 0;
-               for (i = 0, leaf = cl.worldmodel->leafs + 1;i < cl.worldmodel->numleafs;i++, leaf++)
+               for (i = 0, leaf = cl.worldmodel->brushq1.leafs + 1;i < cl.worldmodel->brushq1.numleafs;i++, leaf++)
                        if (leaf->worldnodeframe == castshadowcount)
                                e->numleafs++;
                e->numsurfaces = 0;
-               for (i = 0, surf = cl.worldmodel->surfaces + cl.worldmodel->firstmodelsurface;i < cl.worldmodel->nummodelsurfaces;i++, surf++)
+               for (i = 0, surf = cl.worldmodel->brushq1.surfaces + cl.worldmodel->brushq1.firstmodelsurface;i < cl.worldmodel->brushq1.nummodelsurfaces;i++, surf++)
                        if (surf->castshadow == castshadowcount)
                                e->numsurfaces++;
 
@@ -1910,11 +1925,11 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style
                if (e->numsurfaces)
                        e->surfaces = Mem_Alloc(r_shadow_mempool, e->numsurfaces * sizeof(msurface_t *));
                e->numleafs = 0;
-               for (i = 0, leaf = cl.worldmodel->leafs + 1;i < cl.worldmodel->numleafs;i++, leaf++)
+               for (i = 0, leaf = cl.worldmodel->brushq1.leafs + 1;i < cl.worldmodel->brushq1.numleafs;i++, leaf++)
                        if (leaf->worldnodeframe == castshadowcount)
                                e->leafs[e->numleafs++] = leaf;
                e->numsurfaces = 0;
-               for (i = 0, surf = cl.worldmodel->surfaces + cl.worldmodel->firstmodelsurface;i < cl.worldmodel->nummodelsurfaces;i++, surf++)
+               for (i = 0, surf = cl.worldmodel->brushq1.surfaces + cl.worldmodel->brushq1.firstmodelsurface;i < cl.worldmodel->brushq1.nummodelsurfaces;i++, surf++)
                        if (surf->castshadow == castshadowcount)
                                e->surfaces[e->numsurfaces++] = surf;
 
@@ -2245,7 +2260,7 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
                Con_Printf("No map loaded.\n");
                return;
        }
-       data = cl.worldmodel->entities;
+       data = cl.worldmodel->brush.entities;
        if (!data)
                return;
        for (entnum = 0;COM_ParseToken(&data) && com_token[0] == '{';entnum++)