]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_particles.c
added glFlush call when done feeding geometry, to get a very nice speed boost, and...
[xonotic/darkplaces.git] / r_particles.c
index 1645810889a930268db4072f8d5ca42bf1de564c..cb5795a8861b67b3981035eb368e95121db4d931 100644 (file)
@@ -22,15 +22,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 static rtexturepool_t *particletexturepool;
 
-// these are used by the decal system so they can't be static
-rtexture_t *particlefonttexture;
+static rtexture_t *particlefonttexture;
 // [0] is normal, [1] is fog, they may be the same
-particletexture_t particletexture[MAX_PARTICLETEXTURES][2];
+static particletexture_t particletexture[MAX_PARTICLETEXTURES][2];
 
 static cvar_t r_drawparticles = {0, "r_drawparticles", "1"};
 static cvar_t r_particles_lighting = {0, "r_particles_lighting", "1"};
 
-static byte shadebubble(float dx, float dy, vec3_t light)
+static qbyte shadebubble(float dx, float dy, vec3_t light)
 {
        float   dz, f, dot;
        vec3_t  normal;
@@ -57,13 +56,13 @@ static byte shadebubble(float dx, float dy, vec3_t light)
                f *= 128;
                f += 16; // just to give it a haze so you can see the outline
                f = bound(0, f, 255);
-               return (byte) f;
+               return (qbyte) f;
        }
        else
                return 0;
 }
 
-static void setuptex(int cltexnum, int fog, int rtexnum, byte *data, byte *particletexturedata)
+static void setuptex(int cltexnum, int fog, int rtexnum, qbyte *data, qbyte *particletexturedata)
 {
        int basex, basey, y;
        basex = ((rtexnum >> 0) & 7) * 32;
@@ -80,9 +79,9 @@ static void R_InitParticleTexture (void)
 {
        int             x,y,d,i,m;
        float   dx, dy, radius, f, f2;
-       byte    data[32][32][4], noise1[64][64], noise2[64][64];
+       qbyte   data[32][32][4], noise1[64][64], noise2[64][64];
        vec3_t  light;
-       byte    particletexturedata[256*256*4];
+       qbyte   particletexturedata[256*256*4];
 
        memset(particletexturedata, 255, sizeof(particletexturedata));
 
@@ -100,7 +99,7 @@ static void R_InitParticleTexture (void)
                                dy = y - 16;
                                for (x = 0;x < 32;x++)
                                {
-                                       d = (noise1[y][x] - 128) * 2 + 64; // was + 128
+                                       d = (noise1[y][x] - 128) * 2 + 128;
                                        d = bound(0, d, 255);
                                        data[y][x][0] = data[y][x][1] = data[y][x][2] = d;
                                        dx = x - 16;
@@ -108,7 +107,7 @@ static void R_InitParticleTexture (void)
                                        if (d > 0)
                                                d = (d * (256 - (int) (dx*dx+dy*dy))) >> 8;
                                        d = bound(0, d, 255);
-                                       data[y][x][3] = (byte) d;
+                                       data[y][x][3] = (qbyte) d;
                                        if (m < d)
                                                m = d;
                                }
@@ -123,64 +122,6 @@ 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];
-               fractalnoise(&noise1[0][0], 64, 8);
-               for (y = 0;y < 32;y++)
-                       for (x = 0;x < 32;x++)
-                               p[y][x] = (noise1[y][x] / 8.0f) - 64.0f;
-               for (m = 0;m < 32;m++)
-               {
-                       int j;
-                       float fx, fy, f;
-                       fx = lhrandom(14, 18);
-                       fy = lhrandom(14, 18);
-                       do
-                       {
-                               dx = lhrandom(-1, 1);
-                               dy = lhrandom(-1, 1);
-                               f = (dx * dx + dy * dy);
-                       }
-                       while(f < 0.125f || f > 1.0f);
-                       f = (m + 1) / 40.0f; //lhrandom(0.0f, 1.0);
-                       dx *= 1.0f / 32.0f;
-                       dy *= 1.0f / 32.0f;
-                       for (j = 0;f > 0 && j < (32 * 14);j++)
-                       {
-                               y = fy;
-                               x = fx;
-                               fx += dx;
-                               fy += dy;
-                               if (x < 1 || y < 1 || x >= 31 || y >= 31)
-                                       break;
-                               p[y - 1][x - 1] += f * 0.125f;
-                               p[y - 1][x    ] += f * 0.25f;
-                               p[y - 1][x + 1] += f * 0.125f;
-                               p[y    ][x - 1] += f * 0.25f;
-                               p[y    ][x    ] += f;
-                               p[y    ][x + 1] += f * 0.25f;
-                               p[y + 1][x - 1] += f * 0.125f;
-                               p[y + 1][x    ] += f * 0.25f;
-                               p[y + 1][x + 1] += f * 0.125f;
-//                             f -= (0.5f / (32 * 16));
-                       }
-               }
-               for (y = 0;y < 32;y++)
-               {
-                       for (x = 0;x < 32;x++)
-                       {
-                               m = p[y][x];
-                               data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
-                               data[y][x][3] = (byte) bound(0, m, 255);
-                       }
-               }
-
-               setuptex(i + 8, 0, i + 16, &data[0][0][0], particletexturedata);
-               setuptex(i + 8, 1, i + 16, &data[0][0][0], particletexturedata);
-       }
-
        // rain splash
        for (i = 0;i < 16;i++)
        {
@@ -198,8 +139,8 @@ static void R_InitParticleTexture (void)
                                data[y][x][3] = (int) f;
                        }
                }
-               setuptex(i + 16, 0, i + 24, &data[0][0][0], particletexturedata);
-               setuptex(i + 16, 1, i + 24, &data[0][0][0], particletexturedata);
+               setuptex(i + 8, 0, i + 16, &data[0][0][0], particletexturedata);
+               setuptex(i + 8, 1, i + 16, &data[0][0][0], particletexturedata);
        }
 
        // normal particle
@@ -212,11 +153,11 @@ static void R_InitParticleTexture (void)
                        dx = x - 16;
                        d = (256 - (dx*dx+dy*dy));
                        d = bound(0, d, 255);
-                       data[y][x][3] = (byte) d;
+                       data[y][x][3] = (qbyte) d;
                }
        }
-       setuptex(32, 0, 40, &data[0][0][0], particletexturedata);
-       setuptex(32, 1, 40, &data[0][0][0], particletexturedata);
+       setuptex(24, 0, 32, &data[0][0][0], particletexturedata);
+       setuptex(24, 1, 32, &data[0][0][0], particletexturedata);
 
        // rain
        light[0] = 1;light[1] = 1;light[2] = 1;
@@ -229,8 +170,8 @@ static void R_InitParticleTexture (void)
                        data[y][x][3] = shadebubble((x - 16) * (1.0 / 8.0), y < 24 ? (y - 24) * (1.0 / 24.0) : (y - 24) * (1.0 / 8.0), light);
                }
        }
-       setuptex(33, 0, 41, &data[0][0][0], particletexturedata);
-       setuptex(33, 1, 41, &data[0][0][0], particletexturedata);
+       setuptex(25, 0, 33, &data[0][0][0], particletexturedata);
+       setuptex(25, 1, 33, &data[0][0][0], particletexturedata);
 
        // bubble
        light[0] = 1;light[1] = 1;light[2] = 1;
@@ -243,8 +184,8 @@ static void R_InitParticleTexture (void)
                        data[y][x][3] = shadebubble((x - 16) * (1.0 / 16.0), (y - 16) * (1.0 / 16.0), light);
                }
        }
-       setuptex(34, 0, 42, &data[0][0][0], particletexturedata);
-       setuptex(34, 1, 42, &data[0][0][0], particletexturedata);
+       setuptex(26, 0, 34, &data[0][0][0], particletexturedata);
+       setuptex(26, 1, 34, &data[0][0][0], particletexturedata);
 
        // rocket flare
        for (y = 0;y < 32;y++)
@@ -260,11 +201,11 @@ static void R_InitParticleTexture (void)
                        data[y][x][3] = bound(0, d * 1.0f, 255);
                }
        }
-       setuptex(35, 0, 43, &data[0][0][0], particletexturedata);
+       setuptex(27, 0, 35, &data[0][0][0], particletexturedata);
        for (y = 0;y < 32;y++)
                for (x = 0;x < 32;x++)
                        data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
-       setuptex(35, 1, 44, &data[0][0][0], particletexturedata);
+       setuptex(28, 1, 36, &data[0][0][0], particletexturedata);
 
        particlefonttexture = R_LoadTexture (particletexturepool, "particlefont", 256, 256, particletexturedata, TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
 }
@@ -291,7 +232,7 @@ void R_Particles_Init (void)
        R_RegisterModule("R_Particles", r_part_start, r_part_shutdown, r_part_newmap);
 }
 
-//int partindexarray[6] = {0, 1, 2, 0, 2, 3};
+int partindexarray[6] = {0, 1, 2, 0, 2, 3};
 
 void R_DrawParticles (void)
 {
@@ -325,14 +266,14 @@ void R_DrawParticles (void)
        m.transparent = true;
        m.blendfunc1 = GL_SRC_ALPHA;
        m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
-       //m.numtriangles = 2;
-       //m.index = partindexarray;
-       //m.numverts = 4;
+       m.numtriangles = 2;
+       m.index = partindexarray;
+       m.numverts = 4;
        m.vertex = &tvxyz[0][0];
-       //m.vertexstep = sizeof(float[4]);
+       m.vertexstep = sizeof(float[4]);
        m.tex[0] = R_GetTexture(particlefonttexture);
        m.texcoords[0] = &tvst[0][0];
-       //m.texcoordstep[0] = sizeof(float[2]);
+       m.texcoordstep[0] = sizeof(float[2]);
 
        for (i = 0, r = r_refdef.particles;i < r_refdef.numparticles;i++, r++)
        {
@@ -407,55 +348,50 @@ void R_DrawParticles (void)
                tvst[3][0] = tex->s2;
                tvst[3][1] = tex->t1;
 
-               fog = 0;
-               if (fogenabled)
+               if (r->additive)
                {
-                       texfog = &particletexture[r->tex][1];
-                       VectorSubtract(org, r_origin, fogvec);
-                       fog = exp(fogdensity/DotProduct(fogvec,fogvec));
-                       if (fog >= (1.0f / 64.0f))
+                       m.blendfunc2 = GL_ONE;
+                       fog = 0;
+                       if (fogenabled)
                        {
-                               if (fog >= (1.0f - (1.0f / 64.0f)))
+                               texfog = &particletexture[r->tex][1];
+                               VectorSubtract(org, r_origin, fogvec);
+                               ifog = 1 - exp(fogdensity/DotProduct(fogvec,fogvec));
+                               if (ifog < (1.0f - (1.0f / 64.0f)))
                                {
-                                       // 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];
-                                       tvst[0][0] = texfog->s1;
-                                       tvst[0][1] = texfog->t1;
-                                       tvst[1][0] = texfog->s1;
-                                       tvst[1][1] = texfog->t2;
-                                       tvst[2][0] = texfog->s2;
-                                       tvst[2][1] = texfog->t2;
-                                       tvst[3][0] = texfog->s2;
-                                       tvst[3][1] = texfog->t1;
-                                       R_Mesh_DrawDecal(&m);
+                                       if (ifog >= (1.0f / 64.0f))
+                                       {
+                                               // partially fogged, darken it
+                                               m.cr *= ifog;
+                                               m.cg *= ifog;
+                                               m.cb *= ifog;
+                                               R_Mesh_Draw(&m);
+                                       }
                                }
                                else
+                                       R_Mesh_Draw(&m);
+                       }
+                       else
+                               R_Mesh_Draw(&m);
+               }
+               else
+               {
+                       m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
+                       fog = 0;
+                       if (fogenabled)
+                       {
+                               texfog = &particletexture[r->tex][1];
+                               VectorSubtract(org, r_origin, fogvec);
+                               fog = exp(fogdensity/DotProduct(fogvec,fogvec));
+                               if (fog >= (1.0f / 64.0f))
                                {
-                                       // partially fogged, darken the first pass
-                                       ifog = 1 - fog;
-                                       m.cr *= ifog;
-                                       m.cg *= ifog;
-                                       m.cb *= ifog;
-                                       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_DrawDecal(&m);
-                                       }
-                                       else
+                                       if (fog >= (1.0f - (1.0f / 64.0f)))
                                        {
-                                               // render the first pass (alpha), then do additive fog
-                                               R_Mesh_DrawDecal(&m);
-                                               m.blendfunc2 = GL_ONE;
+                                               // 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] * fog;
+                                               m.ca = r->color[3];
                                                tvst[0][0] = texfog->s1;
                                                tvst[0][1] = texfog->t1;
                                                tvst[1][0] = texfog->s1;
@@ -464,15 +400,50 @@ void R_DrawParticles (void)
                                                tvst[2][1] = texfog->t2;
                                                tvst[3][0] = texfog->s2;
                                                tvst[3][1] = texfog->t1;
-                                               R_Mesh_DrawDecal(&m);
-                                               m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
+                                               R_Mesh_Draw(&m);
+                                       }
+                                       else
+                                       {
+                                               // partially fogged, darken the first pass
+                                               ifog = 1 - fog;
+                                               m.cr *= ifog;
+                                               m.cg *= ifog;
+                                               m.cb *= ifog;
+                                               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;
+                                                       tvst[0][0] = texfog->s1;
+                                                       tvst[0][1] = texfog->t1;
+                                                       tvst[1][0] = texfog->s1;
+                                                       tvst[1][1] = texfog->t2;
+                                                       tvst[2][0] = texfog->s2;
+                                                       tvst[2][1] = texfog->t2;
+                                                       tvst[3][0] = texfog->s2;
+                                                       tvst[3][1] = texfog->t1;
+                                                       R_Mesh_Draw(&m);
+                                               }
                                        }
                                }
+                               else
+                                       R_Mesh_Draw(&m);
                        }
                        else
-                               R_Mesh_DrawDecal(&m);
+                               R_Mesh_Draw(&m);
                }
-               else
-                       R_Mesh_DrawDecal(&m);
        }
 }