X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=r_shadow.c;h=f546b146ca6bbd551b1d31ee9eac96a127cf7abc;hb=19f4a480fcbe200d55f810915e0629e40e892ad6;hp=2b9f48e2d9dde8acf3091b6c138c9e61ba35b293;hpb=649e13e4347e891b622d2dbb1a8502c423d92d31;p=xonotic%2Fdarkplaces.git diff --git a/r_shadow.c b/r_shadow.c index 2b9f48e2..f546b146 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -349,6 +349,7 @@ static memexpandablearray_t r_shadow_worldlightsarray; dlight_t *r_shadow_selectedlight; dlight_t r_shadow_bufferlight; vec3_t r_editlights_cursorlocation; +qboolean r_editlights_lockcursor; extern int con_vislines; @@ -442,6 +443,12 @@ void R_Shadow_SetShadowMode(void) r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D; break; } + // Cg has very little choice in depth texture sampling + if (vid.cgcontext) + { + r_shadow_shadowmapsampler = false; + r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D; + } } break; case RENDERPATH_GL13: @@ -659,7 +666,7 @@ void r_shadow_newmap(void) if (r_editlights_sprcubemaplight) R_SkinFrame_MarkUsed(r_editlights_sprcubemaplight); if (r_editlights_sprcubemapnoshadowlight) R_SkinFrame_MarkUsed(r_editlights_sprcubemapnoshadowlight); if (r_editlights_sprselection) R_SkinFrame_MarkUsed(r_editlights_sprselection); - if (cl.worldmodel && strncmp(cl.worldmodel->name, r_shadow_mapname, sizeof(r_shadow_mapname))) + if (strncmp(cl.worldname, r_shadow_mapname, sizeof(r_shadow_mapname))) R_Shadow_EditLights_Reload_f(); } @@ -1317,8 +1324,8 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_VISIBLEVOLUMES) { tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris); - R_Mesh_VertexPointer(shadowvertex3f, 0, 0); - R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0); + R_Mesh_PrepareVertices_Position_Arrays(outverts, shadowvertex3f); + R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0); } else { @@ -1332,13 +1339,12 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, r_refdef.stats.lights_dynamicshadowtriangles += tris; r_refdef.stats.lights_shadowtriangles += tris; CHECKGLERROR - R_Mesh_VertexPointer(shadowvertex3f, 0, 0); if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL) { // increment stencil if frontface is infront of depthbuffer GL_CullFace(r_refdef.view.cullface_front); qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR - R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0); + R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0); // decrement stencil if backface is infront of depthbuffer GL_CullFace(r_refdef.view.cullface_back); qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR @@ -1348,12 +1354,13 @@ void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, // decrement stencil if backface is behind depthbuffer GL_CullFace(r_refdef.view.cullface_front); qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR - R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0); + R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0); // increment stencil if frontface is behind depthbuffer GL_CullFace(r_refdef.view.cullface_back); qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR } - R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0); + R_Mesh_PrepareVertices_Position_Arrays(outverts, shadowvertex3f); + R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0); CHECKGLERROR } } @@ -1507,19 +1514,48 @@ int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border) } // this next test usually clips off more sides than the former, but occasionally clips fewer/different ones, so do both and combine results // check if frustum corners/origin cross plane sides +#if 1 + // infinite version, assumes frustum corners merely give direction and extend to infinite distance + Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.origin, p); + dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn); + masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2)); + masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2)); + dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn); + masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4)); + masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4)); + dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn); + masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0)); + masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0)); + for (i = 0;i < 4;i++) + { + Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.frustumcorner[i], n); + VectorSubtract(n, p, n); + dp = n[0] + n[1], dn = n[0] - n[1], ap = fabs(dp), an = fabs(dn); + if(ap > 0) masks[0] |= dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2); + if(an > 0) masks[1] |= dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2); + dp = n[1] + n[2], dn = n[1] - n[2], ap = fabs(dp), an = fabs(dn); + if(ap > 0) masks[2] |= dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4); + if(an > 0) masks[3] |= dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4); + dp = n[2] + n[0], dn = n[2] - n[0], ap = fabs(dp), an = fabs(dn); + if(ap > 0) masks[4] |= dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0); + if(an > 0) masks[5] |= dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0); + } +#else + // finite version, assumes corners are a finite distance from origin dependent on far plane for (i = 0;i < 5;i++) { Matrix4x4_Transform(&rtlight->matrix_worldtolight, !i ? r_refdef.view.origin : r_refdef.view.frustumcorner[i-1], p); - dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn), + dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn); masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2)); masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2)); - dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn), + dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn); masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4)); masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4)); - dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn), + dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn); masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0)); masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0)); } +#endif return sides & masks[0] & masks[1] & masks[2] & masks[3] & masks[4] & masks[5]; } @@ -1860,6 +1896,8 @@ void R_Shadow_ValidateCvars(void) Cvar_SetValueQuick(&gl_ext_stenciltwoside, 0); } +static const r_vertexposition_t resetvertexposition[3]; + void R_Shadow_RenderMode_Begin(void) { #if 0 @@ -1875,8 +1913,8 @@ void R_Shadow_RenderMode_Begin(void) R_Shadow_MakeTextures(); CHECKGLERROR - R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); + R_Mesh_PrepareVertices_Position(0, resetvertexposition, NULL); GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthRange(0, 1); GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset); @@ -1955,8 +1993,8 @@ void R_Shadow_RenderMode_Reset(void) #endif R_SetViewport(&r_refdef.view.viewport); GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]); - R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); + R_Mesh_PrepareVertices_Position(0, resetvertexposition, NULL); GL_DepthRange(0, 1); GL_DepthTest(true); GL_DepthMask(false); @@ -2108,15 +2146,15 @@ void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size) nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius; farclip = 1.0f; bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius; - r_shadow_shadowmap_parameters[2] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip); - r_shadow_shadowmap_parameters[3] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias; + r_shadow_shadowmap_parameters[1] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias; + r_shadow_shadowmap_parameters[3] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip); r_shadow_shadowmapside = side; r_shadow_shadowmapsize = size; switch (r_shadow_shadowmode) { case R_SHADOW_SHADOWMODE_SHADOWMAP2D: r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder); - r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size; + r_shadow_shadowmap_parameters[2] = r_shadow_shadowmapvsdct ? 2.5f*size : size; R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL); if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D) goto init_done; @@ -2133,7 +2171,7 @@ void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size) break; case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder); - r_shadow_shadowmap_parameters[1] = r_shadow_shadowmapvsdct ? 2.5f*size : size; + r_shadow_shadowmap_parameters[2] = r_shadow_shadowmapvsdct ? 2.5f*size : size; R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL); if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE) goto init_done; @@ -2150,7 +2188,7 @@ void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size) break; case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE: r_shadow_shadowmap_parameters[0] = 1.0f; - r_shadow_shadowmap_parameters[1] = 1.0f; + r_shadow_shadowmap_parameters[2] = 1.0f; R_Viewport_InitCubeSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, nearclip, farclip, NULL); if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE) goto init_done; @@ -2266,7 +2304,7 @@ void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qb break; } } - R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0); + //R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0); CHECKGLERROR } @@ -2335,8 +2373,6 @@ void R_Shadow_RenderMode_DrawDeferredLight(qboolean stenciltest, qboolean shadow for (i = 0;i < 8;i++) Matrix4x4_Transform(matrix, bboxpoints[i], vertex3f + i*3); CHECKGLERROR - R_Mesh_VertexPointer(vertex3f, 0, 0); - R_Mesh_ColorPointer(NULL, 0, 0); GL_ColorMask(1,1,1,1); GL_DepthMask(false); GL_DepthRange(0, 1); @@ -2344,7 +2380,8 @@ void R_Shadow_RenderMode_DrawDeferredLight(qboolean stenciltest, qboolean shadow GL_DepthTest(true); qglDepthFunc(GL_GREATER);CHECKGLERROR GL_CullFace(r_refdef.view.cullface_back); - R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0); + R_Mesh_PrepareVertices_Position_Arrays(8, vertex3f); + R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0); } } @@ -2525,11 +2562,12 @@ qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs) return false; } -static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, int numtriangles, const int *element3i, const float *diffusecolor, const float *ambientcolor) +static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, const float *diffusecolor, const float *ambientcolor) { - const float *vertex3f = rsurface.vertex3f + 3 * firstvertex; - const float *normal3f = rsurface.normal3f + 3 * firstvertex; - float *color4f = rsurface.array_color4f + 4 * firstvertex; + int i; + const float *vertex3f; + const float *normal3f; + float *color4f; float dist, dot, distintensity, shadeintensity, v[3], n[3]; switch (r_shadow_rendermode) { @@ -2537,7 +2575,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN: if (VectorLength2(diffusecolor) > 0) { - for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4) + for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4) { Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v); Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n); @@ -2559,7 +2597,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu } else { - for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4) + for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4) { VectorCopy(ambientcolor, color4f); if (r_refdef.fogenabled) @@ -2567,7 +2605,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu float f; Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v); f = RSurf_FogVertex(vertex3f); - VectorScale(color4f, f, color4f); + VectorScale(color4f + 4*i, f, color4f); } color4f[3] = 1; } @@ -2576,7 +2614,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN: if (VectorLength2(diffusecolor) > 0) { - for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4) + for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4) { Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v); if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)])) @@ -2609,7 +2647,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu } else { - for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4) + for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4) { Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v); if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)])) @@ -2633,7 +2671,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu case R_SHADOW_RENDERMODE_LIGHT_VERTEX: if (VectorLength2(diffusecolor) > 0) { - for (;numverts > 0;numverts--, vertex3f += 3, normal3f += 3, color4f += 4) + for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4) { Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v); if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)])) @@ -2667,7 +2705,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu } else { - for (;numverts > 0;numverts--, vertex3f += 3, color4f += 4) + for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4) { Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v); if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)])) @@ -2694,21 +2732,23 @@ static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int nu } } -static void R_Shadow_RenderLighting_VisibleLighting(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject) +static void R_Shadow_RenderLighting_VisibleLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist) { // used to display how many times a surface is lit for level design purposes - R_Mesh_Draw(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject); + RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist); + R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL); + RSurf_DrawBatch(); } -static void R_Shadow_RenderLighting_Light_GLSL(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject, const vec3_t lightcolor, float ambientscale, float diffusescale, float specularscale) +static void R_Shadow_RenderLighting_Light_GLSL(int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t lightcolor, float ambientscale, float diffusescale, float specularscale) { // ARB2 GLSL shader path (GFFX5200, Radeon 9500) - R_SetupShader_Surface(lightcolor, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT); + R_SetupShader_Surface(lightcolor, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist); if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) { qglDepthFunc(GL_EQUAL);CHECKGLERROR } - R_Mesh_Draw(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject); + RSurf_DrawBatch(); if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) { qglDepthFunc(GL_LEQUAL);CHECKGLERROR @@ -2728,7 +2768,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve float *c; int maxtriangles = 4096; static int newelements[4096*3]; - R_Shadow_RenderLighting_Light_Vertex_Shading(firstvertex, numvertices, numtriangles, element3i, diffusecolor2, ambientcolor2); + R_Shadow_RenderLighting_Light_Vertex_Shading(firstvertex, numvertices, diffusecolor2, ambientcolor2); for (renders = 0;renders < 4;renders++) { stop = true; @@ -2743,7 +2783,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve // renders them at once for (i = 0, e = element3i;i < numtriangles;i++, e += 3) { - if (VectorLength2(rsurface.array_color4f + e[0] * 4) + VectorLength2(rsurface.array_color4f + e[1] * 4) + VectorLength2(rsurface.array_color4f + e[2] * 4) >= 0.01) + if (VectorLength2(rsurface.array_passcolor4f + e[0] * 4) + VectorLength2(rsurface.array_passcolor4f + e[1] * 4) + VectorLength2(rsurface.array_passcolor4f + e[2] * 4) >= 0.01) { if (newnumtriangles) { @@ -2766,7 +2806,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve newe += 3; if (newnumtriangles >= maxtriangles) { - R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, 0); + R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, NULL, NULL, 0); newnumtriangles = 0; newe = newelements; stop = false; @@ -2775,7 +2815,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve } if (newnumtriangles >= 1) { - R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, 0); + R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, NULL, NULL, 0); stop = false; } // if we couldn't find any lit triangles, exit early @@ -2786,7 +2826,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve // handling of negative colors // (some old drivers even have improper handling of >1 color) stop = true; - for (i = 0, c = rsurface.array_color4f + 4 * firstvertex;i < numvertices;i++, c += 4) + for (i = 0, c = rsurface.array_passcolor4f + 4 * firstvertex;i < numvertices;i++, c += 4) { if (c[0] > 1 || c[1] > 1 || c[2] > 1) { @@ -2804,7 +2844,7 @@ static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numve } } -static void R_Shadow_RenderLighting_Light_Vertex(int firstvertex, int numvertices, int numtriangles, const int *element3i, const vec3_t lightcolor, float ambientscale, float diffusescale) +static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t lightcolor, float ambientscale, float diffusescale) { // OpenGL 1.1 path (anything) float ambientcolorbase[3], diffusecolorbase[3]; @@ -2826,29 +2866,32 @@ static void R_Shadow_RenderLighting_Light_Vertex(int firstvertex, int numvertice diffusecolorpants[0] = diffusecolorbase[0] * surfacepants[0];diffusecolorpants[1] = diffusecolorbase[1] * surfacepants[1];diffusecolorpants[2] = diffusecolorbase[2] * surfacepants[2]; ambientcolorshirt[0] = ambientcolorbase[0] * surfaceshirt[0];ambientcolorshirt[1] = ambientcolorbase[1] * surfaceshirt[1];ambientcolorshirt[2] = ambientcolorbase[2] * surfaceshirt[2]; diffusecolorshirt[0] = diffusecolorbase[0] * surfaceshirt[0];diffusecolorshirt[1] = diffusecolorbase[1] * surfaceshirt[1];diffusecolorshirt[2] = diffusecolorbase[2] * surfaceshirt[2]; + RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | (diffusescale > 0 ? BATCHNEED_ARRAY_NORMAL : 0) | BATCHNEED_ARRAY_TEXCOORD, texturenumsurfaces, texturesurfacelist); + R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset); + R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0); + R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset); R_Mesh_TexBind(0, basetexture); R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix); R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1); - R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset); switch(r_shadow_rendermode) { case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN: R_Mesh_TexBind(1, r_shadow_attenuation3dtexture); R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz); R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1); - R_Mesh_TexCoordPointer(1, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset); + R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset); break; case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN: R_Mesh_TexBind(2, r_shadow_attenuation2dtexture); R_Mesh_TexMatrix(2, &rsurface.entitytoattenuationz); R_Mesh_TexCombine(2, GL_MODULATE, GL_MODULATE, 1, 1); - R_Mesh_TexCoordPointer(2, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset); + R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset); // fall through case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN: R_Mesh_TexBind(1, r_shadow_attenuation2dtexture); R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz); R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1); - R_Mesh_TexCoordPointer(1, 3, rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset); + R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset); break; case R_SHADOW_RENDERMODE_LIGHT_VERTEX: break; @@ -2856,21 +2899,21 @@ static void R_Shadow_RenderLighting_Light_Vertex(int firstvertex, int numvertice break; } //R_Mesh_TexBind(0, basetexture); - R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorbase, ambientcolorbase); + R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorbase, ambientcolorbase); if (dopants) { R_Mesh_TexBind(0, pantstexture); - R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorpants, ambientcolorpants); + R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorpants, ambientcolorpants); } if (doshirt) { R_Mesh_TexBind(0, shirttexture); - R_Shadow_RenderLighting_Light_Vertex_Pass(firstvertex, numvertices, numtriangles, element3i, diffusecolorshirt, ambientcolorshirt); + R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorshirt, ambientcolorshirt); } } extern cvar_t gl_lightmaps; -void R_Shadow_RenderLighting(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int element3i_bufferobject, int element3s_bufferobject) +void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist) { float ambientscale, diffusescale, specularscale; qboolean negated; @@ -2898,16 +2941,16 @@ void R_Shadow_RenderLighting(int firstvertex, int numvertices, int firsttriangle { case R_SHADOW_RENDERMODE_VISIBLELIGHTING: GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer); - R_Shadow_RenderLighting_VisibleLighting(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject); + R_Shadow_RenderLighting_VisibleLighting(texturenumsurfaces, texturesurfacelist); break; case R_SHADOW_RENDERMODE_LIGHT_GLSL: - R_Shadow_RenderLighting_Light_GLSL(firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, element3i_bufferobject, element3s_bufferobject, lightcolor, ambientscale, diffusescale, specularscale); + R_Shadow_RenderLighting_Light_GLSL(texturenumsurfaces, texturesurfacelist, lightcolor, ambientscale, diffusescale, specularscale); break; case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN: case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN: case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN: case R_SHADOW_RENDERMODE_LIGHT_VERTEX: - R_Shadow_RenderLighting_Light_Vertex(firstvertex, numvertices, numtriangles, element3i + firsttriangle * 3, lightcolor, ambientscale, diffusescale); + R_Shadow_RenderLighting_Light_Vertex(texturenumsurfaces, texturesurfacelist, lightcolor, ambientscale, diffusescale); break; default: Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode); @@ -3291,8 +3334,8 @@ void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const if (!mesh->sidetotals[r_shadow_shadowmapside]) continue; r_refdef.stats.lights_shadowtriangles += mesh->sidetotals[r_shadow_shadowmapside]; - R_Mesh_VertexPointer(mesh->vertex3f, mesh->vbo, mesh->vbooffset_vertex3f); - R_Mesh_Draw(0, mesh->numverts, mesh->sideoffsets[r_shadow_shadowmapside], mesh->sidetotals[r_shadow_shadowmapside], mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s); + R_Mesh_PrepareVertices_Position(mesh->numverts, mesh->vertexposition, mesh->vertexpositionbuffer); + R_Mesh_Draw(0, mesh->numverts, mesh->sideoffsets[r_shadow_shadowmapside], mesh->sidetotals[r_shadow_shadowmapside], mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset); } CHECKGLERROR } @@ -3324,13 +3367,13 @@ void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, co for (;mesh;mesh = mesh->next) { r_refdef.stats.lights_shadowtriangles += mesh->numtriangles; - R_Mesh_VertexPointer(mesh->vertex3f, mesh->vbo, mesh->vbooffset_vertex3f); + R_Mesh_PrepareVertices_Position(mesh->numverts, mesh->vertexposition, mesh->vertexpositionbuffer); if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL) { // increment stencil if frontface is infront of depthbuffer GL_CullFace(r_refdef.view.cullface_back); qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);CHECKGLERROR - R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s); + R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset); // decrement stencil if backface is infront of depthbuffer GL_CullFace(r_refdef.view.cullface_front); qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);CHECKGLERROR @@ -3340,12 +3383,12 @@ void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, co // decrement stencil if backface is behind depthbuffer GL_CullFace(r_refdef.view.cullface_front); qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR - R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s); + R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset); // increment stencil if frontface is behind depthbuffer GL_CullFace(r_refdef.view.cullface_back); qglStencilOp(GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR } - R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3s, mesh->ebo3i, mesh->ebo3s); + R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset); } CHECKGLERROR } @@ -3456,19 +3499,19 @@ void R_Shadow_PrepareLight(rtlight_t *rtlight) static entity_render_t *lightentities_noselfshadow[MAX_EDICTS]; static entity_render_t *shadowentities[MAX_EDICTS]; static entity_render_t *shadowentities_noselfshadow[MAX_EDICTS]; + qboolean nolight; rtlight->draw = false; // skip lights that don't light because of ambientscale+diffusescale+specularscale being 0 (corona only lights) // skip lights that are basically invisible (color 0 0 0) - if (VectorLength2(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale) < (1.0f / 1048576.0f)) - return; + nolight = VectorLength2(rtlight->color) * (rtlight->ambientscale + rtlight->diffusescale + rtlight->specularscale) < (1.0f / 1048576.0f); // loading is done before visibility checks because loading should happen // all at once at the start of a level, not when it stalls gameplay. // (especially important to benchmarks) // compile light - if (rtlight->isstatic && (!rtlight->compiled || (rtlight->shadow && rtlight->shadowmode != (int)r_shadow_shadowmode)) && r_shadow_realtime_world_compile.integer) + if (rtlight->isstatic && !nolight && (!rtlight->compiled || (rtlight->shadow && rtlight->shadowmode != (int)r_shadow_shadowmode)) && r_shadow_realtime_world_compile.integer) { if (rtlight->compiled) R_RTLight_Uncompile(rtlight); @@ -3493,6 +3536,10 @@ void R_Shadow_PrepareLight(rtlight_t *rtlight) if (VectorLength2(rtlight->currentcolor) < (1.0f / 1048576.0f)) return; + // skip processing on corona-only lights + if (nolight) + return; + // if the light box is offscreen, skip it if (R_CullBox(rtlight->cullmins, rtlight->cullmaxs)) return; @@ -3951,7 +3998,6 @@ void R_Shadow_DrawPrepass(void) entity_render_t *ent; GL_AlphaTest(false); - R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); GL_DepthMask(true); GL_ColorMask(1,1,1,1); @@ -4202,18 +4248,90 @@ extern cvar_t r_shadows_drawafterrtlighting; extern cvar_t r_shadows_castfrombmodels; extern cvar_t r_shadows_throwdistance; extern cvar_t r_shadows_throwdirection; +extern cvar_t r_shadows_focus; +extern cvar_t r_shadows_shadowmapscale; + +void R_Shadow_PrepareModelShadows(void) +{ + int i; + float scale, size, radius, dot1, dot2; + vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus, shadowmins, shadowmaxs; + entity_render_t *ent; + + if (!r_refdef.scene.numentities) + return; + + switch (r_shadow_shadowmode) + { + case R_SHADOW_SHADOWMODE_SHADOWMAP2D: + case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE: + if (r_shadows.integer >= 2) + break; + // fall through + case R_SHADOW_SHADOWMODE_STENCIL: + for (i = 0;i < r_refdef.scene.numentities;i++) + { + ent = r_refdef.scene.entities[i]; + if (!ent->animcache_vertex3f && ent->model && ent->model->DrawShadowVolume != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW)) + R_AnimCache_GetEntity(ent, false, false); + } + return; + default: + return; + } + + size = 2*r_shadow_shadowmapmaxsize; + scale = r_shadow_shadowmapping_precision.value * r_shadows_shadowmapscale.value; + radius = 0.5f * size / scale; + + 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); + CrossProduct(shadowdir, shadowforward, shadowright); + Math_atov(r_shadows_focus.string, shadowfocus); + VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin); + VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin); + VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin); + VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin); + if (shadowfocus[0] || shadowfocus[1] || shadowfocus[2]) + dot1 = 1; + VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin); + + shadowmins[0] = shadoworigin[0] - r_shadows_throwdistance.value * fabs(shadowdir[0]) - radius * (fabs(shadowforward[0]) + fabs(shadowright[0])); + shadowmins[1] = shadoworigin[1] - r_shadows_throwdistance.value * fabs(shadowdir[1]) - radius * (fabs(shadowforward[1]) + fabs(shadowright[1])); + shadowmins[2] = shadoworigin[2] - r_shadows_throwdistance.value * fabs(shadowdir[2]) - radius * (fabs(shadowforward[2]) + fabs(shadowright[2])); + shadowmaxs[0] = shadoworigin[0] + r_shadows_throwdistance.value * fabs(shadowdir[0]) + radius * (fabs(shadowforward[0]) + fabs(shadowright[0])); + shadowmaxs[1] = shadoworigin[1] + r_shadows_throwdistance.value * fabs(shadowdir[1]) + radius * (fabs(shadowforward[1]) + fabs(shadowright[1])); + shadowmaxs[2] = shadoworigin[2] + r_shadows_throwdistance.value * fabs(shadowdir[2]) + radius * (fabs(shadowforward[2]) + fabs(shadowright[2])); + + for (i = 0;i < r_refdef.scene.numentities;i++) + { + ent = r_refdef.scene.entities[i]; + if (!BoxesOverlap(ent->mins, ent->maxs, shadowmins, shadowmaxs)) + continue; + // cast shadows from anything of the map (submodels are optional) + if (!ent->animcache_vertex3f && ent->model && ent->model->DrawShadowMap != NULL && (!ent->model->brush.submodel || r_shadows_castfrombmodels.integer) && (ent->flags & RENDER_SHADOW)) + R_AnimCache_GetEntity(ent, false, false); + } +} void R_DrawModelShadowMaps(void) { int i; - float relativethrowdistance, scale, size, nearclip, farclip, dot1, dot2; + float relativethrowdistance, scale, size, radius, nearclip, farclip, bias, dot1, dot2; entity_render_t *ent; vec3_t relativelightorigin; - vec3_t relativelightdirection; + vec3_t relativelightdirection, relativeforward, relativeright; vec3_t relativeshadowmins, relativeshadowmaxs; - vec3_t shadowdir, shadowforward; + vec3_t shadowdir, shadowforward, shadowright, shadoworigin, shadowfocus; float m[12]; - matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix; + matrix4x4_t shadowmatrix, cameramatrix, mvpmatrix, invmvpmatrix, scalematrix, texmatrix; r_viewport_t viewport; GLuint fbo = 0; @@ -4257,17 +4375,24 @@ void R_DrawModelShadowMaps(void) } 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; + scale = (r_shadow_shadowmapping_precision.value * r_shadows_shadowmapscale.value) / size; + radius = 0.5f / scale; nearclip = -r_shadows_throwdistance.value; farclip = r_shadows_throwdistance.value; + bias = r_shadow_shadowmapping_bias.value * r_shadow_shadowmapping_nearclip.value / (2 * r_shadows_throwdistance.value) * (1024.0f / size); + + r_shadow_shadowmap_parameters[0] = size; + r_shadow_shadowmap_parameters[1] = size; + r_shadow_shadowmap_parameters[2] = 1.0; + r_shadow_shadowmap_parameters[3] = bound(0.0f, 1.0f - r_shadows_darken.value, 1.0f); + Math_atov(r_shadows_throwdirection.string, shadowdir); VectorNormalize(shadowdir); + Math_atov(r_shadows_focus.string, shadowfocus); + VectorM(shadowfocus[0], r_refdef.view.right, shadoworigin); + VectorMA(shadoworigin, shadowfocus[1], r_refdef.view.up, shadoworigin); + VectorMA(shadoworigin, -shadowfocus[2], r_refdef.view.forward, shadoworigin); + VectorAdd(shadoworigin, r_refdef.view.origin, shadoworigin); dot1 = DotProduct(r_refdef.view.forward, shadowdir); dot2 = DotProduct(r_refdef.view.up, shadowdir); if (fabs(dot1) <= fabs(dot2)) @@ -4276,16 +4401,20 @@ void R_DrawModelShadowMaps(void) 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]); + if (shadowfocus[0] || shadowfocus[1] || shadowfocus[2]) + dot1 = 1; + m[3] = fabs(dot1) * 0.5f - DotProduct(shadoworigin, &m[0]); + CrossProduct(shadowdir, shadowforward, shadowright); + VectorM(scale, shadowright, &m[4]); + m[7] = 0.5f - DotProduct(shadoworigin, &m[4]); VectorM(1.0f / (farclip - nearclip), shadowdir, &m[8]); - m[11] = 0.5f - DotProduct(r_refdef.view.origin, &m[8]); + m[11] = 0.5f - DotProduct(shadoworigin, &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); + R_Viewport_InitOrtho(&viewport, &cameramatrix, 0, 0, size, size, 0, 0, 1, 1, 0, -1, NULL); + VectorMA(shadoworigin, (1.0f - fabs(dot1)) * radius, shadowforward, shadoworigin); + #if 0 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);CHECKGLERROR R_SetupShader_ShowDepth(); @@ -4317,10 +4446,16 @@ void R_DrawModelShadowMaps(void) 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_Transform(&ent->inversematrix, shadoworigin, relativelightorigin); Matrix4x4_Transform3x3(&ent->inversematrix, shadowdir, relativelightdirection); - VectorScale(relativelightdirection, -relativethrowdistance, relativelightorigin); + Matrix4x4_Transform3x3(&ent->inversematrix, shadowforward, relativeforward); + Matrix4x4_Transform3x3(&ent->inversematrix, shadowright, relativeright); + relativeshadowmins[0] = relativelightorigin[0] - r_shadows_throwdistance.value * fabs(relativelightdirection[0]) - radius * (fabs(relativeforward[0]) + fabs(relativeright[0])); + relativeshadowmins[1] = relativelightorigin[1] - r_shadows_throwdistance.value * fabs(relativelightdirection[1]) - radius * (fabs(relativeforward[1]) + fabs(relativeright[1])); + relativeshadowmins[2] = relativelightorigin[2] - r_shadows_throwdistance.value * fabs(relativelightdirection[2]) - radius * (fabs(relativeforward[2]) + fabs(relativeright[2])); + relativeshadowmaxs[0] = relativelightorigin[0] + r_shadows_throwdistance.value * fabs(relativelightdirection[0]) + radius * (fabs(relativeforward[0]) + fabs(relativeright[0])); + relativeshadowmaxs[1] = relativelightorigin[1] + r_shadows_throwdistance.value * fabs(relativelightdirection[1]) + radius * (fabs(relativeforward[1]) + fabs(relativeright[1])); + relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2])); 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 @@ -4331,7 +4466,10 @@ void R_DrawModelShadowMaps(void) 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); + Matrix4x4_CreateScale3(&scalematrix, size, -size, 1); + Matrix4x4_AdjustOrigin(&scalematrix, 0, size, -0.5f * bias); + Matrix4x4_Concat(&texmatrix, &scalematrix, &shadowmatrix); + Matrix4x4_Concat(&r_shadow_shadowmapmatrix, &texmatrix, &invmvpmatrix); r_shadow_usingshadowmaportho = true; switch (r_shadow_shadowmode) @@ -4357,7 +4495,7 @@ void R_DrawModelShadows(void) vec3_t relativeshadowmins, relativeshadowmaxs; vec3_t tmp, shadowdir; - if (!r_refdef.scene.numentities || !vid.stencil || r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL) + if (!r_refdef.scene.numentities || !vid.stencil || (r_shadow_shadowmode != R_SHADOW_SHADOWMODE_STENCIL && r_shadows.integer != 1)) return; CHECKGLERROR @@ -4397,26 +4535,34 @@ void R_DrawModelShadows(void) { if(ent->entitynumber != 0) { - // networked entity - might be attached in some way (then we should use the parent's light direction, to not tear apart attached entities) - int entnum, entnum2, recursion; - entnum = entnum2 = ent->entitynumber; - for(recursion = 32; recursion > 0; --recursion) + if(ent->entitynumber >= MAX_EDICTS) // csqc entity { - entnum2 = cl.entities[entnum].state_current.tagentity; - if(entnum2 >= 1 && entnum2 < cl.num_entities && cl.entities_active[entnum2]) - entnum = entnum2; - else - break; + // FIXME handle this + VectorNegate(ent->modellight_lightdir, relativelightdirection); } - if(recursion && recursion != 32) // if we followed a valid non-empty attachment chain + else { - VectorNegate(cl.entities[entnum].render.modellight_lightdir, relativelightdirection); - // transform into modelspace of OUR entity - Matrix4x4_Transform3x3(&cl.entities[entnum].render.matrix, relativelightdirection, tmp); - Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection); + // networked entity - might be attached in some way (then we should use the parent's light direction, to not tear apart attached entities) + int entnum, entnum2, recursion; + entnum = entnum2 = ent->entitynumber; + for(recursion = 32; recursion > 0; --recursion) + { + entnum2 = cl.entities[entnum].state_current.tagentity; + if(entnum2 >= 1 && entnum2 < cl.num_entities && cl.entities_active[entnum2]) + entnum = entnum2; + else + break; + } + if(recursion && recursion != 32) // if we followed a valid non-empty attachment chain + { + VectorNegate(cl.entities[entnum].render.modellight_lightdir, relativelightdirection); + // transform into modelspace of OUR entity + Matrix4x4_Transform3x3(&cl.entities[entnum].render.matrix, relativelightdirection, tmp); + Matrix4x4_Transform3x3(&ent->inversematrix, tmp, relativelightdirection); + } + else + VectorNegate(ent->modellight_lightdir, relativelightdirection); } - else - VectorNegate(ent->modellight_lightdir, relativelightdirection); } else VectorNegate(ent->modellight_lightdir, relativelightdirection); @@ -4439,9 +4585,6 @@ void R_DrawModelShadows(void) //R_EntityMatrix(&identitymatrix); //R_Mesh_ResetTextureState(); R_ResetViewRendering2D(); - R_Mesh_VertexPointer(r_screenvertex3f, 0, 0); - R_Mesh_ColorPointer(NULL, 0, 0); - R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); // set up a darkening blend on shadowed areas GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -4458,7 +4601,9 @@ void R_DrawModelShadows(void) qglStencilFunc(GL_NOTEQUAL, 128, 255);CHECKGLERROR // apply the blend to the shadowed areas - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); + R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL); + R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); // restore the viewport R_SetViewport(&r_refdef.view.viewport); @@ -4490,14 +4635,14 @@ void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequery) qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels); qglDepthFunc(GL_ALWAYS); R_CalcSprite_Vertex3f(vertex3f, centerorigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale); - R_Mesh_VertexPointer(vertex3f, 0, 0); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); + R_Mesh_PrepareVertices_Position_Arrays(4, vertex3f); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); qglEndQueryARB(GL_SAMPLES_PASSED_ARB); qglDepthFunc(GL_LEQUAL); qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_visiblepixels); R_CalcSprite_Vertex3f(vertex3f, rtlight->shadoworigin, r_refdef.view.right, r_refdef.view.up, scale, -scale, -scale, scale); - R_Mesh_VertexPointer(vertex3f, 0, 0); - R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0); + R_Mesh_PrepareVertices_Position_Arrays(4, vertex3f); + R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0); qglEndQueryARB(GL_SAMPLES_PASSED_ARB); CHECKGLERROR } @@ -4589,7 +4734,6 @@ void R_Shadow_DrawCoronas(void) GL_DepthRange(0, 1); GL_PolygonOffset(0, 0); GL_DepthTest(true); - R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1); } @@ -4791,7 +4935,8 @@ void R_Shadow_DrawLightSprites(void) if (light) R_MeshQueue_AddTransparent(light->origin, R_Shadow_DrawLightSprite_TransparentCallback, (entity_render_t *)light, 5, &light->rtlight); } - R_MeshQueue_AddTransparent(r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL); + if (!r_editlights_lockcursor) + R_MeshQueue_AddTransparent(r_editlights_cursorlocation, R_Shadow_DrawCursor_TransparentCallback, NULL, 0, NULL); } int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color) @@ -4823,6 +4968,9 @@ void R_Shadow_SelectLightInView(void) size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked best = NULL; bestrating = 0; + + if (r_editlights_lockcursor) + return; for (lightindex = 0;lightindex < range;lightindex++) { light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex); @@ -4853,8 +5001,7 @@ void R_Shadow_LoadWorldLights(void) Con_Print("No map loaded.\n"); return; } - FS_StripExtension (cl.worldmodel->name, name, sizeof (name)); - strlcat (name, ".rtlights", sizeof (name)); + dpsnprintf(name, sizeof(name), "%s.rtlights", cl.worldnamenoextension); lightsstring = (char *)FS_LoadFile(name, tempmempool, false, NULL); if (lightsstring) { @@ -4964,8 +5111,7 @@ void R_Shadow_SaveWorldLights(void) Con_Print("No map loaded.\n"); return; } - FS_StripExtension (cl.worldmodel->name, name, sizeof (name)); - strlcat (name, ".rtlights", sizeof (name)); + dpsnprintf(name, sizeof(name), "%s.rtlights", cl.worldnamenoextension); bufchars = bufmaxchars = 0; buf = NULL; for (lightindex = 0;lightindex < range;lightindex++) @@ -5013,8 +5159,7 @@ void R_Shadow_LoadLightsFile(void) Con_Print("No map loaded.\n"); return; } - FS_StripExtension (cl.worldmodel->name, name, sizeof (name)); - strlcat (name, ".lights", sizeof (name)); + dpsnprintf(name, sizeof(name), "%s.lights", cl.worldnamenoextension); lightsstring = (char *)FS_LoadFile(name, tempmempool, false, NULL); if (lightsstring) { @@ -5076,8 +5221,7 @@ void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void) return; } // try to load a .ent file first - FS_StripExtension (cl.worldmodel->name, key, sizeof (key)); - strlcat (key, ".ent", sizeof (key)); + dpsnprintf(key, sizeof(key), "%s.ent", cl.worldnamenoextension); data = entfiledata = (char *)FS_LoadFile(key, tempmempool, true, NULL); // and if that is not found, fall back to the bsp file entity string if (!data) @@ -5326,7 +5470,7 @@ void R_Shadow_EditLights_Reload_f(void) { if (!cl.worldmodel) return; - strlcpy(r_shadow_mapname, cl.worldmodel->name, sizeof(r_shadow_mapname)); + strlcpy(r_shadow_mapname, cl.worldname, sizeof(r_shadow_mapname)); R_Shadow_ClearWorldLights(); R_Shadow_LoadWorldLights(); if (!Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray)) @@ -5691,7 +5835,7 @@ void R_Shadow_EditLights_Edit_f(void) void R_Shadow_EditLights_EditAll_f(void) { size_t lightindex; - dlight_t *light; + dlight_t *light, *oldselected; size_t range; if (!r_editlights.integer) @@ -5700,6 +5844,7 @@ void R_Shadow_EditLights_EditAll_f(void) return; } + oldselected = r_shadow_selectedlight; // EditLights doesn't seem to have a "remove" command or something so: range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked for (lightindex = 0;lightindex < range;lightindex++) @@ -5710,6 +5855,8 @@ void R_Shadow_EditLights_EditAll_f(void) R_Shadow_SelectLight(light); R_Shadow_EditLights_Edit_f(); } + // return to old selected (to not mess editing once selection is locked) + R_Shadow_SelectLight(oldselected); } void R_Shadow_EditLights_DrawSelectedLightProperties(void) @@ -5819,6 +5966,7 @@ void R_Shadow_EditLights_Help_f(void) "r_editlights_help : this help\n" "r_editlights_clear : remove all lights\n" "r_editlights_reload : reload .rtlights, .lights file, or entities\n" +"r_editlights_lock : lock selection to current light, if already locked - unlock\n" "r_editlights_save : save to .rtlights file\n" "r_editlights_spawn : create a light with default settings\n" "r_editlights_edit command : edit selected light - more documentation below\n" @@ -5903,6 +6051,26 @@ void R_Shadow_EditLights_PasteInfo_f(void) R_Shadow_UpdateWorldLight(r_shadow_selectedlight, r_shadow_selectedlight->origin, r_shadow_bufferlight.angles, r_shadow_bufferlight.color, r_shadow_bufferlight.radius, r_shadow_bufferlight.corona, r_shadow_bufferlight.style, r_shadow_bufferlight.shadow, r_shadow_bufferlight.cubemapname, r_shadow_bufferlight.coronasizescale, r_shadow_bufferlight.ambientscale, r_shadow_bufferlight.diffusescale, r_shadow_bufferlight.specularscale, r_shadow_bufferlight.flags); } +void R_Shadow_EditLights_Lock_f(void) +{ + if (!r_editlights.integer) + { + Con_Print("Cannot lock on light when not in editing mode. Set r_editlights to 1.\n"); + return; + } + if (r_editlights_lockcursor) + { + r_editlights_lockcursor = false; + return; + } + if (!r_shadow_selectedlight) + { + Con_Print("No selected light to lock on.\n"); + return; + } + r_editlights_lockcursor = true; +} + void R_Shadow_EditLights_Init(void) { Cvar_RegisterVariable(&r_editlights); @@ -5925,6 +6093,7 @@ void R_Shadow_EditLights_Init(void) Cmd_AddCommand("r_editlights_importlightsfile", R_Shadow_EditLights_ImportLightsFile_f, "load lights from .lights file (ignoring .rtlights or .ent files and map entities)"); Cmd_AddCommand("r_editlights_copyinfo", R_Shadow_EditLights_CopyInfo_f, "store a copy of all properties (except origin) of the selected light"); Cmd_AddCommand("r_editlights_pasteinfo", R_Shadow_EditLights_PasteInfo_f, "apply the stored properties onto the selected light (making it exactly identical except for origin)"); + Cmd_AddCommand("r_editlights_lock", R_Shadow_EditLights_Lock_f, "lock selection to current light, if already locked - unlock"); }