-static void R_DrawDecal_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
-{
- int surfacelistindex;
- const decal_t *d;
- float *v3f, *t2f, *c4f;
- particletexture_t *tex;
- float right[3], up[3], size, ca;
- float alphascale = (1.0f / 65536.0f) * cl_particles_alpha.value;
-
- RSurf_ActiveWorldEntity();
-
- r_refdef.stats.drawndecals += numsurfaces;
-// R_Mesh_ResetTextureState();
- GL_DepthMask(false);
- GL_DepthRange(0, 1);
- GL_PolygonOffset(0, 0);
- GL_DepthTest(true);
- GL_CullFace(GL_NONE);
-
- // generate all the vertices at once
- for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
- {
- d = cl.decals + surfacelist[surfacelistindex];
-
- // calculate color
- c4f = particle_color4f + 16*surfacelistindex;
- ca = d->alpha * alphascale;
- // ensure alpha multiplier saturates properly
- if (ca > 1.0f / 256.0f)
- ca = 1.0f / 256.0f;
- if (r_refdef.fogenabled)
- ca *= RSurf_FogVertex(d->org);
- Vector4Set(c4f, d->color[0] * ca, d->color[1] * ca, d->color[2] * ca, 1);
- Vector4Copy(c4f, c4f + 4);
- Vector4Copy(c4f, c4f + 8);
- Vector4Copy(c4f, c4f + 12);
-
- // calculate vertex positions
- size = d->size * cl_particles_size.value;
- VectorVectors(d->normal, right, up);
- VectorScale(right, size, right);
- VectorScale(up, size, up);
- v3f = particle_vertex3f + 12*surfacelistindex;
- v3f[ 0] = d->org[0] - right[0] - up[0];
- v3f[ 1] = d->org[1] - right[1] - up[1];
- v3f[ 2] = d->org[2] - right[2] - up[2];
- v3f[ 3] = d->org[0] - right[0] + up[0];
- v3f[ 4] = d->org[1] - right[1] + up[1];
- v3f[ 5] = d->org[2] - right[2] + up[2];
- v3f[ 6] = d->org[0] + right[0] + up[0];
- v3f[ 7] = d->org[1] + right[1] + up[1];
- v3f[ 8] = d->org[2] + right[2] + up[2];
- v3f[ 9] = d->org[0] + right[0] - up[0];
- v3f[10] = d->org[1] + right[1] - up[1];
- v3f[11] = d->org[2] + right[2] - up[2];
-
- // calculate texcoords
- tex = &particletexture[d->texnum];
- t2f = particle_texcoord2f + 8*surfacelistindex;
- 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;
- }
-
- // now render the decals all at once
- // (this assumes they all use one particle font texture!)
- GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
- R_SetupShader_Generic(particletexture[63].texture, NULL, GL_MODULATE, 1, false, false, true);
- R_Mesh_PrepareVertices_Generic_Arrays(numsurfaces * 4, particle_vertex3f, particle_color4f, particle_texcoord2f);
- R_Mesh_Draw(0, numsurfaces * 4, 0, numsurfaces * 2, NULL, NULL, 0, particle_elements, NULL, 0);
-}
-
-void R_DrawDecals (void)
-{
- int i;
- int drawdecals = r_drawdecals.integer;
- decal_t *decal;
- float frametime;
- float decalfade;
- float drawdist2;
- int killsequence = cl.decalsequence - max(0, cl_decals_max.integer);
-
- frametime = bound(0, cl.time - cl.decals_updatetime, 1);
- cl.decals_updatetime = bound(cl.time - 1, cl.decals_updatetime + frametime, cl.time + 1);
-
- // LordHavoc: early out conditions
- if (!cl.num_decals)
- return;
-
- decalfade = frametime * 256 / cl_decals_fadetime.value;
- drawdist2 = r_drawdecals_drawdistance.value * r_refdef.view.quality;
- drawdist2 = drawdist2*drawdist2;
-
- for (i = 0, decal = cl.decals;i < cl.num_decals;i++, decal++)
- {
- if (!decal->typeindex)
- continue;
-
- if (killsequence - decal->decalsequence > 0)
- goto killdecal;
-
- if (cl.time > decal->time2 + cl_decals_time.value)
- {
- decal->alpha -= decalfade;
- if (decal->alpha <= 0)
- goto killdecal;
- }
-
- if (decal->owner)
- {
- if (cl.entities[decal->owner].render.model == decal->ownermodel)
- {
- Matrix4x4_Transform(&cl.entities[decal->owner].render.matrix, decal->relativeorigin, decal->org);
- Matrix4x4_Transform3x3(&cl.entities[decal->owner].render.matrix, decal->relativenormal, decal->normal);
- }
- else
- goto killdecal;
- }
-
- if(cl_decals_visculling.integer && decal->clusterindex > -1000 && !CHECKPVSBIT(r_refdef.viewcache.world_pvsbits, decal->clusterindex))
- continue;
-
- if (!drawdecals)
- continue;
-
- if (DotProduct(r_refdef.view.origin, decal->normal) > DotProduct(decal->org, decal->normal) && VectorDistance2(decal->org, r_refdef.view.origin) < drawdist2 * (decal->size * decal->size))
- R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, decal->org, R_DrawDecal_TransparentCallback, NULL, i, NULL);
- continue;
-killdecal:
- decal->typeindex = 0;
- if (cl.free_decal > i)
- cl.free_decal = i;
- }
-
- // reduce cl.num_decals if possible
- while (cl.num_decals > 0 && cl.decals[cl.num_decals - 1].typeindex == 0)
- cl.num_decals--;
-
- if (cl.num_decals == cl.max_decals && cl.max_decals < MAX_DECALS)
- {
- decal_t *olddecals = cl.decals;
- cl.max_decals = min(cl.max_decals * 2, MAX_DECALS);
- cl.decals = (decal_t *) Mem_Alloc(cls.levelmempool, cl.max_decals * sizeof(decal_t));
- memcpy(cl.decals, olddecals, cl.num_decals * sizeof(decal_t));
- Mem_Free(olddecals);
- }
-
- r_refdef.stats.totaldecals = cl.num_decals;
-}
-