X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=cl_particles.c;h=a11671209ddaa136d9779855aaa6ac588f34acc1;hp=ebdaad0089ff2e99b72d682eede6b3d6647a8353;hb=93ee242c05da6c2b71a6eaf4e393435988ca6c5a;hpb=4e08e20e6bfbd53bb1796e8de40d261bbfd0e7c3 diff --git a/cl_particles.c b/cl_particles.c index ebdaad00..a1167120 100644 --- a/cl_particles.c +++ b/cl_particles.c @@ -192,6 +192,81 @@ static const int tex_bubble = 62; static const int tex_raindrop = 61; static const int tex_beam = 60; +particleeffectinfo_t baselineparticleeffectinfo = +{ + 0, //int effectnameindex; // which effect this belongs to + // PARTICLEEFFECT_* bits + 0, //int flags; + // blood effects may spawn very few particles, so proper fraction-overflow + // handling is very important, this variable keeps track of the fraction + 0.0, //double particleaccumulator; + // the math is: countabsolute + requestedcount * countmultiplier * quality + // absolute number of particles to spawn, often used for decals + // (unaffected by quality and requestedcount) + 0.0f, //float countabsolute; + // multiplier for the number of particles CL_ParticleEffect was told to + // spawn, most effects do not really have a count and hence use 1, so + // this is often the actual count to spawn, not merely a multiplier + 0.0f, //float countmultiplier; + // if > 0 this causes the particle to spawn in an evenly spaced line from + // originmins to originmaxs (causing them to describe a trail, not a box) + 0.0f, //float trailspacing; + // type of particle to spawn (defines some aspects of behavior) + pt_alphastatic, //ptype_t particletype; + // blending mode used on this particle type + PBLEND_ALPHA, //pblend_t blendmode; + // orientation of this particle type (BILLBOARD, SPARK, BEAM, etc) + PARTICLE_BILLBOARD, //porientation_t orientation; + // range of colors to choose from in hex RRGGBB (like HTML color tags), + // randomly interpolated at spawn + {0xFFFFFF, 0xFFFFFF}, //unsigned int color[2]; + // a random texture is chosen in this range (note the second value is one + // past the last choosable, so for example 8,16 chooses any from 8 up and + // including 15) + // if start and end of the range are the same, no randomization is done + {63, 63 /* tex_particle */}, //int tex[2]; + // range of size values randomly chosen when spawning, plus size increase over time + {1, 1, 0.0f}, //float size[3]; + // range of alpha values randomly chosen when spawning, plus alpha fade + {0.0f, 256.0f, 256.0f}, //float alpha[3]; + // how long the particle should live (note it is also removed if alpha drops to 0) + {16777216.0f, 16777216.0f}, //float time[2]; + // how much gravity affects this particle (negative makes it fly up!) + 0.0f, //float gravity; + // how much bounce the particle has when it hits a surface + // if negative the particle is removed on impact + 0.0f, //float bounce; + // if in air this friction is applied + // if negative the particle accelerates + 0.0f, //float airfriction; + // if in liquid (water/slime/lava) this friction is applied + // if negative the particle accelerates + 0.0f, //float liquidfriction; + // these offsets are added to the values given to particleeffect(), and + // then an ellipsoid-shaped jitter is added as defined by these + // (they are the 3 radii) + 1.0f, //float stretchfactor; + // stretch velocity factor (used for sparks) + {0.0f, 0.0f, 0.0f}, //float originoffset[3]; + {0.0f, 0.0f, 0.0f}, //float velocityoffset[3]; + {0.0f, 0.0f, 0.0f}, //float originjitter[3]; + {0.0f, 0.0f, 0.0f}, //float velocityjitter[3]; + 0.0f, //float velocitymultiplier; + // an effect can also spawn a dlight + 0.0f, //float lightradiusstart; + 0.0f, //float lightradiusfade; + 16777216.0f, //float lighttime; + {1.0f, 1.0f, 1.0f}, //float lightcolor[3]; + true, //qboolean lightshadow; + 0, //int lightcubemapnum; + {(unsigned int)-1, (unsigned int)-1}, //unsigned int staincolor[2]; // note: 0x808080 = neutral (particle's own color), these are modding factors for the particle's original color! + {-1, -1}, //int staintex[2]; + {1.0f, 1.0f}, //float stainalpha[2]; + {2.0f, 2.0f}, //float stainsize[2]; + // other parameters + {0.0f, 360.0f, 0.0f, 0.0f}, //float rotate[4]; // min/max base angle, min/max rotation over time +}; + cvar_t cl_particles = {CVAR_SAVE, "cl_particles", "1", "enables particle effects"}; cvar_t cl_particles_quality = {CVAR_SAVE, "cl_particles_quality", "1", "multiplies number of particles"}; cvar_t cl_particles_alpha = {CVAR_SAVE, "cl_particles_alpha", "1", "multiplies opacity of particles"}; @@ -227,7 +302,7 @@ cvar_t cl_decals_bias = {CVAR_SAVE, "cl_decals_bias", "0.125", "distance to bias cvar_t cl_decals_max = {CVAR_SAVE, "cl_decals_max", "4096", "maximum number of decals allowed to exist in the world at once"}; -void CL_Particles_ParseEffectInfo(const char *textstart, const char *textend, const char *filename) +static void CL_Particles_ParseEffectInfo(const char *textstart, const char *textend, const char *filename) { int arrayindex; int argc; @@ -242,7 +317,7 @@ void CL_Particles_ParseEffectInfo(const char *textstart, const char *textend, co argv[arrayindex][0] = 0; for (;;) { - if (!COM_ParseToken_Simple(&text, true, false)) + if (!COM_ParseToken_Simple(&text, true, false, true)) return; if (!strcmp(com_token, "\n")) break; @@ -289,37 +364,9 @@ void CL_Particles_ParseEffectInfo(const char *textstart, const char *textend, co break; } info = particleeffectinfo + numparticleeffectinfo++; + // copy entire info from baseline, then fix up the nameindex + *info = baselineparticleeffectinfo; info->effectnameindex = effectnameindex; - info->particletype = pt_alphastatic; - info->blendmode = particletype[info->particletype].blendmode; - info->orientation = particletype[info->particletype].orientation; - info->tex[0] = tex_particle; - info->tex[1] = tex_particle; - info->color[0] = 0xFFFFFF; - info->color[1] = 0xFFFFFF; - info->size[0] = 1; - info->size[1] = 1; - info->alpha[0] = 0; - info->alpha[1] = 256; - info->alpha[2] = 256; - info->time[0] = 9999; - info->time[1] = 9999; - VectorSet(info->lightcolor, 1, 1, 1); - info->lightshadow = true; - info->lighttime = 9999; - info->stretchfactor = 1; - info->staincolor[0] = (unsigned int)-1; - info->staincolor[1] = (unsigned int)-1; - info->staintex[0] = -1; - info->staintex[1] = -1; - info->stainalpha[0] = 1; - info->stainalpha[1] = 1; - info->stainsize[0] = 2; - info->stainsize[1] = 2; - info->rotate[0] = 0; - info->rotate[1] = 360; - info->rotate[2] = 0; - info->rotate[3] = 0; } else if (info == NULL) { @@ -462,7 +509,7 @@ static const char *standardeffectnames[EFFECT_TOTAL] = "SVC_PARTICLE" }; -void CL_Particles_LoadEffectInfo(void) +static void CL_Particles_LoadEffectInfo(void) { int i; int filepass; @@ -602,6 +649,12 @@ particle_t *CL_NewParticle(const vec3_t sortorigin, unsigned short ptypeindex, i part->color[0] = ((((pcolor1 >> 16) & 0xFF) * l1 + ((pcolor2 >> 16) & 0xFF) * l2) >> 8) & 0xFF; part->color[1] = ((((pcolor1 >> 8) & 0xFF) * l1 + ((pcolor2 >> 8) & 0xFF) * l2) >> 8) & 0xFF; part->color[2] = ((((pcolor1 >> 0) & 0xFF) * l1 + ((pcolor2 >> 0) & 0xFF) * l2) >> 8) & 0xFF; + if (vid.sRGB3D) + { + part->color[0] = (unsigned char)floor(Image_LinearFloatFromsRGB(part->color[0]) * 255.0f + 0.5f); + part->color[1] = (unsigned char)floor(Image_LinearFloatFromsRGB(part->color[1]) * 255.0f + 0.5f); + part->color[2] = (unsigned char)floor(Image_LinearFloatFromsRGB(part->color[2]) * 255.0f + 0.5f); + } part->alpha = palpha; part->alphafade = palphafade; part->staintexnum = staintex; @@ -758,7 +811,10 @@ void CL_SpawnDecalParticleForSurface(int hitent, const vec3_t org, const vec3_t if (cl_decals_newsystem.integer) { - R_DecalSystem_SplatEntities(org, normal, color[0]*(1.0f/255.0f), color[1]*(1.0f/255.0f), color[2]*(1.0f/255.0f), alpha*(1.0f/255.0f), particletexture[texnum].s1, particletexture[texnum].t1, particletexture[texnum].s2, particletexture[texnum].t2, size); + if (vid.sRGB3D) + R_DecalSystem_SplatEntities(org, normal, Image_LinearFloatFromsRGB(color[0]), Image_LinearFloatFromsRGB(color[1]), Image_LinearFloatFromsRGB(color[2]), alpha*(1.0f/255.0f), particletexture[texnum].s1, particletexture[texnum].t1, particletexture[texnum].s2, particletexture[texnum].t2, size); + else + R_DecalSystem_SplatEntities(org, normal, color[0]*(1.0f/255.0f), color[1]*(1.0f/255.0f), color[2]*(1.0f/255.0f), alpha*(1.0f/255.0f), particletexture[texnum].s1, particletexture[texnum].t1, particletexture[texnum].s2, particletexture[texnum].t2, size); return; } @@ -780,6 +836,12 @@ void CL_SpawnDecalParticleForSurface(int hitent, const vec3_t org, const vec3_t decal->color[0] = color[0]; decal->color[1] = color[1]; decal->color[2] = color[2]; + if (vid.sRGB3D) + { + decal->color[0] = (unsigned char)(Image_LinearFloatFromsRGB(decal->color[0]) * 256.0f); + decal->color[1] = (unsigned char)(Image_LinearFloatFromsRGB(decal->color[1]) * 256.0f); + decal->color[2] = (unsigned char)(Image_LinearFloatFromsRGB(decal->color[2]) * 256.0f); + } decal->owner = hitent; decal->clusterindex = -1000; // no vis culling unless we're sure if (hitent) @@ -829,7 +891,7 @@ void CL_SpawnDecalParticleForPoint(const vec3_t org, float maxdist, float size, static void CL_Sparks(const vec3_t originmins, const vec3_t originmaxs, const vec3_t velocitymins, const vec3_t velocitymaxs, float sparkcount); static void CL_Smoke(const vec3_t originmins, const vec3_t originmaxs, const vec3_t velocitymins, const vec3_t velocitymaxs, float smokecount); -void CL_ParticleEffect_Fallback(int effectnameindex, float count, const vec3_t originmins, const vec3_t originmaxs, const vec3_t velocitymins, const vec3_t velocitymaxs, entity_t *ent, int palettecolor, qboolean spawndlight, qboolean spawnparticles) +static void CL_ParticleEffect_Fallback(int effectnameindex, float count, const vec3_t originmins, const vec3_t originmaxs, const vec3_t velocitymins, const vec3_t velocitymaxs, entity_t *ent, int palettecolor, qboolean spawndlight, qboolean spawnparticles) { vec3_t center; matrix4x4_t tempmatrix; @@ -1355,6 +1417,7 @@ void CL_ParticleEffect_Fallback(int effectnameindex, float count, const vec3_t o void CL_ParticleTrail(int effectnameindex, float pcount, const vec3_t originmins, const vec3_t originmaxs, const vec3_t velocitymins, const vec3_t velocitymaxs, entity_t *ent, int palettecolor, qboolean spawndlight, qboolean spawnparticles, float tintmins[4], float tintmaxs[4]) { qboolean found = false; + char vabuf[1024]; if (effectnameindex < 1 || effectnameindex >= MAX_PARTICLEEFFECTNAME || !particleeffectname[effectnameindex][0]) { Con_DPrintf("Unknown effect number %i received from server\n", effectnameindex); @@ -1423,7 +1486,7 @@ void CL_ParticleTrail(int effectnameindex, float pcount, const vec3_t originmins rvec[0] = info->lightcolor[0]*avgtint[0]*avgtint[3]; rvec[1] = info->lightcolor[1]*avgtint[1]*avgtint[3]; rvec[2] = info->lightcolor[2]*avgtint[2]*avgtint[3]; - R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &tempmatrix, rvec, -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, rvec, -1, info->lightcubemapnum > 0 ? va(vabuf, sizeof(vabuf), "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];r_refdef.scene.numlights++; } } @@ -1625,11 +1688,11 @@ void CL_ParseParticleEffect (void) vec3_t org, dir; int i, count, msgcount, color; - MSG_ReadVector(org, cls.protocol); + MSG_ReadVector(&cl_message, org, cls.protocol); for (i=0 ; i<3 ; i++) - dir[i] = MSG_ReadChar () * (1.0 / 16.0); - msgcount = MSG_ReadByte (); - color = MSG_ReadByte (); + dir[i] = MSG_ReadChar(&cl_message) * (1.0 / 16.0); + msgcount = MSG_ReadByte(&cl_message); + color = MSG_ReadByte(&cl_message); if (msgcount == 255) count = 1024; @@ -1868,7 +1931,7 @@ static unsigned char shadebubble(float dx, float dy, vec3_t light) } int particlefontwidth, particlefontheight, particlefontcellwidth, particlefontcellheight, particlefontrows, particlefontcols; -void CL_Particle_PixelCoordsForTexnum(int texnum, int *basex, int *basey, int *width, int *height) +static void CL_Particle_PixelCoordsForTexnum(int texnum, int *basex, int *basey, int *width, int *height) { *basex = (texnum % particlefontcols) * particlefontcellwidth; *basey = ((texnum / particlefontcols) % particlefontrows) * particlefontcellheight; @@ -1886,7 +1949,7 @@ static void setuptex(int texnum, unsigned char *data, unsigned char *particletex memcpy(particletexturedata + ((basey + y) * PARTICLEFONTSIZE + basex) * 4, data + y * PARTICLETEXTURESIZE * 4, PARTICLETEXTURESIZE * 4); } -void particletextureblotch(unsigned char *data, float radius, float red, float green, float blue, float alpha) +static void particletextureblotch(unsigned char *data, float radius, float red, float green, float blue, float alpha) { int x, y; float cx, cy, dx, dy, f, iradius; @@ -1915,7 +1978,8 @@ void particletextureblotch(unsigned char *data, float radius, float red, float g } } -void particletextureclamp(unsigned char *data, int minr, int ming, int minb, int maxr, int maxg, int maxb) +#if 0 +static void particletextureclamp(unsigned char *data, int minr, int ming, int minb, int maxr, int maxg, int maxb) { int i; for (i = 0;i < PARTICLETEXTURESIZE*PARTICLETEXTURESIZE;i++, data += 4) @@ -1925,8 +1989,9 @@ void particletextureclamp(unsigned char *data, int minr, int ming, int minb, int data[2] = bound(minr, data[2], maxr); } } +#endif -void particletextureinvert(unsigned char *data) +static void particletextureinvert(unsigned char *data) { int i; for (i = 0;i < PARTICLETEXTURESIZE*PARTICLETEXTURESIZE;i++, data += 4) @@ -2197,7 +2262,7 @@ static void R_InitParticleTexture (void) bufptr = buf; for(;;) { - if(!COM_ParseToken_Simple(&bufptr, true, false)) + if(!COM_ParseToken_Simple(&bufptr, true, false, true)) break; if(!strcmp(com_token, "\n")) continue; // empty line @@ -2209,22 +2274,22 @@ static void R_InitParticleTexture (void) s2 = 1; t2 = 1; - if (COM_ParseToken_Simple(&bufptr, true, false) && strcmp(com_token, "\n")) + if (COM_ParseToken_Simple(&bufptr, true, false, true) && strcmp(com_token, "\n")) { strlcpy(texturename, com_token, sizeof(texturename)); s1 = atof(com_token); - if (COM_ParseToken_Simple(&bufptr, true, false) && strcmp(com_token, "\n")) + if (COM_ParseToken_Simple(&bufptr, true, false, true) && strcmp(com_token, "\n")) { texturename[0] = 0; t1 = atof(com_token); - if (COM_ParseToken_Simple(&bufptr, true, false) && strcmp(com_token, "\n")) + if (COM_ParseToken_Simple(&bufptr, true, false, true) && strcmp(com_token, "\n")) { s2 = atof(com_token); - if (COM_ParseToken_Simple(&bufptr, true, false) && strcmp(com_token, "\n")) + if (COM_ParseToken_Simple(&bufptr, true, false, true) && strcmp(com_token, "\n")) { t2 = atof(com_token); strlcpy(texturename, "particles/particlefont.tga", sizeof(texturename)); - if (COM_ParseToken_Simple(&bufptr, true, false) && strcmp(com_token, "\n")) + if (COM_ParseToken_Simple(&bufptr, true, false, true) && strcmp(com_token, "\n")) strlcpy(texturename, com_token, sizeof(texturename)); } } @@ -2242,7 +2307,7 @@ static void R_InitParticleTexture (void) Con_Printf("particles/particlefont.txt: texnum %i outside valid range (0 to %i)\n", i, MAX_PARTICLETEXTURES); continue; } - sf = R_SkinFrame_LoadExternal(texturename, TEXF_ALPHA | TEXF_FORCELINEAR | TEXF_RGBMULTIPLYBYALPHA, true); + sf = R_SkinFrame_LoadExternal(texturename, TEXF_ALPHA | TEXF_FORCELINEAR | TEXF_RGBMULTIPLYBYALPHA, true); // note: this loads as sRGB if sRGB is active! if(!sf) { // R_SkinFrame_LoadExternal already complained @@ -2306,7 +2371,7 @@ void R_Particles_Init (void) R_RegisterModule("R_Particles", r_part_start, r_part_shutdown, r_part_newmap, NULL, NULL); } -void R_DrawDecal_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) +static void R_DrawDecal_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) { int surfacelistindex; const decal_t *d; @@ -2374,7 +2439,7 @@ void R_DrawDecal_TransparentCallback(const entity_render_t *ent, const rtlight_t // now render the decals all at once // (this assumes they all use one particle font texture!) GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); - R_SetupShader_Generic(particletexture[63].texture, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(particletexture[63].texture, NULL, GL_MODULATE, 1, false, false, true); R_Mesh_PrepareVertices_Generic_Arrays(numsurfaces * 4, particle_vertex3f, particle_color4f, particle_texcoord2f); R_Mesh_Draw(0, numsurfaces * 4, 0, numsurfaces * 2, NULL, NULL, 0, particle_elements, NULL, 0); } @@ -2433,7 +2498,7 @@ void R_DrawDecals (void) continue; if (DotProduct(r_refdef.view.origin, decal->normal) > DotProduct(decal->org, decal->normal) && VectorDistance2(decal->org, r_refdef.view.origin) < drawdist2 * (decal->size * decal->size)) - R_MeshQueue_AddTransparent(decal->org, R_DrawDecal_TransparentCallback, NULL, i, NULL); + R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, decal->org, R_DrawDecal_TransparentCallback, NULL, i, NULL); continue; killdecal: decal->typeindex = 0; @@ -2457,7 +2522,7 @@ killdecal: r_refdef.stats.totaldecals = cl.num_decals; } -void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) +static void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist) { int surfacelistindex; int batchstart, batchcount; @@ -2684,7 +2749,7 @@ void R_DrawParticle_TransparentCallback(const entity_render_t *ent, const rtligh if (texture != particletexture[p->texnum].texture) { texture = particletexture[p->texnum].texture; - R_SetupShader_Generic(texture, NULL, GL_MODULATE, 1); + R_SetupShader_Generic(texture, NULL, GL_MODULATE, 1, false, false, false); } if (p->blendmode == PBLEND_INVMOD) @@ -2912,7 +2977,7 @@ void R_DrawParticles (void) { case pt_beam: // beams have no culling - R_MeshQueue_AddTransparent(p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL); + R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL); break; default: if(cl_particles_visculling.integer) @@ -2926,7 +2991,7 @@ void R_DrawParticles (void) } // anything else just has to be in front of the viewer and visible at this distance if (DotProduct(p->org, r_refdef.view.forward) >= minparticledist_start && VectorDistance2(p->org, r_refdef.view.origin) < drawdist2 * (p->size * p->size)) - R_MeshQueue_AddTransparent(p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL); + R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, p->sortorigin, R_DrawParticle_TransparentCallback, NULL, i, NULL); break; }