/* ================= 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 // PMM - 3.20 code .. replaced with original way of doing it to keep mod authors happy // 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; } /* // 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. e->angles[ROLL] = e->angles[ROLL] * R_RollMult(); // Knightmare- roll is backwards R_RotateForEntity (e, true); e->angles[PITCH] = -e->angles[PITCH]; // sigh. e->angles[ROLL] = e->angles[ROLL] * R_RollMult(); // Knightmare- roll is backwards // 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 1 if (gl_showbbox->value) // Knightmare- show bbox option { qglColor4f (1.0f, 1.0f, 1.0f, 1.0f); 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();*/ qglBegin( GL_QUADS ); qglVertex3fv( bbox[0] ); qglVertex3fv( bbox[1] ); qglVertex3fv( bbox[3] ); qglVertex3fv( bbox[2] ); qglVertex3fv( bbox[4] ); qglVertex3fv( bbox[5] ); qglVertex3fv( bbox[7] ); qglVertex3fv( bbox[6] ); qglVertex3fv( bbox[0] ); qglVertex3fv( bbox[1] ); qglVertex3fv( bbox[5] ); qglVertex3fv( bbox[4] ); qglVertex3fv( bbox[2] ); qglVertex3fv( bbox[3] ); qglVertex3fv( bbox[7] ); qglVertex3fv( bbox[6] ); 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 (gl_shadows->value && !(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL))) { // qglPushMatrix (); // R_RotateForEntity (e, false); // qglDisable (GL_TEXTURE_2D); // qglEnable (GL_BLEND); // qglColor4f (0, 0, 0, gl_shadowalpha->value); // was 0.5 GL_DrawAliasShadow (e, paliashdr, currententity->frame ); // qglEnable (GL_TEXTURE_2D); // qglDisable (GL_BLEND); // qglPopMatrix (); } qglColor4f (1,1,1,1); }
/* ** GL_SetDefaultState */ void GL_SetDefaultState( void ) { glClearDepth( 1.0f ); glCullFace( GL_FRONT ); glColor4f( 1, 1, 1, 1 ); // initialize downstream texture unit if we're running // in a multitexture environment if ( GLEW_ARB_multitexture ) { GL_SelectTexture( 1 ); GL_TextureMode( r_textureMode->string ); GL_TextureAnisotropy( r_textureAnisotropy->value ); GL_TexEnv( GL_MODULATE ); glDisable( GL_TEXTURE_2D ); GL_SelectTexture( 0 ); } glEnable( GL_TEXTURE_2D ); GL_TextureMode( r_textureMode->string ); GL_TextureAnisotropy( r_textureAnisotropy->value ); GL_TexEnv( GL_MODULATE ); glShadeModel( GL_SMOOTH ); glDepthFunc( GL_LEQUAL ); // the vertex array is always enabled, but the color and texture // arrays are enabled and disabled around the compiled vertex array call glEnableClientState( GL_VERTEX_ARRAY ); // // make sure our GL state vector is set correctly // glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE; glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); glDepthMask( GL_TRUE ); glDisable( GL_DEPTH_TEST ); glEnable( GL_SCISSOR_TEST ); glDisable( GL_CULL_FACE ); glDisable( GL_BLEND ); //----(SA) added. #if 0 // ATI pn_triangles if ( GLEW_ATI_pn_triangles ) { int maxtess; // get max supported tesselation glGetIntegerv( GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI, ( GLint * ) &maxtess ); #ifdef __MACOS__ glConfig.ATIMaxTruformTess = 7; #else glConfig.ATIMaxTruformTess = maxtess; #endif // cap if necessary if ( r_ati_truform_tess->value > maxtess ) { ri.Cvar_Set( "r_ati_truform_tess", va( "%d", maxtess ) ); } // set Wolf defaults glPNTrianglesfATI( GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, r_ati_truform_tess->value ); } #endif if ( glConfig.anisotropicAvailable ) { float maxAnisotropy; glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy ); glConfig.maxAnisotropy = maxAnisotropy; // set when rendering // glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glConfig.maxAnisotropy); } //----(SA) end }
/* ============= R_DrawScaledImage Psychospaz's code for drawing stretched crosshairs ============= */ void R_DrawScaledImage (int32_t x, int32_t y, float scale, float alpha, image_t *gl) { float xoff, yoff; float scale_x, scale_y; int32_t i; vec2_t texCoord[4], verts[4]; if (scrap_dirty) Scrap_Upload (); // add alpha support if (gl->has_alpha || alpha < 1.0) { GL_Disable (GL_ALPHA_TEST); GL_TexEnv (GL_MODULATE); GL_Enable (GL_BLEND); GL_DepthMask (false); } GL_Bind (gl->texnum); scale_x = scale_y = scale; scale_x *= gl->replace_scale_w; // scale down if replacing a pcx image scale_y *= gl->replace_scale_h; // scale down if replacing a pcx image Vector2Set(texCoord[0], gl->sl, gl->tl); Vector2Set(texCoord[1], gl->sh, gl->tl); Vector2Set(texCoord[2], gl->sh, gl->th); Vector2Set(texCoord[3], gl->sl, gl->th); xoff = gl->width*scale_x-gl->width; yoff = gl->height*scale_y-gl->height; Vector2Set(verts[0], x, y); Vector2Set(verts[1], x+gl->width+xoff, y); Vector2Set(verts[2], x+gl->width+xoff, y+gl->height+yoff); Vector2Set(verts[3], x, y+gl->height+yoff); rb_vertex = rb_index = 0; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+1; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+3; for (i=0; i<4; i++) { VA_SetElem2(texCoordArray[0][rb_vertex], texCoord[i][0], texCoord[i][1]); VA_SetElem3(vertexArray[rb_vertex], verts[i][0], verts[i][1], 0); VA_SetElem4(colorArray[rb_vertex], 1.0, 1.0, 1.0, alpha); rb_vertex++; } RB_RenderMeshGeneric (false); if (gl->has_alpha || alpha < 1.0) { GL_DepthMask (true); GL_TexEnv (GL_REPLACE); GL_Disable (GL_BLEND); GL_Enable (GL_ALPHA_TEST); // add alpha support } }
void R_DrawCameraEffect (void) { image_t *image[2]; int32_t x, y, w, h, i, j; float texparms[2][4]; vec2_t texCoord[4]; vec3_t verts[4]; renderparms_t cameraParms; image[0] = R_DrawFindPic ("/gfx/2d/screenstatic.tga"); image[1] = R_DrawFindPic ("/gfx/2d/scanlines.tga"); if (!image[0] || !image[1]) return; x = y = 0; w = vid.width; h = vid.height; GL_Disable (GL_ALPHA_TEST); GL_TexEnv (GL_MODULATE); GL_Enable (GL_BLEND); GL_BlendFunc (GL_DST_COLOR, GL_SRC_COLOR); GL_DepthMask (false); VectorSet(verts[0], x, y, 0); VectorSet(verts[1], x+w, y, 0); VectorSet(verts[2], x+w, y+h, 0); VectorSet(verts[3], x, y+h, 0); Vector4Set(texparms[0], 2, 2, -30, 10); Vector4Set(texparms[1], 1, 10, 0, 0); rb_vertex = rb_index = 0; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+1; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+3; rb_vertex = 4; for (i=0; i<2; i++) { GL_Bind (image[i]->texnum); Vector2Set(texCoord[0], x/image[i]->width, y/image[i]->height); Vector2Set(texCoord[1], (x+w)/image[i]->width, y/image[i]->height); Vector2Set(texCoord[2], (x+w)/image[i]->width, (y+h)/image[i]->height); Vector2Set(texCoord[3], x/image[i]->width, (y+h)/image[i]->height); Mod_SetRenderParmsDefaults (&cameraParms); cameraParms.scale_x = texparms[i][0]; cameraParms.scale_y = texparms[i][1]; cameraParms.scroll_x = texparms[i][2]; cameraParms.scroll_y = texparms[i][3]; RB_ModifyTextureCoords (&texCoord[0][0], &verts[0][0], 4, cameraParms); for (j=0; j<4; j++) { VA_SetElem2(texCoordArray[0][j], texCoord[j][0], texCoord[j][1]); VA_SetElem3(vertexArray[j], verts[j][0], verts[j][1], verts[j][2]); VA_SetElem4(colorArray[j], 1, 1, 1, 1); } RB_DrawArrays (); } rb_vertex = rb_index = 0; GL_DepthMask (true); GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GL_Disable (GL_BLEND); GL_TexEnv (GL_REPLACE); GL_Enable (GL_ALPHA_TEST); }
static void ProjectDlightTexture( void ) { int i, l; vec3_t origin; float *texCoords; byte *colors; byte clipBits[SHADER_MAX_VERTEXES]; float texCoordsArray[SHADER_MAX_VERTEXES][2]; byte colorArray[SHADER_MAX_VERTEXES][4]; glIndex_t hitIndexes[SHADER_MAX_INDEXES]; int numIndexes; float scale; float radius; int fogging; vec3_t floatColor; shaderStage_t *dStage; if ( !backEnd.refdef.num_dlights ) { return; } for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { dlight_t *dl; if ( !( tess.dlightBits & ( 1 << l ) ) ) { continue; // this surface definately doesn't have any of this light } texCoords = texCoordsArray[0]; colors = colorArray[0]; dl = &backEnd.refdef.dlights[l]; VectorCopy( dl->transformed, origin ); radius = dl->radius; scale = 1.0f / radius; floatColor[0] = dl->color[0] * 255.0f; floatColor[1] = dl->color[1] * 255.0f; floatColor[2] = dl->color[2] * 255.0f; for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) { vec3_t dist; int clip; float modulate; backEnd.pc.c_dlightVertexes++; VectorSubtract( origin, tess.xyz[i], dist ); int l = 1; int bestIndex = 0; float greatest = tess.normal[i][0]; if (greatest < 0.0f) { greatest = -greatest; } if (VectorCompare(tess.normal[i], vec3_origin)) { //damn you terrain! bestIndex = 2; } else { while (l < 3) { if ((tess.normal[i][l] > greatest && tess.normal[i][l] > 0.0f) || (tess.normal[i][l] < -greatest && tess.normal[i][l] < 0.0f)) { greatest = tess.normal[i][l]; if (greatest < 0.0f) { greatest = -greatest; } bestIndex = l; } l++; } } float dUse = 0.0f; const float maxScale = 1.5f; const float maxGroundScale = 1.4f; const float lightScaleTolerance = 0.1f; if (bestIndex == 2) { dUse = origin[2]-tess.xyz[i][2]; if (dUse < 0.0f) { dUse = -dUse; } dUse = (radius*0.5f)/dUse; if (dUse > maxGroundScale) { dUse = maxGroundScale; } else if (dUse < 0.1f) { dUse = 0.1f; } if (VectorCompare(tess.normal[i], vec3_origin) || tess.normal[i][0] > lightScaleTolerance || tess.normal[i][0] < -lightScaleTolerance || tess.normal[i][1] > lightScaleTolerance || tess.normal[i][1] < -lightScaleTolerance) { //if not perfectly flat, we must use a constant dist scale = 1.0f / radius; } else { scale = 1.0f / (radius*dUse); } texCoords[0] = 0.5f + dist[0] * scale; texCoords[1] = 0.5f + dist[1] * scale; } else if (bestIndex == 1) { dUse = origin[1]-tess.xyz[i][1]; if (dUse < 0.0f) { dUse = -dUse; } dUse = (radius*0.5f)/dUse; if (dUse > maxScale) { dUse = maxScale; } else if (dUse < 0.1f) { dUse = 0.1f; } if (tess.normal[i][0] > lightScaleTolerance || tess.normal[i][0] < -lightScaleTolerance || tess.normal[i][2] > lightScaleTolerance || tess.normal[i][2] < -lightScaleTolerance) { //if not perfectly flat, we must use a constant dist scale = 1.0f / radius; } else { scale = 1.0f / (radius*dUse); } texCoords[0] = 0.5f + dist[0] * scale; texCoords[1] = 0.5f + dist[2] * scale; } else { dUse = origin[0]-tess.xyz[i][0]; if (dUse < 0.0f) { dUse = -dUse; } dUse = (radius*0.5f)/dUse; if (dUse > maxScale) { dUse = maxScale; } else if (dUse < 0.1f) { dUse = 0.1f; } if (tess.normal[i][2] > lightScaleTolerance || tess.normal[i][2] < -lightScaleTolerance || tess.normal[i][1] > lightScaleTolerance || tess.normal[i][1] < -lightScaleTolerance) { //if not perfectly flat, we must use a constant dist scale = 1.0f / radius; } else { scale = 1.0f / (radius*dUse); } texCoords[0] = 0.5f + dist[1] * scale; texCoords[1] = 0.5f + dist[2] * scale; } clip = 0; if ( texCoords[0] < 0.0f ) { clip |= 1; } else if ( texCoords[0] > 1.0f ) { clip |= 2; } if ( texCoords[1] < 0.0f ) { clip |= 4; } else if ( texCoords[1] > 1.0f ) { clip |= 8; } // modulate the strength based on the height and color if ( dist[bestIndex] > radius ) { clip |= 16; modulate = 0.0f; } else if ( dist[bestIndex] < -radius ) { clip |= 32; modulate = 0.0f; } else { dist[bestIndex] = Q_fabs(dist[bestIndex]); if ( dist[bestIndex] < radius * 0.5f ) { modulate = 1.0f; } else { modulate = 2.0f * (radius - dist[bestIndex]) * scale; } } clipBits[i] = clip; colors[0] = Q_ftol(floatColor[0] * modulate); colors[1] = Q_ftol(floatColor[1] * modulate); colors[2] = Q_ftol(floatColor[2] * modulate); colors[3] = 255; } // build a list of triangles that need light numIndexes = 0; for ( i = 0 ; i < tess.numIndexes ; i += 3 ) { int a, b, c; a = tess.indexes[i]; b = tess.indexes[i+1]; c = tess.indexes[i+2]; if ( clipBits[a] & clipBits[b] & clipBits[c] ) { continue; // not lighted } hitIndexes[numIndexes] = a; hitIndexes[numIndexes+1] = b; hitIndexes[numIndexes+2] = c; numIndexes += 3; } if ( !numIndexes ) { continue; } //don't have fog enabled when we redraw with alpha test, or it will double over //and screw the tri up -rww if (r_drawfog->value == 2 && tr.world && (tess.fogNum == tr.world->globalFog || tess.fogNum == tr.world->numfogs)) { fogging = qglIsEnabled(GL_FOG); if (fogging) { qglDisable(GL_FOG); } } else { fogging = 0; } dStage = NULL; if (tess.shader && qglActiveTextureARB) { int i = 0; while (i < tess.shader->numUnfoggedPasses) { const int blendBits = (GLS_SRCBLEND_BITS+GLS_DSTBLEND_BITS); if (((tess.shader->stages[i].bundle[0].image && !tess.shader->stages[i].bundle[0].isLightmap && !tess.shader->stages[i].bundle[0].numTexMods) || (tess.shader->stages[i].bundle[1].image && !tess.shader->stages[i].bundle[1].isLightmap && !tess.shader->stages[i].bundle[1].numTexMods)) && (tess.shader->stages[i].stateBits & blendBits) == 0 ) { //only use non-lightmap opaque stages dStage = &tess.shader->stages[i]; break; } i++; } } if (dStage) { GL_SelectTexture( 0 ); GL_State(0); qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] ); if (dStage->bundle[0].image && !dStage->bundle[0].isLightmap && !dStage->bundle[0].numTexMods) { R_BindAnimatedImage( &dStage->bundle[0] ); } else { R_BindAnimatedImage( &dStage->bundle[1] ); } GL_SelectTexture( 1 ); qglEnable( GL_TEXTURE_2D ); qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] ); qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray ); GL_Bind( tr.dlightImage ); GL_TexEnv( GL_MODULATE ); GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL);// | GLS_ATEST_GT_0); R_DrawElements( numIndexes, hitIndexes ); qglDisable( GL_TEXTURE_2D ); GL_SelectTexture(0); } else { qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] ); qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray ); GL_Bind( tr.dlightImage ); // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light // where they aren't rendered if ( dl->additive ) { GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } else { GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } R_DrawElements( numIndexes, hitIndexes ); } if (fogging) { qglEnable(GL_FOG); } backEnd.pc.c_totalIndexes += numIndexes; backEnd.pc.c_dlightIndexes += numIndexes; } }
/* =================== DrawMultitextured output = t0 * t1 or t0 + t1 t0 = most upstream according to spec t1 = most downstream according to spec =================== */ static void DrawMultitextured(shaderCommands_t * input, int stage) { shaderStage_t *pStage; pStage = tess.xstages[stage]; // Ridah if(tess.shader->noFog && pStage->isFogged) { R_FogOn(); } else if(tess.shader->noFog && !pStage->isFogged) { R_FogOff(); // turn it back off } else { // make sure it's on R_FogOn(); } // done. GL_State(pStage->stateBits); // this is an ugly hack to work around a GeForce driver // bug with multitexture and clip planes if(backEnd.viewParms.isPortal) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } // // base // GL_SelectTexture(0); glTexCoordPointer(2, GL_FLOAT, 0, input->svars.texcoords[0]); R_BindAnimatedImage(&pStage->bundle[0]); // // lightmap/secondary pass // GL_SelectTexture(1); glEnable(GL_TEXTURE_2D); glEnableClientState(GL_TEXTURE_COORD_ARRAY); if(r_lightmap->integer) { GL_TexEnv(GL_REPLACE); } else { GL_TexEnv(tess.shader->multitextureEnv); } glTexCoordPointer(2, GL_FLOAT, 0, input->svars.texcoords[1]); R_BindAnimatedImage(&pStage->bundle[1]); R_DrawElements(input->numIndexes, input->indexes); // // disable texturing on TEXTURE1, then select TEXTURE0 // //glDisableClientState( GL_TEXTURE_COORD_ARRAY ); glDisable(GL_TEXTURE_2D); GL_SelectTexture(0); }
/* ================= R_Bloom_GeneratexDiamonds ================= */ void R_Bloom_GeneratexDiamonds( refdef_t *fd ) { int i, j; static float intensity; //set up sample size workspace qglViewport( 0, 0, sample_width, sample_height ); qglMatrixMode( GL_PROJECTION ); qglLoadIdentity (); qglOrtho(0, sample_width, sample_height, 0, -10, 100); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity (); //copy small scene into r_bloomeffecttexture GL_Bind(r_bloomeffecttexture->texnum); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); //start modifying the small scene corner qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); GL_Enable(GL_BLEND); //Com_Printf("%d %d\n", r_bloom_darken->value, fd->bloomdarken); //darkening passes if( r_bloom_darken->value ) { GL_BlendFunc(GL_DST_COLOR, GL_ZERO); GL_TexEnv(GL_MODULATE); for(i=0; i< r_bloom_darken->value ; i++) { R_Bloom_SamplePass( 0, 0 ); } qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); } //bluring passes //GL_BlendFunc(GL_ONE, GL_ONE); GL_BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); if( r_bloom_diamond_size->value > 7 || r_bloom_diamond_size->value <= 3) { if( (int)r_bloom_diamond_size->value != 8 ) Cvar_SetValue( "r_bloom_diamond_size", 8 ); for(i=0; i<r_bloom_diamond_size->value; i++) { for(j=0; j<r_bloom_diamond_size->value; j++) { intensity = /*bc mod*/(fd->bloomintensity + r_bloom_intensity->value) * 0.3 * Diamond8x[i][j]; if( intensity < r_bloom_threshold->value ) continue; qglColor4f( intensity, intensity, intensity, 1.0); R_Bloom_SamplePass( i-4, j-4 ); } } } else if( r_bloom_diamond_size->value > 5 ) { if( r_bloom_diamond_size->value != 6 ) Cvar_SetValue( "r_bloom_diamond_size", 6 ); for(i=0; i<r_bloom_diamond_size->value; i++) { for(j=0; j<r_bloom_diamond_size->value; j++) { intensity = /*bc mod*/(fd->bloomintensity + r_bloom_intensity->value) * 0.5 * Diamond6x[i][j]; if( intensity < r_bloom_threshold->value ) continue; qglColor4f( intensity, intensity, intensity, 1.0); R_Bloom_SamplePass( i-3, j-3 ); } } } else if( r_bloom_diamond_size->value > 3 ) { if( (int)r_bloom_diamond_size->value != 4 ) Cvar_SetValue( "r_bloom_diamond_size", 4 ); for(i=0; i<r_bloom_diamond_size->value; i++) { for(j=0; j<r_bloom_diamond_size->value; j++) { intensity = /*bc mod*/(fd->bloomintensity + r_bloom_intensity->value) * 0.8f * Diamond4x[i][j]; if( intensity < r_bloom_threshold->value ) continue; qglColor4f( intensity, intensity, intensity, 1.0); R_Bloom_SamplePass( i-2, j-2 ); } } } qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); //restore full screen workspace qglViewport( 0, 0, vid.width, vid.height ); qglMatrixMode( GL_PROJECTION ); qglLoadIdentity (); qglOrtho(0, vid.width, vid.height, 0, -10, 100); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity (); }
void RB_StageIteratorLightmappedMultitexture( void ) { shaderCommands_t *input; shader_t *shader; input = &tess; shader = input->shader; // // log this call // if ( r_logFile->integer ) { // don't just call LogComment, or we will get // a call to va() every frame! GLimp_LogComment( va("--- RB_StageIteratorLightmappedMultitexture( %s ) ---\n", tess.shader->name) ); } // // set face culling appropriately // GL_Cull( shader->cullType ); // // set color, pointers, and lock // GL_State( GLS_DEFAULT ); qglVertexPointer( 3, GL_FLOAT, 16, input->xyz ); #ifdef REPLACE_MODE qglDisableClientState( GL_COLOR_ARRAY ); qglColor3f( 1, 1, 1 ); qglShadeModel( GL_FLAT ); #else qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.constantColor255 ); #endif // // select base stage // GL_SelectTexture( 0 ); qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); R_BindAnimatedImage( &tess.xstages[0]->bundle[0] ); qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][0] ); // // configure second stage // GL_SelectTexture( 1 ); qglEnable( GL_TEXTURE_2D ); if ( r_lightmap->integer ) { GL_TexEnv( GL_REPLACE ); } else { GL_TexEnv( GL_MODULATE ); } R_BindAnimatedImage( &tess.xstages[0]->bundle[1] ); qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][1] ); // // lock arrays // if ( qglLockArraysEXT ) { qglLockArraysEXT(0, input->numVertexes); GLimp_LogComment( "glLockArraysEXT\n" ); } R_DrawElements( input->numIndexes, input->indexes ); // // disable texturing on TEXTURE1, then select TEXTURE0 // qglDisable( GL_TEXTURE_2D ); qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); GL_SelectTexture( 0 ); #ifdef REPLACE_MODE GL_TexEnv( GL_MODULATE ); qglShadeModel( GL_SMOOTH ); #endif // // now do any dynamic lighting needed // if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE ) { ProjectDlightTexture(); } // // now do fog // if ( tess.fogNum && tess.shader->fogPass ) { RB_FogPass(); } // // unlock arrays // if ( qglUnlockArraysEXT ) { qglUnlockArraysEXT(); GLimp_LogComment( "glUnlockArraysEXT\n" ); } }
void Draw_ScaledPic(int x, int y, float scale, float alpha, char *pic, float red, float green, float blue, qboolean fixcoords, qboolean repscale) { float xoff, yoff; image_t *gl; gl = Draw_FindPic(pic); if (!gl) { ri.Con_Printf(PRINT_ALL, "Can't find pic: %s\n", pic); return; } if (scrap_dirty) Scrap_Upload(); if (((gl_config.renderer == GL_RENDERER_MCD) || (gl_config.renderer & GL_RENDERER_RENDITION)) && !gl->has_alpha) qglDisable(GL_ALPHA_TEST); /* add alpha support */ { qglDisable(GL_ALPHA_TEST); qglBindTexture(GL_TEXTURE_2D, gl->texnum); GL_TexEnv(GL_MODULATE); qglColor4f(red, green, blue, alpha); qglEnable(GL_BLEND); qglDepthMask(false); } /* NOTE: replace this with shaders as soon as they are supported */ if (repscale) scale *= gl->replace_scale; /* scale down if replacing a pcx image */ if (fixcoords) { /* Knightmare- whether to adjust coordinates for scaling */ xoff = (gl->width * scale - gl->width) / 2; yoff = (gl->height * scale - gl->height) / 2; GL_Bind(gl->texnum); qglBegin(GL_QUADS); qglTexCoord2f(gl->sl, gl->tl); qglVertex2f(x - xoff, y - yoff); qglTexCoord2f(gl->sh, gl->tl); qglVertex2f(x + gl->width + xoff, y - yoff); qglTexCoord2f(gl->sh, gl->th); qglVertex2f(x + gl->width + xoff, y + gl->height + yoff); qglTexCoord2f(gl->sl, gl->th); qglVertex2f(x - xoff, y + gl->height + yoff); qglEnd(); } else { xoff = gl->width * scale - gl->width; yoff = gl->height * scale - gl->height; GL_Bind(gl->texnum); qglBegin(GL_QUADS); qglTexCoord2f(gl->sl, gl->tl); qglVertex2f(x, y); qglTexCoord2f(gl->sh, gl->tl); qglVertex2f(x + gl->width + xoff, y); qglTexCoord2f(gl->sh, gl->th); qglVertex2f(x + gl->width + xoff, y + gl->height + yoff); qglTexCoord2f(gl->sl, gl->th); qglVertex2f(x, y + gl->height + yoff); qglEnd(); } /* add alpha support */ { qglDepthMask(true); GL_TexEnv(GL_REPLACE); qglDisable(GL_BLEND); qglColor4f(1, 1, 1, 1); qglEnable(GL_ALPHA_TEST); } if (((gl_config.renderer == GL_RENDERER_MCD) || (gl_config.renderer & GL_RENDERER_RENDITION)) && !gl->has_alpha) qglEnable(GL_ALPHA_TEST); }
/* ================= R_Bloom_GeneratexCross - alternative bluring method ================= */ void R_Bloom_GeneratexCross( void ) { int i; static int BLOOM_BLUR_RADIUS = 8; //static float BLOOM_BLUR_INTENSITY = 2.5f; float BLOOM_BLUR_INTENSITY; static float intensity; static float range; //set up sample size workspace qglViewport( 0, 0, sample_width, sample_height ); qglMatrixMode( GL_PROJECTION ); qglLoadIdentity (); qglOrtho(0, sample_width, sample_height, 0, -10, 100); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity (); //copy small scene into r_bloomeffecttexture GL_Bind(0, r_bloomeffecttexture); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); //start modifying the small scene corner qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); GL_Enable(GL_BLEND); //darkening passes if( r_bloom_darken->value ) { GL_BlendFunc(GL_DST_COLOR, GL_ZERO); GL_TexEnv(GL_MODULATE); for(i=0; i<r_bloom_darken->value ; i++) { R_Bloom_SamplePass( 0, 0 ); } qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); } //bluring passes if( BLOOM_BLUR_RADIUS ) { GL_BlendFunc(GL_ONE, GL_ONE); range = (float)BLOOM_BLUR_RADIUS; BLOOM_BLUR_INTENSITY = r_bloom_intensity->value; //diagonal-cross draw 4 passes to add initial smooth qglColor4f( 0.5f, 0.5f, 0.5f, 1.0); R_Bloom_SamplePass( 1, 1 ); R_Bloom_SamplePass( -1, 1 ); R_Bloom_SamplePass( -1, -1 ); R_Bloom_SamplePass( 1, -1 ); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); for(i=-(BLOOM_BLUR_RADIUS+1); i<BLOOM_BLUR_RADIUS; i++) { intensity = BLOOM_BLUR_INTENSITY/(range*2+1)*(1 - fabs(i*i)/(float)(range*range)); if( intensity < 0.05f ) continue; qglColor4f( intensity, intensity, intensity, 1.0f); R_Bloom_SamplePass( i, 0 ); //R_Bloom_SamplePass( -i, 0 ); } qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); //for(i=0;i<BLOOM_BLUR_RADIUS;i++) { for(i=-(BLOOM_BLUR_RADIUS+1); i<BLOOM_BLUR_RADIUS; i++) { intensity = BLOOM_BLUR_INTENSITY/(range*2+1)*(1 - fabs(i*i)/(float)(range*range)); if( intensity < 0.05f ) continue; qglColor4f( intensity, intensity, intensity, 1.0f); R_Bloom_SamplePass( 0, i ); //R_Bloom_SamplePass( 0, -i ); } qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height); } //restore full screen workspace qglViewport( 0, 0, glState.width, glState.height ); qglMatrixMode( GL_PROJECTION ); qglLoadIdentity (); qglOrtho(0, glState.width, glState.height, 0, -10, 100); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity (); }
void R_DrawSkyBox (void) { #ifdef ENABLE_HYG_STARS R_DrawStars(); // jitstarviewer #else int i; if (fogenabled) // jitfog qgl.Disable(GL_FOG); if (skyrotate) { // check for no sky at all for (i = 0; i < 6; ++i) { if (skymins[0][i] < skymaxs[0][i] && skymins[1][i] < skymaxs[1][i]) break; } if (i == 6) return; // nothing visible } qgl.PushMatrix(); qgl.Translatef(r_origin[0], r_origin[1], r_origin[2]); qgl.Rotatef(r_newrefdef.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]); if (fogenabled && sky_images[0] == r_whitetexture) // jitfog { qgl.Color3fv(fogcolor); GLSTATE_ENABLE_BLEND GL_TexEnv(GL_MODULATE); } for (i = 0; i < 6; ++i) { if (skyrotate) { // hack, forces full sky to draw when rotating skymins[0][i] = -1; skymins[1][i] = -1; skymaxs[0][i] = 1; skymaxs[1][i] = 1; } if (skymins[0][i] >= skymaxs[0][i] || skymins[1][i] >= skymaxs[1][i]) continue; GL_Bind(sky_images[skytexorder[i]]->texnum); qgl.Begin(GL_QUADS); MakeSkyVec(skymins[0][i], skymins[1][i], i); MakeSkyVec(skymins[0][i], skymaxs[1][i], i); MakeSkyVec(skymaxs[0][i], skymaxs[1][i], i); MakeSkyVec(skymaxs[0][i], skymins[1][i], i); qgl.End(); } qgl.PopMatrix(); if (fogenabled) // jitfog { qgl.Color3f(1, 1, 1); GLSTATE_DISABLE_BLEND qgl.Enable(GL_FOG); } #endif }
// MPO : this is my version... void EmitWaterPolys (msurface_t *fa) { //============================== glpoly_t *p; glpoly_t *bp; float *v; int i; float s; float t; float os; float ot; float scroll; float rdt = r_newrefdef.time; float zValue = 0.0; // height of water qboolean waterNotFlat = false; qboolean flowing; //============================== if (g_drawing_refl) return; // we don't want any water drawn while we are doing our reflection if (fa->texinfo->flags & SURF_FLOWING) { scroll = -64.0f * ((r_newrefdef.time * 0.5f) - (int)(r_newrefdef.time * 0.5f)); flowing = true; } else { scroll = 0.0f; flowing = false; } // skip the water texture on transparent surfaces if (r_reflectivewater->value && (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))) { for (bp = fa->polys; bp; bp = bp->next) { p = bp; for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE) { // if it hasn't been initalized before if (zValue == 0.0f) zValue = v[2]; // Make sure polygons are on the same plane // Fix for not perfectly flat water on base1 - strange .. else if (fabs(zValue - v[2]) > 8.0f) waterNotFlat = true; } } } if (waterNotFlat || !r_reflectivewater->value || !(fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))) { for (bp = fa->polys; bp; bp = bp->next) { p = bp; qgl.Begin(GL_TRIANGLE_FAN); c_brush_polys += p->numverts / 3; // jitrspeeds for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE) { os = v[3]; ot = v[4]; #if !id386 s = os + r_turbsin[(int)((ot * 0.125f + r_newrefdef.time) * TURBSCALE) & 255]; #else s = os + r_turbsin[Q_ftol(((ot * 0.125f + rdt) * TURBSCALE)) & 255]; #endif s += scroll; s *= 0.015625f; // 1/64 #if !id386 t = ot + r_turbsin[(int)((os * 0.125f + rdt) * TURBSCALE) & 255]; #else t = ot + r_turbsin[Q_ftol(((os * 0.125f + rdt) * TURBSCALE)) & 255]; #endif t *= 0.015625f; // 1/64 // if it hasn't been initalized before if (zValue == 0.0f) zValue = v[2]; // Make sure polygons are on the same plane // Fix for not perfectly flat water on base1 - strange .. else if (fabs(zValue - v[2]) > 0.1f) waterNotFlat = true; qgl.TexCoord2f(s, t); qgl.Vertex3f(v[0], v[1], v[2]); } qgl.End(); } } if (waterNotFlat) return; if (r_reflectivewater->value) { #if 0 //==================== vec3_t distanceVector; float distance; //==================== #endif v = p->verts[0]; #if 0 VectorSubtract(v, r_newrefdef.vieworg, distanceVector); distance = VectorLength(distanceVector); //R_add_refl(zValue, distance); #endif R_add_refl(v[0], v[1], zValue); g_refl_enabled = true; } // find out which reflection we have that corresponds to the surface that we're drawing for (g_active_refl = 0; g_active_refl < g_num_refl; g_active_refl++) { // if we find which reflection to bind if (fabs(g_refl_Z[g_active_refl] - zValue) < 8.0f) { // === jitwater if (gl_state.fragment_program) { qgl.Enable(GL_VERTEX_PROGRAM_ARB); qgl.BindProgramARB(GL_VERTEX_PROGRAM_ARB, g_water_vertex_program_id); qgl.Enable(GL_FRAGMENT_PROGRAM_ARB); qgl.BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, g_water_fragment_program_id); GL_MBind(QGL_TEXTURE1, distort_tex->texnum); // Distortion texture GL_MBind(QGL_TEXTURE2, water_normal_tex->texnum); // Normal texture } GL_MBind(QGL_TEXTURE0, g_refl_images[g_active_refl]->texnum); // Reflection texture // jitwater === break; } } // if we found a reflective surface correctly, then go ahead and draw it if (g_active_refl != g_num_refl) { qgl.Color4f(1.0f, 1.0f, 1.0f, 1.0f); if (!gl_state.blend) qgl.Enable(GL_BLEND); GL_TexEnv(GL_MODULATE); qgl.ShadeModel(GL_SMOOTH); if (gl_state.fragment_program) { float w, h; R_GetReflTexScale(&w, &h); // Probably unnecessary qgl.ProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 0, w, h, rs_realtime * (flowing ? -0.3f : 0.2f), rs_realtime * -0.2f); qgl.ProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 1, r_newrefdef.vieworg[0], r_newrefdef.vieworg[1], r_newrefdef.vieworg[2], 1.0f); } else { // Put UV coords in screen space for rendering the reflection texture. Only need to do this when fragment programs are disabled. It's handled in the vertex shader otherwise. R_LoadReflMatrix(); } // draw reflected water layer on top of regular for (bp = fa->polys; bp; bp = bp->next) { p = bp; qgl.Begin(GL_TRIANGLE_FAN); c_brush_polys += p->numverts / 3; // jitrspeeds for (i = 0, v = p->verts[0]; i < p->numverts; ++i, v += VERTEXSIZE) { if (gl_state.fragment_program) { qgl.MultiTexCoord3fvARB(QGL_TEXTURE0, v); // Used for world space qgl.MultiTexCoord3fvARB(QGL_TEXTURE1, v + 3); // Actual texture UV's. } else { vec3_t vAngle; qgl.TexCoord3f(v[0], v[1] + CalcWave(v[0], v[1]), v[2]); if (r_newrefdef.rdflags & RDF_UNDERWATER) { VectorSubtract(v, r_newrefdef.vieworg, vAngle); VectorNormalize(vAngle); if (vAngle[2] > 0.55f) vAngle[2] = 0.55f; qgl.Color4f(1.0f, 1.0f, 1.0f, 0.9f - (vAngle[2] * 1.0f)); } else { VectorSubtract(r_newrefdef.vieworg, v, vAngle); VectorNormalize(vAngle); if (vAngle[2] > 0.55f) vAngle[2] = 0.55f; qgl.Color4f(1.0f, 1.0f, 1.0f, 0.9f - (vAngle[2] * 1.0f)); } } qgl.Vertex3f(v[0], v[1], v[2]); } qgl.End(); } R_ClearReflMatrix(); if (!gl_state.blend) qgl.Disable(GL_BLEND); if (gl_state.fragment_program) // jitwater { qgl.Disable(GL_FRAGMENT_PROGRAM_ARB); qgl.Disable(GL_VERTEX_PROGRAM_ARB); } } }
/* ============= R_DrawScaledImage Psychospaz's code for drawing stretched crosshairs ============= */ void R_DrawScaledImage (int32_t x, int32_t y, float scale, float alpha, image_t *gl) { float xoff, yoff; float scale_x, scale_y; const vec4_t color[4] = { {1.0, 1.0, 1.0, alpha}, {1.0, 1.0, 1.0, alpha}, {1.0, 1.0, 1.0, alpha}, {1.0, 1.0, 1.0, alpha} }; if (scrap_dirty) Scrap_Upload (); // add alpha support if (gl->has_alpha || alpha < 1.0) { GL_Disable (GL_ALPHA_TEST); GL_TexEnv (GL_MODULATE); GL_Enable (GL_BLEND); GL_DepthMask (false); } GL_Bind (gl->texnum); scale_x = scale_y = scale; scale_x *= gl->replace_scale_w; // scale down if replacing a pcx image scale_y *= gl->replace_scale_h; // scale down if replacing a pcx image xoff = gl->width*scale_x-gl->width; yoff = gl->height*scale_y-gl->height; rb_vertex = rb_index = 0; memcpy(indexArray, indices, sizeof(indices)); rb_index = 6; VA_SetElem2(texCoordArray[0][0], gl->sl, gl->tl); VA_SetElem2(texCoordArray[0][1], gl->sh, gl->tl); VA_SetElem2(texCoordArray[0][2], gl->sh, gl->th); VA_SetElem2(texCoordArray[0][3], gl->sl, gl->th); VA_SetElem3(vertexArray[0], x, y, 0); VA_SetElem3(vertexArray[1], x+gl->width+xoff, y, 0); VA_SetElem3(vertexArray[2], x+gl->width+xoff, y+gl->height+yoff, 0); VA_SetElem3(vertexArray[3], x, y+gl->height+yoff, 0); memcpy(colorArray, color, sizeof(vec4_t) * 4); rb_vertex = 4; RB_RenderMeshGeneric (false); if (gl->has_alpha || alpha < 1.0) { GL_DepthMask (true); GL_TexEnv (GL_REPLACE); GL_Disable (GL_BLEND); GL_Enable (GL_ALPHA_TEST); // add alpha support } }
void R_DrawSkyBox (void) { int i; #if 0 qglEnable (GL_BLEND); GL_TexEnv( GL_MODULATE ); qglColor4f (1,1,1,0.5); qglDisable (GL_DEPTH_TEST); #endif // jkrige - skybox qglDisable (GL_DEPTH_TEST); /*if (skyrotate) { // check for no sky at all for (i=0 ; i<6 ; i++) if (skymins[0][i] < skymaxs[0][i] && skymins[1][i] < skymaxs[1][i]) break; if (i == 6) return; // nothing visible }*/ // jkrige - skybox qglPushMatrix (); qglTranslatef (r_origin[0], r_origin[1], r_origin[2]); qglRotatef (r_newrefdef.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]); for (i=0 ; i<6 ; i++) { // jkrige - skybox /*if (skyrotate) { // hack, forces full sky to draw when rotating skymins[0][i] = -1; skymins[1][i] = -1; skymaxs[0][i] = 1; skymaxs[1][i] = 1; } if (skymins[0][i] >= skymaxs[0][i] || skymins[1][i] >= skymaxs[1][i]) continue;*/ // jkrige - skybox GL_Bind (sky_images[skytexorder[i]]->texnum); qglBegin (GL_QUADS); // jkrige - skybox MakeSkyVec (-1, -1, i); MakeSkyVec (-1, 1, i); MakeSkyVec (1, 1, i); MakeSkyVec (1, -1, i); //MakeSkyVec (skymins[0][i], skymins[1][i], i); //MakeSkyVec (skymins[0][i], skymaxs[1][i], i); //MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i); //MakeSkyVec (skymaxs[0][i], skymins[1][i], i); // jkrige - skybox qglEnd (); } qglPopMatrix (); #if 0 glDisable (GL_BLEND); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glColor4f (1,1,1,0.5); glEnable (GL_DEPTH_TEST); #endif // jkrige - skybox qglEnable (GL_DEPTH_TEST); // jkrige - skybox }
void R_BloomBlend ( refdef_t *fd ) { if( !(fd->rdflags & RDF_BLOOM) || !r_bloom->value || r_showtris->value ) return; if( !BLOOM_SIZE ) R_Bloom_InitTextures(); if( screen_texture_width < BLOOM_SIZE || screen_texture_height < BLOOM_SIZE ) return; //set up full screen workspace qglViewport ( 0, 0, vid.width, vid.height ); GL_TexEnv (GL_REPLACE); // Knightmare added GL_Disable (GL_DEPTH_TEST); qglMatrixMode (GL_PROJECTION); qglLoadIdentity (); qglOrtho(0, vid.width, vid.height, 0, -10, 100); qglMatrixMode (GL_MODELVIEW); qglLoadIdentity (); GL_Disable (GL_CULL_FACE); GL_Disable (GL_BLEND); qglEnable (GL_TEXTURE_2D); qglColor4f (1, 1, 1, 1); //set up current sizes curView_x = fd->x; curView_y = fd->y; curView_width = fd->width; curView_height = fd->height; screenText_tcw = ((float)fd->width / (float)screen_texture_width); screenText_tch = ((float)fd->height / (float)screen_texture_height); if( fd->height > fd->width ) { sampleText_tcw = ((float)fd->width / (float)fd->height); sampleText_tch = 1.0f; } else { sampleText_tcw = 1.0f; sampleText_tch = ((float)fd->height / (float)fd->width); } sample_width = BLOOM_SIZE * sampleText_tcw; sample_height = BLOOM_SIZE * sampleText_tch; //copy the screen space we'll use to work into the backup texture GL_Bind(r_bloombackuptexture->texnum); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, r_screenbackuptexture_size * sampleText_tcw, r_screenbackuptexture_size * sampleText_tch); //create the bloom image R_Bloom_DownsampleView(); R_Bloom_GeneratexDiamonds( fd ); //R_Bloom_GeneratexCross(); //restore the screen-backup to the screen GL_Disable(GL_BLEND); GL_Bind(r_bloombackuptexture->texnum); qglColor4f( 1, 1, 1, 1 ); R_Bloom_Quad( 0, vid.height - (r_screenbackuptexture_size * sampleText_tch), r_screenbackuptexture_size * sampleText_tcw, r_screenbackuptexture_size * sampleText_tch, sampleText_tcw, sampleText_tch ); R_Bloom_DrawEffect( fd ); // Knightmare added R_SetupGL (); GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); qglEnable (GL_TEXTURE_2D); qglColor4f(1,1,1,1); }
/* ================== RB_ARB_DrawInteraction backEnd.vLight backEnd.depthFunc must be equal for alpha tested surfaces to work right, it is set to lessThan for blended transparent surfaces ================== */ static void RB_ARB_DrawInteraction(const drawInteraction_t *din) { const drawSurf_t *surf = din->surf; const srfTriangles_t *tri = din->surf->geo; // set the vertex arrays, which may not all be enabled on a given pass idDrawVert *ac = (idDrawVert *)vertexCache.Position(tri->ambientCache); qglVertexPointer(3, GL_FLOAT, sizeof(idDrawVert), ac->xyz.ToFloatPtr()); GL_SelectTexture(0); qglTexCoordPointer(2, GL_FLOAT, sizeof(idDrawVert), (void *)&ac->st); //----------------------------------------------------- // // bump / falloff // //----------------------------------------------------- // render light falloff * bumpmap lighting // // draw light falloff to the alpha channel // GL_State(GLS_COLORMASK | GLS_DEPTHMASK | backEnd.depthFunc); qglColor3f(1, 1, 1); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); qglEnable(GL_TEXTURE_GEN_S); qglTexGenfv(GL_S, GL_OBJECT_PLANE, din->lightProjection[3].ToFloatPtr()); qglTexCoord2f(0, 0.5); // ATI R100 can't do partial texgens #define NO_MIXED_TEXGEN #ifdef NO_MIXED_TEXGEN idVec4 plane; plane[0] = 0; plane[1] = 0; plane[2] = 0; plane[3] = 0.5; qglEnable(GL_TEXTURE_GEN_T); qglTexGenfv(GL_T, GL_OBJECT_PLANE, plane.ToFloatPtr()); plane[0] = 0; plane[1] = 0; plane[2] = 0; plane[3] = 1; qglEnable(GL_TEXTURE_GEN_Q); qglTexGenfv(GL_Q, GL_OBJECT_PLANE, plane.ToFloatPtr()); #endif din->lightFalloffImage->Bind(); // draw it RB_DrawElementsWithCounters(tri); qglDisable(GL_TEXTURE_GEN_S); #ifdef NO_MIXED_TEXGEN qglDisable(GL_TEXTURE_GEN_T); qglDisable(GL_TEXTURE_GEN_Q); #endif #if 0 GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | backEnd.depthFunc); // the texccords are the non-normalized vector towards the light origin GL_SelectTexture(0); globalImages->normalCubeMapImage->Bind(); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); qglTexCoordPointer(3, GL_FLOAT, sizeof(lightingCache_t), ((lightingCache_t *)vertexCache.Position(tri->lightingCache))->localLightVector.ToFloatPtr()); // draw it RB_DrawElementsWithCounters(tri); return; #endif // we can't do bump mapping with standard calls, so skip it if (glConfig.envDot3Available && glConfig.cubeMapAvailable) { // // draw the bump map result onto the alpha channel // GL_State(GLS_SRCBLEND_DST_ALPHA | GLS_DSTBLEND_ZERO | GLS_COLORMASK | GLS_DEPTHMASK | backEnd.depthFunc); // texture 0 will be the per-surface bump map GL_SelectTexture(0); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); // FIXME: matrix work! RB_BindStageTexture( surfaceRegs, &surfaceStage->texture, surf ); din->bumpImage->Bind(); // texture 1 is the normalization cube map // the texccords are the non-normalized vector towards the light origin GL_SelectTexture(1); if (din->ambientLight) { globalImages->ambientNormalMap->Bind(); // fixed value } else { globalImages->normalCubeMapImage->Bind(); } qglEnableClientState(GL_TEXTURE_COORD_ARRAY); qglTexCoordPointer(3, GL_FLOAT, sizeof(lightingCache_t), ((lightingCache_t *)vertexCache.Position(tri->lightingCache))->localLightVector.ToFloatPtr()); // I just want alpha = Dot( texture0, texture1 ) GL_TexEnv(GL_COMBINE_ARB); qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGBA_ARB); qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1); qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1); // draw it RB_DrawElementsWithCounters(tri); GL_TexEnv(GL_MODULATE); globalImages->BindNull(); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); GL_SelectTexture(0); // RB_FinishStageTexture( &surfaceStage->texture, surf ); } //----------------------------------------------------- // // projected light / surface color for diffuse maps // //----------------------------------------------------- // don't trash alpha GL_State(GLS_SRCBLEND_DST_ALPHA | GLS_DSTBLEND_ONE | GLS_ALPHAMASK | GLS_DEPTHMASK | backEnd.depthFunc); // texture 0 will get the surface color texture GL_SelectTexture(0); // select the vertex color source if (din->vertexColor == SVC_IGNORE) { qglColor4fv(din->diffuseColor.ToFloatPtr()); } else { // FIXME: does this not get diffuseColor blended in? qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(idDrawVert), (void *)&ac->color); qglEnableClientState(GL_COLOR_ARRAY); if (din->vertexColor == SVC_INVERSE_MODULATE) { GL_TexEnv(GL_COMBINE_ARB); qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_COLOR); qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1); } } qglEnableClientState(GL_TEXTURE_COORD_ARRAY); // FIXME: does this not get the texture matrix? // RB_BindStageTexture( surfaceRegs, &surfaceStage->texture, surf ); din->diffuseImage->Bind(); // texture 1 will get the light projected texture GL_SelectTexture(1); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); qglEnable(GL_TEXTURE_GEN_S); qglEnable(GL_TEXTURE_GEN_T); qglEnable(GL_TEXTURE_GEN_Q); qglTexGenfv(GL_S, GL_OBJECT_PLANE, din->lightProjection[0].ToFloatPtr()); qglTexGenfv(GL_T, GL_OBJECT_PLANE, din->lightProjection[1].ToFloatPtr()); qglTexGenfv(GL_Q, GL_OBJECT_PLANE, din->lightProjection[2].ToFloatPtr()); din->lightImage->Bind(); // draw it RB_DrawElementsWithCounters(tri); qglDisable(GL_TEXTURE_GEN_S); qglDisable(GL_TEXTURE_GEN_T); qglDisable(GL_TEXTURE_GEN_Q); globalImages->BindNull(); GL_SelectTexture(0); if (din->vertexColor != SVC_IGNORE) { qglDisableClientState(GL_COLOR_ARRAY); GL_TexEnv(GL_MODULATE); } // RB_FinishStageTexture( &surfaceStage->texture, surf ); }
/* =================== RB_StageIteratorLightmappedMultitexture =================== */ void RB_StageIteratorLightmappedMultitexture(void) { shaderCommands_t *input = &tess; shader_t *shader = input->shader; // log this call if (r_logFile->integer) { // don't just call LogComment, or we will get // a call to va() every frame! GLimp_LogComment(va("--- RB_StageIteratorLightmappedMultitexture( %s ) ---\n", tess.shader->name)); } // set GL fog SetIteratorFog(); // set face culling appropriately GL_Cull(shader->cullType); // set color, pointers, and lock GL_State(GLS_DEFAULT); qglVertexPointer(3, GL_FLOAT, 16, input->xyz); #ifdef REPLACE_MODE qglDisableClientState(GL_COLOR_ARRAY); qglColor3f(1, 1, 1); qglShadeModel(GL_FLAT); #else qglEnableClientState(GL_COLOR_ARRAY); qglColorPointer(4, GL_UNSIGNED_BYTE, 0, tess.constantColor255); #endif // select base stage GL_SelectTexture(0); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); R_BindAnimatedImage(&tess.xstages[0]->bundle[0]); qglTexCoordPointer(2, GL_FLOAT, 8, tess.texCoords0); // configure second stage GL_SelectTexture(1); qglEnable(GL_TEXTURE_2D); if (r_lightmap->integer) { GL_TexEnv(GL_REPLACE); } else { GL_TexEnv(GL_MODULATE); } // modified for snooper if (tess.xstages[0]->bundle[1].isLightmap && (backEnd.refdef.rdflags & RDF_SNOOPERVIEW)) { GL_Bind(tr.whiteImage); } else { R_BindAnimatedImage(&tess.xstages[0]->bundle[1]); } qglEnableClientState(GL_TEXTURE_COORD_ARRAY); qglTexCoordPointer(2, GL_FLOAT, 8, tess.texCoords1); // lock arrays if (qglLockArraysEXT) { qglLockArraysEXT(0, input->numVertexes); GLimp_LogComment("glLockArraysEXT\n"); } R_DrawElements(input->numIndexes, input->indexes); // disable texturing on TEXTURE1, then select TEXTURE0 qglDisable(GL_TEXTURE_2D); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); GL_SelectTexture(0); #ifdef REPLACE_MODE GL_TexEnv(GL_MODULATE); qglShadeModel(GL_SMOOTH); #endif // now do any dynamic lighting needed //if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE ) if (tess.dlightBits && tess.shader->fogPass && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY))) { if (r_dynamiclight->integer == 2) { DynamicLightPass(); } else { DynamicLightSinglePass(); } } // now do fog if (tess.fogNum && tess.shader->fogPass) { RB_FogPass(); } // unlock arrays if (qglUnlockArraysEXT) { qglUnlockArraysEXT(); GLimp_LogComment("glUnlockArraysEXT\n"); } }
/* =================== ProjectDlightTexture Perform dynamic lighting with another rendering pass =================== */ static void ProjectDlightTexture2( void ) { int i, l; vec3_t origin; byte clipBits[SHADER_MAX_VERTEXES]; float texCoordsArray[SHADER_MAX_VERTEXES][2]; float oldTexCoordsArray[SHADER_MAX_VERTEXES][2]; float vertCoordsArray[SHADER_MAX_VERTEXES][4]; unsigned int colorArray[SHADER_MAX_VERTEXES]; glIndex_t hitIndexes[SHADER_MAX_INDEXES]; int numIndexes; float radius; int fogging; shaderStage_t *dStage; vec3_t posa; vec3_t posb; vec3_t posc; vec3_t dist; vec3_t e1; vec3_t e2; vec3_t normal; float fac,modulate; vec3_t floatColor; byte colorTemp[4]; int needResetVerts=0; if ( !backEnd.refdef.num_dlights ) { return; } for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { dlight_t *dl; if ( !( tess.dlightBits & ( 1 << l ) ) ) { continue; // this surface definately doesn't have any of this light } dl = &backEnd.refdef.dlights[l]; VectorCopy( dl->transformed, origin ); radius = dl->radius; int clipall = 63; for ( i = 0 ; i < tess.numVertexes ; i++) { int clip; VectorSubtract( origin, tess.xyz[i], dist ); clip = 0; if ( dist[0] < -radius ) { clip |= 1; } else if ( dist[0] > radius ) { clip |= 2; } if ( dist[1] < -radius ) { clip |= 4; } else if ( dist[1] > radius ) { clip |= 8; } if ( dist[2] < -radius ) { clip |= 16; } else if ( dist[2] > radius ) { clip |= 32; } clipBits[i] = clip; clipall &= clip; } if ( clipall ) { continue; // this surface doesn't have any of this light } floatColor[0] = dl->color[0] * 255.0f; floatColor[1] = dl->color[1] * 255.0f; floatColor[2] = dl->color[2] * 255.0f; // build a list of triangles that need light numIndexes = 0; for ( i = 0 ; i < tess.numIndexes ; i += 3 ) { int a, b, c; a = tess.indexes[i]; b = tess.indexes[i+1]; c = tess.indexes[i+2]; if ( clipBits[a] & clipBits[b] & clipBits[c] ) { continue; // not lighted } // copy the vertex positions VectorCopy(tess.xyz[a],posa); VectorCopy(tess.xyz[b],posb); VectorCopy(tess.xyz[c],posc); VectorSubtract( posa, posb,e1); VectorSubtract( posc, posb,e2); CrossProduct(e1,e2,normal); // rjr - removed for hacking if ( (!r_dlightBacks->integer && DotProduct(normal,origin)-DotProduct(normal,posa) <= 0.0f) || // backface if ( DotProduct(normal,origin)-DotProduct(normal,posa) <= 0.0f || // backface DotProduct(normal,normal) < 1E-8f) // junk triangle { continue; } VectorNormalize(normal); fac=DotProduct(normal,origin)-DotProduct(normal,posa); if (fac >= radius) // out of range { continue; } modulate = 1.0f-((fac*fac) / (radius*radius)); fac = 0.5f/sqrtf(radius*radius - fac*fac); // save the verts VectorCopy(posa,vertCoordsArray[numIndexes]); VectorCopy(posb,vertCoordsArray[numIndexes+1]); VectorCopy(posc,vertCoordsArray[numIndexes+2]); // now we need e1 and e2 to be an orthonormal basis if (DotProduct(e1,e1) > DotProduct(e2,e2)) { VectorNormalize(e1); CrossProduct(e1,normal,e2); } else { VectorNormalize(e2); CrossProduct(normal,e2,e1); } VectorScale(e1,fac,e1); VectorScale(e2,fac,e2); VectorSubtract( posa, origin,dist); texCoordsArray[numIndexes][0]=DotProduct(dist,e1)+0.5f; texCoordsArray[numIndexes][1]=DotProduct(dist,e2)+0.5f; VectorSubtract( posb, origin,dist); texCoordsArray[numIndexes+1][0]=DotProduct(dist,e1)+0.5f; texCoordsArray[numIndexes+1][1]=DotProduct(dist,e2)+0.5f; VectorSubtract( posc, origin,dist); texCoordsArray[numIndexes+2][0]=DotProduct(dist,e1)+0.5f; texCoordsArray[numIndexes+2][1]=DotProduct(dist,e2)+0.5f; if ((texCoordsArray[numIndexes][0] < 0.0f && texCoordsArray[numIndexes+1][0] < 0.0f && texCoordsArray[numIndexes+2][0] < 0.0f) || (texCoordsArray[numIndexes][0] > 1.0f && texCoordsArray[numIndexes+1][0] > 1.0f && texCoordsArray[numIndexes+2][0] > 1.0f) || (texCoordsArray[numIndexes][1] < 0.0f && texCoordsArray[numIndexes+1][1] < 0.0f && texCoordsArray[numIndexes+2][1] < 0.0f) || (texCoordsArray[numIndexes][1] > 1.0f && texCoordsArray[numIndexes+1][1] > 1.0f && texCoordsArray[numIndexes+2][1] > 1.0f) ) { continue; // didn't end up hitting this tri } /* old code, get from the svars = wrong oldTexCoordsArray[numIndexes][0]=tess.svars.texcoords[0][a][0]; oldTexCoordsArray[numIndexes][1]=tess.svars.texcoords[0][a][1]; oldTexCoordsArray[numIndexes+1][0]=tess.svars.texcoords[0][b][0]; oldTexCoordsArray[numIndexes+1][1]=tess.svars.texcoords[0][b][1]; oldTexCoordsArray[numIndexes+2][0]=tess.svars.texcoords[0][c][0]; oldTexCoordsArray[numIndexes+2][1]=tess.svars.texcoords[0][c][1]; */ oldTexCoordsArray[numIndexes][0]=tess.texCoords[a][0][0]; oldTexCoordsArray[numIndexes][1]=tess.texCoords[a][0][1]; oldTexCoordsArray[numIndexes+1][0]=tess.texCoords[b][0][0]; oldTexCoordsArray[numIndexes+1][1]=tess.texCoords[b][0][1]; oldTexCoordsArray[numIndexes+2][0]=tess.texCoords[c][0][0]; oldTexCoordsArray[numIndexes+2][1]=tess.texCoords[c][0][1]; colorTemp[0] = Q_ftol(floatColor[0] * modulate); colorTemp[1] = Q_ftol(floatColor[1] * modulate); colorTemp[2] = Q_ftol(floatColor[2] * modulate); colorTemp[3] = 255; byteAlias_t *ba = (byteAlias_t *)&colorTemp; colorArray[numIndexes + 0] = ba->ui; colorArray[numIndexes + 1] = ba->ui; colorArray[numIndexes + 2] = ba->ui; hitIndexes[numIndexes] = numIndexes; hitIndexes[numIndexes+1] = numIndexes+1; hitIndexes[numIndexes+2] = numIndexes+2; numIndexes += 3; if (numIndexes>=SHADER_MAX_VERTEXES-3) { break; // we are out of space, so we are done :) } } if ( !numIndexes ) { continue; } //don't have fog enabled when we redraw with alpha test, or it will double over //and screw the tri up -rww if (r_drawfog->value == 2 && tr.world && (tess.fogNum == tr.world->globalFog || tess.fogNum == tr.world->numfogs)) { fogging = qglIsEnabled(GL_FOG); if (fogging) { qglDisable(GL_FOG); } } else { fogging = 0; } dStage = NULL; if (tess.shader && qglActiveTextureARB) { int i = 0; while (i < tess.shader->numUnfoggedPasses) { const int blendBits = (GLS_SRCBLEND_BITS+GLS_DSTBLEND_BITS); if (((tess.shader->stages[i].bundle[0].image && !tess.shader->stages[i].bundle[0].isLightmap && !tess.shader->stages[i].bundle[0].numTexMods && tess.shader->stages[i].bundle[0].tcGen != TCGEN_ENVIRONMENT_MAPPED && tess.shader->stages[i].bundle[0].tcGen != TCGEN_FOG) || (tess.shader->stages[i].bundle[1].image && !tess.shader->stages[i].bundle[1].isLightmap && !tess.shader->stages[i].bundle[1].numTexMods && tess.shader->stages[i].bundle[1].tcGen != TCGEN_ENVIRONMENT_MAPPED && tess.shader->stages[i].bundle[1].tcGen != TCGEN_FOG)) && (tess.shader->stages[i].stateBits & blendBits) == 0 ) { //only use non-lightmap opaque stages dStage = &tess.shader->stages[i]; break; } i++; } } if (!needResetVerts) { needResetVerts=1; if (qglUnlockArraysEXT) { qglUnlockArraysEXT(); GLimp_LogComment( "glUnlockArraysEXT\n" ); } } qglVertexPointer (3, GL_FLOAT, 16, vertCoordsArray); // padded for SIMD if (dStage) { GL_SelectTexture( 0 ); GL_State(0); qglTexCoordPointer( 2, GL_FLOAT, 0, oldTexCoordsArray[0] ); if (dStage->bundle[0].image && !dStage->bundle[0].isLightmap && !dStage->bundle[0].numTexMods && dStage->bundle[0].tcGen != TCGEN_ENVIRONMENT_MAPPED && dStage->bundle[0].tcGen != TCGEN_FOG) { R_BindAnimatedImage( &dStage->bundle[0] ); } else { R_BindAnimatedImage( &dStage->bundle[1] ); } GL_SelectTexture( 1 ); qglEnable( GL_TEXTURE_2D ); qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] ); qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray ); GL_Bind( tr.dlightImage ); GL_TexEnv( GL_MODULATE ); GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL);// | GLS_ATEST_GT_0); R_DrawElements( numIndexes, hitIndexes ); qglDisable( GL_TEXTURE_2D ); GL_SelectTexture(0); } else { qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] ); qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray ); GL_Bind( tr.dlightImage ); // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light // where they aren't rendered if ( dl->additive ) { GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } else { GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } R_DrawElements( numIndexes, hitIndexes ); } if (fogging) { qglEnable(GL_FOG); } backEnd.pc.c_totalIndexes += numIndexes; backEnd.pc.c_dlightIndexes += numIndexes; } if (needResetVerts) { qglVertexPointer (3, GL_FLOAT, 16, tess.xyz); // padded for SIMD if (qglLockArraysEXT) { qglLockArraysEXT(0, tess.numVertexes); GLimp_LogComment( "glLockArraysEXT\n" ); } } }
/* ** R_DrawTriangleOutlines */ void R_DrawTriangleOutlines(msurface_t *surf) // jit/GuyP, redone { int i; glpoly_t *p; if (!gl_showtris->value) return; // Guy: *\/\/\/ gl_showtris fix begin \/\/\/* qgl.Disable(GL_DEPTH_TEST); qgl.Color4f(1.0f, 1.0f, 1.0f, 1.0f); if (!surf) // Guy: Called from non-multitexture mode; need to loop through surfaces defined by non-mtex functions { int j; qgl.Disable(GL_TEXTURE_2D); for (i = 0; i < MAX_LIGHTMAPS; i++) { for (surf = gl_lms.lightmap_surfaces[i]; surf != 0; surf = surf->lightmapchain) { for (p = surf->polys; p; p = p->chain) { for (j = 2; j < p->numverts; j++) { qgl.Begin(GL_LINE_STRIP); qgl.Vertex3fv(p->verts[0]); qgl.Vertex3fv(p->verts[j - 1]); qgl.Vertex3fv(p->verts[j]); qgl.Vertex3fv(p->verts[0]); qgl.End(); } } } } qgl.Enable(GL_TEXTURE_2D); } else // Guy: Called from multitexture mode; surface to be rendered in wireframe already passed in { float tex_state0, tex_state1; GL_SelectTexture(QGL_TEXTURE0); qgl.GetTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_state0); GL_SelectTexture(QGL_TEXTURE1); qgl.GetTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_state1); GL_EnableMultitexture(false); qgl.Disable(GL_TEXTURE_2D); for (p = surf->polys; p; p = p->chain) { for (i = 2; i < p->numverts; i++) { //distcolor = p->verts[ qgl.Begin(GL_LINE_STRIP); //qgl.Color4f(1, 1, 1, 1); //qgl.Color4f(0,1,0,1); qgl.Vertex3fv(p->verts[0]); qgl.Vertex3fv(p->verts[i - 1]); qgl.Vertex3fv(p->verts[i]); qgl.Vertex3fv(p->verts[0]); qgl.End(); } } qgl.Enable(GL_TEXTURE_2D); GL_EnableMultitexture(true); GL_SelectTexture(QGL_TEXTURE0); GL_TexEnv(tex_state0); GL_SelectTexture(QGL_TEXTURE1); GL_TexEnv(tex_state1); } qgl.Enable(GL_DEPTH_TEST); // Guy: */\/\/\ gl_showtris fix end /\/\/\* }
/* ================= R_Bloom_GeneratexDiamonds ================= */ static void R_Bloom_GeneratexDiamonds( void ) { int i, j, k; float intensity, scale, *diamond; // set up sample size workspace qglScissor( 0, 0, sample_width, sample_height ); qglViewport( 0, 0, sample_width, sample_height ); qglMatrixMode( GL_PROJECTION ); qglLoadIdentity(); qglOrtho( 0, sample_width, sample_height, 0, -10, 100 ); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity(); // copy small scene into r_bloomeffecttexture GL_Bind( 0, r_bloomeffecttexture ); qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height ); // start modifying the small scene corner qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); // darkening passes if( r_bloom_darken->integer ) { GL_TexEnv( GL_MODULATE ); GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_ZERO ); for( i = 0; i < r_bloom_darken->integer; i++ ) R_Bloom_SamplePass( 0, 0 ); qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height ); } // bluring passes GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE_MINUS_SRC_COLOR ); if( r_bloom_diamond_size->integer > 7 || r_bloom_diamond_size->integer <= 3 ) { if( r_bloom_diamond_size->integer != 8 ) Cvar_ForceSet( "r_bloom_diamond_size", "8" ); } else if( r_bloom_diamond_size->integer > 5 ) { if( r_bloom_diamond_size->integer != 6 ) Cvar_ForceSet( "r_bloom_diamond_size", "6" ); } else if( r_bloom_diamond_size->integer > 3 ) { if( r_bloom_diamond_size->integer != 4 ) Cvar_ForceSet( "r_bloom_diamond_size", "4" ); } switch( r_bloom_diamond_size->integer ) { case 4: k = 2; diamond = &Diamond4x[0][0]; scale = r_bloom_intensity->value * 0.8f; break; case 6: k = 3; diamond = &Diamond6x[0][0]; scale = r_bloom_intensity->value * 0.5f; break; default: // case 8: k = 4; diamond = &Diamond8x[0][0]; scale = r_bloom_intensity->value * 0.3f; break; } for( i = 0; i < r_bloom_diamond_size->integer; i++ ) { for( j = 0; j < r_bloom_diamond_size->integer; j++, diamond++ ) { intensity = *diamond * scale; if( intensity < 0.01f ) continue; qglColor4f( intensity, intensity, intensity, 1.0 ); R_Bloom_SamplePass( i - k, j - k ); } } qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height ); // restore full screen workspace qglScissor( 0, 0, glState.width, glState.height ); qglViewport( 0, 0, glState.width, glState.height ); qglMatrixMode( GL_PROJECTION ); qglLoadIdentity(); qglOrtho( 0, glState.width, glState.height, 0, -10, 100 ); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity(); }
/* ================= R_DrawAliasModel ================= */ void R_DrawAliasModel (entity_t *e) { maliasmodel_t *paliashdr; vec3_t bbox[8]; qboolean mirrormodel = false; int i; // also skip this for viewermodels and cameramodels if ( !(e->flags & RF_WEAPONMODEL || e->flags & RF_VIEWERMODEL || e->renderfx & RF2_CAMERAMODEL) ) { if (R_CullAliasModel(bbox, e)) return; } // mirroring support if (e->flags & RF_WEAPONMODEL) { if (r_lefthand->value == 2) return; else if (r_lefthand->value == 1) mirrormodel = true; } else if (e->renderfx & RF2_CAMERAMODEL) { if (r_lefthand->value==1) mirrormodel = true; } else if (e->flags & RF_MIRRORMODEL) mirrormodel = true; // end mirroring support paliashdr = (maliasmodel_t *)currentmodel->extradata; R_SetShadeLight (); if (e->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls { if (r_newrefdef.rdflags & RDF_NOWORLDMODEL) GL_DepthRange (gldepthmin, gldepthmin + 0.01*(gldepthmax-gldepthmin)); else GL_DepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); } // mirroring support if (mirrormodel) R_FlipModel(true); for (i=0; i < paliashdr->num_meshes; i++) c_alias_polys += paliashdr->meshes[i].num_tris; qglPushMatrix (); e->angles[ROLL] = -e->angles[ROLL]; // roll is backwards R_RotateForEntity (e, true); e->angles[ROLL] = -e->angles[ROLL]; // roll is backwards GL_ShadeModel (GL_SMOOTH); GL_TexEnv(GL_MODULATE); if ( (e->frame >= paliashdr->num_frames) || (e->frame < 0) ) { VID_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such frame %d\n", currentmodel->name, e->frame); e->frame = 0; e->oldframe = 0; } if ( (e->oldframe >= paliashdr->num_frames) || (e->oldframe < 0)) { VID_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n", currentmodel->name, e->oldframe); e->frame = 0; e->oldframe = 0; } if (!r_lerpmodels->value) e->backlerp = 0; R_DrawAliasFrameLerp (paliashdr, e); GL_TexEnv(GL_REPLACE); GL_ShadeModel (GL_FLAT); qglPopMatrix (); // mirroring support if (mirrormodel) R_FlipModel(false); // show model bounding box R_DrawAliasModelBBox (bbox, e); if (e->flags & RF_DEPTHHACK) GL_DepthRange (gldepthmin, gldepthmax); aliasShadowAlpha = R_CalcShadowAlpha(e); if (!(e->flags & (RF_WEAPONMODEL | RF_NOSHADOW)) // no shadows from shells && !( (e->flags & (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM)) && (e->flags & RF_TRANSLUCENT) ) && r_shadows->value >= 1 && aliasShadowAlpha >= DIV255) { qglPushMatrix (); GL_DisableTexture(0); GL_Enable (GL_BLEND); if (r_shadows->value == 3) { e->angles[ROLL] = -e->angles[ROLL]; // roll is backwards R_RotateForEntity (e, true); e->angles[ROLL] = -e->angles[ROLL]; // roll is backwards R_DrawAliasVolumeShadow (paliashdr, bbox); } else { R_RotateForEntity (e, false); R_DrawAliasPlanarShadow (paliashdr); } GL_Disable (GL_BLEND); GL_EnableTexture(0); qglPopMatrix (); } }