/** * @brief Draw a raindrop * @details Render a rain particle. */ static void CG_RainParticleRender(cg_atmosphericParticle_t *particle) { vec3_t forward, right; polyVert_t verts[3]; vec2_t line; float len, dist; vec3_t start, finish; float groundHeight; if (particle->active == ACT_NOT) { return; } if (CG_CullPoint(particle->pos)) { return; } VectorCopy(particle->pos, start); dist = DistanceSquared(particle->pos, cg.refdef_current->vieworg); // make sure it doesn't clip through surfaces groundHeight = BG_GetSkyGroundHeightAtPoint(start); len = particle->height; if (start[2] - ATMOSPHERIC_PARTICLE_OFFSET <= groundHeight) { // stop rain going through surfaces len = particle->height - groundHeight + start[2]; VectorMA(start, len - particle->height, particle->deltaNormalized, start); } if (len <= 0) { return; } // fade nearby rain particles if (dist < Square(128.f)) { dist = .25f + .75f * (dist / Square(128.f)); } else { dist = 1.0f; } VectorCopy(particle->deltaNormalized, forward); VectorMA(start, -len, forward, finish); line[0] = DotProduct(forward, cg.refdef_current->viewaxis[1]); line[1] = DotProduct(forward, cg.refdef_current->viewaxis[2]); VectorScale(cg.refdef_current->viewaxis[1], line[1], right); VectorMA(right, -line[0], cg.refdef_current->viewaxis[2], right); VectorNormalize(right); VectorCopy(finish, verts[0].xyz); verts[0].st[0] = 0.5f; verts[0].st[1] = 0; verts[0].modulate[0] = particle->colour[0]; verts[0].modulate[1] = particle->colour[1]; verts[0].modulate[2] = particle->colour[2]; verts[0].modulate[3] = 100 * dist; VectorMA(start, -particle->weight, right, verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = particle->colour[0]; verts[1].modulate[1] = particle->colour[1]; verts[2].modulate[2] = particle->colour[2]; verts[1].modulate[3] = 200 * dist; VectorMA(start, particle->weight, right, verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = particle->colour[0]; verts[2].modulate[1] = particle->colour[1]; verts[2].modulate[2] = particle->colour[2]; verts[2].modulate[3] = 200 * dist; CG_AddPolyToPool(*particle->effectshader, verts); }
/** * @brief Draw a snowflake * @details Render a snow particle. */ static void CG_SnowParticleRender(cg_atmosphericParticle_t *particle) { vec3_t forward, right; polyVert_t verts[3]; vec2_t line; float len, sinTumbling, cosTumbling, particleWidth, dist; vec3_t start, finish; float groundHeight; if (particle->active == ACT_NOT) { return; } if (CG_CullPoint(particle->pos)) { return; } VectorCopy(particle->pos, start); sinTumbling = sin(particle->pos[2] * 0.03125f * (0.5f * particle->weight)); cosTumbling = cos((particle->pos[2] + particle->pos[1]) * 0.03125f * (0.5f * particle->weight)); start[0] += 24 * (1 - particle->deltaNormalized[2]) * sinTumbling; start[1] += 24 * (1 - particle->deltaNormalized[2]) * cosTumbling; // make sure it doesn't clip through surfaces groundHeight = BG_GetSkyGroundHeightAtPoint(start); len = particle->height; if (start[2] - len - ATMOSPHERIC_PARTICLE_OFFSET <= groundHeight) { return; // stop snow going through surfaces //len = particle->height - groundHeight + start[2]; //VectorMA(start, len - particle->height, particle->deltaNormalized, start); } if (len <= 0) { return; } line[0] = particle->pos[0] - cg.refdef_current->vieworg[0]; line[1] = particle->pos[1] - cg.refdef_current->vieworg[1]; dist = DistanceSquared(particle->pos, cg.refdef_current->vieworg); // dist becomes scale if (dist > Square(500.f)) { dist = 1.f + ((dist - Square(500.f)) * (10.f / Square(2000.f))); } else { dist = 1.f; } len *= dist; VectorCopy(particle->deltaNormalized, forward); VectorMA(start, -(len /* sinTumbling */), forward, finish); line[0] = DotProduct(forward, cg.refdef_current->viewaxis[1]); line[1] = DotProduct(forward, cg.refdef_current->viewaxis[2]); VectorScale(cg.refdef_current->viewaxis[1], line[1], right); VectorMA(right, -line[0], cg.refdef_current->viewaxis[2], right); VectorNormalize(right); particleWidth = dist * (/* cosTumbling */ particle->weight); VectorMA(finish, -particleWidth, right, verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255; verts[0].modulate[1] = 255; verts[0].modulate[2] = 255; verts[0].modulate[3] = 255; VectorMA(start, -particleWidth, right, verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255; verts[1].modulate[1] = 255; verts[1].modulate[2] = 255; verts[1].modulate[3] = 255; VectorMA(start, particleWidth, right, verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255; verts[2].modulate[1] = 255; verts[2].modulate[2] = 255; verts[2].modulate[3] = 255; CG_AddPolyToPool(*particle->effectshader, verts); }
static void CG_RainParticleRender( cg_atmosphericParticle_t *particle ) { // Draw a raindrop vec3_t forward, right; polyVert_t verts[3]; vec2_t line; float len, frac, dist; vec3_t start, finish; float groundHeight; // int msec = trap_Milliseconds(); // n_rendertime++; if( particle->active == ACT_NOT ) { // rendertime += trap_Milliseconds() - msec; return; } if( CG_CullPoint( particle->pos ) ) { return; } VectorCopy( particle->pos, start ); dist = DistanceSquared( particle->pos, cg.refdef_current->vieworg ); // Make sure it doesn't clip through surfaces groundHeight = BG_GetSkyGroundHeightAtPoint( start ); len = particle->height; if( start[2] <= groundHeight ) { // Stop snow going through surfaces. len = particle->height - groundHeight + start[2]; frac = start[2]; VectorMA( start, len - particle->height, particle->deltaNormalized, start ); } if( len <= 0 ) { // rendertime += trap_Milliseconds() - msec; return; } // fade nearby rain particles if( dist < Square( 128.f ) ) dist = .25f + .75f * ( dist / Square( 128.f ) ); else dist = 1.0f; VectorCopy( particle->deltaNormalized, forward ); VectorMA( start, -len, forward, finish ); line[0] = DotProduct( forward, cg.refdef_current->viewaxis[1] ); line[1] = DotProduct( forward, cg.refdef_current->viewaxis[2] ); VectorScale( cg.refdef_current->viewaxis[1], line[1], right ); VectorMA( right, -line[0], cg.refdef_current->viewaxis[2], right ); VectorNormalize( right ); // dist = 1.0; VectorCopy( finish, verts[0].xyz ); verts[0].st[0] = 0.5f; verts[0].st[1] = 0; verts[0].modulate[0] = particle->colour[0]; verts[0].modulate[1] = particle->colour[1]; verts[0].modulate[2] = particle->colour[2]; verts[0].modulate[3] = 100 * dist; VectorMA( start, -particle->weight, right, verts[1].xyz ); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = particle->colour[0]; verts[1].modulate[1] = particle->colour[1]; verts[2].modulate[2] = particle->colour[2]; verts[1].modulate[3] = 200 * dist; VectorMA( start, particle->weight, right, verts[2].xyz ); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = particle->colour[0]; verts[2].modulate[1] = particle->colour[1]; verts[2].modulate[2] = particle->colour[2]; verts[2].modulate[3] = 200 * dist; CG_AddPolyToPool( *particle->effectshader, verts ); // rendertime += trap_Milliseconds() - msec; }