]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
shadow volume rendering still very incomplete, but works mostly
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 4 Oct 2002 13:52:01 +0000 (13:52 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 4 Oct 2002 13:52:01 +0000 (13:52 +0000)
committing this before I add 3D textures to the texture manager
(alert: this is the last version of the stencil shadow rendering that will work with TNT class hardware (and not well), 3D textures will be required and will not work on TNT class... sorry.  vertex just looks too horrible)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2496 d7cf8633-e32d-0410-b094-e92efae38249

13 files changed:
gl_models.c
gl_rmain.c
gl_rsurf.c
model_alias.c
model_brush.c
model_brush.h
model_shared.c
model_shared.h
model_sprite.c
r_shadow.c
r_shadow.h
r_sprites.c
render.h

index ceb9b5bf9cce1cdf0ec2faf6ae79340afb733b2d..a0a077b3cf038200fc3c42a6ef56e06b9660035c 100644 (file)
@@ -438,20 +438,21 @@ void R_DrawQ1Q2AliasModelCallback (const void *calldata1, int calldata2)
        }
 }
 
-void R_DrawQ1Q2AliasModelShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume)
+void R_Model_Alias_Draw(entity_render_t *ent)
 {
-       float projectdistance;
-       projectdistance = lightradius + ent->model->radius - sqrt(DotProduct(relativelightorigin, relativelightorigin));
-       if (projectdistance > 0.1)
-       {
-               R_Mesh_ResizeCheck(ent->model->numverts * 2);
-               R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
-               R_Shadow_Volume(ent->model->numverts, ent->model->numtris, varray_vertex, ent->model->mdlmd2data_indices, ent->model->mdlmd2data_triangleneighbors, relativelightorigin, lightradius, projectdistance, visiblevolume);
-       }
+       if (ent->alpha < (1.0f / 64.0f))
+               return; // basically completely transparent
+
+       c_models++;
+
+       if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_FetchSkinFrame(ent)->fog != NULL)
+               R_MeshQueue_AddTransparent(ent->origin, R_DrawQ1Q2AliasModelCallback, ent, 0);
+       else
+               R_DrawQ1Q2AliasModelCallback(ent, 0);
 }
 
 extern cvar_t r_shadows;
-void R_DrawQ1Q2AliasModelFakeShadow (entity_render_t *ent)
+void R_Model_Alias_DrawFakeShadow (entity_render_t *ent)
 {
        int i;
        rmeshstate_t m;
@@ -563,6 +564,39 @@ void R_DrawQ1Q2AliasModelFakeShadow (entity_render_t *ent)
        R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
 }
 
+void R_Model_Alias_DrawDepth(entity_render_t *ent)
+{
+       R_Mesh_ResizeCheck(ent->model->numverts);
+       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+       R_Mesh_Draw(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices);
+}
+
+void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume)
+{
+       float projectdistance;
+       projectdistance = lightradius + ent->model->radius - sqrt(DotProduct(relativelightorigin, relativelightorigin));
+       if (projectdistance > 0.1)
+       {
+               R_Mesh_ResizeCheck(ent->model->numverts * 2);
+               R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+               R_Shadow_Volume(ent->model->numverts, ent->model->numtris, varray_vertex, ent->model->mdlmd2data_indices, ent->model->mdlmd2data_triangleneighbors, relativelightorigin, lightradius, projectdistance, visiblevolume);
+       }
+}
+
+void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor)
+{
+       R_Mesh_ResizeCheck(ent->model->numverts);
+       R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+       R_Shadow_VertexLight(ent->model->numverts, varray_vertex, aliasvertnorm, relativelightorigin, lightradius * lightradius, lightdistbias, lightsubtract, lightcolor);
+       GL_UseColorArray();
+       R_Mesh_Draw(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices);
+}
+
+void R_Model_Alias_DrawOntoLight(entity_render_t *ent)
+{
+       // FIXME
+}
+
 int ZymoticLerpBones(int count, const zymbonematrix *bonebase, const frameblend_t *blend, const zymbone_t *bone)
 {
        int i;
@@ -914,7 +948,7 @@ void R_DrawZymoticModelMeshCallback (const void *calldata1, int calldata2)
        }
 }
 
-void R_DrawZymoticModel (entity_render_t *ent)
+void R_Model_Zymotic_Draw(entity_render_t *ent)
 {
        int i;
        zymtype1header_t *m;
@@ -936,15 +970,17 @@ void R_DrawZymoticModel (entity_render_t *ent)
        }
 }
 
-void R_DrawQ1Q2AliasModel(entity_render_t *ent)
+void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent)
 {
-       if (ent->alpha < (1.0f / 64.0f))
-               return; // basically completely transparent
+       // FIXME
+}
 
-       c_models++;
+void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor)
+{
+       // FIXME
+}
 
-       if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_FetchSkinFrame(ent)->fog != NULL)
-               R_MeshQueue_AddTransparent(ent->origin, R_DrawQ1Q2AliasModelCallback, ent, 0);
-       else
-               R_DrawQ1Q2AliasModelCallback(ent, 0);
+void R_Model_Zymotic_DrawOntoLight(entity_render_t *ent)
+{
+       // FIXME
 }
index 7ab983c1839144d6f1464d232419a1bf43b5134f..65c6420346b6e7ae6f6b18b6be878ad0d6947b83 100644 (file)
@@ -52,6 +52,7 @@ unsigned short d_lightstylevalue[256];
 cvar_t r_drawentities = {0, "r_drawentities","1"};
 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "1"};
+cvar_t r_staticworldlights = {0, "r_staticworldlights", "1"};
 cvar_t r_speeds = {0, "r_speeds","0"};
 cvar_t r_fullbright = {0, "r_fullbright","0"};
 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
@@ -220,6 +221,7 @@ void GL_Main_Init(void)
        Cvar_RegisterVariable (&r_drawentities);
        Cvar_RegisterVariable (&r_drawviewmodel);
        Cvar_RegisterVariable (&r_shadows);
+       Cvar_RegisterVariable (&r_staticworldlights);
        Cvar_RegisterVariable (&r_speeds);
        Cvar_RegisterVariable (&r_fullbrights);
        Cvar_RegisterVariable (&r_wateralpha);
@@ -564,6 +566,8 @@ void R_DrawFakeShadows (void)
        }
 }
 
+#include "r_shadow.h"
+
 void R_TestAndDrawShadowVolume(entity_render_t *ent, vec3_t lightorigin, float lightradius, int visiblevolume)
 {
        int i;
@@ -634,14 +638,14 @@ void R_TestAndDrawShadowVolume(entity_render_t *ent, vec3_t lightorigin, float l
        }
 }
 
-void R_DrawWorldLightShadowVolume(mlight_t *sl)
+void R_DrawWorldLightShadowVolume(mlight_t *sl, int visiblevolume)
 {
        shadowmesh_t *mesh;
        R_Mesh_Matrix(&cl_entities[0].render.matrix);
        for (mesh = sl->shadowvolume;mesh;mesh = mesh->next)
        {
                memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->elements);
+               R_Shadow_RenderVolume(mesh->numverts, mesh->numtriangles, mesh->elements, visiblevolume);
        }
 }
 
@@ -658,6 +662,7 @@ void R_DrawShadowVolumes (void)
        {
                if (d_lightstylevalue[sl->style] <= 0)
                        continue;
+               /*
                mins[0] = sl->origin[0] - sl->cullradius;
                maxs[0] = sl->origin[0] + sl->cullradius;
                mins[1] = sl->origin[1] - sl->cullradius;
@@ -666,13 +671,16 @@ void R_DrawShadowVolumes (void)
                maxs[2] = sl->origin[2] + sl->cullradius;
                if (R_CullBox(mins, maxs))
                        continue;
+               */
+               if (R_CullBox(sl->mins, sl->maxs))
+                       continue;
                memset(&m, 0, sizeof(m));
                m.blendfunc1 = GL_ONE;
                m.blendfunc2 = GL_ONE;
                R_Mesh_State(&m);
                GL_Color(0.0 * r_colorscale, 0.0125 * r_colorscale, 0.1 * r_colorscale, 1);
-               if (sl->shadowvolume)
-                       R_DrawWorldLightShadowVolume(sl);
+               if (sl->shadowvolume && r_staticworldlights.integer)
+                       R_DrawWorldLightShadowVolume(sl, true);
                else
                {
                        ent = &cl_entities[0].render;
@@ -762,6 +770,255 @@ void R_DrawShadowVolumes (void)
        }
 }
 
+#define SHADOWSPHERE_SEGMENTS 16
+
+shadowmesh_t *shadowsphere;
+void R_CreateShadowSphere(void)
+{
+       int i, j;
+       vec3_t angles, angles2, angles3, angles4;
+       float verts[12];
+       shadowsphere = Mod_ShadowMesh_Begin(zonemempool);
+       for (i = 0;i < SHADOWSPHERE_SEGMENTS;i++)
+       {
+               for (j = 0;j < SHADOWSPHERE_SEGMENTS;j++)
+               {
+                       angles[0] = i * 360.0f / SHADOWSPHERE_SEGMENTS;
+                       angles[1] = j * 360.0f / SHADOWSPHERE_SEGMENTS;
+                       angles[2] = 0;
+                       VectorCopy(angles, angles2);
+                       VectorCopy(angles, angles3);
+                       VectorCopy(angles, angles4);
+                       angles2[1] += 360.0f / SHADOWSPHERE_SEGMENTS;
+                       angles3[0] += 360.0f / SHADOWSPHERE_SEGMENTS;
+                       angles3[1] += 360.0f / SHADOWSPHERE_SEGMENTS;
+                       angles4[0] += 360.0f / SHADOWSPHERE_SEGMENTS;
+                       AngleVectorsFLU(angles, verts, NULL, NULL);
+                       AngleVectorsFLU(angles2, verts + 9, NULL, NULL);
+                       AngleVectorsFLU(angles3, verts + 6, NULL, NULL);
+                       AngleVectorsFLU(angles4, verts + 3, NULL, NULL);
+                       VectorScale(&verts[0], 64.0f, &verts[0]);
+                       VectorScale(&verts[3], 64.0f, &verts[3]);
+                       VectorScale(&verts[6], 64.0f, &verts[6]);
+                       VectorScale(&verts[9], 64.0f, &verts[9]);
+                       Mod_ShadowMesh_AddPolygon(zonemempool, shadowsphere, 4, verts);
+                       AngleVectorsFLU(angles, verts, NULL, NULL);
+                       AngleVectorsFLU(angles2, verts + 3, NULL, NULL);
+                       AngleVectorsFLU(angles3, verts + 6, NULL, NULL);
+                       AngleVectorsFLU(angles4, verts + 9, NULL, NULL);
+                       VectorScale(&verts[0], 128.0f, &verts[0]);
+                       VectorScale(&verts[3], 128.0f, &verts[3]);
+                       VectorScale(&verts[6], 128.0f, &verts[6]);
+                       VectorScale(&verts[9], 128.0f, &verts[9]);
+                       Mod_ShadowMesh_AddPolygon(zonemempool, shadowsphere, 4, verts);
+               }
+       }
+       shadowsphere = Mod_ShadowMesh_Finish(zonemempool, shadowsphere);
+}
+
+
+void R_DrawShadowSphere(vec3_t origin, float radius, int visiblevolume)
+{
+       int i;
+       float *v;
+       shadowmesh_t *mesh;
+       //matrix4x4_t matrix;
+       if (!shadowsphere)
+               R_CreateShadowSphere();
+       //Matrix4x4_CreateTranslate(&matrix, origin[0], origin[1], origin[2]);
+       //Matrix4x4_ConcatScale(&matrix, radius);
+       //R_Mesh_Matrix(&matrix);
+       R_Mesh_Matrix(&r_identitymatrix);
+       for (mesh = shadowsphere;mesh;mesh = mesh->next)
+       {
+               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+               for (i = 0, v = varray_vertex;i < mesh->numverts;i++, v += 4)
+                       VectorMA(origin, radius, v, v);
+               R_Shadow_RenderVolume(mesh->numverts, mesh->numtriangles, mesh->elements, visiblevolume);
+       }
+}
+
+void R_ShadowVolumeLighting (void)
+{
+       int i;
+       entity_render_t *ent;
+       int lnum;
+       float f;
+       vec3_t mins, maxs, relativelightorigin, lightcolor;
+       mlight_t *sl;
+       rdlight_t *rd;
+
+       R_Shadow_Stage_Depth();
+       ent = &cl_entities[0].render;
+       if (ent->model && ent->model->DrawDepth)
+       {
+               R_Mesh_Matrix(&ent->matrix);
+               ent->model->DrawDepth(ent);
+       }
+       if (r_drawentities.integer)
+       {
+               for (i = 0;i < r_refdef.numentities;i++)
+               {
+                       ent = r_refdef.entities[i];
+                       if (ent->visframe == r_framecount && ent->model && ent->model->DrawDepth)
+                       {
+                               R_Mesh_Matrix(&ent->matrix);
+                               ent->model->DrawDepth(ent);
+                       }
+               }
+       }
+
+       for (lnum = 0, sl = cl.worldmodel->lights;lnum < cl.worldmodel->numlights;lnum++, sl++)
+       {
+               if (d_lightstylevalue[sl->style] <= 0)
+                       continue;
+               VectorCopy(sl->mins, mins);
+               VectorCopy(sl->maxs, maxs);
+               /*
+               mins[0] = sl->origin[0] - sl->cullradius;
+               maxs[0] = sl->origin[0] + sl->cullradius;
+               mins[1] = sl->origin[1] - sl->cullradius;
+               maxs[1] = sl->origin[1] + sl->cullradius;
+               mins[2] = sl->origin[2] - sl->cullradius;
+               maxs[2] = sl->origin[2] + sl->cullradius;
+               if (R_CullBox(mins, maxs))
+                       continue;
+               */
+               if (R_CullBox(mins, maxs))
+                       continue;
+
+               f = d_lightstylevalue[sl->style] * (1.0f / 32768.0f);
+               VectorScale(sl->light, f, lightcolor);
+
+               R_Shadow_Stage_ShadowVolumes();
+               R_DrawShadowSphere(sl->origin, 1.0f/*sl->cullradius - 16*/, false);
+               if (sl->shadowvolume && r_staticworldlights.integer)
+                       R_DrawWorldLightShadowVolume(sl, false);
+               else
+                       R_TestAndDrawShadowVolume(&cl_entities[0].render, sl->origin, sl->cullradius, false);
+               if (r_drawentities.integer)
+               {
+                       for (i = 0;i < r_refdef.numentities;i++)
+                       {
+                               ent = r_refdef.entities[i];
+                               if (ent->maxs[0] >= mins[0]
+                                && ent->mins[0] <= maxs[0]
+                                && ent->maxs[1] >= mins[1]
+                                && ent->mins[1] <= maxs[1]
+                                && ent->maxs[2] >= mins[2]
+                                && ent->mins[2] <= maxs[2])
+                                       R_TestAndDrawShadowVolume(r_refdef.entities[i], sl->origin, sl->cullradius, false);
+                       }
+               }
+
+               R_Shadow_Stage_Light();
+               ent = &cl_entities[0].render;
+               if (ent->model && ent->model->DrawLight)
+               {
+                       Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin);
+                       R_Mesh_Matrix(&ent->matrix);
+                       ent->model->DrawLight(ent, relativelightorigin, sl->cullradius, sl->distbias, sl->subtract, lightcolor);
+               }
+               if (r_drawentities.integer)
+               {
+                       for (i = 0;i < r_refdef.numentities;i++)
+                       {
+                               ent = r_refdef.entities[i];
+                               if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
+                                && ent->maxs[0] >= mins[0]
+                                && ent->mins[0] <= maxs[0]
+                                && ent->maxs[1] >= mins[1]
+                                && ent->mins[1] <= maxs[1]
+                                && ent->maxs[2] >= mins[2]
+                                && ent->mins[2] <= maxs[2])
+                               {
+                                       Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin);
+                                       R_Mesh_Matrix(&ent->matrix);
+                                       ent->model->DrawLight(ent, relativelightorigin, sl->cullradius, sl->distbias, sl->subtract, lightcolor);
+                               }
+                       }
+               }
+       }
+       for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
+       {
+               mins[0] = rd->origin[0] - rd->cullradius;
+               maxs[0] = rd->origin[0] + rd->cullradius;
+               mins[1] = rd->origin[1] - rd->cullradius;
+               maxs[1] = rd->origin[1] + rd->cullradius;
+               mins[2] = rd->origin[2] - rd->cullradius;
+               maxs[2] = rd->origin[2] + rd->cullradius;
+               if (R_CullBox(mins, maxs))
+                       continue;
+
+               R_Shadow_Stage_ShadowVolumes();
+               R_TestAndDrawShadowVolume(&cl_entities[0].render, rd->origin, rd->cullradius, false);
+               if (r_drawentities.integer)
+               {
+                       for (i = 0;i < r_refdef.numentities;i++)
+                       {
+                               ent = r_refdef.entities[i];
+                               if (ent->maxs[0] >= mins[0]
+                                && ent->mins[0] <= maxs[0]
+                                && ent->maxs[1] >= mins[1]
+                                && ent->mins[1] <= maxs[1]
+                                && ent->maxs[2] >= mins[2]
+                                && ent->mins[2] <= maxs[2])
+                               R_TestAndDrawShadowVolume(ent, rd->origin, rd->cullradius, false);
+                       }
+               }
+
+               R_Shadow_Stage_Light();
+               ent = &cl_entities[0].render;
+               if (ent->model && ent->model->DrawLight)
+               {
+                       Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
+                       R_Mesh_Matrix(&ent->matrix);
+                       ent->model->DrawLight(ent, relativelightorigin, rd->cullradius, LIGHTOFFSET, rd->subtract, rd->light);
+               }
+               if (r_drawentities.integer)
+               {
+                       for (i = 0;i < r_refdef.numentities;i++)
+                       {
+                               ent = r_refdef.entities[i];
+                               if (ent->visframe == r_framecount && ent->model && ent->model->DrawLight
+                                && ent->maxs[0] >= mins[0]
+                                && ent->mins[0] <= maxs[0]
+                                && ent->maxs[1] >= mins[1]
+                                && ent->mins[1] <= maxs[1]
+                                && ent->maxs[2] >= mins[2]
+                                && ent->mins[2] <= maxs[2])
+                               {
+                                       Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
+                                       R_Mesh_Matrix(&ent->matrix);
+                                       ent->model->DrawLight(ent, relativelightorigin, rd->cullradius, LIGHTOFFSET, rd->subtract, rd->light);
+                               }
+                       }
+               }
+       }
+
+       R_Shadow_Stage_Textures();
+       ent = &cl_entities[0].render;
+       if (ent->model && ent->model->DrawOntoLight)
+       {
+               R_Mesh_Matrix(&ent->matrix);
+               ent->model->DrawOntoLight(ent);
+       }
+       if (r_drawentities.integer)
+       {
+               for (i = 0;i < r_refdef.numentities;i++)
+               {
+                       ent = r_refdef.entities[i];
+                       if (ent->visframe == r_framecount && ent->model && ent->model->DrawOntoLight)
+                       {
+                               R_Mesh_Matrix(&ent->matrix);
+                               ent->model->DrawOntoLight(ent);
+                       }
+               }
+       }
+
+       R_Shadow_Stage_End();
+}
+
 static void R_SetFrustum (void)
 {
        int i;
@@ -872,17 +1129,23 @@ void R_RenderView (void)
 
        R_FarClip_Start(r_origin, vpn, 768.0f);
        R_MarkEntities();
-       r_farclip = R_FarClip_Finish() + 256.0f;
+       r_farclip = R_FarClip_Finish() + 16384.0f;//256.0f;
        R_TimeReport("markentity");
 
        GL_SetupView_ViewPort(r_refdef.x, r_refdef.y, r_refdef.width, r_refdef.height);
        GL_SetupView_Mode_Perspective((double) r_refdef.height / r_refdef.width, r_refdef.fov_x, r_refdef.fov_y, 1.0f, r_farclip);
        GL_SetupView_Orientation_FromEntity (r_refdef.vieworg, r_refdef.viewangles);
        qglDepthFunc(GL_LEQUAL);
-       
+
        R_Mesh_Start();
        R_MeshQueue_BeginScene();
 
+       if (r_shadows.integer == 3 && !vid_stencil.integer)
+       {
+               Con_Printf("Stencil not enabled, turning off r_shadows 3\n");
+               Cvar_SetValueQuick(&r_shadows, 0);
+       }
+
        if (R_DrawBrushModelsSky())
                R_TimeReport("bmodelsky");
 
@@ -897,6 +1160,9 @@ void R_RenderView (void)
        R_DrawModels();
        R_TimeReport("models");
 
+       if (r_shadows.integer == 3)
+               R_ShadowVolumeLighting();
+
        R_DrawParticles();
        R_TimeReport("particles");
 
index b6c8051857ba58acf5a97974372c25b3b796a4fb..9bbf8afcdb218430e18bb584ebab88eb9f10000a 100644 (file)
@@ -1814,23 +1814,33 @@ void R_DrawWorld (entity_render_t *ent)
        R_DrawSurfaces(ent, true, true);
 }
 
-/*
-=================
-R_DrawBrushModel
-=================
-*/
-void R_DrawBrushModelSky (entity_render_t *ent)
+void R_Model_Brush_DrawSky (entity_render_t *ent)
 {
        R_DrawBrushModel(ent, true, false);
 }
 
-void R_DrawBrushModelNormal (entity_render_t *ent)
+void R_Model_Brush_Draw (entity_render_t *ent)
 {
        c_bmodels++;
        R_DrawBrushModel(ent, false, true);
 }
 
-void R_DrawBrushModelShadowVolume (entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume)
+void R_Model_Brush_DrawDepth (entity_render_t *ent)
+{
+       shadowmesh_t *mesh;
+       if (!cl.worldmodel->numlights)
+               GL_Color(0.3, 0.3, 0.3, 1);
+       for (mesh = ent->model->shadowmesh;mesh;mesh = mesh->next)
+       {
+               R_Mesh_ResizeCheck(mesh->numverts);
+               memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+               R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->elements);
+       }
+       if (!cl.worldmodel->numlights)
+               GL_Color(0, 0, 0, 1);
+}
+
+void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume)
 {
 #if 0
        float projectdistance, temp[3];
@@ -1847,13 +1857,12 @@ void R_DrawBrushModelShadowVolume (entity_render_t *ent, vec3_t relativelightori
                }
        }
 #else
-       int i, numsurfaces;
+       int i;
        msurface_t *surf;
        float projectdistance, f, temp[3], lightradius2;
        surfmesh_t *mesh;
-       numsurfaces = ent->model->nummodelsurfaces;
        lightradius2 = lightradius * lightradius;
-       for (i = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;i < numsurfaces;i++, surf++)
+       for (i = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;i < ent->model->nummodelsurfaces;i++, surf++)
        {
                f = PlaneDiff(relativelightorigin, surf->plane);
                if (surf->flags & SURF_PLANEBACK)
@@ -1877,6 +1886,46 @@ void R_DrawBrushModelShadowVolume (entity_render_t *ent, vec3_t relativelightori
 #endif
 }
 
+void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor)
+{
+       int i;
+       msurface_t *surf;
+       float f, lightradius2;
+       surfmesh_t *mesh;
+       vec3_t modelorg;
+       Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+       lightradius2 = lightradius * lightradius;
+       GL_UseColorArray();
+       for (i = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;i < ent->model->nummodelsurfaces;i++, surf++)
+       {
+               f = PlaneDiff(relativelightorigin, surf->plane);
+               if (surf->flags & SURF_PLANEBACK)
+                       f = -f;
+               if (f >= -0.1 && f < lightradius)
+               {
+                       f = PlaneDiff(modelorg, surf->plane);
+                       if (surf->flags & SURF_PLANEBACK)
+                               f = -f;
+                       if (f > 0)
+                       {
+                               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+                               {
+                                       R_Mesh_ResizeCheck(mesh->numverts);
+                                       memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+                                       R_Shadow_VertexLight(mesh->numverts, varray_vertex, mesh->normals, relativelightorigin, lightradius2, lightdistbias, lightsubtract, lightcolor);
+                                       R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
+                               }
+                       }
+               }
+       }
+}
+
+void R_Model_Brush_DrawOntoLight(entity_render_t *ent)
+{
+       // FIXME
+       c_bmodels++;
+}
+
 /*
 extern cvar_t r_shadows;
 void R_DrawBrushModelFakeShadow (entity_render_t *ent)
index bcf3959b66598471b16dd81af80ec869aa0efd70..557811e801a25a2fc6c121ddf70af6cd5a464faf 100644 (file)
@@ -248,7 +248,12 @@ static int Mod_LoadInternalSkin (char *basename, qbyte *skindata, qbyte *skintem
 
 #define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)\n", loadmodel->name, VALUE, MIN, MAX);
 #define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)\n", loadmodel->name, VALUE, MIN, MAX);
-extern void R_DrawQ1Q2AliasModelShadowVolume (entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
+extern void R_Model_Alias_Draw(entity_render_t *ent);
+extern void R_Model_Alias_DrawFakeShadow(entity_render_t *ent);
+extern void R_Model_Alias_DrawDepth(entity_render_t *ent);
+extern void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
+extern void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
+extern void R_Model_Alias_DrawOntoLight(entity_render_t *ent);
 void Mod_LoadAliasModel (model_t *mod, void *buffer)
 {
        int                                             i, j, version, numverts, totalposes, totalskins, skinwidth, skinheight, totalverts, groupframes, groupskins;
@@ -281,6 +286,13 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
 
        loadmodel->type = mod_alias;
        loadmodel->aliastype = ALIASTYPE_MDLMD2;
+       loadmodel->DrawSky = NULL;
+       loadmodel->Draw = R_Model_Alias_Draw;
+       loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow;
+       loadmodel->DrawDepth = R_Model_Alias_DrawDepth;
+       loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
+       loadmodel->DrawLight = R_Model_Alias_DrawLight;
+       loadmodel->DrawOntoLight = R_Model_Alias_DrawOntoLight;
 
        loadmodel->numskins = LittleLong(pinmodel->numskins);
        BOUNDI(loadmodel->numskins,0,256);
@@ -528,11 +540,6 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
        loadmodel->radius = modelradius;
        loadmodel->radius2 = modelradius * modelradius;
 
-       loadmodel->Draw = R_DrawQ1Q2AliasModel;
-       loadmodel->DrawSky = NULL;
-       loadmodel->DrawFakeShadow = R_DrawQ1Q2AliasModelFakeShadow;
-       loadmodel->DrawShadowVolume = R_DrawQ1Q2AliasModelShadowVolume;
-
        loadmodel->mdlmd2data_triangleneighbors = Mem_Alloc(loadmodel->mempool, loadmodel->numtris * sizeof(int[3]));
        Mod_BuildTriangleNeighbors(loadmodel->mdlmd2data_triangleneighbors, loadmodel->mdlmd2data_indices, loadmodel->numtris);
 }
@@ -606,9 +613,13 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
 
        loadmodel->type = mod_alias;
        loadmodel->aliastype = ALIASTYPE_MDLMD2;
-       loadmodel->Draw = R_DrawQ1Q2AliasModel;
        loadmodel->DrawSky = NULL;
-       loadmodel->DrawFakeShadow = NULL;
+       loadmodel->Draw = R_Model_Alias_Draw;
+       loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow;
+       loadmodel->DrawDepth = R_Model_Alias_DrawDepth;
+       loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
+       loadmodel->DrawLight = R_Model_Alias_DrawLight;
+       loadmodel->DrawOntoLight = R_Model_Alias_DrawOntoLight;
 
        if (LittleLong(pinmodel->num_tris < 1) || LittleLong(pinmodel->num_tris) > MD2MAX_TRIANGLES)
                Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
@@ -805,6 +816,13 @@ static void zymswapintblock(int *m, int size)
        }
 }
 
+extern void R_Model_Zymotic_DrawSky(entity_render_t *ent);
+extern void R_Model_Zymotic_Draw(entity_render_t *ent);
+extern void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent);
+extern void R_Model_Zymotic_DrawDepth(entity_render_t *ent);
+extern void R_Model_Zymotic_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
+extern void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
+extern void R_Model_Zymotic_DrawOntoLight(entity_render_t *ent);
 void Mod_LoadZymoticModel(model_t *mod, void *buffer)
 {
        int i, pbase, *bonecount, numposes;
@@ -999,7 +1017,11 @@ void Mod_LoadZymoticModel(model_t *mod, void *buffer)
        loadmodel->radius = modelradius;
        loadmodel->radius2 = modelradius * modelradius;
 
-       loadmodel->Draw = R_DrawZymoticModel;
        loadmodel->DrawSky = NULL;
-       loadmodel->DrawFakeShadow = NULL;
+       loadmodel->Draw = R_Model_Zymotic_Draw;
+       loadmodel->DrawFakeShadow = NULL;//R_Model_Zymotic_DrawFakeShadow;
+       loadmodel->DrawDepth = NULL;//R_Model_Zymotic_DrawDepth;
+       loadmodel->DrawShadowVolume = NULL;//R_Model_Zymotic_DrawShadowVolume;
+       loadmodel->DrawLight = NULL;//R_Model_Zymotic_DrawLight;
+       loadmodel->DrawOntoLight = NULL;//R_Model_Zymotic_DrawOntoLight;
 }
index fa85dc6cd0935512b2a32e2adb2f9808fb15104f..b5bc85e1b14248e83d2a4e3394ed08bce28734dc 100644 (file)
@@ -1229,9 +1229,9 @@ void Mod_ProcessLightList(void)
                                if (loadmodel->surfacevisframes[j] == -2)
                                        e->surfaces[e->numsurfaces++] = loadmodel->surfaces + j;
                }
-               /*
                {
                // find bounding box and sphere of lit surfaces
+               // (these will be used for creating a shape to clip the light)
                float *v, temp[3], radius2;
                radius2 = 0;
                for (j = 0;j < e->numsurfaces;j++)
@@ -1253,26 +1253,37 @@ void Mod_ProcessLightList(void)
                                        radius2 = dist;
                        }
                }
+               /*
                if (e->cullradius2 > radius2)
                {
                        e->cullradius2 = radius2;
                        e->cullradius = sqrt(e->cullradius2);
                }
-               }
                */
+               }
 #if 1
                // clip shadow volumes against eachother to remove unnecessary
                // polygons (and sections of polygons)
                {
+                       vec3_t temp, outermins, outermaxs, innermins, innermaxs;
+                       int maxverts = 4;
+                       float *verts = Mem_Alloc(loadmodel->mempool, maxverts * sizeof(float[3]));
+                       float f, *v0, *v1, projectdistance;
                        svworld_t *svworld;
-                       float f;
-                       float temp[3];
-                       float *verts = NULL;
                        svbrush_t *svbrush;
-                       float *v0;
-                       float projectdistance;
-                       int maxverts = 0;
-                       float *v1;
+
+                       innermins[0] = e->mins[0] - 1;
+                       innermins[1] = e->mins[1] - 1;
+                       innermins[2] = e->mins[2] - 1;
+                       innermaxs[0] = e->maxs[0] + 1;
+                       innermaxs[1] = e->maxs[1] + 1;
+                       innermaxs[2] = e->maxs[2] + 1;
+                       outermins[0] = loadmodel->normalmins[0] - 1;
+                       outermins[1] = loadmodel->normalmins[1] - 1;
+                       outermins[2] = loadmodel->normalmins[2] - 1;
+                       outermaxs[0] = loadmodel->normalmaxs[0] + 1;
+                       outermaxs[1] = loadmodel->normalmaxs[1] + 1;
+                       outermaxs[2] = loadmodel->normalmaxs[2] + 1;
                        svworld = Mod_ShadowBrush_NewWorld(loadmodel->mempool);
                        for (j = 0, surf = loadmodel->surfaces + loadmodel->firstmodelsurface;j < loadmodel->nummodelsurfaces;j++, surf++)
                        {
@@ -1324,6 +1335,90 @@ void Mod_ProcessLightList(void)
                                }
                                Mod_ShadowBrush_EndBrush(svworld, svbrush);
                        }
+                       // add bounding box around the whole shadow volume set,
+                       // facing inward to limit light area, with an outer bounding box
+                       // facing outward (this is needed by the shadow rendering method)
+                       // X major
+                       svbrush = Mod_ShadowBrush_BeginBrush(loadmodel->mempool);
+                       verts[ 0] = innermaxs[0];verts[ 1] = innermins[1];verts[ 2] = innermaxs[2];
+                       verts[ 3] = innermaxs[0];verts[ 4] = innermins[1];verts[ 5] = innermins[2];
+                       verts[ 6] = innermaxs[0];verts[ 7] = innermaxs[1];verts[ 8] = innermins[2];
+                       verts[ 9] = innermaxs[0];verts[10] = innermaxs[1];verts[11] = innermaxs[2];
+                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+                       verts[ 0] = outermaxs[0];verts[ 1] = outermaxs[1];verts[ 2] = outermaxs[2];
+                       verts[ 3] = outermaxs[0];verts[ 4] = outermaxs[1];verts[ 5] = outermins[2];
+                       verts[ 6] = outermaxs[0];verts[ 7] = outermins[1];verts[ 8] = outermins[2];
+                       verts[ 9] = outermaxs[0];verts[10] = outermins[1];verts[11] = outermaxs[2];
+                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+                       Mod_ShadowBrush_EndBrush(svworld, svbrush);
+                       // X minor
+                       svbrush = Mod_ShadowBrush_BeginBrush(loadmodel->mempool);
+                       verts[ 0] = innermins[0];verts[ 1] = innermaxs[1];verts[ 2] = innermaxs[2];
+                       verts[ 3] = innermins[0];verts[ 4] = innermaxs[1];verts[ 5] = innermins[2];
+                       verts[ 6] = innermins[0];verts[ 7] = innermins[1];verts[ 8] = innermins[2];
+                       verts[ 9] = innermins[0];verts[10] = innermins[1];verts[11] = innermaxs[2];
+                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+                       verts[ 0] = outermins[0];verts[ 1] = outermins[1];verts[ 2] = outermaxs[2];
+                       verts[ 3] = outermins[0];verts[ 4] = outermins[1];verts[ 5] = outermins[2];
+                       verts[ 6] = outermins[0];verts[ 7] = outermaxs[1];verts[ 8] = outermins[2];
+                       verts[ 9] = outermins[0];verts[10] = outermaxs[1];verts[11] = outermaxs[2];
+                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+                       Mod_ShadowBrush_EndBrush(svworld, svbrush);
+                       // Y major
+                       svbrush = Mod_ShadowBrush_BeginBrush(loadmodel->mempool);
+                       verts[ 0] = innermaxs[0];verts[ 1] = innermaxs[1];verts[ 2] = innermaxs[2];
+                       verts[ 3] = innermaxs[0];verts[ 4] = innermaxs[1];verts[ 5] = innermins[2];
+                       verts[ 6] = innermins[0];verts[ 7] = innermaxs[1];verts[ 8] = innermins[2];
+                       verts[ 9] = innermins[0];verts[10] = innermaxs[1];verts[11] = innermaxs[2];
+                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+                       verts[ 0] = outermins[0];verts[ 1] = outermaxs[1];verts[ 2] = outermaxs[2];
+                       verts[ 3] = outermins[0];verts[ 4] = outermaxs[1];verts[ 5] = outermins[2];
+                       verts[ 6] = outermaxs[0];verts[ 7] = outermaxs[1];verts[ 8] = outermins[2];
+                       verts[ 9] = outermaxs[0];verts[10] = outermaxs[1];verts[11] = outermaxs[2];
+                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+                       Mod_ShadowBrush_EndBrush(svworld, svbrush);
+                       // Y minor
+                       svbrush = Mod_ShadowBrush_BeginBrush(loadmodel->mempool);
+                       verts[ 0] = innermins[0];verts[ 1] = innermins[1];verts[ 2] = innermaxs[2];
+                       verts[ 3] = innermins[0];verts[ 4] = innermins[1];verts[ 5] = innermins[2];
+                       verts[ 6] = innermaxs[0];verts[ 7] = innermins[1];verts[ 8] = innermins[2];
+                       verts[ 9] = innermaxs[0];verts[10] = innermins[1];verts[11] = innermaxs[2];
+                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+                       verts[ 0] = outermaxs[0];verts[ 1] = outermins[1];verts[ 2] = outermaxs[2];
+                       verts[ 3] = outermaxs[0];verts[ 4] = outermins[1];verts[ 5] = outermins[2];
+                       verts[ 6] = outermins[0];verts[ 7] = outermins[1];verts[ 8] = outermins[2];
+                       verts[ 9] = outermins[0];verts[10] = outermins[1];verts[11] = outermaxs[2];
+                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+                       Mod_ShadowBrush_EndBrush(svworld, svbrush);
+                       // Z major
+                       svbrush = Mod_ShadowBrush_BeginBrush(loadmodel->mempool);
+                       verts[ 0] = innermaxs[0];verts[ 1] = innermins[1];verts[ 2] = innermaxs[2];
+                       verts[ 3] = innermaxs[0];verts[ 4] = innermaxs[1];verts[ 5] = innermaxs[2];
+                       verts[ 6] = innermins[0];verts[ 7] = innermaxs[1];verts[ 8] = innermaxs[2];
+                       verts[ 9] = innermins[0];verts[10] = innermins[1];verts[11] = innermaxs[2];
+                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+                       verts[ 0] = outermaxs[0];verts[ 1] = outermaxs[1];verts[ 2] = outermaxs[2];
+                       verts[ 3] = outermaxs[0];verts[ 4] = outermins[1];verts[ 5] = outermaxs[2];
+                       verts[ 6] = outermins[0];verts[ 7] = outermins[1];verts[ 8] = outermaxs[2];
+                       verts[ 9] = outermins[0];verts[10] = outermaxs[1];verts[11] = outermaxs[2];
+                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+                       Mod_ShadowBrush_EndBrush(svworld, svbrush);
+                       // Z minor
+                       svbrush = Mod_ShadowBrush_BeginBrush(loadmodel->mempool);
+                       verts[ 0] = innermaxs[0];verts[ 1] = innermaxs[1];verts[ 2] = innermins[2];
+                       verts[ 3] = innermaxs[0];verts[ 4] = innermins[1];verts[ 5] = innermins[2];
+                       verts[ 6] = innermins[0];verts[ 7] = innermins[1];verts[ 8] = innermins[2];
+                       verts[ 9] = innermins[0];verts[10] = innermaxs[1];verts[11] = innermins[2];
+                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+                       verts[ 0] = outermaxs[0];verts[ 1] = outermins[1];verts[ 2] = outermins[2];
+                       verts[ 3] = outermaxs[0];verts[ 4] = outermaxs[1];verts[ 5] = outermins[2];
+                       verts[ 6] = outermins[0];verts[ 7] = outermaxs[1];verts[ 8] = outermins[2];
+                       verts[ 9] = outermins[0];verts[10] = outermins[1];verts[11] = outermins[2];
+                       Mod_ShadowBrush_AddPolygon(loadmodel->mempool, svbrush, 4, verts);
+                       Mod_ShadowBrush_EndBrush(svworld, svbrush);
+                       // clip away hidden polygons
+                       Mod_ShadowBrush_ProcessWorld(loadmodel->mempool, svworld);
+                       // build the triangle mesh
                        e->shadowvolume = Mod_ShadowBrush_BuildMeshs(loadmodel->mempool, svworld);
                        Mod_ShadowBrush_FreeWorld(svworld);
                }
@@ -3219,7 +3314,13 @@ static void Mod_MakePortals(void)
 Mod_LoadBrushModel
 =================
 */
-extern void R_DrawBrushModelShadowVolume (entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
+extern void R_Model_Brush_DrawSky(entity_render_t *ent);
+extern void R_Model_Brush_Draw(entity_render_t *ent);
+//extern void R_Model_Brush_DrawFakeShadow(entity_render_t *ent);
+extern void R_Model_Brush_DrawDepth(entity_render_t *ent);
+extern void R_Model_Brush_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
+extern void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
+extern void R_Model_Brush_DrawOntoLight(entity_render_t *ent);
 void Mod_LoadBrushModel (model_t *mod, void *buffer)
 {
        int                     i, j;
@@ -3308,7 +3409,14 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                mod->firstmodelsurface = bm->firstface;
                mod->nummodelsurfaces = bm->numfaces;
 
+               // this gets altered below if sky is used
                mod->DrawSky = NULL;
+               mod->Draw = R_Model_Brush_Draw;
+               mod->DrawFakeShadow = NULL;
+               mod->DrawDepth = R_Model_Brush_DrawDepth;
+               mod->DrawShadowVolume = R_Model_Brush_DrawShadowVolume;
+               mod->DrawLight = R_Model_Brush_DrawLight;
+               mod->DrawOntoLight = R_Model_Brush_DrawOntoLight;
                if (mod->nummodelsurfaces)
                {
                        // LordHavoc: calculate bmodel bounding box rather than trusting what it says
@@ -3316,7 +3424,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                        {
                                // we only need to have a drawsky function if it is used (usually only on world model)
                                if (surf->texinfo->texture->shader == &Cshader_sky)
-                                       mod->DrawSky = R_DrawBrushModelSky;
+                                       mod->DrawSky = R_Model_Brush_DrawSky;
                                for (k = 0;k < surf->numedges;k++)
                                {
                                        l = mod->surfedges[k + surf->firstedge];
@@ -3373,10 +3481,6 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
 
                mod->numleafs = bm->visleafs;
 
-               mod->Draw = R_DrawBrushModelNormal;
-               mod->DrawFakeShadow = NULL;
-               mod->DrawShadowVolume = R_DrawBrushModelShadowVolume;
-
                // LordHavoc: only register submodels if it is the world
                // (prevents bsp models from replacing world submodels)
                if (loadmodel->isworldmodel && i < (mod->numsubmodels - 1))
index 7a8e1d0c7bd0800b7b7f8f300f7b4b09b0d523bf..e95fdae6bf5b91f9a6d53c9bcc2cb2ce1308534a 100644 (file)
@@ -336,7 +336,7 @@ typedef struct mlight_s
        int numsurfaces;
        msurface_t **surfaces;
        // lit area
-       //vec3_t mins, maxs;
+       vec3_t mins, maxs;
        // precomputed shadow volume meshs
        //svbspmesh_t *shadowvolume;
        //vec3_t shadowvolumemins, shadowvolumemaxs;
index 8506945e1f30b9f4cc03aca0d6a9b62b9a10761b..a2e8013b9ff72ba8c76fc3da11c9ba411be38b48 100644 (file)
@@ -484,7 +484,7 @@ shadowmesh_t *Mod_ShadowMesh_Begin(mempool_t *mempool)
 
 shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh)
 {
-       int i;
+       //int i;
        shadowmesh_t *mesh, *newmesh, *nextmesh;
        // reallocate meshs to conserve space
        for (mesh = firstmesh, firstmesh = NULL;mesh;mesh = nextmesh)
@@ -494,9 +494,9 @@ shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh)
                newmesh->next = firstmesh;
                firstmesh = newmesh;
                Mem_Free(mesh);
-               Con_Printf("mesh\n");
-               for (i = 0;i < newmesh->numtriangles;i++)
-                       Con_Printf("tri %d %d %d\n", newmesh->elements[i * 3 + 0], newmesh->elements[i * 3 + 1], newmesh->elements[i * 3 + 2]);
+               //Con_Printf("mesh\n");
+               //for (i = 0;i < newmesh->numtriangles;i++)
+               //      Con_Printf("tri %d %d %d\n", newmesh->elements[i * 3 + 0], newmesh->elements[i * 3 + 1], newmesh->elements[i * 3 + 2]);
                Mod_BuildTriangleNeighbors(newmesh->neighbors, newmesh->elements, newmesh->numtriangles);
        }
        return firstmesh;
index 998e02844cfe82036806bd2eab785638f0527fbf..c80f495133c91096b27d867586104f8e59caa9f7 100644 (file)
@@ -212,14 +212,25 @@ typedef struct model_s
        int                             sprnum_type;
        mspriteframe_t  *sprdata_frames;
 
-       // draw the model
-       void(*Draw)(struct entity_render_s *ent);
+
+       // functions used in both rendering modes
        // draw the model's sky polygons (only used by brush models)
        void(*DrawSky)(struct entity_render_s *ent);
+
+       // functions used only in normal rendering mode
+       // draw the model
+       void(*Draw)(struct entity_render_s *ent);
        // draw a fake shadow for the model
        void(*DrawFakeShadow)(struct entity_render_s *ent);
+
+       // functions used only in shadow volume rendering mode
+       void(*DrawDepth)(struct entity_render_s *ent);
        // draw a shadow volume for the model based on light source
        void(*DrawShadowVolume)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume);
+       // draw the lighting on a model (through stencil)
+       void(*DrawLight)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, float lightdistbias, float lightsubtract, float *lightcolor);
+       // draw the model with lighting already in framebuffer
+       void(*DrawOntoLight)(struct entity_render_s *ent);
 
        // memory pool for allocations
        mempool_t               *mempool;
index 28ddbd3d33075963636a5523ef6fd985cd119922..4f4e791f8a1aafdb61674abde76d111aea6a271b 100644 (file)
@@ -234,6 +234,7 @@ static void Mod_Sprite_SharedSetup(qbyte *datapointer, int version, int *palette
 Mod_LoadSpriteModel
 =================
 */
+extern void R_Model_Sprite_Draw(entity_render_t *ent);
 void Mod_LoadSpriteModel (model_t *mod, void *buffer)
 {
        int version, i, rendermode;
@@ -244,10 +245,13 @@ void Mod_LoadSpriteModel (model_t *mod, void *buffer)
 
        datapointer = buffer;
 
-       loadmodel->Draw = R_DrawSpriteModel;
        loadmodel->DrawSky = NULL;
+       loadmodel->Draw = R_Model_Sprite_Draw;
        loadmodel->DrawFakeShadow = NULL;
+       loadmodel->DrawDepth = NULL;
        loadmodel->DrawShadowVolume = NULL;
+       loadmodel->DrawLight = NULL;
+       loadmodel->DrawOntoLight = NULL;
 
        version = LittleLong(((dsprite_t *)buffer)->version);
        if (version == SPRITE_VERSION || SPRITE32_VERSION)
index ee32a61baf979ef8df0fc9e80ae253c76d5664b1..c13a9779d631727405390ba6e0565fa8069fbb79 100644 (file)
@@ -1,5 +1,6 @@
 
 #include "quakedef.h"
+#include "r_shadow.h"
 
 mempool_t *r_shadow_mempool;
 
@@ -216,41 +217,117 @@ void R_Shadow_Volume(int numverts, int numtris, float *vertex, int *elements, in
                        }
                }
        }
+       R_Shadow_RenderVolume(numverts * 2, tris, shadowelements, visiblevolume);
+}
+
+void R_Shadow_RenderVolume(int numverts, int numtris, int *elements, int visiblevolume)
+{
        // draw the volume
        if (visiblevolume)
        {
-               //qglDisable(GL_CULL_FACE);
-               R_Mesh_Draw(numverts * 2, tris, shadowelements);
-               //qglEnable(GL_CULL_FACE);
+               qglDisable(GL_CULL_FACE);
+               R_Mesh_Draw(numverts, numtris, elements);
+               qglEnable(GL_CULL_FACE);
        }
        else
        {
-               qglColorMask(0,0,0,0);
-               qglDepthMask(0);
-               qglEnable(GL_STENCIL_TEST);
-
                // 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(numverts * 2, tris, shadowelements);
-               // decrement stencil if frontface is infront of depthbuffer
+               R_Mesh_Draw(numverts, numtris, elements);
+               // 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(numverts * 2, tris, shadowelements);
-
-               // restore to normal quake rendering
-               qglDisable(GL_STENCIL_TEST);
-               qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-               qglDepthMask(1);
-               qglColorMask(1,1,1,1);
+               R_Mesh_Draw(numverts, numtris, elements);
        }
 }
 
+void R_Shadow_Stage_Depth(void)
+{
+       rmeshstate_t m;
+       memset(&m, 0, sizeof(m));
+       m.blendfunc1 = GL_ONE;
+       m.blendfunc2 = GL_ZERO;
+       R_Mesh_State(&m);
+       GL_Color(0, 0, 0, 1);
+}
+
+void R_Shadow_Stage_ShadowVolumes(void)
+{
+       GL_Color(1, 1, 1, 1);
+       qglColorMask(0, 0, 0, 0);
+       qglDisable(GL_BLEND);
+       qglDepthMask(0);
+       qglDepthFunc(GL_LEQUAL);
+       qglClearStencil(0);
+       qglClear(GL_STENCIL_BUFFER_BIT);
+       qglEnable(GL_STENCIL_TEST);
+       qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+       qglStencilFunc(GL_ALWAYS, 0, 0xFF);
+}
+
+void R_Shadow_Stage_Light(void)
+{
+       qglEnable(GL_BLEND);
+       qglBlendFunc(GL_ONE, GL_ONE);
+       GL_Color(1, 1, 1, 1);
+       qglColorMask(1, 1, 1, 1);
+       qglDepthMask(0);
+       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 0 (non-zero means shadow)
+       qglStencilFunc(GL_EQUAL, 0, 0xFF);
+}
+
+void R_Shadow_Stage_Textures(void)
+{
+       rmeshstate_t m;
+       // attempt to restore state to what Mesh_State thinks it is
+       qglDisable(GL_BLEND);
+       qglBlendFunc(GL_ONE, GL_ZERO);
+       qglDepthMask(1);
+
+       // now change to a more useful state
+       memset(&m, 0, sizeof(m));
+       m.blendfunc1 = GL_DST_COLOR;
+       m.blendfunc2 = GL_SRC_COLOR;
+       R_Mesh_State(&m);
+
+       // now hack some more
+       GL_Color(1, 1, 1, 1);
+       qglColorMask(1, 1, 1, 1);
+       qglDepthFunc(GL_EQUAL);
+       qglEnable(GL_STENCIL_TEST);
+       qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+       // only draw in lit areas
+       qglStencilFunc(GL_EQUAL, 0, 0xFF);
+}
+
+void R_Shadow_Stage_End(void)
+{
+       rmeshstate_t m;
+       GL_Color(1, 1, 1, 1);
+       qglColorMask(1, 1, 1, 1);
+       qglDepthFunc(GL_LEQUAL);
+       qglDisable(GL_STENCIL_TEST);
+       qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+       qglStencilFunc(GL_ALWAYS, 0, 0xFF);
+
+       // now change to a more useful state
+       memset(&m, 0, sizeof(m));
+       m.blendfunc1 = GL_ONE;
+       m.blendfunc2 = GL_ZERO;
+       R_Mesh_State(&m);
+}
+
 void R_Shadow_VertexLight(int numverts, float *vertex, float *normals, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor)
 {
        int i;
-       float *n, *v, *c, f, dist, temp[3];
+       float *n, *v, *c, f, dist, temp[3], light[3];
        // calculate vertex colors
+       VectorCopy(lightcolor, light);
        for (i = 0, v = vertex, c = varray_color, n = normals;i < numverts;i++, v += 4, c += 4, n += 3)
        {
                VectorSubtract(relativelightorigin, v, temp);
@@ -265,28 +342,10 @@ void R_Shadow_VertexLight(int numverts, float *vertex, float *normals, vec3_t re
                        if (dist < lightradius2)
                        {
                                f = ((1.0f / (dist + lightdistbias)) - lightsubtract) * (f / sqrt(dist));
-                               c[0] = f * lightcolor[0];
-                               c[1] = f * lightcolor[1];
-                               c[2] = f * lightcolor[2];
+                               c[0] = f * light[0];
+                               c[1] = f * light[1];
+                               c[2] = f * light[2];
                        }
                }
        }
 }
-
-void R_Shadow_RenderLightThroughStencil(int numverts, int numtris, int *elements, vec3_t relativelightorigin, float *normals)
-{
-       // only draw light where this geometry was already rendered AND the
-       // stencil is 0 (non-zero means shadow)
-       qglDepthFunc(GL_EQUAL);
-       qglEnable(GL_STENCIL_TEST);
-       qglStencilFunc(GL_EQUAL, 0, 0xFF);
-       R_Mesh_Draw(numverts, numtris, elements);
-       qglDisable(GL_STENCIL_TEST);
-       qglDepthFunc(GL_LEQUAL);
-}
-
-void R_Shadow_ClearStencil(void)
-{
-       qglClearStencil(0);
-       qglClear(GL_STENCIL_BUFFER_BIT);
-}
index bd3669d01ace60dde2c2d73d22e6a209a4c3d1b6..cea3a9ef3be57ab126186f7a9aa2ade10db7e2c9 100644 (file)
@@ -8,4 +8,11 @@ void R_Shadow_VertexLight(int numverts, float *vertex, float *normals, vec3_t re
 void R_Shadow_RenderLightThroughStencil(int numverts, int numtris, int *elements, vec3_t relativelightorigin, float *normals);
 void R_Shadow_ClearStencil(void);
 
+void R_Shadow_RenderVolume(int numverts, int numtris, int *elements, int visiblevolume);
+void R_Shadow_Stage_Depth(void);
+void R_Shadow_Stage_ShadowVolumes(void);
+void R_Shadow_Stage_Light(void);
+void R_Shadow_Stage_Textures(void);
+void R_Shadow_Stage_End(void);
+
 #endif
index b979805850d96c78ce6b75cc622710a618bc4f81..b69140da5a7d64ca5ea8e3f98b868b19579d8c41 100644 (file)
@@ -168,12 +168,7 @@ void R_DrawSpriteModelCallback(const void *calldata1, int calldata2)
 #endif
 }
 
-/*
-=================
-R_DrawSpriteModel
-=================
-*/
-void R_DrawSpriteModel (entity_render_t *ent)
+void R_Model_Sprite_Draw(entity_render_t *ent)
 {
        if (ent->frameblend[0].frame < 0)
                return;
index 21499f90a982dcaa6296e082271906dd15fb5c60..bb73ebd5f8712a47c15f1176194cca8380f1f1a6 100644 (file)
--- a/render.h
+++ b/render.h
@@ -111,12 +111,6 @@ void R_NewMap (void);
 void R_DrawWorld(entity_render_t *ent);
 void R_DrawParticles(void);
 void R_DrawExplosions(void);
-void R_DrawBrushModelSky(entity_render_t *ent);
-void R_DrawBrushModelNormal(entity_render_t *ent);
-void R_DrawZymoticModel(entity_render_t *ent);
-void R_DrawQ1Q2AliasModel(entity_render_t *ent);
-void R_DrawQ1Q2AliasModelFakeShadow(entity_render_t *ent);
-void R_DrawSpriteModel(entity_render_t *ent);
 
 // LordHavoc: vertex transform
 #include "transform.h"