X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=gl_rsurf.c;h=a5d1e3f3f71a4b2144948069aaa95712adfa1c42;hp=ff9f78b99fc3544187bb9d2fb82f50ac8e93b538;hb=5204bb8cced9548d5c44f6d6a5ab2e5e4a841030;hpb=ae4bf5903861f5790ab1fd23c568d99afcbf06bd diff --git a/gl_rsurf.c b/gl_rsurf.c index ff9f78b9..a5d1e3f3 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -61,7 +61,7 @@ void R_BuildLightMap (const entity_render_t *ent, msurface_t *surface) if (!model->brushq1.lightdata) { for (i = 0;i < size3;i++) - bl[i] = 255*256; + bl[i] = 128*256; } else { @@ -337,14 +337,15 @@ static void R_DrawPortal_Callback(const entity_render_t *ent, const rtlight_t *r CHECKGLERROR GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_DepthMask(false); + GL_DepthRange(0, 1); GL_DepthTest(true); GL_CullFace(GL_NONE); R_Mesh_Matrix(&identitymatrix); numpoints = min(portal->numpoints, POLYGONELEMENTS_MAXPOINTS); - R_Mesh_VertexPointer(vertex3f); - R_Mesh_ColorPointer(NULL); + R_Mesh_VertexPointer(vertex3f, 0, 0); + R_Mesh_ColorPointer(NULL, 0, 0); R_Mesh_ResetTextureState(); i = surfacelist[0]; @@ -354,7 +355,7 @@ static void R_DrawPortal_Callback(const entity_render_t *ent, const rtlight_t *r 0.125f); for (i = 0, v = vertex3f;i < numpoints;i++, v += 3) VectorCopy(portal->points[i].position, v); - R_Mesh_Draw(0, numpoints, numpoints - 2, polygonelements); + R_Mesh_Draw(0, numpoints, numpoints - 2, polygonelements, 0, 0); } // LordHavoc: this is just a nice debugging tool, very slow @@ -472,8 +473,10 @@ void R_View_WorldVisibility(void) leafstackpos = 1; while (leafstackpos) { - r_refdef.stats.world_leafs++; leaf = leafstack[--leafstackpos]; + if (r_viewcache.world_leafvisible[leaf - model->brush.data_leafs]) + continue; + r_refdef.stats.world_leafs++; r_viewcache.world_leafvisible[leaf - model->brush.data_leafs] = true; // mark any surfaces bounding this leaf if (leaf->numleafsurfaces) @@ -505,7 +508,10 @@ void R_Q1BSP_DrawSky(entity_render_t *ent) { if (ent->model == NULL) return; - R_DrawSurfaces(ent, true); + if (ent == r_refdef.worldentity) + R_DrawWorldSurfaces(true); + else + R_DrawModelSurfaces(ent, true); } void R_Q1BSP_Draw(entity_render_t *ent) @@ -513,7 +519,10 @@ void R_Q1BSP_Draw(entity_render_t *ent) model_t *model = ent->model; if (model == NULL) return; - R_DrawSurfaces(ent, false); + if (ent == r_refdef.worldentity) + R_DrawWorldSurfaces(false); + else + R_DrawModelSurfaces(ent, false); } typedef struct r_q1bsp_getlightinfo_s @@ -527,6 +536,8 @@ typedef struct r_q1bsp_getlightinfo_s int *outsurfacelist; unsigned char *outsurfacepvs; unsigned char *tempsurfacepvs; + unsigned char *outshadowtrispvs; + unsigned char *outlighttrispvs; int outnumsurfaces; vec3_t outmins; vec3_t outmaxs; @@ -549,14 +560,15 @@ void R_Q1BSP_RecursiveGetLightInfo(r_q1bsp_getlightinfo_t *info, mnode_t *node) // return; if (!plane) break; + //if (!r_shadow_compilingrtlight && R_CullBoxCustomPlanes(node->mins, node->maxs, r_shadow_rtlight_numfrustumplanes, r_shadow_rtlight_frustumplanes)) + // return; if (plane->type < 3) - sides = ((info->lightmaxs[plane->type] >= plane->dist) | ((info->lightmins[plane->type] < plane->dist) << 1)); - else - sides = BoxOnPlaneSide(info->lightmins, info->lightmaxs, plane); - if (sides == 3) { - // recurse front side first because the svbsp building prefers it - if (PlaneDist(info->relativelightorigin, plane) > 0) + if (info->lightmins[plane->type] > plane->dist) + node = node->children[0]; + else if (info->lightmaxs[plane->type] < plane->dist) + node = node->children[1]; + else if (info->relativelightorigin[plane->type] >= plane->dist) { R_Q1BSP_RecursiveGetLightInfo(info, node->children[0]); node = node->children[1]; @@ -567,11 +579,31 @@ void R_Q1BSP_RecursiveGetLightInfo(r_q1bsp_getlightinfo_t *info, mnode_t *node) node = node->children[0]; } } - else if (sides == 0) - return; // ERROR: NAN bounding box! else - node = node->children[sides - 1]; + { + sides = BoxOnPlaneSide(info->lightmins, info->lightmaxs, plane); + if (sides == 3) + { + // recurse front side first because the svbsp building prefers it + if (PlaneDist(info->relativelightorigin, plane) >= 0) + { + R_Q1BSP_RecursiveGetLightInfo(info, node->children[0]); + node = node->children[1]; + } + else + { + R_Q1BSP_RecursiveGetLightInfo(info, node->children[1]); + node = node->children[0]; + } + } + else if (sides == 0) + return; // ERROR: NAN bounding box! + else + node = node->children[sides - 1]; + } } + if (!r_shadow_compilingrtlight && R_CullBoxCustomPlanes(node->mins, node->maxs, r_shadow_rtlight_numfrustumplanes, r_shadow_rtlight_frustumplanes)) + return; leaf = (mleaf_t *)node; if (info->svbsp_active) { @@ -630,35 +662,76 @@ void R_Q1BSP_RecursiveGetLightInfo(r_q1bsp_getlightinfo_t *info, mnode_t *node) if (BoxesOverlap(info->lightmins, info->lightmaxs, surface->mins, surface->maxs) && (!info->svbsp_insertoccluder || !(surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOSHADOW))) { + qboolean addedtris = false; + qboolean insidebox = BoxInsideBox(surface->mins, surface->maxs, info->lightmins, info->lightmaxs); for (triangleindex = 0, t = surface->num_firstshadowmeshtriangle, e = info->model->brush.shadowmesh->element3i + t * 3;triangleindex < surface->num_triangles;triangleindex++, t++, e += 3) { 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 ((!r_shadow_frontsidecasting.integer || 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]))) + if (insidebox || TriangleOverlapsBox(v[0], v[1], v[2], info->lightmins, info->lightmaxs)) { - if (info->svbsp_active) + if (info->svbsp_insertoccluder) { + if (!(surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOCULLFACE) && r_shadow_frontsidecasting.integer != PointInfrontOfTriangle(info->relativelightorigin, v[0], v[1], v[2])) + continue; + if (surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOSHADOW) + continue; VectorCopy(v[0], v2[0]); VectorCopy(v[1], v2[1]); VectorCopy(v[2], v2[2]); - if (!(SVBSP_AddPolygon(&r_svbsp, 3, v2[0], info->svbsp_insertoccluder, NULL, NULL, 0) & 2)) + if (!(SVBSP_AddPolygon(&r_svbsp, 3, v2[0], true, NULL, NULL, 0) & 2)) continue; + addedtris = true; } - SETPVSBIT(info->outsurfacepvs, surfaceindex); - info->outsurfacelist[info->outnumsurfaces++] = surfaceindex; - if (info->svbsp_insertoccluder) - continue; else - break; + { + if (info->svbsp_active) + { + VectorCopy(v[0], v2[0]); + VectorCopy(v[1], v2[1]); + VectorCopy(v[2], v2[2]); + if (!(SVBSP_AddPolygon(&r_svbsp, 3, v2[0], false, NULL, NULL, 0) & 2)) + continue; + } + if (surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOCULLFACE) + { + // if the material is double sided we + // can't cull by direction + SETPVSBIT(info->outlighttrispvs, t); + addedtris = true; + if (!(surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOSHADOW)) + SETPVSBIT(info->outshadowtrispvs, t); + } + else if (r_shadow_frontsidecasting.integer) + { + // front side casting occludes backfaces, + // so they are completely useless as both + // casters and lit polygons + if (!PointInfrontOfTriangle(info->relativelightorigin, v[0], v[1], v[2])) + continue; + SETPVSBIT(info->outlighttrispvs, t); + addedtris = true; + if (!(surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOSHADOW)) + SETPVSBIT(info->outshadowtrispvs, t); + } + else + { + // back side casting does not occlude + // anything so we can't cull lit polygons + SETPVSBIT(info->outlighttrispvs, t); + addedtris = true; + if (!PointInfrontOfTriangle(info->relativelightorigin, v[0], v[1], v[2]) && !(surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOSHADOW)) + SETPVSBIT(info->outshadowtrispvs, t); + } + } } } + if (addedtris) + { + SETPVSBIT(info->outsurfacepvs, surfaceindex); + info->outsurfacelist[info->outnumsurfaces++] = surfaceindex; + } } } } @@ -738,7 +811,7 @@ void R_Q1BSP_CallRecursiveGetLightInfo(r_q1bsp_getlightinfo_t *info, qboolean us } } -void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer) +void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer, unsigned char *outshadowtrispvs, unsigned char *outlighttrispvs) { r_q1bsp_getlightinfo_t info; VectorCopy(relativelightorigin, info.relativelightorigin); @@ -763,11 +836,18 @@ void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, floa info.outnumleafs = 0; info.outsurfacelist = outsurfacelist; info.outsurfacepvs = outsurfacepvs; + info.outshadowtrispvs = outshadowtrispvs; + info.outlighttrispvs = outlighttrispvs; info.outnumsurfaces = 0; VectorCopy(info.relativelightorigin, info.outmins); VectorCopy(info.relativelightorigin, info.outmaxs); memset(outleafpvs, 0, (info.model->brush.num_leafs + 7) >> 3); memset(outsurfacepvs, 0, (info.model->nummodelsurfaces + 7) >> 3); + if (info.model->brush.shadowmesh) + memset(outshadowtrispvs, 0, (info.model->brush.shadowmesh->numtriangles + 7) >> 3); + else + memset(outshadowtrispvs, 0, (info.model->surfmesh.num_triangles + 7) >> 3); + memset(outlighttrispvs, 0, (info.model->surfmesh.num_triangles + 7) >> 3); if (info.model->brush.GetPVS && r_shadow_frontsidecasting.integer) info.pvs = info.model->brush.GetPVS(info.model, info.relativelightorigin); else @@ -777,12 +857,12 @@ void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, floa if (r_shadow_frontsidecasting.integer && r_shadow_compilingrtlight && r_shadow_realtime_world_compileportalculling.integer) { // 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); + 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, info.outshadowtrispvs, info.outlighttrispvs); } else if (r_shadow_frontsidecasting.integer && 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); + 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, info.outshadowtrispvs, info.outlighttrispvs); } else { @@ -821,7 +901,7 @@ void R_Q1BSP_CompileShadowVolume(entity_render_t *ent, vec3_t relativelightorigi R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, relativelightdirection, r_shadow_compilingrtlight->cullmins, r_shadow_compilingrtlight->cullmaxs, surface->mins, surface->maxs); } R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, relativelightdirection, projectdistance, numshadowmark, shadowmarklist); - r_shadow_compilingrtlight->static_meshchain_shadow = Mod_ShadowMesh_Finish(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow, false, false); + r_shadow_compilingrtlight->static_meshchain_shadow = Mod_ShadowMesh_Finish(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow, false, false, true); } void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativelightdirection, float lightradius, int modelnumsurfaces, const int *modelsurfacelist, const vec3_t lightmins, const vec3_t lightmaxs) @@ -849,7 +929,6 @@ void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, else { projectdistance = lightradius + model->radius*2; - RSurf_ActiveEntity(ent, false, false); R_Shadow_PrepareShadowMark(model->surfmesh.num_triangles); // identify lit faces within the bounding box for (modelsurfacelistindex = 0;modelsurfacelistindex < modelnumsurfaces;modelsurfacelistindex++) @@ -865,15 +944,14 @@ void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, } } -#define BATCHSIZE 256 +#define BATCHSIZE 1024 static void R_Q1BSP_DrawLight_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) { - int i, j, batchnumsurfaces, endsurface; + int i, j, endsurface; texture_t *t; msurface_t *surface; - msurface_t *batchsurfaces[BATCHSIZE]; - // note: in practice this never actually batches, oh well + // note: in practice this never actually receives batches), oh well R_Shadow_RenderMode_Begin(); R_Shadow_RenderMode_ActiveLight((rtlight_t *)rtlight); R_Shadow_RenderMode_Lighting(false, true); @@ -886,83 +964,140 @@ static void R_Q1BSP_DrawLight_TransparentCallback(const entity_render_t *ent, co R_UpdateTextureInfo(ent, t); rsurface_texture = t->currentframe; endsurface = min(j + BATCHSIZE, numsurfaces); - batchnumsurfaces = 0; - batchsurfaces[batchnumsurfaces++] = surface; - for (;j < endsurface;j++) + for (j = i;j < endsurface;j++) { surface = rsurface_model->data_surfaces + surfacelist[j]; if (t != surface->texture) - continue; - batchsurfaces[batchnumsurfaces++] = surface; + break; + RSurf_PrepareVerticesForBatch(true, true, 1, &surface); + R_Shadow_RenderLighting(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, ent->model->surfmesh.data_element3i + surface->num_firsttriangle * 3, ent->model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle)); } - R_Shadow_RenderSurfacesLighting(batchnumsurfaces, batchsurfaces); } R_Shadow_RenderMode_End(); } -static void R_Q1BSP_DrawLight_TransparentBatch(int batchnumsurfaces, msurface_t **batchsurfacelist) -{ - int batchsurfaceindex; - msurface_t *batchsurface; - vec3_t tempcenter, center; - for (batchsurfaceindex = 0;batchsurfaceindex < batchnumsurfaces;batchsurfaceindex++) - { - batchsurface = batchsurfacelist[batchsurfaceindex]; - tempcenter[0] = (batchsurface->mins[0] + batchsurface->maxs[0]) * 0.5f; - tempcenter[1] = (batchsurface->mins[1] + batchsurface->maxs[1]) * 0.5f; - tempcenter[2] = (batchsurface->mins[2] + batchsurface->maxs[2]) * 0.5f; - Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center); - R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_Q1BSP_DrawLight_TransparentCallback, rsurface_entity, batchsurface - rsurface_model->data_surfaces, r_shadow_rtlight); - } -} - #define RSURF_MAX_BATCHSURFACES 1024 -void R_Q1BSP_DrawLight(entity_render_t *ent, int numsurfaces, const int *surfacelist) +void R_Q1BSP_DrawLight(entity_render_t *ent, int numsurfaces, const int *surfacelist, const unsigned char *trispvs) { model_t *model = ent->model; msurface_t *surface; - int i, j, k, l, endsurface, batchnumsurfaces; + int i, k, l, m, mend, endsurface, batchnumsurfaces, batchnumtriangles, batchfirstvertex, batchlastvertex; + qboolean usebufferobject; + const int *element3i; msurface_t *batchsurfacelist[RSURF_MAX_BATCHSURFACES]; + int batchelements[BATCHSIZE*3]; texture_t *tex; CHECKGLERROR - RSurf_ActiveEntity(ent, true, true); + RSurf_ActiveModelEntity(ent, true, true); R_UpdateAllTextureInfo(ent); CHECKGLERROR + element3i = rsurface_model->surfmesh.data_element3i; // this is a double loop because non-visible surface skipping has to be // fast, and even if this is not the world model (and hence no visibility // checking) the input surface list and batch buffer are different formats // so some processing is necessary. (luckily models have few surfaces) - for (i = 0;i < numsurfaces;i = j) + for (i = 0;i < numsurfaces;) { batchnumsurfaces = 0; endsurface = min(i + RSURF_MAX_BATCHSURFACES, numsurfaces); if (ent == r_refdef.worldentity) { - for (j = i;j < endsurface;j++) - if (r_viewcache.world_surfacevisible[surfacelist[j]]) - batchsurfacelist[batchnumsurfaces++] = model->data_surfaces + surfacelist[j]; + for (;i < endsurface;i++) + if (r_viewcache.world_surfacevisible[surfacelist[i]]) + batchsurfacelist[batchnumsurfaces++] = model->data_surfaces + surfacelist[i]; } else { - for (j = i;j < endsurface;j++) - batchsurfacelist[batchnumsurfaces++] = model->data_surfaces + surfacelist[j]; + for (;i < endsurface;i++) + batchsurfacelist[batchnumsurfaces++] = model->data_surfaces + surfacelist[i]; } if (!batchnumsurfaces) continue; for (k = 0;k < batchnumsurfaces;k = l) { - l = k + 1; surface = batchsurfacelist[k]; tex = surface->texture; rsurface_texture = tex->currentframe; - for (;l < batchnumsurfaces && tex == batchsurfacelist[k]->texture;l++); if (rsurface_texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_WATER)) { - if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED) - R_Q1BSP_DrawLight_TransparentBatch(l - k, batchsurfacelist + k); + if (rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) + { + vec3_t tempcenter, center; + for (l = k;l < batchnumsurfaces && tex == batchsurfacelist[l]->texture;l++) + { + surface = batchsurfacelist[l]; + tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f; + tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f; + tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f; + Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center); + R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_Q1BSP_DrawLight_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight); + } + } else - R_Shadow_RenderSurfacesLighting(l - k, batchsurfacelist + k); + { + // use the bufferobject if all triangles are accepted + usebufferobject = true; + batchnumtriangles = 0; + // note: this only accepts consecutive surfaces because + // non-consecutive surfaces often have extreme vertex + // ranges (due to large numbers of surfaces omitted + // between them) + surface = batchsurfacelist[k]; + for (l = k;l < batchnumsurfaces && surface == batchsurfacelist[l] && tex == surface->texture;l++, surface++) + { + RSurf_PrepareVerticesForBatch(true, true, 1, &surface); + for (m = surface->num_firsttriangle, mend = m + surface->num_triangles;m < mend;m++) + { + if (r_shadow_culltriangles.integer) + { + if (trispvs) + { + if (!CHECKPVSBIT(trispvs, m)) + { + usebufferobject = false; + continue; + } + } + else + { + if (r_shadow_frontsidecasting.integer && !PointInfrontOfTriangle(r_shadow_entitylightorigin, rsurface_vertex3f + element3i[m*3+0]*3, rsurface_vertex3f + element3i[m*3+1]*3, rsurface_vertex3f + element3i[m*3+2]*3)) + { + usebufferobject = false; + continue; + } + } + } + batchelements[batchnumtriangles*3+0] = element3i[m*3+0]; + batchelements[batchnumtriangles*3+1] = element3i[m*3+1]; + batchelements[batchnumtriangles*3+2] = element3i[m*3+2]; + batchnumtriangles++; + r_refdef.stats.lights_lighttriangles++; + if (batchnumtriangles >= BATCHSIZE) + { + Mod_VertexRangeFromElements(batchnumtriangles*3, batchelements, &batchfirstvertex, &batchlastvertex); + R_Shadow_RenderLighting(batchfirstvertex, batchlastvertex + 1 - batchfirstvertex, batchnumtriangles, batchelements, 0, 0); + batchnumtriangles = 0; + usebufferobject = false; + } + } + r_refdef.stats.lights_lighttriangles += batchsurfacelist[l]->num_triangles; + } + if (batchnumtriangles > 0) + { + Mod_VertexRangeFromElements(batchnumtriangles*3, batchelements, &batchfirstvertex, &batchlastvertex); + if (usebufferobject) + R_Shadow_RenderLighting(batchfirstvertex, batchlastvertex + 1 - batchfirstvertex, batchnumtriangles, batchelements, ent->model->surfmesh.ebo, sizeof(int[3]) * batchsurfacelist[k]->num_firsttriangle); + else + R_Shadow_RenderLighting(batchfirstvertex, batchlastvertex + 1 - batchfirstvertex, batchnumtriangles, batchelements, 0, 0); + } + } + } + else + { + // skip ahead to the next texture + for (l = k;l < batchnumsurfaces && tex == batchsurfacelist[l]->texture;l++) + ; } } } @@ -1048,8 +1183,8 @@ void GL_Surf_Init(void) Cvar_RegisterVariable(&r_useportalculling); Cvar_RegisterVariable(&r_q3bsp_renderskydepth); - Cmd_AddCommand ("r_replacemaptexture", R_ReplaceWorldTexture, "override a map texture for testing purposes"); // By [515] - Cmd_AddCommand ("r_listmaptextures", R_ListWorldTextures, "list all textures used by the current map"); // By [515] + Cmd_AddCommand ("r_replacemaptexture", R_ReplaceWorldTexture, "override a map texture for testing purposes"); + Cmd_AddCommand ("r_listmaptextures", R_ListWorldTextures, "list all textures used by the current map"); //R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap); }