]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_particles.c
update crosshair slider
[xonotic/darkplaces.git] / cl_particles.c
index ee2b0ad5906041a4297b6db52c62460da2614afe..67ee07844c7aca41773e4e99c6b9f98db3441c0f 100644 (file)
@@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 // must match ptype_t values
 particletype_t particletype[pt_total] =
 {
-       {0, 0, false}, // pt_dead
+       {PBLEND_INVALID, PARTICLE_INVALID, false}, //pt_dead (should never happen)
        {PBLEND_ALPHA, PARTICLE_BILLBOARD, false}, //pt_alphastatic
        {PBLEND_ADD, PARTICLE_BILLBOARD, false}, //pt_static
        {PBLEND_ADD, PARTICLE_SPARK, false}, //pt_spark
@@ -196,8 +196,9 @@ cvar_t cl_particles_smoke_alpha = {CVAR_SAVE, "cl_particles_smoke_alpha", "0.5",
 cvar_t cl_particles_smoke_alphafade = {CVAR_SAVE, "cl_particles_smoke_alphafade", "0.55", "brightness fade per second"};
 cvar_t cl_particles_sparks = {CVAR_SAVE, "cl_particles_sparks", "1", "enables sparks (used by multiple effects)"};
 cvar_t cl_particles_bubbles = {CVAR_SAVE, "cl_particles_bubbles", "1", "enables bubbles (used by multiple effects)"};
-cvar_t cl_particles_novis = {CVAR_SAVE, "cl_particles_novis", "0", "turn off PVS culling of particles"};
+cvar_t cl_particles_visculling = {CVAR_SAVE, "cl_particles_visculling", "0", "perform a costly check if each particle is visible before drawing"};
 cvar_t cl_decals = {CVAR_SAVE, "cl_decals", "1", "enables decals (bullet holes, blood, etc)"};
+cvar_t cl_decals_visculling = {CVAR_SAVE, "cl_decals_visculling", "1", "perform a very cheap check if each decal is visible before drawing"};
 cvar_t cl_decals_time = {CVAR_SAVE, "cl_decals_time", "20", "how long before decals start to fade away"};
 cvar_t cl_decals_fadetime = {CVAR_SAVE, "cl_decals_fadetime", "1", "how long decals take to fade away"};
 
@@ -467,8 +468,9 @@ void CL_Particles_Init (void)
        Cvar_RegisterVariable (&cl_particles_smoke_alphafade);
        Cvar_RegisterVariable (&cl_particles_sparks);
        Cvar_RegisterVariable (&cl_particles_bubbles);
-       Cvar_RegisterVariable (&cl_particles_novis);
+       Cvar_RegisterVariable (&cl_particles_visculling);
        Cvar_RegisterVariable (&cl_decals);
+       Cvar_RegisterVariable (&cl_decals_visculling);
        Cvar_RegisterVariable (&cl_decals_time);
        Cvar_RegisterVariable (&cl_decals_fadetime);
 }
@@ -605,6 +607,7 @@ void CL_SpawnDecalParticleForSurface(int hitent, const vec3_t org, const vec3_t
        decal->color[1] = ((((color1 >>  8) & 0xFF) * l1 + ((color2 >>  8) & 0xFF) * l2) >> 8) & 0xFF;
        decal->color[2] = ((((color1 >>  0) & 0xFF) * l1 + ((color2 >>  0) & 0xFF) * l2) >> 8) & 0xFF;
        decal->owner = hitent;
+       decal->clusterindex = -1000; // no vis culling unless we're sure
        if (hitent)
        {
                // these relative things are only used to regenerate p->org and p->vel if decal->owner is not world (0)
@@ -612,6 +615,15 @@ void CL_SpawnDecalParticleForSurface(int hitent, const vec3_t org, const vec3_t
                Matrix4x4_Transform(&cl.entities[decal->owner].render.inversematrix, org, decal->relativeorigin);
                Matrix4x4_Transform3x3(&cl.entities[decal->owner].render.inversematrix, normal, decal->relativenormal);
        }
+       else
+       {
+               if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.PointInLeaf)
+               {
+                       mleaf_t *leaf = r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, decal->org);
+                       if(leaf)
+                               decal->clusterindex = leaf->clusterindex;
+               }
+       }
 }
 
 void CL_SpawnDecalParticleForPoint(const vec3_t org, float maxdist, float size, float alpha, int texnum, int color1, int color2)
@@ -969,7 +981,8 @@ void CL_ParticleEffect_Fallback(int effectnameindex, float count, const vec3_t o
                        {
                                matrix4x4_t tempmatrix;
                                Matrix4x4_CreateFromQuakeEntity(&tempmatrix, originmaxs[0], originmaxs[1], originmaxs[2], 0, 0, 0, light[3]);
-                               R_RTLight_Update(&r_refdef.scene.lights[r_refdef.scene.numlights++], false, &tempmatrix, light, -1, NULL, true, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+                               R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &tempmatrix, light, -1, NULL, true, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+                               r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights++];
                        }
                }
 
@@ -1217,7 +1230,8 @@ void CL_ParticleTrail(int effectnameindex, float pcount, const vec3_t originmins
                                                // glowing entity
                                                // called by CL_LinkNetworkEntity
                                                Matrix4x4_Scale(&tempmatrix, info->lightradiusstart, 1);
-                                               R_RTLight_Update(&r_refdef.scene.lights[r_refdef.scene.numlights++], false, &tempmatrix, info->lightcolor, -1, info->lightcubemapnum > 0 ? va("cubemaps/%i", info->lightcubemapnum) : NULL, info->lightshadow, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+                                               R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &tempmatrix, info->lightcolor, -1, info->lightcubemapnum > 0 ? va("cubemaps/%i", info->lightcubemapnum) : NULL, info->lightshadow, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+                                               r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights++];
                                        }
                                }
 
@@ -1753,7 +1767,7 @@ static void R_InitParticleTexture (void)
        // we invert it again during the blendfunc to make it work...
 
 #ifndef DUMPPARTICLEFONT
-       particlefonttexture = loadtextureimage(particletexturepool, "particles/particlefont.tga", false, TEXF_ALPHA | TEXF_PRECACHE, true);
+       particlefonttexture = loadtextureimage(particletexturepool, "particles/particlefont.tga", false, TEXF_ALPHA | TEXF_PRECACHE | TEXF_FORCELINEAR, true);
        if (!particlefonttexture)
 #endif
        {
@@ -1880,7 +1894,7 @@ static void R_InitParticleTexture (void)
                Image_WriteTGABGRA ("particles/particlefont.tga", PARTICLEFONTSIZE, PARTICLEFONTSIZE, particletexturedata);
 #endif
 
-               particlefonttexture = R_LoadTexture2D(particletexturepool, "particlefont", PARTICLEFONTSIZE, PARTICLEFONTSIZE, particletexturedata, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
+               particlefonttexture = R_LoadTexture2D(particletexturepool, "particlefont", PARTICLEFONTSIZE, PARTICLEFONTSIZE, particletexturedata, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_PRECACHE | TEXF_FORCELINEAR, NULL);
 
                Mem_Free(particletexturedata);
        }
@@ -1896,7 +1910,7 @@ static void R_InitParticleTexture (void)
        }
 
 #ifndef DUMPPARTICLEFONT
-       particletexture[tex_beam].texture = loadtextureimage(particletexturepool, "particles/nexbeam.tga", false, TEXF_ALPHA | TEXF_PRECACHE, true);
+       particletexture[tex_beam].texture = loadtextureimage(particletexturepool, "particles/nexbeam.tga", false, TEXF_ALPHA | TEXF_PRECACHE | TEXF_FORCELINEAR, true);
        if (!particletexture[tex_beam].texture)
 #endif
        {
@@ -1919,7 +1933,7 @@ static void R_InitParticleTexture (void)
 #ifdef DUMPPARTICLEFONT
                Image_WriteTGABGRA ("particles/nexbeam.tga", 64, 64, &data2[0][0][0]);
 #endif
-               particletexture[tex_beam].texture = R_LoadTexture2D(particletexturepool, "nexbeam", 16, 64, &data2[0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE, NULL);
+               particletexture[tex_beam].texture = R_LoadTexture2D(particletexturepool, "nexbeam", 16, 64, &data2[0][0][0], TEXTYPE_BGRA, TEXF_ALPHA | TEXF_PRECACHE | TEXF_FORCELINEAR, NULL);
        }
        particletexture[tex_beam].s1 = 0;
        particletexture[tex_beam].t1 = 0;
@@ -2088,19 +2102,11 @@ void R_DrawDecals (void)
                                goto killdecal;
                }
 
+               if(cl_decals_visculling.integer && decal->clusterindex > -1000 && !CHECKPVSBIT(r_refdef.viewcache.world_pvsbits, decal->clusterindex))
+                       continue;
+
                if (DotProduct(r_refdef.view.origin, decal->normal) > DotProduct(decal->org, decal->normal) && VectorDistance2(decal->org, r_refdef.view.origin) < drawdist2 * (decal->size * decal->size))
-               {
-                       if(!cl_particles_novis.integer)
-                               if (!r_refdef.viewcache.world_novis)
-                                       if(r_refdef.scene.worldmodel->brush.PointInLeaf)
-                                       {
-                                               mleaf_t *leaf = r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, decal->org);
-                                               if(leaf)
-                                                       if(!CHECKPVSBIT(r_refdef.viewcache.world_pvsbits, leaf->clusterindex))
-                                                               continue;
-                                       }
                        R_MeshQueue_AddTransparent(decal->org, R_DrawDecal_TransparentCallback, NULL, i, NULL);
-               }
                continue;
 killdecal:
                decal->typeindex = 0;
@@ -2164,6 +2170,7 @@ void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtligh
                c4f[3] = p->alpha * colormultiplier[3];
                switch (blendmode)
                {
+               case PBLEND_INVALID:
                case PBLEND_INVMOD:
                case PBLEND_ADD:
                        // additive and modulate can just fade out in fog (this is correct)
@@ -2204,6 +2211,7 @@ void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtligh
                tex = &particletexture[p->texnum];
                switch(p->orientation)
                {
+               case PARTICLE_INVALID:
                case PARTICLE_BILLBOARD:
                        VectorScale(r_refdef.view.left, -size * p->stretch, right);
                        VectorScale(r_refdef.view.up, size, up);
@@ -2274,7 +2282,7 @@ void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtligh
        }
 
        // now render batches of particles based on blendmode and texture
-       blendmode = -1;
+       blendmode = PBLEND_INVALID;
        texture = NULL;
        GL_LockArrays(0, numsurfaces*4);
        batchstart = 0;
@@ -2291,6 +2299,7 @@ void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtligh
                        case PBLEND_ALPHA:
                                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                                break;
+                       case PBLEND_INVALID:
                        case PBLEND_ADD:
                                GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
                                break;
@@ -2491,9 +2500,9 @@ void R_DrawParticles (void)
                        R_MeshQueue_AddTransparent(p->org, R_DrawParticle_TransparentCallback, NULL, i, NULL);
                        break;
                default:
-                       if(!cl_particles_novis.integer)
+                       if(cl_particles_visculling.integer)
                                if (!r_refdef.viewcache.world_novis)
-                                       if(r_refdef.scene.worldmodel->brush.PointInLeaf)
+                                       if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.PointInLeaf)
                                        {
                                                mleaf_t *leaf = r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, p->org);
                                                if(leaf)