/* ================ DrawTris Draws triangle outlines for debugging ================ */ static void DrawTris (shaderCommands_t *input) { GL_Bind( tr.whiteImage ); qglColor3f (1,1,1); GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE ); qglDepthRange( 0, 0 ); qglDisableClientState (GL_COLOR_ARRAY); qglDisableClientState (GL_TEXTURE_COORD_ARRAY); qglVertexPointer (3, GL_FLOAT, 16, input->xyz); // padded for SIMD if (qglLockArraysEXT) { qglLockArraysEXT(0, input->numVertexes); GLimp_LogComment( "glLockArraysEXT\n" ); } #ifdef HAVE_GLES qglDrawElements( GL_LINE_STRIP, input->numIndexes, GL_INDEX_TYPE, input->indexes ); #else R_DrawElements( input->numIndexes, input->indexes ); #endif if (qglUnlockArraysEXT) { qglUnlockArraysEXT(); GLimp_LogComment( "glUnlockArraysEXT\n" ); } qglDepthRange( 0, 1 ); }
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 //*TODO* Try to switch from many DrawArrays of GL_TRIANGLE_STRIP to a single DrawArrays of TRIANGLES to see if it perform better qglVertexPointer (3, GL_FLOAT, 0, vtx); qglTexCoordPointer(2, GL_FLOAT, 0, tex); qglDrawArrays(GL_TRIANGLE_STRIP, 0, idx); #else qglEnd(); #endif } #ifdef HAVE_GLES if (glcol) qglEnableClientState(GL_COLOR_ARRAY); if (!text) qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); #endif }
//DRAWCEL static void DrawCel (shaderCommands_t *input) { GL_Bind( tr.whiteImage ); qglColor3f (1,1,1); GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE ); qglDisableClientState (GL_COLOR_ARRAY); qglDisableClientState (GL_TEXTURE_COORD_ARRAY); qglVertexPointer (3, GL_FLOAT, 16, input->xyz); // padded for SIMD if (qglLockArraysEXT) { qglLockArraysEXT(0, input->numVertexes); GLimp_LogComment( "glLockArraysEXT\n" ); } R_DrawCel( input->numIndexes, input->indexes ); if (qglUnlockArraysEXT) { qglUnlockArraysEXT(); GLimp_LogComment( "glUnlockArraysEXT\n" ); } }
/* ================== RB_NV20_DI_DiffuseColorPass ================== */ static void RB_NV20_DI_DiffuseColorPass(const drawInteraction_t *din) { RB_LogComment("---------- RB_NV20_DiffuseColorPass ----------\n"); GL_State(GLS_SRCBLEND_DST_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_ALPHAMASK | backEnd.depthFunc); // texture 0 will be the per-surface diffuse map #ifdef MACOS_X GL_SelectTexture(0); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(0); #endif din->diffuseImage->Bind(); // texture 1 will be the light projected texture #ifdef MACOS_X GL_SelectTexture(1); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(1); #endif din->lightImage->Bind(); // texture 2 is disabled #ifdef MACOS_X GL_SelectTexture(2); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(2); #endif globalImages->BindNull(); // texture 3 is disabled #ifdef MACOS_X GL_SelectTexture(3); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(3); #endif globalImages->BindNull(); // bind our "fragment program" RB_NV20_DiffuseColorFragment(); // override one parameter for inverted vertex color if (din->vertexColor == SVC_INVERSE_MODULATE) { qglCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_PRIMARY_COLOR_NV, GL_UNSIGNED_INVERT_NV, GL_RGB); } // draw it qglBindProgramARB(GL_VERTEX_PROGRAM_ARB, VPROG_NV20_DIFFUSE_COLOR); RB_DrawElementsWithCounters(din->surf->geo); }
/* ================= RB_ShadowFinish Darken everything that is is a shadow volume. We have to delay this until everything has been shadowed, because otherwise shadows from different body parts would overlap and double darken. ================= */ void RB_ShadowFinish(void) { if (r_shadows->integer != 2) { return; } if (glConfig.stencilBits < 4) { return; } qglEnable(GL_STENCIL_TEST); qglStencilFunc(GL_NOTEQUAL, 0, 255); qglDisable(GL_CLIP_PLANE0); qglDisable(GL_CULL_FACE); GL_Bind(tr.whiteImage); qglLoadIdentity(); qglColor3f(0.6f, 0.6f, 0.6f); GL_State(GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO); GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY); GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY); if (text) { qglDisableClientState(GL_TEXTURE_COORD_ARRAY); } if (glcol) { qglDisableClientState(GL_COLOR_ARRAY); } GLfloat vtx[] = { -100, 100, -10, 100, 100, -10, 100, -100, -10, -100, -100, -10 }; qglVertexPointer(3, GL_FLOAT, 0, vtx); qglDrawArrays(GL_TRIANGLE_FAN, 0, 4); if (text) { qglEnableClientState(GL_TEXTURE_COORD_ARRAY); } if (glcol) { qglEnableClientState(GL_COLOR_ARRAY); } qglColor4f(1, 1, 1, 1); qglDisable(GL_STENCIL_TEST); }
static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] ) { int s, t, i = 0; int size; glIndex_t *indicies; size = (maxs[1] - mins[1]) * (maxs[0] - mins[0] + 1); indicies = ri.Hunk_AllocateTempMemory(sizeof(glIndex_t) * size); GL_Bind( image ); for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) { for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) { indicies[i++] = t * (SKY_SUBDIVISIONS + 1) + s; indicies[i++] = (t + 1) * (SKY_SUBDIVISIONS + 1) + s; } } qglDisableClientState(GL_COLOR_ARRAY); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); qglTexCoordPointer(2, GL_FLOAT, 0, s_skyTexCoords); qglVertexPointer(3, GL_FLOAT, 0, s_skyPoints); qglDrawElements(GL_TRIANGLE_STRIP, i, GL_INDEX_TYPE, indicies); Hunk_FreeTempMemory(indicies); }
/* ====================== RB_FinishStageTexture ====================== */ void RB_FinishStageTexture( const textureStage_t *texture, const drawSurf_t *surf ) { if ( texture->texgen == TG_DIFFUSE_CUBE || texture->texgen == TG_SKYBOX_CUBE || texture->texgen == TG_WOBBLESKY_CUBE ) { qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), (void *)&(((idDrawVert *)vertexCache.Position( surf->geo->ambientCache ))->st) ); } if ( texture->texgen == TG_REFLECT_CUBE ) { 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 ( texture->hasMatrix ) { qglMatrixMode( GL_TEXTURE ); qglLoadIdentity(); qglMatrixMode( GL_MODELVIEW ); } }
/* ============= RB_DrawMeshTris Re-draws a mesh in outline mode ============= */ void RB_DrawMeshTris (void) { int i, numTMUs = 0; if (!r_showtris->value) return; if (r_showtris->value == 1) GL_Disable(GL_DEPTH_TEST); qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE); for (i=0; i<glConfig.max_texunits; i++) if (glState.activetmu[i]) { numTMUs++; GL_DisableTexture (i); } qglDisableClientState (GL_COLOR_ARRAY); qglColor4f(1.0, 1.0, 1.0, 1.0); RB_DrawArrays (); qglEnableClientState (GL_COLOR_ARRAY); for (i=0; i<numTMUs; i++) GL_EnableTexture(i); qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); if (r_showtris->value == 1) GL_Enable(GL_DEPTH_TEST); }
/* ============= RB_DrawMeshTris Re-draws a mesh in outline mode ============= */ void RB_DrawMeshTris (GLenum polyMode, int numTMUs) { int i; if (!r_showtris->value) return; if (r_showtris->value == 1) GL_Disable(GL_DEPTH_TEST); qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE); for (i=0; i<numTMUs; i++) GL_DisableTexture (i); qglDisableClientState (GL_COLOR_ARRAY); qglColor4f(1.0, 1.0, 1.0, 1.0); RB_DrawArrays(polyMode); qglEnableClientState (GL_COLOR_ARRAY); for (i=0; i<numTMUs; i++) GL_EnableTexture(i); qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); if (r_showtris->value == 1) GL_Enable(GL_DEPTH_TEST); }
/* ====================== RB_SetDefaultGLState This should initialize all GL state that any part of the entire program may touch, including the editor. ====================== */ void RB_SetDefaultGLState( void ) { int i; RB_LogComment( "--- R_SetDefaultGLState ---\n" ); qglClearDepth( 1.0f ); qglColor4f (1,1,1,1); // the vertex array is always enabled qglEnableClientState( GL_VERTEX_ARRAY ); qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); qglDisableClientState( GL_COLOR_ARRAY ); // // make sure our GL state vector is set correctly // memset( &backEnd.glState, 0, sizeof( backEnd.glState ) ); backEnd.glState.forceGlState = true; qglColorMask( 1, 1, 1, 1 ); qglEnable( GL_DEPTH_TEST ); qglEnable( GL_BLEND ); qglEnable( GL_SCISSOR_TEST ); qglEnable( GL_CULL_FACE ); qglDisable( GL_LIGHTING ); qglDisable( GL_LINE_STIPPLE ); qglDisable( GL_STENCIL_TEST ); qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); qglDepthMask( GL_TRUE ); qglDepthFunc( GL_ALWAYS ); qglCullFace( GL_FRONT_AND_BACK ); qglShadeModel( GL_SMOOTH ); if ( r_useScissor.GetBool() ) { qglScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight ); } for ( i = glConfig.maxTextureUnits - 1 ; i >= 0 ; i-- ) { GL_SelectTexture( i ); // object linear texgen is our default 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 ); qglTexGenf( GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR ); GL_TexEnv( GL_MODULATE ); qglDisable( GL_TEXTURE_2D ); if ( glConfig.texture3DAvailable ) { qglDisable( GL_TEXTURE_3D ); } if ( glConfig.cubeMapAvailable ) { qglDisable( GL_TEXTURE_CUBE_MAP_EXT ); } } }
/* ================== RB_NV20_DrawInteraction ================== */ static void RB_NV20_DrawInteraction(const drawInteraction_t *din) { const drawSurf_t *surf = din->surf; // 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->specularMatrix[0].ToFloatPtr()); qglProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, PP_SPECULAR_MATRIX_T, din->specularMatrix[1].ToFloatPtr()); // set the constant colors qglCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, din->diffuseColor.ToFloatPtr()); qglCombinerParameterfvNV(GL_CONSTANT_COLOR1_NV, din->specularColor.ToFloatPtr()); // vertex color passes should be pretty rare (cross-faded bump map surfaces), so always // run them down as three-passes if (din->vertexColor != SVC_IGNORE) { qglEnableClientState(GL_COLOR_ARRAY); RB_NV20_DI_BumpAndLightPass(din, false); RB_NV20_DI_DiffuseColorPass(din); RB_NV20_DI_SpecularColorPass(din); qglDisableClientState(GL_COLOR_ARRAY); return; } qglColor3f(1, 1, 1); // on an ideal card, we would now just bind the textures and call a // single pass vertex / fragment program, but // on NV20, we need to decide which single / dual / tripple pass set of programs to use // ambient light could be done as a single pass if we want to optimize for it // monochrome light is two passes int internalFormat = din->lightImage->internalFormat; if ((r_useNV20MonoLights.GetInteger() == 2) || (din->lightImage->isMonochrome && r_useNV20MonoLights.GetInteger())) { // do a two-pass rendering RB_NV20_DI_BumpAndLightPass(din, true); RB_NV20_DI_DiffuseAndSpecularColorPass(din); } else { // general case is three passes // ( bump dot lightDir ) * lightFalloff // diffuse * lightProject // specular * ( bump dot halfAngle extended ) * lightProject RB_NV20_DI_BumpAndLightPass(din, false); RB_NV20_DI_DiffuseColorPass(din); RB_NV20_DI_SpecularColorPass(din); } }
/* ===================== RB_StencilShadowPass Stencil test should already be enabled, and the stencil buffer should have been set to 128 on any surfaces that might receive shadows ===================== */ void RB_StencilShadowPass(const drawSurf_t *drawSurfs) { if (!r_shadows.GetBool()) { return; } if (!drawSurfs) { return; } RB_LogComment("---------- RB_StencilShadowPass ----------\n"); globalImages->BindNull(); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); // for visualizing the shadows if (r_showShadows.GetInteger()) { if (r_showShadows.GetInteger() == 2) { // draw filled in GL_State(GLS_DEPTHMASK | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_LESS); } else { // draw as lines, filling the depth buffer GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_POLYMODE_LINE | GLS_DEPTHFUNC_ALWAYS); } } else { // don't write to the color buffer, just the stencil buffer GL_State(GLS_DEPTHMASK | GLS_COLORMASK | GLS_ALPHAMASK | GLS_DEPTHFUNC_LESS); } if (r_shadowPolygonFactor.GetFloat() || r_shadowPolygonOffset.GetFloat()) { qglPolygonOffset(r_shadowPolygonFactor.GetFloat(), -r_shadowPolygonOffset.GetFloat()); qglEnable(GL_POLYGON_OFFSET_FILL); } qglStencilFunc(GL_ALWAYS, 1, 255); if (glConfig.depthBoundsTestAvailable && r_useDepthBoundsTest.GetBool()) { qglEnable(GL_DEPTH_BOUNDS_TEST_EXT); } RB_RenderDrawSurfChainWithFunction(drawSurfs, RB_T_Shadow); GL_Cull(CT_FRONT_SIDED); if (r_shadowPolygonFactor.GetFloat() || r_shadowPolygonOffset.GetFloat()) { qglDisable(GL_POLYGON_OFFSET_FILL); } if (glConfig.depthBoundsTestAvailable && r_useDepthBoundsTest.GetBool()) { qglDisable(GL_DEPTH_BOUNDS_TEST_EXT); } qglEnableClientState(GL_TEXTURE_COORD_ARRAY); qglStencilFunc(GL_GEQUAL, 128, 255); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); }
/* =================== RB_OutlinesPass Draws outlines on surfaces with shader.hasOutlines set =================== */ static void RB_OutlinesPass( void ) { int outlines; float outlinesAlpha; outlines = r_outlines->value; outlinesAlpha = r_outlinesAlpha->value; if ( !tess.shader->hasOutlines ) return; if ( !r_outlines->integer ) return; GL_Bind( tr.whiteImage ); qglColor4f( 0, 0, 0, outlinesAlpha ); GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); qglPolygonMode( GL_BACK, GL_LINE ); qglLineWidth( outlines + 1 ); qglCullFace( GL_BACK ); qglDisableClientState( GL_COLOR_ARRAY ); qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); qglVertexPointer (3, GL_FLOAT, 16, tess.xyz); // padded for SIMD if (qglLockArraysEXT) { qglLockArraysEXT(0, tess.numVertexes); GLimp_LogComment( "glLockArraysEXT\n" ); } R_DrawElements( tess.numIndexes, tess.indexes ); if (qglUnlockArraysEXT) { qglUnlockArraysEXT(); GLimp_LogComment( "glUnlockArraysEXT\n" ); } // FIX: Must reset these manually or renderer will b0rk! qglCullFace( GL_FRONT ); qglLineWidth( 1 ); }
void CMistyFog2::Render(CWorldEffectsSystem *system) { if (mFadeAlpha <= 0.0) { return; } qglMatrixMode(GL_PROJECTION); qglPushMatrix(); qglLoadIdentity (); MYgluPerspective (80.0, 1.0, 4, 2048.0); qglMatrixMode(GL_MODELVIEW); qglPushMatrix(); qglLoadIdentity (); qglRotatef (-90, 1, 0, 0); // put Z going up qglRotatef (90, 0, 0, 1); // put Z going up qglRotatef (0, 1, 0, 0); qglRotatef (-90, 0, 1, 0); qglRotatef (-90, 0, 0, 1); qglDisable(GL_TEXTURE_2D); GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_ONE); qglShadeModel (GL_SMOOTH); qglColorPointer(4, GL_FLOAT, 0, mColors); qglEnableClientState(GL_COLOR_ARRAY); qglVertexPointer( 3, GL_FLOAT, 0, mVerts ); qglEnableClientState(GL_VERTEX_ARRAY); if (qglLockArraysEXT) { qglLockArraysEXT(0, MISTYFOG_HEIGHT*MISTYFOG_WIDTH); } qglDrawElements(GL_QUADS, (MISTYFOG_HEIGHT-1)*(MISTYFOG_WIDTH-1)*4, GL_UNSIGNED_INT, mIndexes); if ( qglUnlockArraysEXT ) { qglUnlockArraysEXT(); } qglDisableClientState(GL_COLOR_ARRAY); // qglDisableClientState(GL_VERTEX_ARRAY); backend doesn't ever re=enable this properly qglPopMatrix(); qglMatrixMode(GL_PROJECTION); qglPopMatrix(); qglMatrixMode(GL_MODELVIEW); // bug somewhere in the backend which requires this }
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_STD_FillDepthBuffer If we are rendering a subview with a near clip plane, use a second texture to force the alpha test to fail when behind that clip plane ===================== */ void RB_STD_FillDepthBuffer(drawSurf_t **drawSurfs, int numDrawSurfs) { // if we are just doing 2D rendering, no need to fill the depth buffer if (!backEnd.viewDef->viewEntitys) { return; } RB_LogComment("---------- RB_STD_FillDepthBuffer ----------\n"); // enable the second texture for mirror plane clipping if needed if (backEnd.viewDef->numClipPlanes) { GL_SelectTexture(1); globalImages->alphaNotchImage->Bind(); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); qglEnable(GL_TEXTURE_GEN_S); qglTexCoord2f(1, 0.5); } // the first texture will be used for alpha tested surfaces GL_SelectTexture(0); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); // decal surfaces may enable polygon offset qglPolygonOffset(r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat()); GL_State(GLS_DEPTHFUNC_LESS); // Enable stencil test if we are going to be using it for shadows. // If we didn't do this, it would be legal behavior to get z fighting // from the ambient pass and the light passes. qglEnable(GL_STENCIL_TEST); qglStencilFunc(GL_ALWAYS, 1, 255); RB_RenderDrawSurfListWithFunction(drawSurfs, numDrawSurfs, RB_T_FillDepthBuffer); if (backEnd.viewDef->numClipPlanes) { GL_SelectTexture(1); globalImages->BindNull(); qglDisable(GL_TEXTURE_GEN_S); GL_SelectTexture(0); } }
void Gui_DrawLoadScreen(int value) { qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); qglPushAttrib(GL_ENABLE_BIT | GL_PIXEL_MODE_BIT | GL_COLOR_BUFFER_BIT); qglPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); qglPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); qglPixelStorei(GL_UNPACK_ALIGNMENT, 1); qglEnableClientState(GL_VERTEX_ARRAY); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); qglEnableClientState(GL_COLOR_ARRAY); qglDisableClientState(GL_NORMAL_ARRAY); qglEnable(GL_BLEND); qglEnable(GL_TEXTURE_2D); qglDisable(GL_ALPHA_TEST); qglDepthMask(GL_FALSE); qglPolygonMode(GL_FRONT, GL_FILL); qglFrontFace(GL_CCW); const GLfloat color_w[4] = {1.0f, 1.0f, 1.0f, 1.0f}; const text_shader_description *shader = renderer.shaderManager->getTextShader(); screenSize[0] = screen_info.w; screenSize[1] = screen_info.h; qglUseProgramObjectARB(shader->program); qglUniform1iARB(shader->sampler, 0); qglUniform2fvARB(shader->screenSize, 1, screenSize); Gui_DrawRect(0.0, 0.0, screen_info.w, screen_info.h, color_w, color_w, color_w, color_w, BM_OPAQUE, load_screen_tex); if(value >= 0) { Bar[BAR_LOADING].Show(value); } qglDepthMask(GL_TRUE); qglPopClientAttrib(); qglPopAttrib(); Engine_GLSwapWindow(); }
/* ================== 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(); } }
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" ); } }
/* ** 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 ); } }
/* ================ DrawTris Draws triangle outlines for debugging ================ */ static void DrawTris( shaderCommands_t *input ) { char *s = r_trisColor->string; vec4_t trisColor = { 1, 1, 1, 1 }; unsigned int stateBits = 0; GL_Bind( tr.whiteImage ); if ( *s == '0' && ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) ) { s += 2; if ( Q_IsHexColorString( s ) ) { trisColor[0] = ( (float)( gethex( *( s ) ) * 16 + gethex( *( s + 1 ) ) ) ) / 255.00; trisColor[1] = ( (float)( gethex( *( s + 2 ) ) * 16 + gethex( *( s + 3 ) ) ) ) / 255.00; trisColor[2] = ( (float)( gethex( *( s + 4 ) ) * 16 + gethex( *( s + 5 ) ) ) ) / 255.00; if ( Q_HexColorStringHasAlpha( s ) ) { trisColor[3] = ( (float)( gethex( *( s + 6 ) ) * 16 + gethex( *( s + 7 ) ) ) ) / 255.00; } } } else { int i; char *token; for ( i = 0 ; i < 4 ; i++ ) { token = COM_Parse( &s ); if ( token ) { trisColor[i] = atof( token ); } else { trisColor[i] = 1.f; } } if ( !trisColor[3] ) { trisColor[3] = 1.f; } } if ( trisColor[3] < 1.f ) { stateBits |= ( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); } qglColor4fv( trisColor ); // ydnar r_showtris 2 if ( r_showtris->integer == 2 ) { stateBits |= ( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE ); GL_State( stateBits ); qglDepthRange( 0, 0 ); } #ifdef CELSHADING_HACK else if ( r_showtris->integer == 3 ) { stateBits |= ( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE ); GL_State( stateBits ); qglEnable( GL_POLYGON_OFFSET_LINE ); qglPolygonOffset( 4.0, 0.5 ); qglLineWidth( 5.0 ); } #endif else { stateBits |= ( GLS_POLYMODE_LINE ); GL_State( stateBits ); qglEnable( GL_POLYGON_OFFSET_LINE ); qglPolygonOffset( r_offsetFactor->value, r_offsetUnits->value ); } qglDisableClientState( GL_COLOR_ARRAY ); qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); qglVertexPointer( 3, GL_FLOAT, 16, input->xyz ); // padded for SIMD if ( qglLockArraysEXT ) { qglLockArraysEXT( 0, input->numVertexes ); GLimp_LogComment( "glLockArraysEXT\n" ); } R_DrawElements( input->numIndexes, input->indexes ); if ( qglUnlockArraysEXT ) { qglUnlockArraysEXT(); GLimp_LogComment( "glUnlockArraysEXT\n" ); } qglDepthRange( 0, 1 ); qglDisable( GL_POLYGON_OFFSET_LINE ); }
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 ); }
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_ARB2_DrawInteractions ================== */ void RB_ARB2_DrawInteractions( void ) { viewLight_t *vLight; const idMaterial *lightShader; GL_SelectTexture( 0 ); qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); // // for each light, perform adding and shadowing // for ( vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) { backEnd.vLight = vLight; // do fogging later if ( vLight->lightShader->IsFogLight() ) { continue; } if ( vLight->lightShader->IsBlendLight() ) { continue; } if ( !vLight->localInteractions && !vLight->globalInteractions && !vLight->translucentInteractions ) { continue; } lightShader = vLight->lightShader; // clear the stencil buffer if needed if ( vLight->globalShadows || vLight->localShadows ) { backEnd.currentScissor = vLight->scissorRect; if ( r_useScissor.GetBool() ) { 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 ); } qglClear( GL_STENCIL_BUFFER_BIT ); } else { // no shadows, so no need to read or write the stencil buffer // we might in theory want to use GL_ALWAYS instead of disabling // completely, to satisfy the invarience rules qglStencilFunc( GL_ALWAYS, 128, 255 ); } if ( r_useShadowVertexProgram.GetBool() ) { qglEnable( GL_VERTEX_PROGRAM_ARB ); qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_STENCIL_SHADOW ); RB_StencilShadowPass( vLight->globalShadows ); RB_ARB2_CreateDrawInteractions( vLight->localInteractions ); qglEnable( GL_VERTEX_PROGRAM_ARB ); qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_STENCIL_SHADOW ); RB_StencilShadowPass( vLight->localShadows ); RB_ARB2_CreateDrawInteractions( vLight->globalInteractions ); qglDisable( GL_VERTEX_PROGRAM_ARB ); // if there weren't any globalInteractions, it would have stayed on } else { RB_StencilShadowPass( vLight->globalShadows ); RB_ARB2_CreateDrawInteractions( vLight->localInteractions ); RB_StencilShadowPass( vLight->localShadows ); RB_ARB2_CreateDrawInteractions( vLight->globalInteractions ); } // translucent surfaces never get stencil shadowed if ( r_skipTranslucent.GetBool() ) { continue; } qglStencilFunc( GL_ALWAYS, 128, 255 ); backEnd.depthFunc = GLS_DEPTHFUNC_LESS; RB_ARB2_CreateDrawInteractions( vLight->translucentInteractions ); backEnd.depthFunc = GLS_DEPTHFUNC_EQUAL; } // disable stencil shadow test qglStencilFunc( GL_ALWAYS, 128, 255 ); GL_SelectTexture( 0 ); qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); }
/* ============= RB_ARB2_CreateDrawInteractions ============= */ void RB_ARB2_CreateDrawInteractions( const drawSurf_t *surf ) { if ( !surf ) { return; } // perform setup here that will be constant for all interactions GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | backEnd.depthFunc ); // bind the vertex program if ( r_testARBProgram.GetBool() ) { qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_TEST ); qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_TEST ); } else { qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_INTERACTION ); qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_INTERACTION ); } qglEnable(GL_VERTEX_PROGRAM_ARB); qglEnable(GL_FRAGMENT_PROGRAM_ARB); // enable the vertex arrays qglEnableVertexAttribArrayARB( 8 ); qglEnableVertexAttribArrayARB( 9 ); qglEnableVertexAttribArrayARB( 10 ); qglEnableVertexAttribArrayARB( 11 ); qglEnableClientState( GL_COLOR_ARRAY ); // texture 0 is the normalization cube map for the vector towards the light GL_SelectTextureNoClient( 0 ); if ( backEnd.vLight->lightShader->IsAmbientLight() ) { globalImages->ambientNormalMap->Bind(); } else { globalImages->normalCubeMapImage->Bind(); } // texture 6 is the specular lookup table GL_SelectTextureNoClient( 6 ); if ( r_testARBProgram.GetBool() ) { globalImages->specular2DTableImage->Bind(); // variable specularity in alpha channel } else { globalImages->specularTableImage->Bind(); } for ( ; surf ; surf=surf->nextOnLight ) { // perform setup here that will not change over multiple interaction passes // set the vertex pointers idDrawVert *ac = (idDrawVert *)vertexCache.Position( surf->geo->ambientCache ); qglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( idDrawVert ), ac->color ); qglVertexAttribPointerARB( 11, 3, GL_FLOAT, false, 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() ); qglVertexAttribPointerARB( 8, 2, GL_FLOAT, false, sizeof( idDrawVert ), ac->st.ToFloatPtr() ); qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() ); // this may cause RB_ARB2_DrawInteraction to be exacuted multiple // times with different colors and images if the surface or light have multiple layers RB_CreateSingleDrawInteractions( surf, RB_ARB2_DrawInteraction ); } qglDisableVertexAttribArrayARB( 8 ); qglDisableVertexAttribArrayARB( 9 ); qglDisableVertexAttribArrayARB( 10 ); qglDisableVertexAttribArrayARB( 11 ); qglDisableClientState( GL_COLOR_ARRAY ); // disable features GL_SelectTextureNoClient( 6 ); globalImages->BindNull(); GL_SelectTextureNoClient( 5 ); globalImages->BindNull(); GL_SelectTextureNoClient( 4 ); globalImages->BindNull(); GL_SelectTextureNoClient( 3 ); globalImages->BindNull(); GL_SelectTextureNoClient( 2 ); globalImages->BindNull(); GL_SelectTextureNoClient( 1 ); globalImages->BindNull(); backEnd.glState.currenttmu = -1; GL_SelectTexture( 0 ); qglDisable(GL_VERTEX_PROGRAM_ARB); qglDisable(GL_FRAGMENT_PROGRAM_ARB); }
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 ); }
/* ================= RB_ShadowFinish Darken everything that is is a shadow volume. We have to delay this until everything has been shadowed, because otherwise shadows from different body parts would overlap and double darken. ================= */ void RB_ShadowFinish( void ) { if ( r_shadows->integer != 2 ) { return; } if ( glConfig.stencilBits < 4 ) { return; } #ifdef _DEBUG_STENCIL_SHADOWS return; #endif qglEnable( GL_STENCIL_TEST ); qglStencilFunc( GL_NOTEQUAL, 0, 255 ); qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); bool planeZeroBack = false; if (qglIsEnabled(GL_CLIP_PLANE0)) { planeZeroBack = true; qglDisable (GL_CLIP_PLANE0); } GL_Cull(CT_TWO_SIDED); //qglDisable (GL_CULL_FACE); GL_Bind( tr.whiteImage ); qglPushMatrix(); qglLoadIdentity (); // qglColor3f( 0.6f, 0.6f, 0.6f ); // GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO ); // qglColor3f( 1, 0, 0 ); // GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); qglColor4f( 0.0f, 0.0f, 0.0f, 0.5f ); //GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); #ifdef HAVE_GLES GLfloat vtx[] = { -100, 100, -10, 100, 100, -10, 100, -100, -10, -100, -100, -10 }; GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY); GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY); if (text) qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); if (glcol) qglDisableClientState( GL_COLOR_ARRAY ); qglVertexPointer ( 3, GL_FLOAT, 0, vtx ); qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); if (text) qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); if (glcol) qglEnableClientState( GL_COLOR_ARRAY ); #else qglBegin( GL_QUADS ); qglVertex3f( -100, 100, -10 ); qglVertex3f( 100, 100, -10 ); qglVertex3f( 100, -100, -10 ); qglVertex3f( -100, -100, -10 ); qglEnd (); #endif qglColor4f(1,1,1,1); qglDisable( GL_STENCIL_TEST ); if (planeZeroBack) { qglEnable (GL_CLIP_PLANE0); } qglPopMatrix(); }
void RB_DoShadowTessEnd( vec3_t lightPos ) { int i; int numTris; vec3_t lightDir; // we can only do this if we have enough space in the vertex buffers if ( tess.numVertexes >= SHADER_MAX_VERTEXES / 2 ) { return; } if ( glConfig.stencilBits < 4 ) { return; } #if 1 //controlled method - try to keep shadows in range so they don't show through so much -rww vec3_t worldxyz; vec3_t entLight; float groundDist; VectorCopy( backEnd.currentEntity->lightDir, entLight ); entLight[2] = 0.0f; VectorNormalize(entLight); //Oh well, just cast them straight down no matter what onto the ground plane. //This presets no chance of screwups and still looks better than a stupid //shader blob. VectorSet(lightDir, entLight[0]*0.3f, entLight[1]*0.3f, 1.0f); // project vertexes away from light direction for ( i = 0 ; i < tess.numVertexes ; i++ ) { //add or.origin to vert xyz to end up with world oriented coord, then figure //out the ground pos for the vert to project the shadow volume to VectorAdd(tess.xyz[i], backEnd.ori.origin, worldxyz); groundDist = worldxyz[2] - backEnd.currentEntity->e.shadowPlane; groundDist += 16.0f; //fudge factor VectorMA( tess.xyz[i], -groundDist, lightDir, tess.xyz[i+tess.numVertexes] ); } #else if (lightPos) { for ( i = 0 ; i < tess.numVertexes ; i++ ) { tess.xyz[i+tess.numVertexes][0] = tess.xyz[i][0]+(( tess.xyz[i][0]-lightPos[0] )*128.0f); tess.xyz[i+tess.numVertexes][1] = tess.xyz[i][1]+(( tess.xyz[i][1]-lightPos[1] )*128.0f); tess.xyz[i+tess.numVertexes][2] = tess.xyz[i][2]+(( tess.xyz[i][2]-lightPos[2] )*128.0f); } } else { VectorCopy( backEnd.currentEntity->lightDir, lightDir ); // project vertexes away from light direction for ( i = 0 ; i < tess.numVertexes ; i++ ) { VectorMA( tess.xyz[i], -512, lightDir, tess.xyz[i+tess.numVertexes] ); } } #endif // decide which triangles face the light memset( numEdgeDefs, 0, 4 * tess.numVertexes ); numTris = tess.numIndexes / 3; for ( i = 0 ; i < numTris ; i++ ) { int i1, i2, i3; vec3_t d1, d2, normal; float *v1, *v2, *v3; float d; i1 = tess.indexes[ i*3 + 0 ]; i2 = tess.indexes[ i*3 + 1 ]; i3 = tess.indexes[ i*3 + 2 ]; v1 = tess.xyz[ i1 ]; v2 = tess.xyz[ i2 ]; v3 = tess.xyz[ i3 ]; if (!lightPos) { VectorSubtract( v2, v1, d1 ); VectorSubtract( v3, v1, d2 ); CrossProduct( d1, d2, normal ); d = DotProduct( normal, lightDir ); } else { float planeEq[4]; planeEq[0] = v1[1]*(v2[2]-v3[2]) + v2[1]*(v3[2]-v1[2]) + v3[1]*(v1[2]-v2[2]); planeEq[1] = v1[2]*(v2[0]-v3[0]) + v2[2]*(v3[0]-v1[0]) + v3[2]*(v1[0]-v2[0]); planeEq[2] = v1[0]*(v2[1]-v3[1]) + v2[0]*(v3[1]-v1[1]) + v3[0]*(v1[1]-v2[1]); planeEq[3] = -( v1[0]*( v2[1]*v3[2] - v3[1]*v2[2] ) + v2[0]*(v3[1]*v1[2] - v1[1]*v3[2]) + v3[0]*(v1[1]*v2[2] - v2[1]*v1[2]) ); d = planeEq[0]*lightPos[0]+ planeEq[1]*lightPos[1]+ planeEq[2]*lightPos[2]+ planeEq[3]; } if ( d > 0 ) { facing[ i ] = 1; } else { facing[ i ] = 0; } // create the edges R_AddEdgeDef( i1, i2, facing[ i ] ); R_AddEdgeDef( i2, i3, facing[ i ] ); R_AddEdgeDef( i3, i1, facing[ i ] ); } GL_Bind( tr.whiteImage ); //qglEnable( GL_CULL_FACE ); GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); #ifndef _DEBUG_STENCIL_SHADOWS qglColor3f( 0.2f, 0.2f, 0.2f ); // don't write to the color buffer qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); qglEnable( GL_STENCIL_TEST ); qglStencilFunc( GL_ALWAYS, 1, 255 ); #else qglColor3f( 1.0f, 0.0f, 0.0f ); qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //qglDisable(GL_DEPTH_TEST); #endif #ifdef HAVE_GLES GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY); GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY); if (text) qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); if (glcol) qglDisableClientState( GL_COLOR_ARRAY ); qglVertexPointer (3, GL_FLOAT, 16, tess.xyz); #endif #ifdef _STENCIL_REVERSE qglDepthFunc(GL_LESS); //now using the Carmack Reverse<tm> -rww if ( backEnd.viewParms.isMirror ) { //qglCullFace( GL_BACK ); GL_Cull(CT_BACK_SIDED); qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP ); R_RenderShadowEdges(); //qglCullFace( GL_FRONT ); GL_Cull(CT_FRONT_SIDED); qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP ); #ifdef HAVE_GLES qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes); #else R_RenderShadowEdges(); #endif } else { //qglCullFace( GL_FRONT ); GL_Cull(CT_FRONT_SIDED); qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP ); R_RenderShadowEdges(); //qglCullFace( GL_BACK ); GL_Cull(CT_BACK_SIDED); qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP ); #ifdef HAVE_GLES qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes); #else R_RenderShadowEdges(); #endif } qglDepthFunc(GL_LEQUAL); #else // mirrors have the culling order reversed if ( backEnd.viewParms.isMirror ) { qglCullFace( GL_FRONT ); qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); R_RenderShadowEdges(); qglCullFace( GL_BACK ); qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); #ifdef HAVE_GLES qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes); #else R_RenderShadowEdges(); #endif } else { qglCullFace( GL_BACK ); qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); R_RenderShadowEdges(); qglCullFace( GL_FRONT ); qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); #ifdef HAVE_GLES qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes); #else R_RenderShadowEdges(); #endif } #endif // reenable writing to the color buffer qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); #ifdef HAVE_GLES if (text) qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); if (glcol) qglEnableClientState( GL_COLOR_ARRAY ); #endif #ifdef _DEBUG_STENCIL_SHADOWS qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif }
/* ============= RB_GLSL_CreateDrawInteractions ============= */ static void RB_GLSL_CreateDrawInteractions( const drawSurf_t *surf ) { if ( !surf ) { return; } // perform setup here that will be constant for all interactions GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | backEnd.depthFunc ); // bind the vertex and fragment program if ( backEnd.vLight->lightShader->IsAmbientLight() ) { qglUseProgramObjectARB( interactionAmbShader.program ); } else { qglUseProgramObjectARB( interactionDirShader.program ); } // enable the vertex arrays qglEnableVertexAttribArrayARB( 8 ); qglEnableVertexAttribArrayARB( 9 ); qglEnableVertexAttribArrayARB( 10 ); qglEnableVertexAttribArrayARB( 11 ); qglEnableClientState( GL_COLOR_ARRAY ); for ( ; surf; surf = surf->nextOnLight ) { // perform setup here that will not change over multiple interaction passes // ---> sikk - Custom Interaction Shaders: Local Parameters const float *regs; regs = surf->shaderRegisters; for ( int i = 0; i < surf->material->GetNumInteractionParms(); i++ ) { float parm[ 4 ]; parm[ 0 ] = regs[ surf->material->GetInteractionParm( i, 0 ) ]; parm[ 1 ] = regs[ surf->material->GetInteractionParm( i, 1 ) ]; parm[ 2 ] = regs[ surf->material->GetInteractionParm( i, 2 ) ]; parm[ 3 ] = regs[ surf->material->GetInteractionParm( i, 3 ) ]; if ( backEnd.vLight->lightShader->IsAmbientLight() ) { qglUniform4fvARB( interactionAmbShader.localParms[ i ], 1, parm ); } else { qglUniform4fvARB( interactionDirShader.localParms[ i ], 1, parm ); } } // <--- sikk - Custom Interaction Shaders: Local Parameters // ---> sikk - Specular Exponent Scale/Bias float parm[ 4 ]; parm[ 0 ] = surf->material->GetSpecExp( 0 ); parm[ 1 ] = surf->material->GetSpecExp( 1 ); parm[ 2 ] = 0.0f; parm[ 3 ] = 0.0f; if ( backEnd.vLight->lightShader->IsAmbientLight() ) { qglUniform4fvARB( interactionAmbShader.specExp, 1, parm ); } else { qglUniform4fvARB( interactionDirShader.specExp, 1, parm ); } // <--- sikk - Custom Interaction Shaders: Local Parameters // set the vertex pointers idDrawVert *ac = (idDrawVert *)vertexCache.Position( surf->geo->ambientCache ); qglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( idDrawVert ), ac->color ); qglVertexAttribPointerARB( 11, 3, GL_FLOAT, false, 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() ); qglVertexAttribPointerARB( 8, 2, GL_FLOAT, false, sizeof( idDrawVert ), ac->st.ToFloatPtr() ); qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() ); // set model matrix //if ( backEnd.vLight->lightShader->IsAmbientLight() ) { // qglUniformMatrix4fvARB( interactionAmbShader.modelMatrix, 1, false, surf->space->modelMatrix ); //} else { // qglUniformMatrix4fvARB( interactionDirShader.modelMatrix, 1, false, surf->space->modelMatrix ); //} // this may cause RB_GLSL_DrawInteraction to be executed multiple // times with different colors and images if the surface or light have multiple layers RB_CreateSingleDrawInteractions( surf, RB_GLSL_DrawInteraction ); } qglDisableVertexAttribArrayARB( 8 ); qglDisableVertexAttribArrayARB( 9 ); qglDisableVertexAttribArrayARB( 10 ); qglDisableVertexAttribArrayARB( 11 ); qglDisableClientState( GL_COLOR_ARRAY ); // disable features // ---> sikk - Auxilary textures for interaction shaders // per-surface auxilary texture 0 - 9 for ( int i = 15; i > 0; i-- ) { GL_SelectTextureNoClient( i ); globalImages->BindNull(); } // <--- sikk - Auxilary textures for interaction shaders backEnd.glState.currenttmu = -1; GL_SelectTexture( 0 ); qglUseProgramObjectARB( 0 ); }