#include "quakedef.h"
#include "r_shadow.h"
+#include "portals.h"
#define MAX_LIGHTMAP_SIZE 256
// NVIDIA Geforce3 distortion texture shader on water
float args[4] = {0.05f,0,0,0.04f};
memset(&m, 0, sizeof(m));
- m.tex[0] = R_GetTexture(mod_shared_distorttexture[(int)(r_refdef.time * 16)&63]);
+ m.tex[0] = R_GetTexture(r_texture_distorttexture[(int)(r_refdef.time * 16)&63]);
m.tex[1] = R_GetTexture(texture->skin.base);
m.texcombinergb[0] = GL_REPLACE;
m.texcombinergb[1] = GL_REPLACE;
model_t *model;
vec3_t relativelightorigin;
float lightradius;
- int *outclusterlist;
- qbyte *outclusterpvs;
- int outnumclusters;
+ int *outleaflist;
+ qbyte *outleafpvs;
+ int outnumleafs;
int *outsurfacelist;
qbyte *outsurfacepvs;
int outnumsurfaces;
info->outmaxs[0] = max(info->outmaxs[0], leaf->maxs[0]);
info->outmaxs[1] = max(info->outmaxs[1], leaf->maxs[1]);
info->outmaxs[2] = max(info->outmaxs[2], leaf->maxs[2]);
- if (info->outclusterpvs)
+ if (info->outleafpvs)
{
- if (!CHECKPVSBIT(info->outclusterpvs, leaf->clusterindex))
+ int leafindex = leaf - info->model->brush.data_leafs;
+ if (!CHECKPVSBIT(info->outleafpvs, leafindex))
{
- SETPVSBIT(info->outclusterpvs, leaf->clusterindex);
- info->outclusterlist[info->outnumclusters++] = leaf->clusterindex;
+ SETPVSBIT(info->outleafpvs, leafindex);
+ info->outleaflist[info->outnumleafs++] = leafindex;
}
}
if (info->outsurfacepvs)
v[0] = info->model->brush.shadowmesh->vertex3f + e[0] * 3;
v[1] = info->model->brush.shadowmesh->vertex3f + e[1] * 3;
v[2] = info->model->brush.shadowmesh->vertex3f + e[2] * 3;
- if (info->lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && info->lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && info->lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && info->lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && info->lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && info->lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+ if (PointInfrontOfTriangle(info->relativelightorigin, v[0], v[1], v[2]) && info->lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && info->lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && info->lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && info->lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && info->lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && info->lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
{
SETPVSBIT(info->outsurfacepvs, surfaceindex);
info->outsurfacelist[info->outnumsurfaces++] = surfaceindex;
}
}
-void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outclusterlist, qbyte *outclusterpvs, int *outnumclusterspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer)
+void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, qbyte *outleafpvs, int *outnumleafspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer)
{
r_q1bsp_getlightinfo_t info;
VectorCopy(relativelightorigin, info.relativelightorigin);
{
VectorCopy(info.lightmins, outmins);
VectorCopy(info.lightmaxs, outmaxs);
- *outnumclusterspointer = 0;
+ *outnumleafspointer = 0;
*outnumsurfacespointer = 0;
return;
}
info.model = ent->model;
- info.outclusterlist = outclusterlist;
- info.outclusterpvs = outclusterpvs;
- info.outnumclusters = 0;
+ info.outleaflist = outleaflist;
+ info.outleafpvs = outleafpvs;
+ info.outnumleafs = 0;
info.outsurfacelist = outsurfacelist;
info.outsurfacepvs = outsurfacepvs;
info.outnumsurfaces = 0;
VectorCopy(info.relativelightorigin, info.outmins);
VectorCopy(info.relativelightorigin, info.outmaxs);
- memset(outclusterpvs, 0, info.model->brush.num_pvsclusterbytes);
+ memset(outleafpvs, 0, (info.model->brush.num_leafs + 7) >> 3);
memset(outsurfacepvs, 0, (info.model->nummodelsurfaces + 7) >> 3);
if (info.model->brush.GetPVS)
info.pvs = info.model->brush.GetPVS(info.model, info.relativelightorigin);
else
info.pvs = NULL;
R_UpdateAllTextureInfo(ent);
- // use BSP recursion as lights are often small
- R_Q1BSP_RecursiveGetLightInfo(&info, info.model->brush.data_nodes);
+ if (r_shadow_compilingrtlight)
+ {
+ // use portal recursion for exact light volume culling, and exact surface checking
+ Portal_Visibility(info.model, info.relativelightorigin, info.outleaflist, info.outleafpvs, &info.outnumleafs, info.outsurfacelist, info.outsurfacepvs, &info.outnumsurfaces, NULL, 0, true, info.lightmins, info.lightmaxs, info.outmins, info.outmaxs);
+ }
+ else if (r_shadow_realtime_dlight_portalculling.integer)
+ {
+ // use portal recursion for exact light volume culling, but not the expensive exact surface checking
+ Portal_Visibility(info.model, info.relativelightorigin, info.outleaflist, info.outleafpvs, &info.outnumleafs, info.outsurfacelist, info.outsurfacepvs, &info.outnumsurfaces, NULL, 0, r_shadow_realtime_dlight_portalculling.integer >= 2, info.lightmins, info.lightmaxs, info.outmins, info.outmaxs);
+ }
+ else
+ {
+ // use BSP recursion as lights are often small
+ R_Q1BSP_RecursiveGetLightInfo(&info, info.model->brush.data_nodes);
+ }
// limit combined leaf box to light boundaries
- outmins[0] = max(info.outmins[0], info.lightmins[0]);
- outmins[1] = max(info.outmins[1], info.lightmins[1]);
- outmins[2] = max(info.outmins[2], info.lightmins[2]);
- outmaxs[0] = min(info.outmaxs[0], info.lightmaxs[0]);
- outmaxs[1] = min(info.outmaxs[1], info.lightmaxs[1]);
- outmaxs[2] = min(info.outmaxs[2], info.lightmaxs[2]);
-
- *outnumclusterspointer = info.outnumclusters;
+ outmins[0] = max(info.outmins[0] - 1, info.lightmins[0]);
+ outmins[1] = max(info.outmins[1] - 1, info.lightmins[1]);
+ outmins[2] = max(info.outmins[2] - 1, info.lightmins[2]);
+ outmaxs[0] = min(info.outmaxs[0] + 1, info.lightmaxs[0]);
+ outmaxs[1] = min(info.outmaxs[1] + 1, info.lightmaxs[1]);
+ outmaxs[2] = min(info.outmaxs[2] + 1, info.lightmaxs[2]);
+
+ *outnumleafspointer = info.outnumleafs;
*outnumsurfacespointer = info.outnumsurfaces;
}
int surfacelistindex;
if (r_drawcollisionbrushes.integer < 2)
{
- R_Mesh_Matrix(&ent->matrix);
R_Shadow_PrepareShadowMark(model->brush.shadowmesh->numtriangles);
if (!r_shadow_compilingrtlight)
R_UpdateAllTextureInfo(ent);
}
}
-void R_Q1BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int numsurfaces, const int *surfacelist, int visiblelighting)
+void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolor, int numsurfaces, const int *surfacelist)
{
model_t *model = ent->model;
msurface_t *surface;
// if compiling an rtlight, capture the mesh
t = surface->texture;
if ((t->basematerialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL)
+ {
+#if 1
+ int tri;
+ int *e;
+ float *lightmins, *lightmaxs, *v[3], *vertex3f;
+ e = surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle;
+ vertex3f = surface->groupmesh->data_vertex3f;
+ lightmins = r_shadow_compilingrtlight->cullmins;
+ lightmaxs = r_shadow_compilingrtlight->cullmaxs;
+ for (tri = 0;tri < surface->num_triangles;tri++, e += 3)
+ {
+ v[0] = vertex3f + e[0] * 3;
+ v[1] = vertex3f + e[1] * 3;
+ v[2] = vertex3f + e[2] * 3;
+ if (PointInfrontOfTriangle(r_shadow_compilingrtlight->shadoworigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
+ Mod_ShadowMesh_AddMesh(r_shadow_mempool, r_shadow_compilingrtlight->static_meshchain_light, surface->texture->skin.base, surface->texture->skin.gloss, surface->texture->skin.nmap, surface->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, 1, e);
+ }
+#else
Mod_ShadowMesh_AddMesh(r_shadow_mempool, r_shadow_compilingrtlight->static_meshchain_light, surface->texture->skin.base, surface->texture->skin.gloss, surface->texture->skin.nmap, surface->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
+#endif
+ }
}
else if (ent != r_refdef.worldentity || r_worldsurfacevisible[surfacelist[surfacelistindex]])
{
{
if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
qglDisable(GL_CULL_FACE);
- R_Shadow_RenderLighting(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle), surface->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, NULL, NULL, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, NULL, NULL, t->skin.nmap, t->skin.gloss, lightcubemap, ambientscale, diffusescale, specularscale, visiblelighting);
+ R_Shadow_RenderLighting(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle), surface->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, lightcolor, vec3_origin, vec3_origin, t->skin.base, NULL, NULL, t->skin.nmap, t->skin.gloss);
if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
qglEnable(GL_CULL_FACE);
}