void V_CalcViewBlend(void) { float a2; int j; r_refdef.viewblend[0] = 0; r_refdef.viewblend[1] = 0; r_refdef.viewblend[2] = 0; r_refdef.viewblend[3] = 0; r_refdef.frustumscale_x = 1; r_refdef.frustumscale_y = 1; if (cls.state == ca_connected && cls.signon == SIGNONS) { // set contents color int supercontents; vec3_t vieworigin; Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, vieworigin); supercontents = CL_PointSuperContents(vieworigin); if (supercontents & SUPERCONTENTS_LIQUIDSMASK) { r_refdef.frustumscale_x *= 1 - (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value); r_refdef.frustumscale_y *= 1 - (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value); if (supercontents & SUPERCONTENTS_LAVA) { cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 255; cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 80; cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 0; } else if (supercontents & SUPERCONTENTS_SLIME) { cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 0; cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 25; cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 5; } else { cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 130; cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 80; cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 50; } cl.cshifts[CSHIFT_CONTENTS].percent = 150 * 0.5; } else { cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 0; cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 0; cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 0; cl.cshifts[CSHIFT_CONTENTS].percent = 0; } if (gamemode != GAME_TRANSFUSION) { if (cl.stats[STAT_ITEMS] & IT_QUAD) { cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0; cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255; cl.cshifts[CSHIFT_POWERUP].percent = 30; } else if (cl.stats[STAT_ITEMS] & IT_SUIT) { cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; cl.cshifts[CSHIFT_POWERUP].percent = 20; } else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) { cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100; cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100; cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100; cl.cshifts[CSHIFT_POWERUP].percent = 100; } else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) { cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255; cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; cl.cshifts[CSHIFT_POWERUP].percent = 30; } else cl.cshifts[CSHIFT_POWERUP].percent = 0; } cl.cshifts[CSHIFT_VCSHIFT].destcolor[0] = v_cshift.destcolor[0]; cl.cshifts[CSHIFT_VCSHIFT].destcolor[1] = v_cshift.destcolor[1]; cl.cshifts[CSHIFT_VCSHIFT].destcolor[2] = v_cshift.destcolor[2]; cl.cshifts[CSHIFT_VCSHIFT].percent = v_cshift.percent; // LordHavoc: fixed V_CalcBlend for (j = 0;j < NUM_CSHIFTS;j++) { a2 = bound(0.0f, cl.cshifts[j].percent * (1.0f / 255.0f), 1.0f); if (a2 > 0) { VectorLerp(r_refdef.viewblend, a2, cl.cshifts[j].destcolor, r_refdef.viewblend); r_refdef.viewblend[3] = (1 - (1 - r_refdef.viewblend[3]) * (1 - a2)); // correct alpha multiply... took a while to find it on the web } } // saturate color (to avoid blending in black) if (r_refdef.viewblend[3]) { a2 = 1 / r_refdef.viewblend[3]; VectorScale(r_refdef.viewblend, a2, r_refdef.viewblend); } r_refdef.viewblend[0] = bound(0.0f, r_refdef.viewblend[0], 255.0f); r_refdef.viewblend[1] = bound(0.0f, r_refdef.viewblend[1], 255.0f); r_refdef.viewblend[2] = bound(0.0f, r_refdef.viewblend[2], 255.0f); r_refdef.viewblend[3] = bound(0.0f, r_refdef.viewblend[3] * gl_polyblend.value, 1.0f); if (vid.sRGB3D) { r_refdef.viewblend[0] = Image_LinearFloatFromsRGB(r_refdef.viewblend[0]); r_refdef.viewblend[1] = Image_LinearFloatFromsRGB(r_refdef.viewblend[1]); r_refdef.viewblend[2] = Image_LinearFloatFromsRGB(r_refdef.viewblend[2]); } else { r_refdef.viewblend[0] *= (1.0f/256.0f); r_refdef.viewblend[1] *= (1.0f/256.0f); r_refdef.viewblend[2] *= (1.0f/256.0f); } // Samual: Ugly hack, I know. But it's the best we can do since // there is no way to detect client states from the engine. if (cl.stats[STAT_HEALTH] <= 0 && cl.stats[STAT_HEALTH] != -666 && cl.stats[STAT_HEALTH] != -2342 && cl_deathfade.value > 0) { cl.deathfade += cl_deathfade.value * max(0.00001, cl.time - cl.oldtime); cl.deathfade = bound(0.0f, cl.deathfade, 0.9f); } else cl.deathfade = 0.0f; if(cl.deathfade > 0) { float a; float deathfadevec[3] = {0.3f, 0.0f, 0.0f}; a = r_refdef.viewblend[3] + cl.deathfade - r_refdef.viewblend[3]*cl.deathfade; if(a > 0) VectorMAM(r_refdef.viewblend[3] * (1 - cl.deathfade) / a, r_refdef.viewblend, cl.deathfade / a, deathfadevec, r_refdef.viewblend); r_refdef.viewblend[3] = a; } } }
void CL_Beam_AddPolygons(const beam_t *b) { vec3_t beamdir, right, up, offset, start, end; vec_t beamscroll = r_refdef.scene.time * -r_lightningbeam_scroll.value; vec_t beamrepeatscale = 1.0f / r_lightningbeam_repeatdistance.value; float length, t1, t2; dp_model_t *mod; msurface_t *surf; if (r_lightningbeam_qmbtexture.integer && cl_beams_externaltexture.currentskinframe == NULL) CL_Beams_SetupExternalTexture(); if (!r_lightningbeam_qmbtexture.integer && cl_beams_builtintexture.currentskinframe == NULL) CL_Beams_SetupBuiltinTexture(); // calculate beam direction (beamdir) vector and beam length // get difference vector CL_Beam_CalculatePositions(b, start, end); VectorSubtract(end, start, beamdir); // find length of difference vector length = sqrt(DotProduct(beamdir, beamdir)); // calculate scale to make beamdir a unit vector (normalized) t1 = 1.0f / length; // scale beamdir so it is now normalized VectorScale(beamdir, t1, beamdir); // calculate up vector such that it points toward viewer, and rotates around the beamdir // get direction from start of beam to viewer VectorSubtract(r_refdef.view.origin, start, up); // remove the portion of the vector that moves along the beam // (this leaves only a vector pointing directly away from the beam) t1 = -DotProduct(up, beamdir); VectorMA(up, t1, beamdir, up); // generate right vector from forward and up, the result is unnormalized CrossProduct(beamdir, up, right); // now normalize the right vector and up vector VectorNormalize(right); VectorNormalize(up); // calculate T coordinate scrolling (start and end texcoord along the beam) t1 = beamscroll; t1 = t1 - (int)t1; t2 = t1 + beamrepeatscale * length; // the beam is 3 polygons in this configuration: // * 2 // * * // 1***** // * * // * 3 // they are showing different portions of the beam texture, creating an // illusion of a beam that appears to curl around in 3D space // (and realize that the whole polygon assembly orients itself to face // the viewer) mod = &cl_meshentitymodels[MESH_PARTICLES]; surf = Mod_Mesh_AddSurface(mod, r_lightningbeam_qmbtexture.integer ? &cl_beams_externaltexture : &cl_beams_builtintexture, false); // polygon 1 VectorM(r_lightningbeam_thickness.value, right, offset); CL_Beam_AddQuad(mod, surf, start, end, offset, t1, t2); // polygon 2 VectorMAM(r_lightningbeam_thickness.value * 0.70710681f, right, r_lightningbeam_thickness.value * 0.70710681f, up, offset); CL_Beam_AddQuad(mod, surf, start, end, offset, t1 + 0.33f, t2 + 0.33f); // polygon 3 VectorMAM(r_lightningbeam_thickness.value * 0.70710681f, right, r_lightningbeam_thickness.value * -0.70710681f, up, offset); CL_Beam_AddQuad(mod, surf, start, end, offset, t1 + 0.66f, t2 + 0.66f); }