+
+void R_DrawModelShadowMaps(void)
+{
+ int i;
+ float relativethrowdistance, scale, size, nearclip, farclip, dot1, dot2;
+ entity_render_t *ent;
+ vec3_t relativelightorigin;
+ vec3_t relativelightdirection;
+ vec3_t relativeshadowmins, relativeshadowmaxs;
+ vec3_t shadowdir, shadowforward;
+ float m[12];
+ matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix;
+ r_viewport_t viewport;
+ GLuint fbo = 0;
+
+ if (!r_refdef.scene.numentities)
+ return;
+
+ switch (r_shadow_shadowmode)
+ {
+ case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
+ case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
+ break;
+ default:
+ return;
+ }
+
+ CHECKGLERROR
+ R_ResetViewRendering3D();
+ R_Shadow_RenderMode_Begin();
+ R_Shadow_RenderMode_ActiveLight(NULL);
+
+ switch (r_shadow_shadowmode)
+ {
+ case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
+ if (!r_shadow_shadowmap2dtexture)
+ R_Shadow_MakeShadowMap(0, r_shadow_shadowmapmaxsize);
+ fbo = r_shadow_fbo2d;
+ r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
+ r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
+ r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
+ break;
+ case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
+ if (!r_shadow_shadowmaprectangletexture)
+ R_Shadow_MakeShadowMap(0, r_shadow_shadowmapmaxsize);
+ fbo = r_shadow_fborectangle;
+ r_shadow_shadowmap_texturescale[0] = 1.0f;
+ r_shadow_shadowmap_texturescale[1] = 1.0f;
+ r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
+ break;
+ default:
+ break;
+ }
+
+ size = 2*r_shadow_shadowmapmaxsize;
+
+ r_shadow_shadowmap_parameters[0] = bound(0.0f, 1.0f - r_shadows_darken.value, 1.0f);
+ r_shadow_shadowmap_parameters[1] = 1.0f;
+ r_shadow_shadowmap_parameters[2] = size;
+ r_shadow_shadowmap_parameters[3] = size;
+
+ scale = r_shadow_shadowmapping_precision.value;
+ nearclip = -r_shadows_throwdistance.value;
+ farclip = r_shadows_throwdistance.value;
+ Math_atov(r_shadows_throwdirection.string, shadowdir);
+ VectorNormalize(shadowdir);
+ dot1 = DotProduct(r_refdef.view.forward, shadowdir);
+ dot2 = DotProduct(r_refdef.view.up, shadowdir);
+ if (fabs(dot1) <= fabs(dot2))
+ VectorMA(r_refdef.view.forward, -dot1, shadowdir, shadowforward);
+ else
+ VectorMA(r_refdef.view.up, -dot2, shadowdir, shadowforward);
+ VectorNormalize(shadowforward);
+ VectorM(scale, shadowforward, &m[0]);
+ m[3] = fabs(dot1) * 0.5f * size - DotProduct(r_refdef.view.origin, &m[0]);
+ CrossProduct(shadowdir, shadowforward, &m[4]);
+ VectorM(scale, &m[4], &m[4]);
+ m[7] = 0.5f * size - DotProduct(r_refdef.view.origin, &m[4]);
+ VectorM(1.0f / (farclip - nearclip), shadowdir, &m[8]);
+ m[11] = 0.5f - DotProduct(r_refdef.view.origin, &m[8]);
+ Matrix4x4_FromArray12FloatD3D(&shadowmatrix, m);
+ Matrix4x4_Invert_Full(&cameramatrix, &shadowmatrix);
+ R_Viewport_InitOrtho(&viewport, &cameramatrix, 0, 0, size, size, 0, size, size, 0, 0, -1, NULL);
+
+#if 0
+ qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);CHECKGLERROR
+ R_SetupShader_ShowDepth();
+#else
+ qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);CHECKGLERROR
+ R_SetupShader_DepthOrShadow();
+#endif
+ CHECKGLERROR
+ GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+ R_SetViewport(&viewport);
+ GL_Scissor(viewport.x, viewport.y, min(viewport.width + r_shadow_shadowmapborder, 2*r_shadow_shadowmapmaxsize), viewport.height + r_shadow_shadowmapborder);
+ qglClearDepth(1);
+#if 0
+ qglClearColor(1,1,1,1);
+ GL_Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+#else
+ GL_Clear(GL_DEPTH_BUFFER_BIT);
+#endif
+ GL_Scissor(viewport.x + r_shadow_shadowmapborder, viewport.y + r_shadow_shadowmapborder, viewport.width - 2*r_shadow_shadowmapborder, viewport.height - 2*r_shadow_shadowmapborder);
+ CHECKGLERROR
+
+ for (i = 0;i < r_refdef.scene.numentities;i++)
+ {
+ ent = r_refdef.scene.entities[i];
+
+ // cast shadows from anything of the map (submodels are optional)
+ if (ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW))
+ {
+ relativethrowdistance = r_shadows_throwdistance.value * Matrix4x4_ScaleFromMatrix(&ent->inversematrix);
+ VectorSet(relativeshadowmins, -relativethrowdistance, -relativethrowdistance, -relativethrowdistance);
+ VectorSet(relativeshadowmaxs, relativethrowdistance, relativethrowdistance, relativethrowdistance);
+ Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection);
+ VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin);
+ RSurf_ActiveModelEntity(ent, false, false, false);
+ ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs);
+ rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
+ }
+ }
+
+ R_Shadow_RenderMode_End();
+
+ Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
+ Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
+ Matrix4x4_Concat(&r_shadow_shadowmapmatrix, &shadowmatrix, &invmvpmatrix);
+
+ r_shadow_usingshadowmaportho = true;
+ switch (r_shadow_shadowmode)
+ {
+ case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
+ r_shadow_usingshadowmap2d = true;
+ break;
+ case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
+ r_shadow_usingshadowmaprect = true;
+ break;
+ default:
+ break;
+ }
+}
+