static void calc_lighting (entity_t *ent, float *ambient, float *shadelight, vec3_t lightvec) { unsigned i; float add; vec3_t dist; int light; VectorSet ( -1, 0, 0, lightvec); //FIXME light = R_LightPoint (ent->origin); *ambient = max (light, max (ent->model->min_light, ent->min_light) * 128); *shadelight = *ambient; for (i = 0; i < r_maxdlights; i++) { if (r_dlights[i].die >= vr_data.realtime) { VectorSubtract (ent->origin, r_dlights[i].origin, dist); add = r_dlights[i].radius - VectorLength (dist); if (add > 0) *ambient += add; } } if (*ambient >= 128) *ambient = 128; if (*shadelight > 192 - *ambient) *shadelight = 192 - *ambient; }
void GL_VertexLight(vec3_t vertex) { extern vec3_t lightcolor; R_LightPoint(vertex); VectorScale(lightcolor, 1.0f / 100.0f, lightcolor); glColor3fv(lightcolor); }
/* ============= GL_DrawAliasShadow -- johnfitz -- rewritten TODO: orient shadow onto "lightplane" (a global mplane_t*) ============= */ void GL_DrawAliasShadow (entity_t *e) { float shadowmatrix[16] = {1, 0, 0, 0, 0, 1, 0, 0, SHADOW_SKEW_X, SHADOW_SKEW_Y, SHADOW_VSCALE, 0, 0, 0, SHADOW_HEIGHT, 1}; float lheight; aliashdr_t *paliashdr; lerpdata_t lerpdata; if (R_CullModelForEntity(e)) return; if (e == &cl.viewent || e->model->flags & MOD_NOSHADOW) return; entalpha = ENTALPHA_DECODE(e->alpha); if (entalpha == 0) return; paliashdr = (aliashdr_t *)Mod_Extradata (e->model); R_SetupAliasFrame (paliashdr, e->frame, &lerpdata); R_SetupEntityTransform (e, &lerpdata); R_LightPoint (e->origin); lheight = currententity->origin[2] - lightspot[2]; // set up matrix glPushMatrix (); glTranslatef (lerpdata.origin[0], lerpdata.origin[1], lerpdata.origin[2]); glTranslatef (0,0,-lheight); glMultMatrixf (shadowmatrix); glTranslatef (0,0,lheight); glRotatef (lerpdata.angles[1], 0, 0, 1); glRotatef (-lerpdata.angles[0], 0, 1, 0); glRotatef (lerpdata.angles[2], 1, 0, 0); glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); // draw it glDepthMask(GL_FALSE); glEnable (GL_BLEND); GL_DisableMultitexture (); glDisable (GL_TEXTURE_2D); shading = false; glColor4f(0,0,0,entalpha * 0.5); GL_DrawAliasFrame (paliashdr, lerpdata); glEnable (GL_TEXTURE_2D); glDisable (GL_BLEND); glDepthMask(GL_TRUE); //clean up glPopMatrix (); }
/* ================ R_AliasSetupLighting ================ */ static void R_AliasSetupLighting(void) { float cp, cy, sp, sy; vec_t yaw; vec3_t light; int i; // all components of light should be identical in software if (currententity->flags & RF_FULLBRIGHT) { VectorSet(light, 1, 1, 1); } else { R_LightPoint(currententity->origin, light); } if (currententity->flags & RF_MINLIGHT) { for (i = 0; i < 3; i++) if (light[i] < 0.1) light[i] = 0.1; } if (currententity->flags & RF_GLOW) { // bonus items will pulse with time float scale; float min; scale = 0.1 * sin(r_newrefdef.time * 7); for (i = 0; i < 3; i++) { min = light[i] * 0.8; light[i] += scale; if (light[i] < min) light[i] = min; } } for (i = 0; i < 3; i++) clamp(light[i], 0, 1); r_aliasblendcolor[0] = light[0] * 255; r_aliasblendcolor[1] = light[1] * 255; r_aliasblendcolor[2] = light[2] * 255; // rotate the lighting vector into the model's frame of reference yaw = -DEG2RAD(currententity->angles[YAW]); cy = cos(yaw); sy = sin(yaw); cp = cos(-M_PI / 4); sp = sin(-M_PI / 4); r_plightvec[0] = cp * cy; r_plightvec[1] = cp * sy; r_plightvec[2] = -sp; }
/* ================= R_SetupAliasLighting ================= */ void R_SetupAliasLighting (entity_t *e, float *shadelight) { R_LightPoint (e, shadelight); VectorCopy (lightspot, e->aliasstate.lightspot); // if we're overbright we scale down by half so that the clamp doesn't flatten the light as much if (overbright) VectorScale (shadelight, 0.5f, shadelight); // scale consistently with BSP lighting shadelight[0] *= (1.0f / 128.0f); shadelight[1] *= (1.0f / 128.0f); shadelight[2] *= (1.0f / 128.0f); // and now we clamp shadelight[0] = shadelight[0] > 255.0f ? 255.0f : shadelight[0]; shadelight[1] = shadelight[1] > 255.0f ? 255.0f : shadelight[1]; shadelight[2] = shadelight[2] > 255.0f ? 255.0f : shadelight[2]; // minimum light value on gun (24) if (e->renderfx & RF_WEAPONMODEL) R_MinimumLighting (shadelight, 72.0f); // minimum light value on players (8) if (e->model->modhint == MOD_PLAYER || e->renderfx & RF_PLAYERMODEL) R_MinimumLighting (shadelight, 24.0f); // hack up the brightness when fullbrights but no overbrights (256) if (gl_fullbrights.value && !gl_overbright.value) { if (e->model->flags & MOD_FBRIGHTHACK) { shadelight[0] = 255.0f; shadelight[1] = 255.0f; shadelight[2] = 255.0f; } } // take to final scale - alpha will be stored in shadelight[3] separately VectorScale (shadelight, 1.0f / 255.0f, shadelight); }
/* ================ R_AliasSetupLighting FIXME: put lighting into tables ================ */ static void R_AliasSetupLighting(entity_t *currententity) { alight_t lighting; float lightvec[3] = {-1, 0, 0}; vec3_t light; int i, j; // all components of light should be identical in software if ( currententity->flags & RF_FULLBRIGHT ) { for (i=0 ; i<3 ; i++) light[i] = 1.0; } else { R_LightPoint (currententity, currententity->origin, light); } // save off light value for server to look at (BIG HACK!) if ( currententity->flags & RF_WEAPONMODEL ) r_lightlevel->value = 150.0 * light[0]; if ( currententity->flags & RF_MINLIGHT ) { for (i=0 ; i<3 ; i++) if (light[i] < 0.1) light[i] = 0.1; } if ( currententity->flags & RF_GLOW ) { // bonus items will pulse with time float scale; scale = 0.1 * sin(r_newrefdef.time*7); for (i=0 ; i<3 ; i++) { float min; min = light[i] * 0.8; light[i] += scale; if (light[i] < min) light[i] = min; } } j = (light[0] + light[1] + light[2])*0.3333*255; lighting.ambientlight = j; lighting.shadelight = j; lighting.plightvec = lightvec; // clamp lighting so it doesn't overbright as much if (lighting.ambientlight > 128) lighting.ambientlight = 128; if (lighting.ambientlight + lighting.shadelight > 192) lighting.shadelight = 192 - lighting.ambientlight; // guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't have // to clamp off the bottom r_ambientlight = lighting.ambientlight; if (r_ambientlight < LIGHT_MIN) r_ambientlight = LIGHT_MIN; r_ambientlight = (255 - r_ambientlight) << VID_CBITS; if (r_ambientlight < LIGHT_MIN) r_ambientlight = LIGHT_MIN; r_shadelight = lighting.shadelight; if (r_shadelight < 0) r_shadelight = 0; r_shadelight *= VID_GRADES; // rotate the lighting vector into the model's frame of reference r_plightvec[0] = DotProduct( lighting.plightvec, s_alias_forward ); r_plightvec[1] = -DotProduct( lighting.plightvec, s_alias_right ); r_plightvec[2] = DotProduct( lighting.plightvec, s_alias_up ); }
/* ============= R_DrawViewModel ============= */ void R_DrawViewModel (void) { float ambient[4], diffuse[4]; int j; int lnum; vec3_t dist; float add; dlight_t *dl; int ambientlight, shadelight; if (!r_drawviewmodel.value) return; if (chase_active.value) return; if (envmap) return; if (!r_drawentities.value) return; if (cl.items & IT_INVISIBILITY) return; if (cl.stats[STAT_HEALTH] <= 0) return; currententity = &cl.viewent; if (!currententity->model) return; j = R_LightPoint (currententity->origin); if (j < 24) j = 24; // allways give some light on gun ambientlight = j; shadelight = j; // add dynamic lights for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++) { dl = &cl_dlights[lnum]; if (!dl->radius) continue; if (!dl->radius) continue; if (dl->die < cl.time) continue; VectorSubtract (currententity->origin, dl->origin, dist); add = dl->radius - Length(dist); if (add > 0) ambientlight += add; } ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128; diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128; // hack the depth range to prevent view model from poking into walls glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); R_DrawAliasModel (currententity); glDepthRange (gldepthmin, gldepthmax); }
/* ================= R_DrawAliasModel ================= */ void R_DrawAliasModel (entity_t *e) { int i, j; int lnum; vec3_t dist; float add; model_t *clmodel; vec3_t mins, maxs; aliashdr_t *paliashdr; trivertx_t *verts, *v; int index; float s, t, an; int anim; clmodel = currententity->model; VectorAdd (currententity->origin, clmodel->mins, mins); VectorAdd (currententity->origin, clmodel->maxs, maxs); if (R_CullBox (mins, maxs)) return; VectorCopy (currententity->origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); // // get lighting information // ambientlight = shadelight = R_LightPoint (currententity->origin); // allways give the gun some light if (e == &cl.viewent && ambientlight < 24) ambientlight = shadelight = 24; for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++) { if (cl_dlights[lnum].die >= cl.time) { VectorSubtract (currententity->origin, cl_dlights[lnum].origin, dist); add = cl_dlights[lnum].radius - Length(dist); if (add > 0) { ambientlight += add; //ZOID models should be affected by dlights as well shadelight += add; } } } // clamp lighting so it doesn't overbright as much if (ambientlight > 128) ambientlight = 128; if (ambientlight + shadelight > 192) shadelight = 192 - ambientlight; // ZOID: never allow players to go totally black i = currententity - cl_entities; if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */) if (ambientlight < 8) ambientlight = shadelight = 8; // HACK HACK HACK -- no fullbright colors, so make torches full light if (!strcmp (clmodel->name, "progs/flame2.mdl") || !strcmp (clmodel->name, "progs/flame.mdl") ) ambientlight = shadelight = 256; shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; shadelight = shadelight / 200.0; an = e->angles[1]/180*M_PI; shadevector[0] = cos(-an); shadevector[1] = sin(-an); shadevector[2] = 1; VectorNormalize (shadevector); // // locate the proper data // paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model); c_alias_polys += paliashdr->numtris; // // draw all the triangles // GL_DisableMultitexture(); glPushMatrix (); R_RotateForEntity (e); if (!strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes.value) { glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8)); // double size of eyes, since they are really hard to see in gl glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2); } else { glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); } anim = (int)(cl.time*10) & 3; GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]); // we can't dynamically colormap textures, so they are cached // seperately for the players. Heads are just uncolored. if (currententity->colormap != vid.colormap && !gl_nocolors.value) { i = currententity - cl_entities; if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */) GL_Bind(playertextures - 1 + i); } if (gl_smoothmodels.value) glShadeModel (GL_SMOOTH); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); if (gl_affinemodels.value) glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); R_SetupAliasFrame (currententity->frame, paliashdr); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glShadeModel (GL_FLAT); if (gl_affinemodels.value) glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glPopMatrix (); if (r_shadows.value) { glPushMatrix (); R_RotateForEntity (e); glDisable (GL_TEXTURE_2D); glEnable (GL_BLEND); glColor4f (0,0,0,0.5); GL_DrawAliasShadow (paliashdr, lastposenum); glEnable (GL_TEXTURE_2D); glDisable (GL_BLEND); glColor4f (1,1,1,1); glPopMatrix (); } }
/* ================= R_SetShadeLight ================= */ void R_SetShadeLight (void) { int32_t i; if (currententity->flags & RF_MASK_SHELL) { VectorClear (shadelight); if (currententity->flags & RF_SHELL_HALF_DAM) { shadelight[0] = 0.56; shadelight[1] = 0.59; shadelight[2] = 0.45; } if ( currententity->flags & RF_SHELL_DOUBLE ) { shadelight[0] = 0.9; shadelight[1] = 0.7; } if ( currententity->flags & RF_SHELL_RED ) shadelight[0] = 1.0; if ( currententity->flags & RF_SHELL_GREEN ) shadelight[1] = 1.0; if ( currententity->flags & RF_SHELL_BLUE ) shadelight[2] = 1.0; } else if ( currententity->flags & RF_FULLBRIGHT ) { for (i=0 ; i<3 ; i++) shadelight[i] = 1.0; } else { // Set up basic lighting... if (r_model_shading->value && r_model_dlights->value) { int32_t max = r_model_dlights->value; if (max<0) max=0; if (max>MAX_MODEL_DLIGHTS) max=MAX_MODEL_DLIGHTS; R_LightPointDynamics (currententity->origin, shadelight, model_dlights, &model_dlights_num, max); } else { R_LightPoint (currententity->origin, shadelight, false);//true); model_dlights_num = 0; } // player lighting hack for communication back to server // big hack! if ( currententity->flags & RF_WEAPONMODEL ) { // pick the greatest component, which should be the same // as the mono value returned by software if (shadelight[0] > shadelight[1]) { if (shadelight[0] > shadelight[2]) r_lightlevel->value = 150*shadelight[0]; else r_lightlevel->value = 150*shadelight[2]; } else { if (shadelight[1] > shadelight[2]) r_lightlevel->value = 150*shadelight[1]; else r_lightlevel->value = 150*shadelight[2]; } } } if ( currententity->flags & RF_MINLIGHT ) { for (i=0; i<3; i++) if (shadelight[i] > 0.02) break; if (i == 3) { shadelight[0] = 0.02; shadelight[1] = 0.02; shadelight[2] = 0.02; } } if ( currententity->flags & RF_GLOW ) { // bonus items will pulse with time float scale; float min; scale = 0.2 * sin(r_newrefdef.time*7); for (i=0 ; i<3 ; i++) { min = shadelight[i] * 0.8; shadelight[i] += scale; if (shadelight[i] < min) shadelight[i] = min; } } if (r_newrefdef.rdflags & RDF_IRGOGGLES) { if (currententity->flags & RF_IR_VISIBLE) { shadelight[0] = 1.0; shadelight[1] = 0.0; shadelight[2] = 0.0; } } /* if (r_newrefdef.rdflags & RDF_UVGOGGLES) { if (currententity->flags & RF_IR_VISIBLE) { shadelight[0] = 0.5; shadelight[1] = 1.0; shadelight[2] = 0.5; } else { shadelight[0] = 0.0; shadelight[1] = 1.0; shadelight[2] = 0.0; } }*/ shadedots = r_avertexnormal_dots[((int32_t)(currententity->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; }
void R_DrawAliasModel ( entity_t *e ) { int i; dmdl_t *paliashdr; float an; vec3_t bbox [ 8 ]; image_t *skin; if ( !( e->flags & RF_WEAPONMODEL ) ) { if ( R_CullAliasModel( bbox, e ) ) { return; } } if ( e->flags & RF_WEAPONMODEL ) { if ( gl_lefthand->value == 2 ) { return; } } paliashdr = (dmdl_t *) currentmodel->extradata; /* get lighting information */ if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) ) { VectorClear( shadelight ); if ( currententity->flags & RF_SHELL_HALF_DAM ) { shadelight [ 0 ] = 0.56; shadelight [ 1 ] = 0.59; shadelight [ 2 ] = 0.45; } if ( currententity->flags & RF_SHELL_DOUBLE ) { shadelight [ 0 ] = 0.9; shadelight [ 1 ] = 0.7; } if ( currententity->flags & RF_SHELL_RED ) { shadelight [ 0 ] = 1.0; } if ( currententity->flags & RF_SHELL_GREEN ) { shadelight [ 1 ] = 1.0; } if ( currententity->flags & RF_SHELL_BLUE ) { shadelight [ 2 ] = 1.0; } } else if ( currententity->flags & RF_FULLBRIGHT ) { for ( i = 0; i < 3; i++ ) { shadelight [ i ] = 1.0; } } else { R_LightPoint( currententity->origin, shadelight ); /* player lighting hack for communication back to server */ if ( currententity->flags & RF_WEAPONMODEL ) { /* pick the greatest component, which should be the same as the mono value returned by software */ if ( shadelight [ 0 ] > shadelight [ 1 ] ) { if ( shadelight [ 0 ] > shadelight [ 2 ] ) { gl_lightlevel->value = 150 * shadelight [ 0 ]; } else { gl_lightlevel->value = 150 * shadelight [ 2 ]; } } else { if ( shadelight [ 1 ] > shadelight [ 2 ] ) { gl_lightlevel->value = 150 * shadelight [ 1 ]; } else { gl_lightlevel->value = 150 * shadelight [ 2 ]; } } } } if ( currententity->flags & RF_MINLIGHT ) { for ( i = 0; i < 3; i++ ) { if ( shadelight [ i ] > 0.1 ) { break; } } if ( i == 3 ) { shadelight [ 0 ] = 0.1; shadelight [ 1 ] = 0.1; shadelight [ 2 ] = 0.1; } } if ( currententity->flags & RF_GLOW ) { /* bonus items will pulse with time */ float scale; float min; scale = 0.1 * sin( r_newrefdef.time * 7 ); for ( i = 0; i < 3; i++ ) { min = shadelight [ i ] * 0.8; shadelight [ i ] += scale; if ( shadelight [ i ] < min ) { shadelight [ i ] = min; } } } /* ir goggles color override */ if ( r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE ) { shadelight [ 0 ] = 1.0; shadelight [ 1 ] = 0.0; shadelight [ 2 ] = 0.0; } shadedots = r_avertexnormal_dots [ ( (int) ( currententity->angles [ 1 ] * ( SHADEDOT_QUANT / 360.0 ) ) ) & ( SHADEDOT_QUANT - 1 ) ]; an = currententity->angles [ 1 ] / 180 * M_PI; shadevector [ 0 ] = cos( -an ); shadevector [ 1 ] = sin( -an ); shadevector [ 2 ] = 1; VectorNormalize( shadevector ); /* locate the proper data */ c_alias_polys += paliashdr->num_tris; /* draw all the triangles */ if ( currententity->flags & RF_DEPTHHACK ) /* hack the depth range to prevent view model from poking into walls */ { qglDepthRange( gldepthmin, gldepthmin + 0.3 * ( gldepthmax - gldepthmin ) ); } if ( ( currententity->flags & RF_WEAPONMODEL ) && ( gl_lefthand->value == 1.0F ) ) { extern void R_MYgluPerspective ( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ); qglMatrixMode( GL_PROJECTION ); qglPushMatrix(); qglLoadIdentity(); qglScalef( -1, 1, 1 ); R_MYgluPerspective( r_newrefdef.fov_y, (float) r_newrefdef.width / r_newrefdef.height, 4, 4096 ); qglMatrixMode( GL_MODELVIEW ); qglCullFace( GL_BACK ); } qglPushMatrix(); e->angles [ PITCH ] = -e->angles [ PITCH ]; R_RotateForEntity( e ); e->angles [ PITCH ] = -e->angles [ PITCH ]; /* select skin */ if ( currententity->skin ) { skin = currententity->skin; /* custom player skin */ } else { if ( currententity->skinnum >= MAX_MD2SKINS ) { skin = currentmodel->skins [ 0 ]; } else { skin = currentmodel->skins [ currententity->skinnum ]; if ( !skin ) { skin = currentmodel->skins [ 0 ]; } } } if ( !skin ) { skin = r_notexture; /* fallback... */ } R_Bind( skin->texnum ); /* draw it */ qglShadeModel( GL_SMOOTH ); R_TexEnv( GL_MODULATE ); if ( currententity->flags & RF_TRANSLUCENT ) { qglEnable( GL_BLEND ); } if ( ( currententity->frame >= paliashdr->num_frames ) || ( currententity->frame < 0 ) ) { ri.Con_Printf( PRINT_ALL, "R_DrawAliasModel %s: no such frame %d\n", currentmodel->name, currententity->frame ); currententity->frame = 0; currententity->oldframe = 0; } if ( ( currententity->oldframe >= paliashdr->num_frames ) || ( currententity->oldframe < 0 ) ) { ri.Con_Printf( PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n", currentmodel->name, currententity->oldframe ); currententity->frame = 0; currententity->oldframe = 0; } if ( !gl_lerpmodels->value ) { currententity->backlerp = 0; } R_DrawAliasFrameLerp( paliashdr, currententity->backlerp ); R_TexEnv( GL_REPLACE ); qglShadeModel( GL_FLAT ); qglPopMatrix(); if ( ( currententity->flags & RF_WEAPONMODEL ) && ( gl_lefthand->value == 1.0F ) ) { qglMatrixMode( GL_PROJECTION ); qglPopMatrix(); qglMatrixMode( GL_MODELVIEW ); qglCullFace( GL_FRONT ); } if ( currententity->flags & RF_TRANSLUCENT ) { qglDisable( GL_BLEND ); } if ( currententity->flags & RF_DEPTHHACK ) { qglDepthRange( gldepthmin, gldepthmax ); } if ( gl_shadows->value && !( currententity->flags & ( RF_TRANSLUCENT | RF_WEAPONMODEL | RF_NOSHADOW ) ) ) { qglPushMatrix(); /* don't rotate shadows on ungodly axes */ qglTranslatef( e->origin [ 0 ], e->origin [ 1 ], e->origin [ 2 ] ); qglRotatef( e->angles [ 1 ], 0, 0, 1 ); qglDisable( GL_TEXTURE_2D ); qglEnable( GL_BLEND ); qglColor4f( 0, 0, 0, 0.5f ); R_DrawAliasShadow( paliashdr, currententity->frame ); qglEnable( GL_TEXTURE_2D ); qglDisable( GL_BLEND ); qglPopMatrix(); } qglColor4f( 1, 1, 1, 1 ); }
/* ================= R_DrawAliasModelShadow ================= */ void R_DrawAliasModelShadow(entity_t *e) { int i; dmdl_t *hdr; float an; vec3_t bbox[8]; image_t *skin; float lightspot[3]; glmatrix shadowmatrix; float lheight; if (gl_shadows->value && (e->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL | RF_NOSHADOW))) return; if (!(e->flags & RF_WEAPONMODEL)) { if (R_CullAliasModel(bbox, e)) return; } if (e->flags & RF_WEAPONMODEL) { if (r_lefthand->value == 2) return; } hdr = (dmdl_t *)e->model->extradata; if (e->flags & (RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE)) { VectorClear(gl_meshuboupdate.shadelight); if (e->flags & RF_SHELL_RED) gl_meshuboupdate.shadelight[0] = 1.0; if (e->flags & RF_SHELL_GREEN) gl_meshuboupdate.shadelight[1] = 1.0; if (e->flags & RF_SHELL_BLUE) gl_meshuboupdate.shadelight[2] = 1.0; } else if (e->flags & RF_FULLBRIGHT) { gl_meshuboupdate.shadelight[0] = 1.0; gl_meshuboupdate.shadelight[1] = 1.0; gl_meshuboupdate.shadelight[2] = 1.0; } else { R_LightPoint(e->currorigin, gl_meshuboupdate.shadelight, lightspot); // player lighting hack for communication back to server // big hack! if (e->flags & RF_WEAPONMODEL) { // pick the greatest component, which should be the same // as the mono value returned by software if (gl_meshuboupdate.shadelight[0] > gl_meshuboupdate.shadelight[1]) { if (gl_meshuboupdate.shadelight[0] > gl_meshuboupdate.shadelight[2]) r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[0]; else r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[2]; } else { if (gl_meshuboupdate.shadelight[1] > gl_meshuboupdate.shadelight[2]) r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[1]; else r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[2]; } } } if (e->flags & RF_MINLIGHT) { for (i = 0; i < 3; i++) if (gl_meshuboupdate.shadelight[i] > 0.1) break; if (i == 3) { gl_meshuboupdate.shadelight[0] = 0.1; gl_meshuboupdate.shadelight[1] = 0.1; gl_meshuboupdate.shadelight[2] = 0.1; } } if (e->flags & RF_GLOW) { // bonus items will pulse with time float scale; float min; scale = 0.1 * sin(r_newrefdef.time * 7); for (i = 0; i < 3; i++) { min = gl_meshuboupdate.shadelight[i] * 0.8; gl_meshuboupdate.shadelight[i] += scale; if (gl_meshuboupdate.shadelight[i] < min) gl_meshuboupdate.shadelight[i] = min; } } an = e->angles[1] / 180 * M_PI; Q_sincos(-an, &gl_meshuboupdate.shadevector[1], &gl_meshuboupdate.shadevector[0]); gl_meshuboupdate.shadevector[2] = 1; VectorNormalize(gl_meshuboupdate.shadevector); // locate the proper data c_alias_polys += hdr->num_tris; // draw all the triangles GL_LoadMatrix(&gl_meshuboupdate.localMatrix, &r_mvpmatrix); GL_TranslateMatrix(&gl_meshuboupdate.localMatrix, e->currorigin[0], e->currorigin[1], e->currorigin[2]); GL_RotateMatrix(&gl_meshuboupdate.localMatrix, e->angles[1], 0, 0, 1); GL_RotateMatrix(&gl_meshuboupdate.localMatrix, e->angles[0], 0, 1, 0); GL_RotateMatrix(&gl_meshuboupdate.localMatrix, -e->angles[2], 1, 0, 0); // select skin if (e->skin) skin = e->skin; // custom player skin else { if (e->skinnum >= MAX_MD2SKINS) skin = e->model->skins[0]; else { skin = e->model->skins[e->skinnum]; if (!skin) skin = e->model->skins[0]; } } if (!skin) skin = r_notexture; // fallback... GL_BindTexture(GL_TEXTURE0, GL_TEXTURE_2D, r_modelsampler, skin->texnum); if ((e->currframe >= hdr->num_frames) || (e->currframe < 0)) { VID_Printf(PRINT_ALL, S_COLOR_RED "R_DrawAliasModel %s: no such frame %d\n", e->model->name, e->currframe); e->currframe = 0; e->lastframe = 0; } if ((e->lastframe >= hdr->num_frames) || (e->lastframe < 0)) { VID_Printf(PRINT_ALL, S_COLOR_RED "R_DrawAliasModel %s: no such oldframe %d\n", e->model->name, e->lastframe); e->currframe = 0; e->lastframe = 0; } if (!r_lerpmodels->value) e->backlerp = 0; lheight = e->currorigin[2] - lightspot[2]; GL_TranslateMatrix(&gl_meshuboupdate.localMatrix, 0.0f, 0.0f, -lheight); shadowmatrix.m[0][0] = 1; shadowmatrix.m[0][1] = 0; shadowmatrix.m[0][2] = 0; shadowmatrix.m[0][3] = 0; shadowmatrix.m[1][0] = 0; shadowmatrix.m[1][1] = 1; shadowmatrix.m[1][2] = 0; shadowmatrix.m[1][3] = 0; shadowmatrix.m[2][0] = SHADOW_SKEW_X; shadowmatrix.m[2][1] = SHADOW_SKEW_Y; shadowmatrix.m[2][2] = SHADOW_VSCALE; shadowmatrix.m[2][3] = 0; shadowmatrix.m[3][0] = 0; shadowmatrix.m[3][1] = 0; shadowmatrix.m[3][2] = SHADOW_HEIGHT; shadowmatrix.m[3][3] = 1; GL_MultMatrix(&gl_meshuboupdate.localMatrix, &gl_meshuboupdate.localMatrix, &shadowmatrix); GL_TranslateMatrix(&gl_meshuboupdate.localMatrix, 0.0f, 0.0f, lheight); // draw shadow GL_DrawAliasFrameLerp(e, hdr, e->backlerp); }
void R_DrawBrushModel(entity_t *e) { int k; vec3_t mins, maxs; model_t *clmodel; bool rotated; int i; extern vec3_t lightcolor; int lnum; vec3_t dist; float add; float modelorg[3]; clmodel = e->model; if (e->angles[0] || e->angles[1] || e->angles[2]) { rotated = true; for (i = 0; i < 3; i++) { mins[i] = e->origin[i] - clmodel->radius; maxs[i] = e->origin[i] + clmodel->radius; } } else { rotated = false; VectorAdd(e->origin, clmodel->mins, mins); VectorAdd(e->origin, clmodel->maxs, maxs); } if (R_CullBox(mins, maxs)) return; //Lighting for model //dynamic lights for non lightmaped bmodels if (clmodel->firstmodelsurface == 0) { R_LightPoint(e->origin); for (lnum = 0; lnum < MAX_DLIGHTS; lnum++) { if (cl_dlights[lnum].die >= cl.time) { VectorSubtract(e->origin, cl_dlights[lnum].origin, dist); add = cl_dlights[lnum].radius - VectorLength(dist); if (add > 0) { lightcolor[0] += add * cl_dlights[lnum].colour[0]; lightcolor[1] += add * cl_dlights[lnum].colour[1]; lightcolor[2] += add * cl_dlights[lnum].colour[2]; } } } VectorScale(lightcolor, 1.0f / 100.0f, lightcolor); if (gl_ammoflash.getBool()) { lightcolor[0] += sin(2 * cl.time * M_PI) / 4; lightcolor[1] += sin(2 * cl.time * M_PI) / 4; lightcolor[2] += sin(2 * cl.time * M_PI) / 4; } glColor3fv(lightcolor); } else { glColor3f(1.0, 1.0, 1.0); memset(lightmap_polys, 0, sizeof (lightmap_polys)); } VectorSubtract(r_refdef.vieworg, e->origin, modelorg); if (rotated) { vec3_t temp; vec3_t forward, right, up; VectorCopy(modelorg, temp); AngleVectors(e->angles, forward, right, up); modelorg[0] = DotProduct(temp, forward); modelorg[1] = -DotProduct(temp, right); modelorg[2] = DotProduct(temp, up); } glPushMatrix(); e->angles[0] = -e->angles[0]; // stupid quake bug R_RotateForEntity(e); e->angles[0] = -e->angles[0]; // stupid quake bug // calculate dynamic lighting for bmodel if it's not an // instanced model if (clmodel->firstmodelsurface != 0 && !gl_flashblend.getBool()) { for (k = 0; k < MAX_DLIGHTS; k++) { if ((cl_dlights[k].die < cl.time) || (!cl_dlights[k].radius)) continue; R_MarkLights(&cl_dlights[k], 1 << k, clmodel->nodes + clmodel->hulls[0].firstclipnode); } } R_DrawBrush(clmodel, &modelorg[0]); glPopMatrix(); }
/* ================= R_SetupAliasLighting -- johnfitz -- broken out from R_DrawAliasModel and rewritten ================= */ void R_SetupAliasLighting (entity_t *e) { vec3_t dist; float add; int i; R_LightPoint (e->origin); //add dlights for (i=0 ; i<MAX_DLIGHTS ; i++) { if (cl_dlights[i].die >= cl.time) { VectorSubtract (currententity->origin, cl_dlights[i].origin, dist); add = cl_dlights[i].radius - VectorLength(dist); if (add > 0) VectorMA (lightcolor, add, cl_dlights[i].color, lightcolor); } } // minimum light value on gun (24) if (e == &cl.viewent) { add = 72.0f - (lightcolor[0] + lightcolor[1] + lightcolor[2]); if (add > 0.0f) { lightcolor[0] += add / 3.0f; lightcolor[1] += add / 3.0f; lightcolor[2] += add / 3.0f; } } // minimum light value on players (8) if (currententity > cl_entities && currententity <= cl_entities + cl.maxclients) { add = 24.0f - (lightcolor[0] + lightcolor[1] + lightcolor[2]); if (add > 0.0f) { lightcolor[0] += add / 3.0f; lightcolor[1] += add / 3.0f; lightcolor[2] += add / 3.0f; } } // clamp lighting so it doesn't overbright as much (96) if (overbright) { add = 288.0f / (lightcolor[0] + lightcolor[1] + lightcolor[2]); if (add < 1.0f) VectorScale(lightcolor, add, lightcolor); } //hack up the brightness when fullbrights but no overbrights (256) if (gl_fullbrights.value && !gl_overbright_models.value) if (e->model->flags & MOD_FBRIGHTHACK) { lightcolor[0] = 256.0f; lightcolor[1] = 256.0f; lightcolor[2] = 256.0f; } shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; VectorScale(lightcolor, 1.0f / 200.0f, lightcolor); }
void R_DrawAliasModel(entity_t *e) { extern void AddFire(vec3_t org, float size); int lnum; vec3_t dist; float add; model_t *clmodel; vec3_t mins, maxs; aliashdr_t *paliashdr; float an; //s, t, int anim; md2_t *pheader; // LH / muff int shell; //QMB :model shells //not implemented yet // byte c, *color; //QMB :color map //does the model need a shell? if (cl.items & IT_QUAD && e == &cl.viewent) shell = true; else shell = false; //set get the model from the e clmodel = e->model; //work out its max and mins VectorAdd(e->origin, clmodel->mins, mins); VectorAdd(e->origin, clmodel->maxs, maxs); //make sure its in screen if (R_CullBox(mins, maxs) && e != &cl.viewent) return; //QMB: FIXME //should use a particle emitter linked to the model for its org //needs to be linked when the model is created and distroyed when //the entity is distroyed //check if its a fire and add the particle effect if (!strcmp(clmodel->name, "progs/flame.mdl")) AddFire(e->origin, 4); if (!strcmp(clmodel->name, "progs/flame2.mdl")) { AddFire(e->origin, 10); return; //do not draw the big fire model, its just a place holder for the particles } // get lighting information //QMB: FIXME //SHOULD CHANGE TO A PASSED VAR //get vertex normals (for lighting and shells) shadedots = r_avertexnormal_dots[((int) (e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; //make a default lighting direction an = e->angles[1] / 180 * M_PI; shadevector[0] = cos(-an); shadevector[1] = sin(-an); shadevector[2] = 1; //e->angles[0]; VectorNormalize(shadevector); //get the light for the model R_LightPoint(e->origin); // LordHavoc: lightcolor is all that matters from this //work out lighting from the dynamic lights for (lnum = 0; lnum < MAX_DLIGHTS; lnum++) { //if the light is alive if (cl_dlights[lnum].die >= cl.time) { //work out the distance to the light VectorSubtract(e->origin, cl_dlights[lnum].origin, dist); add = cl_dlights[lnum].radius - VectorLength(dist); //if its close enough add light from it if (add > 0) { lightcolor[0] += add * cl_dlights[lnum].colour[0]; lightcolor[1] += add * cl_dlights[lnum].colour[1]; lightcolor[2] += add * cl_dlights[lnum].colour[2]; } } } //scale lighting to floating point VectorScale(lightcolor, 1.0f / 200.0f, lightcolor); // locate the proper data glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); if (gl_n_patches && gl_npatches.getBool()) { glEnable(GL_PN_TRIANGLES_ATI); glPNTrianglesiATI(GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, gl_npatches.getInt()); if (true) glPNTrianglesiATI(GL_PN_TRIANGLES_POINT_MODE_ATI, GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI); else glPNTrianglesiATI(GL_PN_TRIANGLES_POINT_MODE_ATI, GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI); if (true) glPNTrianglesiATI(GL_PN_TRIANGLES_NORMAL_MODE_ATI, GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI); else glPNTrianglesiATI(GL_PN_TRIANGLES_NORMAL_MODE_ATI, GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI); } if (clmodel->aliastype == MD3IDHEADER) { //do nothing for testing if (!r_modeltexture.getBool()) { GL_DisableTMU(GL_TEXTURE0_ARB); }//disable texture if needed R_DrawQ3Model(e, false, false); if (!r_modeltexture.getBool()) { GL_EnableTMU(GL_TEXTURE0_ARB); }//enable texture if needed if (r_celshading.getBool() || r_outline.getBool()) { glCullFace(GL_BACK); glEnable(GL_BLEND); glPolygonMode(GL_FRONT, GL_LINE); if (e == &cl.viewent) { glLineWidth(1.0f); } else { glLineWidth(5.0f); } glEnable(GL_LINE_SMOOTH); GL_DisableTMU(GL_TEXTURE0_ARB); glColor3f(0.0, 0.0, 0.0); R_DrawQ3Model(e, false, true); glColor3f(1.0, 1.0, 1.0); GL_EnableTMU(GL_TEXTURE0_ARB); glPolygonMode(GL_FRONT, GL_FILL); glDisable(GL_BLEND); glCullFace(GL_FRONT); } if (shell) { glBindTexture(GL_TEXTURE_2D, quadtexture); glColor4f(1.0, 1.0, 1.0, 0.5); glEnable(GL_BLEND); R_DrawQ3Model(e, true, false); glDisable(GL_BLEND); glColor3f(1.0, 1.0, 1.0); } } else if (clmodel->aliastype != ALIASTYPE_MD2) { paliashdr = (aliashdr_t *) Mod_Extradata(e->model); c_alias_polys += paliashdr->numtris; glPushMatrix(); //interpolate unless its the viewmodel if (e != &cl.viewent) R_BlendedRotateForEntity(e); else R_RotateForEntity(e); glTranslatef(paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); glScalef(paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); anim = (int) (cl.time * 10) & 3; glBindTexture(GL_TEXTURE_2D, paliashdr->gl_texturenum[e->skinnum][anim]); // draw all the triangles if (!r_modeltexture.getBool()) { GL_DisableTMU(GL_TEXTURE0_ARB); } else { //highlighting test code if (0 && gl_textureunits > 2) { GL_EnableTMU(GL_TEXTURE1_ARB); glBindTexture(GL_TEXTURE_2D, TextureManager::highlighttexture); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); //need correct mode glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0); //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); } } glColor3fv(lightcolor); R_SetupAliasBlendedFrame(e->frame, paliashdr, e, false, false); glDisable(GL_TEXTURE_1D); if (r_celshading.getBool() || r_outline.getBool()) { glColor3f(0.0, 0.0, 0.0); R_SetupAliasBlendedFrame(e->frame, paliashdr, e, false, true); glColor3f(1.0, 1.0, 1.0); } if (!r_modeltexture.getBool()) { GL_EnableTMU(GL_TEXTURE0_ARB); } else { if (0 && gl_textureunits > 2) { //highlighting test code glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); GL_DisableTMU(GL_TEXTURE1_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } glActiveTexture(GL_TEXTURE0_ARB); //colour map code... not working yet... /* if (e->colormap != vid.colormap && !gl_nocolors.value) { if (paliashdr->gl_texturenumColorMap&&paliashdr->gl_texturenumColorMap){ glBindTexture(GL_TEXTURE_2D,paliashdr->gl_texturenumColorMap); c = (byte)e->colormap & 0xF0; c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges color = (byte *) (&d_8to24table[c]); //glColor3fv(color); glColor3f(1.0,1.0,1.0); } }*/ if (shell) { glBindTexture(GL_TEXTURE_2D, quadtexture); glColor4f(1.0, 1.0, 1.0, 0.5); glEnable(GL_BLEND); R_SetupAliasBlendedFrame(e->frame, paliashdr, e, true, false); glDisable(GL_BLEND); glColor3f(1.0, 1.0, 1.0); } glPopMatrix(); } else { pheader = (md2_t *) Mod_Extradata(e->model); c_alias_polys += pheader->num_tris; glBindTexture(GL_TEXTURE_2D, pheader->gl_texturenum[e->skinnum]); R_SetupQ2AliasFrame(e, pheader); } if (gl_n_patches && gl_npatches.getBool()) { glDisable(GL_PN_TRIANGLES_ATI); } glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); }
/* ================= RE_AddDecal Adds a single decal to the decal list ================= */ void RE_GL_AddDecal (vec3_t origin, vec3_t dir, vec4_t color, float size, int type, int flags, float angle) { int i, j, numfragments; vec3_t verts[MAX_DECAL_VERTS], shade, temp; markFragment_t *fr, fragments[MAX_FRAGMENTS_PER_DECAL]; vec3_t axis[3]; cdecal_t *d; float lightspot[3]; if (!gl_decals->value) return; // invalid decal size if (size <= 0) return; // a hack to produce decals from explosions etc if (VectorCompare(dir, vec3_origin)) { float scale = 1.5 * size; trace_t trace; vec3_t end, dirs[6] = { { 1.0, 0.0, 0.0 }, { -1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, -1.0, 0.0 }, { 0.0, 0.0, 1.0 }, { 0.0, 0.0, -1.0 } }; for (i = 0; i < 6; i++) { VectorMA(origin, scale, dirs[i], end); trace = CL_Trace(origin, end, 0, MASK_SOLID); if (trace.fraction != 1.0) RE_GL_AddDecal(origin, trace.plane.normal, color, size, type, flags, angle); } return; } // calculate orientation matrix VectorNormalize2(dir, axis[0]); PerpendicularVector(axis[1], axis[0]); RotatePointAroundVector(axis[2], axis[0], axis[1], angle); CrossProduct(axis[0], axis[2], axis[1]); // clip it against the world numfragments = R_GetClippedFragments(origin, axis, size, MAX_DECAL_VERTS, verts, MAX_FRAGMENTS_PER_DECAL, fragments); if (!numfragments) return; // no valid fragments // store out vertex data size = 0.5f / size; VectorScale(axis[1], size, axis[1]); VectorScale(axis[2], size, axis[2]); for (i = 0, fr = fragments; i < numfragments; i++, fr++) { // check if we have hit the max if (fr->numPoints > MAX_DECAL_VERTS) fr->numPoints = MAX_DECAL_VERTS; else if (fr->numPoints <= 0) continue; d = R_AllocDecal(); d->time = r_newrefdef.time; d->node = fr->node; VectorCopy(fr->surf->plane->normal, d->direction); if (!(fr->surf->flags & SURF_PLANEBACK)) VectorNegate(d->direction, d->direction); // reverse direction Vector4Set(d->color, color[0], color[1], color[2], color[3]); VectorCopy(origin, d->org); //if (flags & DF_SHADE) { R_LightPoint(origin, shade, lightspot); for (j = 0; j < 3; j++) d->color[j] = (d->color[j] * shade[j] * 0.6) + (d->color[j] * 0.4); } d->type = type; d->flags = flags; // make the decal vert d->numverts = fr->numPoints; for (j = 0; j < fr->numPoints && j < MAX_VERTS_PER_FRAGMENT; j++) { // xyz VectorCopy(verts[fr->firstPoint + j], d->verts[j]); // st VectorSubtract(d->verts[j], origin, temp); d->stcoords[j][0] = DotProduct(temp, axis[1]) + 0.5f; d->stcoords[j][1] = DotProduct(temp, axis[2]) + 0.5f; } } }
/* ================= R_DrawAliasModel ================= */ void R_DrawAliasModel (entity_t *e) { int i; dmdl_t *paliashdr; float an; vec3_t bbox[8]; image_t *skin; if ( !( e->flags & RF_WEAPONMODEL ) ) { if ( R_CullAliasModel( bbox, e ) ) return; } if ( e->flags & RF_WEAPONMODEL ) { if ( r_lefthand->value == 2 ) return; } paliashdr = (dmdl_t *)currentmodel->extradata; // // get lighting information // // PMM - rewrote, reordered to handle new shells & mixing // if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) ) { // PMM -special case for godmode if ( (currententity->flags & RF_SHELL_RED) && (currententity->flags & RF_SHELL_BLUE) && (currententity->flags & RF_SHELL_GREEN) ) { for (i=0 ; i<3 ; i++) shadelight[i] = 1.0; } else if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) ) { VectorClear (shadelight); if ( currententity->flags & RF_SHELL_RED ) { shadelight[0] = 1.0; if (currententity->flags & (RF_SHELL_BLUE|RF_SHELL_DOUBLE) ) shadelight[2] = 1.0; } else if ( currententity->flags & RF_SHELL_BLUE ) { if ( currententity->flags & RF_SHELL_DOUBLE ) { shadelight[1] = 1.0; shadelight[2] = 1.0; } else { shadelight[2] = 1.0; } } else if ( currententity->flags & RF_SHELL_DOUBLE ) { shadelight[0] = 0.9; shadelight[1] = 0.7; } } else if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN ) ) { VectorClear (shadelight); // PMM - new colors if ( currententity->flags & RF_SHELL_HALF_DAM ) { shadelight[0] = 0.56; shadelight[1] = 0.59; shadelight[2] = 0.45; } if ( currententity->flags & RF_SHELL_GREEN ) { shadelight[1] = 1.0; } } } //PMM - ok, now flatten these down to range from 0 to 1.0. // max_shell_val = max(shadelight[0], max(shadelight[1], shadelight[2])); // if (max_shell_val > 0) // { // for (i=0; i<3; i++) // { // shadelight[i] = shadelight[i] / max_shell_val; // } // } // pmm else if ( currententity->flags & RF_FULLBRIGHT ) { for (i=0 ; i<3 ; i++) shadelight[i] = 1.0; } else { R_LightPoint (currententity->origin, shadelight); // player lighting hack for communication back to server // big hack! if ( currententity->flags & RF_WEAPONMODEL ) { // pick the greatest component, which should be the same // as the mono value returned by software if (shadelight[0] > shadelight[1]) { if (shadelight[0] > shadelight[2]) r_lightlevel->value = 150*shadelight[0]; else r_lightlevel->value = 150*shadelight[2]; } else { if (shadelight[1] > shadelight[2]) r_lightlevel->value = 150*shadelight[1]; else r_lightlevel->value = 150*shadelight[2]; } } if ( gl_monolightmap->string[0] != '0' ) { float s = shadelight[0]; if ( s < shadelight[1] ) s = shadelight[1]; if ( s < shadelight[2] ) s = shadelight[2]; shadelight[0] = s; shadelight[1] = s; shadelight[2] = s; } } if ( currententity->flags & RF_MINLIGHT ) { for (i=0 ; i<3 ; i++) if (shadelight[i] > 0.1) break; if (i == 3) { shadelight[0] = 0.1; shadelight[1] = 0.1; shadelight[2] = 0.1; } } if ( currententity->flags & RF_GLOW ) { // bonus items will pulse with time float scale; float min; scale = 0.1 * sin(r_newrefdef.time*7); for (i=0 ; i<3 ; i++) { min = shadelight[i] * 0.8; shadelight[i] += scale; if (shadelight[i] < min) shadelight[i] = min; } } // ================= // PGM ir goggles color override if ( r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE) { shadelight[0] = 1.0; shadelight[1] = 0.0; shadelight[2] = 0.0; } // PGM // ================= shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; an = currententity->angles[1]/180*M_PI; shadevector[0] = cos(-an); shadevector[1] = sin(-an); shadevector[2] = 1; VectorNormalize (shadevector); // // locate the proper data // c_alias_polys += paliashdr->num_tris; // // draw all the triangles // if (currententity->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) ) { extern void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ); qglMatrixMode( GL_PROJECTION ); qglPushMatrix(); qglLoadIdentity(); qglScalef( -1, 1, 1 ); MYgluPerspective( r_newrefdef.fov_y, ( float ) r_newrefdef.width / r_newrefdef.height, 4, 4096); qglMatrixMode( GL_MODELVIEW ); qglCullFace( GL_BACK ); } qglPushMatrix (); e->angles[PITCH] = -e->angles[PITCH]; // sigh. R_RotateForEntity (e); e->angles[PITCH] = -e->angles[PITCH]; // sigh. // select skin if (currententity->skin) skin = currententity->skin; // custom player skin else { if (currententity->skinnum >= MAX_MD2SKINS) skin = currentmodel->skins[0]; else { skin = currentmodel->skins[currententity->skinnum]; if (!skin) skin = currentmodel->skins[0]; } } if (!skin) skin = r_notexture; // fallback... GL_Bind(skin->texnum); // draw it qglShadeModel (GL_SMOOTH); GL_TexEnv( GL_MODULATE ); if ( currententity->flags & RF_TRANSLUCENT ) { qglEnable (GL_BLEND); } if ( (currententity->frame >= paliashdr->num_frames) || (currententity->frame < 0) ) { ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such frame %d\n", currentmodel->name, currententity->frame); currententity->frame = 0; currententity->oldframe = 0; } if ( (currententity->oldframe >= paliashdr->num_frames) || (currententity->oldframe < 0)) { ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n", currentmodel->name, currententity->oldframe); currententity->frame = 0; currententity->oldframe = 0; } if ( !r_lerpmodels->value ) currententity->backlerp = 0; GL_DrawAliasFrameLerp (paliashdr, currententity->backlerp); GL_TexEnv( GL_REPLACE ); qglShadeModel (GL_FLAT); qglPopMatrix (); #if 0 qglDisable( GL_CULL_FACE ); qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); qglDisable( GL_TEXTURE_2D ); qglBegin( GL_TRIANGLE_STRIP ); for ( i = 0; i < 8; i++ ) { qglVertex3fv( bbox[i] ); } qglEnd(); qglEnable( GL_TEXTURE_2D ); qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); qglEnable( GL_CULL_FACE ); #endif if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) ) { qglMatrixMode( GL_PROJECTION ); qglPopMatrix(); qglMatrixMode( GL_MODELVIEW ); qglCullFace( GL_FRONT ); } if ( currententity->flags & RF_TRANSLUCENT ) { qglDisable (GL_BLEND); } if (currententity->flags & RF_DEPTHHACK) qglDepthRange (gldepthmin, gldepthmax); #if 1 if (gl_shadows->value && !(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL))) { qglPushMatrix (); R_RotateForEntity (e); qglDisable (GL_TEXTURE_2D); qglEnable (GL_BLEND); qglColor4f (0,0,0,0.5); GL_DrawAliasShadow (paliashdr, currententity->frame ); qglEnable (GL_TEXTURE_2D); qglDisable (GL_BLEND); qglPopMatrix (); } #endif qglColor4f (1,1,1,1); }
void R_AliasSetupLighting_enhanced (alight_t *plighting) { float fakegrid; // leilei float lightvec[3]; float rlightvec[3]; float glightvec[3]; float blightvec[3]; float colr; float colg; float colb; vec3_t dist; vec3_t distr, distg, distb; float add, radd, gadd, badd; float amblevel, shadlevel; int lnum; dlight_t *dl; vec3_t t; //begin lightvec[0] = 0; lightvec[1] = 0; lightvec[2] = 0; if (coloredlights){ rlightvec[0] = 0; rlightvec[1] = 0; rlightvec[2] = 0; glightvec[0] = 0; glightvec[1] = 0; glightvec[2] = 0; blightvec[0] = 0; blightvec[1] = 0; blightvec[2] = 0; } VectorCopy(currententity->origin, t); r_shadelight = R_LightPoint (t); r_rlight = lightcolor[0]; r_glight = lightcolor[1]; r_blight = lightcolor[2]; if (r_shading->value == 3){ amblevel = 0.01; r_shadelight = r_ambientlight * amblevel ; r_rlight = r_ramb * amblevel; r_glight = r_gamb * amblevel; r_blight = r_bamb * amblevel; shadlevel = 3.4; } else{ amblevel = 0.3; shadlevel = 1; } // add dynamic lights including world lights for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++) { float scale, scaler, scaleg, scaleb; dl = &cl_dlights[lnum]; if (!dl->radius) continue; if (dl->die < cl.time) continue; colr = dl->color[0]; colg = dl->color[1]; colb = dl->color[2]; VectorSubtract (t, dl->origin, dist); VectorSubtract (t, dl->origin, distr); VectorSubtract (t, dl->origin, distg); VectorSubtract (t, dl->origin, distb); add = dl->radius - Length(dist); radd = dl->radius * colr - Length(distr); gadd = dl->radius * colg - Length(distg); badd = dl->radius * colb - Length(distb); scale = 1.0-(Length(dist)/dl->radius); if (dl->unmark) scale *= scale * 0.1f * shadlevel; // leilei - have soft lighting for world else scale *= scale * 0.4f * shadlevel; // leilei - slightly more harsh for dyn lights scaler = 1-(Length(distr)/dl->radius); scaleg = 1-(Length(distg)/dl->radius); scaleb = 1-(Length(distb)/dl->radius); if (dl->unmark){ scaler *= scaler * 0.054f * shadlevel; scaleg *= scaleg * 0.054f * shadlevel; scaleb *= scaleb * 0.054f * shadlevel; } else { if (r_shading->value == 3){ scaler *= scaler * (0.054f) * shadlevel; scaleg *= scaleg * (0.054f) * shadlevel; scaleb *= scaleb * (0.054f) * shadlevel; } else { scaler *= scaler * (0.44f) * shadlevel; scaleg *= scaleg * (0.44f) * shadlevel; scaleb *= scaleb * (0.44f) * shadlevel; } } if (add > 0) { r_shadelight += add*(scale); r_rlight += radd*(scale); r_glight += gadd*(scale); r_blight += badd*(scale); VectorScale (dist, scale, dist); VectorScale (distr, scaler, distr); VectorScale (distg, scaleg, distg); VectorScale (distb, scaleb, distb); if (dl->dark) { VectorSubtract(lightvec, dist, lightvec); } else{ VectorAdd(lightvec, dist, lightvec); VectorAdd(rlightvec, distr, rlightvec); VectorAdd(glightvec, distg, glightvec); VectorAdd(blightvec, distb, blightvec); } } } r_ambientlight = plighting->ambientlight * amblevel; r_ambientlight = (255 - r_ambientlight) << VID_CBITS; if (r_ambientlight < LIGHT_MIN) r_ambientlight = LIGHT_MIN; if (r_shadelight < 0) r_shadelight = 0; else r_shadelight = (float)(r_shadelight * VID_GRADES); r_rlight = (float)(r_rlight * VID_GRADES); r_glight = (float)(r_glight * VID_GRADES); r_blight = (float)(r_blight * VID_GRADES); // rotate the lighting vector into the model's frame of reference r_plightvec[0] = DotProduct (lightvec, alias_forward); r_plightvec[1] = -DotProduct (lightvec, alias_right); r_plightvec[2] = DotProduct (lightvec, alias_up); if (coloredlights){ r_ramb = plighting->ramb* amblevel; r_gamb = plighting->gamb* amblevel; r_bamb = plighting->bamb* amblevel; if (r_ramb < 0) r_ramb = 0; if (r_gamb < 0) r_gamb = 0; if (r_bamb < 0) r_bamb = 0; r_ramb = (255 - r_ramb)<< VID_CBITS; if (r_ramb < LIGHT_MIN) r_ramb = LIGHT_MIN; r_gamb = (255 - r_gamb)<< VID_CBITS; if (r_gamb < LIGHT_MIN) r_gamb = LIGHT_MIN; r_bamb = (255 - r_bamb)<< VID_CBITS; if (r_bamb < LIGHT_MIN) r_bamb = LIGHT_MIN; r_rlightvec[0] = DotProduct (rlightvec, alias_forward); r_rlightvec[1] = -DotProduct (rlightvec, alias_right); r_rlightvec[2] = DotProduct (rlightvec, alias_up); r_glightvec[0] = DotProduct (glightvec, alias_forward); r_glightvec[1] = -DotProduct (glightvec, alias_right); r_glightvec[2] = DotProduct (glightvec, alias_up); r_blightvec[0] = DotProduct (blightvec, alias_forward); r_blightvec[1] = -DotProduct (blightvec, alias_right); r_blightvec[2] = DotProduct (blightvec, alias_up); } // shadow hack... { int e; for (e=0;e<3;e++){ currententity->shadowvec[e] = r_plightvec[e]; if(coloredlights){ currententity->shadowvec[e] = rlightvec[e] * 0.333; currententity->shadowvec[e] += glightvec[e] * 0.333; currententity->shadowvec[e] += blightvec[e] * 0.333; } } currententity->shadowdist; if (coloredlights) currententity->shadowopacity = currententity->shadowvec[0] + currententity->shadowvec[1] + currententity->shadowvec[2] / 6; else currententity->shadowopacity = add / 255 * -1; } };
/* ================= R_DrawAliasModel ================= */ void R_DrawAliasModel (entity_t *e) { int i; dmdl_t *hdr; float an; vec3_t bbox[8]; image_t *skin; float lightspot[3]; if (!(e->flags & RF_WEAPONMODEL)) { if (R_CullAliasModel (bbox, e)) return; } if (e->flags & RF_WEAPONMODEL) { if (r_lefthand->value == 2) return; } hdr = (dmdl_t *) e->model->extradata; if (e->flags & (RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE)) { VectorClear (gl_meshuboupdate.shadelight); if (e->flags & RF_SHELL_RED) gl_meshuboupdate.shadelight[0] = 1.0; if (e->flags & RF_SHELL_GREEN) gl_meshuboupdate.shadelight[1] = 1.0; if (e->flags & RF_SHELL_BLUE) gl_meshuboupdate.shadelight[2] = 1.0; } else if (e->flags & RF_FULLBRIGHT) { gl_meshuboupdate.shadelight[0] = 1.0; gl_meshuboupdate.shadelight[1] = 1.0; gl_meshuboupdate.shadelight[2] = 1.0; } else { dlight_t *l; int i; // grab static lighting from lightmap R_LightPoint (e->currorigin, gl_meshuboupdate.shadelight, lightspot); // grab dynamic lighting glProgramUniform1i (gl_meshprog, u_meshMaxLights, r_newrefdef.num_dlights); glProgramUniform3fv (gl_meshprog, u_meshEntOrig, 1, e->currorigin); for (i = 0, l = r_newrefdef.dlights; i < r_newrefdef.num_dlights; i++, l++) { glProgramUniform3fv (gl_meshprog, u_meshLightPos[i], 1, l->origin); glProgramUniform3fv (gl_meshprog, u_meshLightColor[i], 1, l->color); glProgramUniform1f (gl_meshprog, u_meshLightAtten[i], l->radius); } // player lighting hack for communication back to server // big hack! if (e->flags & RF_WEAPONMODEL) { // pick the greatest component, which should be the same // as the mono value returned by software if (gl_meshuboupdate.shadelight[0] > gl_meshuboupdate.shadelight[1]) { if (gl_meshuboupdate.shadelight[0] > gl_meshuboupdate.shadelight[2]) r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[0]; else r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[2]; } else { if (gl_meshuboupdate.shadelight[1] > gl_meshuboupdate.shadelight[2]) r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[1]; else r_lightlevel->value = 150 * gl_meshuboupdate.shadelight[2]; } } } if (e->flags & RF_MINLIGHT) { for (i = 0; i < 3; i++) { if (gl_meshuboupdate.shadelight[i] > 0.1) break; } if (i == 3) { gl_meshuboupdate.shadelight[0] = 0.1; gl_meshuboupdate.shadelight[1] = 0.1; gl_meshuboupdate.shadelight[2] = 0.1; } } if (e->flags & RF_GLOW) { // bonus items will pulse with time float scale; float min; scale = 0.1 * sin (r_newrefdef.time * 7); for (i = 0; i < 3; i++) { min = gl_meshuboupdate.shadelight[i] * 0.8; gl_meshuboupdate.shadelight[i] += scale; if (gl_meshuboupdate.shadelight[i] < min) gl_meshuboupdate.shadelight[i] = min; } } an = e->angles[1] / 180 * M_PI; Q_sincos (-an, &gl_meshuboupdate.shadevector[1], &gl_meshuboupdate.shadevector[0]); gl_meshuboupdate.shadevector[2] = 1; VectorNormalize (gl_meshuboupdate.shadevector); // locate the proper data c_alias_polys += hdr->num_tris; // draw all the triangles if (e->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls glDepthRange (gldepthmin, gldepthmin + 0.3 * (gldepthmax - gldepthmin)); if ((e->flags & RF_WEAPONMODEL) && (r_lefthand->value == 1.0F)) { glmatrix gunmatrix; GL_LoadIdentity (&gunmatrix); GL_ScaleMatrix (&gunmatrix, -1, 1, 1); GL_PerspectiveMatrix (&gunmatrix, r_newrefdef.fov_y, (float) r_newrefdef.width / r_newrefdef.height); // eval a new mvp for left-handedness GL_LoadMatrix (&gl_meshuboupdate.localMatrix, &r_worldmatrix); GL_MultMatrix (&gl_meshuboupdate.localMatrix, &gl_meshuboupdate.localMatrix, &gunmatrix); glCullFace (GL_BACK); } else GL_LoadMatrix (&gl_meshuboupdate.localMatrix, &r_mvpmatrix); GL_TranslateMatrix (&gl_meshuboupdate.localMatrix, e->currorigin[0], e->currorigin[1], e->currorigin[2]); GL_RotateMatrix (&gl_meshuboupdate.localMatrix, e->angles[1], 0, 0, 1); GL_RotateMatrix (&gl_meshuboupdate.localMatrix, e->angles[0], 0, 1, 0); GL_RotateMatrix (&gl_meshuboupdate.localMatrix, -e->angles[2], 1, 0, 0); // select skin if (e->skin) skin = e->skin; // custom player skin else { if (e->skinnum >= MAX_MD2SKINS) skin = e->model->skins[0]; else { skin = e->model->skins[e->skinnum]; if (!skin) skin = e->model->skins[0]; } } if (!skin) skin = r_notexture; // fallback... GL_BindTexture (GL_TEXTURE0, GL_TEXTURE_2D, r_modelsampler, skin->texnum); if ((e->currframe >= hdr->num_frames) || (e->currframe < 0)) { VID_Printf (PRINT_ALL, S_COLOR_RED "R_DrawAliasModel %s: no such frame %d\n", e->model->name, e->currframe); e->currframe = 0; e->lastframe = 0; } if ((e->lastframe >= hdr->num_frames) || (e->lastframe < 0)) { VID_Printf (PRINT_ALL, S_COLOR_RED "R_DrawAliasModel %s: no such oldframe %d\n", e->model->name, e->lastframe); e->currframe = 0; e->lastframe = 0; } if (!r_lerpmodels->value) e->backlerp = 0; GL_DrawAliasFrameLerp (e, hdr, e->backlerp); if ((e->flags & RF_WEAPONMODEL) && (r_lefthand->value == 1.0F)) { glCullFace (GL_FRONT); } if (e->flags & RF_DEPTHHACK) glDepthRange (gldepthmin, gldepthmax); }