/* ================== RB_NV20_DI_SpecularColorPass ================== */ static void RB_NV20_DI_SpecularColorPass(const drawInteraction_t *din) { RB_LogComment("---------- RB_NV20_SpecularColorPass ----------\n"); GL_State(GLS_SRCBLEND_DST_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_ALPHAMASK | backEnd.depthFunc); // texture 0 is the normalization cube map for the half angle #ifdef MACOS_X GL_SelectTexture(0); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(0); #endif globalImages->normalCubeMapImage->Bind(); // texture 1 will be the per-surface bump map #ifdef MACOS_X GL_SelectTexture(1); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(1); #endif din->bumpImage->Bind(); // texture 2 will be the per-surface specular map #ifdef MACOS_X GL_SelectTexture(2); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(2); #endif din->specularImage->Bind(); // texture 3 will be the light projected texture #ifdef MACOS_X GL_SelectTexture(3); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(3); #endif din->lightImage->Bind(); // bind our "fragment program" RB_NV20_SpecularColorFragment(); // override one parameter for inverted vertex color if (din->vertexColor == SVC_INVERSE_MODULATE) { qglCombinerInputNV(GL_COMBINER3_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_SPECULAR_COLOR); RB_DrawElementsWithCounters(din->surf->geo); }
/* ================== RB_NV20_DI_DiffuseAndSpecularColorPass ================== */ static void RB_NV20_DI_DiffuseAndSpecularColorPass(const drawInteraction_t *din) { RB_LogComment("---------- RB_NV20_DI_DiffuseAndSpecularColorPass ----------\n"); GL_State(GLS_SRCBLEND_DST_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | backEnd.depthFunc); // texture 0 is the normalization cube map for the half angle // still bound from RB_NV_BumpAndLightPass // GL_SelectTextureNoClient( 0 ); // GL_Bind( tr.normalCubeMapImage ); // texture 1 is the per-surface bump map // still bound from RB_NV_BumpAndLightPass // GL_SelectTextureNoClient( 1 ); // GL_Bind( din->bumpImage ); // texture 2 is the per-surface diffuse map #ifdef MACOS_X GL_SelectTexture(2); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(2); #endif din->diffuseImage->Bind(); // texture 3 is the per-surface specular map #ifdef MACOS_X GL_SelectTexture(3); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(3); #endif din->specularImage->Bind(); // bind our "fragment program" RB_NV20_DiffuseAndSpecularColorFragment(); // draw it qglBindProgramARB(GL_VERTEX_PROGRAM_ARB, VPROG_NV20_DIFFUSE_AND_SPECULAR_COLOR); RB_DrawElementsWithCounters(din->surf->geo); }
/* ================== RB_ARB2_DrawInteraction ================== */ void RB_ARB2_DrawInteraction( const drawInteraction_t *din ) { // 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() ); // testing fragment based normal mapping if ( r_testARBProgram.GetBool() ) { qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 2, din->localLightOrigin.ToFloatPtr() ); qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 3, din->localViewOrigin.ToFloatPtr() ); } 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; } // set the constant colors qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 0, din->diffuseColor.ToFloatPtr() ); qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 1, din->specularColor.ToFloatPtr() ); // set the textures // texture 1 will be the per-surface bump map GL_SelectTextureNoClient( 1 ); din->bumpImage->Bind(); // texture 2 will be the light falloff texture GL_SelectTextureNoClient( 2 ); din->lightFalloffImage->Bind(); // texture 3 will be the light projection texture GL_SelectTextureNoClient( 3 ); din->lightImage->Bind(); // texture 4 is the per-surface diffuse map GL_SelectTextureNoClient( 4 ); din->diffuseImage->Bind(); // texture 5 is the per-surface specular map GL_SelectTextureNoClient( 5 ); din->specularImage->Bind(); // draw it RB_DrawElementsWithCounters( din->surf->geo ); }
/* ============= 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); }
/* ================== RB_GLSL_DrawInteraction ================== */ static void RB_GLSL_DrawInteraction( const drawInteraction_t *din ) { // load all the shader parameters if ( din->ambientLight ) { // ---> sikk - Included non-power-of-two/frag position conversion // screen power of two correction factor, assuming the copy to _currentRender // also copied an extra row and column for the bilerp float parm[ 4 ]; int w = backEnd.viewDef->viewport.x2 - backEnd.viewDef->viewport.x1 + 1; int h = backEnd.viewDef->viewport.y2 - backEnd.viewDef->viewport.y1 + 1; parm[0] = (float)w / globalImages->currentRenderImage->uploadWidth; parm[1] = (float)h / globalImages->currentRenderImage->uploadHeight; parm[2] = parm[0] / w; // sikk - added - one less fragment shader instruction parm[3] = parm[1] / h; // sikk - added - one less fragment shader instruction qglUniform4fvARB( interactionAmbShader.nonPoT, 1, parm ); // window coord to 0.0 to 1.0 conversion parm[0] = 1.0 / w; parm[1] = 1.0 / h; parm[2] = w; // sikk - added - can be useful to have resolution size in shader parm[3] = h; // sikk - added - can be useful to have resolution size in shader qglUniform4fvARB( interactionAmbShader.invRes, 1, parm ); // <--- sikk - Included non-power-of-two/frag position conversion qglUniform4fvARB( interactionAmbShader.localLightOrigin, 1, din->localLightOrigin.ToFloatPtr() ); qglUniform4fvARB( interactionAmbShader.localViewOrigin, 1, din->localViewOrigin.ToFloatPtr() ); qglUniform4fvARB( interactionAmbShader.lightProjectionS, 1, din->lightProjection[0].ToFloatPtr() ); qglUniform4fvARB( interactionAmbShader.lightProjectionT, 1, din->lightProjection[1].ToFloatPtr() ); qglUniform4fvARB( interactionAmbShader.lightProjectionQ, 1, din->lightProjection[2].ToFloatPtr() ); qglUniform4fvARB( interactionAmbShader.lightFalloff, 1, din->lightProjection[3].ToFloatPtr() ); qglUniform4fvARB( interactionAmbShader.bumpMatrixS, 1, din->bumpMatrix[0].ToFloatPtr() ); qglUniform4fvARB( interactionAmbShader.bumpMatrixT, 1, din->bumpMatrix[1].ToFloatPtr() ); qglUniform4fvARB( interactionAmbShader.diffuseMatrixS, 1, din->diffuseMatrix[0].ToFloatPtr() ); qglUniform4fvARB( interactionAmbShader.diffuseMatrixT, 1, din->diffuseMatrix[1].ToFloatPtr() ); qglUniform4fvARB( interactionAmbShader.specularMatrixS, 1, din->specularMatrix[0].ToFloatPtr() ); qglUniform4fvARB( interactionAmbShader.specularMatrixT, 1, din->specularMatrix[1].ToFloatPtr() ); // ---> sikk - Include model matrix for to-world-space transformations const struct viewEntity_s *space = backEnd.currentSpace; qglUniformMatrix4fvARB( interactionAmbShader.modelMatrix, 1, 0, space->modelMatrix ); // <--- sikk - Include model matrix for to-world-space transformations static const float ignore[ 4 ] = { 0.0, 1.0, 1.0, 1.0 }; static const float modulate[ 4 ] = { 1.0, 0.0, 1.0, 1.0 }; static const float inv_modulate[ 4 ] = { -1.0, 1.0, 1.0, 1.0 }; switch ( din->vertexColor ) { case SVC_IGNORE: qglUniform4fvARB( interactionAmbShader.colorMAD, 1, ignore ); break; case SVC_MODULATE: qglUniform4fvARB( interactionAmbShader.colorMAD, 1, modulate ); break; case SVC_INVERSE_MODULATE: qglUniform4fvARB( interactionAmbShader.colorMAD, 1, inv_modulate ); break; } // set the constant color qglUniform4fvARB( interactionAmbShader.diffuseColor, 1, din->diffuseColor.ToFloatPtr() ); qglUniform4fvARB( interactionAmbShader.specularColor, 1, din->specularColor.ToFloatPtr() ); } else { // ---> sikk - Included non-power-of-two/frag position conversion // screen power of two correction factor, assuming the copy to _currentRender // also copied an extra row and column for the bilerp float parm[ 4 ]; int w = backEnd.viewDef->viewport.x2 - backEnd.viewDef->viewport.x1 + 1; int h = backEnd.viewDef->viewport.y2 - backEnd.viewDef->viewport.y1 + 1; parm[0] = (float)w / globalImages->currentRenderImage->uploadWidth; parm[1] = (float)h / globalImages->currentRenderImage->uploadHeight; parm[2] = parm[0] / w; // sikk - added - one less fragment shader instruction parm[3] = parm[1] / h; // sikk - added - one less fragment shader instruction qglUniform4fvARB( interactionDirShader.nonPoT, 1, parm ); // window coord to 0.0 to 1.0 conversion parm[0] = 1.0 / w; parm[1] = 1.0 / h; parm[2] = w; // sikk - added - can be useful to have resolution size in shader parm[3] = h; // sikk - added - can be useful to have resolution size in shader qglUniform4fvARB( interactionDirShader.invRes, 1, parm ); // <--- sikk - Included non-power-of-two/frag position conversion qglUniform4fvARB( interactionDirShader.localLightOrigin, 1, din->localLightOrigin.ToFloatPtr() ); qglUniform4fvARB( interactionDirShader.localViewOrigin, 1, din->localViewOrigin.ToFloatPtr() ); qglUniform4fvARB( interactionDirShader.lightProjectionS, 1, din->lightProjection[0].ToFloatPtr() ); qglUniform4fvARB( interactionDirShader.lightProjectionT, 1, din->lightProjection[1].ToFloatPtr() ); qglUniform4fvARB( interactionDirShader.lightProjectionQ, 1, din->lightProjection[2].ToFloatPtr() ); qglUniform4fvARB( interactionDirShader.lightFalloff, 1, din->lightProjection[3].ToFloatPtr() ); qglUniform4fvARB( interactionDirShader.bumpMatrixS, 1, din->bumpMatrix[0].ToFloatPtr() ); qglUniform4fvARB( interactionDirShader.bumpMatrixT, 1, din->bumpMatrix[1].ToFloatPtr() ); qglUniform4fvARB( interactionDirShader.diffuseMatrixS, 1, din->diffuseMatrix[0].ToFloatPtr() ); qglUniform4fvARB( interactionDirShader.diffuseMatrixT, 1, din->diffuseMatrix[1].ToFloatPtr() ); qglUniform4fvARB( interactionDirShader.specularMatrixS, 1, din->specularMatrix[0].ToFloatPtr() ); qglUniform4fvARB( interactionDirShader.specularMatrixT, 1, din->specularMatrix[1].ToFloatPtr() ); // ---> sikk - Include model matrix for to-world-space transformations const struct viewEntity_s *space = backEnd.currentSpace; qglUniformMatrix4fvARB( interactionDirShader.modelMatrix, 1, 0, space->modelMatrix ); // <--- sikk - Include model matrix for to-world-space transformations if ( !backEnd.vLight->lightDef->parms.pointLight ) { // 2D Light Shader (projected lights) qglUniform1iARB( interactionDirShader.falloffType, 2 ); //qglUseProgramObjectARB( interactionDirShader.program ); //qglUniform1iARB( interactionDirShader.u_lightProjectionTexture, 0 ); //qglUseProgramObjectARB( 0 ); } else { // 3D Light Shader (point lights) if ( backEnd.vLight->lightDef->parms.parallel ) { // shader specific for sun light (no attenuation) qglUniform1iARB( interactionDirShader.falloffType, 1 ); } else { // default quadratic attenuation qglUniform1iARB( interactionDirShader.falloffType, 0 ); } } static const float ignore[ 4 ] = { 0.0, 1.0, 1.0, 1.0 }; static const float modulate[ 4 ] = { 1.0, 0.0, 1.0, 1.0 }; static const float inv_modulate[ 4 ] = { -1.0, 1.0, 1.0, 1.0 }; switch ( din->vertexColor ) { case SVC_IGNORE: qglUniform4fvARB( interactionDirShader.colorMAD, 1, ignore ); break; case SVC_MODULATE: qglUniform4fvARB( interactionDirShader.colorMAD, 1, modulate ); break; case SVC_INVERSE_MODULATE: qglUniform4fvARB( interactionDirShader.colorMAD, 1, inv_modulate ); break; } // set the constant colors qglUniform4fvARB( interactionDirShader.diffuseColor, 1, din->diffuseColor.ToFloatPtr() ); qglUniform4fvARB( interactionDirShader.specularColor, 1, din->specularColor.ToFloatPtr() ); } // set the textures // texture 0 will be the light projection texture GL_SelectTextureNoClient( 0 ); din->lightImage->Bind(); if ( !din->ambientLight ) { GL_SelectTextureNoClient( 16 ); din->lightImage->Bind(); } // texture 1 will be the light falloff texture GL_SelectTextureNoClient( 1 ); din->lightFalloffImage->Bind(); // texture 1 will be the per-surface bump map GL_SelectTextureNoClient( 2 ); din->bumpImage->Bind(); // texture 2 is the per-surface diffuse map GL_SelectTextureNoClient( 3 ); din->diffuseImage->Bind(); // texture 3 is the per-surface specular map GL_SelectTextureNoClient( 4 ); din->specularImage->Bind(); // texture 4 is the ssao buffer GL_SelectTextureNoClient( 5 ); globalImages->ssaoImage->Bind(); // ---> sikk - Auxilary textures for interaction shaders // per-surface auxilary texture 0 - 9 for ( int i = 0; i < din->surf->material->GetNumInteractionImages(); i++ ) { GL_SelectTextureNoClient( i + 6 ); din->surf->material->GetInteractionImage( i )->Bind(); } // <--- sikk - Auxilary textures for interaction shaders // draw it RB_DrawElementsWithCounters( din->surf->geo ); }
/* ============= 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 ); }
/* ================== RB_GLSL_DrawInteraction ================== */ static void RB_GLSL_DrawInteraction( const drawInteraction_t *din ) { // load all the shader parameters if ( din->ambientLight ) { qglUniform4fvARB( ambientInteractionShader.localLightOrigin, 1, din->localLightOrigin.ToFloatPtr() ); qglUniform4fvARB( ambientInteractionShader.lightProjectionS, 1, din->lightProjection[0].ToFloatPtr() ); qglUniform4fvARB( ambientInteractionShader.lightProjectionT, 1, din->lightProjection[1].ToFloatPtr() ); qglUniform4fvARB( ambientInteractionShader.lightProjectionQ, 1, din->lightProjection[2].ToFloatPtr() ); qglUniform4fvARB( ambientInteractionShader.lightFalloff, 1, din->lightProjection[3].ToFloatPtr() ); qglUniform4fvARB( ambientInteractionShader.bumpMatrixS, 1, din->bumpMatrix[0].ToFloatPtr() ); qglUniform4fvARB( ambientInteractionShader.bumpMatrixT, 1, din->bumpMatrix[1].ToFloatPtr() ); qglUniform4fvARB( ambientInteractionShader.diffuseMatrixS, 1, din->diffuseMatrix[0].ToFloatPtr() ); qglUniform4fvARB( ambientInteractionShader.diffuseMatrixT, 1, din->diffuseMatrix[1].ToFloatPtr() ); 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: qglUniform4fARB( ambientInteractionShader.colorModulate, zero[0], zero[1], zero[2], zero[3] ); qglUniform4fARB( ambientInteractionShader.colorAdd, one[0], one[1], one[2], one[3] ); break; case SVC_MODULATE: qglUniform4fARB( ambientInteractionShader.colorModulate, one[0], one[1], one[2], one[3] ); qglUniform4fARB( ambientInteractionShader.colorAdd, zero[0], zero[1], zero[2], zero[3] ); break; case SVC_INVERSE_MODULATE: qglUniform4fARB( ambientInteractionShader.colorModulate, negOne[0], negOne[1], negOne[2], negOne[3] ); qglUniform4fARB( ambientInteractionShader.colorAdd, one[0], one[1], one[2], one[3] ); break; } // set the constant color qglUniform4fvARB( ambientInteractionShader.diffuseColor, 1, din->diffuseColor.ToFloatPtr() ); } else { qglUniform4fvARB( interactionShader.localLightOrigin, 1, din->localLightOrigin.ToFloatPtr() ); qglUniform4fvARB( interactionShader.localViewOrigin, 1, din->localViewOrigin.ToFloatPtr() ); qglUniform4fvARB( interactionShader.lightProjectionS, 1, din->lightProjection[0].ToFloatPtr() ); qglUniform4fvARB( interactionShader.lightProjectionT, 1, din->lightProjection[1].ToFloatPtr() ); qglUniform4fvARB( interactionShader.lightProjectionQ, 1, din->lightProjection[2].ToFloatPtr() ); qglUniform4fvARB( interactionShader.lightFalloff, 1, din->lightProjection[3].ToFloatPtr() ); qglUniform4fvARB( interactionShader.bumpMatrixS, 1, din->bumpMatrix[0].ToFloatPtr() ); qglUniform4fvARB( interactionShader.bumpMatrixT, 1, din->bumpMatrix[1].ToFloatPtr() ); qglUniform4fvARB( interactionShader.diffuseMatrixS, 1, din->diffuseMatrix[0].ToFloatPtr() ); qglUniform4fvARB( interactionShader.diffuseMatrixT, 1, din->diffuseMatrix[1].ToFloatPtr() ); qglUniform4fvARB( interactionShader.specularMatrixS, 1, din->specularMatrix[0].ToFloatPtr() ); qglUniform4fvARB( interactionShader.specularMatrixT, 1, din->specularMatrix[1].ToFloatPtr() ); 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: qglUniform4fARB( interactionShader.colorModulate, zero[0], zero[1], zero[2], zero[3] ); qglUniform4fARB( interactionShader.colorAdd, one[0], one[1], one[2], one[3] ); break; case SVC_MODULATE: qglUniform4fARB( interactionShader.colorModulate, one[0], one[1], one[2], one[3] ); qglUniform4fARB( interactionShader.colorAdd, zero[0], zero[1], zero[2], zero[3] ); break; case SVC_INVERSE_MODULATE: qglUniform4fARB( interactionShader.colorModulate, negOne[0], negOne[1], negOne[2], negOne[3] ); qglUniform4fARB( interactionShader.colorAdd, one[0], one[1], one[2], one[3] ); break; } // set the constant colors qglUniform4fvARB( interactionShader.diffuseColor, 1, din->diffuseColor.ToFloatPtr() ); qglUniform4fvARB( interactionShader.specularColor, 1, din->specularColor.ToFloatPtr() ); } // set the textures // texture 0 will be the per-surface bump map GL_SelectTextureNoClient( 0 ); din->bumpImage->Bind(); // texture 1 will be the light falloff texture GL_SelectTextureNoClient( 1 ); din->lightFalloffImage->Bind(); // texture 2 will be the light projection texture GL_SelectTextureNoClient( 2 ); din->lightImage->Bind(); // texture 3 is the per-surface diffuse map GL_SelectTextureNoClient( 3 ); din->diffuseImage->Bind(); if ( !din->ambientLight ) { // texture 4 is the per-surface specular map GL_SelectTextureNoClient( 4 ); din->specularImage->Bind(); } // draw it RB_DrawElementsWithCounters( din->surf->geo ); }
/* ============= 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() ) { if (ambientInteractionShader.program == -1) qglUseProgramObjectARB( 0 ); else qglUseProgramObjectARB( ambientInteractionShader.program ); } else { if (interactionShader.program == -1) qglUseProgramObjectARB( 0 ); else qglUseProgramObjectARB( interactionShader.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 // 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( ambientInteractionShader.modelMatrix, 1, false, surf->space->modelMatrix ); } else { qglUniformMatrix4fvARB( interactionShader.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 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 ); qglUseProgramObjectARB( 0 ); }
/* ============= RB_NV20_CreateDrawInteractions ============= */ static void RB_NV20_CreateDrawInteractions(const drawSurf_t *surf) { if (!surf) { return; } qglEnable(GL_VERTEX_PROGRAM_ARB); qglEnable(GL_REGISTER_COMBINERS_NV); #ifdef MACOS_X GL_SelectTexture(0); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); #else qglDisableClientState(GL_TEXTURE_COORD_ARRAY); qglEnableVertexAttribArrayARB(8); qglEnableVertexAttribArrayARB(9); qglEnableVertexAttribArrayARB(10); qglEnableVertexAttribArrayARB(11); #endif for (; surf ; surf=surf->nextOnLight) { // set the vertex pointers idDrawVert *ac = (idDrawVert *)vertexCache.Position(surf->geo->ambientCache); qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(idDrawVert), ac->color); #ifdef MACOS_X GL_SelectTexture(0); qglTexCoordPointer(2, GL_FLOAT, sizeof(idDrawVert), ac->st.ToFloatPtr()); GL_SelectTexture(1); qglTexCoordPointer(3, GL_FLOAT, sizeof(idDrawVert), ac->tangents[0].ToFloatPtr()); GL_SelectTexture(2); qglTexCoordPointer(3, GL_FLOAT, sizeof(idDrawVert), ac->tangents[1].ToFloatPtr()); GL_SelectTexture(3); qglTexCoordPointer(3, GL_FLOAT, sizeof(idDrawVert), ac->normal.ToFloatPtr()); GL_SelectTexture(0); #else 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()); #endif qglVertexPointer(3, GL_FLOAT, sizeof(idDrawVert), ac->xyz.ToFloatPtr()); RB_CreateSingleDrawInteractions(surf, RB_NV20_DrawInteraction); } #ifndef MACOS_X qglDisableVertexAttribArrayARB(8); qglDisableVertexAttribArrayARB(9); qglDisableVertexAttribArrayARB(10); qglDisableVertexAttribArrayARB(11); #endif // disable features #ifdef MACOS_X GL_SelectTexture(3); globalImages->BindNull(); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); GL_SelectTexture(2); globalImages->BindNull(); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); GL_SelectTexture(1); globalImages->BindNull(); qglDisableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(3); globalImages->BindNull(); GL_SelectTextureNoClient(2); globalImages->BindNull(); GL_SelectTextureNoClient(1); globalImages->BindNull(); #endif backEnd.glState.currenttmu = -1; GL_SelectTexture(0); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); qglDisable(GL_VERTEX_PROGRAM_ARB); qglDisable(GL_REGISTER_COMBINERS_NV); }
/* ================== RB_NV20_DI_BumpAndLightPass We are going to write alpha as light falloff * ( bump dot light ) * lightProjection If the light isn't a monoLightShader, the lightProjection will be skipped, because it will have to be done on an itterated basis ================== */ static void RB_NV20_DI_BumpAndLightPass(const drawInteraction_t *din, bool monoLightShader) { RB_LogComment("---------- RB_NV_BumpAndLightPass ----------\n"); GL_State(GLS_COLORMASK | GLS_DEPTHMASK | backEnd.depthFunc); // texture 0 is the normalization cube map // GL_TEXTURE0_ARB will be the normalized vector // towards the light source #ifdef MACOS_X GL_SelectTexture(0); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(0); #endif if (din->ambientLight) { globalImages->ambientNormalMap->Bind(); } else { globalImages->normalCubeMapImage->Bind(); } // texture 1 will be the per-surface bump map #ifdef MACOS_X GL_SelectTexture(1); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(1); #endif din->bumpImage->Bind(); // texture 2 will be the light falloff texture #ifdef MACOS_X GL_SelectTexture(2); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(2); #endif din->lightFalloffImage->Bind(); // texture 3 will be the light projection texture #ifdef MACOS_X GL_SelectTexture(3); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); #else GL_SelectTextureNoClient(3); #endif if (monoLightShader) { din->lightImage->Bind(); } else { // if the projected texture is multi-colored, we // will need to do it in subsequent passes globalImages->whiteImage->Bind(); } // bind our "fragment program" RB_NV20_BumpAndLightFragment(); // draw it qglBindProgramARB(GL_VERTEX_PROGRAM_ARB, VPROG_NV20_BUMP_AND_LIGHT); RB_DrawElementsWithCounters(din->surf->geo); }