doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
draw_exp.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
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.
13 
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.
18 
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/>.
21 
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.
23 
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.
25 
26 ===========================================================================
27 */
28 
29 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 #include "tr_local.h"
33 #include "../sys/win32/win_local.h"
34 
35 /*
36 
37 strictly experimental / research codepaths
38 
39 !!!if we use front facing occluders, we can portal flow from light centers
40 
41 try depth_component_16 rendering
42 
43 do we care about portals from light perspective? back / front face issues.
44 
45 how do we do weapon depth hacks with shadow buffers?
46  distort their world space vertexes instead of offsetting their depth?
47 
48 jittering off the side of a projection will give wrong shadows
49 
50 really huge lights, like sunlight, are going to be problematic with fixed projections
51  we could tile the projections and let the auto-resize cut them down as necessary
52 
53 It sucks that depth buffers are non-linear, because the bias and compares change with distance
54 
55 polygon offset factor causes occasional texture holes from highly angled textures
56 
57 */
58 
59 static bool initialized;
60 
61 static int lightBufferSize = 1024;
62 static int maxLightBufferSize = 1024;
63 static float lightBufferSizeFraction = 0.5;
64 
65 static int viewBufferSize = 1024;
66 static int viewBufferHeight = 768;
67 static int maxViewBufferSize = 1024;
68 static float viewBufferSizeFraction = 0.5;
69 static float viewBufferHeightFraction = 0.5;
70 static bool nativeViewBuffer = false; // true if viewBufferSize is the viewport width
71 
72 static HPBUFFERARB floatPbuffer;
73 static HDC floatPbufferDC;
74 static idImage *floatPbufferImage;
75 
76 static HPBUFFERARB floatPbuffer2;
77 static HDC floatPbuffer2DC;
78 static idImage *floatPbuffer2Image;
79 
80 static HPBUFFERARB floatPbufferQuarter;
81 static HDC floatPbufferQuarterDC;
82 static idImage *floatPbufferQuarterImage;
83 
84 static HGLRC floatContext;
85 
86 static HPBUFFERARB shadowPbuffer;
87 static HDC shadowPbufferDC;
88 
89 static HPBUFFERARB viewPbuffer;
90 static HDC viewPbufferDC;
91 
92 static idImage *shadowImage[3];
93 
94 static idImage *viewDepthImage;
95 static idImage *viewAlphaImage;
96 
97 static idImage *viewShadowImage;
98 
99 static idImage *jitterImage16;
100 static idImage *jitterImage4;
101 static idImage *jitterImage1;
102 
103 static idImage *random256Image;
104 
105 static int shadowVertexProgram;
106 static int shadowFragmentProgram16;
107 static int shadowFragmentProgram4;
108 static int shadowFragmentProgram1;
109 static int shadowFragmentProgram0;
110 
111 static int screenSpaceShadowVertexProgram;
112 static int screenSpaceShadowFragmentProgram16;
113 static int screenSpaceShadowFragmentProgram4;
114 static int screenSpaceShadowFragmentProgram1;
115 static int screenSpaceShadowFragmentProgram0;
116 
117 static int depthMidpointVertexProgram;
118 static int depthMidpointFragmentProgram;
119 
120 static int shadowResampleVertexProgram;
121 static int shadowResampleFragmentProgram;
122 
123 static int gammaDitherVertexProgram;
124 static int gammaDitherFragmentProgram;
125 
126 static int downSampleVertexProgram;
127 static int downSampleFragmentProgram;
128 
129 static int bloomVertexProgram;
130 static int bloomFragmentProgram;
131 
132 static float viewLightAxialSize;
133 
134 idCVar r_sb_lightResolution( "r_sb_lightResolution", "1024", CVAR_RENDERER | CVAR_INTEGER, "Pixel dimensions for each shadow buffer, 64 - 2048" );
135 idCVar r_sb_viewResolution( "r_sb_viewResolution", "1024", CVAR_RENDERER | CVAR_INTEGER, "Width of screen space shadow sampling" );
136 idCVar r_sb_noShadows( "r_sb_noShadows", "0", CVAR_RENDERER | CVAR_BOOL, "don't draw any occluders" );
137 idCVar r_sb_usePbuffer( "r_sb_usePbuffer", "1", CVAR_RENDERER | CVAR_BOOL, "draw offscreen" );
138 idCVar r_sb_jitterScale( "r_sb_jitterScale", "0.006", CVAR_RENDERER | CVAR_FLOAT, "scale factor for jitter offset" );
139 idCVar r_sb_biasScale( "r_sb_biasScale", "0.0001", CVAR_RENDERER | CVAR_FLOAT, "scale factor for jitter bias" );
140 idCVar r_sb_samples( "r_sb_samples", "4", CVAR_RENDERER | CVAR_INTEGER, "0, 1, 4, or 16" );
141 idCVar r_sb_randomize( "r_sb_randomize", "1", CVAR_RENDERER | CVAR_BOOL, "randomly offset jitter texture each draw" );
142 // polyOfsFactor causes holes in low res images
143 idCVar r_sb_polyOfsFactor( "r_sb_polyOfsFactor", "2", CVAR_RENDERER | CVAR_FLOAT, "polygonOffset factor for drawing shadow buffer" );
144 idCVar r_sb_polyOfsUnits( "r_sb_polyOfsUnits", "3000", CVAR_RENDERER | CVAR_FLOAT, "polygonOffset units for drawing shadow buffer" );
145 idCVar r_sb_occluderFacing( "r_sb_occluderFacing", "0", CVAR_RENDERER | CVAR_INTEGER, "0 = front faces, 1 = back faces, 2 = midway between" );
146 // r_sb_randomizeBufferOrientation?
147 
148 idCVar r_sb_frustomFOV( "r_sb_frustomFOV", "92", CVAR_RENDERER | CVAR_FLOAT, "oversize FOV for point light side matching" );
149 idCVar r_sb_showFrustumPixels( "r_sb_showFrustumPixels", "0", CVAR_RENDERER | CVAR_BOOL, "color the pixels contained in the frustum" );
150 idCVar r_sb_singleSide( "r_sb_singleSide", "-1", CVAR_RENDERER | CVAR_INTEGER, "only draw a single side (0-5) of point lights" );
151 idCVar r_sb_useCulling( "r_sb_useCulling", "1", CVAR_RENDERER | CVAR_BOOL, "cull geometry to individual side frustums" );
152 idCVar r_sb_linearFilter( "r_sb_linearFilter", "1", CVAR_RENDERER | CVAR_BOOL, "use GL_LINEAR instead of GL_NEAREST on shadow maps" );
153 
154 idCVar r_sb_screenSpaceShadow( "r_sb_screenSpaceShadow", "1", CVAR_RENDERER | CVAR_BOOL, "build shadows in screen space instead of on surfaces" );
155 
156 idCVar r_hdr_useFloats( "r_hdr_useFloats", "0", CVAR_RENDERER | CVAR_BOOL, "use a floating point rendering buffer" );
157 idCVar r_hdr_exposure( "r_hdr_exposure", "1.0", CVAR_RENDERER | CVAR_FLOAT, "maximum light scale" );
158 idCVar r_hdr_bloomFraction( "r_hdr_bloomFraction", "0.1", CVAR_RENDERER | CVAR_FLOAT, "fraction to smear across neighbors" );
159 idCVar r_hdr_gamma( "r_hdr_gamma", "1", CVAR_RENDERER | CVAR_FLOAT, "monitor gamma power" );
160 idCVar r_hdr_monitorDither( "r_hdr_monitorDither", "0.01", CVAR_RENDERER | CVAR_FLOAT, "random dither in monitor space" );
161 
162 // from world space to light origin, looking down the X axis
163 static float unflippedLightMatrix[16];
164 
165 // from world space to OpenGL view space, looking down the negative Z axis
166 static float lightMatrix[16];
167 
168 // from OpenGL view space to OpenGL NDC ( -1 : 1 in XYZ )
169 static float lightProjectionMatrix[16];
170 
171 
172 void RB_ARB2_DrawInteraction( const drawInteraction_t *din );
173 
174 typedef struct {
175  const char *name;
176  int num;
177 } wglString_t;
178 
180 { "WGL_NUMBER_PIXEL_FORMATS_ARB", 0x2000 },
181 { "WGL_DRAW_TO_WINDOW_ARB", 0x2001 },
182 { "WGL_DRAW_TO_BITMAP_ARB", 0x2002 },
183 { "WGL_ACCELERATION_ARB", 0x2003 },
184 { "WGL_NEED_PALETTE_ARB", 0x2004 },
185 { "WGL_NEED_SYSTEM_PALETTE_ARB", 0x2005 },
186 { "WGL_SWAP_LAYER_BUFFERS_ARB", 0x2006 },
187 { "WGL_SWAP_METHOD_ARB", 0x2007 },
188 { "WGL_NUMBER_OVERLAYS_ARB", 0x2008 },
189 { "WGL_NUMBER_UNDERLAYS_ARB", 0x2009 },
190 { "WGL_TRANSPARENT_ARB", 0x200A },
191 { "WGL_TRANSPARENT_RED_VALUE_ARB", 0x2037 },
192 { "WGL_TRANSPARENT_GREEN_VALUE_ARB", 0x2038 },
193 { "WGL_TRANSPARENT_BLUE_VALUE_ARB", 0x2039 },
194 { "WGL_TRANSPARENT_ALPHA_VALUE_ARB", 0x203A },
195 { "WGL_TRANSPARENT_INDEX_VALUE_ARB", 0x203B },
196 { "WGL_SHARE_DEPTH_ARB", 0x200C },
197 { "WGL_SHARE_STENCIL_ARB", 0x200D },
198 { "WGL_SHARE_ACCUM_ARB", 0x200E },
199 { "WGL_SUPPORT_GDI_ARB", 0x200F },
200 { "WGL_SUPPORT_OPENGL_ARB", 0x2010 },
201 { "WGL_DOUBLE_BUFFER_ARB", 0x2011 },
202 { "WGL_STEREO_ARB", 0x2012 },
203 { "WGL_PIXEL_TYPE_ARB", 0x2013 },
204 { "WGL_COLOR_BITS_ARB", 0x2014 },
205 { "WGL_RED_BITS_ARB", 0x2015 },
206 { "WGL_RED_SHIFT_ARB", 0x2016 },
207 { "WGL_GREEN_BITS_ARB", 0x2017 },
208 { "WGL_GREEN_SHIFT_ARB", 0x2018 },
209 { "WGL_BLUE_BITS_ARB", 0x2019 },
210 { "WGL_BLUE_SHIFT_ARB", 0x201A },
211 { "WGL_ALPHA_BITS_ARB", 0x201B },
212 { "WGL_ALPHA_SHIFT_ARB", 0x201C },
213 { "WGL_ACCUM_BITS_ARB", 0x201D },
214 { "WGL_ACCUM_RED_BITS_ARB", 0x201E },
215 { "WGL_ACCUM_GREEN_BITS_ARB", 0x201F },
216 { "WGL_ACCUM_BLUE_BITS_ARB", 0x2020 },
217 { "WGL_ACCUM_ALPHA_BITS_ARB", 0x2021 },
218 { "WGL_DEPTH_BITS_ARB", 0x2022 },
219 { "WGL_STENCIL_BITS_ARB", 0x2023 },
220 { "WGL_AUX_BUFFERS_ARB", 0x2024 },
221 
222 { "WGL_NO_ACCELERATION_ARB", 0x2025 },
223 { "WGL_GENERIC_ACCELERATION_ARB", 0x2026 },
224 { "WGL_FULL_ACCELERATION_ARB", 0x2027 },
225 
226 { "WGL_SWAP_EXCHANGE_ARB", 0x2028 },
227 { "WGL_SWAP_COPY_ARB", 0x2029 },
228 { "WGL_SWAP_UNDEFINED_ARB", 0x202A },
229 
230 { "WGL_TYPE_RGBA_ARB", 0x202B },
231 { "WGL_TYPE_COLORINDEX_ARB", 0x202C },
232 };
233 
234 static const int NUM_WGL_STRINGS = sizeof( wglString ) / sizeof( wglString[0] );
235 
236 static void R_CheckWglErrors( void ) {
237  int err = GetLastError();
238  char *name;
239 
240 #if 0
241  LPVOID lpMsgBuf;
242  FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
243  NULL,
244  err,
245  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
246  (LPTSTR) &lpMsgBuf,
247  0,
248  NULL
249  );
250 #endif
251  err &= 0xffff;
252  switch ( err ) {
253  case 13: name = "ERROR_INVALID_DATA"; break;
254  case 6: name = "ERROR_INVALID_HANDLE"; break;
255  case 4317: name = "ERROR_INVALID_OPERATION"; break;
256  default: name = va( "code %i", err ); break;
257  }
258 
259  common->Printf( "GetLastError: %s\n", name );
260 }
261 
262 static void R_MakeCurrent( HDC dc, HGLRC context, HPBUFFERARB pbuffer ) {
263  if ( pbuffer ) {
264  if ( !wglReleaseTexImageARB( pbuffer, WGL_FRONT_LEFT_ARB ) ) {
265  R_CheckWglErrors();
266  common->Error( "wglReleaseTexImageARB failed" );
267  }
268  }
269  if ( !qwglMakeCurrent( dc, context ) ) {
270  R_CheckWglErrors();
271  common->FatalError( "qwglMakeCurrent failed" );
272  }
273 }
274 
275 static void R_BindTexImage( HPBUFFERARB pbuffer ) {
276  if ( !wglReleaseTexImageARB( pbuffer, WGL_FRONT_LEFT_ARB ) ) {
277  R_CheckWglErrors();
278  common->Error( "wglReleaseTexImageARB failed" );
279  }
280  if ( !wglBindTexImageARB( pbuffer, WGL_FRONT_LEFT_ARB ) ) {
281  R_CheckWglErrors();
282  common->Error( "failed wglBindTexImageARB" );
283  }
284 }
285 
286 static void R_ReportTextureParms( void ) {
287  int parms[8];
288 
289 // q glGetTexParameteriv( GL_TEXTURE_RECTANGLE_NV,
291 
292 }
293 
294 /*
295 ====================
296 RB_CreateBloomTable
297 ====================
298 */
299 static const int BLOOM_RADIUS = 8;
300 static void RB_CreateBloomTable( void ) {
301  float bloom[BLOOM_RADIUS];
302  float total = 0;
303 
304  // gaussian
305  float stdDev = 2.0;
306  for ( int i = 0 ; i < BLOOM_RADIUS ; i++ ) {
307  float f = (float)i / stdDev;
308  bloom[i] = exp( -0.5 * f * f );
309  total += bloom[i];
310  }
311 
312  total = ( total - bloom[0] ) * 2 + bloom[0];
313 
314  // normalize to 1.0 contribution, so a full row or column will equal 1.0
315  for ( int i = 0 ; i < BLOOM_RADIUS ; i++ ) {
316  bloom[i] *= 1.0 / total;
317  common->Printf( "PARAM bloom%i = { %f };\n", i, bloom[i] );
318  }
319 
320 }
321 
322 /*
323 ====================
324 GL_SelectTextureNoClient
325 ====================
326 */
327 static void GL_SelectTextureNoClient( int unit ) {
328  backEnd.glState.currenttmu = unit;
329  qglActiveTextureARB( GL_TEXTURE0_ARB + unit );
330  RB_LogComment( "glActiveTextureARB( %i )\n", unit );
331 }
332 
333 
334 /*
335 ================
336 R_CreateShadowBufferImage
337 
338 ================
339 */
340 static void R_CreateShadowBufferImage( idImage *image ) {
341  byte *data = (byte *)Mem_Alloc( lightBufferSize*lightBufferSize );
342 
343  memset( data, 0, lightBufferSize*lightBufferSize );
344 
345  image->GenerateImage( (byte *)data, 4, 4,
347 
348  // now reset it to a shadow depth image
349  GL_CheckErrors();
350  image->uploadWidth = image->uploadHeight = lightBufferSize;
351  qglTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, lightBufferSize, lightBufferSize,
352  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, data );
353 
355 // qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE );
356  qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL );
357 
358  // explicit zero depth border
359  float color[4];
360  color[0] = color[1] = color[2] = color[3] = 0;
361  qglTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color );
362 
363  GL_CheckErrors();
364 
365  Mem_Free( data );
366 }
367 
368 static void R_CreateViewAlphaImage( idImage *image ) {
369  int c = viewBufferSize*viewBufferSize*4;
370  byte *data = (byte *)Mem_Alloc( c );
371 
372  // don't let it pick an intensity format
373  for ( int i = 0 ; i < c ; i++ ) {
374  data[i] = i;
375  }
376  memset( data, 0, viewBufferSize*viewBufferSize );
377 
378  image->GenerateImage( (byte *)data, viewBufferSize, viewBufferSize,
380 }
381 
382 static void R_CreateStubImage( idImage *image ) {
383  float data[3][4][4];
384 
385  // generate the texture number
386  qglGenTextures( 1, &image->texnum );
388  memset( data, 0, sizeof( data ) );
389  glTexImage2D( GL_TEXTURE_RECTANGLE_NV, 0, GL_FLOAT_RGBA16_NV, 4, 3, 0, GL_RGBA, GL_FLOAT, &data );
390 }
391 
392 /*
393 ================
394 R_CreateJitterImage
395 
396 ================
397 */
398 const static int JITTER_SIZE = 128;
399 static void R_CreateJitterImage16( idImage *image ) {
400  byte data[JITTER_SIZE][JITTER_SIZE*16][4];
401 
402  for ( int i = 0 ; i < JITTER_SIZE ; i++ ) {
403  for ( int s = 0 ; s < 16 ; s++ ) {
404  int sOfs = 64 * ( s & 3 );
405  int tOfs = 64 * ( ( s >> 2 ) & 3 );
406 
407  for ( int j = 0 ; j < JITTER_SIZE ; j++ ) {
408  data[i][s*JITTER_SIZE+j][0] = (rand() & 63 ) | sOfs;
409  data[i][s*JITTER_SIZE+j][1] = (rand() & 63 ) | tOfs;
410  data[i][s*JITTER_SIZE+j][2] = rand();
411  data[i][s*JITTER_SIZE+j][3] = 0;
412  }
413  }
414  }
415 
416  image->GenerateImage( (byte *)data, JITTER_SIZE*16, JITTER_SIZE,
418 }
419 
420 static void R_CreateJitterImage4( idImage *image ) {
421  byte data[JITTER_SIZE][JITTER_SIZE*4][4];
422 
423  for ( int i = 0 ; i < JITTER_SIZE ; i++ ) {
424  for ( int s = 0 ; s < 4 ; s++ ) {
425  int sOfs = 128 * ( s & 1 );
426  int tOfs = 128 * ( ( s >> 1 ) & 1 );
427 
428  for ( int j = 0 ; j < JITTER_SIZE ; j++ ) {
429  data[i][s*JITTER_SIZE+j][0] = (rand() & 127 ) | sOfs;
430  data[i][s*JITTER_SIZE+j][1] = (rand() & 127 ) | tOfs;
431  data[i][s*JITTER_SIZE+j][2] = rand();
432  data[i][s*JITTER_SIZE+j][3] = 0;
433  }
434  }
435  }
436 
437  image->GenerateImage( (byte *)data, JITTER_SIZE*4, JITTER_SIZE,
439 }
440 
441 static void R_CreateJitterImage1( idImage *image ) {
442  byte data[JITTER_SIZE][JITTER_SIZE][4];
443 
444  for ( int i = 0 ; i < JITTER_SIZE ; i++ ) {
445  for ( int j = 0 ; j < JITTER_SIZE ; j++ ) {
446  data[i][j][0] = rand();
447  data[i][j][1] = rand();
448  data[i][j][2] = rand();
449  data[i][j][3] = 0;
450  }
451  }
452 
453  image->GenerateImage( (byte *)data, JITTER_SIZE, JITTER_SIZE,
455 }
456 
457 static void R_CreateRandom256Image( idImage *image ) {
458  byte data[256][256][4];
459 
460  for ( int i = 0 ; i < 256 ; i++ ) {
461  for ( int j = 0 ; j < 256 ; j++ ) {
462  data[i][j][0] = rand();
463  data[i][j][1] = rand();
464  data[i][j][2] = rand();
465  data[i][j][3] = rand();
466  }
467  }
468 
469  image->GenerateImage( (byte *)data, 256, 256,
471 }
472 
473 
474 /*
475 ==================
476 R_PrintPixelFormat
477 ==================
478 */
479 void R_PrintPixelFormat( int pixelFormat ) {
480  int res;
481  int iAttribute;
482  int iValue;
483 
484  common->Printf( "----- pixelFormat %i -----\n", pixelFormat );
485 
486  for ( int i = 1 ; i < NUM_WGL_STRINGS ; i++ ) {
487  iAttribute = wglString[i].num;
488  res = wglGetPixelFormatAttribivARB( win32.hDC, pixelFormat, 0, 1, &iAttribute, &iValue );
489  if ( res && iValue ) {
490  common->Printf( "%s : %i\n", wglString[i].name, iValue );
491  }
492  }
493 }
494 
495 
496 /*
497 ==================
498 R_Exp_Allocate
499 ==================
500 */
501 void R_Exp_Allocate( void ) {
502  // find a pixel format for our floating point pbuffer
503  int iAttributes[NUM_WGL_STRINGS*2], *atr_p;
504  FLOAT fAttributes[] = {0, 0};
505  UINT numFormats;
506  int pixelformats[1024];
507  int ret;
508  int pbiAttributes[] = {0, 0};
509 
510  initialized = true;
511 
512 #if 1
513  //
514  // allocate the floating point rendering buffer
515  //
516  atr_p = iAttributes;
517 
518  *atr_p++ = WGL_DRAW_TO_PBUFFER_ARB;
519  *atr_p++ = TRUE;
520  *atr_p++ = WGL_FLOAT_COMPONENTS_NV;
521  *atr_p++ = TRUE;
523  *atr_p++ = TRUE;
524 // *atr_p++ = WGL_BIND_TO_TEXTURE_RGBA_ARB;
525 // *atr_p++ = TRUE;
526  *atr_p++ = WGL_DEPTH_BITS_ARB;
527  *atr_p++ = 24;
528  *atr_p++ = WGL_STENCIL_BITS_ARB;
529  *atr_p++ = 8;
530  *atr_p++ = 0;
531  *atr_p++ = 0;
532 
533  ret = wglChoosePixelFormatARB( win32.hDC, iAttributes, fAttributes,
534  sizeof( pixelformats ) / sizeof( pixelformats[0] ), pixelformats, &numFormats );
535 
536 #if 0
537  for ( int i = 0 ; i < (int)numFormats ; i++ ) {
538  R_PrintPixelFormat( pixelformats[i] );
539  }
540 #endif
541  common->Printf( "\nfloatPbuffer:\n" );
542  R_PrintPixelFormat( pixelformats[0] );
543 
544  // allocate a pbuffer with this pixel format
545  int pbiAttributesTexture[] = {
547  WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_RECTANGLE_NV, // WGL_TEXTURE_2D_ARB,
548  0, 0};
549 
550  floatPbuffer = wglCreatePbufferARB( win32.hDC, pixelformats[0], glConfig.vidWidth,
551  glConfig.vidHeight, pbiAttributesTexture );
552  if ( !floatPbuffer ) {
553  common->Printf( "failed to create floatPbuffer.\n" );
554  GL_CheckErrors();
555  }
556  floatPbufferDC = wglGetPbufferDCARB( floatPbuffer );
557  floatPbufferImage = globalImages->ImageFromFunction( "_floatPbuffer", R_CreateStubImage );
558 
559  // create a second buffer for ping-pong operations
560  floatPbuffer2 = wglCreatePbufferARB( win32.hDC, pixelformats[0], glConfig.vidWidth,
561  glConfig.vidHeight, pbiAttributesTexture );
562  if ( !floatPbuffer2 ) {
563  common->Printf( "failed to create floatPbuffer.\n" );
564  GL_CheckErrors();
565  }
566  floatPbuffer2DC = wglGetPbufferDCARB( floatPbuffer2 );
567  floatPbuffer2Image = globalImages->ImageFromFunction( "_floatPbuffer2", R_CreateStubImage );
568 
569  // create a third buffer for down sampling operations
570  floatPbufferQuarter = wglCreatePbufferARB( win32.hDC, pixelformats[0], glConfig.vidWidth / 4,
571  glConfig.vidHeight / 4, pbiAttributesTexture );
572  if ( !floatPbufferQuarter ) {
573  common->Printf( "failed to create floatPbuffer.\n" );
574  GL_CheckErrors();
575  }
576  floatPbufferQuarterDC = wglGetPbufferDCARB( floatPbufferQuarter );
577  floatPbufferQuarterImage = globalImages->ImageFromFunction( "floatPbufferQuarter", R_CreateStubImage );
578 
579  // create a new GL context for this pixel format and share textures
580  floatContext = wglCreateContext( floatPbufferDC );
581  if ( !floatContext ) {
582  common->Printf( "failed to create context for floatPbufferDC.\n" );
583  GL_CheckErrors();
584  }
585 
586  if ( !wglShareLists( floatContext, win32.hGLRC ) ) {
587  common->Printf( "failed to share lists.\n" );
588  }
589 
590  // create a rendering context for this pixel format and share textures
591 
592  // allocate a texture for the rendering
593 
594 #endif
595 
596  //=================================================================================
597 
598  //
599  // allocate the shadow pbuffer
600  //
601  atr_p = iAttributes;
602 
603  *atr_p++ = WGL_DRAW_TO_PBUFFER_ARB;
604  *atr_p++ = TRUE;
605  *atr_p++ = WGL_RED_BITS_ARB;
606  *atr_p++ = 8;
607  *atr_p++ = WGL_GREEN_BITS_ARB;
608  *atr_p++ = 8;
609  *atr_p++ = WGL_BLUE_BITS_ARB;
610  *atr_p++ = 8;
611  *atr_p++ = WGL_ALPHA_BITS_ARB;
612  *atr_p++ = 8;
613  *atr_p++ = WGL_DEPTH_BITS_ARB;
614  *atr_p++ = 24;
615  *atr_p++ = WGL_STENCIL_BITS_ARB;
616  *atr_p++ = 8;
617  *atr_p++ = 0;
618  *atr_p++ = 0;
619 
620  ret = wglChoosePixelFormatARB( win32.hDC, iAttributes, fAttributes,
621  sizeof( pixelformats ) / sizeof( pixelformats[0] ), pixelformats, &numFormats );
622 #if 0
623  for ( int i = 0 ; i < (int)numFormats ; i++ ) {
624  R_PrintPixelFormat( pixelformats[i] );
625  }
626 #endif
627  common->Printf( "\nshadowPbuffer:\n" );
628  R_PrintPixelFormat( pixelformats[0] );
629 
630 pixelformats[0] = win32.pixelformat; // forced to do this by wgl...
631 
632  //-----------------------------------
633 
634  lightBufferSize = maxLightBufferSize;
635 
636  // allocate a pbuffer with this pixel format
637  shadowPbuffer = wglCreatePbufferARB( win32.hDC, pixelformats[0], lightBufferSize,
638  lightBufferSize, pbiAttributes );
639 
640  // allocate a rendering context for the pbuffer
641  shadowPbufferDC = wglGetPbufferDCARB( shadowPbuffer );
642 
643  // generate the texture number
644  shadowImage[0] = globalImages->ImageFromFunction( va("_shadowBuffer%i_0",lightBufferSize), R_CreateShadowBufferImage );
645  shadowImage[1] = globalImages->ImageFromFunction( va("_shadowBuffer%i_1",lightBufferSize), R_CreateShadowBufferImage );
646  shadowImage[2] = globalImages->ImageFromFunction( va("_shadowBuffer%i_2",lightBufferSize), R_CreateShadowBufferImage );
647 
648  //-----------------------------------
649 
650  lightBufferSize = maxViewBufferSize;
651 
652  // allocate a pbuffer with this pixel format
653  viewPbuffer = wglCreatePbufferARB( win32.hDC, pixelformats[0], maxViewBufferSize,
654  maxViewBufferSize, pbiAttributes );
655 
656  // allocate a rendering context for the pbuffer
657  viewPbufferDC = wglGetPbufferDCARB( viewPbuffer );
658 
659  // create the image space depth buffer for image-space shadow trnasforms
660  viewDepthImage = globalImages->ImageFromFunction("_viewDepth", R_CreateShadowBufferImage );
661 
662  // create the image space shadow alpha buffer for subsampling the shadow calculation
663  viewAlphaImage = globalImages->ImageFromFunction("_viewAlpha", R_CreateViewAlphaImage );
664 
665  //-----------------------------------
666 
667  // generate the jitter image
668  jitterImage16 = globalImages->ImageFromFunction( "_jitter16", R_CreateJitterImage16 );
669  jitterImage4 = globalImages->ImageFromFunction( "_jitter4", R_CreateJitterImage4 );
670  jitterImage1 = globalImages->ImageFromFunction( "_jitter1", R_CreateJitterImage1 );
671 
672  depthMidpointVertexProgram = R_FindARBProgram( GL_VERTEX_PROGRAM_ARB, "depthMidpoint.vfp" );
673  depthMidpointFragmentProgram = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, "depthMidpoint.vfp" );
674 
675  shadowResampleVertexProgram = R_FindARBProgram( GL_VERTEX_PROGRAM_ARB, "shadowResample.vfp" );
676  shadowResampleFragmentProgram = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, "shadowResample.vfp" );
677 
678  screenSpaceShadowVertexProgram = R_FindARBProgram( GL_VERTEX_PROGRAM_ARB, "screenSpaceShadow1.vfp" );
679 
680  screenSpaceShadowFragmentProgram0 = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, "screenSpaceShadow0.vfp" );
681  screenSpaceShadowFragmentProgram1 = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, "screenSpaceShadow1.vfp" );
682  screenSpaceShadowFragmentProgram4 = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, "screenSpaceShadow4.vfp" );
683  screenSpaceShadowFragmentProgram16 = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, "screenSpaceShadow16.vfp" );
684 
685  shadowVertexProgram = R_FindARBProgram( GL_VERTEX_PROGRAM_ARB, "shadowBufferInteraction1.vfp" );
686 
687  shadowFragmentProgram0 = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, "shadowBufferInteraction0.vfp" );
688  shadowFragmentProgram1 = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, "shadowBufferInteraction1.vfp" );
689  shadowFragmentProgram4 = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, "shadowBufferInteraction4.vfp" );
690  shadowFragmentProgram16 = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, "shadowBufferInteraction16.vfp" );
691 
692  gammaDitherVertexProgram = R_FindARBProgram( GL_VERTEX_PROGRAM_ARB, "gammaDither.vfp" );
693  gammaDitherFragmentProgram = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, "gammaDither.vfp" );
694 
695  downSampleVertexProgram = R_FindARBProgram( GL_VERTEX_PROGRAM_ARB, "downSample.vfp" );
696  downSampleFragmentProgram = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, "downSample.vfp" );
697 
698  bloomVertexProgram = R_FindARBProgram( GL_VERTEX_PROGRAM_ARB, "bloom.vfp" );
699  bloomFragmentProgram = R_FindARBProgram( GL_FRAGMENT_PROGRAM_ARB, "bloom.vfp" );
700 
701  random256Image = globalImages->ImageFromFunction( "_random256", R_CreateRandom256Image );
702 }
703 
704 //===========================================================================================
705 
706 static const int CULL_RECEIVER = 1; // still draw occluder, but it is out of the view
707 static const int CULL_OCCLUDER_AND_RECEIVER = 2; // the surface doesn't effect the view at all
708 
709 /*
710 ==================
711 RB_EXP_CullInteractions
712 
713 Sets surfaceInteraction_t->cullBits
714 ==================
715 */
716 void RB_EXP_CullInteractions( viewLight_t *vLight, idPlane frustumPlanes[6] ) {
717  for ( idInteraction *inter = vLight->lightDef->firstInteraction ; inter ; inter = inter->lightNext ) {
718  const idRenderEntityLocal *entityDef = inter->entityDef;
719  if ( !entityDef ) {
720  continue;
721  }
722  if ( inter->numSurfaces < 1 ) {
723  continue;
724  }
725 
726  int culled = 0;
727 
728  if ( r_sb_useCulling.GetBool() ) {
729  // transform light frustum into object space, positive side points outside the light
730  idPlane localPlanes[6];
731  int plane;
732  for ( plane = 0 ; plane < 6 ; plane++ ) {
733  R_GlobalPlaneToLocal( entityDef->modelMatrix, frustumPlanes[plane], localPlanes[plane] );
734  }
735 
736  // cull the entire entity bounding box
737  // has referenceBounds been tightened to the actual model bounds?
738  idVec3 corners[8];
739  for ( int i = 0 ; i < 8 ; i++ ) {
740  corners[i][0] = entityDef->referenceBounds[i&1][0];
741  corners[i][1] = entityDef->referenceBounds[(i>>1)&1][1];
742  corners[i][2] = entityDef->referenceBounds[(i>>2)&1][2];
743  }
744 
745  for ( plane = 0 ; plane < 6 ; plane++ ) {
746  int j;
747  for ( j = 0 ; j < 8 ; j++ ) {
748  // if a corner is on the negative side (inside) of the frustum, the surface is not culled
749  // by this plane
750  if ( corners[j] * localPlanes[plane].ToVec4().ToVec3() + localPlanes[plane][3] < 0 ) {
751  break;
752  }
753  }
754  if ( j == 8 ) {
755  break; // all points outside the light
756  }
757  }
758  if ( plane < 6 ) {
759  culled = CULL_OCCLUDER_AND_RECEIVER;
760  }
761  }
762 
763  for ( int i = 0 ; i < inter->numSurfaces ; i++ ) {
764  surfaceInteraction_t *surfInt = &inter->surfaces[i];
765 
766  if ( !surfInt->ambientTris ) {
767  continue;
768  }
769  surfInt->expCulled = culled;
770  }
771 
772  }
773 }
774 
775 /*
776 ==================
777 RB_EXP_RenderOccluders
778 ==================
779 */
781  for ( idInteraction *inter = vLight->lightDef->firstInteraction ; inter ; inter = inter->lightNext ) {
782  const idRenderEntityLocal *entityDef = inter->entityDef;
783  if ( !entityDef ) {
784  continue;
785  }
786  if ( inter->numSurfaces < 1 ) {
787  continue;
788  }
789 
790  // no need to check for current on this, because each interaction is always
791  // a different space
792  float matrix[16];
793  myGlMultMatrix( inter->entityDef->modelMatrix, lightMatrix, matrix );
794  qglLoadMatrixf( matrix );
795 
796  // draw each surface
797  for ( int i = 0 ; i < inter->numSurfaces ; i++ ) {
798  surfaceInteraction_t *surfInt = &inter->surfaces[i];
799 
800  if ( !surfInt->ambientTris ) {
801  continue;
802  }
803  if ( surfInt->shader && !surfInt->shader->SurfaceCastsShadow() ) {
804  continue;
805  }
806 
807  // cull it
808  if ( surfInt->expCulled == CULL_OCCLUDER_AND_RECEIVER ) {
809  continue;
810  }
811 
812  // render it
813  const srfTriangles_t *tri = surfInt->ambientTris;
814  if ( !tri->ambientCache ) {
815  R_CreateAmbientCache( const_cast<srfTriangles_t *>(tri), false );
816  }
818  qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() );
819  qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), ac->st.ToFloatPtr() );
820  if ( surfInt->shader ) {
821  surfInt->shader->GetEditorImage()->Bind();
822  }
824  }
825  }
826 }
827 
828 /*
829 ==================
830 RB_RenderShadowBuffer
831 ==================
832 */
833 void RB_RenderShadowBuffer( viewLight_t *vLight, int side ) {
834  float xmin, xmax, ymin, ymax;
835  float width, height;
836  float zNear;
837 
838  float fov = r_sb_frustomFOV.GetFloat();
839 
840  //
841  // set up 90 degree projection matrix
842  //
843  zNear = 4;
844 
845  ymax = zNear * tan( fov * idMath::PI / 360.0f );
846  ymin = -ymax;
847 
848  xmax = zNear * tan( fov * idMath::PI / 360.0f );
849  xmin = -xmax;
850 
851  width = xmax - xmin;
852  height = ymax - ymin;
853 
854  lightProjectionMatrix[0] = 2 * zNear / width;
855  lightProjectionMatrix[4] = 0;
856  lightProjectionMatrix[8] = 0;
857  lightProjectionMatrix[12] = 0;
858 
859  lightProjectionMatrix[1] = 0;
860  lightProjectionMatrix[5] = 2 * zNear / height;
861  lightProjectionMatrix[9] = 0;
862  lightProjectionMatrix[13] = 0;
863 
864  // this is the far-plane-at-infinity formulation, and
865  // crunches the Z range slightly so w=0 vertexes do not
866  // rasterize right at the wraparound point
867  lightProjectionMatrix[2] = 0;
868  lightProjectionMatrix[6] = 0;
869  lightProjectionMatrix[10] = -0.999f;
870  lightProjectionMatrix[14] = -2.0f * zNear;
871 
872  lightProjectionMatrix[3] = 0;
873  lightProjectionMatrix[7] = 0;
874  lightProjectionMatrix[11] = -1;
875  lightProjectionMatrix[15] = 0;
876 
877 
878  if ( r_sb_usePbuffer.GetBool() ) {
879  // set the current openGL drawable to the shadow buffer
880  R_MakeCurrent( shadowPbufferDC, win32.hGLRC, NULL /* !@# shadowPbuffer */ );
881  }
882 
883  qglMatrixMode( GL_PROJECTION );
884  qglLoadMatrixf( lightProjectionMatrix );
885  qglMatrixMode( GL_MODELVIEW );
886 
887  qglViewport( 0, 0, lightBufferSize, lightBufferSize );
888  qglScissor( 0, 0, lightBufferSize, lightBufferSize );
889  qglStencilFunc( GL_ALWAYS, 0, 255 );
890 
891 qglClearColor( 0, 1, 0, 0 );
892 GL_State( GLS_DEPTHFUNC_LESS | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); // make sure depth mask is off before clear
893 qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
894 
895 // draw all the occluders
896 qglColor3f( 1, 1, 1 );
897 GL_SelectTexture( 0 );
898 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
899 
901 
902  static float s_flipMatrix[16] = {
903  // convert from our coordinate system (looking down X)
904  // to OpenGL's coordinate system (looking down -Z)
905  0, 0, -1, 0,
906  -1, 0, 0, 0,
907  0, 1, 0, 0,
908  0, 0, 0, 1
909  };
910 
911  float viewMatrix[16];
912 
913  idVec3 vec;
914  idVec3 origin = vLight->lightDef->globalLightOrigin;
915 
916  if ( side == -1 ) {
917  // projected light
918  vec = vLight->lightDef->parms.target;
919  vec.Normalize();
920  viewMatrix[0] = vec[0];
921  viewMatrix[4] = vec[1];
922  viewMatrix[8] = vec[2];
923 
924  vec = vLight->lightDef->parms.right;
925  vec.Normalize();
926  viewMatrix[1] = -vec[0];
927  viewMatrix[5] = -vec[1];
928  viewMatrix[9] = -vec[2];
929 
930  vec = vLight->lightDef->parms.up;
931  vec.Normalize();
932  viewMatrix[2] = vec[0];
933  viewMatrix[6] = vec[1];
934  viewMatrix[10] = vec[2];
935  } else {
936  // side of a point light
937  memset( viewMatrix, 0, sizeof( viewMatrix ) );
938  switch ( side ) {
939  case 0:
940  viewMatrix[0] = 1;
941  viewMatrix[9] = 1;
942  viewMatrix[6] = -1;
943  break;
944  case 1:
945  viewMatrix[0] = -1;
946  viewMatrix[9] = -1;
947  viewMatrix[6] = -1;
948  break;
949  case 2:
950  viewMatrix[4] = 1;
951  viewMatrix[1] = -1;
952  viewMatrix[10] = 1;
953  break;
954  case 3:
955  viewMatrix[4] = -1;
956  viewMatrix[1] = -1;
957  viewMatrix[10] = -1;
958  break;
959  case 4:
960  viewMatrix[8] = 1;
961  viewMatrix[1] = -1;
962  viewMatrix[6] = -1;
963  break;
964  case 5:
965  viewMatrix[8] = -1;
966  viewMatrix[1] = 1;
967  viewMatrix[6] = -1;
968  break;
969  }
970  }
971 
972  viewMatrix[12] = -origin[0] * viewMatrix[0] + -origin[1] * viewMatrix[4] + -origin[2] * viewMatrix[8];
973  viewMatrix[13] = -origin[0] * viewMatrix[1] + -origin[1] * viewMatrix[5] + -origin[2] * viewMatrix[9];
974  viewMatrix[14] = -origin[0] * viewMatrix[2] + -origin[1] * viewMatrix[6] + -origin[2] * viewMatrix[10];
975 
976  viewMatrix[3] = 0;
977  viewMatrix[7] = 0;
978  viewMatrix[11] = 0;
979  viewMatrix[15] = 1;
980 
981  memcpy( unflippedLightMatrix, viewMatrix, sizeof( unflippedLightMatrix ) );
982  myGlMultMatrix( viewMatrix, s_flipMatrix,lightMatrix);
983 
984  // create frustum planes
985  idPlane globalFrustum[6];
986 
987  // near clip
988  globalFrustum[0][0] = -viewMatrix[0];
989  globalFrustum[0][1] = -viewMatrix[4];
990  globalFrustum[0][2] = -viewMatrix[8];
991  globalFrustum[0][3] = -(origin[0] * globalFrustum[0][0] + origin[1] * globalFrustum[0][1] + origin[2] * globalFrustum[0][2]);
992 
993  // far clip
994  globalFrustum[1][0] = viewMatrix[0];
995  globalFrustum[1][1] = viewMatrix[4];
996  globalFrustum[1][2] = viewMatrix[8];
997  globalFrustum[1][3] = -globalFrustum[0][3] - viewLightAxialSize;
998 
999  // side clips
1000  globalFrustum[2][0] = -viewMatrix[0] + viewMatrix[1];
1001  globalFrustum[2][1] = -viewMatrix[4] + viewMatrix[5];
1002  globalFrustum[2][2] = -viewMatrix[8] + viewMatrix[9];
1003 
1004  globalFrustum[3][0] = -viewMatrix[0] - viewMatrix[1];
1005  globalFrustum[3][1] = -viewMatrix[4] - viewMatrix[5];
1006  globalFrustum[3][2] = -viewMatrix[8] - viewMatrix[9];
1007 
1008  globalFrustum[4][0] = -viewMatrix[0] + viewMatrix[2];
1009  globalFrustum[4][1] = -viewMatrix[4] + viewMatrix[6];
1010  globalFrustum[4][2] = -viewMatrix[8] + viewMatrix[10];
1011 
1012  globalFrustum[5][0] = -viewMatrix[0] - viewMatrix[2];
1013  globalFrustum[5][1] = -viewMatrix[4] - viewMatrix[6];
1014  globalFrustum[5][2] = -viewMatrix[8] - viewMatrix[10];
1015 
1016  // is this nromalization necessary?
1017  for ( int i = 0 ; i < 6 ; i++ ) {
1018  globalFrustum[i].ToVec4().ToVec3().Normalize();
1019  }
1020 
1021  for ( int i = 2 ; i < 6 ; i++ ) {
1022  globalFrustum[i][3] = - (origin * globalFrustum[i].ToVec4().ToVec3() );
1023  }
1024 
1025  RB_EXP_CullInteractions( vLight, globalFrustum );
1026 
1027 
1028  // FIXME: we want to skip the sampling as well as the generation when not casting shadows
1029  if ( !r_sb_noShadows.GetBool() && vLight->lightShader->LightCastsShadows() ) {
1030  //
1031  // set polygon offset for the rendering
1032  //
1033  switch ( r_sb_occluderFacing.GetInteger() ) {
1034  case 0: // front sides
1036  qglEnable( GL_POLYGON_OFFSET_FILL );
1037  RB_EXP_RenderOccluders( vLight );
1038  qglDisable( GL_POLYGON_OFFSET_FILL );
1039  break;
1040  case 1: // back sides
1042  qglEnable( GL_POLYGON_OFFSET_FILL );
1044  RB_EXP_RenderOccluders( vLight );
1046  qglDisable( GL_POLYGON_OFFSET_FILL );
1047  break;
1048  case 2: // both sides
1050  RB_EXP_RenderOccluders( vLight );
1052  shadowImage[2]->Bind();
1053  qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, lightBufferSize, lightBufferSize );
1054 
1055  RB_EXP_RenderOccluders( vLight );
1056  shadowImage[1]->Bind();
1057  qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, lightBufferSize, lightBufferSize );
1058 
1059  // fragment program to combine the two depth images
1060  qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, depthMidpointVertexProgram );
1061  qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, depthMidpointFragmentProgram );
1064 
1066  shadowImage[1]->Bind();
1067  qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE );
1068  qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
1069  qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
1070 
1072  shadowImage[2]->Bind();
1073  qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE );
1074  qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
1075  qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
1076 
1077  // draw a full screen quad
1078  qglMatrixMode( GL_PROJECTION );
1079  qglLoadIdentity();
1080  qglOrtho( 0, 1, 0, 1, -1, 1 );
1081  qglMatrixMode( GL_MODELVIEW );
1082  qglLoadIdentity();
1083 
1085 
1086  qglBegin( GL_TRIANGLE_FAN );
1087  qglTexCoord2f( 0, 0 );
1088  qglVertex2f( 0, 0 );
1089  qglTexCoord2f( 0, lightBufferSizeFraction );
1090  qglVertex2f( 0, 1 );
1091  qglTexCoord2f( lightBufferSizeFraction, lightBufferSizeFraction );
1092  qglVertex2f( 1, 1 );
1093  qglTexCoord2f( lightBufferSizeFraction, 0 );
1094  qglVertex2f( 1, 0 );
1095  qglEnd();
1096 
1099 
1100  break;
1101  }
1102  }
1103 
1104  // copy to the texture
1105  shadowImage[0]->Bind();
1106  qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, lightBufferSize, lightBufferSize );
1107 
1108 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1109 
1110 
1111  // reset the normal view matrix
1112 
1113  qglMatrixMode( GL_PROJECTION );
1115  qglMatrixMode( GL_MODELVIEW );
1116 
1117  // the current modelView matrix is not valid
1119 }
1120 
1121 /*
1122 ==================
1123 RB_EXP_DrawInteraction
1124 ==================
1125 */
1127  // load all the vertex program parameters
1140 
1141 
1142 // calculate depth projection for shadow buffer
1143 float sRow[4];
1144 float tRow[4];
1145 float rRow[4];
1146 float qRow[4];
1147 float matrix[16];
1148 float matrix2[16];
1149 myGlMultMatrix( din->surf->space->modelMatrix, lightMatrix, matrix );
1150 myGlMultMatrix( matrix, lightProjectionMatrix, matrix2 );
1151 
1152 // the final values need to be in 0.0 : 1.0 range instead of -1 : 1
1153 sRow[0] = 0.5 * lightBufferSizeFraction * ( matrix2[0] + matrix2[3] );
1154 sRow[1] = 0.5 * lightBufferSizeFraction * ( matrix2[4] + matrix2[7] );
1155 sRow[2] = 0.5 * lightBufferSizeFraction * ( matrix2[8] + matrix2[11] );
1156 sRow[3] = 0.5 * lightBufferSizeFraction * ( matrix2[12] + matrix2[15] );
1158 tRow[0] = 0.5 * lightBufferSizeFraction * ( matrix2[1] + matrix2[3] );
1159 tRow[1] = 0.5 * lightBufferSizeFraction * ( matrix2[5] + matrix2[7] );
1160 tRow[2] = 0.5 * lightBufferSizeFraction * ( matrix2[9] + matrix2[11] );
1161 tRow[3] = 0.5 * lightBufferSizeFraction * ( matrix2[13] + matrix2[15] );
1163 rRow[0] = 0.5 * ( matrix2[2] + matrix2[3] );
1164 rRow[1] = 0.5 * ( matrix2[6] + matrix2[7] );
1165 rRow[2] = 0.5 * ( matrix2[10] + matrix2[11] );
1166 rRow[3] = 0.5 * ( matrix2[14] + matrix2[15] );
1168 qRow[0] = matrix2[3];
1169 qRow[1] = matrix2[7];
1170 qRow[2] = matrix2[11];
1171 qRow[3] = matrix2[15];
1173 
1174 
1175  // testing fragment based normal mapping
1176  if ( r_testARBProgram.GetBool() ) {
1179  }
1180 
1181  static const float zero[4] = { 0, 0, 0, 0 };
1182  static const float one[4] = { 1, 1, 1, 1 };
1183  static const float negOne[4] = { -1, -1, -1, -1 };
1184 
1185  switch ( din->vertexColor ) {
1186  case SVC_IGNORE:
1189  break;
1190  case SVC_MODULATE:
1193  break;
1194  case SVC_INVERSE_MODULATE:
1197  break;
1198  }
1199 
1200  // set the constant colors
1203 
1204  //-----------------------------------------------------
1205  // screen power of two correction factor
1206 
1207  float parm[4];
1208  parm[0] = 1.0 / ( JITTER_SIZE * r_sb_samples.GetInteger() ) ;
1209  parm[1] = 1.0 / JITTER_SIZE;
1210  parm[2] = 0;
1211  parm[3] = 1;
1213 
1214  // jitter tex scale
1215  parm[0] =
1216  parm[1] = r_sb_jitterScale.GetFloat() * lightBufferSizeFraction;
1217  parm[2] = -r_sb_biasScale.GetFloat();
1218  parm[3] = 0;
1220 
1221  // jitter tex offset
1222  if ( r_sb_randomize.GetBool() ) {
1223  parm[0] = (rand()&255) / 255.0;
1224  parm[1] = (rand()&255) / 255.0;
1225  } else {
1226  parm[0] = parm[1] = 0;
1227  }
1228  parm[2] = 0;
1229  parm[3] = 0;
1231  //-----------------------------------------------------
1232 
1233  // set the textures
1234 
1235  // texture 1 will be the per-surface bump map
1237  din->bumpImage->Bind();
1238 
1239  // texture 2 will be the light falloff texture
1241  din->lightFalloffImage->Bind();
1242 
1243  // texture 3 will be the light projection texture
1245  din->lightImage->Bind();
1246 
1247  // texture 4 is the per-surface diffuse map
1249  din->diffuseImage->Bind();
1250 
1251  // texture 5 is the per-surface specular map
1253  din->specularImage->Bind();
1254 
1255  // draw it
1257 }
1258 
1259 /*
1260 =============
1261 RB_EXP_CreateDrawInteractions
1262 
1263 =============
1264 */
1266  if ( !surf ) {
1267  return;
1268  }
1269  if ( r_sb_screenSpaceShadow.GetBool() ) {
1270  // perform setup here that will be constant for all interactions
1272 
1273  if ( r_testARBProgram.GetBool() ) {
1276  } else {
1279  }
1280  } else {
1281  // perform setup here that will be constant for all interactions
1284 
1285  // bind the vertex program
1286  qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, shadowVertexProgram );
1287  if ( r_sb_samples.GetInteger() == 16 ) {
1288  qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, shadowFragmentProgram16 );
1289  } else if ( r_sb_samples.GetInteger() == 4 ) {
1290  qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, shadowFragmentProgram4 );
1291  } else if ( r_sb_samples.GetInteger() == 1 ) {
1292  qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, shadowFragmentProgram1 );
1293  } else {
1294  qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, shadowFragmentProgram0 );
1295  }
1296  }
1297 
1300 
1301  // enable the vertex arrays
1306  qglEnableClientState( GL_COLOR_ARRAY );
1307 
1308  // texture 0 is the normalization cube map for the vector towards the light
1314  } else {
1316  }
1317 
1318  // texture 6 is the specular lookup table
1320  if ( r_testARBProgram.GetBool() ) {
1321  globalImages->specular2DTableImage->Bind(); // variable specularity in alpha channel
1322  } else {
1324  }
1325 
1326 
1327  for ( ; surf ; surf=surf->nextOnLight ) {
1328  // perform setup here that will not change over multiple interaction passes
1330  float parm[4];
1331 
1332  parm[0] = surf->space->modelMatrix[0];
1333  parm[1] = surf->space->modelMatrix[4];
1334  parm[2] = surf->space->modelMatrix[8];
1335  parm[3] = 0;
1337  parm[0] = surf->space->modelMatrix[1];
1338  parm[1] = surf->space->modelMatrix[5];
1339  parm[2] = surf->space->modelMatrix[9];
1340  parm[3] = 0;
1342  parm[0] = surf->space->modelMatrix[2];
1343  parm[1] = surf->space->modelMatrix[6];
1344  parm[2] = surf->space->modelMatrix[10];
1345  parm[3] = 0;
1347 
1349  const shaderStage_t *stage = backEnd.vLight->lightShader->GetStage( 0 );
1350  if ( stage->newStage ) {
1352  }
1353  }
1354 
1355  // set the vertex pointers
1357  qglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( idDrawVert ), ac->color );
1358  qglVertexAttribPointerARB( 11, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->normal.ToFloatPtr() );
1359  qglVertexAttribPointerARB( 10, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[1].ToFloatPtr() );
1360  qglVertexAttribPointerARB( 9, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[0].ToFloatPtr() );
1361  qglVertexAttribPointerARB( 8, 2, GL_FLOAT, false, sizeof( idDrawVert ), ac->st.ToFloatPtr() );
1362  qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() );
1363 
1364  // this may cause RB_ARB2_DrawInteraction to be exacuted multiple
1365  // times with different colors and images if the surface or light have multiple layers
1366  if ( r_sb_screenSpaceShadow.GetBool() ) {
1368  } else {
1370  }
1371  }
1372 
1377  qglDisableClientState( GL_COLOR_ARRAY );
1378 
1379  // disable features
1382 
1385 
1388 
1391 
1394 
1397 
1398  backEnd.glState.currenttmu = -1;
1399  GL_SelectTexture( 0 );
1400 
1403 }
1404 
1405 void InvertByTranspose( const float a[16], float r[16] ) {
1406  r[ 0] = a[ 0];
1407  r[ 1] = a[ 4];
1408  r[ 2] = a[ 8];
1409  r[ 3] = 0;
1410  r[ 4] = a[ 1];
1411  r[ 5] = a[ 5];
1412  r[ 6] = a[ 9];
1413  r[ 7] = 0;
1414  r[ 8] = a[ 2];
1415  r[ 9] = a[ 6];
1416  r[10] = a[10];
1417  r[11] = 0;
1418  r[12] = -(r[ 0]*a[12] + r[ 4]*a[13] + r[ 8]*a[14]);
1419  r[13] = -(r[ 1]*a[12] + r[ 5]*a[13] + r[ 9]*a[14]);
1420  r[14] = -(r[ 2]*a[12] + r[ 6]*a[13] + r[10]*a[14]);
1421  r[15] = 1;
1422 }
1423 
1424 void FullInvert( const float a[16], float r[16] ) {
1425  idMat4 am;
1426 
1427  for ( int i = 0 ; i < 4 ; i++ ) {
1428  for ( int j = 0 ; j < 4 ; j++ ) {
1429  am[i][j] = a[j*4+i];
1430  }
1431  }
1432 
1433 // idVec4 test( 100, 100, 100, 1 );
1434 // idVec4 transformed, inverted;
1435 // transformed = test * am;
1436 
1437  if ( !am.InverseSelf() ) {
1438  common->Error( "Invert failed" );
1439  }
1440 // inverted = transformed * am;
1441 
1442  for ( int i = 0 ; i < 4 ; i++ ) {
1443  for ( int j = 0 ; j < 4 ; j++ ) {
1444  r[j*4+i] = am[i][j];
1445  }
1446  }
1447 }
1448 
1449 /*
1450 ==================
1451 RB_Exp_TrianglesForFrustum
1452 ==================
1453 */
1455  const srfTriangles_t *tri;
1456 
1457  static srfTriangles_t frustumTri;
1458  static idDrawVert verts[5];
1459  static glIndex_t indexes[18] = { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 1, 2, 1, 4, 2, 4, 3 };
1460 
1461  if ( side == -1 ) {
1462  tri = vLight->frustumTris;
1463  } else {
1464  memset( verts, 0, sizeof( verts ) );
1465 
1466  for ( int i = 0 ; i < 5 ; i++ ) {
1467  verts[i].xyz = vLight->globalLightOrigin;
1468  }
1469 
1470  memset( &frustumTri, 0, sizeof( frustumTri ) );
1471  frustumTri.indexes = indexes;
1472  frustumTri.verts = verts;
1473  frustumTri.numIndexes = 18;
1474  frustumTri.numVerts = 5;
1475 
1476  tri = &frustumTri;
1477 
1478  float size = viewLightAxialSize;
1479 
1480  switch ( side ) {
1481  case 0:
1482  verts[1].xyz[0] += size;
1483  verts[2].xyz[0] += size;
1484  verts[3].xyz[0] += size;
1485  verts[4].xyz[0] += size;
1486  verts[1].xyz[1] += size;
1487  verts[1].xyz[2] += size;
1488  verts[2].xyz[1] -= size;
1489  verts[2].xyz[2] += size;
1490  verts[3].xyz[1] -= size;
1491  verts[3].xyz[2] -= size;
1492  verts[4].xyz[1] += size;
1493  verts[4].xyz[2] -= size;
1494  break;
1495  case 1:
1496  verts[1].xyz[0] -= size;
1497  verts[2].xyz[0] -= size;
1498  verts[3].xyz[0] -= size;
1499  verts[4].xyz[0] -= size;
1500  verts[1].xyz[1] -= size;
1501  verts[1].xyz[2] += size;
1502  verts[2].xyz[1] += size;
1503  verts[2].xyz[2] += size;
1504  verts[3].xyz[1] += size;
1505  verts[3].xyz[2] -= size;
1506  verts[4].xyz[1] -= size;
1507  verts[4].xyz[2] -= size;
1508  break;
1509  case 2:
1510  verts[1].xyz[1] += size;
1511  verts[2].xyz[1] += size;
1512  verts[3].xyz[1] += size;
1513  verts[4].xyz[1] += size;
1514  verts[1].xyz[0] -= size;
1515  verts[1].xyz[2] += size;
1516  verts[2].xyz[0] += size;
1517  verts[2].xyz[2] += size;
1518  verts[3].xyz[0] += size;
1519  verts[3].xyz[2] -= size;
1520  verts[4].xyz[0] -= size;
1521  verts[4].xyz[2] -= size;
1522  break;
1523  case 3:
1524  verts[1].xyz[1] -= size;
1525  verts[2].xyz[1] -= size;
1526  verts[3].xyz[1] -= size;
1527  verts[4].xyz[1] -= size;
1528  verts[1].xyz[0] += size;
1529  verts[1].xyz[2] += size;
1530  verts[2].xyz[0] -= size;
1531  verts[2].xyz[2] += size;
1532  verts[3].xyz[0] -= size;
1533  verts[3].xyz[2] -= size;
1534  verts[4].xyz[0] += size;
1535  verts[4].xyz[2] -= size;
1536  break;
1537  case 4:
1538  verts[1].xyz[2] += size;
1539  verts[2].xyz[2] += size;
1540  verts[3].xyz[2] += size;
1541  verts[4].xyz[2] += size;
1542  verts[1].xyz[0] += size;
1543  verts[1].xyz[1] += size;
1544  verts[2].xyz[0] -= size;
1545  verts[2].xyz[1] += size;
1546  verts[3].xyz[0] -= size;
1547  verts[3].xyz[1] -= size;
1548  verts[4].xyz[0] += size;
1549  verts[4].xyz[1] -= size;
1550  break;
1551  case 5:
1552  verts[1].xyz[2] -= size;
1553  verts[2].xyz[2] -= size;
1554  verts[3].xyz[2] -= size;
1555  verts[4].xyz[2] -= size;
1556  verts[1].xyz[0] -= size;
1557  verts[1].xyz[1] += size;
1558  verts[2].xyz[0] += size;
1559  verts[2].xyz[1] += size;
1560  verts[3].xyz[0] += size;
1561  verts[3].xyz[1] -= size;
1562  verts[4].xyz[0] -= size;
1563  verts[4].xyz[1] -= size;
1564  break;
1565  }
1566 
1567  frustumTri.ambientCache = vertexCache.AllocFrameTemp( verts, sizeof( verts ) );
1568  }
1569 
1570  return tri;
1571 }
1572 
1573 
1574 /*
1575 ==================
1576 RB_Exp_SelectFrustum
1577 ==================
1578 */
1579 void RB_Exp_SelectFrustum( viewLight_t *vLight, int side ) {
1581 
1582  const srfTriangles_t *tri = RB_Exp_TrianglesForFrustum( vLight, side );
1583 
1585  qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() );
1586 
1587  qglDisable( GL_TEXTURE_2D );
1588  qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1589  // clear stencil buffer
1590  qglEnable( GL_SCISSOR_TEST );
1591  qglEnable( GL_STENCIL_TEST );
1592  qglClearStencil( 1 );
1593  qglClear( GL_STENCIL_BUFFER_BIT );
1594 
1595  // draw front faces of the light frustum, incrementing the stencil buffer on depth fail
1596  // so we can't draw on those pixels
1598  qglStencilFunc( GL_ALWAYS, 0, 255 );
1599  qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP );
1601 
1603 
1604  // draw back faces of the light frustum with
1605  // depth test greater
1606  // stencil test of equal 1
1607  // zero stencil stencil when depth test passes, so subsequent surface drawing
1608  // can occur on those pixels
1609 
1610  // this pass does all the shadow filtering
1611  qglStencilFunc( GL_EQUAL, 1, 255 );
1612  qglStencilOp( GL_KEEP, GL_KEEP, GL_ZERO );
1613 
1615  qglDepthFunc( GL_GREATER );
1616 
1617  // write to destination alpha
1618  if ( r_sb_showFrustumPixels.GetBool() ) {
1620  qglDisable( GL_TEXTURE_2D );
1621  qglColor4f( 0, 0.25, 0, 1 );
1622  } else {
1626  qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, screenSpaceShadowVertexProgram );
1627  switch ( r_sb_samples.GetInteger() ) {
1628  case 0:
1629  qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, screenSpaceShadowFragmentProgram0 );
1630  break;
1631  case 1:
1632  qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, screenSpaceShadowFragmentProgram1 );
1633  break;
1634  case 4:
1635  qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, screenSpaceShadowFragmentProgram4 );
1636  break;
1637  case 16:
1638  qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, screenSpaceShadowFragmentProgram16 );
1639  break;
1640  }
1641  }
1642 
1643 /*
1644 texture[0] = view depth texture
1645 texture[1] = jitter texture
1646 texture[2] = light depth texture
1647 */
1649  shadowImage[0]->Bind();
1650 
1652  if ( r_sb_samples.GetInteger() == 16 ) {
1653  jitterImage16->Bind();
1654  } else if ( r_sb_samples.GetInteger() == 4 ) {
1655  jitterImage4->Bind();
1656  } else {
1657  jitterImage1->Bind();
1658  }
1659 
1661  viewDepthImage->Bind();
1662 
1663  /*
1664 PARAM positionToDepthTexScale = program.local[0]; # fragment.position to screen depth texture transformation
1665 PARAM zProject = program.local[1]; # projection[10], projection[14], 0, 0
1666 PARAM positionToViewSpace = program.local[2]; # X add, Y add, X mul, Y mul
1667 PARAM viewToLightS = program.local[3];
1668 PARAM viewToLightT = program.local[4];
1669 PARAM viewToLightR = program.local[5];
1670 PARAM viewToLightQ = program.local[6];
1671 PARAM positionToJitterTexScale = program.local[7]; # fragment.position to jitter texture
1672 PARAM jitterTexScale = program.local[8];
1673 PARAM jitterTexOffset = program.local[9];
1674 */
1675  float parm[4];
1676  int pot;
1677 
1678  // calculate depth projection for shadow buffer
1679  float sRow[4];
1680  float tRow[4];
1681  float rRow[4];
1682  float qRow[4];
1683  float invertedView[16];
1684  float invertedProjection[16];
1685  float matrix[16];
1686  float matrix2[16];
1687 
1688  // we need the inverse of the projection matrix to go from NDC to view
1689  FullInvert( backEnd.viewDef->projectionMatrix, invertedProjection );
1690 
1691  /*
1692  from window to NDC:
1693  ( x - xMid ) * 1.0 / xMid
1694  ( y - yMid ) * 1.0 / yMid
1695  ( z - 0.5 ) * 2
1696 
1697  from NDC to clip coordinates:
1698  rcp(1/w)
1699 
1700  */
1701 
1702  // we need the inverse of the viewMatrix to go from view (looking down negative Z) to world
1704 
1705  // then we go from world to light view space (looking down negative Z)
1706  myGlMultMatrix( invertedView, lightMatrix, matrix );
1707 
1708  // then to light projection, giving X/w, Y/w, Z/w in the -1 : 1 range
1709  myGlMultMatrix( matrix, lightProjectionMatrix, matrix2 );
1710 
1711  // the final values need to be in 0.0 : 1.0 range instead of -1 : 1
1712  sRow[0] = 0.5 * ( matrix2[0] + matrix2[3] ) * lightBufferSizeFraction;
1713  sRow[1] = 0.5 * ( matrix2[4] + matrix2[7] ) * lightBufferSizeFraction;
1714  sRow[2] = 0.5 * ( matrix2[8] + matrix2[11] ) * lightBufferSizeFraction;
1715  sRow[3] = 0.5 * ( matrix2[12] + matrix2[15] ) * lightBufferSizeFraction;
1717  tRow[0] = 0.5 * ( matrix2[1] + matrix2[3] ) * lightBufferSizeFraction;
1718  tRow[1] = 0.5 * ( matrix2[5] + matrix2[7] ) * lightBufferSizeFraction;
1719  tRow[2] = 0.5 * ( matrix2[9] + matrix2[11] ) * lightBufferSizeFraction;
1720  tRow[3] = 0.5 * ( matrix2[13] + matrix2[15] ) * lightBufferSizeFraction;
1722  rRow[0] = 0.5 * ( matrix2[2] + matrix2[3] );
1723  rRow[1] = 0.5 * ( matrix2[6] + matrix2[7] );
1724  rRow[2] = 0.5 * ( matrix2[10] + matrix2[11] );
1725  rRow[3] = 0.5 * ( matrix2[14] + matrix2[15] );
1727  qRow[0] = matrix2[3];
1728  qRow[1] = matrix2[7];
1729  qRow[2] = matrix2[11];
1730  qRow[3] = matrix2[15];
1732 
1733  //-----------------------------------------------------
1734  // these should be constant for the entire frame
1735 
1736  // convert 0..viewport-1 sizes to fractions inside the POT screen depth texture
1737  int w = viewBufferSize;
1738  pot = MakePowerOfTwo( w );
1739  parm[0] = 1.0 / maxViewBufferSize; // * ( (float)viewBufferSize / w );
1740  int h = viewBufferHeight;
1741  pot = MakePowerOfTwo( h );
1742  parm[1] = parm[0]; // 1.0 / pot;
1743  parm[2] = 0;
1744  parm[3] = 1;
1746 
1747  // zProject values
1748  parm[0] = backEnd.viewDef->projectionMatrix[10];
1749  parm[1] = backEnd.viewDef->projectionMatrix[14];
1750  parm[2] = 0;
1751  parm[3] = 0;
1753 
1754  // positionToViewSpace
1755  parm[0] = -1.0 / backEnd.viewDef->projectionMatrix[0];
1756  parm[1] = -1.0 / backEnd.viewDef->projectionMatrix[5];
1757  parm[2] = 2.0/viewBufferSize;
1758  parm[3] = 2.0/viewBufferSize;
1760 
1761  // positionToJitterTexScale
1762  parm[0] = 1.0 / ( JITTER_SIZE * r_sb_samples.GetInteger() ) ;
1763  parm[1] = 1.0 / JITTER_SIZE;
1764  parm[2] = 0;
1765  parm[3] = 1;
1767 
1768  // jitter tex scale
1769  parm[0] =
1770  parm[1] = r_sb_jitterScale.GetFloat() * lightBufferSizeFraction;
1771  parm[2] = -r_sb_biasScale.GetFloat();
1772  parm[3] = 0;
1774 
1775  // jitter tex offset
1776  if ( r_sb_randomize.GetBool() ) {
1777  parm[0] = (rand()&255) / 255.0;
1778  parm[1] = (rand()&255) / 255.0;
1779  } else {
1780  parm[0] = parm[1] = 0;
1781  }
1782  parm[2] = 0;
1783  parm[3] = 0;
1785  //-----------------------------------------------------
1786 
1787 
1788 
1790 
1793 
1795 // qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
1796 
1797  qglDepthFunc( GL_LEQUAL );
1798  if ( r_sb_showFrustumPixels.GetBool() ) {
1799  qglEnable( GL_TEXTURE_2D );
1800  qglColor3f( 1, 1, 1 );
1801  }
1802 
1803  // after all the frustums have been drawn, the surfaces that have been drawn on will get interactions
1804  // scissor may still be a win even with the stencil test for very fast rejects
1805  qglStencilFunc( GL_EQUAL, 0, 255 );
1806  qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
1807 
1808  // we can avoid clearing the stencil buffer by changing the hasLight value for each light
1809 }
1810 
1811 /*
1812 ==================
1813 R_EXP_CalcLightAxialSize
1814 
1815 all light side projections must currently match, so non-centered
1816 and non-cubic lights must take the largest length
1817 ==================
1818 */
1820  float max = 0;
1821 
1822  if ( !vLight->lightDef->parms.pointLight ) {
1823  idVec3 dir = vLight->lightDef->parms.target - vLight->lightDef->parms.origin;
1824  max = dir.Length();
1825  return max;
1826  }
1827 
1828  for ( int i = 0 ; i < 3 ; i++ ) {
1829  float dist = fabs(vLight->lightDef->parms.lightCenter[i] );
1830  dist += vLight->lightDef->parms.lightRadius[i];
1831  if ( dist > max ) {
1832  max = dist;
1833  }
1834  }
1835  return max;
1836 }
1837 
1838 /*
1839 ==================
1840 R_EXP_RenderViewDepthImage
1841 
1842 This could be avoided by drop sampling the native view depth buffer with render to texture
1843 Bilerp might even be aprorpiate, although it would cause issues at edges
1844 ==================
1845 */
1846 void RB_T_FillDepthBuffer( const drawSurf_t *surf );
1847 
1849  if ( !r_sb_screenSpaceShadow.GetBool() ) {
1850  return;
1851  }
1852 
1853  // if the screen resolution is exactly the window width, we can
1854  // use the depth buffer we already have
1855  if ( 0 ) { // nativeViewBuffer ) {
1856  viewDepthImage->CopyDepthbuffer( backEnd.viewDef->viewport.x1,
1859  } else {
1860  RB_LogComment( "---------- R_EXP_RenderViewDepthImage ----------\n" );
1861 
1862  if ( r_sb_usePbuffer.GetBool() ) {
1863  GL_CheckErrors();
1864  // set the current openGL drawable to the shadow buffer
1865  R_MakeCurrent( viewPbufferDC, win32.hGLRC, NULL /* !@# viewPbuffer */ );
1866  }
1867 
1868  // render the depth to the new size
1869  qglViewport( 0, 0, viewBufferSize, viewBufferHeight );
1870  qglScissor( 0, 0, viewBufferSize, viewBufferHeight );
1871  qglClear( GL_DEPTH_BUFFER_BIT );
1872  qglStencilFunc( GL_ALWAYS, 0, 255 );
1873 
1874  // the first texture will be used for alpha tested surfaces
1875  GL_SelectTexture( 0 );
1876  qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
1877 
1879 
1881 
1882  //
1883  // copy it to a texture
1884  //
1885  viewDepthImage->Bind();
1886  qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, viewBufferSize, viewBufferHeight );
1887 
1888  if ( r_sb_usePbuffer.GetBool() ) {
1889  // set the normal screen drawable current
1890  R_MakeCurrent( win32.hDC, win32.hGLRC, NULL );
1891  }
1892 
1893  // reset the window clipping
1894  qglMatrixMode( GL_PROJECTION );
1896  qglMatrixMode( GL_MODELVIEW );
1897 
1906 
1907  // the current modelView matrix is not valid
1909  }
1910 
1911  qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE );
1912  qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE );
1913  qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
1914  qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
1915 }
1916 
1917 /*
1918 ==================
1919 RB_EXP_SetNativeBuffer
1920 
1921 This is always the back buffer, and scissor is set full screen
1922 ==================
1923 */
1925  // set the normal screen drawable current
1926  R_MakeCurrent( win32.hDC, win32.hGLRC, NULL );
1927 
1932 
1934  if ( r_useScissor.GetBool() ) {
1939  }
1940 }
1941 
1942 /*
1943 ==================
1944 RB_EXP_SetRenderBuffer
1945 
1946 This may be to a float pBuffer, and scissor is set to cover only the light
1947 ==================
1948 */
1950  if ( r_hdr_useFloats.GetBool() ) {
1951  R_MakeCurrent( floatPbufferDC, floatContext, floatPbuffer );
1952  } else {
1953  if ( !qwglMakeCurrent( win32.hDC, win32.hGLRC ) ) {
1954  GL_CheckErrors();
1955  common->FatalError( "Couldn't return to normal drawing context" );
1956  }
1957  }
1958 
1963 
1964  if ( !vLight ) {
1966  } else {
1968  }
1969  if ( r_useScissor.GetBool() ) {
1974  }
1975 }
1976 
1977 /*
1978 ==================
1979 RB_shadowResampleAlpha
1980 
1981 ==================
1982 */
1984  viewAlphaImage->Bind();
1985  // we could make this a subimage, but it isn't relevent once we have render-to-texture
1986  qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, viewBufferSize, viewBufferHeight );
1987 
1989 
1990 //=====================
1991 
1993 
1994  // this uses the full light, not side frustums
1995  const srfTriangles_t *tri = backEnd.vLight->frustumTris;
1996 
1998  qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() );
1999 
2000  // clear stencil buffer
2001  qglEnable( GL_SCISSOR_TEST );
2002  qglEnable( GL_STENCIL_TEST );
2003  qglClearStencil( 1 );
2004  qglClear( GL_STENCIL_BUFFER_BIT );
2005 
2006  // draw front faces of the light frustum, incrementing the stencil buffer on depth fail
2007  // so we can't draw on those pixels
2009  qglStencilFunc( GL_ALWAYS, 0, 255 );
2010  qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP );
2012 
2013  // set fragment / vertex program?
2014 
2016 
2017  // draw back faces of the light frustum with
2018  // depth test greater
2019  // stencil test of equal 1
2020  // zero stencil stencil when depth test passes, so subsequent interaction drawing
2021  // can occur on those pixels
2022 
2023  // this pass does all the shadow filtering
2024  qglStencilFunc( GL_EQUAL, 1, 255 );
2025  qglStencilOp( GL_KEEP, GL_KEEP, GL_ZERO );
2026 
2027  // write to destination alpha
2028  if ( r_sb_showFrustumPixels.GetBool() ) {
2030  qglDisable( GL_TEXTURE_2D );
2031  qglColor4f( 0, 0.25, 0, 1 );
2032  } else {
2036  qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, shadowResampleVertexProgram );
2037  qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, shadowResampleFragmentProgram );
2038 
2039  // convert 0..viewport-1 sizes to fractions inside the POT screen depth texture
2040  // shrink by one unit for bilerp
2041  float parm[4];
2042  parm[0] = 1.0 / (maxViewBufferSize+1) * viewBufferSize / maxViewBufferSize;
2043  parm[1] = parm[0];
2044  parm[2] = 0;
2045  parm[3] = 1;
2047  }
2048 
2050  qglDepthFunc( GL_GREATER );
2051 
2053 
2056 
2058 
2059  qglDepthFunc( GL_LEQUAL );
2060  if ( r_sb_showFrustumPixels.GetBool() ) {
2061  qglEnable( GL_TEXTURE_2D );
2062  qglColor3f( 1, 1, 1 );
2063  }
2064 
2065  // after all the frustums have been drawn, the surfaces that have been drawn on will get interactions
2066  // scissor may still be a win even with the stencil test for very fast rejects
2067  qglStencilFunc( GL_EQUAL, 0, 255 );
2068  qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
2069 }
2070 
2071 
2072 /*
2073 ==================
2074 RB_EXP_CoverScreen
2075 ==================
2076 */
2077 void RB_EXP_CoverScreen( void ) {
2078  // draw a full screen quad
2079  qglMatrixMode( GL_PROJECTION );
2080  qglLoadIdentity();
2081  qglOrtho( 0, 1, 0, 1, -1, 1 );
2082  qglMatrixMode( GL_MODELVIEW );
2083  qglLoadIdentity();
2084 
2085  qglBegin( GL_TRIANGLE_FAN );
2086  qglVertex2f( 0, 0 );
2087  qglVertex2f( 0, 1 );
2088  qglVertex2f( 1, 1 );
2089  qglVertex2f( 1, 0 );
2090  qglEnd();
2091 }
2092 
2093 /*
2094 ==================
2095 RB_EXP_ReadFloatBuffer
2096 ==================
2097 */
2100  float *buf = (float *)R_StaticAlloc( pixels * 4 * sizeof( float ) );
2101 
2102  qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGBA, GL_FLOAT, buf );
2103 
2104  float mins[4] = { 9999, 9999, 9999, 9999 };
2105  float maxs[4] = { -9999, -9999, -9999, -9999 };
2106  for ( int i = 0 ; i < pixels ; i++ ) {
2107  for ( int j = 0 ; j < 4 ; j++ ) {
2108  float v = buf[ i*4 + j ];
2109  if ( v < mins[j] ) {
2110  mins[j] = v;
2111  }
2112  if ( v > maxs[j] ) {
2113  maxs[j] = v;
2114  }
2115  }
2116  }
2117 
2119 
2120  qglLoadIdentity();
2121  qglMatrixMode( GL_PROJECTION );
2123  qglColor3f( 1, 1, 1 );
2124  qglPushMatrix();
2125  qglLoadIdentity();
2126  qglDisable( GL_TEXTURE_2D );
2127  qglOrtho( 0, 1, 0, 1, -1, 1 );
2128  qglRasterPos2f( 0.01f, 0.01f );
2129  qglDrawPixels( glConfig.vidWidth, glConfig.vidHeight, GL_RGBA, GL_FLOAT, buf );
2130  qglPopMatrix();
2131  qglEnable( GL_TEXTURE_2D );
2132  qglMatrixMode( GL_MODELVIEW );
2133 
2134  R_StaticFree( buf );
2135 }
2136 
2137 
2138 void RB_TestGamma( void );
2139 
2140 /*
2141 ==================
2142 RB_EXP_GammaDither
2143 ==================
2144 */
2145 void RB_EXP_GammaDither( void ) {
2146  if ( !r_hdr_useFloats.GetBool() ) {
2147  return;
2148  }
2149 
2150 #if 0
2151 r_testGamma.SetBool( true );
2152 RB_TestGamma();
2153 r_testGamma.SetBool( false );
2154 #endif
2155 
2157 
2158  /*
2159 # texture 0 is the high dynamic range buffer
2160 # texture 1 is the random dither texture
2161 # texture 2 is the light bloom texture
2162 
2163 # writes result.color as the 32 bit dithered and gamma corrected values
2164 
2165 PARAM exposure = program.local[0]; # multiply HDR value by this to get screen pixels
2166 PARAM gammaPower = program.local[1];
2167 PARAM monitorDither = program.local[2];
2168 PARAM positionToDitherScale = program.local[3];
2169 PARAM bloomFraction = program.local[4];
2170 PARAM positionToBloomScale = program.local[5];
2171 
2172  */
2173 
2174  qglBindProgramARB( GL_VERTEX_PROGRAM_ARB,gammaDitherVertexProgram );
2175  qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, gammaDitherFragmentProgram );
2178 
2179  qglActiveTextureARB( GL_TEXTURE2_ARB );
2180  qglBindTexture( GL_TEXTURE_RECTANGLE_NV, floatPbufferQuarterImage->texnum );
2181  R_BindTexImage( floatPbufferQuarter );
2182 
2183  qglActiveTextureARB( GL_TEXTURE1_ARB );
2184  random256Image->BindFragment();
2185 
2186  qglActiveTextureARB( GL_TEXTURE0_ARB );
2187  qglBindTexture( GL_TEXTURE_RECTANGLE_NV, floatPbufferImage->texnum );
2188  R_BindTexImage( floatPbuffer );
2189 
2190  float parm[4];
2191 
2192  parm[0] = r_hdr_exposure.GetFloat();
2193  parm[1] = 0;
2194  parm[2] = 0;
2195  parm[3] = 0;
2197 
2198  parm[0] = r_hdr_gamma.GetFloat();
2199  parm[1] = 0;
2200  parm[2] = 0;
2201  parm[3] = 0;
2203 
2204  parm[0] = r_hdr_monitorDither.GetFloat();
2205  parm[1] = 0;
2206  parm[2] = 0;
2207  parm[3] = 0;
2209 
2210  parm[0] = 1.0 / 256;
2211  parm[1] = parm[0];
2212  parm[2] = rand()/65535.0;
2213  parm[3] = rand()/65535.0;
2215 
2216  parm[0] = 1.0 - r_hdr_bloomFraction.GetFloat();
2217  parm[1] = r_hdr_bloomFraction.GetFloat();
2218  parm[2] = 0;
2219  parm[3] = 0;
2221 
2222  parm[0] = 0.25;
2223  parm[1] = 0.25;
2224  parm[2] = 0;
2225  parm[3] = 0;
2227 
2228  qglDisable( GL_STENCIL_TEST );
2229  qglDisable( GL_SCISSOR_TEST );
2230  qglDisable( GL_DEPTH_TEST );
2231 
2233 
2234  qglEnable( GL_DEPTH_TEST );
2235 
2238 }
2239 
2240 /*
2241 ==================
2242 RB_EXP_Bloom
2243 ==================
2244 */
2245 void RB_EXP_Bloom( void ) {
2246  if ( !r_hdr_useFloats.GetBool() ) {
2247  return;
2248  }
2249 
2250  if ( r_hdr_bloomFraction.GetFloat() == 0 ) {
2251  return;
2252  }
2253 
2254  GL_CheckErrors();
2255 
2256  //
2257  // mip map
2258  //
2259 
2260  // draw to the second floatPbuffer
2261  R_MakeCurrent( floatPbuffer2DC, floatContext, floatPbuffer2 );
2262 
2263  GL_State( 0 );
2264  qglDisable( GL_DEPTH_TEST );
2265  qglDisable( GL_SCISSOR_TEST );
2266 
2269 
2270  qglClearColor( 1.0, 0.5, 0, 0 );
2271  qglClear( GL_COLOR_BUFFER_BIT );
2273 
2274  // read from the original floatPbuffer
2275  qglActiveTextureARB( GL_TEXTURE0_ARB );
2276  qglBindTexture( GL_TEXTURE_RECTANGLE_NV, floatPbufferImage->texnum );
2277  R_BindTexImage( floatPbuffer );
2278 
2279  qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, downSampleVertexProgram );
2280  qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, downSampleFragmentProgram );
2281 
2283 
2284  //
2285  // mip map again
2286  //
2288 
2289  // draw to the second floatPbuffer
2290  R_MakeCurrent( floatPbufferQuarterDC, floatContext, floatPbufferQuarter );
2291 
2292  // read from the original floatPbuffer
2293  qglBindTexture( GL_TEXTURE_RECTANGLE_NV, floatPbuffer2Image->texnum );
2294  R_BindTexImage( floatPbuffer2 );
2295 
2297 
2298  //
2299  // blur horizontally
2300  //
2301  /*
2302 # texture 0 is the high dynamic range buffer
2303 # writes result.color as the fp16 result of a smeared bloom
2304 
2305 PARAM step = program.local[0]; # { 1, 0 } or { 0, 1 } for horizontal / vertical separation
2306  */
2307 
2308  // draw to the second floatPbuffer
2309  R_MakeCurrent( floatPbuffer2DC, floatContext, floatPbuffer2 );
2310 
2311  qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, bloomVertexProgram );
2312  qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, bloomFragmentProgram );
2315 
2317 
2318  // blur horizontally first to the second floatPbuffer
2319  qglBindTexture( GL_TEXTURE_RECTANGLE_NV, floatPbufferQuarterImage->texnum );
2320  R_BindTexImage( floatPbufferQuarter );
2321 
2322  float parm[4];
2323 
2324  parm[0] = 1;
2325  parm[1] = 0;
2326  parm[2] = 0;
2327  parm[3] = 0;
2329 
2331 
2332  //
2333  // now blur vertically back to the quarter pbuffer
2334  //
2335  R_MakeCurrent( floatPbufferQuarterDC, floatContext, floatPbufferQuarter );
2336 
2337  qglBindTexture( GL_TEXTURE_RECTANGLE_NV, floatPbuffer2Image->texnum );
2338  R_BindTexImage( floatPbuffer2 );
2339 
2340  parm[0] = 0;
2341  parm[1] = 1;
2342  parm[2] = 0;
2343  parm[3] = 0;
2345 
2347 
2348  //========================
2349 
2350  qglEnable( GL_DEPTH_TEST );
2351  qglEnable( GL_SCISSOR_TEST );
2352 
2355 
2356  GL_CheckErrors();
2357 }
2358 
2359 /*
2360 ==================
2361 RB_Exp_DrawInteractions
2362 ==================
2363 */
2365  if ( !initialized ) {
2366  R_Exp_Allocate();
2367  }
2368 
2369  if ( !backEnd.viewDef->viewLights ) {
2370  return;
2371  }
2372 
2373  // validate the samples
2374  if ( r_sb_samples.GetInteger() != 16 && r_sb_samples.GetInteger() != 4 && r_sb_samples.GetInteger() != 1 ) {
2375  r_sb_samples.SetInteger( 0 );
2376  }
2377 
2378  // validate the light resolution
2379  if ( r_sb_lightResolution.GetInteger() < 64 ) {
2381  } else if ( r_sb_lightResolution.GetInteger() > maxLightBufferSize ) {
2382  r_sb_lightResolution.SetInteger( maxLightBufferSize );
2383  }
2384  lightBufferSize = r_sb_lightResolution.GetInteger();
2385  lightBufferSizeFraction = (float)lightBufferSize / maxLightBufferSize;
2386 
2387  // validate the view resolution
2388  if ( r_sb_viewResolution.GetInteger() < 64 ) {
2390  } else if ( r_sb_viewResolution.GetInteger() > maxViewBufferSize ) {
2391  r_sb_viewResolution.SetInteger( maxViewBufferSize );
2392  }
2393  viewBufferSize = r_sb_viewResolution.GetInteger();
2394  viewBufferHeight = viewBufferSize * 3 / 4;
2395  viewBufferSizeFraction = (float)viewBufferSize / maxViewBufferSize;
2396  viewBufferHeightFraction = (float)viewBufferHeight / maxViewBufferSize;
2397  if ( viewBufferSize == backEnd.viewDef->viewport.x2 - backEnd.viewDef->viewport.x1 + 1 ) {
2398  nativeViewBuffer = true;
2399  } else {
2400  nativeViewBuffer = false;
2401  }
2402 
2403  // set up for either point sampled or percentage-closer filtering for the shadow sampling
2404  shadowImage[0]->BindFragment();
2405  if ( r_sb_linearFilter.GetBool() ) {
2406  qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
2407  qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
2408  } else {
2409  qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
2410  qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
2411  }
2413 
2415 
2416  // copy the current depth buffer to a texture for image-space shadowing,
2417  // or re-render at a lower resolution
2419 
2420  GL_SelectTexture( 0 );
2421  qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
2422 
2423  // disable stencil shadow test
2424  qglStencilFunc( GL_ALWAYS, 128, 255 );
2425 
2426  // the jitter image will be used to offset sample centers
2428  if ( r_sb_samples.GetInteger() == 16 ) {
2429  jitterImage16->BindFragment();
2430  } else if ( r_sb_samples.GetInteger() == 4 ) {
2431  jitterImage4->BindFragment();
2432  } else {
2433  jitterImage1->BindFragment();
2434  }
2435 
2436  // if we are using a float buffer, clear it now
2437  if ( r_hdr_useFloats.GetBool() ) {
2439  // we need to set a lot of things, because this is a completely different context
2441  qglClearColor( 0.001f, 1.0f, 0.01f, 0.1f );
2442  qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
2443  // clear the z buffer, set the projection matrix, etc
2446  }
2447 
2448 
2449  //
2450  // for each light, perform adding and shadowing
2451  //
2452  for ( viewLight_t *vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
2453  backEnd.vLight = vLight;
2454 
2455  const idMaterial *lightShader = vLight->lightShader;
2456 
2457  // do fogging later
2458  if ( lightShader->IsFogLight() ) {
2459  continue;
2460  }
2461  if ( lightShader->IsBlendLight() ) {
2462  continue;
2463  }
2464 
2465  if ( !vLight->localInteractions && !vLight->globalInteractions
2466  && !vLight->translucentInteractions ) {
2467  continue;
2468  }
2469 
2470  if ( !vLight->frustumTris->ambientCache ) {
2471  R_CreateAmbientCache( const_cast<srfTriangles_t *>(vLight->frustumTris), false );
2472  }
2473 
2474  // all light side projections must currently match, so non-centered
2475  // and non-cubic lights must take the largest length
2476  viewLightAxialSize = R_EXP_CalcLightAxialSize( vLight );
2477 
2478  int side, sideStop;
2479 
2480  if ( vLight->lightDef->parms.pointLight ) {
2481  if ( r_sb_singleSide.GetInteger() != -1 ) {
2482  side = r_sb_singleSide.GetInteger();
2483  sideStop = side+1;
2484  } else {
2485  side = 0;
2486  sideStop = 6;
2487  }
2488  } else {
2489  side = -1;
2490  sideStop = 0;
2491  }
2492 
2493  for ( ; side < sideStop ; side++ ) {
2494  // FIXME: check for frustums completely off the screen
2495 
2496  // render a shadow buffer
2497  RB_RenderShadowBuffer( vLight, side );
2498 
2499  // back to view rendering, possibly in the off-screen buffer
2500  if ( nativeViewBuffer || !r_sb_screenSpaceShadow.GetBool() ) {
2501  // directly to screen
2502  RB_EXP_SetRenderBuffer( vLight );
2503  } else {
2504  // to off screen buffer
2505  if ( r_sb_usePbuffer.GetBool() ) {
2506  GL_CheckErrors();
2507  // set the current openGL drawable to the shadow buffer
2508  R_MakeCurrent( viewPbufferDC, win32.hGLRC, viewPbuffer );
2509  }
2510  qglViewport( 0, 0, viewBufferSize, viewBufferHeight );
2511  qglScissor( 0, 0, viewBufferSize, viewBufferHeight ); // !@# FIXME: scale light scissor
2512  }
2513 
2514  // render the shadows into destination alpha on the included pixels
2515  RB_Exp_SelectFrustum( vLight, side );
2516 
2517  if ( !r_sb_screenSpaceShadow.GetBool() ) {
2518  // bind shadow buffer to texture
2520  shadowImage[0]->BindFragment();
2521 
2522  RB_EXP_CreateDrawInteractions( vLight->localInteractions );
2523  RB_EXP_CreateDrawInteractions( vLight->globalInteractions );
2525  RB_EXP_CreateDrawInteractions( vLight->translucentInteractions );
2527  }
2528  }
2529 
2530  // render the native window coordinates interactions
2531  if ( r_sb_screenSpaceShadow.GetBool() ) {
2532  if ( !nativeViewBuffer ) {
2534  qglEnable( GL_STENCIL_TEST );
2535  } else {
2536  RB_EXP_SetRenderBuffer( vLight );
2537 if ( r_ignore.GetBool() ) {
2538 qglEnable( GL_STENCIL_TEST );
2539 } else {
2540 qglDisable( GL_STENCIL_TEST );
2541 }
2542  }
2543  RB_EXP_CreateDrawInteractions( vLight->localInteractions );
2544  RB_EXP_CreateDrawInteractions( vLight->globalInteractions );
2546  RB_EXP_CreateDrawInteractions( vLight->translucentInteractions );
2548  }
2549  }
2550 
2551  GL_SelectTexture( 0 );
2552  qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
2553 
2554  // experimental transfer function
2555  for ( int i = 7 ; i >= 0 ; i-- ) {
2558  }
2559  GL_State( 0 );
2560 
2561  RB_EXP_Bloom();
2563 
2564  // these haven't been state saved
2565  for ( int i = 0 ; i < 8 ; i++ ) {
2567  }
2568 
2569  // take it out of texture compare mode so I can testImage it for debugging
2570  shadowImage[0]->BindFragment();
2571  qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE );
2572 
2573 
2574 }
2575 
2576 
2577 
2578 /*
2579 ==================
2580 R_Exp_Init
2581 ==================
2582 */
2583 void R_Exp_Init( void ) {
2584  glConfig.allowExpPath = false;
2585 
2586  common->Printf( "---------- R_Exp_Init ----------\n" );
2587 
2589  common->Printf( "Not available.\n" );
2590  return;
2591  }
2592 RB_CreateBloomTable();
2593 #if 0
2594  if ( !R_CheckExtension( "GL_NV_float_buffer" ) ) {
2595  common->Printf( "Not available.\n" );
2596  return;
2597  }
2598  if ( !R_CheckExtension( "GL_NV_texture_rectangle" ) ) {
2599  common->Printf( "Not available.\n" );
2600  return;
2601  }
2602 #endif
2603 
2604 #if 0
2605  qglCombinerParameterfvNV = (void (APIENTRY *)( GLenum pname, const GLfloat *params ))
2606  GLimp_ExtensionPointer( "glCombinerParameterfvNV" );
2607 #endif
2608 
2609  common->Printf( "Available.\n" );
2610 
2611  if ( !idStr::Icmp( r_renderer.GetString(), "exp" ) ) {
2612  R_Exp_Allocate();
2613  }
2614 
2615  common->Printf( "--------------------------------------------\n" );
2616 
2617  glConfig.allowExpPath = true;
2618 }
GLenum
Definition: qgl.h:120
FLOAT
Definition: win_qgl.cpp:63
idImage * specular2DTableImage
Definition: Image.h:411
bool SurfaceCastsShadow(void) const
Definition: Material.h:392
#define WGL_FRONT_LEFT_ARB
Definition: wglext.h:162
const int GLS_DSTBLEND_ONE
Definition: tr_local.h:1017
PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB
Definition: win_glimp.cpp:66
const idMaterial * shader
Definition: Interaction.h:76
byte color[4]
Definition: MegaTexture.cpp:54
idVec4 localLightOrigin
Definition: tr_local.h:453
idImage * GetEditorImage(void) const
Definition: Material.cpp:190
#define qglTexCoordPointer
Definition: qgl_linked.h:318
void RB_EXP_CreateDrawInteractions(const drawSurf_t *surf)
Definition: draw_exp.cpp:1265
#define GL_TEXTURE_COMPARE_FUNC_ARB
Definition: glext.h:581
#define qglLoadMatrixf
Definition: qgl_linked.h:188
const srfTriangles_t * geo
Definition: tr_local.h:112
viewEntity_t worldSpace
Definition: tr_local.h:373
float Normalize(void)
Definition: Vector.h:646
Definition: Image.h:146
const int GLS_DEPTHFUNC_LESS
Definition: tr_local.h:1040
#define qglScissor
Definition: qgl_linked.h:280
#define GL_COMPARE_R_TO_TEXTURE
Definition: glext.h:320
idVec3 lightCenter
Definition: RenderWorld.h:179
#define WGL_ALPHA_BITS_ARB
Definition: wglext.h:106
void RB_Exp_SelectFrustum(viewLight_t *vLight, int side)
Definition: draw_exp.cpp:1579
void GL_SelectTextureNoClient(int unit)
Definition: draw_nv20.cpp:61
idCVar r_sb_viewResolution("r_sb_viewResolution","1024", CVAR_RENDERER|CVAR_INTEGER,"Width of screen space shadow sampling")
int iAttribute
Definition: wglext.h:385
PFNGLVERTEXATTRIBPOINTERARBPROC qglVertexAttribPointerARB
void RB_shadowResampleAlpha(void)
Definition: draw_exp.cpp:1983
#define qglEnableClientState
Definition: qgl_linked.h:102
#define qglDisable
Definition: qgl_linked.h:92
#define qglDisableClientState
Definition: qgl_linked.h:93
int numVerts
Definition: Model.h:98
void GenerateImage(const byte *pic, int width, int height, textureFilter_t filter, bool allowDownSize, textureRepeat_t repeat, textureDepth_t depth)
Definition: Image_load.cpp:509
GLdouble GLdouble GLdouble GLdouble zNear
Definition: qgl.h:273
void GL_CheckErrors(void)
stageVertexColor_t vertexColor
Definition: tr_local.h:447
idInteraction * lightNext
Definition: Interaction.h:108
short x2
Definition: tr_local.h:55
bool InverseSelf(void)
Definition: Matrix.cpp:689
CONST PIXELFORMATDESCRIPTOR UINT
Definition: win_qgl.cpp:47
float GetFloat(void) const
Definition: CVarSystem.h:144
drawSurf_t ** drawSurfs
Definition: tr_local.h:411
const GLdouble * v
Definition: glext.h:2936
HGLRC hGLRC
Definition: win_local.h:122
#define GL_TEXTURE1_ARB
Definition: glext.h:378
void RB_RenderShadowBuffer(viewLight_t *vLight, int side)
Definition: draw_exp.cpp:833
GLuint GLenum matrix
Definition: glext.h:5179
#define qglClearColor
Definition: qgl_linked.h:41
idCVar r_testARBProgram("r_testARBProgram","0", CVAR_RENDERER|CVAR_BOOL,"experiment with vertex/fragment programs")
void RB_EXP_SetRenderBuffer(viewLight_t *vLight)
Definition: draw_exp.cpp:1949
const float * ToFloatPtr(void) const
Definition: Vector.h:719
idScreenRect scissorRect
Definition: tr_local.h:307
const int GLS_ALPHAMASK
Definition: tr_local.h:1033
bool R_CheckExtension(char *name)
const int GLS_COLORMASK
Definition: tr_local.h:1034
#define qglBindTexture
Definition: qgl_linked.h:34
#define GL_TEXTURE_BINDING_RECTANGLE_NV
Definition: glext.h:2054
idVec3 xyz
Definition: DrawVert.h:42
static const float PI
Definition: Math.h:205
idCVar r_hdr_monitorDither("r_hdr_monitorDither","0.01", CVAR_RENDERER|CVAR_FLOAT,"random dither in monitor space")
idImage * fragmentProgramImages[MAX_FRAGMENT_IMAGES]
Definition: Material.h:198
#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV
Definition: wglext.h:307
idVec4 diffuseMatrix[2]
Definition: tr_local.h:457
case const int
Definition: Callbacks.cpp:52
PFNWGLRELEASETEXIMAGEARBPROC wglReleaseTexImageARB
Definition: win_glimp.cpp:74
idVec3 tangents[2]
Definition: DrawVert.h:45
PFNGLDISABLEVERTEXATTRIBARRAYARBPROC qglDisableVertexAttribArrayARB
idCVar r_sb_singleSide("r_sb_singleSide","-1", CVAR_RENDERER|CVAR_INTEGER,"only draw a single side (0-5) of point lights")
renderLight_t parms
Definition: tr_local.h:191
#define qglBegin
Definition: qgl_linked.h:33
const char * name
Definition: draw_exp.cpp:175
void R_EXP_RenderViewDepthImage(void)
Definition: draw_exp.cpp:1848
idCVar r_sb_samples("r_sb_samples","4", CVAR_RENDERER|CVAR_INTEGER,"0, 1, 4, or 16")
void R_Exp_Allocate(void)
Definition: draw_exp.cpp:501
#define WGL_TEXTURE_FORMAT_ARB
Definition: wglext.h:145
const idVec4 & ToVec4(void) const
Definition: Plane.h:375
Definition: Vector.h:316
idScreenRect viewport
Definition: tr_local.h:398
case const float
Definition: Callbacks.cpp:62
GLExtension_t GLimp_ExtensionPointer(const char *name)
void RB_EXP_CoverScreen(void)
Definition: draw_exp.cpp:2077
idCVar r_renderer("r_renderer","best", CVAR_RENDERER|CVAR_ARCHIVE,"hardware specific renderer path to use", r_rendererArgs, idCmdSystem::ArgCompletion_String< r_rendererArgs >)
GLenum GLsizei GLenum GLenum const GLvoid * image
Definition: glext.h:2855
#define qglGetIntegerv
Definition: qgl_linked.h:133
#define GL_FLOAT_RGBA16_NV
Definition: glext.h:2694
const drawSurf_t * surf
Definition: tr_local.h:437
#define WGL_DRAW_TO_PBUFFER_ARB
Definition: wglext.h:132
const int GLS_DEPTHFUNC_ALWAYS
Definition: tr_local.h:1038
idImage * diffuseImage
Definition: tr_local.h:442
idCVar r_sb_frustomFOV("r_sb_frustomFOV","92", CVAR_RENDERER|CVAR_FLOAT,"oversize FOV for point light side matching")
float modelMatrix[16]
Definition: tr_local.h:253
bool IsBlendLight() const
Definition: Material.h:461
#define qglReadPixels
Definition: qgl_linked.h:266
void RB_EXP_Bloom(void)
Definition: draw_exp.cpp:2245
short x1
Definition: tr_local.h:55
idRenderLightLocal * lightDef
Definition: tr_local.h:302
GLdouble s
Definition: glext.h:2935
#define qglViewport
Definition: qgl_linked.h:364
#define WGL_STENCIL_BITS_ARB
Definition: wglext.h:114
#define WGL_BLUE_BITS_ARB
Definition: wglext.h:104
const struct viewEntity_s * space
Definition: tr_local.h:113
struct vertCache_s * ambientCache
Definition: Model.h:137
int i
Definition: process.py:33
int currenttmu
Definition: tr_local.h:605
idCVar r_hdr_exposure("r_hdr_exposure","1.0", CVAR_RENDERER|CVAR_FLOAT,"maximum light scale")
float projectionMatrix[16]
Definition: tr_local.h:372
void RB_EXP_GammaDither(void)
Definition: draw_exp.cpp:2145
bool IsAmbientLight() const
Definition: Material.h:464
#define WGL_RED_BITS_ARB
Definition: wglext.h:100
#define qglEnable
Definition: qgl_linked.h:101
const viewEntity_t * currentSpace
Definition: tr_local.h:644
void RB_EXP_CullInteractions(viewLight_t *vLight, idPlane frustumPlanes[6])
Definition: draw_exp.cpp:716
#define qglPolygonOffset
Definition: qgl_linked.h:230
int Icmp(const char *text) const
Definition: Str.h:667
#define GL_TEXTURE2_ARB
Definition: glext.h:379
#define APIENTRY
Definition: glext.h:43
const idMaterial * lightShader
Definition: tr_local.h:326
wglString_t wglString[]
Definition: draw_exp.cpp:179
void RB_Exp_DrawInteractions(void)
Definition: draw_exp.cpp:2364
backEndState_t backEnd
Definition: tr_backend.cpp:35
#define qglPushMatrix
Definition: qgl_linked.h:239
void GL_Cull(int cullType)
Definition: tr_backend.cpp:161
void RB_BeginDrawingView(void)
Definition: tr_render.cpp:555
#define WGL_FLOAT_COMPONENTS_NV
Definition: wglext.h:303
idCVar r_ignore("r_ignore","0", CVAR_RENDERER,"used for random debugging without defining new vars")
bool LightCastsShadows() const
Definition: Material.h:468
idVec4 diffuseColor
Definition: tr_local.h:445
const int GLS_DEPTHFUNC_EQUAL
Definition: tr_local.h:1039
void RB_CreateSingleDrawInteractions(const drawSurf_t *surf, void(*DrawInteraction)(const drawInteraction_t *))
Definition: tr_render.cpp:689
idBounds referenceBounds
Definition: tr_local.h:268
PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB
Definition: win_glimp.cpp:67
struct viewLight_s * next
Definition: tr_local.h:299
void RB_RenderDrawSurfListWithFunction(drawSurf_t **drawSurfs, int numDrawSurfs, void(*triFunc_)(const drawSurf_t *))
Definition: tr_render.cpp:232
idImage * specularImage
Definition: tr_local.h:443
struct viewLight_s * viewLights
Definition: tr_local.h:415
idVec2 st
Definition: DrawVert.h:43
#define qglStencilFunc
Definition: qgl_linked.h:283
const srfTriangles_t * RB_Exp_TrianglesForFrustum(viewLight_t *vLight, int side)
Definition: draw_exp.cpp:1454
#define qglStencilOp
Definition: qgl_linked.h:285
idCVar r_hdr_useFloats("r_hdr_useFloats","0", CVAR_RENDERER|CVAR_BOOL,"use a floating point rendering buffer")
#define WGL_DEPTH_BITS_ARB
Definition: wglext.h:113
idCVar r_sb_showFrustumPixels("r_sb_showFrustumPixels","0", CVAR_RENDERER|CVAR_BOOL,"color the pixels contained in the frustum")
viewLight_t * vLight
Definition: tr_local.h:648
const GLubyte * c
Definition: glext.h:4677
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:3454
idCVar r_sb_randomize("r_sb_randomize","1", CVAR_RENDERER|CVAR_BOOL,"randomly offset jitter texture each draw")
idVec3 lightRadius
Definition: RenderWorld.h:178
float Length(void) const
Definition: Vector.h:631
idCVar r_sb_noShadows("r_sb_noShadows","0", CVAR_RENDERER|CVAR_BOOL,"don't draw any occluders")
idImage * normalCubeMapImage
Definition: Image.h:400
const shaderStage_t * GetStage(const int index) const
Definition: Material.h:368
idImage * lightImage
Definition: tr_local.h:439
PFNGLENABLEVERTEXATTRIBARRAYARBPROC qglEnableVertexAttribArrayARB
GLuint texnum
Definition: Image.h:216
idCVar r_sb_usePbuffer("r_sb_usePbuffer","1", CVAR_RENDERER|CVAR_BOOL,"draw offscreen")
PFNWGLBINDTEXIMAGEARBPROC wglBindTexImageARB
Definition: win_glimp.cpp:73
newShaderStage_t * newStage
Definition: Material.h:216
#define WGL_TEXTURE_TARGET_ARB
Definition: wglext.h:146
void R_Exp_Init(void)
Definition: draw_exp.cpp:2583
idCVar r_hdr_bloomFraction("r_hdr_bloomFraction","0.1", CVAR_RENDERER|CVAR_FLOAT,"fraction to smear across neighbors")
idImage * lightFalloffImage
Definition: tr_local.h:440
idCVar r_sb_polyOfsFactor("r_sb_polyOfsFactor","2", CVAR_RENDERER|CVAR_FLOAT,"polygonOffset factor for drawing shadow buffer")
idCommon * common
Definition: Common.cpp:206
void RB_ARB2_DrawInteraction(const drawInteraction_t *din)
Definition: draw_arb2.cpp:67
PFNGLBINDPROGRAMARBPROC qglBindProgramARB
idVec4 specularColor
Definition: tr_local.h:446
#define NULL
Definition: Lib.h:88
int glIndex_t
Definition: Model.h:52
void SetInteger(const int value)
Definition: CVarSystem.h:148
#define qglTexCoord2f
Definition: qgl_linked.h:296
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:2853
idInteraction * firstInteraction
Definition: tr_local.h:230
bool initialized
Definition: maya_main.cpp:38
int GetInteger(void) const
Definition: CVarSystem.h:143
glstate_t glState
Definition: tr_local.h:663
#define qglOrtho
Definition: qgl_linked.h:218
const int GLS_SRCBLEND_ONE
Definition: tr_local.h:1006
#define qglEnd
Definition: qgl_linked.h:103
idImageManager * globalImages
Definition: Image_init.cpp:74
bool ARBVertexProgramAvailable
Definition: RenderSystem.h:74
#define qglColor3f
Definition: qgl_linked.h:50
virtual void virtual void FatalError(const char *fmt,...) id_attribute((format(printf
#define GL_TEXTURE_COMPARE_MODE_ARB
Definition: glext.h:580
idVec4 bumpMatrix[2]
Definition: tr_local.h:456
Definition: Plane.h:71
void RB_EXP_SetNativeBuffer(void)
Definition: draw_exp.cpp:1924
#define qglTexParameterf
Definition: qgl_linked.h:331
idVec4 specularMatrix[2]
Definition: tr_local.h:458
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB
Definition: win_glimp.cpp:63
void Mem_Free(void *ptr)
Definition: Heap.cpp:1087
idVec3 normal
Definition: DrawVert.h:44
void RB_SetDefaultGLState(void)
Definition: tr_backend.cpp:46
#define qglClearStencil
Definition: qgl_linked.h:44
#define GL_DEPTH_COMPONENT24_ARB
Definition: glext.h:573
idImage * ImageFromFunction(const char *name, void(*generatorFunction)(idImage *image))
GLenum GLsizei width
Definition: glext.h:2846
typedef HDC(WINAPI *PFNWGLGETCURRENTREADDCARBPROC)(void)
GLubyte GLubyte GLubyte a
Definition: glext.h:4662
virtual void Printf(const char *fmt,...) id_attribute((format(printf
idCVar r_sb_polyOfsUnits("r_sb_polyOfsUnits","3000", CVAR_RENDERER|CVAR_FLOAT,"polygonOffset units for drawing shadow buffer")
#define context
Definition: getdate.c:236
float modelMatrix[16]
Definition: tr_local.h:360
void RB_DrawElementsWithCounters(const srfTriangles_t *tri)
Definition: tr_render.cpp:78
const float * ToFloatPtr(void) const
Definition: Vector.h:1051
void RB_T_FillDepthBuffer(const drawSurf_t *surf)
const int GLS_SRCBLEND_DST_ALPHA
Definition: tr_local.h:1011
vertCache_t * AllocFrameTemp(void *data, int bytes)
GLenum GLsizei GLsizei height
Definition: glext.h:2856
const int GLS_DSTBLEND_ZERO
Definition: tr_local.h:1016
int uploadHeight
Definition: Image.h:249
void myGlMultMatrix(const float *a, const float *b, float *out)
idCVar r_testGamma("r_testGamma","0", CVAR_RENDERER|CVAR_FLOAT,"if > 0 draw a grid pattern to test gamma levels", 0, 195)
void InvertByTranspose(const float a[16], float r[16])
Definition: draw_exp.cpp:1405
const char * GetString(void) const
Definition: CVarSystem.h:141
int uploadWidth
Definition: Image.h:249
#define qglPopMatrix
Definition: qgl_linked.h:234
idCVar r_sb_lightResolution("r_sb_lightResolution","1024", CVAR_RENDERER|CVAR_INTEGER,"Pixel dimensions for each shadow buffer, 64 - 2048")
void RB_LogComment(const char *comment,...)
Definition: tr_backend.cpp:112
GLdouble GLdouble GLdouble r
Definition: glext.h:2951
#define WGL_TEXTURE_RECTANGLE_NV
Definition: wglext.h:299
static WindowRef ValidModeCallbackProc inCallback OSStatus err
void BindFragment()
HGLRC
Definition: win_qgl.cpp:52
#define qglCopyTexSubImage2D
Definition: qgl_linked.h:85
idCVar r_sb_occluderFacing("r_sb_occluderFacing","0", CVAR_RENDERER|CVAR_INTEGER,"0 = front faces, 1 = back faces, 2 = midway between")
GLenum pname
Definition: glext.h:2847
#define qglColorPointer
Definition: qgl_linked.h:80
bool GetBool(void) const
Definition: CVarSystem.h:142
glconfig_t glConfig
PFNWGLGETPIXELFORMATATTRIBIVARBPROC wglGetPixelFormatAttribivARB
Definition: win_glimp.cpp:61
tuple f
Definition: idal.py:89
#define qglTexImage2D
Definition: qgl_linked.h:330
#define qglTexParameteri
Definition: qgl_linked.h:333
idVec4 lightProjection[4]
Definition: tr_local.h:455
const float * ToFloatPtr(void) const
Definition: Vector.h:301
unsigned char byte
Definition: Lib.h:75
void * R_StaticAlloc(int bytes)
Definition: tr_main.cpp:301
int viewportOffset[2]
Definition: tr_local.h:758
void RB_STD_FillDepthBuffer(drawSurf_t **drawSurfs, int numDrawSurfs)
const GLcharARB * name
Definition: glext.h:3629
void * Position(vertCache_t *buffer)
void RB_EXP_ReadFloatBuffer(void)
Definition: draw_exp.cpp:2098
GLsizeiptr size
Definition: glext.h:3112
void R_PrintPixelFormat(int pixelFormat)
Definition: draw_exp.cpp:479
const struct drawSurf_s * nextOnLight
Definition: tr_local.h:117
#define GL_VERTEX_PROGRAM_ARB
Definition: glext.h:594
#define qglClear
Definition: qgl_linked.h:39
bool R_CreateAmbientCache(srfTriangles_t *tri, bool needsLighting)
Definition: tr_light.cpp:52
srfTriangles_t * ambientTris
Definition: Interaction.h:74
idCVar r_hdr_gamma("r_hdr_gamma","1", CVAR_RENDERER|CVAR_FLOAT,"monitor gamma power")
#define qglColor4f
Definition: qgl_linked.h:66
#define qglDrawPixels
Definition: qgl_linked.h:97
idImage * bumpImage
Definition: tr_local.h:441
#define qglVertex2f
Definition: qgl_linked.h:341
float modelViewMatrix[16]
Definition: tr_local.h:361
PFNGLPROGRAMENVPARAMETER4FVARBPROC qglProgramEnvParameter4fvARB
PFNGLPROGRAMLOCALPARAMETER4FVARBPROC qglProgramLocalParameter4fvARB
byte color[4]
Definition: DrawVert.h:46
typedef LPVOID(WINAPI *PFNWGLCREATEIMAGEBUFFERI3DPROC)(HDC hDC
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
bool IsFogLight() const
Definition: Material.h:458
int numDrawSurfs
Definition: tr_local.h:412
glIndex_t * indexes
Definition: Model.h:102
idCVar r_sb_screenSpaceShadow("r_sb_screenSpaceShadow","1", CVAR_RENDERER|CVAR_BOOL,"build shadows in screen space instead of on surfaces")
idVertexCache vertexCache
Definition: VertexCache.cpp:41
idRenderSystemLocal tr
idVec3 globalLightOrigin
Definition: tr_local.h:322
#define GL_TEXTURE0_ARB
Definition: glext.h:377
#define qglGenTextures
Definition: qgl_linked.h:127
void SetBool(const bool value)
Definition: CVarSystem.h:147
const idVec3 & ToVec3(void) const
Definition: Vector.h:1043
idCVar r_sb_useCulling("r_sb_useCulling","1", CVAR_RENDERER|CVAR_BOOL,"cull geometry to individual side frustums")
void RB_TestGamma(void)
void GL_State(int stateBits)
Definition: tr_backend.cpp:239
int current2DMap
Definition: tr_local.h:595
GLuint res
Definition: glext.h:5385
float R_EXP_CalcLightAxialSize(viewLight_t *vLight)
Definition: draw_exp.cpp:1819
#define TRUE
Definition: mprintf.c:69
void * Mem_Alloc(const int size)
Definition: Heap.cpp:1067
short y1
Definition: tr_local.h:55
#define qglLoadIdentity
Definition: qgl_linked.h:186
GLint j
Definition: qgl.h:264
#define WGL_GREEN_BITS_ARB
Definition: wglext.h:102
int numIndexes
Definition: Model.h:101
idCVar r_useScissor("r_useScissor","1", CVAR_RENDERER|CVAR_BOOL,"scissor clip as portals and lights are processed")
#define qglTexParameterfv
Definition: qgl_linked.h:332
char * va(const char *fmt,...)
Definition: Str.cpp:1568
Win32Vars_t win32
Definition: win_main.cpp:65
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: glext.h:2878
const srfTriangles_t * frustumTris
Definition: tr_local.h:325
void GL_SelectTexture(int unit)
Definition: tr_backend.cpp:135
void R_StaticFree(void *data)
Definition: tr_main.cpp:335
idImage * specularTableImage
Definition: Image.h:410
#define max(x, y)
Definition: os.h:70
#define WGL_TEXTURE_FLOAT_RGBA_NV
Definition: wglext.h:311
short y2
Definition: tr_local.h:55
virtual void Error(const char *fmt,...) id_attribute((format(printf
#define GL_TEXTURE_RECTANGLE_NV
Definition: glext.h:2053
void Bind()
int MakePowerOfTwo(int num)
Definition: Image_load.cpp:46
idScreenRect currentScissor
Definition: tr_local.h:645
bool ARBFragmentProgramAvailable
Definition: RenderSystem.h:75
void CopyDepthbuffer(int x, int y, int width, int height)
idCVar r_sb_biasScale("r_sb_biasScale","0.0001", CVAR_RENDERER|CVAR_FLOAT,"scale factor for jitter bias")
Definition: Matrix.h:764
typedef HPBUFFERARB(WINAPI *PFNWGLCREATEPBUFFERARBPROC)(HDC hDC
int pixelformat
Definition: win_local.h:124
idCVar r_sb_linearFilter("r_sb_linearFilter","1", CVAR_RENDERER|CVAR_BOOL,"use GL_LINEAR instead of GL_NEAREST on shadow maps")
int R_FindARBProgram(GLenum target, const char *program)
Definition: draw_arb2.cpp:466
#define qglMatrixMode
Definition: qgl_linked.h:203
#define qglVertexPointer
Definition: qgl_linked.h:363
void FullInvert(const float a[16], float r[16])
Definition: draw_exp.cpp:1424
void R_GlobalPlaneToLocal(const float modelMatrix[16], const idPlane &in, idPlane &out)
Definition: tr_main.cpp:547
const int GLS_DEPTHMASK
Definition: tr_local.h:1029
idCVar r_sb_jitterScale("r_sb_jitterScale","0.006", CVAR_RENDERER|CVAR_FLOAT,"scale factor for jitter offset")
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
Definition: stub_gl.cpp:345
idDrawVert * verts
Definition: Model.h:99
#define qglDepthFunc
Definition: qgl_linked.h:89
#define qglRasterPos2f
Definition: qgl_linked.h:243
idVec3 globalLightOrigin
Definition: tr_local.h:216
idVec4 localViewOrigin
Definition: tr_local.h:454
void RB_EXP_RenderOccluders(viewLight_t *vLight)
Definition: draw_exp.cpp:780
GLenum const GLfloat * params
Definition: glext.h:2847
void RB_EXP_DrawInteraction(const drawInteraction_t *din)
Definition: draw_exp.cpp:1126
tmu_t tmu[MAX_MULTITEXTURE_UNITS]
Definition: tr_local.h:604
#define GL_FRAGMENT_PROGRAM_ARB
Definition: glext.h:675
const viewDef_t * viewDef
Definition: tr_local.h:641