]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_shadow.c
Hopefully finished the core of the new ui.
[xonotic/darkplaces.git] / r_shadow.c
index 1826d96cceeaa2a90ff3c1d1f00d6fcc17482daf..9a9071a853434108c9eb4a4b62446d692ca98fd5 100644 (file)
@@ -14,7 +14,16 @@ did not intersect the visible geometry, suitable as a stencil mask for
 rendering lighting everywhere but shadow.
 
 In our case we use a biased stencil clear of 128 to avoid requiring the
-stencil wrap extension (but probably should support it).
+stencil wrap extension (but probably should support it), and to address
+Creative's patent on this sort of technology we also draw the frontfaces
+first, and backfaces second (decrement, increment).
+
+Patent warning:
+This algorithm may be covered by Creative's patent (US Patent #6384822)
+on Carmack's Reverse paper (which I have not read), however that patent
+seems to be about drawing a stencil shadow from a model in an otherwise
+unshadowed scene, where as realtime lighting technology draws light where
+shadows do not lie.
 
 
 
@@ -626,15 +635,15 @@ void R_Shadow_Volume(int numverts, int numtris, const float *invertex3f, int *el
                GL_VertexPointer(varray_vertex3f2);
                if (r_shadowstage == SHADOWSTAGE_STENCIL)
                {
-                       // increment stencil if backface is behind depthbuffer
-                       qglCullFace(GL_BACK); // quake is backwards, this culls front faces
-                       qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
-                       R_Mesh_Draw(outverts, tris, shadowelements);
-                       c_rt_shadowmeshes++;
-                       c_rt_shadowtris += numtris;
                        // decrement stencil if frontface is behind depthbuffer
                        qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
                        qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
+                       R_Mesh_Draw(outverts, tris, shadowelements);
+                       c_rt_shadowmeshes++;
+                       c_rt_shadowtris += numtris;
+                       // increment stencil if backface is behind depthbuffer
+                       qglCullFace(GL_BACK); // quake is backwards, this culls front faces
+                       qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
                }
                R_Mesh_Draw(outverts, tris, shadowelements);
                c_rt_shadowmeshes++;
@@ -647,9 +656,9 @@ void R_Shadow_RenderShadowMeshVolume(shadowmesh_t *firstmesh)
        shadowmesh_t *mesh;
        if (r_shadowstage == SHADOWSTAGE_STENCIL)
        {
-               // increment stencil if backface is behind depthbuffer
-               qglCullFace(GL_BACK); // quake is backwards, this culls front faces
-               qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
+               // decrement stencil if frontface is behind depthbuffer
+               qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
+               qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
                for (mesh = firstmesh;mesh;mesh = mesh->next)
                {
                        GL_VertexPointer(mesh->vertex3f);
@@ -657,9 +666,9 @@ void R_Shadow_RenderShadowMeshVolume(shadowmesh_t *firstmesh)
                        c_rtcached_shadowmeshes++;
                        c_rtcached_shadowtris += mesh->numtriangles;
                }
-               // decrement stencil if frontface is behind depthbuffer
-               qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
-               qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
+               // increment stencil if backface is behind depthbuffer
+               qglCullFace(GL_BACK); // quake is backwards, this culls front faces
+               qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
        }
        for (mesh = firstmesh;mesh;mesh = mesh->next)
        {
@@ -818,6 +827,7 @@ void R_Shadow_Stage_Begin(void)
        GL_DepthTest(true);
        R_Mesh_State_Texture(&m);
        GL_Color(0, 0, 0, 1);
+       qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
        qglDisable(GL_SCISSOR_TEST);
        r_shadowstage = SHADOWSTAGE_NONE;
 
@@ -860,6 +870,7 @@ void R_Shadow_Stage_ShadowVolumes(void)
        else
                qglDisable(GL_POLYGON_OFFSET_FILL);
        qglDepthFunc(GL_LESS);
+       qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
        qglEnable(GL_STENCIL_TEST);
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        qglStencilFunc(GL_ALWAYS, 128, 0xFF);
@@ -887,6 +898,7 @@ void R_Shadow_Stage_LightWithoutShadows(void)
        GL_Color(1, 1, 1, 1);
        qglColorMask(1, 1, 1, 1);
        qglDepthFunc(GL_EQUAL);
+       qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
        qglDisable(GL_STENCIL_TEST);
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        qglStencilFunc(GL_EQUAL, 128, 0xFF);
@@ -906,6 +918,7 @@ void R_Shadow_Stage_LightWithShadows(void)
        GL_Color(1, 1, 1, 1);
        qglColorMask(1, 1, 1, 1);
        qglDepthFunc(GL_EQUAL);
+       qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
        qglEnable(GL_STENCIL_TEST);
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        // only draw light where this geometry was already rendered AND the
@@ -928,6 +941,7 @@ void R_Shadow_Stage_End(void)
        qglColorMask(1, 1, 1, 1);
        qglDisable(GL_SCISSOR_TEST);
        qglDepthFunc(GL_LEQUAL);
+       qglCullFace(GL_FRONT); // quake is backwards, this culls back faces
        qglDisable(GL_STENCIL_TEST);
        qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        qglStencilFunc(GL_ALWAYS, 128, 0xFF);
@@ -1877,12 +1891,12 @@ void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style
                                if (face->lighttemp_castshadow)
                                {
                                        face->lighttemp_castshadow = false;
-                                       if (!(face->texture->renderflags & (Q3MTEXTURERENDERFLAGS_NODRAW | Q3MTEXTURERENDERFLAGS_SKY)))
+                                       if (!(face->texture->surfaceflags & (Q3SURFACEFLAG_NODRAW | Q3SURFACEFLAG_SKY)))
                                        {
                                                if (e->castshadows)
                                                        if (!(face->texture->nativecontents & CONTENTSQ3_TRANSLUCENT))
                                                                Mod_ShadowMesh_AddMesh(r_shadow_mempool, castmesh, NULL, NULL, NULL, face->data_vertex3f, NULL, NULL, NULL, NULL, face->num_triangles, face->data_element3i);
-                                               if (!(face->texture->renderflags & (Q3MTEXTURERENDERFLAGS_SKY)))
+                                               if (!(face->texture->surfaceflags & Q3SURFACEFLAG_SKY))
                                                        Mod_ShadowMesh_AddMesh(r_shadow_mempool, e->meshchain_light, face->texture->skin.base, face->texture->skin.gloss, face->texture->skin.nmap, face->data_vertex3f, face->data_svector3f, face->data_tvector3f, face->data_normal3f, face->data_texcoordtexture2f, face->num_triangles, face->data_element3i);
                                        }
                                }
@@ -2259,7 +2273,7 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
 {
        int entnum, style, islight;
        char key[256], value[1024];
-       float origin[3], radius, color[3], light, scale, originhack[3], overridecolor[3];
+       float origin[3], radius, color[3], light, fadescale, lightscale, originhack[3], overridecolor[3];
        const char *data;
 
        if (cl.worldmodel == NULL)
@@ -2277,7 +2291,8 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
                originhack[0] = originhack[1] = originhack[2] = 0;
                color[0] = color[1] = color[2] = 1;
                overridecolor[0] = overridecolor[1] = overridecolor[2] = 1;
-               scale = 1;
+               fadescale = 1;
+               lightscale = 1;
                style = 0;
                islight = false;
                while (1)
@@ -2304,7 +2319,7 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
                        else if (!strcmp("color", key))
                                sscanf(value, "%f %f %f", &color[0], &color[1], &color[2]);
                        else if (!strcmp("wait", key))
-                               scale = atof(value);
+                               fadescale = atof(value);
                        else if (!strcmp("classname", key))
                        {
                                if (!strncmp(value, "light", 5))
@@ -2377,10 +2392,21 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void)
                        }
                        else if (!strcmp("style", key))
                                style = atoi(value);
+                       else if (cl.worldmodel->type == mod_brushq3)
+                       {
+                               if (!strcmp("scale", key))
+                                       lightscale = atof(value);
+                               if (!strcmp("fade", key))
+                                       fadescale = atof(value);
+                       }
                }
                if (light <= 0 && islight)
                        light = 300;
-               radius = min(light * r_editlights_quakelightsizescale.value / scale, 1048576);
+               if (lightscale <= 0)
+                       lightscale = 1;
+               if (fadescale <= 0)
+                       fadescale = 1;
+               radius = min(light * r_editlights_quakelightsizescale.value * lightscale / fadescale, 1048576);
                light = sqrt(bound(0, light, 1048576)) * (1.0f / 16.0f);
                if (color[0] == 1 && color[1] == 1 && color[2] == 1)
                        VectorCopy(overridecolor, color);