/* =================== 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]; 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 ) { qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); } // // base // GL_SelectTexture( 0 ); qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] ); R_BindAnimatedImage( &pStage->bundle[0] ); // // lightmap/secondary pass // GL_SelectTexture( 1 ); qglEnable( GL_TEXTURE_2D ); qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); if ( r_lightmap->integer ) { GL_TexEnv( GL_REPLACE ); } else { GL_TexEnv( tess.shader->multitextureEnv ); } qglTexCoordPointer( 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 // //qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); qglDisable( GL_TEXTURE_2D ); GL_SelectTexture( 0 ); }
/* =============== RB_ShowImages Draw all the images to the screen, on top of whatever was there. This is used to test for texture thrashing. Also called by RE_EndRegistration =============== */ void RB_ShowImages( void ) { int i; image_t *image; float x, y, w, h; int start, end; if ( !backEnd.projection2D ) { RB_SetGL2D(); } qglClear( GL_COLOR_BUFFER_BIT ); qglFinish(); start = ri.Milliseconds(); for ( i=0 ; i<tr.numImages ; i++ ) { image = tr.images[i]; w = glConfig.vidWidth / 20; h = glConfig.vidHeight / 15; x = i % 20 * w; y = i / 20 * h; // show in proportional size in mode 2 if ( r_showImages->integer == 2 ) { w *= image->uploadWidth / 512.0f; h *= image->uploadHeight / 512.0f; } GL_Bind( image ); /* qglBegin (GL_QUADS); qglTexCoord2f( 0, 0 ); qglVertex2f( x, y ); qglTexCoord2f( 1, 0 ); qglVertex2f( x + w, y ); qglTexCoord2f( 1, 1 ); qglVertex2f( x + w, y + h ); qglTexCoord2f( 0, 1 ); qglVertex2f( x, y + h ); qglEnd(); */ GLfloat texcoords[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.1f, 1.1f, 0.0f, 1.0f }; GLfloat vertices [] = { x, y, x + w, y, x + w, y + h, x, y + h }; qglEnableClientState (GL_VERTEX_ARRAY); qglEnableClientState (GL_TEXTURE_COORD_ARRAY); qglVertexPointer ( 2, GL_FLOAT, 0, vertices ); qglTexCoordPointer ( 2, GL_FLOAT, 0, vertices ); qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); } qglFinish(); end = ri.Milliseconds(); ri.Printf( PRINT_ALL, "%i msec to draw all images\n", end - start ); }
void Gui_DrawCrosshair() { // TBI: actual ingame crosshair BindWhiteTexture(); qglBindBufferARB(GL_ARRAY_BUFFER_ARB, crosshairBuffer); qglVertexPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), (void *)0); qglColorPointer(4, GL_FLOAT, 8 * sizeof(GLfloat), (void *)sizeof(GLfloat[2])); qglTexCoordPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), (void *)sizeof(GLfloat[6])); qglDrawArrays(GL_LINES, 0, 4); }
/* ** RB_IterateStagesGeneric */ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { int stage; for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { shaderStage_t *pStage = tess.xstages[stage]; if ( !pStage ) { break; } ComputeColors( pStage ); ComputeTexCoords( pStage ); if ( !setArraysOnce ) { qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, input->svars.colors ); } // // do multitexture // if ( pStage->bundle[1].image[0] != 0 ) { DrawMultitextured( input, stage ); } else { if ( !setArraysOnce ) { qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] ); } // // set state // R_BindAnimatedImage( &pStage->bundle[0] ); GL_State( pStage->stateBits ); // // draw // R_DrawElements( input->numIndexes, input->indexes ); } // allow skipping out to show just lightmaps during development if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) ) { break; } } }
/* ============== R_DrawSkyBox ============== */ void R_DrawSkyBox( void ) { static const int skytexorder[6] = {0,2,1,3,4,5}; vec5_t verts[4]; int i; if( skyrotate ) { // hack, forces full sky to draw when rotating for( i = 0; i < 6; i++ ) { skymins[0][i] = -1; skymins[1][i] = -1; skymaxs[0][i] = 1; skymaxs[1][i] = 1; } } else { // check for no sky at all for( i = 0; i < 6; i++ ) { if( SKY_VISIBLE( i ) ) { break; } } if( i == 6 ) { return; // nothing visible } } qglPushMatrix (); qglTranslatef (glr.fd.vieworg[0], glr.fd.vieworg[1], glr.fd.vieworg[2]); if( skyrotate ) { qglRotatef (glr.fd.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]); } GL_TexEnv( GL_REPLACE ); GL_Bits( GLS_DEFAULT ); qglVertexPointer( 3, GL_FLOAT, 5*4, &verts[0][0] ); qglTexCoordPointer( 2, GL_FLOAT, 5*4, &verts[0][3] ); for( i = 0; i < 6; i++ ) { if( !SKY_VISIBLE( i ) ) { continue; } GL_BindTexture (sky_images[skytexorder[i]]); MakeSkyVec (skymaxs[0][i], skymins[1][i], i, verts[0]); MakeSkyVec (skymins[0][i], skymins[1][i], i, verts[1]); MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i, verts[2]); MakeSkyVec (skymins[0][i], skymaxs[1][i], i, verts[3]); qglDrawArrays( GL_TRIANGLE_STRIP, 0, 4 ); } qglPopMatrix (); }
/* =============== RB_RenderTriangleSurface Sets texcoord and vertex pointers =============== */ void RB_RenderTriangleSurface( const srfTriangles_t *tri ) { if ( !tri->ambientCache ) { RB_DrawElementsImmediate( tri ); return; } idDrawVert *ac = (idDrawVert *)vertexCache.Position( tri->ambientCache ); qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() ); qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), ac->st.ToFloatPtr() ); RB_DrawElementsWithCounters( tri ); }
static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] ) { int s, t; GL_Bind( image ); #ifdef HAVE_GLES GLfloat vtx[3 * 1024]; // arbitrary sized GLfloat tex[2 * 1024]; int idx; GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY); GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY); if (glcol) qglDisableClientState(GL_COLOR_ARRAY); if (!text) qglEnableClientState(GL_TEXTURE_COORD_ARRAY); #endif for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) { #ifdef HAVE_GLES idx = 0; #else qglBegin(GL_TRIANGLE_STRIP); #endif for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) { #ifdef HAVE_GLES memcpy(tex + idx * 2, s_skyTexCoords[t][s], sizeof(GLfloat) * 2); memcpy(vtx + idx * 3, s_skyPoints[t][s], sizeof(GLfloat) * 3); idx++; memcpy(tex + idx * 2, s_skyTexCoords[t + 1][s], sizeof(GLfloat) * 2); memcpy(vtx + idx * 3, s_skyPoints[t + 1][s], sizeof(GLfloat) * 3); idx++; #else qglTexCoord2fv(s_skyTexCoords[t][s]); qglVertex3fv(s_skyPoints[t][s]); qglTexCoord2fv(s_skyTexCoords[t + 1][s]); qglVertex3fv(s_skyPoints[t + 1][s]); #endif } #ifdef HAVE_GLES qglVertexPointer(3, GL_FLOAT, 0, vtx); qglTexCoordPointer(2, GL_FLOAT, 0, tex); qglDrawArrays(GL_TRIANGLE_STRIP, 0, idx); #else qglEnd(); #endif } }
static void DrawSkySideInner(struct image_s *image, const int mins[2], const int maxs[2]) { int s, t; GL_Bind(image); GLfloat vtx[3 * 1024]; // arbitrary sized GLfloat tex[2 * 1024]; int idx; GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY); GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY); if (glcol) { qglDisableClientState(GL_COLOR_ARRAY); } if (!text) { qglEnableClientState(GL_TEXTURE_COORD_ARRAY); } //qglDisable (GL_BLEND); qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); qglEnable(GL_BLEND); GL_TexEnv(GL_MODULATE); for (t = mins[1] + HALF_SKY_SUBDIVISIONS; t < maxs[1] + HALF_SKY_SUBDIVISIONS; t++) { idx = 0; for (s = mins[0] + HALF_SKY_SUBDIVISIONS; s <= maxs[0] + HALF_SKY_SUBDIVISIONS; s++) { memcpy(tex + idx * 2, s_skyTexCoords[t][s], sizeof(GLfloat) * 2); memcpy(vtx + idx * 3, s_skyPoints[t][s], sizeof(GLfloat) * 3); idx++; memcpy(tex + idx * 2, s_skyTexCoords[t + 1][s], sizeof(GLfloat) * 2); memcpy(vtx + idx * 3, s_skyPoints[t + 1][s], sizeof(GLfloat) * 3); idx++; } qglVertexPointer(3, GL_FLOAT, 0, vtx); qglTexCoordPointer(2, GL_FLOAT, 0, tex); qglDrawArrays(GL_TRIANGLE_STRIP, 0, idx); } qglDisable(GL_BLEND); }
/* =================== RB_FogPass Blends a fog texture on top of everything else =================== */ static void RB_FogPass(void) { fog_t *fog; int i; // no fog pass in snooper if (tr.refdef.rdflags & RDF_SNOOPERVIEW || tess.shader->noFog || !r_wolffog->integer) { return; } // no world, no fogging if (backEnd.refdef.rdflags & RDF_NOWORLDMODEL) { return; } qglEnableClientState(GL_COLOR_ARRAY); qglColorPointer(4, GL_UNSIGNED_BYTE, 0, tess.svars.colors); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); qglTexCoordPointer(2, GL_FLOAT, 0, tess.svars.texcoords[0]); fog = tr.world->fogs + tess.fogNum; for (i = 0; i < tess.numVertexes; i++) { *( int * )&tess.svars.colors[i] = fog->shader->fogParms.colorInt; } RB_CalcFogTexCoords(( float * ) tess.svars.texcoords[0]); GL_Bind(tr.fogImage); if (tess.shader->fogPass == FP_EQUAL) { GL_State(GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL); } else { GL_State(GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA); } R_DrawElements(tess.numIndexes, tess.indexes); }
static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] ) { int s, t; unsigned i; vec3_t points[(SKY_SUBDIVISIONS+1) * (SKY_SUBDIVISIONS+1)]; float texcoords[(SKY_SUBDIVISIONS+1) * (SKY_SUBDIVISIONS+1) * 2]; GL_Bind( image ); for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) { #ifndef GL_VERSION_ES_CM_1_0 qglBegin( GL_TRIANGLE_STRIP ); for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) { qglTexCoord2fv( s_skyTexCoords[t][s] ); qglVertex3fv( s_skyPoints[t][s] ); qglTexCoord2fv( s_skyTexCoords[t+1][s] ); qglVertex3fv( s_skyPoints[t+1][s] ); } qglEnd(); #else for ( s = mins[0]+HALF_SKY_SUBDIVISIONS, i = 0; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++, i += 2 ) { VectorCopy( s_skyPoints[t][s], points[i] ); VectorCopy( s_skyPoints[t+1][s], points[i+1] ); texcoords[i*2] = s_skyTexCoords[t][s][0]; texcoords[i*2+1] = s_skyTexCoords[t][s][1]; texcoords[i*2+2] = s_skyTexCoords[t+1][s][0]; texcoords[i*2+3] = s_skyTexCoords[t+1][s][1]; } qglEnableClientState ( GL_VERTEX_ARRAY ); qglEnableClientState ( GL_TEXTURE_COORD_ARRAY ); qglTexCoordPointer ( 2, GL_FLOAT, 0, texcoords ); qglVertexPointer ( 3, GL_FLOAT, 0, points ); qglDrawArrays( GL_TRIANGLE_STRIP, 0, i ); #endif } }
/* =================== RB_HazePass Blends a fog texture on top of everything but the skybox =================== */ static void RB_HazePass( void ) { int i; unsigned int color[3], colorInt; // TODO; Get color from worlspawn. Use black for now. color[0] = 0; color[1] = 0; color[2] = 0; colorInt = ColorBytes4( color[0] * tr.identityLight, color[1] * tr.identityLight, color[2] * tr.identityLight, 1.0 ); qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors ); qglEnableClientState( GL_TEXTURE_COORD_ARRAY); qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] ); //fog = tr.world->fogs + tess.fogNum; for ( i = 0; i < tess.numVertexes; i++ ) { * ( int * )&tess.svars.colors[i] = colorInt; } RB_CalcFogTexCoords( ( float * ) tess.svars.texcoords[0] ); GL_Bind( tr.fogImage ); if ( tess.shader->fogPass == FP_EQUAL ) { GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL ); } else { GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); } R_DrawElements( tess.numIndexes, tess.indexes ); }
/* ================ RB_PrepareStageTexturing ================ */ void RB_PrepareStageTexturing( const shaderStage_t *pStage, const drawSurf_t *surf, idDrawVert *ac ) { // set privatePolygonOffset if necessary if ( pStage->privatePolygonOffset ) { qglEnable( GL_POLYGON_OFFSET_FILL ); qglPolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * pStage->privatePolygonOffset ); } // set the texture matrix if needed if ( pStage->texture.hasMatrix ) { RB_LoadShaderTextureMatrix( surf->shaderRegisters, &pStage->texture ); } // texgens if ( pStage->texture.texgen == TG_DIFFUSE_CUBE ) { qglTexCoordPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() ); } if ( pStage->texture.texgen == TG_SKYBOX_CUBE || pStage->texture.texgen == TG_WOBBLESKY_CUBE ) { qglTexCoordPointer( 3, GL_FLOAT, 0, vertexCache.Position( surf->dynamicTexCoords ) ); } if ( pStage->texture.texgen == TG_SCREEN ) { qglEnable( GL_TEXTURE_GEN_S ); qglEnable( GL_TEXTURE_GEN_T ); qglEnable( GL_TEXTURE_GEN_Q ); float mat[16], plane[4]; myGlMultMatrix( surf->space->modelViewMatrix, backEnd.viewDef->projectionMatrix, mat ); plane[0] = mat[0]; plane[1] = mat[4]; plane[2] = mat[8]; plane[3] = mat[12]; qglTexGenfv( GL_S, GL_OBJECT_PLANE, plane ); plane[0] = mat[1]; plane[1] = mat[5]; plane[2] = mat[9]; plane[3] = mat[13]; qglTexGenfv( GL_T, GL_OBJECT_PLANE, plane ); plane[0] = mat[3]; plane[1] = mat[7]; plane[2] = mat[11]; plane[3] = mat[15]; qglTexGenfv( GL_Q, GL_OBJECT_PLANE, plane ); } if ( pStage->texture.texgen == TG_SCREEN2 ) { qglEnable( GL_TEXTURE_GEN_S ); qglEnable( GL_TEXTURE_GEN_T ); qglEnable( GL_TEXTURE_GEN_Q ); float mat[16], plane[4]; myGlMultMatrix( surf->space->modelViewMatrix, backEnd.viewDef->projectionMatrix, mat ); plane[0] = mat[0]; plane[1] = mat[4]; plane[2] = mat[8]; plane[3] = mat[12]; qglTexGenfv( GL_S, GL_OBJECT_PLANE, plane ); plane[0] = mat[1]; plane[1] = mat[5]; plane[2] = mat[9]; plane[3] = mat[13]; qglTexGenfv( GL_T, GL_OBJECT_PLANE, plane ); plane[0] = mat[3]; plane[1] = mat[7]; plane[2] = mat[11]; plane[3] = mat[15]; qglTexGenfv( GL_Q, GL_OBJECT_PLANE, plane ); } if ( pStage->texture.texgen == TG_GLASSWARP ) { if ( tr.backEndRenderer == BE_ARB2 /*|| tr.backEndRenderer == BE_NV30*/ ) { qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_GLASSWARP ); qglEnable( GL_FRAGMENT_PROGRAM_ARB ); GL_SelectTexture( 2 ); globalImages->scratchImage->Bind(); GL_SelectTexture( 1 ); globalImages->scratchImage2->Bind(); qglEnable( GL_TEXTURE_GEN_S ); qglEnable( GL_TEXTURE_GEN_T ); qglEnable( GL_TEXTURE_GEN_Q ); float mat[16], plane[4]; myGlMultMatrix( surf->space->modelViewMatrix, backEnd.viewDef->projectionMatrix, mat ); plane[0] = mat[0]; plane[1] = mat[4]; plane[2] = mat[8]; plane[3] = mat[12]; qglTexGenfv( GL_S, GL_OBJECT_PLANE, plane ); plane[0] = mat[1]; plane[1] = mat[5]; plane[2] = mat[9]; plane[3] = mat[13]; qglTexGenfv( GL_T, GL_OBJECT_PLANE, plane ); plane[0] = mat[3]; plane[1] = mat[7]; plane[2] = mat[11]; plane[3] = mat[15]; qglTexGenfv( GL_Q, GL_OBJECT_PLANE, plane ); GL_SelectTexture( 0 ); } } if ( pStage->texture.texgen == TG_REFLECT_CUBE ) { if ( tr.backEndRenderer == BE_ARB2 ) { // see if there is also a bump map specified const shaderStage_t *bumpStage = surf->material->GetBumpStage(); if ( bumpStage ) { // per-pixel reflection mapping with bump mapping GL_SelectTexture( 1 ); bumpStage->texture.image->Bind(); GL_SelectTexture( 0 ); qglNormalPointer( GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() ); qglVertexAttribPointerARB( 10, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[1].ToFloatPtr() ); qglVertexAttribPointerARB( 9, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[0].ToFloatPtr() ); qglEnableVertexAttribArrayARB( 9 ); qglEnableVertexAttribArrayARB( 10 ); qglEnableClientState( GL_NORMAL_ARRAY ); // Program env 5, 6, 7, 8 have been set in RB_SetProgramEnvironmentSpace qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_BUMPY_ENVIRONMENT ); qglEnable( GL_FRAGMENT_PROGRAM_ARB ); qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_BUMPY_ENVIRONMENT ); qglEnable( GL_VERTEX_PROGRAM_ARB ); } else { // per-pixel reflection mapping without a normal map qglNormalPointer( GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() ); qglEnableClientState( GL_NORMAL_ARRAY ); qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_ENVIRONMENT ); qglEnable( GL_FRAGMENT_PROGRAM_ARB ); qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_ENVIRONMENT ); qglEnable( GL_VERTEX_PROGRAM_ARB ); } } else { qglEnable( GL_TEXTURE_GEN_S ); qglEnable( GL_TEXTURE_GEN_T ); qglEnable( GL_TEXTURE_GEN_R ); qglTexGenf( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT ); qglTexGenf( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT ); qglTexGenf( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT ); qglEnableClientState( GL_NORMAL_ARRAY ); qglNormalPointer( GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() ); qglMatrixMode( GL_TEXTURE ); float mat[16]; R_TransposeGLMatrix( backEnd.viewDef->worldSpace.modelViewMatrix, mat ); qglLoadMatrixf( mat ); qglMatrixMode( GL_MODELVIEW ); } } }
/* ================== RB_STD_T_RenderShaderPasses This is also called for the generated 2D rendering ================== */ void RB_STD_T_RenderShaderPasses( const drawSurf_t *surf ) { int stage; const idMaterial *shader; const shaderStage_t *pStage; const float *regs; float color[4]; const srfTriangles_t *tri; tri = surf->geo; shader = surf->material; if ( !shader->HasAmbient() ) { return; } if ( shader->IsPortalSky() ) { return; } // change the matrix if needed if ( surf->space != backEnd.currentSpace ) { qglLoadMatrixf( surf->space->modelViewMatrix ); backEnd.currentSpace = surf->space; RB_SetProgramEnvironmentSpace(); } // change the scissor if needed if ( r_useScissor.GetBool() && !backEnd.currentScissor.Equals( surf->scissorRect ) ) { backEnd.currentScissor = surf->scissorRect; qglScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1, backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1, backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1, backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 ); } // some deforms may disable themselves by setting numIndexes = 0 if ( !tri->numIndexes ) { return; } if ( !tri->ambientCache ) { common->Printf( "RB_T_RenderShaderPasses: !tri->ambientCache\n" ); return; } // get the expressions for conditionals / color / texcoords regs = surf->shaderRegisters; // set face culling appropriately GL_Cull( shader->GetCullType() ); // set polygon offset if necessary if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) { qglEnable( GL_POLYGON_OFFSET_FILL ); qglPolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() ); } if ( surf->space->weaponDepthHack ) { RB_EnterWeaponDepthHack(); } if ( surf->space->modelDepthHack != 0.0f ) { RB_EnterModelDepthHack( surf->space->modelDepthHack ); } idDrawVert *ac = (idDrawVert *)vertexCache.Position( tri->ambientCache ); qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() ); qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), reinterpret_cast<void *>(&ac->st) ); for ( stage = 0; stage < shader->GetNumStages() ; stage++ ) { pStage = shader->GetStage(stage); // check the enable condition if ( regs[ pStage->conditionRegister ] == 0 ) { continue; } // skip the stages involved in lighting if ( pStage->lighting != SL_AMBIENT ) { continue; } // skip if the stage is ( GL_ZERO, GL_ONE ), which is used for some alpha masks if ( ( pStage->drawStateBits & (GLS_SRCBLEND_BITS|GLS_DSTBLEND_BITS) ) == ( GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE ) ) { continue; } // see if we are a new-style stage newShaderStage_t *newStage = pStage->newStage; if ( newStage ) { //-------------------------- // // new style stages // //-------------------------- // completely skip the stage if we don't have the capability if ( tr.backEndRenderer != BE_ARB2 ) { continue; } if ( r_skipNewAmbient.GetBool() ) { continue; } qglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( idDrawVert ), (void *)&ac->color ); qglVertexAttribPointerARB( 9, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[0].ToFloatPtr() ); qglVertexAttribPointerARB( 10, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[1].ToFloatPtr() ); qglNormalPointer( GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() ); qglEnableClientState( GL_COLOR_ARRAY ); qglEnableVertexAttribArrayARB( 9 ); qglEnableVertexAttribArrayARB( 10 ); qglEnableClientState( GL_NORMAL_ARRAY ); GL_State( pStage->drawStateBits ); qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, newStage->vertexProgram ); qglEnable( GL_VERTEX_PROGRAM_ARB ); // megaTextures bind a lot of images and set a lot of parameters if ( newStage->megaTexture ) { newStage->megaTexture->SetMappingForSurface( tri ); idVec3 localViewer; R_GlobalPointToLocal( surf->space->modelMatrix, backEnd.viewDef->renderView.vieworg, localViewer ); newStage->megaTexture->BindForViewOrigin( localViewer ); } for ( int i = 0 ; i < newStage->numVertexParms ; i++ ) { float parm[4]; parm[0] = regs[ newStage->vertexParms[i][0] ]; parm[1] = regs[ newStage->vertexParms[i][1] ]; parm[2] = regs[ newStage->vertexParms[i][2] ]; parm[3] = regs[ newStage->vertexParms[i][3] ]; qglProgramLocalParameter4fvARB( GL_VERTEX_PROGRAM_ARB, i, parm ); } for ( int i = 0 ; i < newStage->numFragmentProgramImages ; i++ ) { if ( newStage->fragmentProgramImages[i] ) { GL_SelectTexture( i ); newStage->fragmentProgramImages[i]->Bind(); } } qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, newStage->fragmentProgram ); qglEnable( GL_FRAGMENT_PROGRAM_ARB ); // draw it RB_DrawElementsWithCounters( tri ); for ( int i = 1 ; i < newStage->numFragmentProgramImages ; i++ ) { if ( newStage->fragmentProgramImages[i] ) { GL_SelectTexture( i ); globalImages->BindNull(); } } if ( newStage->megaTexture ) { newStage->megaTexture->Unbind(); } GL_SelectTexture( 0 ); qglDisable( GL_VERTEX_PROGRAM_ARB ); qglDisable( GL_FRAGMENT_PROGRAM_ARB ); // Fixme: Hack to get around an apparent bug in ATI drivers. Should remove as soon as it gets fixed. qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, 0 ); qglDisableClientState( GL_COLOR_ARRAY ); qglDisableVertexAttribArrayARB( 9 ); qglDisableVertexAttribArrayARB( 10 ); qglDisableClientState( GL_NORMAL_ARRAY ); continue; } //-------------------------- // // old style stages // //-------------------------- // set the color color[0] = regs[ pStage->color.registers[0] ]; color[1] = regs[ pStage->color.registers[1] ]; color[2] = regs[ pStage->color.registers[2] ]; color[3] = regs[ pStage->color.registers[3] ]; // skip the entire stage if an add would be black if ( ( pStage->drawStateBits & (GLS_SRCBLEND_BITS|GLS_DSTBLEND_BITS) ) == ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ) && color[0] <= 0 && color[1] <= 0 && color[2] <= 0 ) { continue; } // skip the entire stage if a blend would be completely transparent if ( ( pStage->drawStateBits & (GLS_SRCBLEND_BITS|GLS_DSTBLEND_BITS) ) == ( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) && color[3] <= 0 ) { continue; } // select the vertex color source if ( pStage->vertexColor == SVC_IGNORE ) { qglColor4fv( color ); } else { qglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( idDrawVert ), (void *)&ac->color ); qglEnableClientState( GL_COLOR_ARRAY ); if ( pStage->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 ); } // for vertex color and modulated color, we need to enable a second // texture stage if ( color[0] != 1 || color[1] != 1 || color[2] != 1 || color[3] != 1 ) { GL_SelectTexture( 1 ); globalImages->whiteImage->Bind(); GL_TexEnv( GL_COMBINE_ARB ); qglTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color ); qglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE ); qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB ); qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_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_COMBINE_ALPHA_ARB, GL_MODULATE ); qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB ); qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_CONSTANT_ARB ); qglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA ); qglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA ); qglTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1 ); GL_SelectTexture( 0 ); } } // bind the texture RB_BindVariableStageImage( &pStage->texture, regs ); // set the state GL_State( pStage->drawStateBits ); RB_PrepareStageTexturing( pStage, surf, ac ); // draw it RB_DrawElementsWithCounters( tri ); RB_FinishStageTexturing( pStage, surf, ac ); if ( pStage->vertexColor != SVC_IGNORE ) { qglDisableClientState( GL_COLOR_ARRAY ); GL_SelectTexture( 1 ); GL_TexEnv( GL_MODULATE ); globalImages->BindNull(); GL_SelectTexture( 0 ); GL_TexEnv( GL_MODULATE ); } } // reset polygon offset if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) { qglDisable( GL_POLYGON_OFFSET_FILL ); } if ( surf->space->weaponDepthHack || surf->space->modelDepthHack != 0.0f ) { RB_LeaveDepthHack(); } }
/* ================== RB_T_FillDepthBuffer ================== */ void RB_T_FillDepthBuffer( const drawSurf_t *surf ) { int stage; const idMaterial *shader; const shaderStage_t *pStage; const float *regs; float color[4]; const srfTriangles_t *tri; tri = surf->geo; shader = surf->material; // update the clip plane if needed if ( backEnd.viewDef->numClipPlanes && surf->space != backEnd.currentSpace ) { GL_SelectTexture( 1 ); idPlane plane; R_GlobalPlaneToLocal( surf->space->modelMatrix, backEnd.viewDef->clipPlanes[0], plane ); plane[3] += 0.5; // the notch is in the middle qglTexGenfv( GL_S, GL_OBJECT_PLANE, plane.ToFloatPtr() ); GL_SelectTexture( 0 ); } if ( !shader->IsDrawn() ) { return; } // some deforms may disable themselves by setting numIndexes = 0 if ( !tri->numIndexes ) { return; } // translucent surfaces don't put anything in the depth buffer and don't // test against it, which makes them fail the mirror clip plane operation if ( shader->Coverage() == MC_TRANSLUCENT ) { return; } if ( !tri->ambientCache ) { common->Printf( "RB_T_FillDepthBuffer: !tri->ambientCache\n" ); return; } // get the expressions for conditionals / color / texcoords regs = surf->shaderRegisters; // if all stages of a material have been conditioned off, don't do anything for ( stage = 0; stage < shader->GetNumStages() ; stage++ ) { pStage = shader->GetStage(stage); // check the stage enable condition if ( regs[ pStage->conditionRegister ] != 0 ) { break; } } if ( stage == shader->GetNumStages() ) { return; } // set polygon offset if necessary if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) { qglEnable( GL_POLYGON_OFFSET_FILL ); qglPolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() ); } // subviews will just down-modulate the color buffer by overbright if ( shader->GetSort() == SS_SUBVIEW ) { GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHFUNC_LESS ); color[0] = color[1] = color[2] = ( 1.0 / backEnd.overBright ); color[3] = 1; } else { // others just draw black color[0] = 0; color[1] = 0; color[2] = 0; color[3] = 1; } idDrawVert *ac = (idDrawVert *)vertexCache.Position( tri->ambientCache ); qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() ); qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), reinterpret_cast<void *>(&ac->st) ); bool drawSolid = false; if ( shader->Coverage() == MC_OPAQUE ) { drawSolid = true; } // we may have multiple alpha tested stages if ( shader->Coverage() == MC_PERFORATED ) { // if the only alpha tested stages are condition register omitted, // draw a normal opaque surface bool didDraw = false; qglEnable( GL_ALPHA_TEST ); // perforated surfaces may have multiple alpha tested stages for ( stage = 0; stage < shader->GetNumStages() ; stage++ ) { pStage = shader->GetStage(stage); if ( !pStage->hasAlphaTest ) { continue; } // check the stage enable condition if ( regs[ pStage->conditionRegister ] == 0 ) { continue; } // if we at least tried to draw an alpha tested stage, // we won't draw the opaque surface didDraw = true; // set the alpha modulate color[3] = regs[ pStage->color.registers[3] ]; // skip the entire stage if alpha would be black if ( color[3] <= 0 ) { continue; } qglColor4fv( color ); qglAlphaFunc( GL_GREATER, regs[ pStage->alphaTestRegister ] ); // bind the texture pStage->texture.image->Bind(); // set texture matrix and texGens RB_PrepareStageTexturing( pStage, surf, ac ); // draw it RB_DrawElementsWithCounters( tri ); RB_FinishStageTexturing( pStage, surf, ac ); } qglDisable( GL_ALPHA_TEST ); if ( !didDraw ) { drawSolid = true; } } // draw the entire surface solid if ( drawSolid ) { qglColor4fv( color ); globalImages->whiteImage->Bind(); // draw it RB_DrawElementsWithCounters( tri ); } // reset polygon offset if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) { qglDisable( GL_POLYGON_OFFSET_FILL ); } // reset blending if ( shader->GetSort() == SS_SUBVIEW ) { GL_State( GLS_DEPTHFUNC_LESS ); } }
/* ================ RB_FinishStageTexturing ================ */ void RB_FinishStageTexturing( const shaderStage_t *pStage, const drawSurf_t *surf, idDrawVert *ac ) { // unset privatePolygonOffset if necessary if ( pStage->privatePolygonOffset && !surf->material->TestMaterialFlag(MF_POLYGONOFFSET) ) { qglDisable( GL_POLYGON_OFFSET_FILL ); } if ( pStage->texture.texgen == TG_DIFFUSE_CUBE || pStage->texture.texgen == TG_SKYBOX_CUBE || pStage->texture.texgen == TG_WOBBLESKY_CUBE ) { qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->st ); } if ( pStage->texture.texgen == TG_SCREEN ) { qglDisable( GL_TEXTURE_GEN_S ); qglDisable( GL_TEXTURE_GEN_T ); qglDisable( GL_TEXTURE_GEN_Q ); } if ( pStage->texture.texgen == TG_SCREEN2 ) { qglDisable( GL_TEXTURE_GEN_S ); qglDisable( GL_TEXTURE_GEN_T ); qglDisable( GL_TEXTURE_GEN_Q ); } if ( pStage->texture.texgen == TG_GLASSWARP ) { if ( tr.backEndRenderer == BE_ARB2 /*|| tr.backEndRenderer == BE_NV30*/ ) { GL_SelectTexture( 2 ); globalImages->BindNull(); GL_SelectTexture( 1 ); if ( pStage->texture.hasMatrix ) { RB_LoadShaderTextureMatrix( surf->shaderRegisters, &pStage->texture ); } qglDisable( GL_TEXTURE_GEN_S ); qglDisable( GL_TEXTURE_GEN_T ); qglDisable( GL_TEXTURE_GEN_Q ); qglDisable( GL_FRAGMENT_PROGRAM_ARB ); globalImages->BindNull(); GL_SelectTexture( 0 ); } } if ( pStage->texture.texgen == TG_REFLECT_CUBE ) { if ( tr.backEndRenderer == BE_ARB2 ) { // see if there is also a bump map specified const shaderStage_t *bumpStage = surf->material->GetBumpStage(); if ( bumpStage ) { // per-pixel reflection mapping with bump mapping GL_SelectTexture( 1 ); globalImages->BindNull(); GL_SelectTexture( 0 ); qglDisableVertexAttribArrayARB( 9 ); qglDisableVertexAttribArrayARB( 10 ); } else { // per-pixel reflection mapping without bump mapping } qglDisableClientState( GL_NORMAL_ARRAY ); qglDisable( GL_FRAGMENT_PROGRAM_ARB ); qglDisable( GL_VERTEX_PROGRAM_ARB ); // Fixme: Hack to get around an apparent bug in ATI drivers. Should remove as soon as it gets fixed. qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, 0 ); } else { qglDisable( GL_TEXTURE_GEN_S ); qglDisable( GL_TEXTURE_GEN_T ); qglDisable( GL_TEXTURE_GEN_R ); qglTexGenf( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR ); qglTexGenf( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR ); qglTexGenf( GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR ); qglDisableClientState( GL_NORMAL_ARRAY ); qglMatrixMode( GL_TEXTURE ); qglLoadIdentity(); qglMatrixMode( GL_MODELVIEW ); } } if ( pStage->texture.hasMatrix ) { qglMatrixMode( GL_TEXTURE ); qglLoadIdentity(); qglMatrixMode( GL_MODELVIEW ); } }
static void ProjectDlightTexture_altivec( void ) { int i, l; vec_t origin0, origin1, origin2; float texCoords0, texCoords1; vector float floatColorVec0, floatColorVec1; vector float modulateVec, colorVec, zero; vector short colorShort; vector signed int colorInt; vector unsigned char floatColorVecPerm, modulatePerm, colorChar; vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff); float *texCoords; byte *colors; byte clipBits[SHADER_MAX_VERTEXES]; float texCoordsArray[SHADER_MAX_VERTEXES][2]; byte colorArray[SHADER_MAX_VERTEXES][4]; unsigned hitIndexes[SHADER_MAX_INDEXES]; int numIndexes; float scale; float radius; vec3_t floatColor; float modulate = 0.0f; if ( !backEnd.refdef.num_dlights ) { return; } // There has to be a better way to do this so that floatColor // and/or modulate are already 16-byte aligned. floatColorVecPerm = vec_lvsl(0,(float *)floatColor); modulatePerm = vec_lvsl(0,(float *)&modulate); modulatePerm = (vector unsigned char)vec_splat((vector unsigned int)modulatePerm,0); zero = (vector float)vec_splat_s8(0); 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]; origin0 = dl->transformed[0]; origin1 = dl->transformed[1]; origin2 = dl->transformed[2]; radius = dl->radius; scale = 1.0f / radius; if(r_greyscale->integer) { float luminance; luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; floatColor[0] = floatColor[1] = floatColor[2] = luminance; } else if(r_greyscale->value) { float luminance; luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value); floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value); floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value); } else { floatColor[0] = dl->color[0] * 255.0f; floatColor[1] = dl->color[1] * 255.0f; floatColor[2] = dl->color[2] * 255.0f; } floatColorVec0 = vec_ld(0, floatColor); floatColorVec1 = vec_ld(11, floatColor); floatColorVec0 = vec_perm(floatColorVec0,floatColorVec0,floatColorVecPerm); for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) { int clip = 0; vec_t dist0, dist1, dist2; dist0 = origin0 - tess.xyz[i][0]; dist1 = origin1 - tess.xyz[i][1]; dist2 = origin2 - tess.xyz[i][2]; backEnd.pc.c_dlightVertexes++; texCoords0 = 0.5f + dist0 * scale; texCoords1 = 0.5f + dist1 * scale; if( !r_dlightBacks->integer && // dist . tess.normal[i] ( dist0 * tess.normal[i][0] + dist1 * tess.normal[i][1] + dist2 * tess.normal[i][2] ) < 0.0f ) { clip = 63; } else { if ( texCoords0 < 0.0f ) { clip |= 1; } else if ( texCoords0 > 1.0f ) { clip |= 2; } if ( texCoords1 < 0.0f ) { clip |= 4; } else if ( texCoords1 > 1.0f ) { clip |= 8; } texCoords[0] = texCoords0; texCoords[1] = texCoords1; // modulate the strength based on the height and color if ( dist2 > radius ) { clip |= 16; modulate = 0.0f; } else if ( dist2 < -radius ) { clip |= 32; modulate = 0.0f; } else { dist2 = Q_fabs(dist2); if ( dist2 < radius * 0.5f ) { modulate = 1.0f; } else { modulate = 2.0f * (radius - dist2) * scale; } } } clipBits[i] = clip; modulateVec = vec_ld(0,(float *)&modulate); modulateVec = vec_perm(modulateVec,modulateVec,modulatePerm); colorVec = vec_madd(floatColorVec0,modulateVec,zero); colorInt = vec_cts(colorVec,0); // RGBx colorShort = vec_pack(colorInt,colorInt); // RGBxRGBx colorChar = vec_packsu(colorShort,colorShort); // RGBxRGBxRGBxRGBx colorChar = vec_sel(colorChar,vSel,vSel); // RGBARGBARGBARGBA replace alpha with 255 vec_ste((vector unsigned int)colorChar,0,(unsigned int *)colors); // store color } // 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; } 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 ); backEnd.pc.c_totalIndexes += numIndexes; backEnd.pc.c_dlightIndexes += numIndexes; } }
void RB_StageIteratorLightmappedMultitexture( void ) { shaderCommands_t *input; input = &tess; // // 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( input->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 ); } //----(SA) 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" ); } }
/* ================== 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_R200_ARB_DrawInteraction =================== */ static void RB_R200_ARB_DrawInteraction( const drawInteraction_t *din ) { // check for the case we can't handle in a single pass (we could calculate this at shader parse time to optimize) if ( din->diffuseImage != globalImages->blackImage && din->specularImage != globalImages->blackImage && memcmp( din->specularMatrix, din->diffuseMatrix, sizeof( din->diffuseMatrix ) ) ) { // common->Printf( "Note: Shader %s drawn as two pass on R200\n", din->surf->shader->getName() ); // draw the specular as a separate pass with a black diffuse map drawInteraction_t d; d = *din; d.diffuseImage = globalImages->blackImage; memcpy( d.diffuseMatrix, d.specularMatrix, sizeof( d.diffuseMatrix ) ); RB_R200_ARB_DrawInteraction( &d ); // now fall through and draw the diffuse pass with a black specular map d = *din; din = &d; d.specularImage = globalImages->blackImage; } // load all the vertex program parameters qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_ORIGIN, din->localLightOrigin.ToFloatPtr() ); qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_VIEW_ORIGIN, din->localViewOrigin.ToFloatPtr() ); qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_S, din->lightProjection[0].ToFloatPtr() ); qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_T, din->lightProjection[1].ToFloatPtr() ); qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_Q, din->lightProjection[2].ToFloatPtr() ); qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_FALLOFF_S, din->lightProjection[3].ToFloatPtr() ); qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_BUMP_MATRIX_S, din->bumpMatrix[0].ToFloatPtr() ); qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_BUMP_MATRIX_T, din->bumpMatrix[1].ToFloatPtr() ); qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_DIFFUSE_MATRIX_S, din->diffuseMatrix[0].ToFloatPtr() ); qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_DIFFUSE_MATRIX_T, din->diffuseMatrix[1].ToFloatPtr() ); qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_SPECULAR_MATRIX_S, din->diffuseMatrix[0].ToFloatPtr() ); qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_SPECULAR_MATRIX_T, din->diffuseMatrix[1].ToFloatPtr() ); const srfTriangles_t *tri = din->surf->geo; idDrawVert *ac = (idDrawVert *)vertexCache.Position( tri->ambientCache ); qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->xyz ); static const float zero[4] = { 0, 0, 0, 0 }; static const float one[4] = { 1, 1, 1, 1 }; static const float negOne[4] = { -1, -1, -1, -1 }; switch ( din->vertexColor ) { case SVC_IGNORE: qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, zero ); qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, one ); break; case SVC_MODULATE: qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, one ); qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, zero ); break; case SVC_INVERSE_MODULATE: qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, negOne ); qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, one ); break; } // texture 0 = light projection // texture 1 = light falloff // texture 2 = surface diffuse // texture 3 = surface specular // texture 4 = surface bump // texture 5 = normalization cube map GL_SelectTexture( 5 ); if ( din->ambientLight ) { globalImages->ambientNormalMap->Bind(); } else { globalImages->normalCubeMapImage->Bind(); } GL_SelectTexture( 4 ); din->bumpImage->Bind(); GL_SelectTexture( 3 ); din->specularImage->Bind(); qglTexCoordPointer( 3, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->normal ); GL_SelectTexture( 2 ); din->diffuseImage->Bind(); qglTexCoordPointer( 3, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->tangents[1][0] ); GL_SelectTexture( 1 ); din->lightFalloffImage->Bind(); qglTexCoordPointer( 3, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->tangents[0][0] ); GL_SelectTexture( 0 ); din->lightImage->Bind(); qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->st[0] ); qglSetFragmentShaderConstantATI( GL_CON_0_ATI, din->diffuseColor.ToFloatPtr() ); qglSetFragmentShaderConstantATI( GL_CON_1_ATI, din->specularColor.ToFloatPtr() ); if ( din->vertexColor != SVC_IGNORE ) { qglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(idDrawVert), (void *)&ac->color ); qglEnableClientState( GL_COLOR_ARRAY ); RB_DrawElementsWithCounters( tri ); qglDisableClientState( GL_COLOR_ARRAY ); qglColor4f( 1, 1, 1, 1 ); } else { RB_DrawElementsWithCounters( tri ); } }
void RB_DistortionFill(void) { float alpha = tr_distortionAlpha; float spost = 0.0f; float spost2 = 0.0f; if ( glConfig.stencilBits < 4 ) { return; } //ok, cap the stupid thing now I guess if (!tr_distortionPrePost) { RB_CaptureScreenImage(); } qglEnable(GL_STENCIL_TEST); qglStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglDisable (GL_CLIP_PLANE0); GL_Cull( CT_TWO_SIDED ); //reset the view matrices and go into ortho mode qglMatrixMode(GL_PROJECTION); qglPushMatrix(); qglLoadIdentity(); qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 32, -1, 1); qglMatrixMode(GL_MODELVIEW); qglPushMatrix(); qglLoadIdentity(); if (tr_distortionStretch) { //override spost = tr_distortionStretch; spost2 = tr_distortionStretch; } else { //do slow stretchy effect spost = sin(tr.refdef.time*0.0005f); if (spost < 0.0f) { spost = -spost; } spost *= 0.2f; spost2 = sin(tr.refdef.time*0.0005f); if (spost2 < 0.0f) { spost2 = -spost2; } spost2 *= 0.08f; } if (alpha != 1.0f) { //blend GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_SRC_ALPHA); } else { //be sure to reset the draw state GL_State(0); } #ifdef HAVE_GLES qglColor4f(1.0f, 1.0f, 1.0f, alpha); GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY); GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY); if (!text) qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); if (glcol) qglDisableClientState( GL_COLOR_ARRAY ); GLfloat tex[] = { 0+spost2, 1-spost, 0+spost2, 0+spost, 1-spost2, 0+spost, 1-spost2, 1-spost }; GLfloat vtx[] = { 0, 0, 0, glConfig.vidHeight, glConfig.vidWidth, glConfig.vidHeight, glConfig.vidWidth, 0 }; qglTexCoordPointer( 2, GL_FLOAT, 0, tex ); qglVertexPointer ( 2, GL_FLOAT, 0, vtx ); qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); /* if (glcol) qglEnableClientState( GL_COLOR_ARRAY ); if (!text) qglDisableClientState( GL_TEXTURE_COORD_ARRAY );*/ #else qglBegin(GL_QUADS); qglColor4f(1.0f, 1.0f, 1.0f, alpha); qglTexCoord2f(0+spost2, 1-spost); qglVertex2f(0, 0); qglTexCoord2f(0+spost2, 0+spost); qglVertex2f(0, glConfig.vidHeight); qglTexCoord2f(1-spost2, 0+spost); qglVertex2f(glConfig.vidWidth, glConfig.vidHeight); qglTexCoord2f(1-spost2, 1-spost); qglVertex2f(glConfig.vidWidth, 0); qglEnd(); #endif if (tr_distortionAlpha == 1.0f && tr_distortionStretch == 0.0f) { //no overrides if (tr_distortionNegate) { //probably the crazy alternate saber trail alpha = 0.8f; GL_State(GLS_SRCBLEND_ZERO|GLS_DSTBLEND_ONE_MINUS_SRC_COLOR); } else { alpha = 0.5f; GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_SRC_ALPHA); } spost = sin(tr.refdef.time*0.0008f); if (spost < 0.0f) { spost = -spost; } spost *= 0.08f; spost2 = sin(tr.refdef.time*0.0008f); if (spost2 < 0.0f) { spost2 = -spost2; } spost2 *= 0.2f; #ifdef HAVE_GLES qglColor4f(1.0f, 1.0f, 1.0f, alpha); /* GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY); GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY); if (!text) qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); if (glcol) qglDisableClientState( GL_COLOR_ARRAY );*/ GLfloat tex[] = { 0+spost2, 1-spost, 0+spost2, 0+spost, 1-spost2, 0+spost, 1-spost2, 1-spost }; GLfloat vtx[] = { 0, 0, 0, glConfig.vidHeight, glConfig.vidWidth, glConfig.vidHeight, glConfig.vidWidth, 0 }; qglTexCoordPointer( 2, GL_FLOAT, 0, tex ); qglVertexPointer ( 2, GL_FLOAT, 0, vtx ); qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); #else qglBegin(GL_QUADS); qglColor4f(1.0f, 1.0f, 1.0f, alpha); qglTexCoord2f(0+spost2, 1-spost); qglVertex2f(0, 0); qglTexCoord2f(0+spost2, 0+spost); qglVertex2f(0, glConfig.vidHeight); qglTexCoord2f(1-spost2, 0+spost); qglVertex2f(glConfig.vidWidth, glConfig.vidHeight); qglTexCoord2f(1-spost2, 1-spost); qglVertex2f(glConfig.vidWidth, 0); qglEnd(); #endif } #ifdef HAVE_GLES if (glcol) qglEnableClientState( GL_COLOR_ARRAY ); if (!text) qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); #endif //pop the view matrices back qglMatrixMode(GL_PROJECTION); qglPopMatrix(); qglMatrixMode(GL_MODELVIEW); qglPopMatrix(); qglDisable( GL_STENCIL_TEST ); }
void CQuickSpriteSystem::Flush(void) { if (mNextVert==0) { return; } // // render the main pass // R_BindAnimatedImage( mTexBundle ); GL_State(mGLStateBits); // // set arrays and lock // qglTexCoordPointer( 2, GL_FLOAT, 0, mTextureCoords ); qglEnableClientState( GL_TEXTURE_COORD_ARRAY); qglEnableClientState( GL_COLOR_ARRAY); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, mColors ); qglVertexPointer (3, GL_FLOAT, 16, mVerts); if ( qglLockArraysEXT ) { qglLockArraysEXT(0, mNextVert); GLimp_LogComment( "glLockArraysEXT\n" ); } qglDrawArrays(GL_QUADS, 0, mNextVert); backEnd.pc.c_vertexes += mNextVert; backEnd.pc.c_indexes += mNextVert; backEnd.pc.c_totalIndexes += mNextVert; if (mUseFog) { // // render the fog pass // GL_Bind( tr.fogImage ); GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL ); // // set arrays and lock // qglTexCoordPointer( 2, GL_FLOAT, 0, mFogTextureCoords); // qglEnableClientState( GL_TEXTURE_COORD_ARRAY); // Done above qglDisableClientState( GL_COLOR_ARRAY ); qglColor4ubv((GLubyte *)&mFogColor); // qglVertexPointer (3, GL_FLOAT, 16, mVerts); // Done above qglDrawArrays(GL_QUADS, 0, mNextVert); // Second pass from fog backEnd.pc.c_totalIndexes += mNextVert; } // // unlock arrays // if (qglUnlockArraysEXT) { qglUnlockArraysEXT(); GLimp_LogComment( "glUnlockArraysEXT\n" ); } mNextVert=0; }
/* ** RB_StageIteratorVertexLitTexture */ void RB_StageIteratorVertexLitTexture( void ) { shaderCommands_t *input; shader_t *shader; input = &tess; shader = input->shader; // // compute colors // RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors ); // // 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_StageIteratorVertexLitTexturedUnfogged( %s ) ---\n", tess.shader->name) ); } // // set face culling appropriately // GL_Cull( shader->cullType ); // // set arrays and lock // qglEnableClientState( GL_COLOR_ARRAY); qglEnableClientState( GL_TEXTURE_COORD_ARRAY); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors ); qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][0] ); qglVertexPointer (3, GL_FLOAT, 16, input->xyz); if ( qglLockArraysEXT ) { qglLockArraysEXT(0, input->numVertexes); GLimp_LogComment( "glLockArraysEXT\n" ); } // // call special shade routine // R_BindAnimatedImage( &tess.xstages[0]->bundle[0] ); GL_State( tess.xstages[0]->stateBits ); R_DrawElements( input->numIndexes, input->indexes ); // // 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" ); } }
/* ** RB_IterateStagesGeneric */ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { int stage; for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { shaderStage_t *pStage = tess.xstages[stage]; if ( !pStage ) { break; } ComputeColors( pStage ); ComputeTexCoords( pStage ); if ( !setArraysOnce ) { qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, input->svars.colors ); } // // do multitexture // if ( pStage->bundle[1].image[0] != 0 ) { DrawMultitextured( input, stage ); } else { int fadeStart, fadeEnd; if ( !setArraysOnce ) { qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] ); } // // set state // R_BindAnimatedImage( &pStage->bundle[0] ); // Ridah, per stage fogging (detail textures) 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. //----(SA) fading model stuff fadeStart = backEnd.currentEntity->e.fadeStartTime; if ( fadeStart ) { fadeEnd = backEnd.currentEntity->e.fadeEndTime; if ( fadeStart > tr.refdef.time ) { // has not started to fade yet GL_State( pStage->stateBits ); } else { int i; unsigned int tempState; float alphaval; if ( fadeEnd < tr.refdef.time ) { // entity faded out completely continue; } alphaval = (float)( fadeEnd - tr.refdef.time ) / (float)( fadeEnd - fadeStart ); tempState = pStage->stateBits; // remove the current blend, and don't write to Z buffer tempState &= ~( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS | GLS_DEPTHMASK_TRUE ); // set the blend to src_alpha, dst_one_minus_src_alpha tempState |= ( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); GL_State( tempState ); GL_Cull( CT_FRONT_SIDED ); // modulate the alpha component of each vertex in the render list for ( i = 0; i < tess.numVertexes; i++ ) { tess.svars.colors[i][0] *= alphaval; tess.svars.colors[i][1] *= alphaval; tess.svars.colors[i][2] *= alphaval; tess.svars.colors[i][3] *= alphaval; } } } //----(SA) end // ydnar: lightmap stages should be GL_ONE GL_ZERO so they can be seen else if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) ) { unsigned int stateBits; stateBits = ( pStage->stateBits & ~( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) | ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); GL_State( stateBits ); } else { GL_State( pStage->stateBits ); } // // draw // R_DrawElements( input->numIndexes, input->indexes ); } // allow skipping out to show just lightmaps during development if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) ) { break; } } }
/* ** RB_IterateStagesGeneric */ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { int stage; int loc; GLenum prog; char texname[MAX_QPATH]; shaderStage_t *pStage; /*if ( input->shader->GLSL ) { prog = getShaderProgram(input->shader->GLSLName); if(prog == -1) return; for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { pStage = tess.xstages[stage]; if(pStage) { ComputeColors( pStage ); ComputeTexCoords( pStage ); if ( !setArraysOnce ) { qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, input->svars.colors ); } if(pStage->bundle[0].image) { qglActiveTextureARB(GL_TEXTURE0_ARB + stage); qglBindTexture (GL_TEXTURE_2D, pStage->bundle[0].image[0]->texnum); Com_sprintf(texname,sizeof(texname),"texture_%i\n", stage); loc = qglGetUniformLocationARB(prog, texname); qglUniform1iARB(loc, stage); } } } pStage = tess.xstages[0]; GL_State( pStage->stateBits ); R_DrawElements( input->numIndexes, input->indexes ); return; }*/ for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { shaderStage_t *pStage = tess.xstages[stage]; if ( !pStage ) { break; } ComputeColors( pStage ); ComputeTexCoords( pStage ); if ( !setArraysOnce ) { qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, input->svars.colors ); } // // do multitexture // if ( pStage->bundle[1].image[0] != 0 ) { //Lightmaps and such DrawMultitextured( input, stage ); } else { if ( !setArraysOnce ) { qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] ); } //LOL WTF, I don't need to do this! /*if(pStage->clamp) { qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); }*/ // // set state // if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer ) { GL_Bind( tr.whiteImage ); } else R_BindAnimatedImage( &pStage->bundle[0] ); GL_State( pStage->stateBits ); // // draw // R_DrawElements( input->numIndexes, input->indexes ); } // allow skipping out to show just lightmaps during development if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) ) { break; } } }
/* ** RB_StageIteratorGeneric */ void RB_StageIteratorGeneric( void ) { shaderCommands_t *input; shader_t *shader; input = &tess; shader = input->shader; RB_DeformTessGeometry(); // // 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_StageIteratorGeneric( %s ) ---\n", tess.shader->name) ); } // // set face culling appropriately // GL_Cull( shader->cullType ); // set polygon offset if necessary if ( shader->polygonOffset ) { qglEnable( GL_POLYGON_OFFSET_FILL ); qglPolygonOffset( r_offsetFactor->value, r_offsetUnits->value ); } // // if there is only a single pass then we can enable color // and texture arrays before we compile, otherwise we need // to avoid compiling those arrays since they will change // during multipass rendering // if ( tess.numPasses > 1 || shader->multitextureEnv ) { setArraysOnce = qfalse; qglDisableClientState (GL_COLOR_ARRAY); qglDisableClientState (GL_TEXTURE_COORD_ARRAY); } else { setArraysOnce = qtrue; qglEnableClientState( GL_COLOR_ARRAY); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors ); qglEnableClientState( GL_TEXTURE_COORD_ARRAY); qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] ); } // // lock XYZ // qglVertexPointer (3, GL_FLOAT, 16, input->xyz); // padded for SIMD if (qglLockArraysEXT) { qglLockArraysEXT(0, input->numVertexes); GLimp_LogComment( "glLockArraysEXT\n" ); } // // enable color and texcoord arrays after the lock if necessary // if ( !setArraysOnce ) { qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); qglEnableClientState( GL_COLOR_ARRAY ); } // // call shader function // RB_IterateStagesGeneric( input ); // // now do any dynamic lighting needed // if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) { ProjectDlightTexture(); } // // now do fog // if ( tess.fogNum && tess.shader->fogPass ) { RB_FogPass(); } // // unlock arrays // if (qglUnlockArraysEXT) { qglUnlockArraysEXT(); GLimp_LogComment( "glUnlockArraysEXT\n" ); } // // reset polygon offset // if ( shader->polygonOffset ) { qglDisable( GL_POLYGON_OFFSET_FILL ); } }
/* * Interpolates between two frames and origins */ void R_DrawAliasFrameLerp ( dmdl_t *paliashdr, float backlerp ) { #if defined(VERTEX_ARRAYS) uint16_t total; GLenum type; #endif float l; daliasframe_t *frame, *oldframe; dtrivertx_t *v, *ov, *verts; int *order; int count; float frontlerp; float alpha; vec3_t move, delta, vectors [ 3 ]; vec3_t frontv, backv; int i; int index_xyz; float *lerp; frame = (daliasframe_t *) ( (byte *) paliashdr + paliashdr->ofs_frames + currententity->frame * paliashdr->framesize ); verts = v = frame->verts; oldframe = (daliasframe_t *) ( (byte *) paliashdr + paliashdr->ofs_frames + currententity->oldframe * paliashdr->framesize ); ov = oldframe->verts; order = (int *) ( (byte *) paliashdr + paliashdr->ofs_glcmds ); if ( currententity->flags & RF_TRANSLUCENT ) { alpha = currententity->alpha; } else { alpha = 1.0; } if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM ) ) { qglDisable( GL_TEXTURE_2D ); } frontlerp = 1.0 - backlerp; /* move should be the delta back to the previous frame * backlerp */ VectorSubtract( currententity->oldorigin, currententity->origin, delta ); AngleVectors( currententity->angles, vectors [ 0 ], vectors [ 1 ], vectors [ 2 ] ); move [ 0 ] = DotProduct( delta, vectors [ 0 ] ); /* forward */ move [ 1 ] = -DotProduct( delta, vectors [ 1 ] ); /* left */ move [ 2 ] = DotProduct( delta, vectors [ 2 ] ); /* up */ VectorAdd( move, oldframe->translate, move ); for ( i = 0; i < 3; i++ ) { move [ i ] = backlerp * move [ i ] + frontlerp * frame->translate [ i ]; } for ( i = 0; i < 3; i++ ) { frontv [ i ] = frontlerp * frame->scale [ i ]; backv [ i ] = backlerp * oldframe->scale [ i ]; } lerp = s_lerped [ 0 ]; R_LerpVerts( paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv ); if ( gl_vertex_arrays->value ) { float colorArray [ MAX_VERTS * 4 ]; qglEnableClientState( GL_VERTEX_ARRAY ); qglVertexPointer( 3, GL_FLOAT, 16, s_lerped ); if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM ) ) { qglColor4f( shadelight [ 0 ], shadelight [ 1 ], shadelight [ 2 ], alpha ); } else { qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 3, GL_FLOAT, 0, colorArray ); /* pre light everything */ for ( i = 0; i < paliashdr->num_xyz; i++ ) { float l = shadedots [ verts [ i ].lightnormalindex ]; colorArray [ i * 3 + 0 ] = l * shadelight [ 0 ]; colorArray [ i * 3 + 1 ] = l * shadelight [ 1 ]; colorArray [ i * 3 + 2 ] = l * shadelight [ 2 ]; } } #if !defined(VERTEX_ARRAYS) if ( qglLockArraysEXT != 0 ) { qglLockArraysEXT( 0, paliashdr->num_xyz ); } #endif while ( 1 ) { /* get the vertex count and primitive type */ count = *order++; if ( !count ) { break; /* done */ } if ( count < 0 ) { count = -count; #if defined(VERTEX_ARRAYS) type = GL_TRIANGLE_FAN; #else qglBegin( GL_TRIANGLE_FAN ); #endif } else { #if defined(VERTEX_ARRAYS) type = GL_TRIANGLE_STRIP; #else qglBegin( GL_TRIANGLE_STRIP ); #endif } #if defined(VERTEX_ARRAYS) total = count; GLfloat vtx[3*total]; GLfloat tex[2*total]; uint32_t index_vtx = 0; uint32_t index_tex = 0; #endif if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM ) ) { do { index_xyz = order [ 2 ]; order += 3; #if defined(VERTEX_ARRAYS) vtx[index_vtx++] = s_lerped [ index_xyz ][0]; vtx[index_vtx++] = s_lerped [ index_xyz ][1]; vtx[index_vtx++] = s_lerped [ index_xyz ][2]; #else qglVertex3fv( s_lerped [ index_xyz ] ); #endif } while ( --count ); } else { do { #if defined(VERTEX_ARRAYS) tex[index_tex++] = ( (float *) order ) [ 0 ]; tex[index_tex++] = ( (float *) order ) [ 1 ]; index_xyz = order [ 2 ]; order += 3; #else /* texture coordinates come from the draw list */ qglTexCoord2f( ( (float *) order ) [ 0 ], ( (float *) order ) [ 1 ] ); index_xyz = order [ 2 ]; order += 3; qglArrayElement( index_xyz ); #endif } while ( --count ); } #if defined(VERTEX_ARRAYS) qglEnableClientState( GL_VERTEX_ARRAY ); qglVertexPointer( 3, GL_FLOAT, 0, vtx ); qglDrawArrays( type, 0, total ); qglDisableClientState( GL_VERTEX_ARRAY ); #else qglEnd(); #endif } #if !defined(VERTEX_ARRAYS) if ( qglUnlockArraysEXT != 0 ) { qglUnlockArraysEXT(); } #endif } else { while ( 1 ) { /* get the vertex count and primitive type */ count = *order++; if ( !count ) { break; /* done */ } if ( count < 0 ) { count = -count; #if defined(VERTEX_ARRAYS) type = GL_TRIANGLE_FAN; #else qglBegin( GL_TRIANGLE_FAN ); #endif } else { #if defined(VERTEX_ARRAYS) type = GL_TRIANGLE_STRIP; #else qglBegin( GL_TRIANGLE_STRIP ); #endif } #if defined(VERTEX_ARRAYS) total = count; GLfloat vtx[3*total]; GLfloat tex[2*total]; GLfloat clr[4*total]; uint32_t index_vtx = 0; uint32_t index_tex = 0; uint32_t index_clr = 0; #endif if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) ) { do { index_xyz = order [ 2 ]; order += 3; #if defined(VERTEX_ARRAYS) clr[index_clr++] = shadelight [ 0 ]; clr[index_clr++] = shadelight [ 1 ]; clr[index_clr++] = shadelight [ 2 ]; clr[index_clr++] = alpha; vtx[index_vtx++] = s_lerped [ index_xyz ][ 0 ]; vtx[index_vtx++] = s_lerped [ index_xyz ][ 1 ]; vtx[index_vtx++] = s_lerped [ index_xyz ][ 2 ]; #else qglColor4f( shadelight [ 0 ], shadelight [ 1 ], shadelight [ 2 ], alpha ); qglVertex3fv( s_lerped [ index_xyz ] ); #endif } while ( --count ); } else { do { /* texture coordinates come from the draw list */ #if defined(VERTEX_ARRAYS) tex[index_tex++] = ( (float *) order ) [ 0 ]; tex[index_tex++] = ( (float *) order ) [ 1 ]; #else qglTexCoord2f( ( (float *) order ) [ 0 ], ( (float *) order ) [ 1 ] ); #endif index_xyz = order [ 2 ]; order += 3; /* normals and vertexes come from the frame list */ l = shadedots [ verts [ index_xyz ].lightnormalindex ]; #if defined(VERTEX_ARRAYS) clr[index_clr++] = l * shadelight [ 0 ]; clr[index_clr++] = l * shadelight [ 1 ]; clr[index_clr++] = l * shadelight [ 2 ]; clr[index_clr++] = alpha; vtx[index_vtx++] = s_lerped [ index_xyz ][ 0 ]; vtx[index_vtx++] = s_lerped [ index_xyz ][ 1 ]; vtx[index_vtx++] = s_lerped [ index_xyz ][ 2 ]; #else qglColor4f( l * shadelight [ 0 ], l * shadelight [ 1 ], l * shadelight [ 2 ], alpha ); qglVertex3fv( s_lerped [ index_xyz ] ); #endif } while ( --count ); } #if defined(VERTEX_ARRAYS) qglEnableClientState( GL_VERTEX_ARRAY ); qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); qglEnableClientState( GL_COLOR_ARRAY ); qglVertexPointer( 3, GL_FLOAT, 0, vtx ); qglTexCoordPointer( 2, GL_FLOAT, 0, tex ); qglColorPointer( 4, GL_FLOAT, 0, clr ); qglDrawArrays( type, 0, total ); qglDisableClientState( GL_VERTEX_ARRAY ); qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); qglDisableClientState( GL_COLOR_ARRAY ); #else qglEnd(); #endif } } if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM ) ) { qglEnable( GL_TEXTURE_2D ); } }
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 CQuickSpriteSystem::Flush(void) { if (mNextVert==0) { return; } /* if (mUseFog && r_drawfog->integer == 2 && mFogIndex == tr.world->globalFog) { //enable hardware fog when we draw this thing if applicable -rww fog_t *fog = tr.world->fogs + mFogIndex; qglFogf(GL_FOG_MODE, GL_EXP2); qglFogf(GL_FOG_DENSITY, logtestExp2 / fog->parms.depthForOpaque); qglFogfv(GL_FOG_COLOR, fog->parms.color); qglEnable(GL_FOG); } */ //this should not be needed, since I just wait to disable fog for the surface til after surface sprites are done // // render the main pass // R_BindAnimatedImage( mTexBundle ); GL_State(mGLStateBits); // // set arrays and lock // qglTexCoordPointer( 2, GL_FLOAT, 0, mTextureCoords ); qglEnableClientState( GL_TEXTURE_COORD_ARRAY); qglEnableClientState( GL_COLOR_ARRAY); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, mColors ); qglVertexPointer (3, GL_FLOAT, 16, mVerts); if ( qglLockArraysEXT ) { qglLockArraysEXT(0, mNextVert); GLimp_LogComment( "glLockArraysEXT\n" ); } qglDrawArrays(GL_QUADS, 0, mNextVert); backEnd.pc.c_vertexes += mNextVert; backEnd.pc.c_indexes += mNextVert; backEnd.pc.c_totalIndexes += mNextVert; //only for software fog pass (global soft/volumetric) -rww if (mUseFog && (r_drawfog->integer != 2 || mFogIndex != tr.world->globalFog)) { fog_t *fog = tr.world->fogs + mFogIndex; // // render the fog pass // GL_Bind( tr.fogImage ); GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL ); // // set arrays and lock // qglTexCoordPointer( 2, GL_FLOAT, 0, mFogTextureCoords); // qglEnableClientState( GL_TEXTURE_COORD_ARRAY); // Done above qglDisableClientState( GL_COLOR_ARRAY ); qglColor4ubv((GLubyte *)&fog->colorInt); // qglVertexPointer (3, GL_FLOAT, 16, mVerts); // Done above qglDrawArrays(GL_QUADS, 0, mNextVert); // Second pass from fog backEnd.pc.c_totalIndexes += mNextVert; } // // unlock arrays // if (qglUnlockArraysEXT) { qglUnlockArraysEXT(); GLimp_LogComment( "glUnlockArraysEXT\n" ); } mNextVert=0; }
static void ProjectDlightTexture_scalar( 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; vec3_t floatColor; float modulate = 0.0f; 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; if(r_greyscale->integer) { float luminance; luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; floatColor[0] = floatColor[1] = floatColor[2] = luminance; } else if(r_greyscale->value) { float luminance; luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value); floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value); floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value); } else { 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 ) { int clip = 0; vec3_t dist; VectorSubtract( origin, tess.xyz[i], dist ); backEnd.pc.c_dlightVertexes++; texCoords[0] = 0.5f + dist[0] * scale; texCoords[1] = 0.5f + dist[1] * scale; if( !r_dlightBacks->integer && // dist . tess.normal[i] ( dist[0] * tess.normal[i][0] + dist[1] * tess.normal[i][1] + dist[2] * tess.normal[i][2] ) < 0.0f ) { clip = 63; } else { 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; } texCoords[0] = texCoords[0]; texCoords[1] = texCoords[1]; // modulate the strength based on the height and color if ( dist[2] > radius ) { clip |= 16; modulate = 0.0f; } else if ( dist[2] < -radius ) { clip |= 32; modulate = 0.0f; } else { dist[2] = Q_fabs(dist[2]); if ( dist[2] < radius * 0.5f ) { modulate = 1.0f; } else { modulate = 2.0f * (radius - dist[2]) * scale; } } } clipBits[i] = clip; colors[0] = ri.ftol(floatColor[0] * modulate); colors[1] = ri.ftol(floatColor[1] * modulate); colors[2] = ri.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; } 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 ); backEnd.pc.c_totalIndexes += numIndexes; backEnd.pc.c_dlightIndexes += numIndexes; } }
/* ** RB_IterateStagesGeneric */ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { int stage; qboolean overridealpha, overridergb; qboolean didanyoverride = qfalse; int oldalphaGen = 0, oldrgbGen = 0; for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { shaderStage_t *pStage = tess.xstages[stage]; if ( !pStage ) { break; } // Override the shader rgb tint if requested. if(backEnd.currentEntity->e.renderfx & RF_RGB_TINT) { overridergb = qtrue; oldrgbGen = pStage->rgbGen; pStage->rgbGen = CGEN_ENTITY; } else overridergb = qfalse; // Override the shader alpha channel if requested. if(backEnd.currentEntity->e.renderfx & RF_FORCE_ENT_ALPHA) { overridealpha = qtrue; oldalphaGen = pStage->alphaGen; pStage->alphaGen = AGEN_ENTITY; } else overridealpha = qfalse; ComputeColors( pStage ); if(overridergb) pStage->rgbGen = (colorGen_t)oldrgbGen; if(overridealpha) pStage->alphaGen = (alphaGen_t)oldalphaGen; ComputeTexCoords( pStage ); if ( !setArraysOnce ) { qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, input->svars.colors ); } // // do multitexture // if ( pStage->bundle[1].image[0] != 0 ) { DrawMultitextured( input, stage ); } else { if ( !setArraysOnce ) { qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] ); } // // set state // if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig2.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer ) { GL_Bind( tr.whiteImage ); } else R_BindAnimatedImage( &pStage->bundle[0] ); if(overridealpha && backEnd.currentEntity->e.shaderRGBA[3] < 0xFF && !(pStage->stateBits & GLS_ATEST_BITS)) { GL_State((pStage->stateBits & ~(GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS | GLS_ATEST_BITS)) // remove the shader set values. | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_ATEST_GT_0); // Now add the default values. didanyoverride = qtrue; } //if(overridergb && (backEnd.currentEntity->e.shaderRGBA[0] < 0xFF || backEnd.currentEntity->e.shaderRGBA[1] < 0xFF || backEnd.currentEntity->e.shaderRGBA[2] < 0xFF) && !(pStage->stateBits & GLS_ATEST_BITS)) //{ // GL_State((pStage->stateBits & ~(GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS | GLS_ATEST_BITS)) // remove the shader set values. // | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_ATEST_GT_0); // Now add the default values. // didanyoverride = qtrue; //} //else if(!didanyoverride) GL_State( pStage->stateBits ); // // draw // R_DrawElements( input->numIndexes, input->indexes ); } // allow skipping out to show just lightmaps during development if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) ) { break; } } }