cleaned up a lot of particle rendering properties (mainly related to rain code),...
authorlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 18 Jan 2002 20:33:38 +0000 (20:33 +0000)
committerlordhavoc <lordhavoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 18 Jan 2002 20:33:38 +0000 (20:33 +0000)
added depthdisable to rmeshinfo_t
gl_backend now uses glDrawRangeElements on non-win32 (need to use dynamic GL binding to get it on win32), nice speedup
rearranged r_speeds2 time reporting code, now times more things (in gl_screen.c especially)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@1365 d7cf8633-e32d-0410-b094-e92efae38249

buildnumber.c
cl_particles.c
client.h
gl_backend.c
gl_backend.h
gl_rmain.c
gl_rsurf.c
gl_screen.c
r_particles.c
render.h

index 37ef334..d57640a 100644 (file)
@@ -1,4 +1,4 @@
 
-#define BUILDNUMBER 659
+#define BUILDNUMBER 710
 
 int buildnumber = BUILDNUMBER;
index 6bb31d8..1196b67 100644 (file)
@@ -32,11 +32,13 @@ ptype_t;
 typedef struct particle_s
 {
        ptype_t         type;
+       int                     orientation; // typically PARTICLE_BILLBOARD
        vec3_t          org;
        vec3_t          vel;
        int                     tex;
        float           die;
-       float           scale;
+       float           scalex;
+       float           scaley;
        float           alpha; // 0-255
        float           time2; // used for various things (snow fluttering, for example)
        float           bounce; // how much bounce-back from a surface the particle hits (0 = no physics, 1 = stop and slide, 2 = keep bouncing forever, 1.5 is typical)
@@ -160,7 +162,7 @@ void CL_Particles_Init (void)
        r_refdef.particles = cl_renderparticles = Mem_Alloc(cl_part_mempool, cl_maxparticles * sizeof(renderparticle_t));
 }
 
-#define particle(ptype, pcolor, ptex, plight, pscale, palpha, ptime, pbounce, px, py, pz, pvx, pvy, pvz, ptime2, pvx2, pvy2, pvz2, pfriction, ppressure)\
+#define particle(ptype, porientation, pcolor, ptex, plight, pscalex, pscaley, palpha, ptime, pbounce, px, py, pz, pvx, pvy, pvz, ptime2, pvx2, pvy2, pvz2, pfriction, ppressure)\
 {\
        particle_t      *part;\
        int tempcolor;\
@@ -174,8 +176,10 @@ void CL_Particles_Init (void)
        part->color[2] = (tempcolor) & 0xFF;\
        part->color[3] = 0xFF;\
        part->tex = (ptex);\
+       part->orientation = (porientation);\
        part->dynlight = (plight);\
-       part->scale = (pscale);\
+       part->scalex = (pscalex);\
+       part->scaley = (pscaley);\
        part->alpha = (palpha);\
        part->die = cl.time + (ptime);\
        part->bounce = (pbounce);\
@@ -229,7 +233,7 @@ void CL_EntityParticles (entity_t *ent)
                forward[1] = cp*sy;
                forward[2] = -sp;
 
-               particle(pt_oneframe, particlepalette[0x6f], tex_particle, false, 2, 255, 9999, 0, ent->render.origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->render.origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->render.origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+               particle(pt_oneframe, PARTICLE_BILLBOARD, particlepalette[0x6f], tex_particle, false, 2, 2, 255, 9999, 0, ent->render.origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->render.origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->render.origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0, 0, 0, 0, 0, 0, 0);
        }
 }
 
@@ -273,7 +277,7 @@ void CL_ReadPointFile_f (void)
                        Con_Printf ("Not enough free particles\n");
                        break;
                }
-               particle(pt_static, particlepalette[(-c)&15], tex_particle, false, 2, 255, 99999, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+               particle(pt_static, PARTICLE_BILLBOARD, particlepalette[(-c)&15], tex_particle, false, 2, 2, 255, 99999, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
        }
 
        Mem_Free(pointfile);
@@ -327,7 +331,7 @@ void CL_ParticleExplosion (vec3_t org, int smoke)
                if (i == CONTENTS_SLIME || i == CONTENTS_WATER)
                {
                        for (i = 0;i < 128;i++)
-                               particle(pt_bubble, 0xFFFFFF, tex_bubble, false, lhrandom(1, 2), 255, 9999, 1.5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-96, 96), lhrandom(-96, 96), lhrandom(-96, 96), 0, 0, 0, 0, 0, 0);
+                               particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, 2, 2, 255, 9999, 1.5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-96, 96), lhrandom(-96, 96), lhrandom(-96, 96), 0, 0, 0, 0, 0, 0);
 
                        ang[2] = lhrandom(0, 360);
                        fractalnoise(noise1, 32, 4);
@@ -344,9 +348,9 @@ void CL_ParticleExplosion (vec3_t org, int smoke)
                                        AngleVectors(ang, v, NULL, NULL);
                                        f = noise1[j*32+i] * 1.5f;
                                        VectorScale(v, f, v);
-                                       particle(pt_underwaterspark, noise2[j*32+i] * 0x010101, tex_smoke[rand()&7], false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2], 512.0f, 0, 0, 0, 2, 0);
+                                       particle(pt_underwaterspark, PARTICLE_BILLBOARD, noise2[j*32+i] * 0x010101, tex_smoke[rand()&7], false, 10, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2], 512.0f, 0, 0, 0, 2, 0);
                                        VectorScale(v, 0.75, v);
-                                       particle(pt_underwaterspark, explosparkramp[(noise2[j*32+i] >> 5)], tex_particle, false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2], 512.0f, 0, 0, 0, 2, 0);
+                                       particle(pt_underwaterspark, PARTICLE_BILLBOARD, explosparkramp[(noise2[j*32+i] >> 5)], tex_particle, false, 10, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2], 512.0f, 0, 0, 0, 2, 0);
                                }
                        }
                }
@@ -367,12 +371,12 @@ void CL_ParticleExplosion (vec3_t org, int smoke)
                                        AngleVectors(ang, v, NULL, NULL);
                                        f = noise1[j*32+i] * 1.5f;
                                        VectorScale(v, f, v);
-                                       particle(pt_spark, noise2[j*32+i] * 0x010101, tex_smoke[rand()&7], false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
+                                       particle(pt_spark, PARTICLE_BILLBOARD, noise2[j*32+i] * 0x010101, tex_smoke[rand()&7], false, 10, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
                                        VectorScale(v, 0.75, v);
-                                       particle(pt_spark, explosparkramp[(noise2[j*32+i] >> 5)], tex_particle, false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
+                                       particle(pt_spark, PARTICLE_BILLBOARD, explosparkramp[(noise2[j*32+i] >> 5)], tex_particle, false, 10, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
                                //      VectorRandom(v);
                                //      VectorScale(v, 384, v);
-                               //      particle(pt_spark, explosparkramp[rand()&7], tex_particle, false, 2, lhrandom(16, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
+                               //      particle(pt_spark, PARTICLE_BILLBOARD, explosparkramp[rand()&7], tex_particle, false, 2, 2, lhrandom(16, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
                                }
                        }
                }
@@ -393,7 +397,7 @@ void CL_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength)
        if (!cl_particles.integer) return;
 
        for (i = 0;i < 512;i++)
-               particle(pt_fade, particlepalette[colorStart + (i % colorLength)], tex_particle, false, 1.5, 255, 0.3, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192), 0, 0, 0, 0, 0.1f, 0);
+               particle(pt_fade, PARTICLE_BILLBOARD, particlepalette[colorStart + (i % colorLength)], tex_particle, false, 1.5, 1.5, 255, 0.3, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192), 0, 0, 0, 0, 0.1f, 0);
 }
 
 /*
@@ -408,9 +412,9 @@ void CL_BlobExplosion (vec3_t org)
        if (!cl_particles.integer) return;
 
        for (i = 0;i < 256;i++)
-               particle(pt_blob , particlepalette[ 66+(rand()%6)], tex_particle, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0);
+               particle(pt_blob , PARTICLE_BILLBOARD, particlepalette[ 66+(rand()%6)], tex_particle, false, 4, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0);
        for (i = 0;i < 256;i++)
-               particle(pt_blob2, particlepalette[150+(rand()%6)], tex_particle, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0);
+               particle(pt_blob2, PARTICLE_BILLBOARD, particlepalette[150+(rand()%6)], tex_particle, false, 4, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0);
 }
 
 /*
@@ -429,7 +433,7 @@ void CL_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
                return;
        }
        while (count--)
-               particle(pt_fade, particlepalette[color + (rand()&7)], tex_particle, false, 1, 128, 9999, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-15, 15), lhrandom(-15, 15), lhrandom(-15, 15), 0, 0, 0, 0, 0, 0);
+               particle(pt_fade, PARTICLE_BILLBOARD, particlepalette[color + (rand()&7)], tex_particle, false, 1, 1, 128, 9999, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-15, 15), lhrandom(-15, 15), lhrandom(-15, 15), 0, 0, 0, 0, 0, 0);
 }
 
 // LordHavoc: added this for spawning sparks/dust (which have strong gravity)
@@ -446,13 +450,13 @@ void CL_SparkShower (vec3_t org, vec3_t dir, int count)
 
        // smoke puff
        if (cl_particles_smoke.integer)
-               particle(pt_bulletsmoke, 0xA0A0A0, tex_smoke[rand()&7], true, 5, 255, 9999, 0, org[0], org[1], org[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16), 0, 0, 0, 0, 0, 0);
+               particle(pt_bulletsmoke, PARTICLE_BILLBOARD, 0xA0A0A0, tex_smoke[rand()&7], true, 5, 5, 255, 9999, 0, org[0], org[1], org[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16), 0, 0, 0, 0, 0, 0);
 
        if (cl_particles_sparks.integer)
        {
                // sparks
                while(count--)
-                       particle(pt_spark, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, lhrandom(0, 255), 9999, 1.5, org[0], org[1], org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(0, 128), 512.0f, 0, 0, 0, 0.2f, 0);
+                       particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, 1, lhrandom(0, 255), 9999, 1.5, org[0], org[1], org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(0, 128), 512.0f, 0, 0, 0, 0.2f, 0);
        }
 }
 
@@ -468,7 +472,7 @@ void CL_BloodPuff (vec3_t org, vec3_t vel, int count)
        bloodcount += count;
        while(bloodcount >= 10)
        {
-               particle(pt_blood, 0x300000, tex_smoke[rand()&7], true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
+               particle(pt_blood, PARTICLE_BILLBOARD, 0x300000, tex_smoke[rand()&7], true, 24, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
                bloodcount -= 10;
        }
 }
@@ -498,7 +502,7 @@ void CL_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count)
                vel[0] = (org[0] - center[0]) * velscale[0];
                vel[1] = (org[1] - center[1]) * velscale[1];
                vel[2] = (org[2] - center[2]) * velscale[2];
-               particle(pt_blood, 0x300000, tex_smoke[rand()&7], true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2], 0, 0, 0, 0, 1.0f, 0);
+               particle(pt_blood, PARTICLE_BILLBOARD, 0x300000, tex_smoke[rand()&7], true, 24, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2], 0, 0, 0, 0, 1.0f, 0);
        }
 }
 
@@ -511,7 +515,7 @@ void CL_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int color
        if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;}
 
        while (count--)
-               particle(gravity ? pt_grav : pt_static, particlepalette[colorbase + (rand()&3)], tex_particle, false, 2, 255, lhrandom(1, 2), 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), dir[0] + lhrandom(-randomvel, randomvel), dir[1] + lhrandom(-randomvel, randomvel), dir[2] + lhrandom(-randomvel, randomvel), 0, 0, 0, 0, 0, 0);
+               particle(gravity ? pt_grav : pt_static, PARTICLE_BILLBOARD, particlepalette[colorbase + (rand()&3)], tex_particle, false, 2, 2, 255, lhrandom(1, 2), 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), dir[0] + lhrandom(-randomvel, randomvel), dir[1] + lhrandom(-randomvel, randomvel), dir[2] + lhrandom(-randomvel, randomvel), 0, 0, 0, 0, 0, 0);
 }
 
 void CL_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int type)
@@ -538,12 +542,14 @@ void CL_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int color
        switch(type)
        {
        case 0:
+               count *= 4; // ick, this should be in the mod or maps?
+
                while(count--)
                {
                        vel[0] = dir[0] + lhrandom(-16, 16);
                        vel[1] = dir[1] + lhrandom(-16, 16);
                        vel[2] = dir[2] + lhrandom(-32, 32);
-                       particle(pt_rain, particlepalette[colorbase + (rand()&3)], tex_rain, true, 3, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2], 0, 0);
+                       particle(pt_rain, PARTICLE_UPRIGHT_FACING, particlepalette[colorbase + (rand()&3)], tex_particle, true, 1, 64, 64, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2], 0, 0);
                }
                break;
        case 1:
@@ -552,7 +558,7 @@ void CL_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int color
                        vel[0] = dir[0] + lhrandom(-16, 16);
                        vel[1] = dir[1] + lhrandom(-16, 16);
                        vel[2] = dir[2] + lhrandom(-32, 32);
-                       particle(pt_snow, particlepalette[colorbase + (rand()&3)], tex_particle, false, 2, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2], 0, 0);
+                       particle(pt_snow, PARTICLE_BILLBOARD, particlepalette[colorbase + (rand()&3)], tex_particle, false, 2, 2, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2], 0, 0);
                }
                break;
        default:
@@ -569,7 +575,7 @@ void CL_FlameCube (vec3_t mins, vec3_t maxs, int count)
        if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;}
 
        while (count--)
-               particle(pt_flame, particlepalette[224 + (rand()&15)], tex_particle, false, 8, 255, 9999, 1.1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 64), 0, 0, 0, 0, 0.1f, 0);
+               particle(pt_flame, PARTICLE_BILLBOARD, particlepalette[224 + (rand()&15)], tex_particle, false, 8, 8, 255, 9999, 1.1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 64), 0, 0, 0, 0, 0.1f, 0);
 }
 
 void CL_Flames (vec3_t org, vec3_t vel, int count)
@@ -577,7 +583,7 @@ void CL_Flames (vec3_t org, vec3_t vel, int count)
        if (!cl_particles.integer) return;
 
        while (count--)
-               particle(pt_flame, particlepalette[224 + (rand()&15)], tex_particle, false, 8, 255, 9999, 1.1, org[0], org[1], org[2], vel[0] + lhrandom(-128, 128), vel[1] + lhrandom(-128, 128), vel[2] + lhrandom(-128, 128), 0, 0, 0, 0, 0.1f, 0);
+               particle(pt_flame, PARTICLE_BILLBOARD, particlepalette[224 + (rand()&15)], tex_particle, false, 8, 8, 255, 9999, 1.1, org[0], org[1], org[2], vel[0] + lhrandom(-128, 128), vel[1] + lhrandom(-128, 128), vel[2] + lhrandom(-128, 128), 0, 0, 0, 0, 0.1f, 0);
 }
 
 
@@ -606,7 +612,7 @@ void CL_LavaSplash (vec3_t origin)
                        org[1] = origin[1] + dir[1];
                        org[2] = origin[2] + lhrandom(0, 64);
                        vel = lhrandom(50, 120) / VectorLength(dir); // normalize and scale
-                       particle(pt_lavasplash, particlepalette[224 + (rand()&7)], tex_particle, false, 7, 255, 9999, 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel, 0, 0, 0, 0, 0, 0);
+                       particle(pt_lavasplash, PARTICLE_BILLBOARD, particlepalette[224 + (rand()&7)], tex_particle, false, 7, 7, 255, 9999, 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel, 0, 0, 0, 0, 0, 0);
                }
        }
 }
@@ -625,7 +631,7 @@ void CL_TeleportSplash (vec3_t org)
        for (i=-16 ; i<16 ; i+=8)
                for (j=-16 ; j<16 ; j+=8)
                        for (k=-24 ; k<32 ; k+=8)
-                               particle(pt_fade, 0xFFFFFF, tex_particle, false, 1, lhrandom(64, 128), 9999, 0, org[0] + i + lhrandom(0, 8), org[1] + j + lhrandom(0, 8), org[2] + k + lhrandom(0, 8), i*2 + lhrandom(-12.5, 12.5), j*2 + lhrandom(-12.5, 12.5), k*2 + lhrandom(27.5, 52.5), 0, 0, 0, 0, 0.1f, -512.0f);
+                               particle(pt_fade, PARTICLE_BILLBOARD, 0xFFFFFF, tex_particle, false, 1, 1, lhrandom(64, 128), 9999, 0, org[0] + i + lhrandom(0, 8), org[1] + j + lhrandom(0, 8), org[2] + k + lhrandom(0, 8), i*2 + lhrandom(-12.5, 12.5), j*2 + lhrandom(-12.5, 12.5), k*2 + lhrandom(27.5, 52.5), 0, 0, 0, 0, 0.1f, -512.0f);
 }
 
 void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
@@ -640,7 +646,7 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
        VectorNormalize(dir);
 
        if (type == 0 && host_frametime != 0) // rocket glow
-               particle(pt_oneframe, 0xFFFFFF, tex_rocketglow, false, 24, 255, 9999, 0, end[0] - 12 * dir[0], end[1] - 12 * dir[1], end[2] - 12 * dir[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+               particle(pt_oneframe, PARTICLE_BILLBOARD, 0xFFFFFF, tex_rocketglow, false, 24, 24, 255, 9999, 0, end[0] - 12 * dir[0], end[1] - 12 * dir[1], end[2] - 12 * dir[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
        t = ent->persistent.trail_time;
        if (t >= cl.time)
@@ -685,18 +691,18 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                else if (bubbles && cl_particles_bubbles.integer)
                                {
                                        dec = 0.005f;
-                                       particle(pt_bubble, 0xFFFFFF, tex_bubble, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
-                                       particle(pt_bubble, 0xFFFFFF, tex_bubble, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
-                                       particle(pt_smoke, 0xFFFFFF, tex_smoke[rand()&7], false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+                                       particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, 2, 2, 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+                                       particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, 2, 2, 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+                                       particle(pt_smoke, PARTICLE_BILLBOARD, 0xFFFFFF, tex_smoke[rand()&7], false, 2, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                }
                                else
                                {
                                        dec = 0.005f;
-                                       particle(pt_smoke, 0xC0C0C0, tex_smoke[rand()&7], true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
-                                       //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
-                                       //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
-                                       //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
-                                       //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
+                                       particle(pt_smoke, PARTICLE_BILLBOARD, 0xC0C0C0, tex_smoke[rand()&7], true, 2, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+                                       //particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
+                                       //particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
+                                       //particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
+                                       //particle(pt_spark, PARTICLE_BILLBOARD, particlepalette[0x68 + (rand() & 7)], tex_particle, false, 1, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
                                }
                                break;
 
@@ -707,14 +713,14 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                else if (bubbles && cl_particles_bubbles.integer)
                                {
                                        dec = 0.02f;
-                                       particle(pt_bubble, 0xFFFFFF, tex_bubble, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
-                                       particle(pt_bubble, 0xFFFFFF, tex_bubble, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
-                                       particle(pt_smoke, 0xFFFFFF, tex_smoke[rand()&7], false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+                                       particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, 2, 2, 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+                                       particle(pt_bubble, PARTICLE_BILLBOARD, 0xFFFFFF, tex_bubble, false, 2, 2, 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+                                       particle(pt_smoke, PARTICLE_BILLBOARD, 0xFFFFFF, tex_smoke[rand()&7], false, 2, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                }
                                else
                                {
                                        dec = 0.02f;
-                                       particle(pt_smoke, 0x808080, tex_smoke[rand()&7], true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+                                       particle(pt_smoke, PARTICLE_BILLBOARD, 0x808080, tex_smoke[rand()&7], true, 2, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                }
                                break;
 
@@ -725,7 +731,7 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                else
                                {
                                        dec = 0.1f;
-                                       particle(pt_blood, 0x300000, tex_smoke[rand()&7], true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
+                                       particle(pt_blood, PARTICLE_BILLBOARD, 0x300000, tex_smoke[rand()&7], true, 24, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
                                }
                                break;
 
@@ -735,23 +741,23 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                else
                                {
                                        dec = 0.15f;
-                                       particle(pt_blood, 0x300000, tex_smoke[rand()&7], true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
+                                       particle(pt_blood, PARTICLE_BILLBOARD, 0x300000, tex_smoke[rand()&7], true, 24, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
                                }
                                break;
 
                        case 3: // green tracer
                                dec = 0.02f;
-                               particle(pt_fade, 0x373707, tex_smoke[rand()&7], false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+                               particle(pt_fade, PARTICLE_BILLBOARD, 0x373707, tex_smoke[rand()&7], false, 4, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                break;
 
                        case 5: // flame tracer
                                dec = 0.02f;
-                               particle(pt_fade, 0xCF632B, tex_smoke[rand()&7], false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+                               particle(pt_fade, PARTICLE_BILLBOARD, 0xCF632B, tex_smoke[rand()&7], false, 4, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                break;
 
                        case 6: // voor trail
                                dec = 0.05f; // sparse trail
-                               particle(pt_fade, 0x47232B, tex_smoke[rand()&7], false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+                               particle(pt_fade, PARTICLE_BILLBOARD, 0x47232B, tex_smoke[rand()&7], false, 4, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                break;
 
                        case 7: // Nehahra smoke tracer
@@ -760,7 +766,7 @@ void CL_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
                                else
                                {
                                        dec = 0.14f;
-                                       particle(pt_smoke, 0xC0C0C0, tex_smoke[rand()&7], true, 10, 64, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+                                       particle(pt_smoke, PARTICLE_BILLBOARD, 0xC0C0C0, tex_smoke[rand()&7], true, 10, 10, 64, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                                }
                                break;
                }
@@ -786,7 +792,7 @@ void CL_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
        color = particlepalette[color];
        while (len--)
        {
-               particle(pt_smoke, color, tex_particle, false, 8, 192, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+               particle(pt_smoke, PARTICLE_BILLBOARD, color, tex_particle, false, 8, 8, 192, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
                VectorAdd (start, vec, start);
        }
 }
@@ -843,7 +849,7 @@ void CL_MoveParticles (void)
                                VectorCopy(v, p->org);
                                if (p->bounce < 0)
                                {
-                                       CL_Decal(v, p->tex, p->scale * cl_particles_size.value, p->color[0] * (1.0f / 255.0f), p->color[1] * (1.0f / 255.0f), p->color[2] * (1.0f / 255.0f), p->alpha * (1.0f / 255.0f));
+                                       CL_Decal(v, p->tex, p->scalex * cl_particles_size.value, p->color[0] * (1.0f / 255.0f), p->color[1] * (1.0f / 255.0f), p->color[2] * (1.0f / 255.0f), p->alpha * (1.0f / 255.0f));
                                        p->die = -1;
                                        freeparticles[j++] = p;
                                        continue;
@@ -894,7 +900,8 @@ void CL_MoveParticles (void)
                        a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
                        if (a != CONTENTS_EMPTY && a != CONTENTS_SKY)
                        {
-                               vec3_t normal;
+                               p->die = -1;
+                               /*
                                if (a == CONTENTS_SOLID && Mod_PointInLeaf(p->oldorg, cl.worldmodel)->contents == CONTENTS_SOLID)
                                        break; // still in solid
                                p->die = cl.time + 1000;
@@ -904,26 +911,34 @@ void CL_MoveParticles (void)
                                case CONTENTS_LAVA:
                                case CONTENTS_SLIME:
                                        p->tex = tex_smoke[rand()&7];
+                                       p->orientation = PARTICLE_BILLBOARD;
                                        p->type = pt_steam;
                                        p->alpha = 96;
-                                       p->scale = 5;
+                                       p->scalex = 5;
+                                       p->scaley = 5;
                                        p->vel[2] = 96;
                                        break;
                                case CONTENTS_WATER:
                                        p->tex = tex_smoke[rand()&7];
+                                       p->orientation = PARTICLE_BILLBOARD;
                                        p->type = pt_splash;
                                        p->alpha = 96;
-                                       p->scale = 5;
+                                       p->scalex = 5;
+                                       p->scaley = 5;
                                        p->vel[2] = 96;
                                        break;
                                default: // CONTENTS_SOLID and any others
                                        TraceLine(p->oldorg, p->org, v, normal, 0);
                                        VectorCopy(v, p->org);
                                        p->tex = tex_smoke[rand()&7];
+                                       p->orientation = PARTICLE_BILLBOARD;
                                        p->type = pt_fade;
+                                       p->scalex = 5;
+                                       p->scaley = 5;
                                        VectorClear(p->vel);
                                        break;
                                }
+                               */
                        }
                        break;
                case pt_blood:
@@ -934,7 +949,8 @@ void CL_MoveParticles (void)
                                if (a == CONTENTS_WATER || a == CONTENTS_SLIME)
                                {
                                        p->friction = 5;
-                                       p->scale += frametime * 32.0f;
+                                       p->scalex += frametime * 32.0f;
+                                       p->scaley += frametime * 32.0f;
                                        p->alpha -= frametime * 128.0f;
                                        p->vel[2] += gravity * 0.125f;
                                        if (p->alpha < 1)
@@ -961,8 +977,10 @@ void CL_MoveParticles (void)
                        if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_EMPTY)
                        {
                                p->tex = tex_smoke[rand()&7];
+                               p->orientation = PARTICLE_BILLBOARD;
                                p->color[0] = p->color[1] = p->color[2] = 255;
-                               p->scale = 16;
+                               p->scalex = 8;
+                               p->scaley = 8;
                                p->type = pt_explosionsplash;
                        }
                        else
@@ -976,7 +994,8 @@ void CL_MoveParticles (void)
                                p->vel[2] -= gravity;
                        else
                                p->alpha = 0;
-                       p->scale += frametime * 64.0f;
+                       p->scalex += frametime * 64.0f;
+                       p->scaley += frametime * 64.0f;
                        p->alpha -= frametime * 1024.0f;
                        if (p->alpha < 1)
                                p->die = -1;
@@ -991,8 +1010,10 @@ void CL_MoveParticles (void)
                        if (a != CONTENTS_WATER && a != CONTENTS_SLIME)
                        {
                                p->tex = tex_smoke[rand()&7];
+                               p->orientation = PARTICLE_BILLBOARD;
                                p->type = pt_splashpuff;
-                               p->scale = 4;
+                               p->scalex = 4;
+                               p->scaley = 4;
                                p->vel[0] = p->vel[1] = p->vel[2] = 0;
                                break;
                        }
@@ -1012,21 +1033,24 @@ void CL_MoveParticles (void)
                                p->die = -1;
                        break;
                case pt_bulletsmoke:
-                       p->scale += frametime * 16;
+                       p->scalex += frametime * 16;
+                       p->scaley += frametime * 16;
                        p->alpha -= frametime * 1024;
                        p->vel[2] += gravity * 0.1;
                        if (p->alpha < 1)
                                p->die = -1;
                        break;
                case pt_smoke:
-                       p->scale += frametime * 24;
+                       p->scalex += frametime * 24;
+                       p->scaley += frametime * 24;
                        p->alpha -= frametime * 256;
                        p->vel[2] += gravity * 0.1;
                        if (p->alpha < 1)
                                p->die = -1;
                        break;
                case pt_steam:
-                       p->scale += frametime * 48;
+                       p->scalex += frametime * 48;
+                       p->scaley += frametime * 48;
                        p->alpha -= frametime * 512;
                        p->vel[2] += gravity * 0.05;
                        if (p->alpha < 1)
@@ -1048,6 +1072,8 @@ void CL_MoveParticles (void)
                                b = traceline_endcontents;
                                if (f < 1 && b != CONTENTS_EMPTY && b != CONTENTS_SKY)
                                {
+                                       p->die = -1;
+                                       /*
                                        p->die = cl.time + 1000;
                                        p->vel[0] = p->vel[1] = p->vel[2] = 0;
                                        VectorCopy(v, p->org);
@@ -1056,22 +1082,28 @@ void CL_MoveParticles (void)
                                        case CONTENTS_LAVA:
                                        case CONTENTS_SLIME:
                                                p->tex = tex_smoke[rand()&7];
+                                               p->orientation = PARTICLE_BILLBOARD;
                                                p->type = pt_steam;
-                                               p->scale = 3;
+                                               p->scalex = 3;
+                                               p->scaley = 3;
                                                p->vel[2] = 96;
                                                break;
                                        default: // water, solid, and anything else
                                                p->tex = tex_rainsplash[0];
+                                               p->orientation = PARTICLE_ORIENTED_DOUBLESIDED;
                                                p->time2 = 0;
                                                VectorCopy(normal, p->vel2);
                                        //      VectorAdd(p->org, normal, p->org);
                                                p->type = pt_raindropsplash;
-                                               p->scale = 8;
+                                               p->scalex = 8;
+                                               p->scaley = 8;
                                                break;
                                        }
+                                       */
                                }
                        }
                        break;
+                       /*
                case pt_raindropsplash:
                        p->time2 += frametime * 64.0f;
                        if (p->time2 >= 16.0f)
@@ -1080,7 +1112,9 @@ void CL_MoveParticles (void)
                                break;
                        }
                        p->tex = tex_rainsplash[(int) p->time2];
+                       p->orientation = PARTICLE_ORIENTED_DOUBLESIDED;
                        break;
+                       */
                case pt_flame:
                        p->alpha -= frametime * 512;
                        p->vel[2] += gravity;
@@ -1109,22 +1143,16 @@ void CL_MoveParticles (void)
                                pressureused = true;
 
                        // build renderparticle for renderer to use
-                       if (p->type == pt_raindropsplash)
-                       {
-                               r->orientation = PARTICLE_ORIENTED_DOUBLESIDED;
-                               r->dir[0] = p->vel2[0];
-                               r->dir[1] = p->vel2[1];
-                               r->dir[2] = p->vel2[2];
-                       }
-                       else if (p->tex == tex_rain)
-                               r->orientation = PARTICLE_UPRIGHT_FACING;
-                       else
-                               r->orientation = PARTICLE_BILLBOARD;
+                       r->orientation = p->orientation;
+                       r->dir[0] = p->vel2[0];
+                       r->dir[1] = p->vel2[1];
+                       r->dir[2] = p->vel2[2];
                        r->org[0] = p->org[0];
                        r->org[1] = p->org[1];
                        r->org[2] = p->org[2];
                        r->tex = p->tex;
-                       r->scale = p->scale * 0.5f * cl_particles_size.value;
+                       r->scalex = p->scalex * 0.5f * cl_particles_size.value;
+                       r->scaley = p->scaley * 0.5f * cl_particles_size.value;
                        r->dynlight = p->dynlight;
                        r->color[0] = p->color[0] * (1.0f / 255.0f);
                        r->color[1] = p->color[1] * (1.0f / 255.0f);
@@ -1164,9 +1192,9 @@ void CL_MoveParticles (void)
                                                dist = DotProduct(diff, diff);
                                                if (dist < 4096 && dist >= 1)
                                                {
-                                                       dist = freeparticles[j]->scale * 4.0f * frametime / sqrt(dist);
+                                                       dist = freeparticles[j]->scalex * 4.0f * frametime / sqrt(dist);
                                                        VectorMA(p->vel, dist, diff, p->vel);
-                                                       //dist = freeparticles[j]->scale * 4.0f * frametime / dist;
+                                                       //dist = freeparticles[j]->scalex * 4.0f * frametime / dist;
                                                        //VectorMA(p->vel, dist, freeparticles[j]->vel, p->vel);
                                                }
                                        }
index d9dbbe5..6f436a4 100644 (file)
--- a/client.h
+++ b/client.h
@@ -438,7 +438,8 @@ typedef struct renderparticle_s
        int                     tex;
        int                     orientation;
        int                     dynlight;
-       float           scale;
+       float           scalex;
+       float           scaley;
        float           org[3];
        float           dir[3];
        float           color[4];
index 16a92c2..7bfd6bf 100644 (file)
@@ -15,11 +15,14 @@ typedef struct buf_mesh_s
 {
        struct buf_mesh_s *next;
        int depthmask;
+       int depthtest;
        int blendfunc1, blendfunc2;
        int textures[MAX_TEXTUREUNITS];
        float texturergbscale[MAX_TEXTUREUNITS];
        int firsttriangle;
        int triangles;
+       int firstvert;
+       int lastvert;
 }
 buf_mesh_t;
 
@@ -284,7 +287,7 @@ int errornumber = 0;
 // renders mesh buffers, called to flush buffers when full
 void R_Mesh_Render(void)
 {
-       int i, k, blendfunc1, blendfunc2, blend, depthmask, unit = 0, clientunit = 0, firsttriangle, triangles, texture[MAX_TEXTUREUNITS];
+       int i, k, blendfunc1, blendfunc2, blend, depthmask, depthtest, unit = 0, clientunit = 0, firsttriangle, triangles, firstvert, lastvert, texture[MAX_TEXTUREUNITS];
        float farclip, texturergbscale[MAX_TEXTUREUNITS];
        buf_mesh_t *mesh;
        if (!backendactive)
@@ -307,6 +310,7 @@ CHECKGLERROR
 CHECKGLERROR
        glCullFace(GL_FRONT);
 CHECKGLERROR
+       depthtest = true;
        glEnable(GL_DEPTH_TEST);
 CHECKGLERROR
        blendfunc1 = GL_ONE;
@@ -545,6 +549,14 @@ CHECKGLERROR
                                }
                        }
                }
+               if (depthtest != mesh->depthtest)
+               {
+                       depthtest = mesh->depthtest;
+                       if (depthtest)
+                               glEnable(GL_DEPTH_TEST);
+                       else
+                               glDisable(GL_DEPTH_TEST);
+               }
                if (depthmask != mesh->depthmask)
                {
                        depthmask = mesh->depthmask;
@@ -554,6 +566,8 @@ CHECKGLERROR
 
                firsttriangle = mesh->firsttriangle;
                triangles = mesh->triangles;
+               firstvert = mesh->firstvert;
+               lastvert = mesh->lastvert;
                mesh = &buf_mesh[++k];
 
                if (meshmerge)
@@ -564,6 +578,7 @@ CHECKGLERROR
                        while (k < currentmesh
                                && mesh->blendfunc1 == blendfunc1
                                && mesh->blendfunc2 == blendfunc2
+                               && mesh->depthtest == depthtest
                                && mesh->depthmask == depthmask
                                && mesh->textures[0] == texture[0]
                                && mesh->textures[1] == texture[1]
@@ -575,11 +590,20 @@ CHECKGLERROR
                                && mesh->texturergbscale[3] == texturergbscale[3])
                        {
                                triangles += mesh->triangles;
+                               if (firstvert > mesh->firstvert)
+                                       firstvert = mesh->firstvert;
+                               if (lastvert < mesh->lastvert)
+                                       lastvert = mesh->lastvert;
                                mesh = &buf_mesh[++k];
                        }
                }
 
+#ifdef WIN32
+               // FIXME: dynamic link to GL so we can get DrawRangeElements on WIN32
                glDrawElements(GL_TRIANGLES, triangles * 3, GL_UNSIGNED_INT, (unsigned int *)&buf_tri[firsttriangle]);
+#else
+               glDrawRangeElements(GL_TRIANGLES, firstvert, lastvert + 1, triangles * 3, GL_UNSIGNED_INT, (unsigned int *)&buf_tri[firsttriangle]);
+#endif
 CHECKGLERROR
        }
 
@@ -638,6 +662,8 @@ CHECKGLERROR
 
        glDisable(GL_BLEND);
 CHECKGLERROR
+       glEnable(GL_DEPTH_TEST);
+CHECKGLERROR
        glDepthMask(true);
 CHECKGLERROR
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -720,6 +746,8 @@ void R_Mesh_AddTransparent(void)
                                buf_tri[currenttriangle].index[0] = tri->index[0] + currentvertex;
                                buf_tri[currenttriangle].index[1] = tri->index[1] + currentvertex;
                                buf_tri[currenttriangle].index[2] = tri->index[2] + currentvertex;
+                               mesh->firstvert = min(buf_tri[currenttriangle].index[0], min(buf_tri[currenttriangle].index[1], buf_tri[currenttriangle].index[2]));
+                               mesh->lastvert = max(buf_tri[currenttriangle].index[0], max(buf_tri[currenttriangle].index[1], buf_tri[currenttriangle].index[2]));
                                mesh->firsttriangle = currenttriangle++;
                                mesh->triangles = 1;
                                tri = tri->next;
@@ -748,7 +776,21 @@ void R_Mesh_Draw(const rmeshinfo_t *m)
         || !m->numtriangles
         || m->vertex == NULL
         || !m->numverts)
-               return;
+               return;
+       // ignore meaningless alpha meshs
+       if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
+       {
+               if (m->color)
+               {
+                       for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
+                               if (*in >= 0.01f)
+                                       break;
+                       if (i == m->numverts)
+                               return;
+               }
+               else if (m->ca < 0.01f)
+                       return;
+       }
 
        if (!backendactive)
                Sys_Error("R_DrawMesh: called when backend is not active\n");
@@ -904,6 +946,7 @@ void R_Mesh_Draw(const rmeshinfo_t *m)
                mesh->blendfunc1 = m->blendfunc1;
                mesh->blendfunc2 = m->blendfunc2;
                mesh->depthmask = false;
+               mesh->depthtest = !m->depthdisable;
                j = -1;
                for (i = 0;i < backendunits;i++)
                {
@@ -935,6 +978,7 @@ void R_Mesh_Draw(const rmeshinfo_t *m)
                mesh->blendfunc1 = m->blendfunc1;
                mesh->blendfunc2 = m->blendfunc2;
                mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
+               mesh->depthtest = !m->depthdisable;
                mesh->firsttriangle = currenttriangle;
                mesh->triangles = m->numtriangles;
                j = -1;
@@ -953,8 +997,10 @@ void R_Mesh_Draw(const rmeshinfo_t *m)
                index = (int *)&buf_tri[currenttriangle];
                for (i = 0;i < m->numtriangles * 3;i++)
                        index[i] = m->index[i] + currentvertex;
+               mesh->firstvert = currentvertex;
                currenttriangle += m->numtriangles;
                currentvertex += m->numverts;
+               mesh->lastvert = currentvertex - 1;
        }
 
        c_meshtris += m->numtriangles;
index c9f98d4..bde446b 100644 (file)
@@ -7,6 +7,7 @@ typedef struct
 {
        int transparent;
        int depthwrite; // force depth writing enabled even if polygon is not opaque
+       int depthdisable; // disable depth read/write entirely
        int blendfunc1;
        int blendfunc2;
        int numtriangles;
index 66b20cf..c84eb7e 100644 (file)
@@ -589,6 +589,13 @@ static void R_SetupGL (void)
        if (!r_render.integer)
                return;
 
+//     glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: moved to SCR_UpdateScreen
+       gldepthmin = 0;
+       gldepthmax = 1;
+       glDepthFunc (GL_LEQUAL);
+
+       glDepthRange (gldepthmin, gldepthmax);
+
        // update farclip based on previous frame
        r_farclip = r_newfarclip;
 
@@ -628,24 +635,7 @@ static void R_SetupGL (void)
        glDepthMask(1);
 }
 
-/*
-=============
-R_Clear
-=============
-*/
-static void R_Clear (void)
-{
-       if (!r_render.integer)
-               return;
-//     glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: moved to SCR_UpdateScreen
-       gldepthmin = 0;
-       gldepthmax = 1;
-       glDepthFunc (GL_LEQUAL);
-
-       glDepthRange (gldepthmin, gldepthmax);
-}
-
-static void GL_BlendView(void)
+static void R_BlendView(void)
 {
        if (!r_render.integer)
                return;
@@ -654,10 +644,10 @@ static void GL_BlendView(void)
                return;
 
        glMatrixMode(GL_PROJECTION);
-    glLoadIdentity ();
+       glLoadIdentity ();
        glOrtho  (0, 1, 1, 0, -99999, 99999);
        glMatrixMode(GL_MODELVIEW);
-    glLoadIdentity ();
+       glLoadIdentity ();
        glDisable (GL_DEPTH_TEST);
        glDisable (GL_CULL_FACE);
        glDisable(GL_TEXTURE_2D);
@@ -686,76 +676,14 @@ R_RenderView
 r_refdef must be set before the first call
 ================
 */
-char r_speeds2_string[1024];
-int speedstringcount;
-
-void timestring(int t, char *desc)
-{
-       char tempbuf[256];
-       int length;
-       if (t < 1000000)
-               sprintf(tempbuf, "%6ius %s", t, desc);
-       else
-               sprintf(tempbuf, "%6ims %s", t / 1000, desc);
-       length = strlen(tempbuf);
-//     while (length < 20)
-//             tempbuf[length++] = ' ';
-//     tempbuf[length] = 0;
-       if (speedstringcount + length > (vid.conwidth / 8))
-       {
-               strcat(r_speeds2_string, "\n");
-               speedstringcount = 0;
-       }
-       // skip the space at the beginning if it's the first on the line
-       if (speedstringcount == 0)
-       {
-               strcat(r_speeds2_string, tempbuf + 1);
-               speedstringcount = length - 1;
-       }
-       else
-       {
-               strcat(r_speeds2_string, tempbuf);
-               speedstringcount += length;
-       }
-}
-
-#define TIMEREPORT(NAME) \
-       if (r_speeds2.integer)\
-       {\
-               temptime = currtime;\
-               currtime = Sys_DoubleTime();\
-               timestring((int) ((currtime - temptime) * 1000000.0), NAME);\
-       }
-
 void R_RenderView (void)
 {
-       double starttime, currtime, temptime;
-
        if (!cl.worldmodel)
                Host_Error ("R_RenderView: NULL worldmodel");
 
-       if (r_speeds2.integer)
-       {
-               speedstringcount = 0;
-               sprintf(r_speeds2_string, "org:'%c%6.2f %c%6.2f %c%6.2f' ang:'%c%3.0f %c%3.0f %c%3.0f' dir:'%c%2.3f %c%2.3f %c%2.3f'\n%6i walls %6i dlitwalls %7i modeltris %7i meshtris\nBSP: %6i faces %6i nodes %6i leafs\n%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n",
-                       r_origin[0] < 0 ? '-' : ' ', fabs(r_origin[0]), r_origin[1] < 0 ? '-' : ' ', fabs(r_origin[1]), r_origin[2] < 0 ? '-' : ' ', fabs(r_origin[2]), r_refdef.viewangles[0] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[0]), r_refdef.viewangles[1] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[1]), r_refdef.viewangles[2] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[2]), vpn[0] < 0 ? '-' : ' ', fabs(vpn[0]), vpn[1] < 0 ? '-' : ' ', fabs(vpn[1]), vpn[2] < 0 ? '-' : ' ', fabs(vpn[2]),
-                       c_brush_polys, c_light_polys, c_alias_polys, c_meshtris,
-                       c_faces, c_nodes, c_leafs,
-                       c_models, c_bmodels, c_sprites, c_particles, c_dlights);
-
-               starttime = currtime = Sys_DoubleTime();
-       }
-       else
-               starttime = currtime = 0;
-
        // FIXME: move to client
        R_MoveExplosions();
-       TIMEREPORT("mexplosion")
-
-       R_Clear();
-       TIMEREPORT("clear     ")
-
-       // render normal view
+       R_TimeReport("mexplosion");
 
        R_SetupFrame();
        R_SetFrustum();
@@ -767,39 +695,39 @@ void R_RenderView (void)
                R_Clip_StartFrame();
        R_BuildLightList();
 
-       TIMEREPORT("setup     ")
+       R_TimeReport("setup");
 
        R_DrawWorld();
-       TIMEREPORT("worldnode ")
+       R_TimeReport("worldnode");
 
        R_MarkEntities();
-       TIMEREPORT("markentity")
+       R_TimeReport("markentity");
 
        if (r_ser.integer)
        {
                R_Clip_EndFrame();
-       TIMEREPORT("hiddensurf")
+               R_TimeReport("hiddensurf");
        }
 
        R_MarkWorldLights();
-       TIMEREPORT("marklights")
+       R_TimeReport("marklights");
 
        if (skyrendermasked && R_DrawBModelSky())
        {
-       TIMEREPORT("bmodelsky ")
+               R_TimeReport("bmodelsky");
        }
 
        R_SetupForWorldRendering();
        R_PrepareSurfaces();
-       TIMEREPORT("surfprep  ")
+       R_TimeReport("surfprep");
 
        R_DrawSurfacesAll();
-       TIMEREPORT("surf      ")
+       R_TimeReport("surfdraw");
 
        if (r_drawportals.integer)
        {
                R_DrawPortals();
-       TIMEREPORT("portals   ")
+               R_TimeReport("portals");
        }
 
        // don't let sound skip if going slow
@@ -808,29 +736,28 @@ void R_RenderView (void)
 
        R_DrawViewModel();
        R_DrawModels();
-       TIMEREPORT("models    ")
+       R_TimeReport("models");
 
        R_DrawDecals();
-       TIMEREPORT("decals    ")
+       R_TimeReport("decals");
 
        R_DrawParticles();
-       TIMEREPORT("particles ")
+       R_TimeReport("particles");
 
        R_DrawExplosions();
-       TIMEREPORT("explosions")
+       R_TimeReport("explosions");
 
        // draw transparent meshs
        R_Mesh_AddTransparent();
-       TIMEREPORT("transmesh ")
+       R_TimeReport("sorttrans");
 
        // render any queued meshs
        R_Mesh_Render();
-       TIMEREPORT("finishmesh")
+       R_TimeReport("meshrender");
 
-       GL_BlendView();
-       TIMEREPORT("blend     ")
+       R_BlendView();
+       R_TimeReport("blendview");
 
-       if (r_speeds2.integer)
-               timestring((int) ((Sys_DoubleTime() - starttime) * 1000000.0),
-                  "total     ");
+       Mem_CheckSentinelsGlobal();
+       R_TimeReport("memtest");
 }
index b0650a9..e27ff41 100644 (file)
@@ -534,7 +534,7 @@ static void RSurfShader_Water_Pass_Base(msurface_t *s)
        else
        {
                m.transparent = false;
-               m.blendfunc1 = GL_SRC_ALPHA;
+               m.blendfunc1 = GL_ONE;
                m.blendfunc2 = GL_ZERO;
        }
        m.numtriangles = s->mesh.numtriangles;
index 54ebddb..dc542a1 100644 (file)
@@ -850,6 +850,59 @@ void GL_BrightenScreen(void)
        CHECKGLERROR
 }
 
+char r_speeds2_string[1024];
+int speedstringcount, r_timereport_active;
+double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0;
+
+void R_TimeReport(char *desc)
+{
+       char tempbuf[256];
+       int length;
+       int t;
+
+       if (!r_timereport_active)
+               return;
+
+       r_timereport_temp = r_timereport_current;
+       r_timereport_current = Sys_DoubleTime();
+       t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0);
+
+       sprintf(tempbuf, "%8i %s", t, desc);
+       length = strlen(tempbuf);
+       while (length < 20)
+               tempbuf[length++] = ' ';
+       tempbuf[length] = 0;
+       if (speedstringcount + length > (vid.conwidth / 8))
+       {
+               strcat(r_speeds2_string, "\n");
+               speedstringcount = 0;
+       }
+       // skip the space at the beginning if it's the first on the line
+       if (speedstringcount == 0)
+       {
+               strcat(r_speeds2_string, tempbuf + 1);
+               speedstringcount = length - 1;
+       }
+       else
+       {
+               strcat(r_speeds2_string, tempbuf);
+               speedstringcount += length;
+       }
+}
+
+void R_TimeReport_Start(void)
+{
+       r_timereport_active = r_speeds2.integer && cl.worldmodel && cls.state == ca_connected;
+       if (r_timereport_active)
+               r_timereport_start = Sys_DoubleTime();
+}
+
+void R_TimeReport_End(void)
+{
+       r_timereport_current = r_timereport_start;
+       R_TimeReport("total");
+}
+
 /*
 ==================
 SCR_UpdateScreen
@@ -887,6 +940,25 @@ void SCR_UpdateScreen (void)
        if (!scr_initialized || !con_initialized)
                return;                         // not initialized yet
 
+       r_speeds2_string[0] = 0;
+       if (r_speeds2.integer)
+       {
+               speedstringcount = 0;
+               sprintf(r_speeds2_string, "org:'%c%6.2f %c%6.2f %c%6.2f' ang:'%c%3.0f %c%3.0f %c%3.0f' dir:'%c%2.3f %c%2.3f %c%2.3f'\n%6i walls %6i dlitwalls %7i modeltris %7i meshtris\nBSP: %6i faces %6i nodes %6i leafs\n%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n",
+                       r_origin[0] < 0 ? '-' : ' ', fabs(r_origin[0]), r_origin[1] < 0 ? '-' : ' ', fabs(r_origin[1]), r_origin[2] < 0 ? '-' : ' ', fabs(r_origin[2]), r_refdef.viewangles[0] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[0]), r_refdef.viewangles[1] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[1]), r_refdef.viewangles[2] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[2]), vpn[0] < 0 ? '-' : ' ', fabs(vpn[0]), vpn[1] < 0 ? '-' : ' ', fabs(vpn[1]), vpn[2] < 0 ? '-' : ' ', fabs(vpn[2]),
+                       c_brush_polys, c_light_polys, c_alias_polys, c_meshtris,
+                       c_faces, c_nodes, c_leafs,
+                       c_models, c_bmodels, c_sprites, c_particles, c_dlights);
+               R_TimeReport_Start();
+       }
+
+       Mem_CheckSentinelsGlobal();
+       R_TimeReport("memtest");
+
+       GL_Finish();
+       GL_EndRendering ();
+
+       R_TimeReport("finish");
 
        GL_BeginRendering (&vid.realx, &vid.realy, &vid.realwidth, &vid.realheight);
 
@@ -922,6 +994,8 @@ void SCR_UpdateScreen (void)
 //     if (vid.recalc_refdef)
                SCR_CalcRefdef();
 
+       R_TimeReport("calcrefdef");
+
        if (r_render.integer)
        {
                glClearColor(0,0,0,0);
@@ -930,6 +1004,8 @@ void SCR_UpdateScreen (void)
                CHECKGLERROR
        }
 
+       R_TimeReport("clear");
+
        if (gl_dither.integer)
                glEnable(GL_DITHER);
        else
@@ -941,8 +1017,12 @@ void SCR_UpdateScreen (void)
 //
        SCR_SetUpToDrawConsole();
 
+       R_TimeReport("setupconsole");
+
        V_RenderView();
 
+       V_UpdateBlends();
+
        GL_Set2D();
 
        R_Clip_DisplayBuffer();
@@ -1004,7 +1084,11 @@ void SCR_UpdateScreen (void)
                Draw_String(vid.conwidth - (8*8), vid.conheight - sb_lines - 8, temp, 9999);
        }
 
-       if (r_speeds2.integer && r_speeds2_string[0])
+       R_TimeReport("2d");
+
+       R_TimeReport_End();
+
+       if (r_speeds2_string[0] && cls.state == ca_connected && cl.worldmodel)
        {
                int i, j, lines, y;
                lines = 1;
@@ -1024,22 +1108,15 @@ void SCR_UpdateScreen (void)
                                i++;
                        y += 8;
                }
-               // clear so it won't reprint without renderer being called again
-               r_speeds2_string[0] = 0;
        }
 
-       V_UpdateBlends();
-
        GL_BrightenScreen();
 
-       GL_Finish();
-
        if (r_speeds.integer)
        {
                time2 = Sys_DoubleTime ();
                Con_Printf ("%3i ms  %4i wpoly %4i epoly %6i meshtris %4i lightpoly %4i BSPnodes %4i BSPleafs %4i BSPfaces %4i models %4i bmodels %4i sprites %4i particles %3i dlights\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys, c_meshtris, c_light_polys, c_nodes, c_leafs, c_faces, c_models, c_bmodels, c_sprites, c_particles, c_dlights);
        }
-       GL_EndRendering ();
 }
 
 // for profiling, this is separated
index 88b8f01..dbd3f00 100644 (file)
@@ -87,6 +87,7 @@ static void R_InitParticleTexture (void)
        memset(particletexturedata, 255, sizeof(particletexturedata));
 
        // the particletexture[][] array numbers must match the cl_part.c textures
+       // smoke/blood
        for (i = 0;i < 8;i++)
        {
                do
@@ -122,6 +123,7 @@ static void R_InitParticleTexture (void)
                setuptex(i + 0, 1, i + 8, &data[0][0][0], particletexturedata);
        }
 
+       // bullet hole
        for (i = 0;i < 8;i++)
        {
                float p[32][32];
@@ -179,6 +181,7 @@ static void R_InitParticleTexture (void)
                setuptex(i + 8, 1, i + 16, &data[0][0][0], particletexturedata);
        }
 
+       // rain splash
        for (i = 0;i < 16;i++)
        {
                radius = i * 3.0f / 16.0f;
@@ -199,6 +202,7 @@ static void R_InitParticleTexture (void)
                setuptex(i + 16, 1, i + 24, &data[0][0][0], particletexturedata);
        }
 
+       // normal particle
        for (y = 0;y < 32;y++)
        {
                dy = y - 16;
@@ -214,6 +218,7 @@ static void R_InitParticleTexture (void)
        setuptex(32, 0, 40, &data[0][0][0], particletexturedata);
        setuptex(32, 1, 40, &data[0][0][0], particletexturedata);
 
+       // rain
        light[0] = 1;light[1] = 1;light[2] = 1;
        VectorNormalize(light);
        for (y = 0;y < 32;y++)
@@ -227,6 +232,7 @@ static void R_InitParticleTexture (void)
        setuptex(33, 0, 41, &data[0][0][0], particletexturedata);
        setuptex(33, 1, 41, &data[0][0][0], particletexturedata);
 
+       // bubble
        light[0] = 1;light[1] = 1;light[2] = 1;
        VectorNormalize(light);
        for (y = 0;y < 32;y++)
@@ -240,6 +246,7 @@ static void R_InitParticleTexture (void)
        setuptex(34, 0, 42, &data[0][0][0], particletexturedata);
        setuptex(34, 1, 42, &data[0][0][0], particletexturedata);
 
+       // rocket flare
        for (y = 0;y < 32;y++)
        {
                dy = y - 16;
@@ -339,13 +346,13 @@ void R_DrawParticles (void)
                VectorCopy(r->org, org);
                if (r->orientation == PARTICLE_BILLBOARD)
                {
-                       VectorScale(vright, r->scale, right);
-                       VectorScale(vup, r->scale, up);
+                       VectorScale(vright, r->scalex, right);
+                       VectorScale(vup, r->scaley, up);
                }
                else if (r->orientation == PARTICLE_UPRIGHT_FACING)
                {
-                       VectorScale(right2, r->scale, right);
-                       VectorScale(up2, r->scale, up);
+                       VectorScale(right2, r->scalex, right);
+                       VectorScale(up2, r->scaley, up);
                }
                else if (r->orientation == PARTICLE_ORIENTED_DOUBLESIDED)
                {
@@ -357,8 +364,8 @@ void R_DrawParticles (void)
                        }
                        else
                                VectorVectors(r->dir, right, up);
-                       VectorScale(right, r->scale, right);
-                       VectorScale(up, r->scale, up);
+                       VectorScale(right, r->scalex, right);
+                       VectorScale(up, r->scaley, up);
                }
                else
                        Host_Error("R_DrawParticles: unknown particle orientation %i\n", r->orientation);
@@ -378,29 +385,6 @@ void R_DrawParticles (void)
                tex = &particletexture[r->tex][0];
                texfog = &particletexture[r->tex][1];
 
-               fog = 0;
-               if (fogenabled)
-               {
-                       VectorSubtract(org, r_origin, diff);
-                       fog = exp(fogdensity/DotProduct(diff,diff));
-                       if (fog >= 0.01f)
-                       {
-                               if (fog > 1)
-                                       fog = 1;
-                               m.cr *= 1 - fog;
-                               m.cg *= 1 - fog;
-                               m.cb *= 1 - fog;
-                               if (tex->s1 == texfog->s1 && tex->t1 == texfog->t1)
-                               {
-                                       m.cr += fogcolor[0] * fog;
-                                       m.cg += fogcolor[1] * fog;
-                                       m.cb += fogcolor[2] * fog;
-                               }
-                       }
-                       else
-                               fog = 0;
-               }
-
                tv[0][0] = org[0] - right[0] - up[0];
                tv[0][1] = org[1] - right[1] - up[1];
                tv[0][2] = org[2] - right[2] - up[2];
@@ -422,27 +406,70 @@ void R_DrawParticles (void)
                tv[3][3] = tex->s2;
                tv[3][4] = tex->t1;
 
-               R_Mesh_Draw(&m);
-
-               if (fog && (tex->s1 != texfog->s1 || tex->t1 != texfog->t1))
+               fog = 0;
+               if (fogenabled)
                {
-                       m.blendfunc2 = GL_ONE;
-                       m.cr = fogcolor[0];
-                       m.cg = fogcolor[1];
-                       m.cb = fogcolor[2];
-                       m.ca = r->color[3] * fog;
-
-                       tv[0][3] = texfog->s1;
-                       tv[0][4] = texfog->t1;
-                       tv[1][3] = texfog->s1;
-                       tv[1][4] = texfog->t2;
-                       tv[2][3] = texfog->s2;
-                       tv[2][4] = texfog->t2;
-                       tv[3][3] = texfog->s2;
-                       tv[3][4] = texfog->t1;
-
-                       R_Mesh_Draw(&m);
-                       m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
+                       VectorSubtract(org, r_origin, diff);
+                       fog = exp(fogdensity/DotProduct(diff,diff));
+                       if (fog >= 0.01f)
+                       {
+                               if (fog >= 0.99f)
+                               {
+                                       // fully fogged, just use the fog texture and render as alpha
+                                       m.cr = fogcolor[0];
+                                       m.cg = fogcolor[1];
+                                       m.cb = fogcolor[2];
+                                       m.ca = r->color[3];
+                                       tv[0][3] = texfog->s1;
+                                       tv[0][4] = texfog->t1;
+                                       tv[1][3] = texfog->s1;
+                                       tv[1][4] = texfog->t2;
+                                       tv[2][3] = texfog->s2;
+                                       tv[2][4] = texfog->t2;
+                                       tv[3][3] = texfog->s2;
+                                       tv[3][4] = texfog->t1;
+                                       R_Mesh_Draw(&m);
+                               }
+                               else
+                               {
+                                       // partially fogged, darken the first pass
+                                       m.cr *= 1 - fog;
+                                       m.cg *= 1 - fog;
+                                       m.cb *= 1 - fog;
+                                       if (tex->s1 == texfog->s1 && tex->t1 == texfog->t1)
+                                       {
+                                               // fog texture is the same as the base, just change the color
+                                               m.cr += fogcolor[0] * fog;
+                                               m.cg += fogcolor[1] * fog;
+                                               m.cb += fogcolor[2] * fog;
+                                               R_Mesh_Draw(&m);
+                                       }
+                                       else
+                                       {
+                                               // render the first pass (alpha), then do additive fog
+                                               R_Mesh_Draw(&m);
+                                               m.blendfunc2 = GL_ONE;
+                                               m.cr = fogcolor[0];
+                                               m.cg = fogcolor[1];
+                                               m.cb = fogcolor[2];
+                                               m.ca = r->color[3] * fog;
+                                               tv[0][3] = texfog->s1;
+                                               tv[0][4] = texfog->t1;
+                                               tv[1][3] = texfog->s1;
+                                               tv[1][4] = texfog->t2;
+                                               tv[2][3] = texfog->s2;
+                                               tv[2][4] = texfog->t2;
+                                               tv[3][3] = texfog->s2;
+                                               tv[3][4] = texfog->t1;
+                                               R_Mesh_Draw(&m);
+                                               m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
+                                       }
+                               }
+                       }
+                       else
+                               R_Mesh_Draw(&m);
                }
+               else
+                       R_Mesh_Draw(&m);
        }
 }
index 0053ca0..6c5d6f2 100644 (file)
--- a/render.h
+++ b/render.h
@@ -217,3 +217,7 @@ particletexture_t;
 #define MAX_PARTICLETEXTURES 64
 // [0] is normal, [1] is fog, they may be the same
 extern particletexture_t particletexture[MAX_PARTICLETEXTURES][2];
+
+void R_TimeReport(char *name);
+void R_TimeReport_Start(void);
+void R_TimeReport_End(void);