qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);CHECKGLERROR
}
-void GL_DepthFunc(int value)
-{
- if (!r_render.integer)
- return;
-
- qglDepthFunc (value);
- CHECKGLERROR
-}
-
-void GL_ClearDepth(void)
-{
- BACKENDACTIVECHECK
-
- if (!r_render.integer)
- return;
-
- qglClear(GL_DEPTH_BUFFER_BIT);
- CHECKGLERROR
-}
-
void R_Mesh_Matrix(const matrix4x4_t *matrix)
{
if (memcmp(matrix, &backend_modelmatrix, sizeof(matrix4x4_t)))
void GL_SetupView_Mode_Ortho (double x1, double y1, double x2, double y2, double zNear, double zFar);
void GL_UseColorArray(void);
void GL_Color(float cr, float cg, float cb, float ca);
-void GL_DepthFunc(int value);
-void GL_ClearDepth(void);
extern cvar_t gl_lockarrays;
}
GL_SetupView_ViewPort(vid.realx, vid.realy, vid.realwidth, vid.realheight);
GL_SetupView_Mode_Ortho(0, 0, vid.conwidth, vid.conheight, -10, 100);
- GL_DepthFunc(GL_LEQUAL);
+ qglDepthFunc(GL_LEQUAL);
R_Mesh_Start();
R_Mesh_Matrix(&r_identitymatrix);
rmeshstate_t m;
model_t *model;
float *v, planenormal[3], planedist, dist, projection[3], floororigin[3], surfnormal[3], lightdirection[3], v2[3];
+ mlight_t *sl;
+ rdlight_t *rd;
if (r_shadows.integer > 1)
{
- float f;
+ float f, lightscale, lightcolor[3];
vec3_t temp;
- for (i = 0;i < r_numdlights;i++)
+ memset(&m, 0, sizeof(m));
+ m.blendfunc1 = GL_ONE;
+ m.blendfunc2 = GL_ONE;
+ R_Mesh_State(&m);
+ R_Mesh_Matrix(&ent->matrix);
+ for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights;i++, sl++)
+ {
+ if (d_lightstylevalue[sl->style] > 0)
+ {
+ VectorSubtract(ent->origin, sl->origin, temp);
+ f = DotProduct(temp,temp);
+ if (f < (ent->model->radius2 + sl->cullradius2))
+ {
+ model = ent->model;
+ R_Mesh_ResizeCheck(model->numverts * 2);
+ R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+ Matrix4x4_Transform(&ent->inversematrix, sl->origin, temp);
+ GL_Color(0.1 * r_colorscale, 0.025 * r_colorscale, 0.0125 * r_colorscale, 1);
+ R_Shadow_Volume(model->numverts, model->numtris, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, sl->cullradius + model->radius - sqrt(f), true);
+ GL_UseColorArray();
+ lightscale = d_lightstylevalue[sl->style] * (1.0f / 65536.0f);
+ VectorScale(sl->light, lightscale, lightcolor);
+ R_Shadow_VertexLight(model->numverts, aliasvertnorm, temp, sl->cullradius2, sl->distbias, sl->subtract, lightcolor);
+ R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
+ }
+ }
+ }
+ for (i = 0, rd = r_dlight;i < r_numdlights;i++, rd++)
{
- if (ent != r_dlight[i].ent)
+ if (ent != rd->ent)
{
- VectorSubtract(ent->origin, r_dlight[i].origin, temp);
+ VectorSubtract(ent->origin, rd->origin, temp);
f = DotProduct(temp,temp);
- if (f < (ent->model->radius2 + r_dlight[i].cullradius2))
+ if (f < (ent->model->radius2 + rd->cullradius2))
{
model = ent->model;
R_Mesh_ResizeCheck(model->numverts * 2);
- memset(&m, 0, sizeof(m));
- m.blendfunc1 = GL_ONE;
- m.blendfunc2 = GL_ONE;
- R_Mesh_State(&m);
- R_Mesh_Matrix(&ent->matrix);
R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvertnorm);
+ Matrix4x4_Transform(&ent->inversematrix, rd->origin, temp);
GL_Color(0.1 * r_colorscale, 0.025 * r_colorscale, 0.0125 * r_colorscale, 1);
- Matrix4x4_Transform(&ent->inversematrix, r_dlight[i].origin, temp);
- R_ShadowVolume(model->numverts, model->numtris, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, r_dlight[i].cullradius + model->radius - sqrt(f), true);
+ R_Shadow_Volume(model->numverts, model->numtris, model->mdlmd2data_indices, model->mdlmd2data_triangleneighbors, temp, rd->cullradius + model->radius - sqrt(f), true);
+ GL_UseColorArray();
+ R_Shadow_VertexLight(model->numverts, aliasvertnorm, temp, rd->cullradius2, LIGHTOFFSET, rd->subtract, rd->light);
+ R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
}
}
}
}
}
-void R_DrawModelFakeShadows (void)
+void R_DrawFakeShadows (void)
{
int i;
entity_render_t *ent;
if (!r_drawentities.integer)
return;
+ ent = &cl_entities[0].render;
+ if (ent->model && ent->model->DrawFakeShadow)
+ ent->model->DrawFakeShadow(ent);
for (i = 0;i < r_refdef.numentities;i++)
{
ent = r_refdef.entities[i];
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);
- GL_DepthFunc(GL_LEQUAL);
+ qglDepthFunc(GL_LEQUAL);
R_Mesh_Start();
R_MeshQueue_BeginScene();
if (!intimerefresh && !r_speeds.integer)
S_ExtraUpdate ();
- if (r_shadows.integer)
- {
- R_DrawModelFakeShadows();
- R_TimeReport("fakeshadows");
- }
-
R_DrawModels();
R_TimeReport("models");
R_MeshQueue_Render();
R_MeshQueue_EndScene();
+ if (r_shadows.integer)
+ {
+ R_DrawFakeShadows();
+ R_TimeReport("fakeshadows");
+ }
R_Mesh_Finish();
R_TimeReport("meshfinish");
}
// r_surf.c: surface-related refresh code
#include "quakedef.h"
+#include "r_shadow.h"
#define MAX_LIGHTMAP_SIZE 256
memset(&m, 0, sizeof(m));
if (skyrendermasked)
{
+ qglColorMask(0,0,0,0);
+ // just to make sure that braindead drivers don't draw anything
+ // despite that colormask...
m.blendfunc1 = GL_ZERO;
m.blendfunc2 = GL_ONE;
}
R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->index);
}
}
+ qglColorMask(1,1,1,1);
}
static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
R_DrawBrushModel(ent, false, true);
}
+void R_DrawBrushModelShadowVolumes (entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int visiblevolume)
+{
+ int i, numsurfaces;
+ 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++)
+ {
+ VectorSubtract(relativelightorigin, surf->poly_center, temp);
+ if (DotProduct(temp, temp) < (surf->poly_radius2 + lightradius2))
+ {
+ f = PlaneDiff(relativelightorigin, surf->plane);
+ if (surf->flags & SURF_PLANEBACK)
+ f = -f;
+ // draw shadows only for backfaces
+ if (f < 0)
+ {
+ projectdistance = lightradius + f;
+ if (projectdistance > 0)
+ {
+ for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+ {
+ R_Mesh_ResizeCheck(mesh->numverts * 2);
+ memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
+ R_Shadow_Volume(mesh->numverts, mesh->numtriangles, mesh->index, mesh->triangleneighbors, relativelightorigin, projectdistance, visiblevolume);
+ }
+ }
+ }
+ }
+ }
+}
+
+extern cvar_t r_shadows;
+void R_DrawBrushModelFakeShadow (entity_render_t *ent)
+{
+ int i;
+ vec3_t relativelightorigin;
+ rmeshstate_t m;
+ mlight_t *sl;
+ rdlight_t *rd;
+
+ if (r_shadows.integer < 2)
+ return;
+
+ memset(&m, 0, sizeof(m));
+ m.blendfunc1 = GL_ONE;
+ m.blendfunc2 = GL_ONE;
+ R_Mesh_State(&m);
+ R_Mesh_Matrix(&ent->matrix);
+ GL_Color(0.0125 * r_colorscale, 0.025 * r_colorscale, 0.1 * r_colorscale, 1);
+ for (i = 0, sl = cl.worldmodel->lights;i < cl.worldmodel->numlights;i++, sl++)
+ {
+ if (d_lightstylevalue[sl->style] > 0
+ && ent->maxs[0] >= sl->origin[0] - sl->cullradius
+ && ent->mins[0] <= sl->origin[0] + sl->cullradius
+ && ent->maxs[1] >= sl->origin[1] - sl->cullradius
+ && ent->mins[1] <= sl->origin[1] + sl->cullradius
+ && ent->maxs[2] >= sl->origin[2] - sl->cullradius
+ && ent->mins[2] <= sl->origin[2] + sl->cullradius)
+ {
+ Matrix4x4_Transform(&ent->inversematrix, sl->origin, relativelightorigin);
+ R_DrawBrushModelShadowVolumes (ent, relativelightorigin, sl->cullradius, true);
+ }
+ }
+ for (i = 0, rd = r_dlight;i < r_numdlights;i++, rd++)
+ {
+ if (ent->maxs[0] >= rd->origin[0] - rd->cullradius
+ && ent->mins[0] <= rd->origin[0] + rd->cullradius
+ && ent->maxs[1] >= rd->origin[1] - rd->cullradius
+ && ent->mins[1] <= rd->origin[1] + rd->cullradius
+ && ent->maxs[2] >= rd->origin[2] - rd->cullradius
+ && ent->mins[2] <= rd->origin[2] + rd->cullradius)
+ {
+ Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
+ R_DrawBrushModelShadowVolumes (ent, relativelightorigin, rd->cullradius, true);
+ }
+ }
+}
+
static void gl_surf_start(void)
{
}
#define GL_ACCUM_BUFFER_BIT 0x00000200
#define GL_STENCIL_BUFFER_BIT 0x00000400
#define GL_COLOR_BUFFER_BIT 0x00004000
+
+#define GL_STENCIL_TEST 0x0B90
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
#endif
// GL_ARB_multitexture
extern void (GLAPIENTRY *qglDepthFunc)(GLenum func);
extern void (GLAPIENTRY *qglDepthMask)(GLboolean flag);
extern void (GLAPIENTRY *qglDepthRange)(GLclampd near_val, GLclampd far_val);
+extern void (GLAPIENTRY *qglColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
extern void (GLAPIENTRY *qglDrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
extern void (GLAPIENTRY *qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
}
}
+void Mod_ProcessLightList(void)
+{
+ int i, j, k, *mark;
+ mlight_t *e;
+ msurface_t *surf;
+ float dist;
+ mleaf_t *l;
+ qbyte *pvs;
+ for (i = 0, e = loadmodel->lights;i < loadmodel->numlights;i++, e++)
+ {
+ e->cullradius2 = DotProduct(e->light, e->light) * (1.0f / (8192.0f * 8192.0f)) / (e->falloff * e->falloff) + 4096.0f;
+ if (e->cullradius2 > 4096.0f * 4096.0f)
+ e->cullradius2 = 4096.0f * 4096.0f;
+ e->cullradius = sqrt(e->cullradius2);
+ l = Mod_PointInLeaf(e->origin, loadmodel);
+ if (l->compressed_vis)
+ pvs = Mod_DecompressVis (l->compressed_vis, loadmodel);
+ else
+ pvs = mod_novis;
+ for (j = 0, l = loadmodel->leafs + 1;j < loadmodel->numleafs - 1;j++)
+ {
+ if (pvs[j >> 3] & (1 << (j & 7)))
+ {
+ for (k = 0, mark = l->firstmarksurface;k < l->nummarksurfaces;k++, mark++)
+ {
+ surf = loadmodel->surfaces + *mark;
+ dist = DotProduct(e->origin, surf->plane->normal) - surf->plane->dist;
+ if (surf->flags & SURF_PLANEBACK)
+ dist = -dist;
+ if (dist > 0 && dist < e->cullradius)
+ loadmodel->surfacevisframes[j] = i - 1000000;
+ }
+ }
+ }
+ e->numsurfaces = 0;
+ for (j = 0;j < loadmodel->nummodelsurfaces;j++)
+ if (loadmodel->surfacevisframes[j] == i - 1000000)
+ e->numsurfaces++;
+ e->surfaces = NULL;
+ if (e->numsurfaces > 0)
+ {
+ e->surfaces = Mem_Alloc(loadmodel->mempool, sizeof(msurface_t *) * e->numsurfaces);
+ e->numsurfaces = 0;
+ for (j = 0;j < loadmodel->nummodelsurfaces;j++)
+ if (loadmodel->surfacevisframes[j] == i - 1000000)
+ e->surfaces[e->numsurfaces++] = loadmodel->surfaces + loadmodel->firstmodelsurface + j;
+ }
+ }
+}
+
/*
=================
void Mod_GenerateWallMesh (msurface_t *surf, int vertexonly)
{
- int i, iu, iv, *index, smax, tmax;
- float *in, s, t, u, v, ubase, vbase, uscale, vscale;
+ int i, iu, iv, *index, *n, smax, tmax;
+ float *in, s, t, u, v, ubase, vbase, uscale, vscale, normal[3];
surfmesh_t *mesh;
smax = surf->extents[0] >> 4;
vscale = (vscale - vbase) * 16.0 / ((surf->extents[1] & ~15) + 16);
}
- surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * (4 + 2 + 2 + 2 + 1) * sizeof(float));
+ surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[6]) + surf->poly_numverts * (4 + 2 + 2 + 2 + 1 + 3) * sizeof(float));
mesh->numverts = surf->poly_numverts;
mesh->numtriangles = surf->poly_numverts - 2;
mesh->verts = (float *)(mesh + 1);
mesh->ab = mesh->uv + mesh->numverts * 2;
mesh->lightmapoffsets = (int *)(mesh->ab + mesh->numverts * 2);
mesh->index = mesh->lightmapoffsets + mesh->numverts;
+ mesh->triangleneighbors = mesh->index + mesh->numtriangles * 3;
+ mesh->normals = (float *)(mesh->triangleneighbors + mesh->numtriangles * 3);
index = mesh->index;
+ n = mesh->triangleneighbors;
for (i = 0;i < mesh->numtriangles;i++)
{
*index++ = 0;
*index++ = i + 1;
*index++ = i + 2;
+ *n++ = i - 1;
+ *n++ = -1;
+ *n++ = i + 1;
}
+ VectorCopy(surf->plane->normal, normal);
+ if (surf->flags & SURF_PLANEBACK)
+ VectorNegate(normal, normal);
for (i = 0, in = surf->poly_verts;i < mesh->numverts;i++, in += 3)
{
s = DotProduct (in, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3];
mesh->ab[i * 2 + 0] = s * (1.0f / 16.0f);
mesh->ab[i * 2 + 1] = t * (1.0f / 16.0f);
mesh->lightmapoffsets[i] = ((iv * (smax+1) + iu) * 3);
+ mesh->normals[i * 3 + 0] = normal[0];
+ mesh->normals[i * 3 + 1] = normal[1];
+ mesh->normals[i * 3 + 2] = normal[2];
}
}
void Mod_GenerateVertexMesh (msurface_t *surf)
{
- int i, *index;
- float *in, s, t;
+ int i, *index, *n;
+ float *in, s, t, normal[3];
surfmesh_t *mesh;
surf->lightmaptexturestride = 0;
surf->lightmaptexture = NULL;
- surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * (4 + 2 + 2) * sizeof(float));
+ surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[6]) + surf->poly_numverts * (4 + 2 + 2 + 3) * sizeof(float));
mesh->numverts = surf->poly_numverts;
mesh->numtriangles = surf->poly_numverts - 2;
mesh->verts = (float *)(mesh + 1);
mesh->st = mesh->verts + mesh->numverts * 4;
mesh->ab = mesh->st + mesh->numverts * 2;
mesh->index = (int *)(mesh->ab + mesh->numverts * 2);
+ mesh->triangleneighbors = mesh->index + mesh->numtriangles * 3;
+ mesh->normals = (float *)(mesh->triangleneighbors + mesh->numtriangles * 3);
index = mesh->index;
+ n = mesh->triangleneighbors;
for (i = 0;i < mesh->numtriangles;i++)
{
*index++ = 0;
*index++ = i + 1;
*index++ = i + 2;
+ *n++ = -1;
+ *n++ = -1;
+ *n++ = i + 1;
}
+ VectorCopy(surf->plane->normal, normal);
+ if (surf->flags & SURF_PLANEBACK)
+ VectorNegate(normal, normal);
for (i = 0, in = surf->poly_verts;i < mesh->numverts;i++, in += 3)
{
s = (DotProduct (in, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]);
mesh->st[i * 2 + 1] = t / surf->texinfo->texture->height;
mesh->ab[i * 2 + 0] = s * (1.0f / 16.0f);
mesh->ab[i * 2 + 1] = t * (1.0f / 16.0f);
+ mesh->normals[i * 3 + 0] = normal[0];
+ mesh->normals[i * 3 + 1] = normal[1];
+ mesh->normals[i * 3 + 2] = normal[2];
}
}
void Mod_GenerateSurfacePolygon (msurface_t *surf)
{
int i, lindex;
- float *vec, *vert, mins[3], maxs[3];
+ float *vec, *vert, mins[3], maxs[3], temp[3], dist;
// convert edges back to a normal polygon
surf->poly_numverts = surf->numedges;
surf->poly_center[0] = (mins[0] + maxs[0]) * 0.5f;
surf->poly_center[1] = (mins[1] + maxs[1]) * 0.5f;
surf->poly_center[2] = (mins[2] + maxs[2]) * 0.5f;
+ surf->poly_radius2 = 0;
+ vert = surf->poly_verts;
+ for (i = 0;i < surf->poly_numverts;i++)
+ {
+ VectorSubtract(vert, surf->poly_center, temp);
+ dist = DotProduct(temp, temp);
+ if (surf->poly_radius2 < dist)
+ surf->poly_radius2 = dist;
+ vert += 3;
+ }
+ surf->poly_radius = sqrt(surf->poly_radius2);
}
/*
Mod_LoadBrushModel
=================
*/
+extern void R_DrawBrushModelFakeShadow (entity_render_t *ent);
void Mod_LoadBrushModel (model_t *mod, void *buffer)
{
int i, j;
dmodel_t *bm;
mempool_t *mainmempool;
char *loadname;
+ model_t *originalloadmodel;
mod->type = mod_brush;
loadname = mod->name;
Mod_LoadLightList ();
+ originalloadmodel = loadmodel;
//
// set up the submodels (FIXME: this is confusing)
mod->numleafs = bm->visleafs;
mod->Draw = R_DrawBrushModelNormal;
- mod->DrawFakeShadow = NULL;
+ mod->DrawFakeShadow = R_DrawBrushModelFakeShadow;
// LordHavoc: only register submodels if it is the world
// (prevents bsp models from replacing world submodels)
mod = loadmodel;
}
}
+
+ loadmodel = originalloadmodel;
+ Mod_ProcessLightList ();
}
int numverts;
int numtriangles;
float *verts;
+ float *normals;
int *lightmapoffsets;
float *st;
float *uv;
float *ab;
int *index;
+ int *triangleneighbors;
}
surfmesh_t;
float *poly_verts;
// bounding box for onscreen checks, and center for sorting
vec3_t poly_mins, poly_maxs, poly_center;
+ // bounding sphere radius (around poly_center)
+ float poly_radius, poly_radius2;
// these are regenerated every frame
// lighting info
float distbias;
// light style controlling this light
int style;
+ // maximum extent of the light for various purposes
+ float cullradius;
+ float cullradius2;
+ // surfaces this shines on
+ int numsurfaces;
+ msurface_t **surfaces;
// used only for loading calculations, number of leafs this shines on
//int numleafs;
}
R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap);
}
-void R_ShadowVolume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance, int visiblevolume)
+void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance, int visiblevolume)
{
int i, *e, *n, *out, tris;
float *v0, *v1, *v2, dir0[3], dir1[3], temp[3], f;
out += 6;
tris += 2;
// check the edges
- if (trianglefacinglight[n[0]])
+ if (n[0] < 0 || trianglefacinglight[n[0]])
{
out[0] = e[0];
out[1] = e[1];
out += 6;
tris += 2;
}
- if (trianglefacinglight[n[1]])
+ if (n[1] < 0 || trianglefacinglight[n[1]])
{
out[0] = e[1];
out[1] = e[2];
out += 6;
tris += 2;
}
- if (trianglefacinglight[n[2]])
+ if (n[2] < 0 || trianglefacinglight[n[2]])
{
out[0] = e[2];
out[1] = e[0];
}
else
{
- qglCullFace(GL_FRONT);
- //qglStencilFunc(
+ qglColorMask(0,0,0,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
+ 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);
+ qglColorMask(1,1,1,1);
+ }
+}
+
+void R_Shadow_VertexLight(int numverts, float *normals, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor)
+{
+ int i;
+ float *n, *v, *c, f, dist, temp[3];
+ // calculate vertex colors
+ for (i = 0, v = varray_vertex, c = varray_color, n = normals;i < numverts;i++, v += 4, c += 4, n += 3)
+ {
+ VectorSubtract(relativelightorigin, v, temp);
+ c[0] = 0;
+ c[1] = 0;
+ c[2] = 0;
+ c[3] = 1;
+ f = DotProduct(n, temp);
+ if (f > 0)
+ {
+ dist = DotProduct(temp, 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];
+ }
+ }
}
}
-void R_Shadow_BeginScene(void)
+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)
{
- rmeshstate_t m;
- memset(&m, 0, sizeof(m));
- m.blendfunc1 = GL_ONE;
- m.blendfunc2 = GL_ZERO;
- R_Mesh_State(&m);
+ qglClearStencil(0);
+ qglClear(GL_STENCIL_BUFFER_BIT);
}
#define R_SHADOW_H
void R_Shadow_Init(void);
-void R_ShadowVolume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance, int visiblevolume);
+void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float projectdistance, int visiblevolume);
+void R_Shadow_VertexLight(int numverts, float *normals, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor);
+void R_Shadow_RenderLightThroughStencil(int numverts, int numtris, int *elements, vec3_t relativelightorigin, float *normals);
+void R_Shadow_ClearStencil(void);
#endif
// this modifies the depth buffer so we have to clear it afterward
//R_SkyRoom();
// clear the depthbuffer that was used while rendering the skyroom
- //R_Mesh_ClearDepth();
+ //qglClear(GL_DEPTH_BUFFER_BIT);
}
*/
}
void (GLAPIENTRY *qglDepthFunc)(GLenum func);
void (GLAPIENTRY *qglDepthMask)(GLboolean flag);
void (GLAPIENTRY *qglDepthRange)(GLclampd near_val, GLclampd far_val);
+void (GLAPIENTRY *qglColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
void (GLAPIENTRY *qglDrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
void (GLAPIENTRY *qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
{"glDepthMask", (void **) &qglDepthMask},
{"glDepthRange", (void **) &qglDepthRange},
{"glDrawElements", (void **) &qglDrawElements},
+ {"glColorMask", (void **) &qglColorMask},
{"glVertexPointer", (void **) &qglVertexPointer},
// {"glNormalPointer", (void **) &qglNormalPointer},
{"glColorPointer", (void **) &qglColorPointer},