/* * R_RenderMeshGLSL_Distortion */ static void R_RenderMeshGLSL_Distortion( r_glslfeat_t programFeatures ) { int i, last_slot; unsigned last_framenum; int state, tcgen; int width = 1, height = 1; int program, object; mat4x4_t unused; cplane_t plane; const char *key; shaderpass_t *pass = r_back.accumPasses[0]; image_t *portaltexture[2]; qboolean frontPlane; PlaneFromPoints( r_back.r_triangle0Copy, &plane ); plane.dist += DotProduct( ri.currententity->origin, plane.normal ); key = R_PortalKeyForPlane( &plane ); last_framenum = last_slot = 0; for( i = 0; i < 2; i++ ) { int slot; portaltexture[i] = NULL; slot = R_FindPortalTextureSlot( key, i+1 ); if( slot ) portaltexture[i] = r_portaltextures[slot-1]; if( portaltexture[i] == NULL ) { portaltexture[i] = r_blacktexture; } else { width = portaltexture[i]->upload_width; height = portaltexture[i]->upload_height; } // find the most recently updated texture if( portaltexture[i]->framenum > last_framenum ) { last_slot = i; last_framenum = i; } } // if textures were not updated sequentially, use the most recent one // and reset the remaining to black if( portaltexture[0]->framenum+1 != portaltexture[1]->framenum ) portaltexture[(last_slot+1)&1] = r_blacktexture; if( pass->anim_frames[0] != r_blankbumptexture ) programFeatures |= GLSL_DISTORTION_APPLY_DUDV; if( ri.params & RP_CLIPPLANE ) programFeatures |= GLSL_COMMON_APPLY_CLIPPING; if( pass->flags & SHADERPASS_GRAYSCALE ) programFeatures |= GLSL_COMMON_APPLY_GRAYSCALE; if( portaltexture[0] != r_blacktexture ) programFeatures |= GLSL_DISTORTION_APPLY_REFLECTION; if( portaltexture[1] != r_blacktexture ) programFeatures |= GLSL_DISTORTION_APPLY_REFRACTION; frontPlane = (PlaneDiff( ri.viewOrigin, &ri.portalPlane ) > 0 ? qtrue : qfalse); if( frontPlane ) { if( pass->alphagen.type != ALPHA_GEN_IDENTITY ) programFeatures |= GLSL_DISTORTION_APPLY_DISTORTION_ALPHA; } tcgen = pass->tcgen; // store the original tcgen R_BindShaderpass( pass, pass->anim_frames[0], 0, NULL ); // dudvmap // calculate the fragment color R_ModifyColor( pass, programFeatures & GLSL_DISTORTION_APPLY_DISTORTION_ALPHA ? qtrue : qfalse, qfalse ); GL_TexEnv( GL_MODULATE ); // set shaderpass state (blending, depthwrite, etc) state = r_back.currentShaderState | ( pass->flags & r_back.currentShaderPassMask ) | GLSTATE_BLEND_MTEX; GL_SetState( state ); if( pass->anim_frames[1] ) { // eyeDot programFeatures |= GLSL_DISTORTION_APPLY_EYEDOT; pass->tcgen = TC_GEN_SVECTORS; GL_Bind( 1, pass->anim_frames[1] ); // normalmap GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY ); R_VertexTCBase( pass, 1, unused, NULL ); } GL_Bind( 2, portaltexture[0] ); // reflection GL_Bind( 3, portaltexture[1] ); // refraction pass->tcgen = tcgen; // restore original tcgen // update uniforms program = R_RegisterGLSLProgram( pass->program_type, pass->program, NULL, NULL, NULL, 0, programFeatures ); object = R_GetProgramObject( program ); if( object ) { qglUseProgramObjectARB( object ); R_UpdateProgramUniforms( program, ri.viewOrigin, vec3_origin, vec3_origin, NULL, NULL, NULL, frontPlane, width, height, 0, 0, 0, colorArrayCopy[0], r_back.overBrightBits, r_back.currentShaderTime, r_back.entityColor ); R_FlushArrays(); qglUseProgramObjectARB( 0 ); } }
void GLSL_InitGPUShaders(void) { int startTime, endTime; int i; char extradefines[1024]; int attribs; int numGenShaders = 0, numLightShaders = 0, numEtcShaders = 0; ri.Printf(PRINT_ALL, "------- GLSL_InitGPUShaders -------\n"); R_IssuePendingRenderCommands(); startTime = ri.Milliseconds(); for (i = 0; i < GENERICDEF_COUNT; i++) { attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_NORMAL | ATTR_COLOR; extradefines[0] = '\0'; if (i & GENERICDEF_USE_DEFORM_VERTEXES) Q_strcat(extradefines, 1024, "#define USE_DEFORM_VERTEXES\n"); if (i & GENERICDEF_USE_TCGEN_AND_TCMOD) { Q_strcat(extradefines, 1024, "#define USE_TCGEN\n"); Q_strcat(extradefines, 1024, "#define USE_TCMOD\n"); } if (i & GENERICDEF_USE_VERTEX_ANIMATION) { Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n"); attribs |= ATTR_POSITION2 | ATTR_NORMAL2; } if (i & GENERICDEF_USE_FOG) Q_strcat(extradefines, 1024, "#define USE_FOG\n"); if (i & GENERICDEF_USE_RGBAGEN) Q_strcat(extradefines, 1024, "#define USE_RGBAGEN\n"); if (!GLSL_InitGPUShader(&tr.genericShader[i], "generic", attribs, qtrue, extradefines, qtrue, fallbackShader_generic_vp, fallbackShader_generic_fp)) { ri.Error(ERR_FATAL, "Could not load generic shader!"); } GLSL_InitUniforms(&tr.genericShader[i]); qglUseProgramObjectARB(tr.genericShader[i].program); GLSL_SetUniformInt(&tr.genericShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP); GLSL_SetUniformInt(&tr.genericShader[i], UNIFORM_LIGHTMAP, TB_LIGHTMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.genericShader[i]); numGenShaders++; } attribs = ATTR_POSITION | ATTR_TEXCOORD; if (!GLSL_InitGPUShader(&tr.textureColorShader, "texturecolor", attribs, qtrue, NULL, qfalse, fallbackShader_texturecolor_vp, fallbackShader_texturecolor_fp)) { ri.Error(ERR_FATAL, "Could not load texturecolor shader!"); } GLSL_InitUniforms(&tr.textureColorShader); qglUseProgramObjectARB(tr.textureColorShader.program); GLSL_SetUniformInt(&tr.textureColorShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.textureColorShader); numEtcShaders++; for (i = 0; i < FOGDEF_COUNT; i++) { attribs = ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TEXCOORD; extradefines[0] = '\0'; if (i & FOGDEF_USE_DEFORM_VERTEXES) Q_strcat(extradefines, 1024, "#define USE_DEFORM_VERTEXES\n"); if (i & FOGDEF_USE_VERTEX_ANIMATION) Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n"); if (!GLSL_InitGPUShader(&tr.fogShader[i], "fogpass", attribs, qtrue, extradefines, qtrue, fallbackShader_fogpass_vp, fallbackShader_fogpass_fp)) { ri.Error(ERR_FATAL, "Could not load fogpass shader!"); } GLSL_InitUniforms(&tr.fogShader[i]); GLSL_FinishGPUShader(&tr.fogShader[i]); numEtcShaders++; } for (i = 0; i < DLIGHTDEF_COUNT; i++) { attribs = ATTR_POSITION | ATTR_NORMAL | ATTR_TEXCOORD; extradefines[0] = '\0'; if (i & DLIGHTDEF_USE_DEFORM_VERTEXES) { Q_strcat(extradefines, 1024, "#define USE_DEFORM_VERTEXES\n"); } if (!GLSL_InitGPUShader(&tr.dlightShader[i], "dlight", attribs, qtrue, extradefines, qtrue, fallbackShader_dlight_vp, fallbackShader_dlight_fp)) { ri.Error(ERR_FATAL, "Could not load dlight shader!"); } GLSL_InitUniforms(&tr.dlightShader[i]); qglUseProgramObjectARB(tr.dlightShader[i].program); GLSL_SetUniformInt(&tr.dlightShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.dlightShader[i]); numEtcShaders++; } for (i = 0; i < LIGHTDEF_COUNT; i++) { int lightType = i & LIGHTDEF_LIGHTTYPE_MASK; qboolean fastLight = !(r_normalMapping->integer || r_specularMapping->integer); // skip impossible combos if ((i & LIGHTDEF_USE_PARALLAXMAP) && !r_parallaxMapping->integer) continue; if (!lightType && (i & LIGHTDEF_USE_PARALLAXMAP)) continue; if (!lightType && (i & LIGHTDEF_USE_SHADOWMAP)) continue; attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_COLOR | ATTR_NORMAL; extradefines[0] = '\0'; if (r_deluxeSpecular->value > 0.000001f) Q_strcat(extradefines, 1024, va("#define r_deluxeSpecular %f\n", r_deluxeSpecular->value)); if (r_specularIsMetallic->value) Q_strcat(extradefines, 1024, "#define SPECULAR_IS_METALLIC\n"); if (r_dlightMode->integer >= 2) Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n"); if (1) Q_strcat(extradefines, 1024, "#define SWIZZLE_NORMALMAP\n"); if (r_hdr->integer && !glRefConfig.floatLightmap) Q_strcat(extradefines, 1024, "#define RGBM_LIGHTMAP\n"); if (lightType) { Q_strcat(extradefines, 1024, "#define USE_LIGHT\n"); if (fastLight) Q_strcat(extradefines, 1024, "#define USE_FAST_LIGHT\n"); switch (lightType) { case LIGHTDEF_USE_LIGHTMAP: Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n"); if (r_deluxeMapping->integer && !fastLight) Q_strcat(extradefines, 1024, "#define USE_DELUXEMAP\n"); attribs |= ATTR_LIGHTCOORD | ATTR_LIGHTDIRECTION; break; case LIGHTDEF_USE_LIGHT_VECTOR: Q_strcat(extradefines, 1024, "#define USE_LIGHT_VECTOR\n"); break; case LIGHTDEF_USE_LIGHT_VERTEX: Q_strcat(extradefines, 1024, "#define USE_LIGHT_VERTEX\n"); attribs |= ATTR_LIGHTDIRECTION; break; default: break; } if (r_normalMapping->integer) { Q_strcat(extradefines, 1024, "#define USE_NORMALMAP\n"); if (r_normalMapping->integer == 2) Q_strcat(extradefines, 1024, "#define USE_OREN_NAYAR\n"); if (r_normalMapping->integer == 3) Q_strcat(extradefines, 1024, "#define USE_TRIACE_OREN_NAYAR\n"); #ifdef USE_VERT_TANGENT_SPACE Q_strcat(extradefines, 1024, "#define USE_VERT_TANGENT_SPACE\n"); attribs |= ATTR_TANGENT; #endif if ((i & LIGHTDEF_USE_PARALLAXMAP) && !(i & LIGHTDEF_ENTITY) && r_parallaxMapping->integer) { Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP\n"); if (r_parallaxMapping->integer > 1) Q_strcat(extradefines, 1024, "#define USE_RELIEFMAP\n"); } } if (r_specularMapping->integer) { Q_strcat(extradefines, 1024, "#define USE_SPECULARMAP\n"); switch (r_specularMapping->integer) { case 1: default: Q_strcat(extradefines, 1024, "#define USE_BLINN\n"); break; case 2: Q_strcat(extradefines, 1024, "#define USE_BLINN_FRESNEL\n"); break; case 3: Q_strcat(extradefines, 1024, "#define USE_MCAULEY\n"); break; case 4: Q_strcat(extradefines, 1024, "#define USE_GOTANDA\n"); break; case 5: Q_strcat(extradefines, 1024, "#define USE_LAZAROV\n"); break; } } if (r_cubeMapping->integer) Q_strcat(extradefines, 1024, "#define USE_CUBEMAP\n"); } if (i & LIGHTDEF_USE_SHADOWMAP) { Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n"); if (r_sunlightMode->integer == 1) Q_strcat(extradefines, 1024, "#define SHADOWMAP_MODULATE\n"); else if (r_sunlightMode->integer == 2) Q_strcat(extradefines, 1024, "#define USE_PRIMARY_LIGHT\n"); } if (i & LIGHTDEF_USE_TCGEN_AND_TCMOD) { Q_strcat(extradefines, 1024, "#define USE_TCGEN\n"); Q_strcat(extradefines, 1024, "#define USE_TCMOD\n"); } if (i & LIGHTDEF_ENTITY) { Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n#define USE_MODELMATRIX\n"); attribs |= ATTR_POSITION2 | ATTR_NORMAL2; #ifdef USE_VERT_TANGENT_SPACE if (r_normalMapping->integer) { attribs |= ATTR_TANGENT2; } #endif } if (!GLSL_InitGPUShader(&tr.lightallShader[i], "lightall", attribs, qtrue, extradefines, qtrue, fallbackShader_lightall_vp, fallbackShader_lightall_fp)) { ri.Error(ERR_FATAL, "Could not load lightall shader!"); } GLSL_InitUniforms(&tr.lightallShader[i]); qglUseProgramObjectARB(tr.lightallShader[i].program); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_LIGHTMAP, TB_LIGHTMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_NORMALMAP, TB_NORMALMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_DELUXEMAP, TB_DELUXEMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_SPECULARMAP, TB_SPECULARMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_SHADOWMAP, TB_SHADOWMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_CUBEMAP, TB_CUBEMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.lightallShader[i]); numLightShaders++; } attribs = ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TEXCOORD; extradefines[0] = '\0'; if (!GLSL_InitGPUShader(&tr.shadowmapShader, "shadowfill", attribs, qtrue, extradefines, qtrue, fallbackShader_shadowfill_vp, fallbackShader_shadowfill_fp)) { ri.Error(ERR_FATAL, "Could not load shadowfill shader!"); } GLSL_InitUniforms(&tr.shadowmapShader); GLSL_FinishGPUShader(&tr.shadowmapShader); numEtcShaders++; attribs = ATTR_POSITION | ATTR_NORMAL; extradefines[0] = '\0'; #ifndef EMSCRIPTEN Q_strcat(extradefines, 1024, "#define USE_PCF\n#define USE_DISCARD\n"); if (!GLSL_InitGPUShader(&tr.pshadowShader, "pshadow", attribs, qtrue, extradefines, qtrue, fallbackShader_pshadow_vp, fallbackShader_pshadow_fp)) { ri.Error(ERR_FATAL, "Could not load pshadow shader!"); } GLSL_InitUniforms(&tr.pshadowShader); qglUseProgramObjectARB(tr.pshadowShader.program); GLSL_SetUniformInt(&tr.pshadowShader, UNIFORM_SHADOWMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.pshadowShader); numEtcShaders++; attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (!GLSL_InitGPUShader(&tr.down4xShader, "down4x", attribs, qtrue, extradefines, qtrue, fallbackShader_down4x_vp, fallbackShader_down4x_fp)) { ri.Error(ERR_FATAL, "Could not load down4x shader!"); } GLSL_InitUniforms(&tr.down4xShader); qglUseProgramObjectARB(tr.down4xShader.program); GLSL_SetUniformInt(&tr.down4xShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.down4xShader); numEtcShaders++; attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (!GLSL_InitGPUShader(&tr.bokehShader, "bokeh", attribs, qtrue, extradefines, qtrue, fallbackShader_bokeh_vp, fallbackShader_bokeh_fp)) { ri.Error(ERR_FATAL, "Could not load bokeh shader!"); } GLSL_InitUniforms(&tr.bokehShader); qglUseProgramObjectARB(tr.bokehShader.program); GLSL_SetUniformInt(&tr.bokehShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.bokehShader); numEtcShaders++; attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (!GLSL_InitGPUShader(&tr.tonemapShader, "tonemap", attribs, qtrue, extradefines, qtrue, fallbackShader_tonemap_vp, fallbackShader_tonemap_fp)) { ri.Error(ERR_FATAL, "Could not load tonemap shader!"); } GLSL_InitUniforms(&tr.tonemapShader); qglUseProgramObjectARB(tr.tonemapShader.program); GLSL_SetUniformInt(&tr.tonemapShader, UNIFORM_TEXTUREMAP, TB_COLORMAP); GLSL_SetUniformInt(&tr.tonemapShader, UNIFORM_LEVELSMAP, TB_LEVELSMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.tonemapShader); numEtcShaders++; for (i = 0; i < 2; i++) { attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (!i) Q_strcat(extradefines, 1024, "#define FIRST_PASS\n"); if (!GLSL_InitGPUShader(&tr.calclevels4xShader[i], "calclevels4x", attribs, qtrue, extradefines, qtrue, fallbackShader_calclevels4x_vp, fallbackShader_calclevels4x_fp)) { ri.Error(ERR_FATAL, "Could not load calclevels4x shader!"); } GLSL_InitUniforms(&tr.calclevels4xShader[i]); qglUseProgramObjectARB(tr.calclevels4xShader[i].program); GLSL_SetUniformInt(&tr.calclevels4xShader[i], UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.calclevels4xShader[i]); numEtcShaders++; } attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (r_shadowFilter->integer >= 1) Q_strcat(extradefines, 1024, "#define USE_SHADOW_FILTER\n"); if (r_shadowFilter->integer >= 2) Q_strcat(extradefines, 1024, "#define USE_SHADOW_FILTER2\n"); if (r_shadowCascadeZFar->integer != 0) Q_strcat(extradefines, 1024, "#define USE_SHADOW_CASCADE\n"); Q_strcat(extradefines, 1024, va("#define r_shadowMapSize %f\n", r_shadowMapSize->value)); Q_strcat(extradefines, 1024, va("#define r_shadowCascadeZFar %f\n", r_shadowCascadeZFar->value)); if (!GLSL_InitGPUShader(&tr.shadowmaskShader, "shadowmask", attribs, qtrue, extradefines, qtrue, fallbackShader_shadowmask_vp, fallbackShader_shadowmask_fp)) { ri.Error(ERR_FATAL, "Could not load shadowmask shader!"); } GLSL_InitUniforms(&tr.shadowmaskShader); qglUseProgramObjectARB(tr.shadowmaskShader.program); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SCREENDEPTHMAP, TB_COLORMAP); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP, TB_SHADOWMAP); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP2, TB_SHADOWMAP2); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP3, TB_SHADOWMAP3); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP4, TB_SHADOWMAP4); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.shadowmaskShader); numEtcShaders++; attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (!GLSL_InitGPUShader(&tr.ssaoShader, "ssao", attribs, qtrue, extradefines, qtrue, fallbackShader_ssao_vp, fallbackShader_ssao_fp)) { ri.Error(ERR_FATAL, "Could not load ssao shader!"); } GLSL_InitUniforms(&tr.ssaoShader); qglUseProgramObjectARB(tr.ssaoShader.program); GLSL_SetUniformInt(&tr.ssaoShader, UNIFORM_SCREENDEPTHMAP, TB_COLORMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.ssaoShader); numEtcShaders++; for (i = 0; i < 2; i++) { attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; if (i & 1) Q_strcat(extradefines, 1024, "#define USE_VERTICAL_BLUR\n"); else Q_strcat(extradefines, 1024, "#define USE_HORIZONTAL_BLUR\n"); if (!GLSL_InitGPUShader(&tr.depthBlurShader[i], "depthBlur", attribs, qtrue, extradefines, qtrue, fallbackShader_depthblur_vp, fallbackShader_depthblur_fp)) { ri.Error(ERR_FATAL, "Could not load depthBlur shader!"); } GLSL_InitUniforms(&tr.depthBlurShader[i]); qglUseProgramObjectARB(tr.depthBlurShader[i].program); GLSL_SetUniformInt(&tr.depthBlurShader[i], UNIFORM_SCREENIMAGEMAP, TB_COLORMAP); GLSL_SetUniformInt(&tr.depthBlurShader[i], UNIFORM_SCREENDEPTHMAP, TB_LIGHTMAP); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.depthBlurShader[i]); numEtcShaders++; } #endif endTime = ri.Milliseconds(); ri.Printf(PRINT_ALL, "loaded %i GLSL shaders (%i gen %i light %i etc) in %5.2f seconds\n", numGenShaders + numLightShaders + numEtcShaders, numGenShaders, numLightShaders, numEtcShaders, (endTime - startTime) / 1000.0); }
/* * R_RenderMeshGLSL_Material */ static void R_RenderMeshGLSL_Material( r_glslfeat_t programFeatures ) { int i; int tcgen, rgbgen; int state; int program, object; image_t *base, *normalmap, *glossmap, *decalmap, *entdecalmap; mat4x4_t unused; vec3_t lightDir = { 0.0f, 0.0f, 0.0f }; vec4_t ambient = { 0.0f, 0.0f, 0.0f, 0.0f }, diffuse = { 0.0f, 0.0f, 0.0f, 0.0f }; float offsetmappingScale, glossExponent; const superLightStyle_t *lightStyle = NULL; const mfog_t *fog = r_back.colorFog; shaderpass_t *pass = r_back.accumPasses[0]; qboolean applyDecal; // handy pointers base = pass->anim_frames[0]; normalmap = pass->anim_frames[1]; glossmap = pass->anim_frames[2]; decalmap = pass->anim_frames[3]; entdecalmap = pass->anim_frames[4]; tcgen = pass->tcgen; // store the original tcgen rgbgen = pass->rgbgen.type; // store the original rgbgen assert( normalmap ); if( normalmap->samples == 4 ) offsetmappingScale = r_offsetmapping_scale->value * r_back.currentShader->offsetmapping_scale; else // no alpha in normalmap, don't bother with offset mapping offsetmappingScale = 0; if( r_back.currentShader->gloss_exponent ) glossExponent = r_back.currentShader->gloss_exponent; else glossExponent = r_lighting_glossexponent->value; applyDecal = decalmap != NULL; if( ri.params & RP_CLIPPLANE ) programFeatures |= GLSL_COMMON_APPLY_CLIPPING; if( pass->flags & SHADERPASS_GRAYSCALE ) programFeatures |= GLSL_COMMON_APPLY_GRAYSCALE; if( fog ) { programFeatures |= GLSL_COMMON_APPLY_FOG; if( fog != ri.fog_eye ) programFeatures |= GLSL_COMMON_APPLY_FOG2; if( GL_IsAlphaBlending( pass->flags & GLSTATE_SRCBLEND_MASK, pass->flags & GLSTATE_DSTBLEND_MASK ) ) programFeatures |= GLSL_COMMON_APPLY_COLOR_FOG_ALPHA; } if( r_back.currentMeshBuffer->infokey > 0 && ( rgbgen != RGB_GEN_LIGHTING_DIFFUSE ) ) { if( !( r_offsetmapping->integer & 1 ) ) { offsetmappingScale = 0; } if( ri.params & RP_LIGHTMAP ) { programFeatures |= GLSL_MATERIAL_APPLY_BASETEX_ALPHA_ONLY; } if( ( ri.params & RP_DRAWFLAT ) && !( r_back.currentShader->flags & SHADER_NODRAWFLAT ) ) { programFeatures |= GLSL_COMMON_APPLY_DRAWFLAT|GLSL_MATERIAL_APPLY_BASETEX_ALPHA_ONLY; } } else if( ( r_back.currentMeshBuffer->sortkey & 3 ) == MB_POLY ) { // polys if( !( r_offsetmapping->integer & 2 ) ) offsetmappingScale = 0; R_BuildTangentVectors( r_backacc.numVerts, vertsArray, normalsArray, coordsArray, r_backacc.numElems/3, elemsArray, inSVectorsArray ); } else { // models and world lightingDiffuse materials if( r_back.currentMeshBuffer->infokey > 0 ) { if( !( r_offsetmapping->integer & 1 ) ) offsetmappingScale = 0; pass->rgbgen.type = RGB_GEN_VERTEX; } else { // models if( !( r_offsetmapping->integer & 4 ) ) offsetmappingScale = 0; #ifdef CELLSHADEDMATERIAL programFeatures |= GLSL_MATERIAL_APPLY_CELLSHADING; #endif #ifdef HALFLAMBERTLIGHTING programFeatures |= GLSL_MATERIAL_APPLY_HALFLAMBERT; #endif } } // add dynamic lights if( r_back.currentDlightBits ) { programFeatures |= R_DlightbitsToProgramFeatures(); } pass->tcgen = TC_GEN_BASE; R_BindShaderpass( pass, base, 0, &programFeatures ); // calculate vertex color R_ModifyColor( pass, applyDecal, r_back.currentMeshVBO != NULL ); // since R_ModifyColor has forcefully generated RGBA for the first vertex, // set the proper number of color elements here, so GL_COLOR_ARRAY will be enabled // before the DrawElements call if( !(pass->flags & SHADERPASS_NOCOLORARRAY) ) r_backacc.numColors = r_backacc.numVerts; // convert rgbgen and alphagen to GLSL feature defines programFeatures |= R_RGBAlphaGenToProgramFeatures( pass->rgbgen.type, pass->alphagen.type ); GL_TexEnv( GL_MODULATE ); // set shaderpass state (blending, depthwrite, etc) state = r_back.currentShaderState | ( pass->flags & r_back.currentShaderPassMask ) | GLSTATE_BLEND_MTEX; GL_SetState( state ); #if 1 // don't waste time on processing GLSL programs with zero colormask if( ( ri.params & RP_SHADOWMAPVIEW ) & !(programFeatures & GLSL_COMMON_APPLY_BONETRANSFORMS) ) { pass->tcgen = tcgen; // restore original tcgen R_FlushArrays(); return; } #endif // we only send S-vectors to GPU and recalc T-vectors as cross product // in vertex shader pass->tcgen = TC_GEN_SVECTORS; GL_Bind( 1, normalmap ); // normalmap GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY ); R_VertexTCBase( pass, 1, unused, NULL ); if( glossmap && r_lighting_glossintensity->value ) { programFeatures |= GLSL_MATERIAL_APPLY_SPECULAR; GL_Bind( 2, glossmap ); // gloss GL_SetTexCoordArrayMode( 0 ); } if( applyDecal ) { programFeatures |= GLSL_MATERIAL_APPLY_DECAL; if( ri.params & RP_LIGHTMAP ) { decalmap = r_blacktexture; programFeatures |= GLSL_MATERIAL_APPLY_DECAL_ADD; } else { // if no alpha, use additive blending if( decalmap->samples == 3 ) programFeatures |= GLSL_MATERIAL_APPLY_DECAL_ADD; } GL_Bind( 3, decalmap ); // decal GL_SetTexCoordArrayMode( 0 ); } if( entdecalmap ) { programFeatures |= GLSL_MATERIAL_APPLY_ENTITY_DECAL; // if no alpha, use additive blending if( entdecalmap->samples == 3 ) programFeatures |= GLSL_MATERIAL_APPLY_ENTITY_DECAL_ADD; GL_Bind( 4, entdecalmap ); // decal GL_SetTexCoordArrayMode( 0 ); } if( offsetmappingScale > 0 ) programFeatures |= r_offsetmapping_reliefmapping->integer ? GLSL_MATERIAL_APPLY_RELIEFMAPPING : GLSL_MATERIAL_APPLY_OFFSETMAPPING; if( r_back.currentMeshBuffer->infokey > 0 && ( rgbgen != RGB_GEN_LIGHTING_DIFFUSE ) ) { // world surface if( r_back.superLightStyle && r_back.superLightStyle->lightmapNum[0] >= 0 ) { lightStyle = r_back.superLightStyle; // bind lightmap textures and set program's features for lightstyles pass->tcgen = TC_GEN_LIGHTMAP; for( i = 0; i < MAX_LIGHTMAPS && lightStyle->lightmapStyles[i] != 255; i++ ) { r_back.lightmapStyleNum[i+4] = i; GL_Bind( i+4, r_worldbrushmodel->lightmapImages[lightStyle->lightmapNum[i]] ); // lightmap GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY ); R_VertexTCBase( pass, i+4, unused, NULL ); } programFeatures |= ( i * GLSL_MATERIAL_APPLY_LIGHTSTYLE0 ); if( i == 1 && !mapConfig.lightingIntensity ) { vec_t *rgb = r_lightStyles[lightStyle->lightmapStyles[0]].rgb; // GLSL_MATERIAL_APPLY_FB_LIGHTMAP indicates that there's no need to renormalize // the lighting vector for specular (saves 3 adds, 3 muls and 1 normalize per pixel) if( rgb[0] == 1 && rgb[1] == 1 && rgb[2] == 1 ) programFeatures |= GLSL_MATERIAL_APPLY_FB_LIGHTMAP; } if( !VectorCompare( mapConfig.ambient, vec3_origin ) ) { VectorCopy( mapConfig.ambient, ambient ); programFeatures |= GLSL_MATERIAL_APPLY_AMBIENT_COMPENSATION; } } } else { vec3_t temp; programFeatures |= GLSL_MATERIAL_APPLY_DIRECTIONAL_LIGHT; if( ( r_back.currentMeshBuffer->sortkey & 3 ) == MB_POLY ) { VectorCopy( r_polys[-r_back.currentMeshBuffer->infokey-1].normal, lightDir ); Vector4Set( ambient, 0, 0, 0, 0 ); Vector4Set( diffuse, 1, 1, 1, 1 ); } else if( ri.currententity ) { if( ri.currententity->flags & RF_FULLBRIGHT ) { Vector4Set( ambient, 1, 1, 1, 1 ); Vector4Set( diffuse, 1, 1, 1, 1 ); } else { if( r_back.currentMeshBuffer->infokey > 0 ) { programFeatures |= GLSL_MATERIAL_APPLY_DIRECTIONAL_LIGHT_MIX; if( r_back.overBrightBits ) programFeatures |= GLSL_COMMON_APPLY_OVERBRIGHT_SCALING; } if( ri.currententity->model && ri.currententity != r_worldent ) { // get weighted incoming direction of world and dynamic lights R_LightForOrigin( ri.currententity->lightingOrigin, temp, ambient, diffuse, ri.currententity->model->radius * ri.currententity->scale); } else { VectorSet( temp, 0.1f, 0.2f, 0.7f ); } if( ri.currententity->flags & RF_MINLIGHT ) { if( ambient[0] <= 0.1f || ambient[1] <= 0.1f || ambient[2] <= 0.1f ) VectorSet( ambient, 0.1f, 0.1f, 0.1f ); } // rotate direction Matrix_TransformVector( ri.currententity->axis, temp, lightDir ); } } } pass->tcgen = tcgen; // restore original tcgen pass->rgbgen.type = rgbgen; // restore original rgbgen program = R_RegisterGLSLProgram( pass->program_type, pass->program, NULL, r_back.currentShader->name, r_back.currentShader->deforms, r_back.currentShader->numdeforms, programFeatures ); object = R_GetProgramObject( program ); if( object ) { qglUseProgramObjectARB( object ); // update uniforms R_UpdateProgramUniforms( program, ri.viewOrigin, vec3_origin, lightDir, ambient, diffuse, lightStyle, qtrue, 0, 0, 0, offsetmappingScale, glossExponent, colorArrayCopy[0], r_back.overBrightBits, r_back.currentShaderTime, r_back.entityColor ); if( programFeatures & GLSL_COMMON_APPLY_FOG ) { cplane_t fogPlane, vpnPlane; R_TransformFogPlanes( fog, fogPlane.normal, &fogPlane.dist, vpnPlane.normal, &vpnPlane.dist ); R_UpdateProgramFogParams( program, fog->shader->fog_color, fog->shader->fog_clearDist, fog->shader->fog_dist, &fogPlane, &vpnPlane, ri.fog_dist_to_eye[fog-r_worldbrushmodel->fogs] ); } // submit animation data if( programFeatures & GLSL_COMMON_APPLY_BONETRANSFORMS ) { R_UpdateProgramBonesParams( program, r_back.currentAnimData->numBones, r_back.currentAnimData->dualQuats ); } // dynamic lights if( r_back.currentDlightBits ) { R_UpdateProgramLightsParams( program, ri.currententity->origin, ri.currententity->axis, r_back.currentDlightBits ); r_back.doDynamicLightsPass = qfalse; } // r_drawflat if( programFeatures & GLSL_COMMON_APPLY_DRAWFLAT ) { R_UpdateDrawFlatParams( program, r_front.wallColor, r_front.floorColor ); } R_FlushArrays(); qglUseProgramObjectARB( 0 ); } }
/* ================== RB_GLSL_DrawInteractions ================== */ void RB_GLSL_DrawInteractions( void ) { viewLight_t *vLight; 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 there are no interactions, get out! if ( !vLight->localInteractions && !vLight->globalInteractions && !vLight->translucentInteractions ) { continue; } // 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() ) { qglUseProgramObjectARB( stencilShadowShader.program ); RB_StencilShadowPass( vLight->globalShadows ); RB_GLSL_CreateDrawInteractions( vLight->localInteractions ); qglUseProgramObjectARB( stencilShadowShader.program ); RB_StencilShadowPass( vLight->localShadows ); RB_GLSL_CreateDrawInteractions( vLight->globalInteractions ); qglUseProgramObjectARB( 0 ); // if there weren't any globalInteractions, it would have stayed on } else { RB_StencilShadowPass( vLight->globalShadows ); RB_GLSL_CreateDrawInteractions( vLight->localInteractions ); RB_StencilShadowPass( vLight->localShadows ); RB_GLSL_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_GLSL_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_GLSL_InitShaders ================== */ static bool RB_GLSL_InitShaders( ) { // load interation shaders R_LoadGLSLShader( "interaction_Dir.vs", &interactionDirShader, GL_VERTEX_SHADER_ARB ); R_LoadGLSLShader( "interaction_Dir.fs", &interactionDirShader, GL_FRAGMENT_SHADER_ARB ); if ( !R_LinkGLSLShader( &interactionDirShader, true ) && !R_ValidateGLSLProgram( &interactionDirShader ) ) { return false; } else { // set uniform locations interactionDirShader.u_lightCubeTexture = qglGetUniformLocationARB( interactionDirShader.program, "u_lightCubeTexture" ); interactionDirShader.u_lightProjectionTexture = qglGetUniformLocationARB( interactionDirShader.program, "u_lightProjectionTexture" ); interactionDirShader.u_lightFalloffTexture = qglGetUniformLocationARB( interactionDirShader.program, "u_lightFalloffTexture" ); interactionDirShader.u_normalTexture = qglGetUniformLocationARB( interactionDirShader.program, "u_normalTexture" ); interactionDirShader.u_diffuseTexture = qglGetUniformLocationARB( interactionDirShader.program, "u_diffuseTexture" ); interactionDirShader.u_specularTexture = qglGetUniformLocationARB( interactionDirShader.program, "u_specularTexture" ); interactionDirShader.u_ssaoTexture = qglGetUniformLocationARB( interactionDirShader.program, "u_ssaoTexture" ); interactionDirShader.u_aux0Texture = qglGetUniformLocationARB( interactionDirShader.program, "u_aux0Texture" ); interactionDirShader.u_aux1Texture = qglGetUniformLocationARB( interactionDirShader.program, "u_aux1Texture" ); interactionDirShader.u_aux2Texture = qglGetUniformLocationARB( interactionDirShader.program, "u_aux2Texture" ); interactionDirShader.u_aux3Texture = qglGetUniformLocationARB( interactionDirShader.program, "u_aux3Texture" ); interactionDirShader.u_aux4Texture = qglGetUniformLocationARB( interactionDirShader.program, "u_aux4Texture" ); interactionDirShader.u_aux5Texture = qglGetUniformLocationARB( interactionDirShader.program, "u_aux5Texture" ); interactionDirShader.u_aux6Texture = qglGetUniformLocationARB( interactionDirShader.program, "u_aux6Texture" ); interactionDirShader.u_aux7Texture = qglGetUniformLocationARB( interactionDirShader.program, "u_aux7Texture" ); interactionDirShader.u_aux8Texture = qglGetUniformLocationARB( interactionDirShader.program, "u_aux8Texture" ); interactionDirShader.u_aux9Texture = qglGetUniformLocationARB( interactionDirShader.program, "u_aux9Texture" ); interactionDirShader.modelMatrix = qglGetUniformLocationARB( interactionDirShader.program, "u_modelMatrix" ); interactionDirShader.localLightOrigin = qglGetUniformLocationARB( interactionDirShader.program, "u_lightOrigin" ); interactionDirShader.localViewOrigin = qglGetUniformLocationARB( interactionDirShader.program, "u_viewOrigin" ); interactionDirShader.lightProjectionS = qglGetUniformLocationARB( interactionDirShader.program, "u_lightProjectionS" ); interactionDirShader.lightProjectionT = qglGetUniformLocationARB( interactionDirShader.program, "u_lightProjectionT" ); interactionDirShader.lightProjectionQ = qglGetUniformLocationARB( interactionDirShader.program, "u_lightProjectionQ" ); interactionDirShader.lightFalloff = qglGetUniformLocationARB( interactionDirShader.program, "u_lightFalloff" ); interactionDirShader.bumpMatrixS = qglGetUniformLocationARB( interactionDirShader.program, "u_bumpMatrixS" ); interactionDirShader.bumpMatrixT = qglGetUniformLocationARB( interactionDirShader.program, "u_bumpMatrixT" ); interactionDirShader.diffuseMatrixS = qglGetUniformLocationARB( interactionDirShader.program, "u_diffuseMatrixS" ); interactionDirShader.diffuseMatrixT = qglGetUniformLocationARB( interactionDirShader.program, "u_diffuseMatrixT" ); interactionDirShader.specularMatrixS = qglGetUniformLocationARB( interactionDirShader.program, "u_specularMatrixS" ); interactionDirShader.specularMatrixT = qglGetUniformLocationARB( interactionDirShader.program, "u_specularMatrixT" ); interactionDirShader.specularMatrixT = qglGetUniformLocationARB( interactionDirShader.program, "u_specularMatrixT" ); interactionDirShader.colorMAD = qglGetUniformLocationARB( interactionDirShader.program, "u_colorMAD" ); interactionDirShader.diffuseColor = qglGetUniformLocationARB( interactionDirShader.program, "u_diffuseColor" ); interactionDirShader.specularColor = qglGetUniformLocationARB( interactionDirShader.program, "u_specularColor" ); interactionDirShader.falloffType = qglGetUniformLocationARB( interactionDirShader.program, "u_falloffType" ); interactionDirShader.specExp = qglGetUniformLocationARB( interactionDirShader.program, "u_specExp" ); interactionDirShader.localParms[0] = qglGetUniformLocationARB( interactionDirShader.program, "u_localParm0" ); interactionDirShader.localParms[1] = qglGetUniformLocationARB( interactionDirShader.program, "u_localParm1" ); interactionDirShader.localParms[2] = qglGetUniformLocationARB( interactionDirShader.program, "u_localParm2" ); interactionDirShader.localParms[3] = qglGetUniformLocationARB( interactionDirShader.program, "u_localParm3" ); interactionDirShader.localParms[4] = qglGetUniformLocationARB( interactionDirShader.program, "u_localParm4" ); interactionDirShader.localParms[5] = qglGetUniformLocationARB( interactionDirShader.program, "u_localParm5" ); interactionDirShader.localParms[6] = qglGetUniformLocationARB( interactionDirShader.program, "u_localParm6" ); interactionDirShader.localParms[7] = qglGetUniformLocationARB( interactionDirShader.program, "u_localParm7" ); // set texture locations qglUseProgramObjectARB( interactionDirShader.program ); qglUniform1iARB( interactionDirShader.u_lightCubeTexture, 0 ); qglUniform1iARB( interactionDirShader.u_lightProjectionTexture, 16 ); qglUniform1iARB( interactionDirShader.u_lightFalloffTexture, 1 ); qglUniform1iARB( interactionDirShader.u_normalTexture, 2 ); qglUniform1iARB( interactionDirShader.u_diffuseTexture, 3 ); qglUniform1iARB( interactionDirShader.u_specularTexture, 4 ); qglUniform1iARB( interactionDirShader.u_ssaoTexture, 5 ); qglUniform1iARB( interactionDirShader.u_aux0Texture, 6 ); qglUniform1iARB( interactionDirShader.u_aux1Texture, 7 ); qglUniform1iARB( interactionDirShader.u_aux2Texture, 8 ); qglUniform1iARB( interactionDirShader.u_aux3Texture, 9 ); qglUniform1iARB( interactionDirShader.u_aux4Texture, 10 ); qglUniform1iARB( interactionDirShader.u_aux5Texture, 11 ); qglUniform1iARB( interactionDirShader.u_aux6Texture, 12 ); qglUniform1iARB( interactionDirShader.u_aux7Texture, 13 ); qglUniform1iARB( interactionDirShader.u_aux8Texture, 14 ); qglUniform1iARB( interactionDirShader.u_aux9Texture, 15 ); qglUseProgramObjectARB( 0 ); } // load ambient interation shaders R_LoadGLSLShader( "interaction_Amb.vs", &interactionAmbShader, GL_VERTEX_SHADER_ARB ); R_LoadGLSLShader( "interaction_Amb.fs", &interactionAmbShader, GL_FRAGMENT_SHADER_ARB ); if ( !R_LinkGLSLShader( &interactionAmbShader, true ) && !R_ValidateGLSLProgram( &interactionAmbShader ) ) { return false; } else { // set uniform locations interactionAmbShader.u_lightCubeTexture = qglGetUniformLocationARB( interactionAmbShader.program, "u_lightCubeTexture" ); interactionAmbShader.u_lightFalloffTexture = qglGetUniformLocationARB( interactionAmbShader.program, "u_lightFalloffTexture" ); interactionAmbShader.u_normalTexture = qglGetUniformLocationARB( interactionAmbShader.program, "u_normalTexture" ); interactionAmbShader.u_diffuseTexture = qglGetUniformLocationARB( interactionAmbShader.program, "u_diffuseTexture" ); interactionAmbShader.u_specularTexture = qglGetUniformLocationARB( interactionAmbShader.program, "u_specularTexture" ); interactionAmbShader.u_ssaoTexture = qglGetUniformLocationARB( interactionAmbShader.program, "u_ssaoTexture" ); interactionAmbShader.u_aux0Texture = qglGetUniformLocationARB( interactionAmbShader.program, "u_aux0Texture" ); interactionAmbShader.u_aux1Texture = qglGetUniformLocationARB( interactionAmbShader.program, "u_aux1Texture" ); interactionAmbShader.u_aux2Texture = qglGetUniformLocationARB( interactionAmbShader.program, "u_aux2Texture" ); interactionAmbShader.u_aux3Texture = qglGetUniformLocationARB( interactionAmbShader.program, "u_aux3Texture" ); interactionAmbShader.u_aux4Texture = qglGetUniformLocationARB( interactionAmbShader.program, "u_aux4Texture" ); interactionAmbShader.u_aux5Texture = qglGetUniformLocationARB( interactionAmbShader.program, "u_aux5Texture" ); interactionAmbShader.u_aux6Texture = qglGetUniformLocationARB( interactionAmbShader.program, "u_aux6Texture" ); interactionAmbShader.u_aux7Texture = qglGetUniformLocationARB( interactionAmbShader.program, "u_aux7Texture" ); interactionAmbShader.u_aux8Texture = qglGetUniformLocationARB( interactionAmbShader.program, "u_aux8Texture" ); interactionAmbShader.u_aux9Texture = qglGetUniformLocationARB( interactionAmbShader.program, "u_aux9Texture" ); interactionAmbShader.modelMatrix = qglGetUniformLocationARB( interactionAmbShader.program, "u_modelMatrix" ); interactionAmbShader.localLightOrigin = qglGetUniformLocationARB( interactionAmbShader.program, "u_lightOrigin" ); interactionAmbShader.localViewOrigin = qglGetUniformLocationARB( interactionAmbShader.program, "u_viewOrigin" ); interactionAmbShader.lightProjectionS = qglGetUniformLocationARB( interactionAmbShader.program, "u_lightProjectionS" ); interactionAmbShader.lightProjectionT = qglGetUniformLocationARB( interactionAmbShader.program, "u_lightProjectionT" ); interactionAmbShader.lightProjectionQ = qglGetUniformLocationARB( interactionAmbShader.program, "u_lightProjectionQ" ); interactionAmbShader.lightFalloff = qglGetUniformLocationARB( interactionAmbShader.program, "u_lightFalloff" ); interactionAmbShader.bumpMatrixS = qglGetUniformLocationARB( interactionAmbShader.program, "u_bumpMatrixS" ); interactionAmbShader.bumpMatrixT = qglGetUniformLocationARB( interactionAmbShader.program, "u_bumpMatrixT" ); interactionAmbShader.diffuseMatrixS = qglGetUniformLocationARB( interactionAmbShader.program, "u_diffuseMatrixS" ); interactionAmbShader.diffuseMatrixT = qglGetUniformLocationARB( interactionAmbShader.program, "u_diffuseMatrixT" ); interactionAmbShader.specularMatrixS = qglGetUniformLocationARB( interactionAmbShader.program, "u_specularMatrixS" ); interactionAmbShader.specularMatrixT = qglGetUniformLocationARB( interactionAmbShader.program, "u_specularMatrixT" ); interactionAmbShader.colorMAD = qglGetUniformLocationARB( interactionAmbShader.program, "u_colorMAD" ); interactionAmbShader.diffuseColor = qglGetUniformLocationARB( interactionAmbShader.program, "u_diffuseColor" ); interactionAmbShader.specularColor = qglGetUniformLocationARB( interactionAmbShader.program, "u_specularColor" ); interactionAmbShader.specExp = qglGetUniformLocationARB( interactionAmbShader.program, "u_specExp" ); interactionAmbShader.localParms[0] = qglGetUniformLocationARB( interactionAmbShader.program, "u_localParm0" ); interactionAmbShader.localParms[1] = qglGetUniformLocationARB( interactionAmbShader.program, "u_localParm1" ); interactionAmbShader.localParms[2] = qglGetUniformLocationARB( interactionAmbShader.program, "u_localParm2" ); interactionAmbShader.localParms[3] = qglGetUniformLocationARB( interactionAmbShader.program, "u_localParm3" ); interactionAmbShader.localParms[4] = qglGetUniformLocationARB( interactionAmbShader.program, "u_localParm4" ); interactionAmbShader.localParms[5] = qglGetUniformLocationARB( interactionAmbShader.program, "u_localParm5" ); interactionAmbShader.localParms[6] = qglGetUniformLocationARB( interactionAmbShader.program, "u_localParm6" ); interactionAmbShader.localParms[7] = qglGetUniformLocationARB( interactionAmbShader.program, "u_localParm7" ); // set texture locations qglUseProgramObjectARB( interactionAmbShader.program ); qglUniform1iARB( interactionAmbShader.u_lightCubeTexture, 0 ); qglUniform1iARB( interactionAmbShader.u_lightFalloffTexture, 1 ); qglUniform1iARB( interactionAmbShader.u_normalTexture, 2 ); qglUniform1iARB( interactionAmbShader.u_diffuseTexture, 3 ); qglUniform1iARB( interactionAmbShader.u_specularTexture, 4 ); qglUniform1iARB( interactionAmbShader.u_ssaoTexture, 5 ); qglUniform1iARB( interactionAmbShader.u_aux0Texture, 6 ); qglUniform1iARB( interactionAmbShader.u_aux1Texture, 7 ); qglUniform1iARB( interactionAmbShader.u_aux2Texture, 8 ); qglUniform1iARB( interactionAmbShader.u_aux3Texture, 9 ); qglUniform1iARB( interactionAmbShader.u_aux4Texture, 10 ); qglUniform1iARB( interactionAmbShader.u_aux5Texture, 11 ); qglUniform1iARB( interactionAmbShader.u_aux6Texture, 12 ); qglUniform1iARB( interactionAmbShader.u_aux7Texture, 13 ); qglUniform1iARB( interactionAmbShader.u_aux8Texture, 14 ); qglUniform1iARB( interactionAmbShader.u_aux9Texture, 15 ); qglUseProgramObjectARB( 0 ); } // load stencil shadow extrusion shaders R_LoadGLSLShader( "stencilshadow.vs", &stencilShadowShader, GL_VERTEX_SHADER_ARB ); R_LoadGLSLShader( "stencilshadow.fs", &stencilShadowShader, GL_FRAGMENT_SHADER_ARB ); if ( !R_LinkGLSLShader( &stencilShadowShader, false ) && !R_ValidateGLSLProgram( &stencilShadowShader ) ) { return false; } else { // set uniform locations stencilShadowShader.localLightOrigin = qglGetUniformLocationARB( stencilShadowShader.program, "u_lightOrigin" ); } return true; }
/* ** RB_EndSurface */ void RB_EndSurface( qboolean forceDepth ) { shaderCommands_t *input; GLenum prog; int loc; int i,size; shaderStage_t stage; image_t image; char tex[MAX_QPATH]; input = &tess; if ( tess.shader == tr.maskEndShader ) { RB_MaskTessFinish(); return; } if (input->numIndexes == 0) { return; } if (input->indexes[SHADER_MAX_INDEXES-1] != 0) { ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_INDEXES hit"); } if (input->xyz[SHADER_MAX_VERTEXES-1][0] != 0) { ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_VERTEXES hit"); } if ( tess.shader == tr.shadowShader ) { RB_ShadowTessEnd(); return; } if ( tess.shader == tr.maskShader ) { RB_MaskTessEnd(); return; } // for debugging of sort order issues, stop rendering after a given sort value if ( r_debugSort->integer && r_debugSort->integer < tess.shader->sort ) { return; } // // update performance counters // backEnd.pc.c_shaders++; backEnd.pc.c_vertexes += tess.numVertexes; backEnd.pc.c_indexes += tess.numIndexes; backEnd.pc.c_totalIndexes += tess.numIndexes * tess.numPasses; if(forceDepth) { //Force depth testing if we are rendering via draw.Start3D -Hxrmn size = sizeof(tess.xstages) / sizeof(tess.xstages[0]); for(i=0; i<size; i++) { if(tess.xstages[i] != NULL) { if(tess.xstages[i]->stateBits & GLS_DEPTHTEST_DISABLE) { tess.xstages[i]->stateBits &= ~GLS_DEPTHTEST_DISABLE; } } } } // // call off to shader specific tess end function // if(tess.shader->GLSL) { prog = getShaderProgram(tess.shader->GLSLName); if(prog != -1) { qglUseProgramObjectARB(prog); if(qglUniform1fARB) { loc = qglGetUniformLocationARB(prog, "cgtime"); qglUniform1fARB(loc, backEnd.refdef.floatTime); } if(qglUniform3fvARB) { loc = qglGetUniformLocationARB(prog, "viewPos"); qglUniform3fARB(loc, backEnd.refdef.vieworg[0], backEnd.refdef.vieworg[1], backEnd.refdef.vieworg[2]); } if(qglUniform3fvARB) { loc = qglGetUniformLocationARB(prog, "viewNormal"); qglUniform3fARB(loc, backEnd.refdef.viewaxis[0][0], backEnd.refdef.viewaxis[0][1], backEnd.refdef.viewaxis[0][2]); } if(qglUniform2fARB) { loc = qglGetUniformLocationARB(prog, "fov"); qglUniform2fARB(loc, backEnd.refdef.fov_x, backEnd.refdef.fov_y); } /* loc = qglGetUniformLocationARB(prog, "texture_0"); qglUniform1iARB(loc, 0); loc = qglGetUniformLocationARB(prog, "texture_1"); qglUniform1iARB(loc, 1);*/ } } //tess.shader->stages[0]->bundle[0].image tess.currentStageIteratorFunc(); if(tess.shader->GLSL) { revertShaderProgram(); qglDisable(GL_TEXTURE0_ARB); qglDisable(GL_TEXTURE1_ARB); qglDisable(GL_TEXTURE2_ARB); qglDisable(GL_TEXTURE3_ARB); } // // draw debugging stuff // if ( r_showtris->integer ) { DrawTris (input); } if ( r_shownormals->integer ) { DrawNormals (input); } // clear shader so we can tell we don't have any unclosed surfaces tess.numIndexes = 0; GLimp_LogComment( "----------\n" ); }
/* ============= 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 ); }
void RB_ColorCorrect( void ) { GLint loc; GLenum target; int width, height; int shift; float mul; if ( !r_enablePostProcess->integer || !r_enableColorCorrect->integer || !glsl ) { return; } GL_SelectTexture(0); qglDisable(GL_TEXTURE_2D); qglEnable(GL_TEXTURE_RECTANGLE_ARB); target = GL_TEXTURE_RECTANGLE_ARB; width = glConfig.vidWidth; height = glConfig.vidHeight; qglBindTexture(target, tr.backBufferTexture); qglCopyTexSubImage2D(target, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight); qglMatrixMode(GL_PROJECTION); qglLoadIdentity(); qglMatrixMode(GL_MODELVIEW); qglLoadIdentity(); RB_SetGL2D(); GL_State( GLS_DEPTHTEST_DISABLE ); qglUseProgramObjectARB(tr.colorCorrectSp); loc = qglGetUniformLocationARB(tr.colorCorrectSp, "p_gammaRecip"); if (loc < 0) { Com_Error(ERR_DROP, "%s() couldn't get p_gammaRecip", __FUNCTION__); } qglUniform1fARB(loc, (GLfloat)(1.0 / r_gamma->value)); //mul = r_overBrightBitsValue->value; mul = r_overBrightBits->value; if (mul < 0.0) { mul = 0.0; } shift = tr.overbrightBits; loc = qglGetUniformLocationARB(tr.colorCorrectSp, "p_overbright"); if (loc < 0) { Com_Error(ERR_DROP, "%s() couldn't get p_overbright", __FUNCTION__); } qglUniform1fARB(loc, (GLfloat)((float)(1 << shift) * mul)); loc = qglGetUniformLocationARB(tr.colorCorrectSp, "p_contrast"); if (loc < 0) { Com_Error(ERR_DROP, "%s() couldn't get p_contrast", __FUNCTION__); } qglUniform1fARB(loc, (GLfloat)r_contrast->value); loc = qglGetUniformLocationARB(tr.colorCorrectSp, "backBufferTex"); if (loc < 0) { Com_Error(ERR_DROP, "%s() couldn't get backBufferTex", __FUNCTION__); } qglUniform1iARB(loc, 0); qglBegin(GL_QUADS); qglTexCoord2i(0, 0); qglVertex2i(0, height); qglTexCoord2i(width, 0); qglVertex2i(width, height); qglTexCoord2i(width, height); qglVertex2i(width, 0); qglTexCoord2i(0, height); qglVertex2i(0, 0); qglEnd(); qglUseProgramObjectARB(0); qglDisable(GL_TEXTURE_RECTANGLE_ARB); qglEnable(GL_TEXTURE_2D); }
static void RB_BloomCombine( void ) { GLenum target; int width, height; GLint loc; GL_SelectTexture(0); qglDisable(GL_TEXTURE_2D); qglEnable(GL_TEXTURE_RECTANGLE_ARB); target = GL_TEXTURE_RECTANGLE_ARB; width = tr.bloomWidth; height = tr.bloomHeight; qglBindTexture(target, tr.bloomTexture); qglCopyTexSubImage2D(target, 0, 0, 0, 0, glConfig.vidHeight - height, width, height); qglUseProgramObjectARB(tr.combineSp); qglBindTexture(target, tr.backBufferTexture); loc = qglGetUniformLocationARB(tr.combineSp, "backBufferTex"); if (loc < 0) { Com_Error(ERR_DROP, "%s() couldn't get backBufferTex", __FUNCTION__); } qglUniform1iARB(loc, 0); GL_SelectTexture(1); qglDisable(GL_TEXTURE_2D); qglEnable(GL_TEXTURE_RECTANGLE_ARB); qglBindTexture(target, tr.bloomTexture); loc = qglGetUniformLocationARB(tr.combineSp, "bloomTex"); if (loc < 0) { Com_Error(ERR_DROP, "%s() couldn't get bloomTex", __FUNCTION__); } qglUniform1iARB(loc, 1); loc = qglGetUniformLocationARB(tr.combineSp, "p_bloomsaturation"); if (loc < 0) { Com_Error(ERR_DROP, "%s() couldn't get p_bloomsaturation", __FUNCTION__); } qglUniform1fARB(loc, (GLfloat)r_BloomSaturation->value); loc = qglGetUniformLocationARB(tr.combineSp, "p_scenesaturation"); if (loc < 0) { Com_Error(ERR_DROP, "%s() couldn't get p_scenesaturation", __FUNCTION__); } qglUniform1fARB(loc, (GLfloat)r_BloomSceneSaturation->value); loc = qglGetUniformLocationARB(tr.combineSp, "p_bloomintensity"); if (loc < 0) { Com_Error(ERR_DROP, "%s() couldn't get p_bloomintensity", __FUNCTION__); } qglUniform1fARB(loc, (GLfloat)r_BloomIntensity->value); loc = qglGetUniformLocationARB(tr.combineSp, "p_sceneintensity"); if (loc < 0) { Com_Error(ERR_DROP, "%s() couldn't get p_sceneintensity", __FUNCTION__); } qglUniform1fARB(loc, (GLfloat)r_BloomSceneIntensity->value); width = glConfig.vidWidth; height = glConfig.vidHeight; qglBegin(GL_QUADS); qglMultiTexCoord2iARB(GL_TEXTURE0_ARB, 0, 0); qglMultiTexCoord2iARB(GL_TEXTURE1_ARB, 0, 0); qglVertex2i(0, height); qglMultiTexCoord2iARB(GL_TEXTURE0_ARB, width, 0); qglMultiTexCoord2iARB(GL_TEXTURE1_ARB, tr.bloomWidth, 0); qglVertex2i(width, height); qglMultiTexCoord2iARB(GL_TEXTURE0_ARB, width, height); qglMultiTexCoord2iARB(GL_TEXTURE1_ARB, tr.bloomWidth, tr.bloomHeight); qglVertex2i(width, 0); qglMultiTexCoord2iARB(GL_TEXTURE0_ARB, 0, height); qglMultiTexCoord2iARB(GL_TEXTURE1_ARB, 0, tr.bloomHeight); qglVertex2i(0, 0); qglEnd(); qglUseProgramObjectARB(0); GL_SelectTexture(1); qglDisable(GL_TEXTURE_RECTANGLE_ARB); qglDisable(GL_TEXTURE_2D); GL_SelectTexture(0); qglDisable(GL_TEXTURE_RECTANGLE_ARB); qglEnable(GL_TEXTURE_2D); }
static bool RB_GLSL_InitShaders( ) { // load interation shaders R_LoadGLSLShader( "interaction.vertex", &interactionShader, GL_VERTEX_SHADER_ARB ); R_LoadGLSLShader( "interaction.fragment", &interactionShader, GL_FRAGMENT_SHADER_ARB ); if ( interactionShader.fragmentShader == -1 || interactionShader.vertexShader == -1 || !R_LinkGLSLShader( &interactionShader, true ) && !R_ValidateGLSLProgram( &interactionShader ) ) { if (interactionShader.fragmentShader != -1) qglDeleteShader(interactionShader.fragmentShader); if (interactionShader.vertexShader != -1) qglDeleteShader(interactionShader.vertexShader); interactionShader.fragmentShader = -1; interactionShader.vertexShader = -1; common->Printf( "GLSL interactionShader failed to init.\n" ); return false; } else { // set uniform locations interactionShader.u_normalTexture = qglGetUniformLocationARB( interactionShader.program, "u_normalTexture" ); interactionShader.u_lightFalloffTexture = qglGetUniformLocationARB( interactionShader.program, "u_lightFalloffTexture" ); interactionShader.u_lightProjectionTexture = qglGetUniformLocationARB( interactionShader.program, "u_lightProjectionTexture" ); interactionShader.u_diffuseTexture = qglGetUniformLocationARB( interactionShader.program, "u_diffuseTexture" ); interactionShader.u_specularTexture = qglGetUniformLocationARB( interactionShader.program, "u_specularTexture" ); interactionShader.modelMatrix = qglGetUniformLocationARB( interactionShader.program, "u_modelMatrix" ); interactionShader.localLightOrigin = qglGetUniformLocationARB( interactionShader.program, "u_lightOrigin" ); interactionShader.localViewOrigin = qglGetUniformLocationARB( interactionShader.program, "u_viewOrigin" ); interactionShader.lightProjectionS = qglGetUniformLocationARB( interactionShader.program, "u_lightProjectionS" ); interactionShader.lightProjectionT = qglGetUniformLocationARB( interactionShader.program, "u_lightProjectionT" ); interactionShader.lightProjectionQ = qglGetUniformLocationARB( interactionShader.program, "u_lightProjectionQ" ); interactionShader.lightFalloff = qglGetUniformLocationARB( interactionShader.program, "u_lightFalloff" ); interactionShader.bumpMatrixS = qglGetUniformLocationARB( interactionShader.program, "u_bumpMatrixS" ); interactionShader.bumpMatrixT = qglGetUniformLocationARB( interactionShader.program, "u_bumpMatrixT" ); interactionShader.diffuseMatrixS = qglGetUniformLocationARB( interactionShader.program, "u_diffuseMatrixS" ); interactionShader.diffuseMatrixT = qglGetUniformLocationARB( interactionShader.program, "u_diffuseMatrixT" ); interactionShader.specularMatrixS = qglGetUniformLocationARB( interactionShader.program, "u_specularMatrixS" ); interactionShader.specularMatrixT = qglGetUniformLocationARB( interactionShader.program, "u_specularMatrixT" ); interactionShader.colorModulate = qglGetUniformLocationARB( interactionShader.program, "u_colorModulate" ); interactionShader.colorAdd = qglGetUniformLocationARB( interactionShader.program, "u_colorAdd" ); interactionShader.diffuseColor = qglGetUniformLocationARB( interactionShader.program, "u_diffuseColor" ); interactionShader.specularColor = qglGetUniformLocationARB( interactionShader.program, "u_specularColor" ); // set texture locations qglUseProgramObjectARB( interactionShader.program ); qglUniform1iARB( interactionShader.u_normalTexture, 0 ); qglUniform1iARB( interactionShader.u_lightFalloffTexture, 1 ); qglUniform1iARB( interactionShader.u_lightProjectionTexture, 2 ); qglUniform1iARB( interactionShader.u_diffuseTexture, 3 ); qglUniform1iARB( interactionShader.u_specularTexture, 4 ); qglUseProgramObjectARB( 0 ); } // load ambient interation shaders R_LoadGLSLShader( "ambientInteraction.vertex", &ambientInteractionShader, GL_VERTEX_SHADER_ARB ); R_LoadGLSLShader( "ambientInteraction.fragment", &ambientInteractionShader, GL_FRAGMENT_SHADER_ARB ); if ( ambientInteractionShader.fragmentShader == -1 || ambientInteractionShader.vertexShader == -1 || !R_LinkGLSLShader( &ambientInteractionShader, true ) && !R_ValidateGLSLProgram( &ambientInteractionShader ) ) { if (ambientInteractionShader.fragmentShader != -1) qglDeleteShader(ambientInteractionShader.fragmentShader); if (ambientInteractionShader.vertexShader != -1) qglDeleteShader(ambientInteractionShader.vertexShader); ambientInteractionShader.fragmentShader = -1; ambientInteractionShader.vertexShader = -1; common->Printf( "GLSL ambientInteractionShader failed to init.\n" ); return false; } else { // set uniform locations ambientInteractionShader.u_normalTexture = qglGetUniformLocationARB( ambientInteractionShader.program, "u_normalTexture" ); ambientInteractionShader.u_lightFalloffTexture = qglGetUniformLocationARB( ambientInteractionShader.program, "u_lightFalloffTexture" ); ambientInteractionShader.u_lightProjectionTexture = qglGetUniformLocationARB( ambientInteractionShader.program, "u_lightProjectionTexture" ); ambientInteractionShader.u_diffuseTexture = qglGetUniformLocationARB( ambientInteractionShader.program, "u_diffuseTexture" ); ambientInteractionShader.modelMatrix = qglGetUniformLocationARB( ambientInteractionShader.program, "u_modelMatrix" ); ambientInteractionShader.localLightOrigin = qglGetUniformLocationARB( ambientInteractionShader.program, "u_lightOrigin" ); ambientInteractionShader.lightProjectionS = qglGetUniformLocationARB( ambientInteractionShader.program, "u_lightProjectionS" ); ambientInteractionShader.lightProjectionT = qglGetUniformLocationARB( ambientInteractionShader.program, "u_lightProjectionT" ); ambientInteractionShader.lightProjectionQ = qglGetUniformLocationARB( ambientInteractionShader.program, "u_lightProjectionQ" ); ambientInteractionShader.lightFalloff = qglGetUniformLocationARB( ambientInteractionShader.program, "u_lightFalloff" ); ambientInteractionShader.bumpMatrixS = qglGetUniformLocationARB( ambientInteractionShader.program, "u_bumpMatrixS" ); ambientInteractionShader.bumpMatrixT = qglGetUniformLocationARB( ambientInteractionShader.program, "u_bumpMatrixT" ); ambientInteractionShader.diffuseMatrixS = qglGetUniformLocationARB( ambientInteractionShader.program, "u_diffuseMatrixS" ); ambientInteractionShader.diffuseMatrixT = qglGetUniformLocationARB( ambientInteractionShader.program, "u_diffuseMatrixT" ); ambientInteractionShader.colorModulate = qglGetUniformLocationARB( ambientInteractionShader.program, "u_colorModulate" ); ambientInteractionShader.colorAdd = qglGetUniformLocationARB( ambientInteractionShader.program, "u_colorAdd" ); ambientInteractionShader.diffuseColor = qglGetUniformLocationARB( ambientInteractionShader.program, "u_diffuseColor" ); // set texture locations qglUseProgramObjectARB( ambientInteractionShader.program ); qglUniform1iARB( ambientInteractionShader.u_normalTexture, 0 ); qglUniform1iARB( ambientInteractionShader.u_lightFalloffTexture, 1 ); qglUniform1iARB( ambientInteractionShader.u_lightProjectionTexture, 2 ); qglUniform1iARB( ambientInteractionShader.u_diffuseTexture, 3 ); qglUseProgramObjectARB( 0 ); } // load stencil shadow extrusion shaders R_LoadGLSLShader( "stencilshadow.vertex", &stencilShadowShader, GL_VERTEX_SHADER_ARB ); R_LoadGLSLShader( "stencilshadow.fragment", &stencilShadowShader, GL_FRAGMENT_SHADER_ARB ); if ( stencilShadowShader.fragmentShader == -1 || stencilShadowShader.vertexShader == -1 || !R_LinkGLSLShader( &stencilShadowShader, false ) && !R_ValidateGLSLProgram( &stencilShadowShader ) ) { if (stencilShadowShader.fragmentShader != -1) qglDeleteShader(stencilShadowShader.fragmentShader); if (stencilShadowShader.vertexShader != -1) qglDeleteShader(stencilShadowShader.vertexShader); stencilShadowShader.fragmentShader = -1; stencilShadowShader.vertexShader = -1; common->Printf( "GLSL stencilShadowShader failed to init.\n" ); return false; } else { // set uniform locations stencilShadowShader.localLightOrigin = qglGetUniformLocationARB( stencilShadowShader.program, "u_lightOrigin" ); } return true; }
/* ============= 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 ); }
void R_Shader_FinishLightRendering() { glDisable( GL_BLEND ); qglUseProgramObjectARB( 0 ); }