+ if (visiblevolumes)
+ {
+ memset(&m, 0, sizeof(m));
+ m.blendfunc1 = GL_ONE;
+ m.blendfunc2 = GL_ONE;
+ if (r_shadow_visiblevolumes.integer >= 2)
+ m.depthdisable = true;
+ R_Mesh_State(&m);
+ qglDisable(GL_CULL_FACE);
+ GL_Color(0.0 * r_colorscale, 0.0125 * r_colorscale, 0.1 * r_colorscale, 1);
+ }
+ else
+ R_Shadow_Stage_Begin();
+ shadowframecount++;
+ if (r_shadow_realtime_world.integer)
+ {
+ R_Shadow_LoadWorldLightsIfNeeded();
+ for (lnum = 0, wl = r_shadow_worldlightchain;wl;wl = wl->next, lnum++)
+ {
+ if (d_lightstylevalue[wl->style] <= 0)
+ continue;
+ if (R_CullBox(wl->mins, wl->maxs))
+ //if (R_CullSphere(wl->origin, cullradius))
+ continue;
+ //if (R_CullBox(wl->mins, wl->maxs) || R_CullSphere(wl->origin, lightradius))
+ // continue;
+ //if (VIS_CullBox(wl->mins, wl->maxs) || VIS_CullSphere(wl->origin, lightradius))
+ // continue;
+ if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
+ continue;
+
+ cullradius = wl->cullradius;
+ lightradius = wl->lightradius;
+
+ if (cl.worldmodel != NULL)
+ {
+ for (i = 0;i < wl->numleafs;i++)
+ if (wl->leafs[i]->visframe == r_framecount)
+ break;
+ if (i == wl->numleafs)
+ continue;
+ leaf = wl->leafs[i++];
+ VectorCopy(leaf->mins, clipmins);
+ VectorCopy(leaf->maxs, clipmaxs);
+ for (;i < wl->numleafs;i++)
+ {
+ leaf = wl->leafs[i];
+ if (leaf->visframe == r_framecount)
+ {
+ if (clipmins[0] > leaf->mins[0]) clipmins[0] = leaf->mins[0];
+ if (clipmaxs[0] < leaf->maxs[0]) clipmaxs[0] = leaf->maxs[0];
+ if (clipmins[1] > leaf->mins[1]) clipmins[1] = leaf->mins[1];
+ if (clipmaxs[1] < leaf->maxs[1]) clipmaxs[1] = leaf->maxs[1];
+ if (clipmins[2] > leaf->mins[2]) clipmins[2] = leaf->mins[2];
+ if (clipmaxs[2] < leaf->maxs[2]) clipmaxs[2] = leaf->maxs[2];
+ }
+ }
+ if (clipmins[0] < wl->mins[0]) clipmins[0] = wl->mins[0];
+ if (clipmaxs[0] > wl->maxs[0]) clipmaxs[0] = wl->maxs[0];
+ if (clipmins[1] < wl->mins[1]) clipmins[1] = wl->mins[1];
+ if (clipmaxs[1] > wl->maxs[1]) clipmaxs[1] = wl->maxs[1];
+ if (clipmins[2] < wl->mins[2]) clipmins[2] = wl->mins[2];
+ if (clipmaxs[2] > wl->maxs[2]) clipmaxs[2] = wl->maxs[2];
+ }
+ else
+ {
+ VectorCopy(wl->mins, clipmins);
+ VectorCopy(wl->maxs, clipmaxs);
+ }
+
+ //if (R_Shadow_ScissorForBBoxAndSphere(clipmins, clipmaxs, wl->origin, wl->cullradius))
+ if (R_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
+ continue;
+
+ // mark the leafs we care about so only things in those leafs will matter
+ if (cl.worldmodel != NULL)
+ for (i = 0;i < wl->numleafs;i++)
+ wl->leafs[i]->worldnodeframe = shadowframecount;
+
+ f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
+ VectorScale(wl->light, f, lightcolor);
+ if (wl->selected)
+ {
+ f = 2 + sin(realtime * M_PI * 4.0);
+ VectorScale(lightcolor, f, lightcolor);
+ }
+
+ if (wl->castshadows && (gl_stencil || visiblevolumes))
+ {
+ if (!visiblevolumes)
+ R_Shadow_Stage_ShadowVolumes();
+ ent = &cl_entities[0].render;
+ if (wl->shadowvolume && r_shadow_staticworldlights.integer)
+ R_Shadow_DrawWorldLightShadowVolume(&ent->matrix, wl);
+ else
+ R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
+ if (r_drawentities.integer)
+ for (i = 0;i < r_refdef.numentities;i++)
+ R_TestAndDrawShadowVolume(r_refdef.entities[i], wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs, true);
+ }
+
+ if (!visiblevolumes)
+ {
+ if (wl->castshadows && gl_stencil)
+ R_Shadow_Stage_LightWithShadows();
+ else
+ R_Shadow_Stage_LightWithoutShadows();
+
+ // calculate world to filter matrix
+ Matrix4x4_CreateFromQuakeEntity(&matrix, wl->origin[0], wl->origin[1], wl->origin[2], wl->angles[0], wl->angles[1], wl->angles[2], lightradius);
+ Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
+ // calculate world to attenuationxyz/xy matrix
+ Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
+ Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
+ // calculate world to attenuationz matrix
+ matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
+ matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
+ matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
+ matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
+ Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
+
+ ent = &cl_entities[0].render;
+ if (ent->model && ent->model->DrawLight)
+ {
+ Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
+ Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+ Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
+ Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
+ Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
+ if (wl->numsurfaces)
+ R_Model_Brush_DrawLightForSurfaceList(ent, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, wl->surfaces, wl->numsurfaces, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
+ else
+ ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
+ }
+ 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
+ && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
+ && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
+ {
+ Matrix4x4_Transform(&ent->inversematrix, wl->origin, relativelightorigin);
+ Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+ Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
+ Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
+ Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
+ ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer)
+ {
+ for (lnum = 0, rd = r_dlight;lnum < r_numdlights;lnum++, rd++)
+ {
+ lightradius = rd->cullradius;
+ clipmins[0] = rd->origin[0] - lightradius;
+ clipmins[1] = rd->origin[1] - lightradius;
+ clipmins[2] = rd->origin[2] - lightradius;
+ clipmaxs[0] = rd->origin[0] + lightradius;
+ clipmaxs[1] = rd->origin[1] + lightradius;
+ clipmaxs[2] = rd->origin[2] + lightradius;
+ if (VIS_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
+ continue;
+
+ cullradius = RadiusFromBoundsAndOrigin(clipmins, clipmaxs, rd->origin);
+ VectorScale(rd->light, (1.0f / 4096.0f), lightcolor);
+
+ if (gl_stencil || visiblevolumes)
+ {
+ if (!visiblevolumes)
+ R_Shadow_Stage_ShadowVolumes();
+ ent = &cl_entities[0].render;
+ R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
+ if (r_drawentities.integer)
+ {
+ for (i = 0;i < r_refdef.numentities;i++)
+ {
+ ent = r_refdef.entities[i];
+ if (ent != rd->ent)
+ R_TestAndDrawShadowVolume(ent, rd->origin, cullradius, lightradius, clipmins, clipmaxs, clipmins, clipmaxs, false);
+ }
+ }
+ }
+
+ if (!visiblevolumes)
+ {
+ if (gl_stencil)
+ R_Shadow_Stage_LightWithShadows();
+ else
+ R_Shadow_Stage_LightWithoutShadows();
+
+ // calculate world to filter matrix
+ Matrix4x4_CreateFromQuakeEntity(&matrix, rd->origin[0], rd->origin[1], rd->origin[2], 0, 0, 0, lightradius);
+ Matrix4x4_Invert_Simple(&matrix_worldtofilter, &matrix);
+ // calculate world to attenuationxyz/xy matrix
+ Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5, 0.5, 0.5, 0, 0, 0, 0.5);
+ Matrix4x4_Concat(&matrix_worldtoattenuationxyz, &matrix, &matrix_worldtofilter);
+ // calculate world to attenuationz matrix
+ matrix.m[0][0] = 0;matrix.m[0][1] = 0;matrix.m[0][2] = 0.5;matrix.m[0][3] = 0.5;
+ matrix.m[1][0] = 0;matrix.m[1][1] = 0;matrix.m[1][2] = 0 ;matrix.m[1][3] = 0.5;
+ matrix.m[2][0] = 0;matrix.m[2][1] = 0;matrix.m[2][2] = 0 ;matrix.m[2][3] = 0.5;
+ matrix.m[3][0] = 0;matrix.m[3][1] = 0;matrix.m[3][2] = 0 ;matrix.m[3][3] = 1;
+ Matrix4x4_Concat(&matrix_worldtoattenuationz, &matrix, &matrix_worldtofilter);
+
+ ent = &cl_entities[0].render;
+ if (ent->model && ent->model->DrawLight)
+ {
+ Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
+ Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+ Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
+ Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
+ Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
+ ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
+ }
+ 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
+ && BoxesOverlap(ent->mins, ent->maxs, clipmins, clipmaxs)
+ && !(ent->effects & EF_ADDITIVE) && ent->alpha == 1)
+ {
+ Matrix4x4_Transform(&ent->inversematrix, rd->origin, relativelightorigin);
+ Matrix4x4_Transform(&ent->inversematrix, r_origin, relativeeyeorigin);
+ Matrix4x4_Concat(&matrix_modeltofilter, &matrix_worldtofilter, &ent->matrix);
+ Matrix4x4_Concat(&matrix_modeltoattenuationxyz, &matrix_worldtoattenuationxyz, &ent->matrix);
+ Matrix4x4_Concat(&matrix_modeltoattenuationz, &matrix_worldtoattenuationz, &ent->matrix);
+ ent->model->DrawLight(ent, relativelightorigin, relativeeyeorigin, lightradius / ent->scale, lightcolor, &matrix_modeltofilter, &matrix_modeltoattenuationxyz, &matrix_modeltoattenuationz);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!visiblevolumes)
+ R_Shadow_Stage_End();
+ qglEnable(GL_CULL_FACE);
+ qglDisable(GL_SCISSOR_TEST);
+}
+
+static void R_SetFrustum (void)
+{