}
}
-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;
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;
}
}
-void R_DrawZymoticModel (entity_render_t *ent)
+void R_Model_Zymotic_Draw(entity_render_t *ent)
{
int i;
zymtype1header_t *m;
}
}
-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
}
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"};
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);
}
}
+#include "r_shadow.h"
+
void R_TestAndDrawShadowVolume(entity_render_t *ent, vec3_t lightorigin, float lightradius, int visiblevolume)
{
int i;
}
}
-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);
}
}
{
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;
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;
}
}
+#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;
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");
R_DrawModels();
R_TimeReport("models");
+ if (r_shadows.integer == 3)
+ R_ShadowVolumeLighting();
+
R_DrawParticles();
R_TimeReport("particles");
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];
}
}
#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)
#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)
#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;
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);
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);
}
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));
}
}
+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;
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;
}
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++)
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++)
{
}
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);
}
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;
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
{
// 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];
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))
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;
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)
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;
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;
Mod_LoadSpriteModel
=================
*/
+extern void R_Model_Sprite_Draw(entity_render_t *ent);
void Mod_LoadSpriteModel (model_t *mod, void *buffer)
{
int version, i, rendermode;
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)
#include "quakedef.h"
+#include "r_shadow.h"
mempool_t *r_shadow_mempool;
}
}
}
+ 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);
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);
-}
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
#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;
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"