2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
28 #include "../idlib/precompiled.h"
35 There are not enough vertex program texture coordinate outputs
36 to have unique texture coordinates for bump, specular, and diffuse,
37 so diffuse and specular are assumed to be the same mapping.
39 To handle properly, those cases with different diffuse and specular
40 mapping will need to be run as two passes.
44 // changed from 1 to 255 to not conflict with ARB2 program names
45 static int FPROG_FAST_PATH = 255;
48 GLint numFragmentRegisters; // 6
49 GLint numFragmentConstants; // 8
51 GLint numInstructionsPerPass; // 8
52 GLint numInstructionsTotal; // 16
53 GLint colorAlphaPairing; // 1
54 GLint numLoopbackComponenets; // 3
55 GLint numInputInterpolatorComponents; // 3
56 } atiFragmentShaderInfo_t;
58 static atiFragmentShaderInfo_t fsi;
61 // vertex shader invariants
62 int lightPos; // light position in object coordinates
63 int viewerPos; // viewer position in object coordinates
64 int lightProjectS; // projected light s texgen
65 int lightProjectT; // projected light t texgen
66 int lightProjectQ; // projected light q texgen
67 int lightFalloffS; // projected light falloff s texgen
68 int bumpTransformS; // bump TEX0 S transformation
69 int bumpTransformT; // bump TEX0 T transformation
70 int colorTransformS; // diffuse/specular texture matrix
71 int colorTransformT; // diffuse/specular texture matrix
73 // vertex shader variants
80 } atiVertexShaderInfo_t;
82 static atiVertexShaderInfo_t vsi;
86 RB_R200_ARB_DrawInteraction
90 static void RB_R200_ARB_DrawInteraction( const drawInteraction_t *din ) {
91 // check for the case we can't handle in a single pass (we could calculate this at shader parse time to optimize)
92 if ( din->diffuseImage != globalImages->blackImage && din->specularImage != globalImages->blackImage
93 && memcmp( din->specularMatrix, din->diffuseMatrix, sizeof( din->diffuseMatrix ) ) ) {
94 // common->Printf( "Note: Shader %s drawn as two pass on R200\n", din->surf->shader->getName() );
96 // draw the specular as a separate pass with a black diffuse map
99 d.diffuseImage = globalImages->blackImage;
100 memcpy( d.diffuseMatrix, d.specularMatrix, sizeof( d.diffuseMatrix ) );
101 RB_R200_ARB_DrawInteraction( &d );
103 // now fall through and draw the diffuse pass with a black specular map
106 d.specularImage = globalImages->blackImage;
109 // load all the vertex program parameters
110 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_ORIGIN, din->localLightOrigin.ToFloatPtr() );
111 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_VIEW_ORIGIN, din->localViewOrigin.ToFloatPtr() );
112 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_S, din->lightProjection[0].ToFloatPtr() );
113 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_T, din->lightProjection[1].ToFloatPtr() );
114 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_PROJECT_Q, din->lightProjection[2].ToFloatPtr() );
115 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_FALLOFF_S, din->lightProjection[3].ToFloatPtr() );
116 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_BUMP_MATRIX_S, din->bumpMatrix[0].ToFloatPtr() );
117 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_BUMP_MATRIX_T, din->bumpMatrix[1].ToFloatPtr() );
118 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_DIFFUSE_MATRIX_S, din->diffuseMatrix[0].ToFloatPtr() );
119 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_DIFFUSE_MATRIX_T, din->diffuseMatrix[1].ToFloatPtr() );
120 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_SPECULAR_MATRIX_S, din->diffuseMatrix[0].ToFloatPtr() );
121 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_SPECULAR_MATRIX_T, din->diffuseMatrix[1].ToFloatPtr() );
123 const srfTriangles_t *tri = din->surf->geo;
124 idDrawVert *ac = (idDrawVert *)vertexCache.Position( tri->ambientCache );
125 qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->xyz );
127 static const float zero[4] = { 0, 0, 0, 0 };
128 static const float one[4] = { 1, 1, 1, 1 };
129 static const float negOne[4] = { -1, -1, -1, -1 };
131 switch ( din->vertexColor ) {
133 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, zero );
134 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, one );
137 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, one );
138 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, zero );
140 case SVC_INVERSE_MODULATE:
141 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_MODULATE, negOne );
142 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_COLOR_ADD, one );
147 // texture 0 = light projection
148 // texture 1 = light falloff
149 // texture 2 = surface diffuse
150 // texture 3 = surface specular
151 // texture 4 = surface bump
152 // texture 5 = normalization cube map
154 GL_SelectTexture( 5 );
155 if ( din->ambientLight ) {
156 globalImages->ambientNormalMap->Bind();
158 globalImages->normalCubeMapImage->Bind();
161 GL_SelectTexture( 4 );
162 din->bumpImage->Bind();
164 GL_SelectTexture( 3 );
165 din->specularImage->Bind();
166 qglTexCoordPointer( 3, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->normal );
168 GL_SelectTexture( 2 );
169 din->diffuseImage->Bind();
170 qglTexCoordPointer( 3, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->tangents[1][0] );
172 GL_SelectTexture( 1 );
173 din->lightFalloffImage->Bind();
174 qglTexCoordPointer( 3, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->tangents[0][0] );
176 GL_SelectTexture( 0 );
177 din->lightImage->Bind();
178 qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->st[0] );
180 qglSetFragmentShaderConstantATI( GL_CON_0_ATI, din->diffuseColor.ToFloatPtr() );
181 qglSetFragmentShaderConstantATI( GL_CON_1_ATI, din->specularColor.ToFloatPtr() );
183 if ( din->vertexColor != SVC_IGNORE ) {
184 qglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(idDrawVert), (void *)&ac->color );
185 qglEnableClientState( GL_COLOR_ARRAY );
187 RB_DrawElementsWithCounters( tri );
189 qglDisableClientState( GL_COLOR_ARRAY );
190 qglColor4f( 1, 1, 1, 1 );
192 RB_DrawElementsWithCounters( tri );
198 RB_R200_ARB_CreateDrawInteractions
201 static void RB_R200_ARB_CreateDrawInteractions( const drawSurf_t *surf ) {
206 // force a space calculation for light vectors
207 backEnd.currentSpace = NULL;
209 // set the depth test
210 if ( surf->material->Coverage() == MC_TRANSLUCENT /* != C_PERFORATED */ ) {
211 GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_LESS );
213 // only draw on the alpha tested pixels that made it to the depth buffer
214 GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | GLS_DEPTHFUNC_EQUAL );
217 // start the vertex shader
218 qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_R200_INTERACTION );
219 qglEnable(GL_VERTEX_PROGRAM_ARB);
221 // start the fragment shader
222 qglBindFragmentShaderATI( FPROG_FAST_PATH );
223 #if defined( MACOS_X )
224 qglEnable( GL_TEXT_FRAGMENT_SHADER_ATI );
226 qglEnable( GL_FRAGMENT_SHADER_ATI );
229 qglColor4f( 1, 1, 1, 1 );
231 GL_SelectTexture( 1 );
232 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
233 GL_SelectTexture( 2 );
234 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
235 GL_SelectTexture( 3 );
236 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
238 for ( ; surf ; surf=surf->nextOnLight ) {
239 RB_CreateSingleDrawInteractions( surf, RB_R200_ARB_DrawInteraction );
242 GL_SelectTexture( 5 );
243 globalImages->BindNull();
245 GL_SelectTexture( 4 );
246 globalImages->BindNull();
248 GL_SelectTexture( 3 );
249 globalImages->BindNull();
250 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
252 GL_SelectTexture( 2 );
253 globalImages->BindNull();
254 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
256 GL_SelectTexture( 1 );
257 globalImages->BindNull();
258 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
260 GL_SelectTexture( 0 );
262 qglDisable( GL_VERTEX_PROGRAM_ARB );
263 #if defined( MACOS_X )
264 qglDisable( GL_TEXT_FRAGMENT_SHADER_ATI );
266 qglDisable( GL_FRAGMENT_SHADER_ATI );
274 RB_R200_DrawInteractions
278 void RB_R200_DrawInteractions( void ) {
279 qglEnable( GL_STENCIL_TEST );
281 for ( viewLight_t *vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
283 if ( vLight->lightShader->IsFogLight() ) {
286 if ( vLight->lightShader->IsBlendLight() ) {
290 backEnd.vLight = vLight;
292 RB_LogComment( "---------- RB_RenderViewLight 0x%p ----------\n", vLight );
294 // clear the stencil buffer if needed
295 if ( vLight->globalShadows || vLight->localShadows ) {
296 backEnd.currentScissor = vLight->scissorRect;
297 if ( r_useScissor.GetBool() ) {
298 qglScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1,
299 backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1,
300 backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1,
301 backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 );
303 qglClear( GL_STENCIL_BUFFER_BIT );
305 // no shadows, so no need to read or write the stencil buffer
306 // we might in theory want to use GL_ALWAYS instead of disabling
307 // completely, to satisfy the invarience rules
308 qglStencilFunc( GL_ALWAYS, 128, 255 );
311 if ( r_useShadowVertexProgram.GetBool() ) {
312 qglEnable( GL_VERTEX_PROGRAM_ARB );
313 qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_STENCIL_SHADOW );
314 RB_StencilShadowPass( vLight->globalShadows );
316 RB_R200_ARB_CreateDrawInteractions( vLight->localInteractions );
318 qglEnable( GL_VERTEX_PROGRAM_ARB );
319 qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_STENCIL_SHADOW );
320 RB_StencilShadowPass( vLight->localShadows );
322 RB_R200_ARB_CreateDrawInteractions( vLight->globalInteractions );
324 qglDisable( GL_VERTEX_PROGRAM_ARB ); // if there weren't any globalInteractions, it would have stayed on
326 RB_StencilShadowPass( vLight->globalShadows );
327 RB_R200_ARB_CreateDrawInteractions( vLight->localInteractions );
329 RB_StencilShadowPass( vLight->localShadows );
330 RB_R200_ARB_CreateDrawInteractions( vLight->globalInteractions );
333 if ( r_skipTranslucent.GetBool() ) {
337 // disable stencil testing for translucent interactions, because
338 // the shadow isn't calculated at their point, and the shadow
339 // behind them may be depth fighting with a back side, so there
340 // isn't any reasonable thing to do
341 qglStencilFunc( GL_ALWAYS, 128, 255 );
342 RB_R200_ARB_CreateDrawInteractions( vLight->translucentInteractions );
349 R_BuildSurfaceFragmentProgram
352 static void R_BuildSurfaceFragmentProgram( int programNum ) {
353 qglBindFragmentShaderATI( programNum );
355 qglBeginFragmentShaderATI();
357 // texture 0 = light projection
358 // texture 1 = light falloff
359 // texture 2 = surface diffuse
360 // texture 3 = surface specular
361 // texture 4 = surface bump
362 // texture 5 = normalization cube map
364 // texcoord 0 = light projection texGen
365 // texcoord 1 = light falloff texGen
366 // texcoord 2 = bumpmap texCoords
367 // texcoord 3 = specular / diffuse texCoords
368 // texcoord 4 = halfangle vector in local tangent space
369 // texcoord 5 = vector to light in local tangent space
371 // constant 0 = diffuse modulate
372 // constant 1 = specular modulate
373 // constant 5 = internal use for 0.75 constant
375 qglSampleMapATI( GL_REG_0_ATI, GL_TEXTURE0_ARB, GL_SWIZZLE_STQ_DQ_ATI );
376 qglSampleMapATI( GL_REG_1_ATI, GL_TEXTURE1_ARB, GL_SWIZZLE_STR_ATI );
377 qglSampleMapATI( GL_REG_4_ATI, GL_TEXTURE2_ARB, GL_SWIZZLE_STR_ATI );
378 qglSampleMapATI( GL_REG_5_ATI, GL_TEXTURE5_ARB, GL_SWIZZLE_STR_ATI );
380 // move the alpha component to the red channel to support rxgb normal map compression
381 if ( globalImages->image_useNormalCompression.GetInteger() == 2 ) {
382 qglColorFragmentOp1ATI( GL_MOV_ATI, GL_REG_4_ATI, GL_RED_BIT_ATI, GL_NONE,
383 GL_REG_4_ATI, GL_ALPHA, GL_NONE );
386 // light projection * light falloff
387 qglColorFragmentOp2ATI( GL_MUL_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
388 GL_REG_0_ATI, GL_NONE, GL_NONE,
389 GL_REG_1_ATI, GL_NONE, GL_NONE );
391 // vectorToLight dot bumpMap
392 qglColorFragmentOp2ATI( GL_DOT3_ATI, GL_REG_1_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
393 GL_REG_4_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
394 GL_REG_5_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI );
397 qglColorFragmentOp2ATI( GL_MUL_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
398 GL_REG_0_ATI, GL_NONE, GL_NONE,
399 GL_REG_1_ATI, GL_NONE, GL_NONE );
401 //-------------------
403 // carry over the incomingLight calculation
404 qglPassTexCoordATI( GL_REG_0_ATI, GL_REG_0_ATI, GL_SWIZZLE_STR_ATI );
406 // sample the diffuse surface map
407 qglSampleMapATI( GL_REG_2_ATI, GL_TEXTURE3_ARB, GL_SWIZZLE_STR_ATI );
409 // sample the specular surface map
410 qglSampleMapATI( GL_REG_3_ATI, GL_TEXTURE3_ARB, GL_SWIZZLE_STR_ATI );
412 // we will use the surface bump map again
413 qglPassTexCoordATI( GL_REG_4_ATI, GL_REG_4_ATI, GL_SWIZZLE_STR_ATI );
415 // normalize the specular halfangle
416 qglSampleMapATI( GL_REG_5_ATI, GL_TEXTURE4_ARB, GL_SWIZZLE_STR_ATI );
418 // R1 = halfangle dot surfaceNormal
419 qglColorFragmentOp2ATI( GL_DOT3_ATI, GL_REG_1_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
420 GL_REG_4_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
421 GL_REG_5_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI );
423 // R1 = 4 * ( R1 - 0.75 )
424 // subtract 0.75 and quadruple to tighten the specular spot
425 float data[4] = { 0.75, 0.75, 0.75, 0.75 };
426 qglSetFragmentShaderConstantATI( GL_CON_5_ATI, data );
427 qglColorFragmentOp2ATI( GL_SUB_ATI, GL_REG_1_ATI, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
428 GL_REG_1_ATI, GL_NONE, GL_NONE,
429 GL_CON_5_ATI, GL_NONE, GL_NONE );
432 // sqare the stretched specular result
433 qglColorFragmentOp2ATI( GL_MUL_ATI, GL_REG_1_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
434 GL_REG_1_ATI, GL_NONE, GL_NONE,
435 GL_REG_1_ATI, GL_NONE, GL_NONE );
438 // R1 = specular power * specular texture * 2
439 qglColorFragmentOp2ATI( GL_MUL_ATI, GL_REG_1_ATI, GL_NONE, GL_2X_BIT_ATI | GL_SATURATE_BIT_ATI,
440 GL_REG_1_ATI, GL_NONE, GL_NONE,
441 GL_REG_3_ATI, GL_NONE, GL_NONE );
444 // down modulate the diffuse map
445 qglColorFragmentOp2ATI( GL_MUL_ATI, GL_REG_2_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
446 GL_REG_2_ATI, GL_NONE, GL_NONE,
447 GL_CON_0_ATI, GL_NONE, GL_NONE );
449 // R2 = R2 + R1 * CONST1
450 // diffuse + specular * specular color
451 qglColorFragmentOp3ATI( GL_MAD_ATI, GL_REG_2_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
452 GL_REG_1_ATI, GL_NONE, GL_NONE,
453 GL_CON_1_ATI, GL_NONE, GL_NONE,
454 GL_REG_2_ATI, GL_NONE, GL_NONE );
456 // out = reflectance * incoming light
457 qglColorFragmentOp2ATI( GL_MUL_ATI, GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
458 GL_REG_0_ATI, GL_NONE, GL_NONE,
459 GL_REG_2_ATI, GL_NONE, GL_NONE );
461 // out * vertex color
462 qglColorFragmentOp2ATI( GL_MUL_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
463 GL_REG_0_ATI, GL_NONE, GL_NONE,
464 GL_PRIMARY_COLOR_ARB, GL_NONE, GL_NONE );
466 // out alpha = 0 to allow blending optimization
467 qglAlphaFragmentOp1ATI( GL_MOV_ATI, GL_REG_0_ATI, GL_NONE,
468 GL_ZERO, GL_NONE, GL_NONE );
470 qglEndFragmentShaderATI();
480 void R_R200_Init( void ) {
481 glConfig.allowR200Path = false;
483 common->Printf( "----------- R200_Init -----------\n" );
485 if ( !glConfig.atiFragmentShaderAvailable || !glConfig.ARBVertexProgramAvailable || !glConfig.ARBVertexBufferObjectAvailable ) {
486 common->Printf( "Not available.\n" );
492 qglGetIntegerv( GL_NUM_FRAGMENT_REGISTERS_ATI, &fsi.numFragmentRegisters );
493 qglGetIntegerv( GL_NUM_FRAGMENT_CONSTANTS_ATI, &fsi.numFragmentConstants );
494 qglGetIntegerv( GL_NUM_PASSES_ATI, &fsi.numPasses );
495 qglGetIntegerv( GL_NUM_INSTRUCTIONS_PER_PASS_ATI, &fsi.numInstructionsPerPass );
496 qglGetIntegerv( GL_NUM_INSTRUCTIONS_TOTAL_ATI, &fsi.numInstructionsTotal );
497 qglGetIntegerv( GL_COLOR_ALPHA_PAIRING_ATI, &fsi.colorAlphaPairing );
498 qglGetIntegerv( GL_NUM_LOOPBACK_COMPONENTS_ATI, &fsi.numLoopbackComponenets );
499 qglGetIntegerv( GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI, &fsi.numInputInterpolatorComponents );
501 common->Printf( "GL_NUM_FRAGMENT_REGISTERS_ATI: %i\n", fsi.numFragmentRegisters );
502 common->Printf( "GL_NUM_FRAGMENT_CONSTANTS_ATI: %i\n", fsi.numFragmentConstants );
503 common->Printf( "GL_NUM_PASSES_ATI: %i\n", fsi.numPasses );
504 common->Printf( "GL_NUM_INSTRUCTIONS_PER_PASS_ATI: %i\n", fsi.numInstructionsPerPass );
505 common->Printf( "GL_NUM_INSTRUCTIONS_TOTAL_ATI: %i\n", fsi.numInstructionsTotal );
506 common->Printf( "GL_COLOR_ALPHA_PAIRING_ATI: %i\n", fsi.colorAlphaPairing );
507 common->Printf( "GL_NUM_LOOPBACK_COMPONENTS_ATI: %i\n", fsi.numLoopbackComponenets );
508 common->Printf( "GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI: %i\n", fsi.numInputInterpolatorComponents );
510 common->Printf( "FPROG_FAST_PATH\n" );
511 R_BuildSurfaceFragmentProgram( FPROG_FAST_PATH );
513 common->Printf( "---------------------\n" );
515 glConfig.allowR200Path = true;