]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
now does batching of transparent surfaces, such as particles, this raised performance...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 26 Apr 2006 12:57:21 +0000 (12:57 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 26 Apr 2006 12:57:21 +0000 (12:57 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6332 d7cf8633-e32d-0410-b094-e92efae38249

cl_particles.c
gl_rmain.c
gl_rsurf.c
meshqueue.c
meshqueue.h
prvm_cmds.c
r_explosion.c
r_lightning.c
r_shadow.c
r_sprites.c

index a1842bd898e80c40c76d4cf3cf711a2b8bc5474f..d7ba1661261a21cf722e0c014a6ba8ee42586d7b 100644 (file)
@@ -1962,87 +1962,122 @@ static void r_part_newmap(void)
 {
 }
 
+#define BATCHSIZE 256
+int particle_element3i[BATCHSIZE*6];
+float particle_vertex3f[BATCHSIZE*12], particle_texcoord2f[BATCHSIZE*8], particle_color4f[BATCHSIZE*16];
+
 void R_Particles_Init (void)
 {
+       int i;
+       for (i = 0;i < BATCHSIZE;i++)
+       {
+               particle_element3i[i*6+0] = i*4+0;
+               particle_element3i[i*6+1] = i*4+1;
+               particle_element3i[i*6+2] = i*4+2;
+               particle_element3i[i*6+3] = i*4+0;
+               particle_element3i[i*6+4] = i*4+2;
+               particle_element3i[i*6+5] = i*4+3;
+       }
+
        Cvar_RegisterVariable(&r_drawparticles);
        R_RegisterModule("R_Particles", r_part_start, r_part_shutdown, r_part_newmap);
 }
 
-float particle_vertex3f[12], particle_texcoord2f[8];
-
-void R_DrawParticle_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
-       const particle_t *p = cl.particles + surfacenumber;
-       rmeshstate_t m;
+       int surfacelistindex;
+       int batchstart, batchcount;
+       const particle_t *p;
        pblend_t blendmode;
-       float org[3], up2[3], v[3], right[3], up[3], fog, ifog, cr, cg, cb, ca, size;
-       particletexture_t *tex;
-
-       VectorCopy(p->org, org);
-
-       blendmode = p->type->blendmode;
-       tex = &particletexture[p->texnum];
-       cr = p->color[0] * (1.0f / 255.0f);
-       cg = p->color[1] * (1.0f / 255.0f);
-       cb = p->color[2] * (1.0f / 255.0f);
-       ca = p->alpha * (1.0f / 255.0f);
-       if (blendmode == PBLEND_MOD)
-       {
-               cr *= ca;
-               cg *= ca;
-               cb *= ca;
-               cr = min(cr, 1);
-               cg = min(cg, 1);
-               cb = min(cb, 1);
-               ca = 1;
-       }
-       ca /= cl_particles_quality.value;
-       if (p->type->lighting)
-       {
-               float ambient[3], diffuse[3], diffusenormal[3];
-               R_CompleteLightPoint(ambient, diffuse, diffusenormal, org, true);
-               cr *= (ambient[0] + 0.5 * diffuse[0]);
-               cg *= (ambient[1] + 0.5 * diffuse[1]);
-               cb *= (ambient[2] + 0.5 * diffuse[2]);
-       }
-       if (fogenabled)
-       {
-               fog = VERTEXFOGTABLE(VectorDistance(org, r_vieworigin));
-               ifog = 1 - fog;
-               cr = cr * ifog;
-               cg = cg * ifog;
-               cb = cb * ifog;
-               if (blendmode == PBLEND_ALPHA)
-               {
-                       cr += fogcolor[0] * fog;
-                       cg += fogcolor[1] * fog;
-                       cb += fogcolor[2] * fog;
-               }
-       }
+       rtexture_t *texture;
+       float *v3f, *t2f, *c4f;
 
        R_Mesh_Matrix(&identitymatrix);
-
+       R_Mesh_ResetTextureState();
        R_Mesh_VertexPointer(particle_vertex3f);
-       R_Mesh_ColorPointer(NULL);
-       memset(&m, 0, sizeof(m));
-       m.tex[0] = R_GetTexture(tex->texture);
-       m.pointer_texcoord[0] = particle_texcoord2f;
-       R_Mesh_TextureState(&m);
-
-       GL_Color(cr, cg, cb, ca);
-
-       if (blendmode == PBLEND_ALPHA)
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       else if (blendmode == PBLEND_ADD)
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-       else //if (blendmode == PBLEND_MOD)
-               GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
+       R_Mesh_TexCoordPointer(0, 2, particle_texcoord2f);
+       R_Mesh_ColorPointer(particle_color4f);
        GL_DepthMask(false);
        GL_DepthTest(true);
-       size = p->size * cl_particles_size.value;
-       if (p->type->orientation == PARTICLE_BILLBOARD || p->type->orientation == PARTICLE_ORIENTED_DOUBLESIDED)
+
+       // first generate all the vertices at once
+       for (surfacelistindex = 0, v3f = particle_vertex3f, t2f = particle_texcoord2f, c4f = particle_color4f;surfacelistindex < numsurfaces;surfacelistindex++, v3f += 3*4, t2f += 2*4, c4f += 4*4)
        {
-               if (p->type->orientation == PARTICLE_ORIENTED_DOUBLESIDED)
+               particletexture_t *tex;
+               const float *org;
+               float up2[3], v[3], right[3], up[3], fog, ifog, cr, cg, cb, ca, size;
+
+               p = cl.particles + surfacelist[surfacelistindex];
+
+               blendmode = p->type->blendmode;
+
+               cr = p->color[0] * (1.0f / 255.0f);
+               cg = p->color[1] * (1.0f / 255.0f);
+               cb = p->color[2] * (1.0f / 255.0f);
+               ca = p->alpha * (1.0f / 255.0f);
+               if (blendmode == PBLEND_MOD)
+               {
+                       cr *= ca;
+                       cg *= ca;
+                       cb *= ca;
+                       cr = min(cr, 1);
+                       cg = min(cg, 1);
+                       cb = min(cb, 1);
+                       ca = 1;
+               }
+               ca /= cl_particles_quality.value;
+               if (p->type->lighting)
+               {
+                       float ambient[3], diffuse[3], diffusenormal[3];
+                       R_CompleteLightPoint(ambient, diffuse, diffusenormal, p->org, true);
+                       cr *= (ambient[0] + 0.5 * diffuse[0]);
+                       cg *= (ambient[1] + 0.5 * diffuse[1]);
+                       cb *= (ambient[2] + 0.5 * diffuse[2]);
+               }
+               if (fogenabled)
+               {
+                       fog = VERTEXFOGTABLE(VectorDistance(p->org, r_vieworigin));
+                       ifog = 1 - fog;
+                       cr = cr * ifog;
+                       cg = cg * ifog;
+                       cb = cb * ifog;
+                       if (blendmode == PBLEND_ALPHA)
+                       {
+                               cr += fogcolor[0] * fog;
+                               cg += fogcolor[1] * fog;
+                               cb += fogcolor[2] * fog;
+                       }
+               }
+               c4f[0] = c4f[4] = c4f[8] = c4f[12] = cr;
+               c4f[1] = c4f[5] = c4f[9] = c4f[13] = cg;
+               c4f[2] = c4f[6] = c4f[10] = c4f[14] = cb;
+               c4f[3] = c4f[7] = c4f[11] = c4f[15] = ca;
+
+               size = p->size * cl_particles_size.value;
+               org = p->org;
+               tex = &particletexture[p->texnum];
+               if (p->type->orientation == PARTICLE_BILLBOARD)
+               {
+                       VectorScale(r_viewleft, -size, right);
+                       VectorScale(r_viewup, size, up);
+                       v3f[ 0] = org[0] - right[0] - up[0];
+                       v3f[ 1] = org[1] - right[1] - up[1];
+                       v3f[ 2] = org[2] - right[2] - up[2];
+                       v3f[ 3] = org[0] - right[0] + up[0];
+                       v3f[ 4] = org[1] - right[1] + up[1];
+                       v3f[ 5] = org[2] - right[2] + up[2];
+                       v3f[ 6] = org[0] + right[0] + up[0];
+                       v3f[ 7] = org[1] + right[1] + up[1];
+                       v3f[ 8] = org[2] + right[2] + up[2];
+                       v3f[ 9] = org[0] + right[0] - up[0];
+                       v3f[10] = org[1] + right[1] - up[1];
+                       v3f[11] = org[2] + right[2] - up[2];
+                       t2f[0] = tex->s1;t2f[1] = tex->t2;
+                       t2f[2] = tex->s1;t2f[3] = tex->t1;
+                       t2f[4] = tex->s2;t2f[5] = tex->t1;
+                       t2f[6] = tex->s2;t2f[7] = tex->t2;
+               }
+               else if (p->type->orientation == PARTICLE_ORIENTED_DOUBLESIDED)
                {
                        // double-sided
                        if (DotProduct(p->vel, r_vieworigin) > DotProduct(p->vel, org))
@@ -2054,58 +2089,93 @@ void R_DrawParticle_TransparentCallback(const entity_render_t *ent, int surfacen
                                VectorVectors(p->vel, right, up);
                        VectorScale(right, size, right);
                        VectorScale(up, size, up);
+                       v3f[ 0] = org[0] - right[0] - up[0];
+                       v3f[ 1] = org[1] - right[1] - up[1];
+                       v3f[ 2] = org[2] - right[2] - up[2];
+                       v3f[ 3] = org[0] - right[0] + up[0];
+                       v3f[ 4] = org[1] - right[1] + up[1];
+                       v3f[ 5] = org[2] - right[2] + up[2];
+                       v3f[ 6] = org[0] + right[0] + up[0];
+                       v3f[ 7] = org[1] + right[1] + up[1];
+                       v3f[ 8] = org[2] + right[2] + up[2];
+                       v3f[ 9] = org[0] + right[0] - up[0];
+                       v3f[10] = org[1] + right[1] - up[1];
+                       v3f[11] = org[2] + right[2] - up[2];
+                       t2f[0] = tex->s1;t2f[1] = tex->t2;
+                       t2f[2] = tex->s1;t2f[3] = tex->t1;
+                       t2f[4] = tex->s2;t2f[5] = tex->t1;
+                       t2f[6] = tex->s2;t2f[7] = tex->t2;
+               }
+               else if (p->type->orientation == PARTICLE_SPARK)
+               {
+                       VectorMA(org, -0.02, p->vel, v);
+                       VectorMA(org, 0.02, p->vel, up2);
+                       R_CalcBeam_Vertex3f(v3f, v, up2, size);
+                       t2f[0] = tex->s1;t2f[1] = tex->t2;
+                       t2f[2] = tex->s1;t2f[3] = tex->t1;
+                       t2f[4] = tex->s2;t2f[5] = tex->t1;
+                       t2f[6] = tex->s2;t2f[7] = tex->t2;
+               }
+               else if (p->type->orientation == PARTICLE_BEAM)
+               {
+                       R_CalcBeam_Vertex3f(v3f, org, p->vel, size);
+                       VectorSubtract(p->vel, org, up);
+                       VectorNormalize(up);
+                       v[0] = DotProduct(org, up) * (1.0f / 64.0f);
+                       v[1] = DotProduct(p->vel, up) * (1.0f / 64.0f);
+                       t2f[0] = 1;t2f[1] = v[0];
+                       t2f[2] = 0;t2f[3] = v[0];
+                       t2f[4] = 0;t2f[5] = v[1];
+                       t2f[6] = 1;t2f[7] = v[1];
                }
                else
                {
-                       VectorScale(r_viewleft, -size, right);
-                       VectorScale(r_viewup, size, up);
+                       Con_Printf("R_DrawParticles: unknown particle orientation %i\n", p->type->orientation);
+                       return;
                }
-               particle_vertex3f[ 0] = org[0] - right[0] - up[0];
-               particle_vertex3f[ 1] = org[1] - right[1] - up[1];
-               particle_vertex3f[ 2] = org[2] - right[2] - up[2];
-               particle_vertex3f[ 3] = org[0] - right[0] + up[0];
-               particle_vertex3f[ 4] = org[1] - right[1] + up[1];
-               particle_vertex3f[ 5] = org[2] - right[2] + up[2];
-               particle_vertex3f[ 6] = org[0] + right[0] + up[0];
-               particle_vertex3f[ 7] = org[1] + right[1] + up[1];
-               particle_vertex3f[ 8] = org[2] + right[2] + up[2];
-               particle_vertex3f[ 9] = org[0] + right[0] - up[0];
-               particle_vertex3f[10] = org[1] + right[1] - up[1];
-               particle_vertex3f[11] = org[2] + right[2] - up[2];
-               particle_texcoord2f[0] = tex->s1;particle_texcoord2f[1] = tex->t2;
-               particle_texcoord2f[2] = tex->s1;particle_texcoord2f[3] = tex->t1;
-               particle_texcoord2f[4] = tex->s2;particle_texcoord2f[5] = tex->t1;
-               particle_texcoord2f[6] = tex->s2;particle_texcoord2f[7] = tex->t2;
-       }
-       else if (p->type->orientation == PARTICLE_SPARK)
-       {
-               VectorMA(p->org, -0.02, p->vel, v);
-               VectorMA(p->org, 0.02, p->vel, up2);
-               R_CalcBeam_Vertex3f(particle_vertex3f, v, up2, size);
-               particle_texcoord2f[0] = tex->s1;particle_texcoord2f[1] = tex->t2;
-               particle_texcoord2f[2] = tex->s1;particle_texcoord2f[3] = tex->t1;
-               particle_texcoord2f[4] = tex->s2;particle_texcoord2f[5] = tex->t1;
-               particle_texcoord2f[6] = tex->s2;particle_texcoord2f[7] = tex->t2;
-       }
-       else if (p->type->orientation == PARTICLE_BEAM)
-       {
-               R_CalcBeam_Vertex3f(particle_vertex3f, p->org, p->vel, size);
-               VectorSubtract(p->vel, p->org, up);
-               VectorNormalize(up);
-               v[0] = DotProduct(p->org, up) * (1.0f / 64.0f);
-               v[1] = DotProduct(p->vel, up) * (1.0f / 64.0f);
-               particle_texcoord2f[0] = 1;particle_texcoord2f[1] = v[0];
-               particle_texcoord2f[2] = 0;particle_texcoord2f[3] = v[0];
-               particle_texcoord2f[4] = 0;particle_texcoord2f[5] = v[1];
-               particle_texcoord2f[6] = 1;particle_texcoord2f[7] = v[1];
        }
-       else
+
+       // now render batches of particles based on blendmode and texture
+       blendmode = PBLEND_ADD;
+       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+       texture = particletexture[63].texture;
+       R_Mesh_TexBind(0, R_GetTexture(texture));
+       GL_LockArrays(0, numsurfaces*4);
+       batchstart = 0;
+       batchcount = 0;
+       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
        {
-               Con_Printf("R_DrawParticles: unknown particle orientation %i\n", p->type->orientation);
-               return;
-       }
+               p = cl.particles + surfacelist[surfacelistindex];
+
+               if (blendmode != p->type->blendmode)
+               {
+                       if (batchcount > 0)
+                               R_Mesh_Draw(batchstart * 4, batchcount * 4, batchcount * 2, particle_element3i + batchstart * 6);
+                       batchcount = 0;
+                       batchstart = surfacelistindex;
+                       blendmode = p->type->blendmode;
+                       if (blendmode == PBLEND_ALPHA)
+                               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                       else if (blendmode == PBLEND_ADD)
+                               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+                       else //if (blendmode == PBLEND_MOD)
+                               GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
+               }
+               if (texture != particletexture[p->texnum].texture)
+               {
+                       if (batchcount > 0)
+                               R_Mesh_Draw(batchstart * 4, batchcount * 4, batchcount * 2, particle_element3i + batchstart * 6);
+                       batchcount = 0;
+                       batchstart = surfacelistindex;
+                       texture = particletexture[p->texnum].texture;
+                       R_Mesh_TexBind(0, R_GetTexture(texture));
+               }
 
-       R_Mesh_Draw(0, 4, 2, polygonelements);
+               batchcount++;
+       }
+       if (batchcount > 0)
+               R_Mesh_Draw(batchstart * 4, batchcount * 4, batchcount * 2, particle_element3i + batchstart * 6);
+       GL_LockArrays(0, 0);
 }
 
 void R_DrawParticles (void)
@@ -2127,12 +2197,7 @@ void R_DrawParticles (void)
                {
                        renderstats.particles++;
                        if (DotProduct(p->org, r_viewforward) >= minparticledist || p->type->orientation == PARTICLE_BEAM)
-                       {
-                               if (p->type == particletype + pt_decal)
-                                       R_DrawParticle_TransparentCallback(0, i, 0);
-                               else
-                                       R_MeshQueue_AddTransparent(p->org, R_DrawParticle_TransparentCallback, NULL, i, NULL);
-                       }
+                               R_MeshQueue_AddTransparent(p->org, R_DrawParticle_TransparentCallback, NULL, i, NULL);
                }
        }
 }
index 96e1a8d370c6c0b24e20a0fb7662d74ce16104cf..608ef9d715a17843d195ba7c7c9e2218b92dfb64 100644 (file)
@@ -2039,11 +2039,13 @@ float nomodelcolor4f[6*4] =
        0.5f, 0.0f, 0.0f, 1.0f
 };
 
-void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
        int i;
        float f1, f2, *c;
        float color4f[6*4];
+       // this is only called once per entity so numsurfaces is always 1, and
+       // surfacelist is always {0}, so this code does not handle batches
        R_Mesh_Matrix(&ent->matrix);
 
        if (ent->flags & EF_ADDITIVE)
@@ -3150,17 +3152,37 @@ static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **textur
        }
 }
 
-static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+#define BATCHSIZE 256
+static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
-       msurface_t *surface = ent->model->data_surfaces + surfacenumber;
+       int surfacelistindex;
+       int batchcount;
+       texture_t *t;
+       msurface_t *texturesurfacelist[BATCHSIZE];
+       RSurf_ActiveEntity(ent);
+       batchcount = 0;
+       t = NULL;
+       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+       {
+               msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
 
-       if (surface->texture->basematerialflags & MATERIALFLAG_SKY)
-               return; // transparent sky is too difficult
+               if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
+               {
+                       if (batchcount > 0)
+                               R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
+                       batchcount = 0;
+                       t = surface->texture;
+                       rsurface_lightmaptexture = surface->lightmaptexture;
+                       R_UpdateTextureInfo(ent, t);
+                       rsurface_texture = t->currentframe;
+               }
+               if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
+                       continue; // transparent sky is too difficult
 
-       RSurf_ActiveEntity(ent);
-       R_UpdateTextureInfo(ent, surface->texture);
-       rsurface_texture = surface->texture->currentframe;
-       R_DrawTextureSurfaceList(1, &surface);
+               texturesurfacelist[batchcount++] = surface;
+       }
+       if (batchcount > 0)
+               R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
        RSurf_CleanUp();
 }
 
index 1ebbfecb893f4f657f9f7b57a916470f4931c2a0..6db1aa005203e1e6bb4299cb234952df9fef8479 100644 (file)
@@ -337,8 +337,11 @@ void R_Stain (const vec3_t origin, float radius, int cr1, int cg1, int cb1, int
 =============================================================
 */
 
-static void R_DrawPortal_Callback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+static void R_DrawPortal_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
+       // due to the hacky nature of this function's parameters, this is never
+       // called with a batch, so numsurfaces is always 1, and the surfacelist
+       // contains only a leaf number for coloring purposes
        const mportal_t *portal = (mportal_t *)ent;
        int i, numpoints;
        float *v;
@@ -356,7 +359,7 @@ static void R_DrawPortal_Callback(const entity_render_t *ent, int surfacenumber,
        R_Mesh_ColorPointer(NULL);
        R_Mesh_ResetTextureState();
 
-       i = surfacenumber;
+       i = surfacelist[0];
        GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f),
                         ((i & 0x0038) >> 3) * (1.0f / 7.0f),
                         ((i & 0x01C0) >> 6) * (1.0f / 7.0f),
@@ -776,16 +779,36 @@ void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin,
        }
 }
 
-static void R_Q1BSP_DrawLight_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+#define BATCHSIZE 256
+
+static void R_Q1BSP_DrawLight_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
-       msurface_t *surface = ent->model->data_surfaces + surfacenumber;
-       R_UpdateTextureInfo(ent, surface->texture);
+       int surfacelistindex, batchcount;
+       texture_t *t;
+       msurface_t *batchsurfaces[BATCHSIZE];
+       // note: in practice this never actualy batches, oh well
        R_Shadow_RenderMode_Begin();
        R_Shadow_RenderMode_ActiveLight((rtlight_t *)rtlight);
        R_Shadow_RenderMode_Lighting(false, true);
        R_Shadow_SetupEntityLight(ent);
-       rsurface_texture = surface->texture->currentframe;
-       R_Shadow_RenderSurfacesLighting(1, &surface);
+       t = NULL;
+       batchcount = 0;
+       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+       {
+               msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
+               if (t != surface->texture)
+               {
+                       if (batchcount > 0)
+                               R_Shadow_RenderSurfacesLighting(batchcount, batchsurfaces);
+                       batchcount = 0;
+                       t = surface->texture;
+                       R_UpdateTextureInfo(ent, t);
+                       rsurface_texture = t->currentframe;
+               }
+               batchsurfaces[batchcount++] = surface;
+       }
+       if (batchcount > 0)
+               R_Shadow_RenderSurfacesLighting(batchcount, batchsurfaces);
        R_Shadow_RenderMode_End();
 }
 
index b7087c01292d8e98025d59468858e7913b02a1c9..6b6ff0761ac8732685a6c965f156a515952749b4 100644 (file)
@@ -9,7 +9,7 @@ cvar_t r_meshqueue_sort = {0, "r_meshqueue_sort", "0", "whether to sort meshes i
 typedef struct meshqueue_s
 {
        struct meshqueue_s *next;
-       void (*callback)(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight);
+       void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfaceindices);
        const entity_render_t *ent;
        int surfacenumber;
        const rtlight_t *rtlight;
@@ -37,11 +37,12 @@ void R_MeshQueue_Init(void)
 
 void R_MeshQueue_Render(void)
 {
+       // this is only used by one piece of code in prvm_cmds, why is it used at all?
        meshqueue_t *mq;
        if (!mq_count)
                return;
        for (mq = mq_listhead;mq;mq = mq->next)
-               mq->callback(mq->ent, mq->surfacenumber, mq->rtlight);
+               mq->callback(mq->ent, mq->rtlight, 1, &mq->surfacenumber);
        mq_count = 0;
        mq_listhead = NULL;
 }
@@ -59,12 +60,13 @@ static void R_MeshQueue_EnlargeTransparentArray(int newtotal)
        mqt_total = newtotal;
 }
 
-void R_MeshQueue_Add(void (*callback)(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+void R_MeshQueue_Add(void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
 {
+       // this is only used by one piece of code in prvm_cmds, why is it used at all?
        meshqueue_t *mq, **mqnext;
        if (r_meshqueue_immediaterender.integer)
        {
-               callback(ent, surfacenumber, rtlight);
+               callback(ent, rtlight, 1, &surfacenumber);
                return;
        }
        if (mq_count >= mq_total)
@@ -108,7 +110,7 @@ void R_MeshQueue_Add(void (*callback)(const entity_render_t *ent, int surfacenum
        *mqnext = mq;
 }
 
-void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
 {
        meshqueue_t *mq;
        if (mqt_count >= mqt_total)
@@ -127,9 +129,14 @@ void R_MeshQueue_RenderTransparent(void)
 {
        int i;
        int hashdist;
+       int batchnumsurfaces;
        float distscale;
+       const entity_render_t *ent;
+       const rtlight_t *rtlight;
+       void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfaceindices);
        meshqueue_t *mqt;
        meshqueue_t *hash[4096], **hashpointer[4096];
+       int batchsurfaceindex[256];
        if (mq_count)
                R_MeshQueue_Render();
        if (!mqt_count)
@@ -148,10 +155,31 @@ void R_MeshQueue_RenderTransparent(void)
                *hashpointer[hashdist] = mqt;
                hashpointer[hashdist] = &mqt->next;
        }
+       callback = NULL;
+       ent = NULL;
+       rtlight = NULL;
+       batchnumsurfaces = 0;
        for (i = 4095;i >= 0;i--)
+       {
                if (hash[i])
+               {
                        for (mqt = hash[i];mqt;mqt = mqt->next)
-                               mqt->callback(mqt->ent, mqt->surfacenumber, mqt->rtlight);
+                       {
+                               if (ent != mqt->ent || rtlight != mqt->rtlight || callback != mqt->callback || batchnumsurfaces >= 256)
+                               {
+                                       if (batchnumsurfaces)
+                                               callback(ent, rtlight, batchnumsurfaces, batchsurfaceindex);
+                                       batchnumsurfaces = 0;
+                                       ent = mqt->ent;
+                                       rtlight = mqt->rtlight;
+                                       callback = mqt->callback;
+                               }
+                               batchsurfaceindex[batchnumsurfaces++] = mqt->surfacenumber;
+                       }
+               }
+       }
+       if (batchnumsurfaces)
+               callback(ent, rtlight, batchnumsurfaces, batchsurfaceindex);
        mqt_count = 0;
 }
 
index fd6cce45f9350b1064d54086053dc784a5f86b97..be2e3f084b1df875b617103751f585e0f84e2ac2 100644 (file)
@@ -3,8 +3,8 @@
 #define MESHQUEUE_H
 
 void R_MeshQueue_Init(void);
-void R_MeshQueue_Add(void (*callback)(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight);
-void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight);
+void R_MeshQueue_Add(void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight);
+void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight);
 void R_MeshQueue_BeginScene(void);
 void R_MeshQueue_Render(void);
 void R_MeshQueue_RenderTransparent(void);
index a3eacce9c66e3a22ec5973cd4fead3a3e0c4d884..0ea7436e2bac3f4be766c64592dc5bb7dbbf2357 100644 (file)
@@ -2855,75 +2855,80 @@ void VM_InitPolygons (void)
        vm_polygons_initialized = true;
 }
 
-void VM_DrawPolygonCallback (const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
-       const vm_polygon_t      *p = &vm_polygons[surfacenumber];
-       int                                     flags = p->flags & 0x0f;
+       int surfacelistindex;
+       // LordHavoc: FIXME: this is stupid code
+       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+       {
+               const vm_polygon_t      *p = &vm_polygons[surfacelist[surfacelistindex]];
+               int                                     flags = p->flags & 0x0f;
 
-       if(flags == DRAWFLAG_ADDITIVE)
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
-       else if(flags == DRAWFLAG_MODULATE)
-               GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
-       else if(flags == DRAWFLAG_2XMODULATE)
-               GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
-       else
-               GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               if(flags == DRAWFLAG_ADDITIVE)
+                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+               else if(flags == DRAWFLAG_MODULATE)
+                       GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
+               else if(flags == DRAWFLAG_2XMODULATE)
+                       GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
+               else
+                       GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
-       R_Mesh_TexBind(0, R_GetTexture(p->tex));
+               R_Mesh_TexBind(0, R_GetTexture(p->tex));
 
-       CHECKGLERROR
-       //[515]: is speed is max ?
-       if(p->flags & VM_POLYGON_FLLINES)       //[515]: lines
-       {
-               qglLineWidth(p->data[13]);CHECKGLERROR
-               qglBegin(GL_LINE_LOOP);
-                       qglTexCoord1f   (p->data[12]);
-                       qglColor4f              (p->data[20], p->data[21], p->data[22], p->data[23]);
-                       qglVertex3f             (p->data[0] , p->data[1],  p->data[2]);
+               CHECKGLERROR
+               //[515]: is speed is max ?
+               if(p->flags & VM_POLYGON_FLLINES)       //[515]: lines
+               {
+                       qglLineWidth(p->data[13]);CHECKGLERROR
+                       qglBegin(GL_LINE_LOOP);
+                               qglTexCoord1f   (p->data[12]);
+                               qglColor4f              (p->data[20], p->data[21], p->data[22], p->data[23]);
+                               qglVertex3f             (p->data[0] , p->data[1],  p->data[2]);
 
-                       qglTexCoord1f   (p->data[14]);
-                       qglColor4f              (p->data[24], p->data[25], p->data[26], p->data[27]);
-                       qglVertex3f             (p->data[3] , p->data[4],  p->data[5]);
+                               qglTexCoord1f   (p->data[14]);
+                               qglColor4f              (p->data[24], p->data[25], p->data[26], p->data[27]);
+                               qglVertex3f             (p->data[3] , p->data[4],  p->data[5]);
 
-                       if(p->flags & VM_POLYGON_FL3V)
-                       {
-                               qglTexCoord1f   (p->data[16]);
+                               if(p->flags & VM_POLYGON_FL3V)
+                               {
+                                       qglTexCoord1f   (p->data[16]);
+                                       qglColor4f              (p->data[28], p->data[29], p->data[30], p->data[31]);
+                                       qglVertex3f             (p->data[6] , p->data[7],  p->data[8]);
+
+                                       if(p->flags & VM_POLYGON_FL4V)
+                                       {
+                                               qglTexCoord1f   (p->data[18]);
+                                               qglColor4f              (p->data[32], p->data[33], p->data[34], p->data[35]);
+                                               qglVertex3f             (p->data[9] , p->data[10],  p->data[11]);
+                                       }
+                               }
+                       qglEnd();
+                       CHECKGLERROR
+               }
+               else
+               {
+                       qglBegin(GL_POLYGON);
+                               qglTexCoord2f   (p->data[12], p->data[13]);
+                               qglColor4f              (p->data[20], p->data[21], p->data[22], p->data[23]);
+                               qglVertex3f             (p->data[0] , p->data[1],  p->data[2]);
+
+                               qglTexCoord2f   (p->data[14], p->data[15]);
+                               qglColor4f              (p->data[24], p->data[25], p->data[26], p->data[27]);
+                               qglVertex3f             (p->data[3] , p->data[4],  p->data[5]);
+
+                               qglTexCoord2f   (p->data[16], p->data[17]);
                                qglColor4f              (p->data[28], p->data[29], p->data[30], p->data[31]);
                                qglVertex3f             (p->data[6] , p->data[7],  p->data[8]);
 
                                if(p->flags & VM_POLYGON_FL4V)
                                {
-                                       qglTexCoord1f   (p->data[18]);
+                                       qglTexCoord2f   (p->data[18], p->data[19]);
                                        qglColor4f              (p->data[32], p->data[33], p->data[34], p->data[35]);
                                        qglVertex3f             (p->data[9] , p->data[10],  p->data[11]);
                                }
-                       }
-               qglEnd();
-               CHECKGLERROR
-       }
-       else
-       {
-               qglBegin(GL_POLYGON);
-                       qglTexCoord2f   (p->data[12], p->data[13]);
-                       qglColor4f              (p->data[20], p->data[21], p->data[22], p->data[23]);
-                       qglVertex3f             (p->data[0] , p->data[1],  p->data[2]);
-
-                       qglTexCoord2f   (p->data[14], p->data[15]);
-                       qglColor4f              (p->data[24], p->data[25], p->data[26], p->data[27]);
-                       qglVertex3f             (p->data[3] , p->data[4],  p->data[5]);
-
-                       qglTexCoord2f   (p->data[16], p->data[17]);
-                       qglColor4f              (p->data[28], p->data[29], p->data[30], p->data[31]);
-                       qglVertex3f             (p->data[6] , p->data[7],  p->data[8]);
-
-                       if(p->flags & VM_POLYGON_FL4V)
-                       {
-                               qglTexCoord2f   (p->data[18], p->data[19]);
-                               qglColor4f              (p->data[32], p->data[33], p->data[34], p->data[35]);
-                               qglVertex3f             (p->data[9] , p->data[10],  p->data[11]);
-                       }
-               qglEnd();
-               CHECKGLERROR
+                       qglEnd();
+                       CHECKGLERROR
+               }
        }
 }
 
index 4dd9f853ed6832c4750842db2998364d80851fb5..a486f42de11d42bb419728ac619240b218850411 100644 (file)
@@ -180,34 +180,30 @@ void R_NewExplosion(const vec3_t org)
        }
 }
 
-static void R_DrawExplosion_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+static void R_DrawExplosion_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
-       const explosion_t *e = explosion + surfacenumber;
-       int numtriangles, numverts;
-       float alpha;
+       int surfacelistindex = 0;
+       const int numtriangles = EXPLOSIONTRIS, numverts = EXPLOSIONVERTS;
        rmeshstate_t m;
-
        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
        GL_DepthMask(false);
        GL_DepthTest(true);
        R_Mesh_Matrix(&identitymatrix);
 
-       numtriangles = EXPLOSIONTRIS;
-       numverts = EXPLOSIONVERTS;
-       alpha = e->alpha;
-
-       R_Mesh_VertexPointer(e->vert[0]);
        R_Mesh_ColorPointer(NULL);
        memset(&m, 0, sizeof(m));
        m.tex[0] = R_GetTexture(explosiontexture);
        m.pointer_texcoord[0] = explosiontexcoord2f[0];
        R_Mesh_TextureState(&m);
-
-       GL_Color(alpha, alpha, alpha, 1);
-
-       GL_LockArrays(0, numverts);
-       R_Mesh_Draw(0, numverts, numtriangles, explosiontris[0]);
-       GL_LockArrays(0, 0);
+       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+       {
+               const explosion_t *e = explosion + surfacelist[surfacelistindex];
+               R_Mesh_VertexPointer(e->vert[0]);
+               GL_Color(e->alpha, e->alpha, e->alpha, 1);
+               GL_LockArrays(0, numverts);
+               R_Mesh_Draw(0, numverts, numtriangles, explosiontris[0]);
+               GL_LockArrays(0, 0);
+       }
 }
 
 static void R_MoveExplosion(explosion_t *e)
index fb219273827d8786efefc5970426bfc1973693cd..8bc56007122e4435bd0920e6ee3cb116f32b7b7d 100644 (file)
@@ -229,57 +229,14 @@ void R_FogLightningBeam_Vertex3f_Color4f(const float *v, float *c, int numverts,
 
 float beamrepeatscale;
 
-void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
-       const beam_t *b = cl.beams + surfacenumber;
+       int surfacelistindex;
        rmeshstate_t m;
-       vec3_t beamdir, right, up, offset;
-       float length, t1, t2;
        float vertex3f[12*3];
        float texcoord2f[12*2];
        float color4f[12*4];
-
        R_Mesh_Matrix(&identitymatrix);
-
-       // calculate beam direction (beamdir) vector and beam length
-       // get difference vector
-       VectorSubtract(b->end, b->start, beamdir);
-       // find length of difference vector
-       length = sqrt(DotProduct(beamdir, beamdir));
-       // calculate scale to make beamdir a unit vector (normalized)
-       t1 = 1.0f / length;
-       // scale beamdir so it is now normalized
-       VectorScale(beamdir, t1, beamdir);
-
-       // calculate up vector such that it points toward viewer, and rotates around the beamdir
-       // get direction from start of beam to viewer
-       VectorSubtract(r_vieworigin, b->start, up);
-       // remove the portion of the vector that moves along the beam
-       // (this leaves only a vector pointing directly away from the beam)
-       t1 = -DotProduct(up, beamdir);
-       VectorMA(up, t1, beamdir, up);
-       // generate right vector from forward and up, the result is unnormalized
-       CrossProduct(beamdir, up, right);
-       // now normalize the right vector and up vector
-       VectorNormalize(right);
-       VectorNormalize(up);
-
-       // calculate T coordinate scrolling (start and end texcoord along the beam)
-       t1 = r_refdef.time * -r_lightningbeam_scroll.value;// + beamrepeatscale * DotProduct(b->start, beamdir);
-       t1 = t1 - (int) t1;
-       t2 = t1 + beamrepeatscale * length;
-
-       // the beam is 3 polygons in this configuration:
-       //  *   2
-       //   * *
-       // 1******
-       //   * *
-       //  *   3
-       // they are showing different portions of the beam texture, creating an
-       // illusion of a beam that appears to curl around in 3D space
-       // (and realize that the whole polygon assembly orients itself to face
-       //  the viewer)
-
        GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
        GL_DepthMask(false);
        GL_DepthTest(true);
@@ -288,21 +245,6 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, int sur
        if (!r_lightningbeam_qmbtexture.integer && r_lightningbeamtexture == NULL)
                r_lightningbeams_setuptexture();
 
-       // polygon 1, verts 0-3
-       VectorScale(right, r_lightningbeam_thickness.value, offset);
-       R_CalcLightningBeamPolygonVertex3f(vertex3f + 0, b->start, b->end, offset);
-       // polygon 2, verts 4-7
-       VectorAdd(right, up, offset);
-       VectorScale(offset, r_lightningbeam_thickness.value * 0.70710681f, offset);
-       R_CalcLightningBeamPolygonVertex3f(vertex3f + 12, b->start, b->end, offset);
-       // polygon 3, verts 8-11
-       VectorSubtract(right, up, offset);
-       VectorScale(offset, r_lightningbeam_thickness.value * 0.70710681f, offset);
-       R_CalcLightningBeamPolygonVertex3f(vertex3f + 24, b->start, b->end, offset);
-       R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 0, t1, t2);
-       R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 8, t1 + 0.33, t2 + 0.33);
-       R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 16, t1 + 0.66, t2 + 0.66);
-
        R_Mesh_VertexPointer(vertex3f);
        if (fogenabled)
        {
@@ -324,10 +266,76 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, int sur
        m.pointer_texcoord[0] = texcoord2f;
        R_Mesh_TextureState(&m);
 
-       // draw the 3 polygons as one batch of 6 triangles using the 12 vertices
-       GL_LockArrays(0, 12);
-       R_Mesh_Draw(0, 12, 6, r_lightningbeamelements);
-       GL_LockArrays(0, 0);
+       for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+       {
+               const beam_t *b = cl.beams + surfacelist[surfacelistindex];
+               vec3_t beamdir, right, up, offset;
+               float length, t1, t2;
+
+               // calculate beam direction (beamdir) vector and beam length
+               // get difference vector
+               VectorSubtract(b->end, b->start, beamdir);
+               // find length of difference vector
+               length = sqrt(DotProduct(beamdir, beamdir));
+               // calculate scale to make beamdir a unit vector (normalized)
+               t1 = 1.0f / length;
+               // scale beamdir so it is now normalized
+               VectorScale(beamdir, t1, beamdir);
+
+               // calculate up vector such that it points toward viewer, and rotates around the beamdir
+               // get direction from start of beam to viewer
+               VectorSubtract(r_vieworigin, b->start, up);
+               // remove the portion of the vector that moves along the beam
+               // (this leaves only a vector pointing directly away from the beam)
+               t1 = -DotProduct(up, beamdir);
+               VectorMA(up, t1, beamdir, up);
+               // generate right vector from forward and up, the result is unnormalized
+               CrossProduct(beamdir, up, right);
+               // now normalize the right vector and up vector
+               VectorNormalize(right);
+               VectorNormalize(up);
+
+               // calculate T coordinate scrolling (start and end texcoord along the beam)
+               t1 = r_refdef.time * -r_lightningbeam_scroll.value;// + beamrepeatscale * DotProduct(b->start, beamdir);
+               t1 = t1 - (int) t1;
+               t2 = t1 + beamrepeatscale * length;
+
+               // the beam is 3 polygons in this configuration:
+               //  *   2
+               //   * *
+               // 1******
+               //   * *
+               //  *   3
+               // they are showing different portions of the beam texture, creating an
+               // illusion of a beam that appears to curl around in 3D space
+               // (and realize that the whole polygon assembly orients itself to face
+               //  the viewer)
+
+               // polygon 1, verts 0-3
+               VectorScale(right, r_lightningbeam_thickness.value, offset);
+               R_CalcLightningBeamPolygonVertex3f(vertex3f + 0, b->start, b->end, offset);
+               // polygon 2, verts 4-7
+               VectorAdd(right, up, offset);
+               VectorScale(offset, r_lightningbeam_thickness.value * 0.70710681f, offset);
+               R_CalcLightningBeamPolygonVertex3f(vertex3f + 12, b->start, b->end, offset);
+               // polygon 3, verts 8-11
+               VectorSubtract(right, up, offset);
+               VectorScale(offset, r_lightningbeam_thickness.value * 0.70710681f, offset);
+               R_CalcLightningBeamPolygonVertex3f(vertex3f + 24, b->start, b->end, offset);
+               R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 0, t1, t2);
+               R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 8, t1 + 0.33, t2 + 0.33);
+               R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 16, t1 + 0.66, t2 + 0.66);
+               if (fogenabled)
+               {
+                       // per vertex colors if fog is used
+                       R_FogLightningBeam_Vertex3f_Color4f(vertex3f, color4f, 12, r_lightningbeam_color_red.value, r_lightningbeam_color_green.value, r_lightningbeam_color_blue.value, 1);
+               }
+
+               // draw the 3 polygons as one batch of 6 triangles using the 12 vertices
+               GL_LockArrays(0, 12);
+               R_Mesh_Draw(0, 12, 6, r_lightningbeamelements);
+               GL_LockArrays(0, 0);
+       }
 }
 
 void R_DrawLightningBeams(void)
index d845cb3b83d96ad9208f722df7251da7aa74c86a..c54e8b750b87d14559aff936ddfcd03683d15fa9 100644 (file)
@@ -2649,14 +2649,17 @@ void R_Shadow_SelectLight(dlight_t *light)
                r_shadow_selectedlight->selected = true;
 }
 
-void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+void R_Shadow_DrawCursor_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
+       // this is never batched (there can be only one)
        float scale = r_editlights_cursorgrid.value * 0.5f;
        R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_crosshairs[1]->tex, NULL, false, r_editlights_cursorlocation, r_viewright, r_viewup, scale, -scale, -scale, scale, 1, 1, 1, 0.5f);
 }
 
-void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
+       // this is never batched (due to the ent parameter changing every time)
+       // so numsurfaces == 1 and surfacelist[0] == lightnumber
        float intensity;
        const dlight_t *light = (dlight_t *)ent;
        intensity = 0.5;
@@ -2664,7 +2667,7 @@ void R_Shadow_DrawLightSprite_TransparentCallback(const entity_render_t *ent, in
                intensity = 0.75 + 0.25 * sin(realtime * M_PI * 4.0);
        if (!light->shadow)
                intensity *= 0.5f;
-       R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_crosshairs[surfacenumber]->tex, NULL, false, light->origin, r_viewright, r_viewup, 8, -8, -8, 8, intensity, intensity, intensity, 0.5);
+       R_DrawSprite(GL_SRC_ALPHA, GL_ONE, r_crosshairs[surfacelist[0]]->tex, NULL, false, light->origin, r_viewright, r_viewup, 8, -8, -8, 8, intensity, intensity, intensity, 0.5);
 }
 
 void R_Shadow_DrawLightSprites(void)
index 0c1b922f910e0eeea7d9ebc634be64c3d24a7518..02f7f2e16eba390f420078b89029e31bc0570e86 100644 (file)
@@ -2,7 +2,7 @@
 #include "quakedef.h"
 #include "r_shadow.h"
 
-void R_Model_Sprite_Draw_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+void R_Model_Sprite_Draw_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
 {
        int i;
        model_t *model = ent->model;