* Experimental branch for using the xreal renderer in the trem-compat branch xreal-compat
authoramanieu
Wed, 10 Jun 2009 09:31:46 +0800
branchxreal-compat
changeset 1372ffee0440255d
parent 1370 75e9d243cc90
* Experimental branch for using the xreal renderer in the trem-compat branch
- Start it with +set com_hunkMegs 512
- Currently only displays a black screen
Makefile
glsl/bloom_fp.glsl
glsl/bloom_vp.glsl
glsl/blurX_fp.glsl
glsl/blurX_vp.glsl
glsl/blurY_fp.glsl
glsl/blurY_vp.glsl
glsl/contrast_fp.glsl
glsl/contrast_vp.glsl
glsl/deferredLighting_DBS_omni_fp.glsl
glsl/deferredLighting_DBS_omni_vp.glsl
glsl/deferredLighting_DBS_proj_fp.glsl
glsl/deferredLighting_DBS_proj_vp.glsl
glsl/deferredShadowing_proj_fp.glsl
glsl/deferredShadowing_proj_vp.glsl
glsl/deluxeMapping_fp.glsl
glsl/deluxeMapping_vp.glsl
glsl/depthFill_fp.glsl
glsl/depthFill_vp.glsl
glsl/depthOfField_fp.glsl
glsl/depthOfField_vp.glsl
glsl/depthTest_fp.glsl
glsl/depthTest_vp.glsl
glsl/depthToColor_fp.glsl
glsl/depthToColor_vp.glsl
glsl/dispersion_C_fp.glsl
glsl/dispersion_C_vp.glsl
glsl/forwardLighting_DBS_omni_fp.glsl
glsl/forwardLighting_DBS_omni_vp.glsl
glsl/forwardLighting_DBS_proj_fp.glsl
glsl/forwardLighting_DBS_proj_vp.glsl
glsl/genericSingle_fp.glsl
glsl/genericSingle_vp.glsl
glsl/geometricFill_DBS_fp.glsl
glsl/geometricFill_DBS_vp.glsl
glsl/heatHaze_fp.glsl
glsl/heatHaze_vp.glsl
glsl/lightMapping_fp.glsl
glsl/lightMapping_vp.glsl
glsl/lightVolume_omni_fp.glsl
glsl/lightVolume_omni_vp.glsl
glsl/liquid_fp.glsl
glsl/liquid_vp.glsl
glsl/portal_fp.glsl
glsl/portal_vp.glsl
glsl/reflection_CB_fp.glsl
glsl/reflection_CB_vp.glsl
glsl/reflection_C_fp.glsl
glsl/reflection_C_vp.glsl
glsl/refraction_C_fp.glsl
glsl/refraction_C_vp.glsl
glsl/rotoscope_fp.glsl
glsl/rotoscope_vp.glsl
glsl/screenSpaceAmbientOcclusion_fp.glsl
glsl/screenSpaceAmbientOcclusion_vp.glsl
glsl/screen_fp.glsl
glsl/screen_vp.glsl
glsl/shadowExtrude_fp.glsl
glsl/shadowExtrude_vp.glsl
glsl/shadowFill_fp.glsl
glsl/shadowFill_vp.glsl
glsl/skybox_fp.glsl
glsl/skybox_vp.glsl
glsl/toneMapping_fp.glsl
glsl/toneMapping_vp.glsl
glsl/uniformFog_fp.glsl
glsl/uniformFog_vp.glsl
glsl/vertexLighting_DBS_entity_fp.glsl
glsl/vertexLighting_DBS_entity_vp.glsl
glsl/vertexLighting_DBS_world_fp.glsl
glsl/vertexLighting_DBS_world_vp.glsl
glsl/volumetricFog_fp.glsl
glsl/volumetricFog_vp.glsl
src/client/cl_cgame.c
src/client/cl_cin.c
src/client/cl_ui.c
src/client/client.h
src/qcommon/q_math.c
src/qcommon/q_shared.c
src/qcommon/q_shared.h
src/qcommon/qfiles.h
src/qcommon/surfaceflags.h
src/renderer/qgl.c
src/renderer/qgl.h
src/renderer/tr_animation.c
src/renderer/tr_backend.c
src/renderer/tr_bsp.c
src/renderer/tr_cmds.c
src/renderer/tr_curve.c
src/renderer/tr_fbo.c
src/renderer/tr_flares.c
src/renderer/tr_font.c
src/renderer/tr_image.c
src/renderer/tr_image_dds.c
src/renderer/tr_image_jpg.c
src/renderer/tr_image_png.c
src/renderer/tr_image_tga.c
src/renderer/tr_init.c
src/renderer/tr_light.c
src/renderer/tr_local.h
src/renderer/tr_main.c
src/renderer/tr_marks.c
src/renderer/tr_mesh.c
src/renderer/tr_model.c
src/renderer/tr_noise.c
src/renderer/tr_public.h
src/renderer/tr_scene.c
src/renderer/tr_shade.c
src/renderer/tr_shade_calc.c
src/renderer/tr_shader.c
src/renderer/tr_shadows.c
src/renderer/tr_sky.c
src/renderer/tr_surface.c
src/renderer/tr_types.h
src/renderer/tr_vbo.c
src/renderer/tr_world.c
src/sdl/sdl_glimp.c
     1.1 --- a/Makefile	Sat Jun 06 03:54:16 2009 +0800
     1.2 +++ b/Makefile	Wed Jun 10 09:31:46 2009 +0800
     1.3 @@ -1395,12 +1395,13 @@
     1.4    $(B)/client/jmemnobs.o \
     1.5    $(B)/client/jutils.o \
     1.6    \
     1.7 +  $(B)/client/qgl.o \
     1.8    $(B)/client/tr_animation.o \
     1.9    $(B)/client/tr_backend.o \
    1.10 -  $(B)/client/tr_bloom.o \
    1.11    $(B)/client/tr_bsp.o \
    1.12    $(B)/client/tr_cmds.o \
    1.13    $(B)/client/tr_curve.o \
    1.14 +  $(B)/client/tr_fbo.o \
    1.15    $(B)/client/tr_flares.o \
    1.16    $(B)/client/tr_font.o \
    1.17    $(B)/client/tr_image.o \
    1.18 @@ -1408,7 +1409,7 @@
    1.19    $(B)/client/tr_image_jpg.o \
    1.20    $(B)/client/tr_image_bmp.o \
    1.21    $(B)/client/tr_image_tga.o \
    1.22 -  $(B)/client/tr_image_pcx.o \
    1.23 +  $(B)/client/tr_image_dds.o \
    1.24    $(B)/client/tr_init.o \
    1.25    $(B)/client/tr_light.o \
    1.26    $(B)/client/tr_main.o \
    1.27 @@ -1423,6 +1424,7 @@
    1.28    $(B)/client/tr_shadows.o \
    1.29    $(B)/client/tr_sky.o \
    1.30    $(B)/client/tr_surface.o \
    1.31 +  $(B)/client/tr_vbo.o \
    1.32    $(B)/client/tr_world.o \
    1.33    \
    1.34    $(B)/client/sdl_gamma.o \
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/glsl/bloom_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
     2.3 @@ -0,0 +1,103 @@
     2.4 +/*
     2.5 +===========================================================================
     2.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
     2.7 +
     2.8 +This file is part of XreaL source code.
     2.9 +
    2.10 +XreaL source code is free software; you can redistribute it
    2.11 +and/or modify it under the terms of the GNU General Public License as
    2.12 +published by the Free Software Foundation; either version 2 of the License,
    2.13 +or (at your option) any later version.
    2.14 +
    2.15 +XreaL source code is distributed in the hope that it will be
    2.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.18 +GNU General Public License for more details.
    2.19 +
    2.20 +You should have received a copy of the GNU General Public License
    2.21 +along with XreaL source code; if not, write to the Free Software
    2.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    2.23 +===========================================================================
    2.24 +*/
    2.25 +
    2.26 +uniform sampler2D	u_ColorMap;
    2.27 +uniform sampler2D	u_ContrastMap;
    2.28 +uniform float		u_BlurMagnitude;
    2.29 +
    2.30 +
    2.31 +
    2.32 +#if defined(GLHW_ATI) || defined(GLHW_ATI_DX10) || defined(MESA)
    2.33 +
    2.34 +/*
    2.35 + AMD Radeon HD 4850:
    2.36 + Fragment shader was successfully compiled to run on hardware.
    2.37 + Not supported when use temporary array indirect index.
    2.38 + Not supported when use temporary array indirect index.
    2.39 + ERROR: Fragment shader(s) failed to link,  vertex shader(s) linked.
    2.40 + Fragment Shader not supported by HW
    2.41 + shaders failed to link
    2.42 + 
    2.43 + Asus EAH4850:
    2.44 + ERROR: Fragment shader(s) failed to link,  vertex shader(s) linked.
    2.45 + Fragment Shader not supported by HWERROR: 0:101: Not supported when use temporary
    2.46 + array indirect index.
    2.47 + ERROR: 0:101: Not supported when use temporary array indirect index.
    2.48 + */
    2.49 +
    2.50 +void main()
    2.51 +{
    2.52 +	discard;
    2.53 +}
    2.54 +#else
    2.55 +void	main()
    2.56 +{
    2.57 +	vec2 st = gl_FragCoord.st;
    2.58 +
    2.59 +	// calculate the screen texcoord in the 0.0 to 1.0 range
    2.60 +	st *= r_FBufScale;
    2.61 +	
    2.62 +	// scale by the screen non-power-of-two-adjust
    2.63 +	st *= r_NPOTScale;
    2.64 +	
    2.65 +	// we use the Normal-gauss distribution formula
    2.66 +	// f(x) being the formula, we used f(0.5)-f(-0.5); f(1.5)-f(0.5)...
    2.67 +
    2.68 +	#if 0
    2.69 +	float gaussFact[3] = float[3](1.0, 2.0, 1.0);
    2.70 +	#elif 1
    2.71 +	float gaussFact[5] = float[5](1.0, 4.0, 6.0, 4.0, 1.0);
    2.72 +	float gaussSum = 4096.0; // = 64.0^2 = result of sumWeights;
    2.73 +	#elif 0
    2.74 +	float gaussFact[7] = float[7](1.0, 6.0, 15.0, 20.0, 15.0, 6.0, 1.0);
    2.75 +	float gaussSum = 4096.0; // = 64.0^2 = result of sumWeights;
    2.76 +	#else
    2.77 +	float gaussFact[11] = float[11](
    2.78 +	0.0222244, 0.0378346, 0.0755906, 0.1309775, 0.1756663,
    2.79 +	0.1974126,
    2.80 +	0.1756663, 0.1309775, 0.0755906, 0.0378346, 0.0222244
    2.81 +	);
    2.82 +	#endif
    2.83 +
    2.84 +	// do a full gaussian blur
    2.85 +	vec4 sumColors = vec4(0.0);
    2.86 +	float sumWeights = 0.0;
    2.87 +
    2.88 +	int tap = 2;
    2.89 +	for(int i = -tap; i < tap; i++)
    2.90 +    {
    2.91 +	    for(int j = -tap; j < tap; j++)
    2.92 +	    {
    2.93 +			float weight = gaussFact[i + 2] * gaussFact[j + 2];
    2.94 +			vec4 color = texture2D(u_ContrastMap, st + vec2(i, j) * u_BlurMagnitude * r_FBufScale) * weight;
    2.95 +			
    2.96 +			sumColors += color;
    2.97 +			sumWeights += weight;
    2.98 +		}
    2.99 +	}
   2.100 +	
   2.101 +	//gl_FragColor = texture2D(u_ColorMap, st) + sumColors / gaussSum;
   2.102 +	//gl_FragColor = sumColors / gaussSum;
   2.103 +	gl_FragColor = sumColors / sumWeights;
   2.104 +}
   2.105 +#endif
   2.106 +
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/glsl/bloom_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
     3.3 @@ -0,0 +1,31 @@
     3.4 +/*
     3.5 +===========================================================================
     3.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
     3.7 +
     3.8 +This file is part of XreaL source code.
     3.9 +
    3.10 +XreaL source code is free software; you can redistribute it
    3.11 +and/or modify it under the terms of the GNU General Public License as
    3.12 +published by the Free Software Foundation; either version 2 of the License,
    3.13 +or (at your option) any later version.
    3.14 +
    3.15 +XreaL source code is distributed in the hope that it will be
    3.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.18 +GNU General Public License for more details.
    3.19 +
    3.20 +You should have received a copy of the GNU General Public License
    3.21 +along with XreaL source code; if not, write to the Free Software
    3.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    3.23 +===========================================================================
    3.24 +*/
    3.25 +
    3.26 +attribute vec4		attr_Position;
    3.27 +
    3.28 +uniform mat4		u_ModelViewProjectionMatrix;
    3.29 +
    3.30 +void	main()
    3.31 +{
    3.32 +	// transform vertex position into homogenous clip-space
    3.33 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
    3.34 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/glsl/blurX_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
     4.3 @@ -0,0 +1,157 @@
     4.4 +/*
     4.5 +===========================================================================
     4.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
     4.7 +
     4.8 +This file is part of XreaL source code.
     4.9 +
    4.10 +XreaL source code is free software; you can redistribute it
    4.11 +and/or modify it under the terms of the GNU General Public License as
    4.12 +published by the Free Software Foundation; either version 2 of the License,
    4.13 +or (at your option) any later version.
    4.14 +
    4.15 +XreaL source code is distributed in the hope that it will be
    4.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.18 +GNU General Public License for more details.
    4.19 +
    4.20 +You should have received a copy of the GNU General Public License
    4.21 +along with XreaL source code; if not, write to the Free Software
    4.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    4.23 +===========================================================================
    4.24 +*/
    4.25 +
    4.26 +uniform sampler2D	u_ColorMap;
    4.27 +uniform float		u_BlurMagnitude;
    4.28 +
    4.29 +void	main()
    4.30 +{
    4.31 +	vec2 st = gl_FragCoord.st;
    4.32 +
    4.33 +	// calculate the screen texcoord in the 0.0 to 1.0 range
    4.34 +	st *= r_FBufScale;
    4.35 +
    4.36 +	// multiply with 4 because the FBO is only 1/4th of the screen resolution
    4.37 +	st *= vec2(4.0, 4.0);
    4.38 +	
    4.39 +	// scale by the screen non-power-of-two-adjust
    4.40 +	st *= r_NPOTScale;
    4.41 +	
    4.42 +#if 1
    4.43 +	// set so a magnitude of 1 is approximately 1 pixel with 640x480
    4.44 +	//vec2 deform = vec2(u_BlurMagnitude * 0.0016, u_BlurMagnitude * 0.00213333);
    4.45 +	vec2 deform = u_BlurMagnitude * r_FBufScale;
    4.46 +	
    4.47 +	// these are the multipliers for the gaussian blur
    4.48 +	float mu01 = 0.00261097;
    4.49 +	float mu02 = 0.00522193;
    4.50 +	float mu03 = 0.01044386;
    4.51 +	float mu04 = 0.02088773;
    4.52 +	float mu05 = 0.04177546;
    4.53 +	float mu06 = 0.08355091;
    4.54 +	float mu07 = 0.16710183;
    4.55 +	float mu08 = 0.33420366;
    4.56 +	float mu09 = 0.66840732;
    4.57 +	
    4.58 +	// fragment offsets for blur samples
    4.59 +	vec2 offset01 = vec2(-8.0, 0.0);
    4.60 +	vec2 offset02 = vec2(-7.0, 0.0);
    4.61 +	vec2 offset03 = vec2(-6.0, 0.0);
    4.62 +	vec2 offset04 = vec2(-5.0, 0.0);
    4.63 +	vec2 offset05 = vec2(-4.0, 0.0);
    4.64 +	vec2 offset06 = vec2(-3.0, 0.0);
    4.65 +	vec2 offset07 = vec2(-2.0, 0.0);
    4.66 +	vec2 offset08 = vec2(-1.0, 0.0);
    4.67 +	vec2 offset09 = vec2( 1.0, 0.0);
    4.68 +	vec2 offset10 = vec2( 2.0, 0.0);
    4.69 +	vec2 offset11 = vec2( 3.0, 0.0);
    4.70 +	vec2 offset12 = vec2( 4.0, 0.0);
    4.71 +	vec2 offset13 = vec2( 5.0, 0.0);
    4.72 +	vec2 offset14 = vec2( 6.0, 0.0);
    4.73 +	vec2 offset15 = vec2( 7.0, 0.0);
    4.74 +	vec2 offset16 = vec2( 8.0, 0.0);
    4.75 +	
    4.76 +	// calculate our offset texture coordinates
    4.77 +	vec2 st01 = st + offset01 * deform;
    4.78 +	vec2 st02 = st + offset02 * deform;
    4.79 +	vec2 st03 = st + offset03 * deform;
    4.80 +	vec2 st04 = st + offset04 * deform;
    4.81 +	vec2 st05 = st + offset05 * deform;
    4.82 +	vec2 st06 = st + offset06 * deform;
    4.83 +	vec2 st07 = st + offset07 * deform;
    4.84 +	vec2 st08 = st + offset08 * deform;
    4.85 +	vec2 st09 = st + offset09 * deform;
    4.86 +	vec2 st10 = st + offset10 * deform;
    4.87 +	vec2 st11 = st + offset11 * deform;
    4.88 +	vec2 st12 = st + offset12 * deform;
    4.89 +	vec2 st13 = st + offset13 * deform;
    4.90 +	vec2 st14 = st + offset14 * deform;
    4.91 +	vec2 st15 = st + offset15 * deform;
    4.92 +	vec2 st16 = st + offset16 * deform;
    4.93 +	
    4.94 +	// base color
    4.95 +	vec4 c00 = texture2D(u_ColorMap, st);
    4.96 +
    4.97 +	// sample the current render for each coordinate
    4.98 +	vec4 c01 = texture2D(u_ColorMap, st01);
    4.99 +	vec4 c02 = texture2D(u_ColorMap, st02);
   4.100 +	vec4 c03 = texture2D(u_ColorMap, st03);
   4.101 +	vec4 c04 = texture2D(u_ColorMap, st04);
   4.102 +	vec4 c05 = texture2D(u_ColorMap, st05);
   4.103 +	vec4 c06 = texture2D(u_ColorMap, st06);
   4.104 +	vec4 c07 = texture2D(u_ColorMap, st07);
   4.105 +	vec4 c08 = texture2D(u_ColorMap, st08);
   4.106 +	vec4 c09 = texture2D(u_ColorMap, st09);
   4.107 +	vec4 c10 = texture2D(u_ColorMap, st10);
   4.108 +	vec4 c11 = texture2D(u_ColorMap, st11);
   4.109 +	vec4 c12 = texture2D(u_ColorMap, st12);
   4.110 +	vec4 c13 = texture2D(u_ColorMap, st13);
   4.111 +	vec4 c14 = texture2D(u_ColorMap, st14);
   4.112 +	vec4 c15 = texture2D(u_ColorMap, st15);
   4.113 +	vec4 c16 = texture2D(u_ColorMap, st16);
   4.114 +	
   4.115 +	vec4 color = c01 * mu01;
   4.116 +	color += c02 * mu02;
   4.117 +	color += c03 * mu03;
   4.118 +	color += c04 * mu04;
   4.119 +	color += c05 * mu05;
   4.120 +	color += c06 * mu06;
   4.121 +	color += c07 * mu07;
   4.122 +	color += c08 * mu08;
   4.123 +	color += c00 * mu09;
   4.124 +	color += c09 * mu08;
   4.125 +	color += c10 * mu07;
   4.126 +	color += c11 * mu06;
   4.127 +	color += c12 * mu05;
   4.128 +	color += c13 * mu04;
   4.129 +	color += c14 * mu03;
   4.130 +	color += c15 * mu02;
   4.131 +	color += c16 * mu01;
   4.132 +	
   4.133 +	gl_FragColor = color;
   4.134 +#else
   4.135 +
   4.136 +	#if 0
   4.137 +	float gaussFact[3] = float[3](1.0, 2.0, 1.0);
   4.138 +	#elif 0
   4.139 +	float gaussFact[5] = float[5](1.0, 4.0, 6.0, 4.0, 1.0);
   4.140 +	float gaussSum = 16.0;
   4.141 +	#elif 1
   4.142 +	float gaussFact[7] = float[7](1.0, 6.0, 15.0, 20.0, 15.0, 6.0, 1.0);
   4.143 +	float gaussSum = 64.0;
   4.144 +	#endif
   4.145 +
   4.146 +	// do a full gaussian blur
   4.147 +	vec4 sumColors = vec4(0.0);
   4.148 +
   4.149 +	int tap = 3;
   4.150 +	for(int i = -tap; i < tap; i++)
   4.151 +    {
   4.152 +	    float weight = gaussFact[i + 2];
   4.153 +		vec4 color = texture2D(u_ColorMap, st + vec2(i, 0) * u_BlurMagnitude * r_FBufScale) * weight;
   4.154 +			
   4.155 +		sumColors += color;
   4.156 +	}
   4.157 +	
   4.158 +	gl_FragColor = sumColors / gaussSum;
   4.159 +#endif
   4.160 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/glsl/blurX_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
     5.3 @@ -0,0 +1,31 @@
     5.4 +/*
     5.5 +===========================================================================
     5.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
     5.7 +
     5.8 +This file is part of XreaL source code.
     5.9 +
    5.10 +XreaL source code is free software; you can redistribute it
    5.11 +and/or modify it under the terms of the GNU General Public License as
    5.12 +published by the Free Software Foundation; either version 2 of the License,
    5.13 +or (at your option) any later version.
    5.14 +
    5.15 +XreaL source code is distributed in the hope that it will be
    5.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.18 +GNU General Public License for more details.
    5.19 +
    5.20 +You should have received a copy of the GNU General Public License
    5.21 +along with XreaL source code; if not, write to the Free Software
    5.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    5.23 +===========================================================================
    5.24 +*/
    5.25 +
    5.26 +attribute vec4		attr_Position;
    5.27 +
    5.28 +uniform mat4		u_ModelViewProjectionMatrix;
    5.29 +
    5.30 +void	main()
    5.31 +{
    5.32 +	// transform vertex position into homogenous clip-space
    5.33 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
    5.34 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/glsl/blurY_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
     6.3 @@ -0,0 +1,157 @@
     6.4 +/*
     6.5 +===========================================================================
     6.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
     6.7 +
     6.8 +This file is part of XreaL source code.
     6.9 +
    6.10 +XreaL source code is free software; you can redistribute it
    6.11 +and/or modify it under the terms of the GNU General Public License as
    6.12 +published by the Free Software Foundation; either version 2 of the License,
    6.13 +or (at your option) any later version.
    6.14 +
    6.15 +XreaL source code is distributed in the hope that it will be
    6.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.18 +GNU General Public License for more details.
    6.19 +
    6.20 +You should have received a copy of the GNU General Public License
    6.21 +along with XreaL source code; if not, write to the Free Software
    6.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    6.23 +===========================================================================
    6.24 +*/
    6.25 +
    6.26 +uniform sampler2D	u_ColorMap;
    6.27 +uniform float		u_BlurMagnitude;
    6.28 +
    6.29 +void	main()
    6.30 +{
    6.31 +	vec2 st = gl_FragCoord.st;
    6.32 +
    6.33 +	// calculate the screen texcoord in the 0.0 to 1.0 range
    6.34 +	st *= r_FBufScale;
    6.35 +
    6.36 +	// multiply with 4 because the FBO is only 1/4th of the screen resolution
    6.37 +	st *= vec2(4.0, 4.0);
    6.38 +	
    6.39 +	// scale by the screen non-power-of-two-adjust
    6.40 +	st *= r_NPOTScale;
    6.41 +	
    6.42 +#if 1
    6.43 +	// set so a magnitude of 1 is approximately 1 pixel with 640x480
    6.44 +	//vec2 deform = vec2(u_BlurMagnitude * 0.0016, u_BlurMagnitude * 0.00213333);
    6.45 +	vec2 deform = u_BlurMagnitude * r_FBufScale;
    6.46 +	
    6.47 +	// these are the multipliers for the gaussian blur
    6.48 +	float mu01 = 0.00261097;
    6.49 +	float mu02 = 0.00522193;
    6.50 +	float mu03 = 0.01044386;
    6.51 +	float mu04 = 0.02088773;
    6.52 +	float mu05 = 0.04177546;
    6.53 +	float mu06 = 0.08355091;
    6.54 +	float mu07 = 0.16710183;
    6.55 +	float mu08 = 0.33420366;
    6.56 +	float mu09 = 0.66840732;
    6.57 +	
    6.58 +	// fragment offsets for blur samples
    6.59 +	vec2 offset01 = vec2( 0.0, -8.0);
    6.60 +	vec2 offset02 = vec2( 0.0, -7.0);
    6.61 +	vec2 offset03 = vec2( 0.0, -6.0);
    6.62 +	vec2 offset04 = vec2( 0.0, -5.0);
    6.63 +	vec2 offset05 = vec2( 0.0, -4.0);
    6.64 +	vec2 offset06 = vec2( 0.0, -3.0);
    6.65 +	vec2 offset07 = vec2( 0.0, -2.0);
    6.66 +	vec2 offset08 = vec2( 0.0, -1.0);
    6.67 +	vec2 offset09 = vec2( 0.0,  1.0);
    6.68 +	vec2 offset10 = vec2( 0.0,  2.0);
    6.69 +	vec2 offset11 = vec2( 0.0,  3.0);
    6.70 +	vec2 offset12 = vec2( 0.0,  4.0);
    6.71 +	vec2 offset13 = vec2( 0.0,  5.0);
    6.72 +	vec2 offset14 = vec2( 0.0,  6.0);
    6.73 +	vec2 offset15 = vec2( 0.0,  7.0);
    6.74 +	vec2 offset16 = vec2( 0.0,  8.0);
    6.75 +	
    6.76 +	// calculate our offset texture coordinates
    6.77 +	vec2 st01 = st + offset01 * deform;
    6.78 +	vec2 st02 = st + offset02 * deform;
    6.79 +	vec2 st03 = st + offset03 * deform;
    6.80 +	vec2 st04 = st + offset04 * deform;
    6.81 +	vec2 st05 = st + offset05 * deform;
    6.82 +	vec2 st06 = st + offset06 * deform;
    6.83 +	vec2 st07 = st + offset07 * deform;
    6.84 +	vec2 st08 = st + offset08 * deform;
    6.85 +	vec2 st09 = st + offset09 * deform;
    6.86 +	vec2 st10 = st + offset10 * deform;
    6.87 +	vec2 st11 = st + offset11 * deform;
    6.88 +	vec2 st12 = st + offset12 * deform;
    6.89 +	vec2 st13 = st + offset13 * deform;
    6.90 +	vec2 st14 = st + offset14 * deform;
    6.91 +	vec2 st15 = st + offset15 * deform;
    6.92 +	vec2 st16 = st + offset16 * deform;
    6.93 +	
    6.94 +	// base color
    6.95 +	vec4 c00 = texture2D(u_ColorMap, st);
    6.96 +
    6.97 +	// sample the current render for each coordinate
    6.98 +	vec4 c01 = texture2D(u_ColorMap, st01);
    6.99 +	vec4 c02 = texture2D(u_ColorMap, st02);
   6.100 +	vec4 c03 = texture2D(u_ColorMap, st03);
   6.101 +	vec4 c04 = texture2D(u_ColorMap, st04);
   6.102 +	vec4 c05 = texture2D(u_ColorMap, st05);
   6.103 +	vec4 c06 = texture2D(u_ColorMap, st06);
   6.104 +	vec4 c07 = texture2D(u_ColorMap, st07);
   6.105 +	vec4 c08 = texture2D(u_ColorMap, st08);
   6.106 +	vec4 c09 = texture2D(u_ColorMap, st09);
   6.107 +	vec4 c10 = texture2D(u_ColorMap, st10);
   6.108 +	vec4 c11 = texture2D(u_ColorMap, st11);
   6.109 +	vec4 c12 = texture2D(u_ColorMap, st12);
   6.110 +	vec4 c13 = texture2D(u_ColorMap, st13);
   6.111 +	vec4 c14 = texture2D(u_ColorMap, st14);
   6.112 +	vec4 c15 = texture2D(u_ColorMap, st15);
   6.113 +	vec4 c16 = texture2D(u_ColorMap, st16);
   6.114 +	
   6.115 +	vec4 color = c01 * mu01;
   6.116 +	color += c02 * mu02;
   6.117 +	color += c03 * mu03;
   6.118 +	color += c04 * mu04;
   6.119 +	color += c05 * mu05;
   6.120 +	color += c06 * mu06;
   6.121 +	color += c07 * mu07;
   6.122 +	color += c08 * mu08;
   6.123 +	color += c00 * mu09;
   6.124 +	color += c09 * mu08;
   6.125 +	color += c10 * mu07;
   6.126 +	color += c11 * mu06;
   6.127 +	color += c12 * mu05;
   6.128 +	color += c13 * mu04;
   6.129 +	color += c14 * mu03;
   6.130 +	color += c15 * mu02;
   6.131 +	color += c16 * mu01;
   6.132 +	
   6.133 +	gl_FragColor = color;
   6.134 +#else
   6.135 +
   6.136 +	#if 0
   6.137 +	float gaussFact[3] = float[3](1.0, 2.0, 1.0);
   6.138 +	#elif 0
   6.139 +	float gaussFact[5] = float[5](1.0, 4.0, 6.0, 4.0, 1.0);
   6.140 +	float gaussSum = 16.0;
   6.141 +	#elif 1
   6.142 +	float gaussFact[7] = float[7](1.0, 6.0, 15.0, 20.0, 15.0, 6.0, 1.0);
   6.143 +	float gaussSum = 64.0;
   6.144 +	#endif
   6.145 +
   6.146 +	// do a full gaussian blur
   6.147 +	vec4 sumColors = vec4(0.0);
   6.148 +
   6.149 +	int tap = 3;
   6.150 +	for(int i = -tap; i < tap; i++)
   6.151 +    {
   6.152 +	    float weight = gaussFact[i + 2];
   6.153 +		vec4 color = texture2D(u_ColorMap, st + vec2(0, i) * u_BlurMagnitude * r_FBufScale) * weight;
   6.154 +			
   6.155 +		sumColors += color;
   6.156 +	}
   6.157 +	
   6.158 +	gl_FragColor = sumColors / gaussSum;
   6.159 +#endif
   6.160 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/glsl/blurY_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
     7.3 @@ -0,0 +1,31 @@
     7.4 +/*
     7.5 +===========================================================================
     7.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
     7.7 +
     7.8 +This file is part of XreaL source code.
     7.9 +
    7.10 +XreaL source code is free software; you can redistribute it
    7.11 +and/or modify it under the terms of the GNU General Public License as
    7.12 +published by the Free Software Foundation; either version 2 of the License,
    7.13 +or (at your option) any later version.
    7.14 +
    7.15 +XreaL source code is distributed in the hope that it will be
    7.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.18 +GNU General Public License for more details.
    7.19 +
    7.20 +You should have received a copy of the GNU General Public License
    7.21 +along with XreaL source code; if not, write to the Free Software
    7.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    7.23 +===========================================================================
    7.24 +*/
    7.25 +
    7.26 +attribute vec4		attr_Position;
    7.27 +
    7.28 +uniform mat4		u_ModelViewProjectionMatrix;
    7.29 +
    7.30 +void	main()
    7.31 +{
    7.32 +	// transform vertex position into homogenous clip-space
    7.33 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
    7.34 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/glsl/contrast_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
     8.3 @@ -0,0 +1,129 @@
     8.4 +/*
     8.5 +===========================================================================
     8.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
     8.7 +
     8.8 +This file is part of XreaL source code.
     8.9 +
    8.10 +XreaL source code is free software; you can redistribute it
    8.11 +and/or modify it under the terms of the GNU General Public License as
    8.12 +published by the Free Software Foundation; either version 2 of the License,
    8.13 +or (at your option) any later version.
    8.14 +
    8.15 +XreaL source code is distributed in the hope that it will be
    8.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.18 +GNU General Public License for more details.
    8.19 +
    8.20 +You should have received a copy of the GNU General Public License
    8.21 +along with XreaL source code; if not, write to the Free Software
    8.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    8.23 +===========================================================================
    8.24 +*/
    8.25 +
    8.26 +uniform sampler2D	u_ColorMap;
    8.27 +#if defined(r_HDRRendering)
    8.28 +uniform float		u_HDRKey;
    8.29 +uniform float		u_HDRAverageLuminance;
    8.30 +uniform float		u_HDRMaxLuminance;
    8.31 +#endif
    8.32 +
    8.33 +const vec4			LUMINANCE_VECTOR = vec4(0.2125, 0.7154, 0.0721, 0.0);
    8.34 +
    8.35 +void	main()
    8.36 +{
    8.37 +	vec2 st = gl_FragCoord.st;
    8.38 +
    8.39 +	// calculate the screen texcoord in the 0.0 to 1.0 range
    8.40 +	st *= r_FBufScale;
    8.41 +
    8.42 +	// multiply with 4 because the FBO is only 1/4th of the screen resolution
    8.43 +	st *= vec2(4.0, 4.0);
    8.44 +	
    8.45 +	// scale by the screen non-power-of-two-adjust
    8.46 +	st *= r_NPOTScale;
    8.47 +	
    8.48 +	
    8.49 +#if defined(r_HDRRendering)
    8.50 +
    8.51 +	vec4 color = texture2D(u_ColorMap, st);
    8.52 +
    8.53 +	float Y = dot(LUMINANCE_VECTOR, color);
    8.54 +
    8.55 +	float Yr = u_HDRKey * Y / u_HDRAverageLuminance;
    8.56 +	float Ymax = u_HDRMaxLuminance;
    8.57 +	
    8.58 +#if defined(r_HDRToneMappingOperator_0)
    8.59 +	
    8.60 +	// simple tone map operator
    8.61 +	float L = Yr / (1.0 + Yr);
    8.62 +	
    8.63 +#elif defined(r_HDRToneMappingOperator_1)
    8.64 +	
    8.65 +	float L = 1.0 - exp(-Yr);
    8.66 +
    8.67 +#elif defined(r_HDRToneMappingOperator_2)
    8.68 +
    8.69 +	float Cmax = color.r;
    8.70 +	if(color.g > Cmax)
    8.71 +		Cmax = color.g;
    8.72 +	if(color.b > Cmax)
    8.73 +		Cmax = color.b;
    8.74 +
    8.75 +	float L = 1.0 - exp(-Yr * Cmax);
    8.76 +
    8.77 +	if(Cmax > 0.0)
    8.78 +	{
    8.79 +		L = L / Cmax;
    8.80 +	}
    8.81 +	else
    8.82 +	{
    8.83 +		L = 0.0;
    8.84 +	}
    8.85 +
    8.86 +#elif defined(r_HDRToneMappingOperator_3)
    8.87 +	
    8.88 +	float L = Yr / (1.0 + Yr) * (1.0 + Yr / (Ymax * Ymax));
    8.89 +	
    8.90 +#else
    8.91 +	
    8.92 +	// recommended by Wolgang Engel
    8.93 +	float L = Yr * (1.0 + Yr / (Ymax * Ymax)) / (1.0 + Yr);
    8.94 +#endif
    8.95 +	
    8.96 +	// adjust contrast
    8.97 +	L = pow(L, 1.32);
    8.98 +	
    8.99 +	float T = max(L - r_HDRContrastThreshold, 0.0);
   8.100 +	float B = T / (r_HDRContrastOffset + T);
   8.101 +	
   8.102 +	color.rgb *= B;
   8.103 +
   8.104 +	gl_FragColor = color;
   8.105 +
   8.106 +#else
   8.107 +	// LDR path
   8.108 +	
   8.109 +	// calculate contrast color
   8.110 +#if 0
   8.111 +	// perform a box filter for the downsample
   8.112 +	vec3 color = texture2D(u_ColorMap, st + vec2(-1.0, 1.0) * r_FBufScale).rgb;
   8.113 +	color += texture2D(u_ColorMap, st + vec2(1.0, 1.0) * r_FBufScale).rgb;
   8.114 +	color += texture2D(u_ColorMap, st + vec2(1.0, -1.0) * r_FBufScale).rgb;
   8.115 +	color += texture2D(u_ColorMap, st + vec2(-1.0, -1.0) * r_FBufScale).rgb;
   8.116 +	color *= 0.25;
   8.117 +#else
   8.118 +	vec4 color = texture2D(u_ColorMap, st);
   8.119 +#endif
   8.120 +
   8.121 +	float L = dot(LUMINANCE_VECTOR, color);
   8.122 +	
   8.123 +	// adjust contrast
   8.124 +	L = pow(L, 1.32);
   8.125 +
   8.126 +	float T = clamp(L - 0.71, 0.0, 1.0);
   8.127 +	
   8.128 +	color.rgb *= T;
   8.129 +	
   8.130 +	gl_FragColor = color;
   8.131 +#endif
   8.132 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/glsl/contrast_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
     9.3 @@ -0,0 +1,31 @@
     9.4 +/*
     9.5 +===========================================================================
     9.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
     9.7 +
     9.8 +This file is part of XreaL source code.
     9.9 +
    9.10 +XreaL source code is free software; you can redistribute it
    9.11 +and/or modify it under the terms of the GNU General Public License as
    9.12 +published by the Free Software Foundation; either version 2 of the License,
    9.13 +or (at your option) any later version.
    9.14 +
    9.15 +XreaL source code is distributed in the hope that it will be
    9.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.18 +GNU General Public License for more details.
    9.19 +
    9.20 +You should have received a copy of the GNU General Public License
    9.21 +along with XreaL source code; if not, write to the Free Software
    9.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    9.23 +===========================================================================
    9.24 +*/
    9.25 +
    9.26 +attribute vec4		attr_Position;
    9.27 +
    9.28 +uniform mat4		u_ModelViewProjectionMatrix;
    9.29 +
    9.30 +void	main()
    9.31 +{
    9.32 +	// transform vertex position into homogenous clip-space
    9.33 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
    9.34 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/glsl/deferredLighting_DBS_omni_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    10.3 @@ -0,0 +1,222 @@
    10.4 +/*
    10.5 +===========================================================================
    10.6 +Copyright (C) 2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    10.7 +
    10.8 +This file is part of XreaL source code.
    10.9 +
   10.10 +XreaL source code is free software; you can redistribute it
   10.11 +and/or modify it under the terms of the GNU General Public License as
   10.12 +published by the Free Software Foundation; either version 2 of the License,
   10.13 +or (at your option) any later version.
   10.14 +
   10.15 +XreaL source code is distributed in the hope that it will be
   10.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.18 +GNU General Public License for more details.
   10.19 +
   10.20 +You should have received a copy of the GNU General Public License
   10.21 +along with XreaL source code; if not, write to the Free Software
   10.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   10.23 +===========================================================================
   10.24 +*/
   10.25 +
   10.26 +uniform sampler2D	u_DiffuseMap;
   10.27 +uniform sampler2D	u_NormalMap;
   10.28 +uniform sampler2D	u_SpecularMap;
   10.29 +uniform sampler2D	u_DepthMap;
   10.30 +uniform sampler2D	u_AttenuationMapXY;
   10.31 +uniform sampler2D	u_AttenuationMapZ;
   10.32 +uniform samplerCube	u_ShadowMap;
   10.33 +uniform vec3		u_ViewOrigin;
   10.34 +uniform vec3		u_LightOrigin;
   10.35 +uniform vec3		u_LightColor;
   10.36 +uniform float		u_LightRadius;
   10.37 +uniform float       u_LightScale;
   10.38 +uniform mat4		u_LightAttenuationMatrix;
   10.39 +#if !defined(GLHW_ATI) && !defined(GLHW_ATI_DX10)
   10.40 +uniform vec4		u_LightFrustum[6];
   10.41 +#endif
   10.42 +uniform int			u_ShadowCompare;
   10.43 +uniform int         u_PortalClipping;
   10.44 +uniform vec4		u_PortalPlane;
   10.45 +uniform mat4		u_UnprojectMatrix;
   10.46 +
   10.47 +void	main()
   10.48 +{
   10.49 +	// calculate the screen texcoord in the 0.0 to 1.0 range
   10.50 +	vec2 st = gl_FragCoord.st * r_FBufScale;
   10.51 +	
   10.52 +	// scale by the screen non-power-of-two-adjust
   10.53 +	st *= r_NPOTScale;
   10.54 +	
   10.55 +	// reconstruct vertex position in world space
   10.56 +	float depth = texture2D(u_DepthMap, st).r;
   10.57 +	vec4 P = u_UnprojectMatrix * vec4(gl_FragCoord.xy, depth, 1.0);
   10.58 +	P.xyz /= P.w;
   10.59 +	
   10.60 +	if(bool(u_PortalClipping))
   10.61 +	{
   10.62 +		float dist = dot(P.xyz, u_PortalPlane.xyz) - u_PortalPlane.w;
   10.63 +		if(dist < 0.0)
   10.64 +		{
   10.65 +			discard;
   10.66 +			return;
   10.67 +		}
   10.68 +	}
   10.69 +	
   10.70 +#if 0
   10.71 +	if(distance(P.xyz, u_LightOrigin) > u_LightRadius)
   10.72 +	{
   10.73 +		// position is outside of light volume
   10.74 +		discard;
   10.75 +		return;
   10.76 +	}
   10.77 +#endif
   10.78 +
   10.79 +#if !defined(GLHW_ATI) && !defined(GLHW_ATI_DX10)
   10.80 +	// make sure that the vertex position is inside the light frustum
   10.81 +	for(int i = 0; i < 6; ++i)
   10.82 +	{
   10.83 +		vec4 plane = u_LightFrustum[i];
   10.84 +
   10.85 +		float dist = dot(P.xyz, plane.xyz) - plane.w;
   10.86 +		if(dist < 0.0)
   10.87 +		{
   10.88 +			discard;
   10.89 +			return;
   10.90 +		}
   10.91 +	}
   10.92 +#endif
   10.93 +
   10.94 +	float shadow = 1.0;
   10.95 +
   10.96 +#if defined(VSM)
   10.97 +	if(bool(u_ShadowCompare))
   10.98 +	{
   10.99 +		// compute incident ray
  10.100 +		vec3 I = P.xyz - u_LightOrigin;
  10.101 +	
  10.102 +		vec4 shadowMoments = textureCube(u_ShadowMap, I);
  10.103 +		
  10.104 +		#if defined(VSM_CLAMP)
  10.105 +		// convert to [-1, 1] vector space
  10.106 +		shadowMoments = 2.0 * (shadowMoments - 0.5);
  10.107 +		#endif
  10.108 +	
  10.109 +		float shadowDistance = shadowMoments.r;
  10.110 +		float shadowDistanceSquared = shadowMoments.a;
  10.111 +		
  10.112 +		const float	SHADOW_BIAS = 0.001;
  10.113 +		float vertexDistance = length(I) / u_LightRadius - SHADOW_BIAS;
  10.114 +	
  10.115 +		// standard shadow map comparison
  10.116 +		shadow = vertexDistance <= shadowDistance ? 1.0 : 0.0;
  10.117 +	
  10.118 +		// variance shadow mapping
  10.119 +		float E_x2 = shadowDistanceSquared;
  10.120 +		float Ex_2 = shadowDistance * shadowDistance;
  10.121 +	
  10.122 +		// AndyTX: VSM_EPSILON is there to avoid some ugly numeric instability with fp16
  10.123 +		float variance = min(max(E_x2 - Ex_2, 0.0) + VSM_EPSILON, 1.0);
  10.124 +	
  10.125 +		float mD = shadowDistance - vertexDistance;
  10.126 +		float mD_2 = mD * mD;
  10.127 +		float p = variance / (variance + mD_2);
  10.128 +	
  10.129 +		#if defined(DEBUG_VSM)
  10.130 +		gl_FragColor.r = DEBUG_VSM & 1 ? variance : 0.0;
  10.131 +		gl_FragColor.g = DEBUG_VSM & 2 ? mD_2 : 0.0;
  10.132 +		gl_FragColor.b = DEBUG_VSM & 4 ? p : 0.0;
  10.133 +		gl_FragColor.a = 1.0;
  10.134 +		return;
  10.135 +		#else
  10.136 +		shadow = max(shadow, p);
  10.137 +		#endif
  10.138 +	}
  10.139 +	
  10.140 +	if(shadow <= 0.0)
  10.141 +	{
  10.142 +		discard;
  10.143 +	}
  10.144 +	else
  10.145 +#elif defined(ESM)
  10.146 +	if(bool(u_ShadowCompare))
  10.147 +	{
  10.148 +		// compute incident ray
  10.149 +		vec3 I = P.xyz - u_LightOrigin;
  10.150 +	
  10.151 +		vec4 shadowMoments = textureCube(u_ShadowMap, I);
  10.152 +		
  10.153 +		const float	SHADOW_BIAS = 0.001;
  10.154 +		float vertexDistance = (length(I) / u_LightRadius) * r_ShadowMapDepthScale;// - SHADOW_BIAS;
  10.155 +		
  10.156 +		float shadowDistance = shadowMoments.a;
  10.157 +		
  10.158 +		// exponential shadow mapping
  10.159 +		shadow = clamp(exp(r_OverDarkeningFactor * (shadowDistance - vertexDistance)), 0.0, 1.0);
  10.160 +		
  10.161 +		#if defined(DEBUG_ESM)
  10.162 +		gl_FragColor.r = DEBUG_ESM & 1 ? shadowDistance : 0.0;
  10.163 +		gl_FragColor.g = DEBUG_ESM & 2 ? -(shadowDistance - vertexDistance) : 0.0;
  10.164 +		gl_FragColor.b = DEBUG_ESM & 4 ? 1.0 - shadow : 0.0;
  10.165 +		gl_FragColor.a = 1.0;
  10.166 +		return;
  10.167 +		#endif
  10.168 +	}
  10.169 +	
  10.170 +	if(shadow <= 0.0)
  10.171 +	{
  10.172 +		discard;
  10.173 +	}
  10.174 +	else
  10.175 +#endif
  10.176 +	{
  10.177 +		// compute the diffuse term
  10.178 +		vec4 diffuse = texture2D(u_DiffuseMap, st);
  10.179 +	
  10.180 +		// compute normal in world space
  10.181 +		vec3 N = 2.0 * (texture2D(u_NormalMap, st).xyz - 0.5);
  10.182 +		
  10.183 +		//vec3 N;
  10.184 +		//N.x = diffuse.a;
  10.185 +		//N.y = S.a;
  10.186 +		//N.z = P.w;
  10.187 +		//N = 2.0 * (N - 0.5);
  10.188 +		//N.z = sqrt(1.0 - dot(N.xy, N.xy));
  10.189 +		//N.z = sqrt(1.0 - N.x*N.x - N.y*N.y);
  10.190 +		//N.x = sqrt(1.0 - N.y*N.y - N.z*N.z);
  10.191 +		//N = normalize(N);
  10.192 +	
  10.193 +		// compute light direction in world space
  10.194 +		vec3 L = normalize(u_LightOrigin - P.xyz);
  10.195 +	
  10.196 +#if defined(r_NormalMapping)
  10.197 +		// compute view direction in world space
  10.198 +		vec3 V = normalize(u_ViewOrigin - P.xyz);
  10.199 +	
  10.200 +		// compute half angle in world space
  10.201 +		vec3 H = normalize(L + V);
  10.202 +		
  10.203 +		// compute the specular term
  10.204 +		vec4 S = texture2D(u_SpecularMap, st);
  10.205 +#endif
  10.206 +	
  10.207 +		// compute attenuation
  10.208 +		vec3 texAttenXYZ		= (u_LightAttenuationMatrix * vec4(P.xyz, 1.0)).xyz;
  10.209 +		vec3 attenuationXY		= texture2D(u_AttenuationMapXY, texAttenXYZ.xy).rgb;
  10.210 +		vec3 attenuationZ		= texture2D(u_AttenuationMapZ, vec2(texAttenXYZ.z, 0)).rgb;
  10.211 +	
  10.212 +		// compute final color
  10.213 +		vec4 color = diffuse;
  10.214 +		color.rgb *= u_LightColor * clamp(dot(N, L), 0.0, 1.0);
  10.215 +#if defined(r_NormalMapping)
  10.216 +		color.rgb += S.rgb * u_LightColor * pow(clamp(dot(N, H), 0.0, 1.0), r_SpecularExponent) * r_SpecularScale;
  10.217 +#endif
  10.218 +		color.rgb *= attenuationXY;
  10.219 +		color.rgb *= attenuationZ;
  10.220 +		color.rgb *= u_LightScale;
  10.221 +		color.rgb *= shadow;
  10.222 +		
  10.223 +		gl_FragColor = color;
  10.224 +	}
  10.225 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/glsl/deferredLighting_DBS_omni_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    11.3 @@ -0,0 +1,31 @@
    11.4 +/*
    11.5 +===========================================================================
    11.6 +Copyright (C) 2007-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    11.7 +
    11.8 +This file is part of XreaL source code.
    11.9 +
   11.10 +XreaL source code is free software; you can redistribute it
   11.11 +and/or modify it under the terms of the GNU General Public License as
   11.12 +published by the Free Software Foundation; either version 2 of the License,
   11.13 +or (at your option) any later version.
   11.14 +
   11.15 +XreaL source code is distributed in the hope that it will be
   11.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.18 +GNU General Public License for more details.
   11.19 +
   11.20 +You should have received a copy of the GNU General Public License
   11.21 +along with XreaL source code; if not, write to the Free Software
   11.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   11.23 +===========================================================================
   11.24 +*/
   11.25 +
   11.26 +attribute vec4		attr_Position;
   11.27 +
   11.28 +uniform mat4		u_ModelViewProjectionMatrix;
   11.29 +
   11.30 +void	main()
   11.31 +{
   11.32 +	// transform vertex position into homogenous clip-space
   11.33 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   11.34 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/glsl/deferredLighting_DBS_proj_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    12.3 @@ -0,0 +1,228 @@
    12.4 +/*
    12.5 +===========================================================================
    12.6 +Copyright (C) 2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    12.7 +
    12.8 +This file is part of XreaL source code.
    12.9 +
   12.10 +XreaL source code is free software; you can redistribute it
   12.11 +and/or modify it under the terms of the GNU General Public License as
   12.12 +published by the Free Software Foundation; either version 2 of the License,
   12.13 +or (at your option) any later version.
   12.14 +
   12.15 +XreaL source code is distributed in the hope that it will be
   12.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   12.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12.18 +GNU General Public License for more details.
   12.19 +
   12.20 +You should have received a copy of the GNU General Public License
   12.21 +along with XreaL source code; if not, write to the Free Software
   12.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   12.23 +===========================================================================
   12.24 +*/
   12.25 +
   12.26 +uniform sampler2D	u_DiffuseMap;
   12.27 +uniform sampler2D	u_NormalMap;
   12.28 +uniform sampler2D	u_SpecularMap;
   12.29 +uniform sampler2D	u_DepthMap;
   12.30 +uniform sampler2D	u_AttenuationMapXY;
   12.31 +uniform sampler2D	u_AttenuationMapZ;
   12.32 +uniform sampler2D	u_ShadowMap;
   12.33 +uniform vec3		u_ViewOrigin;
   12.34 +uniform vec3		u_LightOrigin;
   12.35 +uniform vec3		u_LightColor;
   12.36 +uniform float		u_LightRadius;
   12.37 +uniform float       u_LightScale;
   12.38 +uniform mat4		u_LightAttenuationMatrix;
   12.39 +#if !defined(GLHW_ATI) && !defined(GLHW_ATI_DX10)
   12.40 +uniform vec4		u_LightFrustum[6];
   12.41 +#endif
   12.42 +uniform mat4		u_ShadowMatrix;
   12.43 +uniform int			u_ShadowCompare;
   12.44 +uniform int         u_PortalClipping;
   12.45 +uniform vec4		u_PortalPlane;
   12.46 +uniform mat4		u_UnprojectMatrix;
   12.47 +
   12.48 +void	main()
   12.49 +{
   12.50 +	// calculate the screen texcoord in the 0.0 to 1.0 range
   12.51 +	vec2 st = gl_FragCoord.st * r_FBufScale;
   12.52 +	
   12.53 +	// scale by the screen non-power-of-two-adjust
   12.54 +	st *= r_NPOTScale;
   12.55 +		
   12.56 +	// reconstruct vertex position in world space
   12.57 +	float depth = texture2D(u_DepthMap, st).r;
   12.58 +	vec4 P = u_UnprojectMatrix * vec4(gl_FragCoord.xy, depth, 1.0);
   12.59 +	P.xyz /= P.w;
   12.60 +	
   12.61 +	if(bool(u_PortalClipping))
   12.62 +	{
   12.63 +		float dist = dot(P.xyz, u_PortalPlane.xyz) - u_PortalPlane.w;
   12.64 +		if(dist < 0.0)
   12.65 +		{
   12.66 +			discard;
   12.67 +			return;
   12.68 +		}
   12.69 +	}
   12.70 +	
   12.71 +	// transform vertex position into light space
   12.72 +	vec4 texAtten			= u_LightAttenuationMatrix * vec4(P.xyz, 1.0);
   12.73 +	if(texAtten.q <= 0.0)
   12.74 +	{
   12.75 +		// point is behind the near clip plane
   12.76 +		discard;
   12.77 +		return;
   12.78 +	}
   12.79 +	
   12.80 +#if !defined(GLHW_ATI) && !defined(GLHW_ATI_DX10)
   12.81 +	// make sure that the vertex position is inside the light frustum
   12.82 +	for(int i = 0; i < 6; ++i)
   12.83 +	{
   12.84 +		vec4 plane = u_LightFrustum[i];
   12.85 +
   12.86 +		float dist = dot(P.xyz, plane.xyz) - plane.w;
   12.87 +		if(dist < 0.0)
   12.88 +		{
   12.89 +			discard;
   12.90 +			return;
   12.91 +		}
   12.92 +	}
   12.93 +#endif
   12.94 +
   12.95 +	float shadow = 1.0;
   12.96 +	
   12.97 +#if defined(VSM)
   12.98 +	if(bool(u_ShadowCompare))
   12.99 +	{
  12.100 +		// compute incident ray
  12.101 +		vec3 I = P.xyz - u_LightOrigin;
  12.102 +		
  12.103 +		const float	SHADOW_BIAS = 0.001;
  12.104 +		float vertexDistance = length(I) / u_LightRadius - SHADOW_BIAS;
  12.105 +		
  12.106 +		// no filter
  12.107 +		vec4 texShadow = u_ShadowMatrix * vec4(P.xyz, 1.0);
  12.108 +		vec4 shadowMoments = texture2DProj(u_ShadowMap, texShadow.xyw);
  12.109 +		//vec4 shadowMoments = texture2DProj(u_ShadowMap, SP.xyw);
  12.110 +	
  12.111 +		#if defined(VSM_CLAMP)
  12.112 +		// convert to [-1, 1] vector space
  12.113 +		shadowMoments = 2.0 * (shadowMoments - 0.5);
  12.114 +		#endif
  12.115 +		
  12.116 +		float shadowDistance = shadowMoments.r;
  12.117 +		float shadowDistanceSquared = shadowMoments.a;
  12.118 +	
  12.119 +		// standard shadow map comparison
  12.120 +		shadow = vertexDistance <= shadowDistance ? 1.0 : 0.0;
  12.121 +	
  12.122 +		// variance shadow mapping
  12.123 +		float E_x2 = shadowDistanceSquared;
  12.124 +		float Ex_2 = shadowDistance * shadowDistance;
  12.125 +	
  12.126 +		// AndyTX: VSM_EPSILON is there to avoid some ugly numeric instability with fp16
  12.127 +		float variance = min(max(E_x2 - Ex_2, 0.0) + VSM_EPSILON, 1.0);
  12.128 +		//float variance = smoothstep(VSM_EPSILON, 1.0, max(E_x2 - Ex_2, 0.0));
  12.129 +	
  12.130 +		float mD = shadowDistance - vertexDistance;
  12.131 +		float mD_2 = mD * mD;
  12.132 +		float p = variance / (variance + mD_2);
  12.133 +		p = smoothstep(0.0, 1.0, p);
  12.134 +	
  12.135 +		#if defined(DEBUG_VSM)
  12.136 +		gl_FragColor.r = DEBUG_VSM & 1 ? variance : 0.0;
  12.137 +		gl_FragColor.g = DEBUG_VSM & 2 ? mD_2 : 0.0;
  12.138 +		gl_FragColor.b = DEBUG_VSM & 4 ? p : 0.0;
  12.139 +		gl_FragColor.a = 1.0;
  12.140 +		return;
  12.141 +		#else
  12.142 +		shadow = max(shadow, p);
  12.143 +		#endif
  12.144 +	}
  12.145 +	
  12.146 +	if(shadow <= 0.0)
  12.147 +	{
  12.148 +		discard;
  12.149 +	}
  12.150 +	else
  12.151 +#elif defined(ESM)
  12.152 +	if(bool(u_ShadowCompare))
  12.153 +	{
  12.154 +		// compute incident ray
  12.155 +		vec3 I = P.xyz - u_LightOrigin;
  12.156 +		
  12.157 +		// no filter
  12.158 +		vec4 texShadow = u_ShadowMatrix * vec4(P.xyz, 1.0);
  12.159 +		vec4 shadowMoments = texture2DProj(u_ShadowMap, texShadow.xyw);
  12.160 +		
  12.161 +		const float	SHADOW_BIAS = 0.001;
  12.162 +		float vertexDistance = (length(I) / u_LightRadius) * r_ShadowMapDepthScale; // - SHADOW_BIAS;
  12.163 +		
  12.164 +		float shadowDistance = shadowMoments.a;
  12.165 +		
  12.166 +		// exponential shadow mapping
  12.167 +		//shadow = vertexDistance <= shadowDistance ? 1.0 : 0.0;
  12.168 +		shadow = clamp(exp(r_OverDarkeningFactor * (shadowDistance - vertexDistance)), 0.0, 1.0);
  12.169 +		//shadow = smoothstep(0.0, 1.0, shadow);
  12.170 +		
  12.171 +		#if defined(DEBUG_ESM)
  12.172 +		gl_FragColor.r = DEBUG_ESM & 1 ? shadowDistance : 0.0;
  12.173 +		gl_FragColor.g = DEBUG_ESM & 2 ? -(shadowDistance - vertexDistance) : 0.0;
  12.174 +		gl_FragColor.b = DEBUG_ESM & 4 ? shadow : 0.0;
  12.175 +		gl_FragColor.a = 1.0;
  12.176 +		return;
  12.177 +		#endif
  12.178 +	}
  12.179 +	
  12.180 +	if(shadow <= 0.0)
  12.181 +	{
  12.182 +		discard;
  12.183 +	}
  12.184 +	else
  12.185 +#endif
  12.186 +	{
  12.187 +		// compute the diffuse term
  12.188 +		vec4 diffuse = texture2D(u_DiffuseMap, st);
  12.189 +	
  12.190 +		// compute normal in world space
  12.191 +		vec3 N = 2.0 * (texture2D(u_NormalMap, st).xyz - 0.5);
  12.192 +		
  12.193 +		//vec3 N;
  12.194 +		//N.x = diffuse.a;
  12.195 +		//N.y = S.a;
  12.196 +		//N.z = P.w;
  12.197 +		//N.xyz = 2.0 * (N.xyz - 0.5);
  12.198 +		//N.z = sqrt(1.0 - dot(N.xy, N.xy));
  12.199 +	
  12.200 +		// compute light direction in world space
  12.201 +		vec3 L = normalize(u_LightOrigin - P.xyz);
  12.202 +	
  12.203 +#if defined(r_NormalMapping)
  12.204 +		// compute view direction in world space
  12.205 +		vec3 V = normalize(u_ViewOrigin - P.xyz);
  12.206 +	
  12.207 +		// compute half angle in world space
  12.208 +		vec3 H = normalize(L + V);
  12.209 +		
  12.210 +		// compute the specular term
  12.211 +		vec4 S = texture2D(u_SpecularMap, st);
  12.212 +#endif
  12.213 +	
  12.214 +		// compute attenuation
  12.215 +		vec3 attenuationXY = texture2DProj(u_AttenuationMapXY, texAtten.xyw).rgb;
  12.216 +		vec3 attenuationZ  = texture2D(u_AttenuationMapZ, vec2(clamp(texAtten.z, 0.0, 1.0), 0.0)).rgb;
  12.217 +	
  12.218 +		// compute final color
  12.219 +		vec4 color = diffuse;
  12.220 +		color.rgb *= u_LightColor * clamp(dot(N, L), 0.0, 1.0);
  12.221 +#if defined(r_NormalMapping)
  12.222 +		color.rgb += S.rgb * u_LightColor * pow(clamp(dot(N, H), 0.0, 1.0), r_SpecularExponent) * r_SpecularScale;
  12.223 +#endif
  12.224 +		color.rgb *= attenuationXY;
  12.225 +		color.rgb *= attenuationZ;
  12.226 +		color.rgb *= u_LightScale;
  12.227 +		color.rgb *= shadow;
  12.228 +		
  12.229 +		gl_FragColor = color;
  12.230 +	}
  12.231 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/glsl/deferredLighting_DBS_proj_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    13.3 @@ -0,0 +1,31 @@
    13.4 +/*
    13.5 +===========================================================================
    13.6 +Copyright (C) 2007-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    13.7 +
    13.8 +This file is part of XreaL source code.
    13.9 +
   13.10 +XreaL source code is free software; you can redistribute it
   13.11 +and/or modify it under the terms of the GNU General Public License as
   13.12 +published by the Free Software Foundation; either version 2 of the License,
   13.13 +or (at your option) any later version.
   13.14 +
   13.15 +XreaL source code is distributed in the hope that it will be
   13.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   13.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13.18 +GNU General Public License for more details.
   13.19 +
   13.20 +You should have received a copy of the GNU General Public License
   13.21 +along with XreaL source code; if not, write to the Free Software
   13.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   13.23 +===========================================================================
   13.24 +*/
   13.25 +
   13.26 +attribute vec4		attr_Position;
   13.27 +
   13.28 +uniform mat4		u_ModelViewProjectionMatrix;
   13.29 +
   13.30 +void	main()
   13.31 +{
   13.32 +	// transform vertex position into homogenous clip-space
   13.33 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   13.34 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/glsl/deferredShadowing_proj_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    14.3 @@ -0,0 +1,200 @@
    14.4 +/*
    14.5 +===========================================================================
    14.6 +Copyright (C) 2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    14.7 +
    14.8 +This file is part of XreaL source code.
    14.9 +
   14.10 +XreaL source code is free software; you can redistribute it
   14.11 +and/or modify it under the terms of the GNU General Public License as
   14.12 +published by the Free Software Foundation; either version 2 of the License,
   14.13 +or (at your option) any later version.
   14.14 +
   14.15 +XreaL source code is distributed in the hope that it will be
   14.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   14.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14.18 +GNU General Public License for more details.
   14.19 +
   14.20 +You should have received a copy of the GNU General Public License
   14.21 +along with XreaL source code; if not, write to the Free Software
   14.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   14.23 +===========================================================================
   14.24 +*/
   14.25 +
   14.26 +uniform sampler2D	u_DepthMap;
   14.27 +uniform sampler2D	u_AttenuationMapXY;
   14.28 +uniform sampler2D	u_AttenuationMapZ;
   14.29 +uniform sampler2D	u_ShadowMap;
   14.30 +uniform vec3		u_ViewOrigin;
   14.31 +uniform vec3		u_LightOrigin;
   14.32 +uniform vec3		u_LightColor;
   14.33 +uniform float		u_LightRadius;
   14.34 +uniform mat4		u_LightAttenuationMatrix;
   14.35 +#if !defined(GLHW_ATI) && !defined(GLHW_ATI_DX10)
   14.36 +uniform vec4		u_LightFrustum[6];
   14.37 +#endif
   14.38 +uniform mat4		u_ShadowMatrix;
   14.39 +uniform int			u_ShadowCompare;
   14.40 +uniform int         u_PortalClipping;
   14.41 +uniform vec4		u_PortalPlane;
   14.42 +uniform mat4		u_UnprojectMatrix;
   14.43 +
   14.44 +void	main()
   14.45 +{
   14.46 +	// calculate the screen texcoord in the 0.0 to 1.0 range
   14.47 +	vec2 st = gl_FragCoord.st * r_FBufScale;
   14.48 +	
   14.49 +	// scale by the screen non-power-of-two-adjust
   14.50 +	st *= r_NPOTScale;
   14.51 +		
   14.52 +	// reconstruct vertex position in world space
   14.53 +	float depth = texture2D(u_DepthMap, st).r;
   14.54 +	vec4 P = u_UnprojectMatrix * vec4(gl_FragCoord.xy, depth, 1.0);
   14.55 +	P.xyz /= P.w;
   14.56 +	
   14.57 +	if(bool(u_PortalClipping))
   14.58 +	{
   14.59 +		float dist = dot(P.xyz, u_PortalPlane.xyz) - u_PortalPlane.w;
   14.60 +		if(dist < 0.0)
   14.61 +		{
   14.62 +			discard;
   14.63 +			return;
   14.64 +		}
   14.65 +	}
   14.66 +	
   14.67 +	// transform vertex position into light space
   14.68 +	vec4 texAtten			= u_LightAttenuationMatrix * vec4(P.xyz, 1.0);
   14.69 +	if(texAtten.q <= 0.0)
   14.70 +	{
   14.71 +		// point is behind the near clip plane
   14.72 +		discard;
   14.73 +		return;
   14.74 +	}
   14.75 +	
   14.76 +#if !defined(GLHW_ATI) && !defined(GLHW_ATI_DX10)
   14.77 +	// make sure that the vertex position is inside the light frustum
   14.78 +	for(int i = 0; i < 6; ++i)
   14.79 +	{
   14.80 +		vec4 plane = u_LightFrustum[i];
   14.81 +
   14.82 +		float dist = dot(P.xyz, plane.xyz) - plane.w;
   14.83 +		if(dist < 0.0)
   14.84 +		{
   14.85 +			discard;
   14.86 +			return;
   14.87 +		}
   14.88 +	}
   14.89 +#endif
   14.90 +
   14.91 +	float shadow = 1.0;
   14.92 +	
   14.93 +#if defined(VSM)
   14.94 +	if(bool(u_ShadowCompare))
   14.95 +	{
   14.96 +		// compute incident ray
   14.97 +		vec3 I = P.xyz - u_LightOrigin;
   14.98 +		
   14.99 +		const float	SHADOW_BIAS = 0.001;
  14.100 +		float vertexDistance = length(I) / u_LightRadius - SHADOW_BIAS;
  14.101 +		
  14.102 +		// no filter
  14.103 +		vec4 texShadow = u_ShadowMatrix * vec4(P.xyz, 1.0);
  14.104 +		vec4 shadowMoments = texture2DProj(u_ShadowMap, texShadow.xyw);
  14.105 +		//vec4 shadowMoments = texture2DProj(u_ShadowMap, SP.xyw);
  14.106 +	
  14.107 +		#if defined(VSM_CLAMP)
  14.108 +		// convert to [-1, 1] vector space
  14.109 +		shadowMoments = 2.0 * (shadowMoments - 0.5);
  14.110 +		#endif
  14.111 +		
  14.112 +		float shadowDistance = shadowMoments.r;
  14.113 +		float shadowDistanceSquared = shadowMoments.a;
  14.114 +	
  14.115 +		// standard shadow map comparison
  14.116 +		shadow = vertexDistance <= shadowDistance ? 1.0 : 0.0;
  14.117 +	
  14.118 +		// variance shadow mapping
  14.119 +		float E_x2 = shadowDistanceSquared;
  14.120 +		float Ex_2 = shadowDistance * shadowDistance;
  14.121 +	
  14.122 +		// AndyTX: VSM_EPSILON is there to avoid some ugly numeric instability with fp16
  14.123 +		float variance = min(max(E_x2 - Ex_2, 0.0) + VSM_EPSILON, 1.0);
  14.124 +		//float variance = smoothstep(VSM_EPSILON, 1.0, max(E_x2 - Ex_2, 0.0));
  14.125 +	
  14.126 +		float mD = shadowDistance - vertexDistance;
  14.127 +		float mD_2 = mD * mD;
  14.128 +		float p = variance / (variance + mD_2);
  14.129 +		p = smoothstep(0.0, 1.0, p);
  14.130 +	
  14.131 +		#if defined(DEBUG_VSM)
  14.132 +		gl_FragColor.r = DEBUG_VSM & 1 ? variance : 0.0;
  14.133 +		gl_FragColor.g = DEBUG_VSM & 2 ? mD_2 : 0.0;
  14.134 +		gl_FragColor.b = DEBUG_VSM & 4 ? p : 0.0;
  14.135 +		gl_FragColor.a = 1.0;
  14.136 +		return;
  14.137 +		#else
  14.138 +		shadow = max(shadow, p);
  14.139 +		#endif
  14.140 +		
  14.141 +		shadow = clamp(shadow, 0.0, 1.0);
  14.142 +		shadow = 1.0 - shadow;
  14.143 +	}
  14.144 +	
  14.145 +	if(shadow <= 0.0)
  14.146 +	{
  14.147 +		discard;
  14.148 +	}
  14.149 +	else
  14.150 +#elif defined(ESM)
  14.151 +	if(bool(u_ShadowCompare))
  14.152 +	{
  14.153 +		// compute incident ray
  14.154 +		vec3 I = P.xyz - u_LightOrigin;
  14.155 +		
  14.156 +		// no filter
  14.157 +		vec4 texShadow = u_ShadowMatrix * vec4(P.xyz, 1.0);
  14.158 +		vec4 shadowMoments = texture2DProj(u_ShadowMap, texShadow.xyw);
  14.159 +		
  14.160 +		const float	SHADOW_BIAS = 0.001;
  14.161 +		float vertexDistance = (length(I) / u_LightRadius) * r_ShadowMapDepthScale; // - SHADOW_BIAS;
  14.162 +		
  14.163 +		float shadowDistance = shadowMoments.a;
  14.164 +		
  14.165 +		// exponential shadow mapping
  14.166 +		//shadow = vertexDistance <= shadowDistance ? 1.0 : 0.0;
  14.167 +		shadow = clamp(exp(r_OverDarkeningFactor * (shadowDistance - vertexDistance)), 0.0, 1.0);
  14.168 +		//shadow = smoothstep(0.0, 1.0, shadow);
  14.169 +		
  14.170 +		shadow = clamp(shadow, 0.0, 1.0);
  14.171 +		shadow = 1.0 - shadow;
  14.172 +		
  14.173 +		#if defined(DEBUG_ESM)
  14.174 +		gl_FragColor.r = DEBUG_ESM & 1 ? shadowDistance : 0.0;
  14.175 +		gl_FragColor.g = DEBUG_ESM & 2 ? -(shadowDistance - vertexDistance) : 0.0;
  14.176 +		gl_FragColor.b = DEBUG_ESM & 4 ? shadow : 0.0;
  14.177 +		gl_FragColor.a = 1.0;
  14.178 +		return;
  14.179 +		#endif
  14.180 +	}
  14.181 +	
  14.182 +	if(shadow <= 0.0)
  14.183 +	{
  14.184 +		discard;
  14.185 +	}
  14.186 +	else
  14.187 +#endif
  14.188 +	{
  14.189 +		// compute attenuation
  14.190 +		vec3 attenuationXY = texture2DProj(u_AttenuationMapXY, texAtten.xyw).rgb;
  14.191 +		vec3 attenuationZ  = texture2D(u_AttenuationMapZ, vec2(clamp(texAtten.z, 0.0, 1.0), 0.0)).rgb;
  14.192 +	
  14.193 +		// compute final color
  14.194 +		vec4 color = vec4(1.0, 1.0, 1.0, 1.0);
  14.195 +		color.rgb *= u_LightColor;
  14.196 +		//color.rgb *= attenuationXY;
  14.197 +		//color.rgb *= attenuationZ;
  14.198 +		color.rgb *= shadow;
  14.199 +		color.rgb *= 1.0 - clamp(distance(P.xyz, u_LightOrigin) / (u_LightRadius * 0.7), 0.0, 1.0);
  14.200 +		
  14.201 +		gl_FragColor = color;
  14.202 +	}
  14.203 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/glsl/deferredShadowing_proj_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    15.3 @@ -0,0 +1,31 @@
    15.4 +/*
    15.5 +===========================================================================
    15.6 +Copyright (C) 2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    15.7 +
    15.8 +This file is part of XreaL source code.
    15.9 +
   15.10 +XreaL source code is free software; you can redistribute it
   15.11 +and/or modify it under the terms of the GNU General Public License as
   15.12 +published by the Free Software Foundation; either version 2 of the License,
   15.13 +or (at your option) any later version.
   15.14 +
   15.15 +XreaL source code is distributed in the hope that it will be
   15.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   15.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15.18 +GNU General Public License for more details.
   15.19 +
   15.20 +You should have received a copy of the GNU General Public License
   15.21 +along with XreaL source code; if not, write to the Free Software
   15.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   15.23 +===========================================================================
   15.24 +*/
   15.25 +
   15.26 +attribute vec4		attr_Position;
   15.27 +
   15.28 +uniform mat4		u_ModelViewProjectionMatrix;
   15.29 +
   15.30 +void	main()
   15.31 +{
   15.32 +	// transform vertex position into homogenous clip-space
   15.33 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   15.34 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/glsl/deluxeMapping_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    16.3 @@ -0,0 +1,203 @@
    16.4 +/*
    16.5 +===========================================================================
    16.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    16.7 +
    16.8 +This file is part of XreaL source code.
    16.9 +
   16.10 +XreaL source code is free software; you can redistribute it
   16.11 +and/or modify it under the terms of the GNU General Public License as
   16.12 +published by the Free Software Foundation; either version 2 of the License,
   16.13 +or (at your option) any later version.
   16.14 +
   16.15 +XreaL source code is distributed in the hope that it will be
   16.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   16.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16.18 +GNU General Public License for more details.
   16.19 +
   16.20 +You should have received a copy of the GNU General Public License
   16.21 +along with XreaL source code; if not, write to the Free Software
   16.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   16.23 +===========================================================================
   16.24 +*/
   16.25 +
   16.26 +uniform sampler2D	u_DiffuseMap;
   16.27 +uniform sampler2D	u_NormalMap;
   16.28 +uniform sampler2D	u_SpecularMap;
   16.29 +uniform sampler2D	u_LightMap;
   16.30 +uniform sampler2D	u_DeluxeMap;
   16.31 +uniform int			u_AlphaTest;
   16.32 +uniform vec3		u_ViewOrigin;
   16.33 +uniform int			u_ParallaxMapping;
   16.34 +uniform float		u_DepthScale;
   16.35 +uniform int         u_PortalClipping;
   16.36 +uniform vec4		u_PortalPlane;
   16.37 +
   16.38 +varying vec3		var_Position;
   16.39 +varying vec2		var_TexDiffuse;
   16.40 +varying vec2		var_TexNormal;
   16.41 +varying vec2		var_TexSpecular;
   16.42 +varying vec2		var_TexLight;
   16.43 +varying vec3		var_Tangent;
   16.44 +varying vec3		var_Binormal;
   16.45 +varying vec3		var_Normal;
   16.46 +
   16.47 +
   16.48 +#if defined(r_ParallaxMapping)
   16.49 +float RayIntersectDisplaceMap(vec2 dp, vec2 ds)
   16.50 +{
   16.51 +	const int linearSearchSteps = 16;
   16.52 +	const int binarySearchSteps = 6;
   16.53 +
   16.54 +	float depthStep = 1.0 / float(linearSearchSteps);
   16.55 +
   16.56 +	// current size of search window
   16.57 +	float size = depthStep;
   16.58 +
   16.59 +	// current depth position
   16.60 +	float depth = 0.0;
   16.61 +
   16.62 +	// best match found (starts with last position 1.0)
   16.63 +	float bestDepth = 1.0;
   16.64 +
   16.65 +	// search front to back for first point inside object
   16.66 +	for(int i = 0; i < linearSearchSteps - 1; ++i)
   16.67 +	{
   16.68 +		depth += size;
   16.69 +		
   16.70 +		vec4 t = texture2D(u_NormalMap, dp + ds * depth);
   16.71 +
   16.72 +		if(bestDepth > 0.996)		// if no depth found yet
   16.73 +			if(depth >= t.w)
   16.74 +				bestDepth = depth;	// store best depth
   16.75 +	}
   16.76 +
   16.77 +	depth = bestDepth;
   16.78 +	
   16.79 +	// recurse around first point (depth) for closest match
   16.80 +	for(int i = 0; i < binarySearchSteps; ++i)
   16.81 +	{
   16.82 +		size *= 0.5;
   16.83 +
   16.84 +		vec4 t = texture2D(u_NormalMap, dp + ds * depth);
   16.85 +		
   16.86 +		if(depth >= t.w)
   16.87 +		#ifdef RM_DOUBLEDEPTH
   16.88 +			if(depth <= t.z)
   16.89 +		#endif
   16.90 +			{
   16.91 +				bestDepth = depth;
   16.92 +				depth -= 2.0 * size;
   16.93 +			}
   16.94 +
   16.95 +		depth += size;
   16.96 +	}
   16.97 +
   16.98 +	return bestDepth;
   16.99 +}
  16.100 +#endif
  16.101 +
  16.102 +
  16.103 +void	main()
  16.104 +{
  16.105 +	if(bool(u_PortalClipping))
  16.106 +	{
  16.107 +		float dist = dot(var_Position.xyz, u_PortalPlane.xyz) - u_PortalPlane.w;
  16.108 +		if(dist < 0.0)
  16.109 +		{
  16.110 +			discard;
  16.111 +			return;
  16.112 +		}
  16.113 +	}
  16.114 +
  16.115 +#if defined(r_showLightMaps)
  16.116 +	gl_FragColor = texture2D(u_LightMap, var_TexLight);
  16.117 +#elif defined(r_showDeluxeMaps)
  16.118 +	gl_FragColor = texture2D(u_DeluxeMap, var_TexLight);
  16.119 +#else
  16.120 +
  16.121 +	// invert tangent space for two sided surfaces
  16.122 +	mat3 tangentToWorldMatrix;
  16.123 +	if(gl_FrontFacing)
  16.124 +		tangentToWorldMatrix = mat3(-var_Tangent.xyz, -var_Binormal.xyz, -var_Normal.xyz);
  16.125 +	else
  16.126 +		tangentToWorldMatrix = mat3(var_Tangent.xyz, var_Binormal.xyz, var_Normal.xyz);
  16.127 +	
  16.128 +	// compute view direction in world space
  16.129 +	vec3 I = normalize(u_ViewOrigin - var_Position);
  16.130 +	
  16.131 +	vec2 texDiffuse = var_TexDiffuse.st;
  16.132 +	vec2 texNormal = var_TexNormal.st;
  16.133 +	vec2 texSpecular = var_TexSpecular.st;
  16.134 +
  16.135 +#if defined(r_ParallaxMapping)
  16.136 +	if(bool(u_ParallaxMapping))
  16.137 +	{
  16.138 +		// ray intersect in view direction
  16.139 +		
  16.140 +		mat3 worldToTangentMatrix;
  16.141 +		#if defined(GLHW_ATI) || defined(GLHW_ATI_DX10)
  16.142 +		worldToTangentMatrix = mat3(tangentToWorldMatrix[0][0], tangentToWorldMatrix[1][0], tangentToWorldMatrix[2][0],
  16.143 +									tangentToWorldMatrix[0][1], tangentToWorldMatrix[1][1], tangentToWorldMatrix[2][1], 
  16.144 +									tangentToWorldMatrix[0][2], tangentToWorldMatrix[1][2], tangentToWorldMatrix[2][2]);
  16.145 +		#else
  16.146 +		worldToTangentMatrix = transpose(tangentToWorldMatrix);
  16.147 +		#endif
  16.148 +	
  16.149 +		// compute view direction in tangent space
  16.150 +		vec3 V = worldToTangentMatrix * (u_ViewOrigin - var_Position.xyz);
  16.151 +		V = normalize(V);
  16.152 +		
  16.153 +		// size and start position of search in texture space
  16.154 +		vec2 S = V.xy * -u_DepthScale / V.z;
  16.155 +			
  16.156 +		float depth = RayIntersectDisplaceMap(texNormal, S);
  16.157 +		
  16.158 +		// compute texcoords offset
  16.159 +		vec2 texOffset = S * depth;
  16.160 +		
  16.161 +		texDiffuse.st += texOffset;
  16.162 +		texNormal.st += texOffset;
  16.163 +		texSpecular.st += texOffset;
  16.164 +	}
  16.165 +#endif
  16.166 +
  16.167 +	// compute the diffuse term
  16.168 +	vec4 diffuse = texture2D(u_DiffuseMap, texDiffuse);
  16.169 +	if(u_AlphaTest == ATEST_GT_0 && diffuse.a <= 0.0)
  16.170 +	{
  16.171 +		discard;
  16.172 +		return;
  16.173 +	}
  16.174 +	else if(u_AlphaTest == ATEST_LT_128 && diffuse.a >= 0.5)
  16.175 +	{
  16.176 +		discard;
  16.177 +		return;
  16.178 +	}
  16.179 +	else if(u_AlphaTest == ATEST_GE_128 && diffuse.a < 0.5)
  16.180 +	{
  16.181 +		discard;
  16.182 +		return;
  16.183 +	}
  16.184 +
  16.185 +	// compute normal in world space from normalmap
  16.186 +	vec3 N = tangentToWorldMatrix * (2.0 * (texture2D(u_NormalMap, texNormal).xyz - 0.5));
  16.187 +	
  16.188 +	// compute light direction in world space
  16.189 +	vec3 L = 2.0 * (texture2D(u_DeluxeMap, var_TexLight).xyz - 0.5);
  16.190 +	
  16.191 +	// compute half angle in world space
  16.192 +	vec3 H = normalize(L + I);
  16.193 +	
  16.194 +	// compute light color from world space lightmap
  16.195 +	vec3 lightColor = texture2D(u_LightMap, var_TexLight).rgb;
  16.196 +	
  16.197 +	diffuse.rgb *= lightColor.rgb * clamp(dot(N, L), 0.0, 1.0);
  16.198 +	
  16.199 +	// compute the specular term
  16.200 +	vec3 specular = texture2D(u_SpecularMap, texSpecular).rgb * lightColor * pow(clamp(dot(N, H), 0.0, 1.0), r_SpecularExponent) * r_SpecularScale;
  16.201 +	
  16.202 +	// compute final color
  16.203 +	gl_FragColor.rgba = diffuse;
  16.204 +	gl_FragColor.rgb += specular;
  16.205 +#endif
  16.206 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/glsl/deluxeMapping_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    17.3 @@ -0,0 +1,68 @@
    17.4 +/*
    17.5 +===========================================================================
    17.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    17.7 +
    17.8 +This file is part of XreaL source code.
    17.9 +
   17.10 +XreaL source code is free software; you can redistribute it
   17.11 +and/or modify it under the terms of the GNU General Public License as
   17.12 +published by the Free Software Foundation; either version 2 of the License,
   17.13 +or (at your option) any later version.
   17.14 +
   17.15 +XreaL source code is distributed in the hope that it will be
   17.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   17.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17.18 +GNU General Public License for more details.
   17.19 +
   17.20 +You should have received a copy of the GNU General Public License
   17.21 +along with XreaL source code; if not, write to the Free Software
   17.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   17.23 +===========================================================================
   17.24 +*/
   17.25 +
   17.26 +attribute vec4		attr_Position;
   17.27 +attribute vec4		attr_TexCoord0;
   17.28 +attribute vec4		attr_TexCoord1;
   17.29 +attribute vec3		attr_Tangent;
   17.30 +attribute vec3		attr_Binormal;
   17.31 +attribute vec3		attr_Normal;
   17.32 +
   17.33 +uniform mat4		u_DiffuseTextureMatrix;
   17.34 +uniform mat4		u_NormalTextureMatrix;
   17.35 +uniform mat4		u_SpecularTextureMatrix;
   17.36 +uniform mat4		u_ModelMatrix;
   17.37 +uniform mat4		u_ModelViewProjectionMatrix;
   17.38 +
   17.39 +varying vec3		var_Position;
   17.40 +varying vec2		var_TexDiffuse;
   17.41 +varying vec2		var_TexNormal;
   17.42 +varying vec2		var_TexSpecular;
   17.43 +varying vec2		var_TexLight;
   17.44 +varying vec3		var_Tangent;
   17.45 +varying vec3		var_Binormal;
   17.46 +varying vec3		var_Normal;
   17.47 +
   17.48 +void	main()
   17.49 +{
   17.50 +	// transform vertex position into homogenous clip-space
   17.51 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   17.52 +	
   17.53 +	// transform position into world space
   17.54 +	var_Position = (u_ModelMatrix * attr_Position).xyz;
   17.55 +	
   17.56 +	// transform diffusemap texcoords
   17.57 +	var_TexDiffuse = (u_DiffuseTextureMatrix * attr_TexCoord0).st;
   17.58 +	
   17.59 +	// transform normalmap texcoords
   17.60 +	var_TexNormal = (u_NormalTextureMatrix * attr_TexCoord0).st;
   17.61 +	
   17.62 +	// transform specularmap texcoords
   17.63 +	var_TexSpecular = (u_SpecularTextureMatrix * attr_TexCoord0).st;
   17.64 +	
   17.65 +	// transform lightmap texcoords
   17.66 +	var_TexLight = attr_TexCoord1.st;
   17.67 +	
   17.68 +	var_Tangent.xyz = (u_ModelMatrix * vec4(attr_Tangent, 0.0)).xyz;
   17.69 +	var_Binormal.xyz = (u_ModelMatrix * vec4(attr_Binormal, 0.0)).xyz;
   17.70 +	var_Normal.xyz = (u_ModelMatrix * vec4(attr_Normal, 0.0)).xyz;
   17.71 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/glsl/depthFill_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    18.3 @@ -0,0 +1,51 @@
    18.4 +/*
    18.5 +===========================================================================
    18.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    18.7 +
    18.8 +This file is part of XreaL source code.
    18.9 +
   18.10 +XreaL source code is free software; you can redistribute it
   18.11 +and/or modify it under the terms of the GNU General Public License as
   18.12 +published by the Free Software Foundation; either version 2 of the License,
   18.13 +or (at your option) any later version.
   18.14 +
   18.15 +XreaL source code is distributed in the hope that it will be
   18.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   18.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18.18 +GNU General Public License for more details.
   18.19 +
   18.20 +You should have received a copy of the GNU General Public License
   18.21 +along with XreaL source code; if not, write to the Free Software
   18.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   18.23 +===========================================================================
   18.24 +*/
   18.25 +
   18.26 +uniform sampler2D	u_ColorMap;
   18.27 +uniform int			u_AlphaTest;
   18.28 +
   18.29 +varying vec2		var_Tex;
   18.30 +varying vec4		var_Color;
   18.31 +
   18.32 +void	main()
   18.33 +{
   18.34 +	vec4 color = texture2D(u_ColorMap, var_Tex);
   18.35 +	
   18.36 +	if(u_AlphaTest == ATEST_GT_0 && color.a <= 0.0)
   18.37 +	{
   18.38 +		discard;
   18.39 +		return;
   18.40 +	}
   18.41 +	else if(u_AlphaTest == ATEST_LT_128 && color.a >= 0.5)
   18.42 +	{
   18.43 +		discard;
   18.44 +		return;
   18.45 +	}
   18.46 +	else if(u_AlphaTest == ATEST_GE_128 && color.a < 0.5)
   18.47 +	{
   18.48 +		discard;
   18.49 +		return;
   18.50 +	}
   18.51 +
   18.52 +	color *= var_Color;
   18.53 +	gl_FragColor = color;
   18.54 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/glsl/depthFill_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    19.3 @@ -0,0 +1,75 @@
    19.4 +/*
    19.5 +===========================================================================
    19.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    19.7 +
    19.8 +This file is part of XreaL source code.
    19.9 +
   19.10 +XreaL source code is free software; you can redistribute it
   19.11 +and/or modify it under the terms of the GNU General Public License as
   19.12 +published by the Free Software Foundation; either version 2 of the License,
   19.13 +or (at your option) any later version.
   19.14 +
   19.15 +XreaL source code is distributed in the hope that it will be
   19.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   19.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19.18 +GNU General Public License for more details.
   19.19 +
   19.20 +You should have received a copy of the GNU General Public License
   19.21 +along with XreaL source code; if not, write to the Free Software
   19.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   19.23 +===========================================================================
   19.24 +*/
   19.25 +
   19.26 +attribute vec4		attr_Position;
   19.27 +attribute vec4		attr_TexCoord0;
   19.28 +attribute vec4		attr_Color;
   19.29 +#if defined(r_VertexSkinning)
   19.30 +attribute vec4		attr_BoneIndexes;
   19.31 +attribute vec4		attr_BoneWeights;
   19.32 +uniform int			u_VertexSkinning;
   19.33 +uniform mat4		u_BoneMatrix[MAX_GLSL_BONES];
   19.34 +#endif
   19.35 +
   19.36 +uniform mat4		u_ColorTextureMatrix;
   19.37 +uniform vec3        u_AmbientColor;
   19.38 +uniform mat4		u_ModelViewProjectionMatrix;
   19.39 +
   19.40 +varying vec2		var_Tex;
   19.41 +varying vec4		var_Color;
   19.42 +
   19.43 +void	main()
   19.44 +{
   19.45 +#if defined(r_VertexSkinning)
   19.46 +	if(bool(u_VertexSkinning))
   19.47 +	{
   19.48 +		vec4 vertex = vec4(0.0);
   19.49 +		
   19.50 +		for(int i = 0; i < 4; i++)
   19.51 +		{
   19.52 +			int boneIndex = int(attr_BoneIndexes[i]);
   19.53 +			float boneWeight = attr_BoneWeights[i];
   19.54 +			mat4  boneMatrix = u_BoneMatrix[boneIndex];
   19.55 +			
   19.56 +			vertex += (boneMatrix * attr_Position) * boneWeight;
   19.57 +		}
   19.58 +
   19.59 +		// transform vertex position into homogenous clip-space
   19.60 +		gl_Position = u_ModelViewProjectionMatrix * vertex;
   19.61 +	}
   19.62 +	else
   19.63 +#endif
   19.64 +	{
   19.65 +		// transform vertex position into homogenous clip-space
   19.66 +		gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   19.67 +	}
   19.68 +	
   19.69 +	// transform texcoords
   19.70 +	var_Tex = (u_ColorTextureMatrix * attr_TexCoord0).st;
   19.71 +	
   19.72 +#if defined(r_precomputedLighting)
   19.73 +	// assign color
   19.74 +	var_Color = attr_Color;
   19.75 +#else
   19.76 +	var_Color = vec4(u_AmbientColor, 1.0);
   19.77 +#endif
   19.78 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/glsl/depthOfField_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    20.3 @@ -0,0 +1,61 @@
    20.4 +/*
    20.5 +===========================================================================
    20.6 +Copyright (C) 2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    20.7 +
    20.8 +This file is part of XreaL source code.
    20.9 +
   20.10 +XreaL source code is free software; you can redistribute it
   20.11 +and/or modify it under the terms of the GNU General Public License as
   20.12 +published by the Free Software Foundation; either version 2 of the License,
   20.13 +or (at your option) any later version.
   20.14 +
   20.15 +XreaL source code is distributed in the hope that it will be
   20.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   20.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20.18 +GNU General Public License for more details.
   20.19 +
   20.20 +You should have received a copy of the GNU General Public License
   20.21 +along with XreaL source code; if not, write to the Free Software
   20.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   20.23 +===========================================================================
   20.24 +*/
   20.25 +
   20.26 +uniform sampler2D	u_CurrentMap;
   20.27 +uniform sampler2D	u_DepthMap;
   20.28 +
   20.29 +void	main()
   20.30 +{
   20.31 +	// calculate the screen texcoord in the 0.0 to 1.0 range
   20.32 +	vec2 st = gl_FragCoord.st * r_FBufScale;
   20.33 +	
   20.34 +	// scale by the screen non-power-of-two-adjust
   20.35 +	st *= r_NPOTScale;
   20.36 +
   20.37 +	float focus = 0.98;			// focal distance, normalized 0.8-0.999
   20.38 +	float radius = 0.5;	  	// 0 - 20.0
   20.39 +	
   20.40 +	vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
   20.41 +
   20.42 +	// autofocus
   20.43 +	focus = texture2D(u_DepthMap, vec2(0.5, 0.5) * r_NPOTScale).r;
   20.44 +	
   20.45 +	const float tap = 5.0;
   20.46 +	const float taps = tap * 2.0 + 1.0;
   20.47 +	
   20.48 +	float depth = texture2D(u_DepthMap, st).r;
   20.49 +	float delta = (abs(depth - focus) * abs(depth - focus)) / float(tap);
   20.50 +	delta *= radius;
   20.51 +	//delta = clamp(radius * delta, -max, max);
   20.52 +	
   20.53 +	for(float i = -tap; i < tap; i++)
   20.54 +    {
   20.55 +	    for(float j = -tap; j < tap; j++)
   20.56 +	    {
   20.57 +			sum += texture2D(u_CurrentMap, st + vec2(i, j) * delta);
   20.58 +		}
   20.59 +	}
   20.60 +	
   20.61 +	sum *=  1.0 / (taps * taps);
   20.62 +	
   20.63 +	gl_FragColor = sum;
   20.64 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/glsl/depthOfField_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    21.3 @@ -0,0 +1,31 @@
    21.4 +/*
    21.5 +===========================================================================
    21.6 +Copyright (C) 2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    21.7 +
    21.8 +This file is part of XreaL source code.
    21.9 +
   21.10 +XreaL source code is free software; you can redistribute it
   21.11 +and/or modify it under the terms of the GNU General Public License as
   21.12 +published by the Free Software Foundation; either version 2 of the License,
   21.13 +or (at your option) any later version.
   21.14 +
   21.15 +XreaL source code is distributed in the hope that it will be
   21.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   21.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   21.18 +GNU General Public License for more details.
   21.19 +
   21.20 +You should have received a copy of the GNU General Public License
   21.21 +along with XreaL source code; if not, write to the Free Software
   21.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   21.23 +===========================================================================
   21.24 +*/
   21.25 +
   21.26 +attribute vec4		attr_Position;
   21.27 +
   21.28 +uniform mat4		u_ModelViewProjectionMatrix;
   21.29 +
   21.30 +void	main()
   21.31 +{
   21.32 +	// transform vertex position into homogenous clip-space
   21.33 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   21.34 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/glsl/depthTest_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    22.3 @@ -0,0 +1,39 @@
    22.4 +/*
    22.5 +===========================================================================
    22.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    22.7 +
    22.8 +This file is part of XreaL source code.
    22.9 +
   22.10 +XreaL source code is free software; you can redistribute it
   22.11 +and/or modify it under the terms of the GNU General Public License as
   22.12 +published by the Free Software Foundation; either version 2 of the License,
   22.13 +or (at your option) any later version.
   22.14 +
   22.15 +XreaL source code is distributed in the hope that it will be
   22.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   22.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22.18 +GNU General Public License for more details.
   22.19 +
   22.20 +You should have received a copy of the GNU General Public License
   22.21 +along with XreaL source code; if not, write to the Free Software
   22.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   22.23 +===========================================================================
   22.24 +*/
   22.25 +
   22.26 +uniform sampler2D	u_ColorMap;
   22.27 +uniform sampler2D	u_CurrentMap;
   22.28 +
   22.29 +varying vec2		var_Tex;
   22.30 +
   22.31 +void	main()
   22.32 +{
   22.33 +	vec4 color = texture2D(u_ColorMap, var_Tex);
   22.34 +
   22.35 +	// calculate the screen texcoord in the 0.0 to 1.0 range
   22.36 +	vec2 st = gl_FragCoord.st * r_FBufScale;
   22.37 +	
   22.38 +	// scale by the screen non-power-of-two-adjust
   22.39 +	st *= r_NPOTScale;
   22.40 +
   22.41 +	gl_FragColor = vec4(1.0, 0.0, 0.0, color.a);
   22.42 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/glsl/depthTest_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    23.3 @@ -0,0 +1,38 @@
    23.4 +/*
    23.5 +===========================================================================
    23.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    23.7 +
    23.8 +This file is part of XreaL source code.
    23.9 +
   23.10 +XreaL source code is free software; you can redistribute it
   23.11 +and/or modify it under the terms of the GNU General Public License as
   23.12 +published by the Free Software Foundation; either version 2 of the License,
   23.13 +or (at your option) any later version.
   23.14 +
   23.15 +XreaL source code is distributed in the hope that it will be
   23.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   23.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   23.18 +GNU General Public License for more details.
   23.19 +
   23.20 +You should have received a copy of the GNU General Public License
   23.21 +along with XreaL source code; if not, write to the Free Software
   23.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   23.23 +===========================================================================
   23.24 +*/
   23.25 +
   23.26 +attribute vec4		attr_Position;
   23.27 +attribute vec4		attr_TexCoord0;
   23.28 +
   23.29 +uniform mat4		u_ColorTextureMatrix;
   23.30 +uniform mat4		u_ModelViewProjectionMatrix;
   23.31 +
   23.32 +varying vec2		var_Tex;
   23.33 +
   23.34 +void	main()
   23.35 +{
   23.36 +	// transform vertex position into homogenous clip-space
   23.37 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   23.38 +	
   23.39 +	// transform texcoords
   23.40 +	var_Tex = (u_ColorTextureMatrix * attr_TexCoord0).st;
   23.41 +}
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/glsl/depthToColor_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    24.3 @@ -0,0 +1,55 @@
    24.4 +/*
    24.5 +===========================================================================
    24.6 +Copyright (C) 2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    24.7 +
    24.8 +This file is part of XreaL source code.
    24.9 +
   24.10 +XreaL source code is free software; you can redistribute it
   24.11 +and/or modify it under the terms of the GNU General Public License as
   24.12 +published by the Free Software Foundation; either version 2 of the License,
   24.13 +or (at your option) any later version.
   24.14 +
   24.15 +XreaL source code is distributed in the hope that it will be
   24.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   24.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   24.18 +GNU General Public License for more details.
   24.19 +
   24.20 +You should have received a copy of the GNU General Public License
   24.21 +along with XreaL source code; if not, write to the Free Software
   24.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   24.23 +===========================================================================
   24.24 +*/
   24.25 +
   24.26 +
   24.27 +void	main()
   24.28 +{
   24.29 +	// compute depth instead of world vertex position in a [0..1] range
   24.30 +	float depth = gl_FragCoord.z;
   24.31 +
   24.32 +//#if 0 //defined(GLHW_ATI_DX10) || defined(GLHW_NV_DX10)
   24.33 +//	gl_FragColor = vec4(0.0, 0.0, 0.0, depth);
   24.34 +//#else
   24.35 +	// 32 bit precision
   24.36 +	const vec4 bitSh = vec4(256 * 256 * 256,	256 * 256,				256,         1);
   24.37 +	const vec4 bitMsk = vec4(			0,		1.0 / 256.0,    1.0 / 256.0,    1.0 / 256.0);
   24.38 +	
   24.39 +	vec4 comp;
   24.40 +	comp = depth * bitSh;
   24.41 +	comp = fract(comp);
   24.42 +	comp -= comp.xxyz * bitMsk;
   24.43 +	gl_FragColor = comp;
   24.44 +/*
   24.45 +	// 24 bit precision
   24.46 +	const vec3 bitSh = vec3(256 * 256,			256,		1);
   24.47 +	const vec3 bitMsk = vec3(		0,	1.0 / 256.0,		1.0 / 256.0);
   24.48 +	
   24.49 +	vec3 comp;
   24.50 +	comp = depth * bitSh;
   24.51 +	comp = fract(comp);
   24.52 +	comp -= comp.xxy * bitMsk;
   24.53 +	gl_FragColor = vec4(comp, 0.0);
   24.54 +*/
   24.55 +//#endif
   24.56 +}
   24.57 +
   24.58 +	
   24.59 \ No newline at end of file
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/glsl/depthToColor_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    25.3 @@ -0,0 +1,58 @@
    25.4 +/*
    25.5 +===========================================================================
    25.6 +Copyright (C) 2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    25.7 +
    25.8 +This file is part of XreaL source code.
    25.9 +
   25.10 +XreaL source code is free software; you can redistribute it
   25.11 +and/or modify it under the terms of the GNU General Public License as
   25.12 +published by the Free Software Foundation; either version 2 of the License,
   25.13 +or (at your option) any later version.
   25.14 +
   25.15 +XreaL source code is distributed in the hope that it will be
   25.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   25.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   25.18 +GNU General Public License for more details.
   25.19 +
   25.20 +You should have received a copy of the GNU General Public License
   25.21 +along with XreaL source code; if not, write to the Free Software
   25.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   25.23 +===========================================================================
   25.24 +*/
   25.25 +
   25.26 +attribute vec4		attr_Position;
   25.27 +#if defined(r_VertexSkinning)
   25.28 +attribute vec4		attr_BoneIndexes;
   25.29 +attribute vec4		attr_BoneWeights;
   25.30 +uniform int			u_VertexSkinning;
   25.31 +uniform mat4		u_BoneMatrix[MAX_GLSL_BONES];
   25.32 +#endif
   25.33 +
   25.34 +uniform mat4		u_ModelViewProjectionMatrix;
   25.35 +
   25.36 +void	main()
   25.37 +{
   25.38 +#if defined(r_VertexSkinning)
   25.39 +	if(bool(u_VertexSkinning))
   25.40 +	{
   25.41 +		vec4 vertex = vec4(0.0);
   25.42 +		
   25.43 +		for(int i = 0; i < 4; i++)
   25.44 +		{
   25.45 +			int boneIndex = int(attr_BoneIndexes[i]);
   25.46 +			float boneWeight = attr_BoneWeights[i];
   25.47 +			mat4  boneMatrix = u_BoneMatrix[boneIndex];
   25.48 +			
   25.49 +			vertex += (boneMatrix * attr_Position) * boneWeight;
   25.50 +		}
   25.51 +
   25.52 +		// transform vertex position into homogenous clip-space
   25.53 +		gl_Position = u_ModelViewProjectionMatrix * vertex;
   25.54 +	}
   25.55 +	else
   25.56 +#endif
   25.57 +	{
   25.58 +		// transform vertex position into homogenous clip-space
   25.59 +		gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   25.60 +	}
   25.61 +}
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/glsl/dispersion_C_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    26.3 @@ -0,0 +1,65 @@
    26.4 +/*
    26.5 +===========================================================================
    26.6 +Copyright (C) 2006 Robert Beckebans <trebor_7@users.sourceforge.net>
    26.7 +
    26.8 +This file is part of XreaL source code.
    26.9 +
   26.10 +XreaL source code is free software; you can redistribute it
   26.11 +and/or modify it under the terms of the GNU General Public License as
   26.12 +published by the Free Software Foundation; either version 2 of the License,
   26.13 +or (at your option) any later version.
   26.14 +
   26.15 +XreaL source code is distributed in the hope that it will be
   26.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   26.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   26.18 +GNU General Public License for more details.
   26.19 +
   26.20 +You should have received a copy of the GNU General Public License
   26.21 +along with XreaL source code; if not, write to the Free Software
   26.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   26.23 +===========================================================================
   26.24 +*/
   26.25 +
   26.26 +uniform samplerCube	u_ColorMap;
   26.27 +uniform vec3		u_ViewOrigin;
   26.28 +uniform vec3		u_EtaRatio;
   26.29 +uniform float		u_FresnelPower;
   26.30 +uniform float		u_FresnelScale;
   26.31 +uniform float		u_FresnelBias;
   26.32 +
   26.33 +varying vec3		var_Position;
   26.34 +varying vec3		var_Normal;
   26.35 +
   26.36 +void	main()
   26.37 +{	
   26.38 +	// compute incident ray
   26.39 +	vec3 I = normalize(var_Position - u_ViewOrigin);
   26.40 +	
   26.41 +	// compute normal
   26.42 +	vec3 N = normalize(var_Normal);	// FIXME normalize?
   26.43 +	
   26.44 +	// compute reflection ray
   26.45 +	vec3 R = reflect(I, N);
   26.46 +	
   26.47 +	// compute fresnel term
   26.48 +	float fresnel = u_FresnelBias + pow(1.0 - dot(I, N), u_FresnelPower) * u_FresnelScale;
   26.49 +	
   26.50 +	// compute reflection color
   26.51 +	vec3 reflectColor = textureCube(u_ColorMap, R).rgb;
   26.52 +	
   26.53 +	// compute refraction color using a refraction ray for each channel
   26.54 +	vec3 refractColor;
   26.55 +	
   26.56 +	refractColor.r = textureCube(u_ColorMap, refract(I, N, u_EtaRatio.x)).r;
   26.57 +	refractColor.g = textureCube(u_ColorMap, refract(I, N, u_EtaRatio.y)).g;
   26.58 +	refractColor.b = textureCube(u_ColorMap, refract(I, N, u_EtaRatio.z)).b;
   26.59 +	
   26.60 +	// compute final color
   26.61 +	vec4 color;
   26.62 +	color.r = (1.0 - fresnel) * refractColor.r + reflectColor.r * fresnel;
   26.63 +	color.g = (1.0 - fresnel) * refractColor.g + reflectColor.g * fresnel;
   26.64 +	color.b = (1.0 - fresnel) * refractColor.b + reflectColor.b * fresnel;
   26.65 +	color.a = 1.0;
   26.66 +	
   26.67 +	gl_FragColor = color;
   26.68 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/glsl/dispersion_C_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    27.3 @@ -0,0 +1,78 @@
    27.4 +/*
    27.5 +===========================================================================
    27.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    27.7 +
    27.8 +This file is part of XreaL source code.
    27.9 +
   27.10 +XreaL source code is free software; you can redistribute it
   27.11 +and/or modify it under the terms of the GNU General Public License as
   27.12 +published by the Free Software Foundation; either version 2 of the License,
   27.13 +or (at your option) any later version.
   27.14 +
   27.15 +XreaL source code is distributed in the hope that it will be
   27.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27.18 +GNU General Public License for more details.
   27.19 +
   27.20 +You should have received a copy of the GNU General Public License
   27.21 +along with XreaL source code; if not, write to the Free Software
   27.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   27.23 +===========================================================================
   27.24 +*/
   27.25 +
   27.26 +attribute vec4		attr_Position;
   27.27 +attribute vec3		attr_Normal;
   27.28 +#if defined(r_VertexSkinning)
   27.29 +attribute vec4		attr_BoneIndexes;
   27.30 +attribute vec4		attr_BoneWeights;
   27.31 +uniform int			u_VertexSkinning;
   27.32 +uniform mat4		u_BoneMatrix[MAX_GLSL_BONES];
   27.33 +#endif
   27.34 +
   27.35 +uniform mat4		u_ModelMatrix;
   27.36 +uniform mat4		u_ModelViewProjectionMatrix;
   27.37 +
   27.38 +varying vec3		var_Position;
   27.39 +varying vec3		var_Normal;
   27.40 +
   27.41 +void	main()
   27.42 +{
   27.43 +#if defined(r_VertexSkinning)
   27.44 +	if(bool(u_VertexSkinning))
   27.45 +	{
   27.46 +		vec4 vertex = vec4(0.0);
   27.47 +		vec3 normal = vec3(0.0);
   27.48 +
   27.49 +		for(int i = 0; i < 4; i++)
   27.50 +		{
   27.51 +			int boneIndex = int(attr_BoneIndexes[i]);
   27.52 +			float boneWeight = attr_BoneWeights[i];
   27.53 +			mat4  boneMatrix = u_BoneMatrix[boneIndex];
   27.54 +			
   27.55 +			vertex += (boneMatrix * attr_Position) * boneWeight;
   27.56 +			normal += (boneMatrix * vec4(attr_Normal, 0.0)).xyz * boneWeight;
   27.57 +		}
   27.58 +
   27.59 +		// transform vertex position into homogenous clip-space
   27.60 +		gl_Position = u_ModelViewProjectionMatrix * vertex;
   27.61 +		
   27.62 +		// transform position into world space
   27.63 +		var_Position = (u_ModelMatrix * vertex).xyz;
   27.64 +	
   27.65 +		// transform normal into world space
   27.66 +		var_Normal = (u_ModelMatrix * vec4(normal, 0.0)).xyz;
   27.67 +	}
   27.68 +	else
   27.69 +#endif
   27.70 +	{
   27.71 +		// transform vertex position into homogenous clip-space
   27.72 +		gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   27.73 +	
   27.74 +		// transform position into world space
   27.75 +		var_Position = (u_ModelMatrix * attr_Position).xyz;
   27.76 +	
   27.77 +		// transform normal into world space
   27.78 +		var_Normal = (u_ModelMatrix * vec4(attr_Normal, 0.0)).xyz;
   27.79 +	}
   27.80 +}
   27.81 +
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/glsl/forwardLighting_DBS_omni_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    28.3 @@ -0,0 +1,292 @@
    28.4 +/*
    28.5 +===========================================================================
    28.6 +Copyright (C) 2007-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    28.7 +
    28.8 +This file is part of XreaL source code.
    28.9 +
   28.10 +XreaL source code is free software; you can redistribute it
   28.11 +and/or modify it under the terms of the GNU General Public License as
   28.12 +published by the Free Software Foundation; either version 2 of the License,
   28.13 +or (at your option) any later version.
   28.14 +
   28.15 +XreaL source code is distributed in the hope that it will be
   28.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   28.18 +GNU General Public License for more details.
   28.19 +
   28.20 +You should have received a copy of the GNU General Public License
   28.21 +along with XreaL source code; if not, write to the Free Software
   28.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   28.23 +===========================================================================
   28.24 +*/
   28.25 +
   28.26 +uniform sampler2D	u_DiffuseMap;
   28.27 +uniform sampler2D	u_NormalMap;
   28.28 +uniform sampler2D	u_SpecularMap;
   28.29 +uniform sampler2D	u_AttenuationMapXY;
   28.30 +uniform sampler2D	u_AttenuationMapZ;
   28.31 +#if defined(VSM) || defined(ESM)
   28.32 +uniform samplerCube	u_ShadowMap;
   28.33 +#endif
   28.34 +uniform vec3		u_ViewOrigin;
   28.35 +uniform vec3		u_LightOrigin;
   28.36 +uniform vec3		u_LightColor;
   28.37 +uniform float		u_LightRadius;
   28.38 +uniform float       u_LightScale;
   28.39 +uniform int			u_ShadowCompare;
   28.40 +uniform float       u_ShadowTexelSize;
   28.41 +uniform float       u_ShadowBlur;
   28.42 +uniform int         u_PortalClipping;
   28.43 +uniform vec4		u_PortalPlane;
   28.44 +
   28.45 +varying vec3		var_Position;
   28.46 +varying vec4		var_TexDiffuse;
   28.47 +varying vec4		var_TexNormal;
   28.48 +#if defined(r_NormalMapping)
   28.49 +varying vec2		var_TexSpecular;
   28.50 +#endif
   28.51 +varying vec3		var_TexAttenXYZ;
   28.52 +#if defined(r_NormalMapping)
   28.53 +varying vec4		var_Tangent;
   28.54 +varying vec4		var_Binormal;
   28.55 +#endif
   28.56 +varying vec4		var_Normal;
   28.57 +//varying vec4		var_Color;
   28.58 +
   28.59 +
   28.60 +#if defined(VSM) || defined(ESM)
   28.61 +
   28.62 +/*
   28.63 +================
   28.64 +MakeNormalVectors
   28.65 +
   28.66 +Given a normalized forward vector, create two
   28.67 +other perpendicular vectors
   28.68 +================
   28.69 +*/
   28.70 +void MakeNormalVectors(const vec3 forward, inout vec3 right, inout vec3 up)
   28.71 +{
   28.72 +	// this rotate and negate guarantees a vector
   28.73 +	// not colinear with the original
   28.74 +	right.y = -forward.x;
   28.75 +	right.z = forward.y;
   28.76 +	right.x = forward.z;
   28.77 +
   28.78 +	float d = dot(right, forward);
   28.79 +	right += forward * -d;
   28.80 +	normalize(right);
   28.81 +	up = cross(right, forward);	// GLSL cross product is the same as in Q3A
   28.82 +}
   28.83 +
   28.84 +vec4 PCF(vec3 I, float filterWidth, float samples)
   28.85 +{
   28.86 +	vec3 forward, right, up;
   28.87 +	
   28.88 +	forward = normalize(I);
   28.89 +	MakeNormalVectors(forward, right, up);
   28.90 +
   28.91 +	// compute step size for iterating through the kernel
   28.92 +	float stepSize = 2.0 * filterWidth / samples;
   28.93 +	
   28.94 +	vec4 moments = vec4(0.0, 0.0, 0.0, 0.0);
   28.95 +	for(float i = -filterWidth; i < filterWidth; i += stepSize)
   28.96 +	{
   28.97 +		for(float j = -filterWidth; j < filterWidth; j += stepSize)
   28.98 +		{
   28.99 +			moments += textureCube(u_ShadowMap, I + right * i + up * j);
  28.100 +		}
  28.101 +	}
  28.102 +	
  28.103 +	// return average of the samples
  28.104 +	moments *= (1.0 / (samples * samples));
  28.105 +	return moments;
  28.106 +}
  28.107 +#endif
  28.108 +
  28.109 +void	main()
  28.110 +{
  28.111 +	if(bool(u_PortalClipping))
  28.112 +	{
  28.113 +		float dist = dot(var_Position.xyz, u_PortalPlane.xyz) - u_PortalPlane.w;
  28.114 +		if(dist < 0.0)
  28.115 +		{
  28.116 +			discard;
  28.117 +			return;
  28.118 +		}
  28.119 +	}
  28.120 +
  28.121 +	float shadow = 1.0;
  28.122 +
  28.123 +#if defined(VSM)
  28.124 +	if(bool(u_ShadowCompare))
  28.125 +	{
  28.126 +		// compute incident ray
  28.127 +		vec3 I = var_Position - u_LightOrigin;
  28.128 +	
  28.129 +		#if defined(PCF_2X2)
  28.130 +		vec4 shadowMoments = PCF(I, u_ShadowTexelSize * u_ShadowBlur * length(I), 2.0);
  28.131 +		#elif defined(PCF_3X3)
  28.132 +		vec4 shadowMoments = PCF(I, u_ShadowTexelSize * u_ShadowBlur * length(I), 3.0);
  28.133 +		#elif defined(PCF_4X4)
  28.134 +		vec4 shadowMoments = PCF(I, u_ShadowTexelSize * u_ShadowBlur * length(I), 4.0);
  28.135 +		#elif defined(PCF_5X5)
  28.136 +		vec4 shadowMoments = PCF(I, u_ShadowTexelSize * u_ShadowBlur * length(I), 5.0);
  28.137 +		#elif defined(PCF_6X6)
  28.138 +		vec4 shadowMoments = PCF(I, u_ShadowTexelSize * u_ShadowBlur * length(I), 6.0);
  28.139 +		#else
  28.140 +		vec4 shadowMoments = textureCube(u_ShadowMap, I);
  28.141 +		#endif
  28.142 +		
  28.143 +		#if defined(VSM_CLAMP)
  28.144 +		// convert to [-1, 1] vector space
  28.145 +		shadowMoments = 2.0 * (shadowMoments - 0.5);
  28.146 +		#endif
  28.147 +	
  28.148 +		float shadowDistance = shadowMoments.r;
  28.149 +		float shadowDistanceSquared = shadowMoments.a;
  28.150 +		
  28.151 +		const float	SHADOW_BIAS = 0.001;
  28.152 +		float vertexDistance = length(I) / u_LightRadius - SHADOW_BIAS;
  28.153 +	
  28.154 +		// standard shadow map comparison
  28.155 +		shadow = vertexDistance <= shadowDistance ? 1.0 : 0.0;
  28.156 +	
  28.157 +		// variance shadow mapping
  28.158 +		float E_x2 = shadowDistanceSquared;
  28.159 +		float Ex_2 = shadowDistance * shadowDistance;
  28.160 +	
  28.161 +		// AndyTX: VSM_EPSILON is there to avoid some ugly numeric instability with fp16
  28.162 +		float variance = max(E_x2 - Ex_2, VSM_EPSILON);
  28.163 +	
  28.164 +		// compute probabilistic upper bound
  28.165 +		float mD = shadowDistance - vertexDistance;
  28.166 +		float mD_2 = mD * mD;
  28.167 +		float p = variance / (variance + mD_2);
  28.168 +		
  28.169 +		#if defined(r_LightBleedReduction)
  28.170 +		p = smoothstep(r_LightBleedReduction, 1.0, p);
  28.171 +		#endif
  28.172 +	
  28.173 +		#if defined(DEBUG_VSM)
  28.174 +		gl_FragColor.r = DEBUG_VSM & 1 ? variance : 0.0;
  28.175 +		gl_FragColor.g = DEBUG_VSM & 2 ? mD_2 : 0.0;
  28.176 +		gl_FragColor.b = DEBUG_VSM & 4 ? p : 0.0;
  28.177 +		gl_FragColor.a = 1.0;
  28.178 +		return;
  28.179 +		#else
  28.180 +		shadow = max(shadow, p);
  28.181 +		#endif
  28.182 +	}
  28.183 +	
  28.184 +	if(shadow <= 0.0)
  28.185 +	{
  28.186 +		discard;
  28.187 +	}
  28.188 +	else
  28.189 +#elif defined(ESM)
  28.190 +	if(bool(u_ShadowCompare))
  28.191 +	{
  28.192 +		// compute incident ray
  28.193 +		vec3 I = var_Position - u_LightOrigin;
  28.194 +	
  28.195 +		#if defined(PCF_2X2)
  28.196 +		vec4 shadowMoments = PCF(I, u_ShadowTexelSize * u_ShadowBlur * length(I), 2.0);
  28.197 +		#elif defined(PCF_3X3)
  28.198 +		vec4 shadowMoments = PCF(I, u_ShadowTexelSize * u_ShadowBlur * length(I), 3.0);
  28.199 +		#elif defined(PCF_4X4)
  28.200 +		vec4 shadowMoments = PCF(I, u_ShadowTexelSize * u_ShadowBlur * length(I), 4.0);
  28.201 +		#elif defined(PCF_5X5)
  28.202 +		vec4 shadowMoments = PCF(I, u_ShadowTexelSize * u_ShadowBlur * length(I), 5.0);
  28.203 +		#elif defined(PCF_6X6)
  28.204 +		vec4 shadowMoments = PCF(I, u_ShadowTexelSize * u_ShadowBlur * length(I), 6.0);
  28.205 +		#else
  28.206 +		vec4 shadowMoments = textureCube(u_ShadowMap, I);
  28.207 +		#endif
  28.208 +		
  28.209 +		const float	SHADOW_BIAS = 0.001;
  28.210 +		float vertexDistance = (length(I) / u_LightRadius) * r_ShadowMapDepthScale;// - SHADOW_BIAS;
  28.211 +		
  28.212 +		float shadowDistance = shadowMoments.a;
  28.213 +		
  28.214 +		// exponential shadow mapping
  28.215 +		shadow = clamp(exp(r_OverDarkeningFactor * (shadowDistance - vertexDistance)), 0.0, 1.0);
  28.216 +		
  28.217 +		#if defined(DEBUG_ESM)
  28.218 +		gl_FragColor.r = DEBUG_ESM & 1 ? shadowDistance : 0.0;
  28.219 +		gl_FragColor.g = DEBUG_ESM & 2 ? -(shadowDistance - vertexDistance) : 0.0;
  28.220 +		gl_FragColor.b = DEBUG_ESM & 4 ? 1.0 - shadow : 0.0;
  28.221 +		gl_FragColor.a = 1.0;
  28.222 +		return;
  28.223 +		#endif
  28.224 +	}
  28.225 +	
  28.226 +	if(shadow <= 0.0)
  28.227 +	{
  28.228 +		discard;
  28.229 +	}
  28.230 +	else
  28.231 +#endif
  28.232 +	{
  28.233 +		// compute light direction in world space
  28.234 +		vec3 L = normalize(u_LightOrigin - var_Position);
  28.235 +	
  28.236 +#if defined(r_NormalMapping)
  28.237 +		// compute view direction in world space
  28.238 +		vec3 V = normalize(u_ViewOrigin - var_Position);
  28.239 +	
  28.240 +		// compute half angle in world space
  28.241 +		vec3 H = normalize(L + V);
  28.242 +	
  28.243 +		// compute normal in tangent space from normalmap
  28.244 +		vec3 N = 2.0 * (texture2D(u_NormalMap, var_TexNormal.st).xyz - 0.5);
  28.245 +		#if defined(r_NormalScale)
  28.246 +		N.z *= r_NormalScale;
  28.247 +		normalize(N);
  28.248 +		#endif
  28.249 +		
  28.250 +		// invert tangent space for twosided surfaces
  28.251 +		mat3 tangentToWorldMatrix;
  28.252 +		if(gl_FrontFacing)
  28.253 +			tangentToWorldMatrix = mat3(-var_Tangent.xyz, -var_Binormal.xyz, -var_Normal.xyz);
  28.254 +		else
  28.255 +			tangentToWorldMatrix = mat3(var_Tangent.xyz, var_Binormal.xyz, var_Normal.xyz);
  28.256 +	
  28.257 +		// transform normal into world space
  28.258 +		N = tangentToWorldMatrix * N;
  28.259 +#else
  28.260 +		vec3 N;
  28.261 +		if(gl_FrontFacing)
  28.262 +			N = -normalize(var_Normal.xyz);
  28.263 +		else
  28.264 +			N = normalize(var_Normal.xyz);
  28.265 +#endif
  28.266 +	
  28.267 +		// compute the diffuse term
  28.268 +		vec4 diffuse = texture2D(u_DiffuseMap, var_TexDiffuse.st);
  28.269 +		diffuse.rgb *= u_LightColor * clamp(dot(N, L), 0.0, 1.0);
  28.270 +	
  28.271 +#if defined(r_NormalMapping)
  28.272 +		// compute the specular term
  28.273 +		vec3 specular = texture2D(u_SpecularMap, var_TexSpecular).rgb * u_LightColor * pow(clamp(dot(N, H), 0.0, 1.0), r_SpecularExponent) * r_SpecularScale;
  28.274 +#endif
  28.275 +	
  28.276 +		// compute attenuation
  28.277 +		vec3 attenuationXY		= texture2D(u_AttenuationMapXY, var_TexAttenXYZ.xy).rgb;
  28.278 +		vec3 attenuationZ		= texture2D(u_AttenuationMapZ, vec2(var_TexAttenXYZ.z, 0)).rgb;
  28.279 +					
  28.280 +		// compute final color
  28.281 +		vec4 color = diffuse;
  28.282 +#if defined(r_NormalMapping)
  28.283 +		color.rgb += specular;
  28.284 +#endif
  28.285 +		color.rgb *= attenuationXY;
  28.286 +		color.rgb *= attenuationZ;
  28.287 +		color.rgb *= u_LightScale;
  28.288 +		color.rgb *= shadow;
  28.289 +	
  28.290 +		color.r *= var_TexDiffuse.p;
  28.291 +		color.gb *= var_TexNormal.pq;
  28.292 +
  28.293 +		gl_FragColor = color;
  28.294 +	}
  28.295 +}
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/glsl/forwardLighting_DBS_omni_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    29.3 @@ -0,0 +1,142 @@
    29.4 +/*
    29.5 +===========================================================================
    29.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    29.7 +
    29.8 +This file is part of XreaL source code.
    29.9 +
   29.10 +XreaL source code is free software; you can redistribute it
   29.11 +and/or modify it under the terms of the GNU General Public License as
   29.12 +published by the Free Software Foundation; either version 2 of the License,
   29.13 +or (at your option) any later version.
   29.14 +
   29.15 +XreaL source code is distributed in the hope that it will be
   29.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   29.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   29.18 +GNU General Public License for more details.
   29.19 +
   29.20 +You should have received a copy of the GNU General Public License
   29.21 +along with XreaL source code; if not, write to the Free Software
   29.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   29.23 +===========================================================================
   29.24 +*/
   29.25 +
   29.26 +attribute vec4		attr_Position;
   29.27 +attribute vec4		attr_TexCoord0;
   29.28 +attribute vec3		attr_Tangent;
   29.29 +attribute vec3		attr_Binormal;
   29.30 +attribute vec3		attr_Normal;
   29.31 +attribute vec4		attr_Color;
   29.32 +#if defined(r_VertexSkinning)
   29.33 +attribute vec4		attr_BoneIndexes;
   29.34 +attribute vec4		attr_BoneWeights;
   29.35 +uniform int			u_VertexSkinning;
   29.36 +uniform mat4		u_BoneMatrix[MAX_GLSL_BONES];
   29.37 +#endif
   29.38 +
   29.39 +uniform mat4		u_DiffuseTextureMatrix;
   29.40 +uniform mat4		u_NormalTextureMatrix;
   29.41 +uniform mat4		u_SpecularTextureMatrix;
   29.42 +//uniform int			u_InverseVertexColor;
   29.43 +uniform mat4		u_LightAttenuationMatrix;
   29.44 +uniform mat4		u_ModelMatrix;
   29.45 +uniform mat4		u_ModelViewProjectionMatrix;
   29.46 +
   29.47 +varying vec3		var_Position;
   29.48 +varying vec4		var_TexDiffuse;
   29.49 +varying vec4		var_TexNormal;
   29.50 +#if defined(r_NormalMapping)
   29.51 +varying vec2		var_TexSpecular;
   29.52 +#endif
   29.53 +varying vec3		var_TexAttenXYZ;
   29.54 +#if defined(r_NormalMapping)
   29.55 +varying vec4		var_Tangent;
   29.56 +varying vec4		var_Binormal;
   29.57 +#endif
   29.58 +varying vec4		var_Normal;
   29.59 +//varying vec4		var_Color;	// Tr3B - maximum vars reached
   29.60 +
   29.61 +void	main()
   29.62 +{
   29.63 +#if defined(r_VertexSkinning)
   29.64 +	if(bool(u_VertexSkinning))
   29.65 +	{
   29.66 +		vec4 vertex = vec4(0.0);
   29.67 +		vec3 tangent = vec3(0.0);
   29.68 +		vec3 binormal = vec3(0.0);
   29.69 +		vec3 normal = vec3(0.0);
   29.70 +
   29.71 +		for(int i = 0; i < 4; i++)
   29.72 +		{
   29.73 +			int boneIndex = int(attr_BoneIndexes[i]);
   29.74 +			float boneWeight = attr_BoneWeights[i];
   29.75 +			mat4  boneMatrix = u_BoneMatrix[boneIndex];
   29.76 +			
   29.77 +			vertex += (boneMatrix * attr_Position) * boneWeight;
   29.78 +		
   29.79 +			tangent += (boneMatrix * vec4(attr_Tangent, 0.0)).xyz * boneWeight;
   29.80 +			binormal += (boneMatrix * vec4(attr_Binormal, 0.0)).xyz * boneWeight;
   29.81 +			normal += (boneMatrix * vec4(attr_Normal, 0.0)).xyz * boneWeight;
   29.82 +		}
   29.83 +
   29.84 +		// transform vertex position into homogenous clip-space
   29.85 +		gl_Position = u_ModelViewProjectionMatrix * vertex;
   29.86 +		
   29.87 +		// transform position into world space
   29.88 +		var_Position = (u_ModelMatrix * vertex).xyz;
   29.89 +		
   29.90 +		#if defined(r_NormalMapping)
   29.91 +		var_Tangent.xyz = (u_ModelMatrix * vec4(tangent, 0.0)).xyz;
   29.92 +		var_Binormal.xyz = (u_ModelMatrix * vec4(binormal, 0.0)).xyz;
   29.93 +		#endif
   29.94 +		
   29.95 +		var_Normal.xyz = (u_ModelMatrix * vec4(normal, 0.0)).xyz;
   29.96 +		
   29.97 +		// calc light xy,z attenuation in light space
   29.98 +		var_TexAttenXYZ = (u_LightAttenuationMatrix * vertex).xyz;
   29.99 +	}
  29.100 +	else
  29.101 +#endif
  29.102 +	{
  29.103 +		// transform vertex position into homogenous clip-space
  29.104 +		gl_Position = u_ModelViewProjectionMatrix * attr_Position;
  29.105 +		
  29.106 +		// transform position into world space
  29.107 +		var_Position = (u_ModelMatrix * attr_Position).xyz;
  29.108 +	
  29.109 +		#if defined(r_NormalMapping)
  29.110 +		var_Tangent.xyz = (u_ModelMatrix * vec4(attr_Tangent, 0.0)).xyz;
  29.111 +		var_Binormal.xyz = (u_ModelMatrix * vec4(attr_Binormal, 0.0)).xyz;
  29.112 +		#endif
  29.113 +		
  29.114 +		var_Normal.xyz = (u_ModelMatrix * vec4(attr_Normal, 0.0)).xyz;
  29.115 +		
  29.116 +		// calc light xy,z attenuation in light space
  29.117 +		var_TexAttenXYZ = (u_LightAttenuationMatrix * attr_Position).xyz;
  29.118 +	}
  29.119 +		
  29.120 +	// transform diffusemap texcoords
  29.121 +	var_TexDiffuse.xy = (u_DiffuseTextureMatrix * attr_TexCoord0).st;
  29.122 +	
  29.123 +#if defined(r_NormalMapping)
  29.124 +	// transform normalmap texcoords
  29.125 +	var_TexNormal.xy = (u_NormalTextureMatrix * attr_TexCoord0).st;
  29.126 +	
  29.127 +	// transform specularmap texture coords
  29.128 +	var_TexSpecular = (u_SpecularTextureMatrix * attr_TexCoord0).st;
  29.129 +#endif
  29.130 +	
  29.131 +	// assign color
  29.132 +	/*
  29.133 +	if(bool(u_InverseVertexColor))
  29.134 +	{
  29.135 +		var_TexDiffuse.p = 1.0 - attr_Color.r;
  29.136 +		var_TexNormal.p = 1.0 - attr_Color.g;
  29.137 +		var_TexNormal.q = 1.0 - attr_Color.b;
  29.138 +	}
  29.139 +	else
  29.140 +	*/
  29.141 +	{
  29.142 +		var_TexDiffuse.p = attr_Color.r;
  29.143 +		var_TexNormal.pq = attr_Color.gb;
  29.144 +	}
  29.145 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/glsl/forwardLighting_DBS_proj_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    30.3 @@ -0,0 +1,376 @@
    30.4 +/*
    30.5 +===========================================================================
    30.6 +Copyright (C) 2007-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    30.7 +
    30.8 +This file is part of XreaL source code.
    30.9 +
   30.10 +XreaL source code is free software; you can redistribute it
   30.11 +and/or modify it under the terms of the GNU General Public License as
   30.12 +published by the Free Software Foundation; either version 2 of the License,
   30.13 +or (at your option) any later version.
   30.14 +
   30.15 +XreaL source code is distributed in the hope that it will be
   30.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   30.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   30.18 +GNU General Public License for more details.
   30.19 +
   30.20 +You should have received a copy of the GNU General Public License
   30.21 +along with XreaL source code; if not, write to the Free Software
   30.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   30.23 +===========================================================================
   30.24 +*/
   30.25 +
   30.26 +uniform sampler2D	u_DiffuseMap;
   30.27 +uniform sampler2D	u_NormalMap;
   30.28 +uniform sampler2D	u_SpecularMap;
   30.29 +uniform sampler2D	u_AttenuationMapXY;
   30.30 +uniform sampler2D	u_AttenuationMapZ;
   30.31 +uniform sampler2D	u_ShadowMap;
   30.32 +uniform vec3		u_ViewOrigin;
   30.33 +uniform vec3		u_LightOrigin;
   30.34 +uniform vec3		u_LightColor;
   30.35 +uniform float		u_LightRadius;
   30.36 +uniform float		u_LightScale;
   30.37 +uniform int			u_ShadowCompare;
   30.38 +uniform float       u_ShadowTexelSize;
   30.39 +uniform float       u_ShadowBlur;
   30.40 +uniform mat4		u_ModelMatrix;
   30.41 +uniform int         u_PortalClipping;
   30.42 +uniform vec4		u_PortalPlane;
   30.43 +
   30.44 +varying vec4		var_Position;
   30.45 +varying vec4		var_TexDiffuse;
   30.46 +varying vec4		var_TexNormal;
   30.47 +#if defined(r_NormalMapping)
   30.48 +varying vec2		var_TexSpecular;
   30.49 +#endif
   30.50 +varying vec4		var_TexAtten;
   30.51 +varying vec4		var_Tangent;
   30.52 +varying vec4		var_Binormal;
   30.53 +varying vec4		var_Normal;
   30.54 +
   30.55 +
   30.56 +#if defined(PCSS)
   30.57 +float SumBlocker(vec4 SP, float vertexDistance, float filterWidth, float samples)
   30.58 +{
   30.59 +	float stepSize = 2.0 * filterWidth / samples;
   30.60 +	
   30.61 +	float blockerCount = 0.0;
   30.62 +    float blockerSum = 0.0;
   30.63 +    
   30.64 +	for(float i = -filterWidth; i < filterWidth; i += stepSize)
   30.65 +	{
   30.66 +		for(float j = -filterWidth; j < filterWidth; j += stepSize)
   30.67 +		{
   30.68 +			float shadowDistance = texture2DProj(u_ShadowMap, vec3(SP.xy + vec2(i, j), SP.w)).x;
   30.69 +			//float shadowDistance = texture2D(u_ShadowMap, SP.xy / SP.w + vec2(i, j)).x;
   30.70 +			
   30.71 +			// FIXME VSM_CLAMP
   30.72 +			
   30.73 +			if(vertexDistance > shadowDistance)
   30.74 +			{
   30.75 +				blockerCount += 1.0;
   30.76 +				blockerSum += shadowDistance;
   30.77 +			}
   30.78 +		}
   30.79 +	}
   30.80 +	
   30.81 +	float result;
   30.82 +	if(blockerCount > 0.0)
   30.83 +		result = blockerSum / blockerCount;
   30.84 +	else
   30.85 +		result = 0.0;
   30.86 +	
   30.87 +	return result;
   30.88 +}
   30.89 +
   30.90 +float EstimatePenumbra(float vertexDistance, float blocker)
   30.91 +{
   30.92 +	float penumbra;
   30.93 +	
   30.94 +	if(blocker == 0.0)
   30.95 +		penumbra = 0.0;
   30.96 +	else
   30.97 +		penumbra = ((vertexDistance - blocker) * u_LightRadius) / blocker;
   30.98 +	
   30.99 +	return penumbra;
  30.100 +}
  30.101 +#endif
  30.102 +
  30.103 +#if defined(VSM) || defined(ESM)
  30.104 +vec4 PCF(vec4 SP, float filterWidth, float samples)
  30.105 +{
  30.106 +	// compute step size for iterating through the kernel
  30.107 +	float stepSize = 2.0 * filterWidth / samples;
  30.108 +	
  30.109 +	vec4 moments = vec4(0.0, 0.0, 0.0, 0.0);
  30.110 +	for(float i = -filterWidth; i < filterWidth; i += stepSize)
  30.111 +	{
  30.112 +		for(float j = -filterWidth; j < filterWidth; j += stepSize)
  30.113 +		{
  30.114 +			//moments += texture2DProj(u_ShadowMap, vec3(SP.xy + vec2(i, j), SP.w));
  30.115 +			moments += texture2D(u_ShadowMap, SP.xy / SP.w + vec2(i, j));
  30.116 +		}
  30.117 +	}
  30.118 +	
  30.119 +	// return average of the samples
  30.120 +	moments *= (1.0 / (samples * samples));
  30.121 +	return moments;
  30.122 +}
  30.123 +#endif
  30.124 +
  30.125 +void	main()
  30.126 +{
  30.127 +	if(bool(u_PortalClipping))
  30.128 +	{
  30.129 +		float dist = dot(var_Position.xyz, u_PortalPlane.xyz) - u_PortalPlane.w;
  30.130 +		if(dist < 0.0)
  30.131 +		{
  30.132 +			discard;
  30.133 +			return;
  30.134 +		}
  30.135 +	}
  30.136 +
  30.137 +	float shadow = 1.0;
  30.138 +
  30.139 +	if(var_TexAtten.q <= 0.0)
  30.140 +	{
  30.141 +		discard;
  30.142 +	}
  30.143 +	
  30.144 +#if defined(VSM)
  30.145 +	if(bool(u_ShadowCompare))
  30.146 +	{
  30.147 +		vec4 SP;	// shadow point in shadow space
  30.148 +		SP.x = var_Position.w;
  30.149 +		SP.y = var_Tangent.w;
  30.150 +		SP.z = var_Binormal.w;
  30.151 +		SP.w = var_Normal.w;
  30.152 +		
  30.153 +		// compute incident ray
  30.154 +		vec3 I = var_Position.xyz - u_LightOrigin;
  30.155 +		
  30.156 +		const float	SHADOW_BIAS = 0.001;
  30.157 +		float vertexDistance = length(I) / u_LightRadius - SHADOW_BIAS;
  30.158 +		
  30.159 +		#if defined(PCF_2X2)
  30.160 +		vec4 shadowMoments = PCF(SP, u_ShadowTexelSize * u_ShadowBlur, 2.0);
  30.161 +		#elif defined(PCF_3X3)
  30.162 +		vec4 shadowMoments = PCF(SP, u_ShadowTexelSize * u_ShadowBlur, 3.0);
  30.163 +		#elif defined(PCF_4X4)
  30.164 +		vec4 shadowMoments = PCF(SP, u_ShadowTexelSize * u_ShadowBlur, 4.0);
  30.165 +		#elif defined(PCF_5X5)
  30.166 +		vec4 shadowMoments = PCF(SP, u_ShadowTexelSize * u_ShadowBlur, 5.0);
  30.167 +		#elif defined(PCF_6X6)
  30.168 +		vec4 shadowMoments = PCF(SP, u_ShadowTexelSize * u_ShadowBlur, 6.0);
  30.169 +		#elif defined(PCSS)
  30.170 +		
  30.171 +		// step 1: find blocker estimate
  30.172 +		float blockerSearchWidth = u_ShadowTexelSize * u_LightRadius / vertexDistance;
  30.173 +		float blockerSamples = 6.0; // how many samples to use for blocker search
  30.174 +		float blocker = SumBlocker(SP, vertexDistance, blockerSearchWidth, blockerSamples);
  30.175 +		
  30.176 +		#if 0
  30.177 +		// uncomment to visualize blockers
  30.178 +		gl_FragColor = vec4(blocker * 0.3, 0.0, 0.0, 1.0);
  30.179 +		return;
  30.180 +		#endif
  30.181 +		
  30.182 +		// step 2: estimate penumbra using parallel planes approximation
  30.183 +		float penumbra = EstimatePenumbra(vertexDistance, blocker);
  30.184 +		
  30.185 +		#if 0
  30.186 +		// uncomment to visualize penumbrae
  30.187 +		gl_FragColor = vec4(0.0, 0.0, penumbra, 1.0);
  30.188 +		return;
  30.189 +		#endif
  30.190 +		
  30.191 +		// step 3: compute percentage-closer filter
  30.192 +		vec4 shadowMoments;
  30.193 +		if(penumbra > 0.0)
  30.194 +		{
  30.195 +			const float PCFsamples = 4.0;
  30.196 +			
  30.197 +			/*
  30.198 +			float maxpen = PCFsamples * (1.0 / u_ShadowTexelSize);
  30.199 +			if(penumbra > maxpen)
  30.200 +				penumbra = maxpen;
  30.201 +			*/
  30.202 +		
  30.203 +			shadowMoments = PCF(SP, penumbra, PCFsamples);
  30.204 +		}
  30.205 +		else
  30.206 +		{
  30.207 +			shadowMoments = texture2DProj(u_ShadowMap, SP.xyw);
  30.208 +		}
  30.209 +		#else
  30.210 +		
  30.211 +		// no filter
  30.212 +		vec4 shadowMoments = texture2DProj(u_ShadowMap, SP.xyw);
  30.213 +		#endif
  30.214 +	
  30.215 +		#if defined(VSM_CLAMP)
  30.216 +		// convert to [-1, 1] vector space
  30.217 +		shadowMoments = 2.0 * (shadowMoments - 0.5);
  30.218 +		#endif
  30.219 +		
  30.220 +		float shadowDistance = shadowMoments.r;
  30.221 +		float shadowDistanceSquared = shadowMoments.a;
  30.222 +	
  30.223 +		// standard shadow map comparison
  30.224 +		shadow = vertexDistance <= shadowDistance ? 1.0 : 0.0;
  30.225 +	
  30.226 +		// variance shadow mapping
  30.227 +		float E_x2 = shadowDistanceSquared;
  30.228 +		float Ex_2 = shadowDistance * shadowDistance;
  30.229 +	
  30.230 +		// AndyTX: VSM_EPSILON is there to avoid some ugly numeric instability with fp16
  30.231 +		float variance = max(E_x2 - Ex_2, VSM_EPSILON);
  30.232 +		//float variance = smoothstep(VSM_EPSILON, 1.0, max(E_x2 - Ex_2, 0.0));
  30.233 +	
  30.234 +		float mD = shadowDistance - vertexDistance;
  30.235 +		float mD_2 = mD * mD;
  30.236 +		float p = variance / (variance + mD_2);
  30.237 +		
  30.238 +		#if defined(r_LightBleedReduction)
  30.239 +		p = smoothstep(r_LightBleedReduction, 1.0, p);
  30.240 +		#endif
  30.241 +	
  30.242 +		#if defined(DEBUG_VSM)
  30.243 +		gl_FragColor.r = DEBUG_VSM & 1 ? variance : 0.0;
  30.244 +		gl_FragColor.g = DEBUG_VSM & 2 ? mD_2 : 0.0;
  30.245 +		gl_FragColor.b = DEBUG_VSM & 4 ? p : 0.0;
  30.246 +		gl_FragColor.a = 1.0;
  30.247 +		return;
  30.248 +		#else
  30.249 +		shadow = max(shadow, p);
  30.250 +		#endif
  30.251 +	}
  30.252 +	
  30.253 +	if(shadow <= 0.0)
  30.254 +	{
  30.255 +		discard;
  30.256 +	}
  30.257 +	else
  30.258 +#elif defined(ESM)
  30.259 +	if(bool(u_ShadowCompare))
  30.260 +	{
  30.261 +		vec4 SP;	// shadow point in shadow space
  30.262 +		SP.x = var_Position.w;
  30.263 +		SP.y = var_Tangent.w;
  30.264 +		SP.z = var_Binormal.w;
  30.265 +		SP.w = var_Normal.w;
  30.266 +		
  30.267 +		// compute incident ray
  30.268 +		vec3 I = var_Position.xyz - u_LightOrigin;
  30.269 +		
  30.270 +		const float	SHADOW_BIAS = 0.001;
  30.271 +		float vertexDistance = (length(I) / u_LightRadius) * r_ShadowMapDepthScale; // - SHADOW_BIAS;
  30.272 +		
  30.273 +		#if defined(PCF_2X2)
  30.274 +		vec4 shadowMoments = PCF(SP, u_ShadowTexelSize * u_ShadowBlur, 2.0);
  30.275 +		#elif defined(PCF_3X3)
  30.276 +		vec4 shadowMoments = PCF(SP, u_ShadowTexelSize * u_ShadowBlur, 3.0);
  30.277 +		#elif defined(PCF_4X4)
  30.278 +		vec4 shadowMoments = PCF(SP, u_ShadowTexelSize * u_ShadowBlur, 4.0);
  30.279 +		#elif defined(PCF_5X5)
  30.280 +		vec4 shadowMoments = PCF(SP, u_ShadowTexelSize * u_ShadowBlur, 5.0);
  30.281 +		#elif defined(PCF_6X6)
  30.282 +		vec4 shadowMoments = PCF(SP, u_ShadowTexelSize * u_ShadowBlur, 6.0);
  30.283 +		#else
  30.284 +		// no filter
  30.285 +		vec4 shadowMoments = texture2DProj(u_ShadowMap, SP.xyw);
  30.286 +		#endif
  30.287 +		
  30.288 +		float shadowDistance = shadowMoments.a;
  30.289 +		
  30.290 +		// exponential shadow mapping
  30.291 +		//shadow = vertexDistance <= shadowDistance ? 1.0 : 0.0;
  30.292 +		shadow = clamp(exp(r_OverDarkeningFactor * (shadowDistance - vertexDistance)), 0.0, 1.0);
  30.293 +		//shadow = smoothstep(0.0, 1.0, shadow);
  30.294 +		
  30.295 +		#if defined(DEBUG_ESM)
  30.296 +		gl_FragColor.r = DEBUG_ESM & 1 ? shadowDistance : 0.0;
  30.297 +		gl_FragColor.g = DEBUG_ESM & 2 ? -(shadowDistance - vertexDistance) : 0.0;
  30.298 +		gl_FragColor.b = DEBUG_ESM & 4 ? shadow : 0.0;
  30.299 +		gl_FragColor.a = 1.0;
  30.300 +		return;
  30.301 +		#endif
  30.302 +	}
  30.303 +	
  30.304 +	if(shadow <= 0.0)
  30.305 +	{
  30.306 +		discard;
  30.307 +	}
  30.308 +	else
  30.309 +#endif
  30.310 +	{
  30.311 +		// compute light direction in world space
  30.312 +		vec3 L = normalize(u_LightOrigin - var_Position.xyz);
  30.313 +	
  30.314 +#if defined(r_NormalMapping)
  30.315 +		// compute view direction in world space
  30.316 +		vec3 V = normalize(u_ViewOrigin - var_Position.xyz);
  30.317 +	
  30.318 +		// compute half angle in world space
  30.319 +		vec3 H = normalize(L + V);
  30.320 +	
  30.321 +		// compute normal in tangent space from normalmap
  30.322 +		vec3 N = 2.0 * (texture2D(u_NormalMap, var_TexNormal.st).xyz - 0.5);
  30.323 +		#if defined(r_NormalScale)
  30.324 +		N.z *= r_NormalScale;
  30.325 +		normalize(N);
  30.326 +		#endif
  30.327 +	
  30.328 +		// invert tangent space for twosided surfaces
  30.329 +		mat3 tangentToWorldMatrix;
  30.330 +		if(gl_FrontFacing)
  30.331 +			tangentToWorldMatrix = mat3(-var_Tangent.xyz, -var_Binormal.xyz, -var_Normal.xyz);
  30.332 +		else
  30.333 +			tangentToWorldMatrix = mat3(var_Tangent.xyz, var_Binormal.xyz, var_Normal.xyz);
  30.334 +
  30.335 +		// transform normal into world space
  30.336 +		N = tangentToWorldMatrix * N;
  30.337 +#else
  30.338 +		vec3 N;
  30.339 +		if(gl_FrontFacing)
  30.340 +			N = -normalize(var_Normal.xyz);
  30.341 +		else
  30.342 +			N = normalize(var_Normal.xyz);
  30.343 +#endif
  30.344 +		// compute the diffuse term
  30.345 +		vec4 diffuse = texture2D(u_DiffuseMap, var_TexDiffuse.st);
  30.346 +		diffuse.rgb *= u_LightColor * clamp(dot(N, L), 0.0, 1.0);
  30.347 +	
  30.348 +#if defined(r_NormalMapping)
  30.349 +		// compute the specular term
  30.350 +		vec3 specular = texture2D(u_SpecularMap, var_TexSpecular).rgb * u_LightColor * pow(clamp(dot(N, H), 0.0, 1.0), r_SpecularExponent) * r_SpecularScale;
  30.351 +#endif
  30.352 +	
  30.353 +		// compute attenuation
  30.354 +		#if 0
  30.355 +		vec3 texAtten = var_TexAtten.xyz / var_TexAtten.w;
  30.356 +		vec3 attenuationXY = texture2D(u_AttenuationMapXY, texAtten.xy).rgb;
  30.357 +		vec3 attenuationZ  = texture2D(u_AttenuationMapZ, vec2(texAtten.z, 0.0)).rgb;
  30.358 +		#else
  30.359 +		vec3 attenuationXY = texture2DProj(u_AttenuationMapXY, var_TexAtten.xyw).rgb;
  30.360 +		vec3 attenuationZ  = texture2D(u_AttenuationMapZ, vec2(clamp(var_TexAtten.z, 0.0, 1.0), 0.0)).rgb;
  30.361 +		//vec3 attenuationZ = var_TexAtten.z;
  30.362 +		#endif
  30.363 +
  30.364 +		// compute final color
  30.365 +		vec4 color = diffuse;
  30.366 +#if defined(r_NormalMapping)
  30.367 +		color.rgb += specular;
  30.368 +#endif
  30.369 +		color.rgb *= attenuationXY;
  30.370 +		color.rgb *= attenuationZ;
  30.371 +		color.rgb *= u_LightScale;
  30.372 +		color.rgb *= shadow;
  30.373 +	
  30.374 +		color.r *= var_TexDiffuse.p;
  30.375 +		color.gb *= var_TexNormal.pq;
  30.376 +	
  30.377 +		gl_FragColor = color;
  30.378 +	}
  30.379 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/glsl/forwardLighting_DBS_proj_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    31.3 @@ -0,0 +1,158 @@
    31.4 +/*
    31.5 +===========================================================================
    31.6 +Copyright (C) 2007-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    31.7 +
    31.8 +This file is part of XreaL source code.
    31.9 +
   31.10 +XreaL source code is free software; you can redistribute it
   31.11 +and/or modify it under the terms of the GNU General Public License as
   31.12 +published by the Free Software Foundation; either version 2 of the License,
   31.13 +or (at your option) any later version.
   31.14 +
   31.15 +XreaL source code is distributed in the hope that it will be
   31.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   31.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   31.18 +GNU General Public License for more details.
   31.19 +
   31.20 +You should have received a copy of the GNU General Public License
   31.21 +along with XreaL source code; if not, write to the Free Software
   31.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   31.23 +===========================================================================
   31.24 +*/
   31.25 +
   31.26 +attribute vec4		attr_Position;
   31.27 +attribute vec4		attr_TexCoord0;
   31.28 +attribute vec3		attr_Tangent;
   31.29 +attribute vec3		attr_Binormal;
   31.30 +attribute vec3		attr_Normal;
   31.31 +attribute vec4		attr_Color;
   31.32 +#if defined(r_VertexSkinning)
   31.33 +attribute vec4		attr_BoneIndexes;
   31.34 +attribute vec4		attr_BoneWeights;
   31.35 +uniform int			u_VertexSkinning;
   31.36 +uniform mat4		u_BoneMatrix[MAX_GLSL_BONES];
   31.37 +#endif
   31.38 +
   31.39 +uniform mat4		u_DiffuseTextureMatrix;
   31.40 +uniform mat4		u_NormalTextureMatrix;
   31.41 +uniform mat4		u_SpecularTextureMatrix;
   31.42 +//uniform int			u_InverseVertexColor;
   31.43 +uniform mat4		u_LightAttenuationMatrix;
   31.44 +uniform mat4		u_ShadowMatrix;
   31.45 +uniform mat4		u_ModelMatrix;
   31.46 +uniform mat4		u_ModelViewProjectionMatrix;
   31.47 +
   31.48 +varying vec4		var_Position;
   31.49 +varying vec4		var_TexDiffuse;
   31.50 +varying vec4		var_TexNormal;
   31.51 +#if defined(r_NormalMapping)
   31.52 +varying vec2		var_TexSpecular;
   31.53 +#endif
   31.54 +varying vec4		var_TexAtten;
   31.55 +varying vec4		var_Tangent;
   31.56 +varying vec4		var_Binormal;
   31.57 +varying vec4		var_Normal;
   31.58 +
   31.59 +void	main()
   31.60 +{
   31.61 +#if defined(r_VertexSkinning)
   31.62 +	if(bool(u_VertexSkinning))
   31.63 +	{
   31.64 +		vec4 vertex = vec4(0.0);
   31.65 +		vec3 tangent = vec3(0.0);
   31.66 +		vec3 binormal = vec3(0.0);
   31.67 +		vec3 normal = vec3(0.0);
   31.68 +
   31.69 +		for(int i = 0; i < 4; i++)
   31.70 +		{
   31.71 +			int boneIndex = int(attr_BoneIndexes[i]);
   31.72 +			float boneWeight = attr_BoneWeights[i];
   31.73 +			mat4  boneMatrix = u_BoneMatrix[boneIndex];
   31.74 +			
   31.75 +			vertex += (boneMatrix * attr_Position) * boneWeight;
   31.76 +		
   31.77 +			tangent += (boneMatrix * vec4(attr_Tangent, 0.0)).xyz * boneWeight;
   31.78 +			binormal += (boneMatrix * vec4(attr_Binormal, 0.0)).xyz * boneWeight;
   31.79 +			normal += (boneMatrix * vec4(attr_Normal, 0.0)).xyz * boneWeight;
   31.80 +		}
   31.81 +
   31.82 +		// transform vertex position into homogenous clip-space
   31.83 +		gl_Position = u_ModelViewProjectionMatrix * vertex;
   31.84 +		
   31.85 +		// transform position into world space
   31.86 +		var_Position = u_ModelMatrix * vertex;
   31.87 +		
   31.88 +		#if defined(r_NormalMapping)
   31.89 +		var_Tangent.xyz = (u_ModelMatrix * vec4(tangent, 0.0)).xyz;
   31.90 +		var_Binormal.xyz = (u_ModelMatrix * vec4(binormal, 0.0)).xyz;
   31.91 +		#endif
   31.92 +		
   31.93 +		var_Normal.xyz = (u_ModelMatrix * vec4(normal, 0.0)).xyz;
   31.94 +		
   31.95 +		// calc light attenuation in light space
   31.96 +		var_TexAtten = u_LightAttenuationMatrix * vertex;
   31.97 +	
   31.98 +		// calc shadow attenuation in light space
   31.99 +		vec4 texShadow = u_ShadowMatrix * vertex;
  31.100 +	
  31.101 +		// Tr3B: put it into other varyings because we reached the maximum on a Geforce 6600
  31.102 +		var_Position.w = texShadow.s;
  31.103 +		var_Tangent.w = texShadow.t;
  31.104 +		var_Binormal.w = texShadow.p;
  31.105 +		var_Normal.w = texShadow.q;
  31.106 +	}
  31.107 +	else
  31.108 +#endif
  31.109 +	{
  31.110 +		// transform vertex position into homogenous clip-space
  31.111 +		gl_Position = u_ModelViewProjectionMatrix * attr_Position;
  31.112 +		
  31.113 +		// transform position into world space
  31.114 +		var_Position = u_ModelMatrix * attr_Position;
  31.115 +	
  31.116 +		#if defined(r_NormalMapping)
  31.117 +		var_Tangent.xyz = (u_ModelMatrix * vec4(attr_Tangent, 0.0)).xyz;
  31.118 +		var_Binormal.xyz = (u_ModelMatrix * vec4(attr_Binormal, 0.0)).xyz;
  31.119 +		#endif
  31.120 +		
  31.121 +		var_Normal.xyz = (u_ModelMatrix * vec4(attr_Normal, 0.0)).xyz;
  31.122 +		
  31.123 +		// calc light attenuation in light space
  31.124 +		var_TexAtten = u_LightAttenuationMatrix * attr_Position;
  31.125 +	
  31.126 +		// calc shadow attenuation in light space
  31.127 +		vec4 texShadow = u_ShadowMatrix * attr_Position;
  31.128 +	
  31.129 +		// Tr3B: put it into other varyings because we reached the maximum on a Geforce 6600
  31.130 +		var_Position.w = texShadow.s;
  31.131 +		var_Tangent.w = texShadow.t;
  31.132 +		var_Binormal.w = texShadow.p;
  31.133 +		var_Normal.w = texShadow.q;
  31.134 +	}
  31.135 +	
  31.136 +	// transform diffusemap texcoords
  31.137 +	var_TexDiffuse.st = (u_DiffuseTextureMatrix * attr_TexCoord0).st;
  31.138 +	
  31.139 +#if defined(r_NormalMapping)
  31.140 +	// transform normalmap texcoords
  31.141 +	var_TexNormal.st = (u_NormalTextureMatrix * attr_TexCoord0).st;
  31.142 +	
  31.143 +	// transform specularmap texture coords
  31.144 +	var_TexSpecular = (u_SpecularTextureMatrix * attr_TexCoord0).st;
  31.145 +#endif
  31.146 +	
  31.147 +	// assign color
  31.148 +	/*
  31.149 +	if(bool(u_InverseVertexColor))
  31.150 +	{
  31.151 +		var_TexDiffuse.p = 1.0 - attr_Color.r;
  31.152 +		var_TexNormal.p = 1.0 - attr_Color.g;
  31.153 +		var_TexNormal.q = 1.0 - attr_Color.b;
  31.154 +	}
  31.155 +	else
  31.156 +	*/
  31.157 +	{
  31.158 +		var_TexDiffuse.p = attr_Color.r;
  31.159 +		var_TexNormal.pq = attr_Color.gb;
  31.160 +	}
  31.161 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/glsl/genericSingle_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    32.3 @@ -0,0 +1,63 @@
    32.4 +/*
    32.5 +===========================================================================
    32.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    32.7 +
    32.8 +This file is part of XreaL source code.
    32.9 +
   32.10 +XreaL source code is free software; you can redistribute it
   32.11 +and/or modify it under the terms of the GNU General Public License as
   32.12 +published by the Free Software Foundation; either version 2 of the License,
   32.13 +or (at your option) any later version.
   32.14 +
   32.15 +XreaL source code is distributed in the hope that it will be
   32.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   32.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   32.18 +GNU General Public License for more details.
   32.19 +
   32.20 +You should have received a copy of the GNU General Public License
   32.21 +along with XreaL source code; if not, write to the Free Software
   32.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   32.23 +===========================================================================
   32.24 +*/
   32.25 +
   32.26 +uniform sampler2D	u_ColorMap;
   32.27 +uniform int			u_AlphaTest;
   32.28 +uniform int         u_PortalClipping;
   32.29 +uniform vec4		u_PortalPlane;
   32.30 +
   32.31 +varying vec3		var_Position;
   32.32 +varying vec2		var_Tex;
   32.33 +varying vec4		var_Color;
   32.34 +
   32.35 +void	main()
   32.36 +{
   32.37 +	if(bool(u_PortalClipping))
   32.38 +	{
   32.39 +		float dist = dot(var_Position.xyz, u_PortalPlane.xyz) - u_PortalPlane.w;
   32.40 +		if(dist < 0.0)
   32.41 +		{
   32.42 +			discard;
   32.43 +			return;
   32.44 +		}
   32.45 +	}
   32.46 +
   32.47 +	vec4 color = texture2D(u_ColorMap, var_Tex);
   32.48 +	if(u_AlphaTest == ATEST_GT_0 && color.a <= 0.0)
   32.49 +	{
   32.50 +		discard;
   32.51 +		return;
   32.52 +	}
   32.53 +	else if(u_AlphaTest == ATEST_LT_128 && color.a >= 0.5)
   32.54 +	{
   32.55 +		discard;
   32.56 +		return;
   32.57 +	}
   32.58 +	else if(u_AlphaTest == ATEST_GE_128 && color.a < 0.5)
   32.59 +	{
   32.60 +		discard;
   32.61 +		return;
   32.62 +	}
   32.63 +	
   32.64 +	color *= var_Color;
   32.65 +	gl_FragColor = color;
   32.66 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/glsl/genericSingle_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    33.3 @@ -0,0 +1,133 @@
    33.4 +/*
    33.5 +===========================================================================
    33.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    33.7 +
    33.8 +This file is part of XreaL source code.
    33.9 +
   33.10 +XreaL source code is free software; you can redistribute it
   33.11 +and/or modify it under the terms of the GNU General Public License as
   33.12 +published by the Free Software Foundation; either version 2 of the License,
   33.13 +or (at your option) any later version.
   33.14 +
   33.15 +XreaL source code is distributed in the hope that it will be
   33.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   33.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   33.18 +GNU General Public License for more details.
   33.19 +
   33.20 +You should have received a copy of the GNU General Public License
   33.21 +along with XreaL source code; if not, write to the Free Software
   33.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   33.23 +===========================================================================
   33.24 +*/
   33.25 +
   33.26 +attribute vec4		attr_Position;
   33.27 +attribute vec4		attr_TexCoord0;
   33.28 +attribute vec3		attr_Normal;
   33.29 +attribute vec4		attr_Color;
   33.30 +#if defined(r_VertexSkinning)
   33.31 +attribute vec4		attr_BoneIndexes;
   33.32 +attribute vec4		attr_BoneWeights;
   33.33 +uniform int			u_VertexSkinning;
   33.34 +uniform mat4		u_BoneMatrix[MAX_GLSL_BONES];
   33.35 +#endif
   33.36 +
   33.37 +uniform mat4		u_ColorTextureMatrix;
   33.38 +uniform vec3		u_ViewOrigin;
   33.39 +uniform int			u_TCGen_Environment;
   33.40 +uniform int			u_ColorGen;
   33.41 +uniform int			u_AlphaGen;
   33.42 +uniform vec4		u_Color;
   33.43 +uniform mat4		u_ModelMatrix;
   33.44 +//uniform mat4		u_ProjectionMatrix;
   33.45 +uniform mat4		u_ModelViewProjectionMatrix;
   33.46 +
   33.47 +varying vec3		var_Position;
   33.48 +varying vec2		var_Tex;
   33.49 +varying vec4		var_Color;
   33.50 +
   33.51 +void	main()
   33.52 +{
   33.53 +	vec4 position = vec4(0.0);
   33.54 +
   33.55 +#if defined(r_VertexSkinning)
   33.56 +	if(bool(u_VertexSkinning))
   33.57 +	{
   33.58 +		vec4 vertex = vec4(0.0);
   33.59 +		
   33.60 +		for(int i = 0; i < 4; i++)
   33.61 +		{
   33.62 +			int boneIndex = int(attr_BoneIndexes[i]);
   33.63 +			float boneWeight = attr_BoneWeights[i];
   33.64 +			mat4  boneMatrix = u_BoneMatrix[boneIndex];
   33.65 +			
   33.66 +			position += (boneMatrix * attr_Position) * boneWeight;
   33.67 +		}
   33.68 +
   33.69 +		// transform vertex position into homogenous clip-space
   33.70 +		gl_Position = u_ModelViewProjectionMatrix * position;
   33.71 +		
   33.72 +		// transform position into world space
   33.73 +		var_Position = (u_ModelMatrix * vertex).xyz;
   33.74 +	}
   33.75 +	else
   33.76 +#endif
   33.77 +	{
   33.78 +		// transform vertex position into homogenous clip-space
   33.79 +		gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   33.80 +		//gl_Position = u_ProjectionMatrix * u_ModelViewMatrix * attr_Position;
   33.81 +		//gl_Position = u_ProjectionMatrix * attr_Position;
   33.82 +		
   33.83 +		position = attr_Position;
   33.84 +		
   33.85 +		// transform position into world space
   33.86 +		var_Position = (u_ModelMatrix * attr_Position).xyz;
   33.87 +	}
   33.88 +	
   33.89 +	// transform texcoords
   33.90 +	if(bool(u_TCGen_Environment))
   33.91 +	{
   33.92 +		vec3 viewer = normalize(u_ViewOrigin - position.xyz);
   33.93 +
   33.94 +		float d = dot(attr_Normal, viewer);
   33.95 +
   33.96 +		vec3 reflected = attr_Normal * 2.0 * d - viewer;
   33.97 +		
   33.98 +		var_Tex.s = 0.5 + reflected.y * 0.5;
   33.99 +		var_Tex.t = 0.5 - reflected.z * 0.5;
  33.100 +	}
  33.101 +	else
  33.102 +	{
  33.103 +		var_Tex = (u_ColorTextureMatrix * attr_TexCoord0).st;
  33.104 +	}
  33.105 +	
  33.106 +	// assign color
  33.107 +	if(u_ColorGen == CGEN_VERTEX)
  33.108 +	{
  33.109 +		var_Color.r = attr_Color.r;
  33.110 +		var_Color.g = attr_Color.g;
  33.111 +		var_Color.b = attr_Color.b;
  33.112 +	}
  33.113 +	else if(u_ColorGen == CGEN_ONE_MINUS_VERTEX)
  33.114 +	{
  33.115 +		var_Color.r = 1.0 - attr_Color.r;
  33.116 +		var_Color.g = 1.0 - attr_Color.g;
  33.117 +		var_Color.b = 1.0 - attr_Color.b;
  33.118 +	}
  33.119 +	else
  33.120 +	{
  33.121 +		var_Color.rgb = u_Color.rgb;
  33.122 +	}
  33.123 +	
  33.124 +	if(u_AlphaGen == AGEN_VERTEX)
  33.125 +	{
  33.126 +		var_Color.a = attr_Color.a;
  33.127 +	}
  33.128 +	else if(u_AlphaGen == AGEN_ONE_MINUS_VERTEX)
  33.129 +	{
  33.130 +		var_Color.a = 1.0 - attr_Color.a;
  33.131 +	}
  33.132 +	else
  33.133 +	{
  33.134 +		var_Color.a = u_Color.a;
  33.135 +	}
  33.136 +}
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/glsl/geometricFill_DBS_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    34.3 @@ -0,0 +1,210 @@
    34.4 +/*
    34.5 +===========================================================================
    34.6 +Copyright (C) 2007-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    34.7 +
    34.8 +This file is part of XreaL source code.
    34.9 +
   34.10 +XreaL source code is free software; you can redistribute it
   34.11 +and/or modify it under the terms of the GNU General Public License as
   34.12 +published by the Free Software Foundation; either version 2 of the License,
   34.13 +or (at your option) any later version.
   34.14 +
   34.15 +XreaL source code is distributed in the hope that it will be
   34.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   34.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   34.18 +GNU General Public License for more details.
   34.19 +
   34.20 +You should have received a copy of the GNU General Public License
   34.21 +along with XreaL source code; if not, write to the Free Software
   34.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   34.23 +===========================================================================
   34.24 +*/
   34.25 +
   34.26 +#extension GL_ARB_draw_buffers : enable
   34.27 +
   34.28 +uniform sampler2D	u_DiffuseMap;
   34.29 +uniform sampler2D	u_NormalMap;
   34.30 +uniform sampler2D	u_SpecularMap;
   34.31 +uniform int			u_AlphaTest;
   34.32 +uniform vec3		u_ViewOrigin;
   34.33 +uniform vec3        u_AmbientColor;
   34.34 +uniform int			u_ParallaxMapping;
   34.35 +uniform float		u_DepthScale;
   34.36 +uniform mat4		u_ModelMatrix;
   34.37 +
   34.38 +varying vec4		var_Position;
   34.39 +varying vec2		var_TexDiffuse;
   34.40 +#if defined(r_NormalMapping)
   34.41 +varying vec2		var_TexNormal;
   34.42 +varying vec2		var_TexSpecular;
   34.43 +varying vec4		var_Tangent;
   34.44 +varying vec4		var_Binormal;
   34.45 +#endif
   34.46 +varying vec4		var_Normal;
   34.47 +
   34.48 +
   34.49 +#if defined(r_ParallaxMapping)
   34.50 +float RayIntersectDisplaceMap(vec2 dp, vec2 ds)
   34.51 +{
   34.52 +	const int linearSearchSteps = 16;
   34.53 +	const int binarySearchSteps = 6;
   34.54 +
   34.55 +	float depthStep = 1.0 / float(linearSearchSteps);
   34.56 +
   34.57 +	// current size of search window
   34.58 +	float size = depthStep;
   34.59 +
   34.60 +	// current depth position
   34.61 +	float depth = 0.0;
   34.62 +
   34.63 +	// best match found (starts with last position 1.0)
   34.64 +	float bestDepth = 1.0;
   34.65 +
   34.66 +	// search front to back for first point inside object
   34.67 +	for(int i = 0; i < linearSearchSteps - 1; ++i)
   34.68 +	{
   34.69 +		depth += size;
   34.70 +		
   34.71 +		vec4 t = texture2D(u_NormalMap, dp + ds * depth);
   34.72 +
   34.73 +		if(bestDepth > 0.996)		// if no depth found yet
   34.74 +			if(depth >= t.w)
   34.75 +				bestDepth = depth;	// store best depth
   34.76 +	}
   34.77 +
   34.78 +	depth = bestDepth;
   34.79 +	
   34.80 +	// recurse around first point (depth) for closest match
   34.81 +	for(int i = 0; i < binarySearchSteps; ++i)
   34.82 +	{
   34.83 +		size *= 0.5;
   34.84 +
   34.85 +		vec4 t = texture2D(u_NormalMap, dp + ds * depth);
   34.86 +		
   34.87 +		if(depth >= t.w)
   34.88 +		#ifdef RM_DOUBLEDEPTH
   34.89 +			if(depth <= t.z)
   34.90 +		#endif
   34.91 +			{
   34.92 +				bestDepth = depth;
   34.93 +				depth -= 2.0 * size;
   34.94 +			}
   34.95 +
   34.96 +		depth += size;
   34.97 +	}
   34.98 +
   34.99 +	return bestDepth;
  34.100 +}
  34.101 +#endif
  34.102 +
  34.103 +void	main()
  34.104 +{
  34.105 +#if defined(r_NormalMapping)
  34.106 +	// invert tangent space for two sided surfaces
  34.107 +	mat3 tangentToWorldMatrix;
  34.108 +	if(gl_FrontFacing)
  34.109 +		tangentToWorldMatrix = mat3(-var_Tangent.xyz, -var_Binormal.xyz, -var_Normal.xyz);
  34.110 +	else
  34.111 +		tangentToWorldMatrix = mat3(var_Tangent.xyz, var_Binormal.xyz, var_Normal.xyz);
  34.112 +#endif
  34.113 +		
  34.114 +	vec2 texDiffuse = var_TexDiffuse.st;
  34.115 +#if defined(r_NormalMapping)
  34.116 +	vec2 texNormal = var_TexNormal.st;
  34.117 +	vec2 texSpecular = var_TexSpecular.st;
  34.118 +#endif
  34.119 +
  34.120 +#if defined(r_ParallaxMapping)
  34.121 +	if(bool(u_ParallaxMapping))
  34.122 +	{
  34.123 +		// construct tangent-world-space-to-tangent-space 3x3 matrix
  34.124 +		#if defined(GLHW_ATI) || defined(GLHW_ATI_DX10)
  34.125 +	
  34.126 +		mat3 worldToTangentMatrix;
  34.127 +		/*
  34.128 +		for(int i = 0; i < 3; ++i)
  34.129 +		{
  34.130 +			for(int j = 0; j < 3; ++j)
  34.131 +				worldToTangentMatrix[i][j] = tangentToWorldMatrix[j][i];
  34.132 +		}
  34.133 +		*/
  34.134 +		
  34.135 +		worldToTangentMatrix = mat3(tangentToWorldMatrix[0][0], tangentToWorldMatrix[1][0], tangentToWorldMatrix[2][0],
  34.136 +									tangentToWorldMatrix[0][1], tangentToWorldMatrix[1][1], tangentToWorldMatrix[2][1], 
  34.137 +									tangentToWorldMatrix[0][2], tangentToWorldMatrix[1][2], tangentToWorldMatrix[2][2]);
  34.138 +		#else
  34.139 +		mat3 worldToTangentMatrix = transpose(tangentToWorldMatrix);
  34.140 +		#endif
  34.141 +	
  34.142 +		// compute view direction in tangent space
  34.143 +		vec3 V = worldToTangentMatrix * (u_ViewOrigin - var_Position.xyz);
  34.144 +		V = normalize(V);
  34.145 +		
  34.146 +		// ray intersect in view direction
  34.147 +		
  34.148 +		// size and start position of search in texture space
  34.149 +		vec2 S = V.xy * -u_DepthScale / V.z;
  34.150 +			
  34.151 +		float depth = RayIntersectDisplaceMap(texNormal, S);
  34.152 +		
  34.153 +		// compute texcoords offset
  34.154 +		vec2 texOffset = S * depth;
  34.155 +		
  34.156 +		texDiffuse.st += texOffset;
  34.157 +		texNormal.st += texOffset;
  34.158 +		texSpecular.st += texOffset;
  34.159 +	}
  34.160 +#endif
  34.161 +		
  34.162 +	vec4 diffuse = texture2D(u_DiffuseMap, texDiffuse);
  34.163 +	if(u_AlphaTest == ATEST_GT_0 && diffuse.a <= 0.0)
  34.164 +	{
  34.165 +		discard;
  34.166 +		return;
  34.167 +	}
  34.168 +	else if(u_AlphaTest == ATEST_LT_128 && diffuse.a >= 0.5)
  34.169 +	{
  34.170 +		discard;
  34.171 +		return;
  34.172 +	}
  34.173 +	else if(u_AlphaTest == ATEST_GE_128 && diffuse.a < 0.5)
  34.174 +	{
  34.175 +		discard;
  34.176 +		return;
  34.177 +	}
  34.178 +	
  34.179 +	vec4 depthColor = diffuse;
  34.180 +	depthColor.rgb *= u_AmbientColor;
  34.181 +	
  34.182 +#if defined(r_NormalMapping)
  34.183 +	// compute normal in tangent space from normalmap
  34.184 +	vec3 N = 2.0 * (texture2D(u_NormalMap, texNormal).xyz - 0.5);
  34.185 +	//N.z = sqrt(1.0 - dot(N.xy, N.xy));
  34.186 +	#if defined(r_NormalScale)
  34.187 +	N.z *= r_NormalScale;
  34.188 +	normalize(N);
  34.189 +	#endif
  34.190 +	
  34.191 +	// transform normal into world space
  34.192 +	N = tangentToWorldMatrix * N;
  34.193 +	
  34.194 +	vec3 specular = texture2D(u_SpecularMap, texSpecular).rgb;
  34.195 +#else
  34.196 +	vec3 N;
  34.197 +	if(gl_FrontFacing)
  34.198 +		N = -normalize(var_Normal.xyz);
  34.199 +	else
  34.200 +		N = normalize(var_Normal.xyz);
  34.201 +#endif
  34.202 +
  34.203 +	// convert normal back to [0,1] color space
  34.204 +	N = N * 0.5 + 0.5;
  34.205 +
  34.206 +	gl_FragData[0] = vec4(diffuse.rgb, 0.0);
  34.207 +	gl_FragData[1] = vec4(N, 0.0);
  34.208 +#if defined(r_NormalMapping)
  34.209 +	gl_FragData[2] = vec4(specular, 0.0);
  34.210 +#endif
  34.211 +}
  34.212 +
  34.213 +
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/glsl/geometricFill_DBS_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    35.3 @@ -0,0 +1,115 @@
    35.4 +/*
    35.5 +===========================================================================
    35.6 +Copyright (C) 2007-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    35.7 +
    35.8 +This file is part of XreaL source code.
    35.9 +
   35.10 +XreaL source code is free software; you can redistribute it
   35.11 +and/or modify it under the terms of the GNU General Public License as
   35.12 +published by the Free Software Foundation; either version 2 of the License,
   35.13 +or (at your option) any later version.
   35.14 +
   35.15 +XreaL source code is distributed in the hope that it will be
   35.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   35.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   35.18 +GNU General Public License for more details.
   35.19 +
   35.20 +You should have received a copy of the GNU General Public License
   35.21 +along with XreaL source code; if not, write to the Free Software
   35.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   35.23 +===========================================================================
   35.24 +*/
   35.25 +
   35.26 +attribute vec4		attr_Position;
   35.27 +attribute vec4		attr_TexCoord0;
   35.28 +attribute vec3		attr_Tangent;
   35.29 +attribute vec3		attr_Binormal;
   35.30 +attribute vec3		attr_Normal;
   35.31 +#if defined(r_VertexSkinning)
   35.32 +attribute vec4		attr_BoneIndexes;
   35.33 +attribute vec4		attr_BoneWeights;
   35.34 +uniform int			u_VertexSkinning;
   35.35 +uniform mat4		u_BoneMatrix[MAX_GLSL_BONES];
   35.36 +#endif
   35.37 +
   35.38 +uniform mat4		u_DiffuseTextureMatrix;
   35.39 +uniform mat4		u_NormalTextureMatrix;
   35.40 +uniform mat4		u_SpecularTextureMatrix;
   35.41 +uniform mat4		u_ModelMatrix;
   35.42 +uniform mat4		u_ModelViewProjectionMatrix;
   35.43 +
   35.44 +varying vec4		var_Position;
   35.45 +varying vec2		var_TexDiffuse;
   35.46 +#if defined(r_NormalMapping)
   35.47 +varying vec2		var_TexNormal;
   35.48 +varying vec2		var_TexSpecular;
   35.49 +varying vec4		var_Tangent;
   35.50 +varying vec4		var_Binormal;
   35.51 +#endif
   35.52 +varying vec4		var_Normal;
   35.53 +
   35.54 +void	main()
   35.55 +{
   35.56 +#if defined(r_VertexSkinning)
   35.57 +	if(bool(u_VertexSkinning))
   35.58 +	{
   35.59 +		vec4 vertex = vec4(0.0);
   35.60 +		vec3 tangent = vec3(0.0);
   35.61 +		vec3 binormal = vec3(0.0);
   35.62 +		vec3 normal = vec3(0.0);
   35.63 +
   35.64 +		for(int i = 0; i < 4; i++)
   35.65 +		{
   35.66 +			int boneIndex = int(attr_BoneIndexes[i]);
   35.67 +			float boneWeight = attr_BoneWeights[i];
   35.68 +			mat4  boneMatrix = u_BoneMatrix[boneIndex];
   35.69 +			
   35.70 +			vertex += (boneMatrix * attr_Position) * boneWeight;
   35.71 +		
   35.72 +			tangent += (boneMatrix * vec4(attr_Tangent, 0.0)).xyz * boneWeight;
   35.73 +			binormal += (boneMatrix * vec4(attr_Binormal, 0.0)).xyz * boneWeight;
   35.74 +			normal += (boneMatrix * vec4(attr_Normal, 0.0)).xyz * boneWeight;
   35.75 +		}
   35.76 +
   35.77 +		// transform vertex position into homogenous clip-space
   35.78 +		gl_Position = u_ModelViewProjectionMatrix * vertex;
   35.79 +		
   35.80 +		// transform position into world space
   35.81 +		var_Position = u_ModelMatrix * vertex;
   35.82 +		
   35.83 +		#if defined(r_NormalMapping)
   35.84 +		var_Tangent.xyz = (u_ModelMatrix * vec4(tangent, 0.0)).xyz;
   35.85 +		var_Binormal.xyz = (u_ModelMatrix * vec4(binormal, 0.0)).xyz;
   35.86 +		#endif
   35.87 +		
   35.88 +		var_Normal.xyz = (u_ModelMatrix * vec4(normal, 0.0)).xyz;
   35.89 +	}
   35.90 +	else
   35.91 +#endif
   35.92 +	{
   35.93 +		// transform vertex position into homogenous clip-space
   35.94 +		gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   35.95 +		
   35.96 +		// transform position into world space
   35.97 +		var_Position = u_ModelMatrix * attr_Position;
   35.98 +	
   35.99 +		#if defined(r_NormalMapping)
  35.100 +		var_Tangent.xyz = (u_ModelMatrix * vec4(attr_Tangent, 0.0)).xyz;
  35.101 +		var_Binormal.xyz = (u_ModelMatrix * vec4(attr_Binormal, 0.0)).xyz;
  35.102 +		#endif
  35.103 +		
  35.104 +		var_Normal.xyz = (u_ModelMatrix * vec4(attr_Normal, 0.0)).xyz;
  35.105 +	}
  35.106 +
  35.107 +	// transform diffusemap texcoords
  35.108 +	var_TexDiffuse = (u_DiffuseTextureMatrix * attr_TexCoord0).st;
  35.109 +
  35.110 +#if defined(r_NormalMapping)	
  35.111 +	// transform normalmap texcoords
  35.112 +	var_TexNormal = (u_NormalTextureMatrix * attr_TexCoord0).st;
  35.113 +	
  35.114 +	// transform specularmap texture coords
  35.115 +	var_TexSpecular = (u_SpecularTextureMatrix * attr_TexCoord0).st;
  35.116 +#endif
  35.117 +}
  35.118 +
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/glsl/heatHaze_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    36.3 @@ -0,0 +1,89 @@
    36.4 +/*
    36.5 +===========================================================================
    36.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    36.7 +Copyright (C) 2006 defconx          <defcon-x@ns-co.net>
    36.8 +
    36.9 +This file is part of XreaL source code.
   36.10 +
   36.11 +XreaL source code is free software; you can redistribute it
   36.12 +and/or modify it under the terms of the GNU General Public License as
   36.13 +published by the Free Software Foundation; either version 2 of the License,
   36.14 +or (at your option) any later version.
   36.15 +
   36.16 +XreaL source code is distributed in the hope that it will be
   36.17 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   36.18 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   36.19 +GNU General Public License for more details.
   36.20 +
   36.21 +You should have received a copy of the GNU General Public License
   36.22 +along with XreaL source code; if not, write to the Free Software
   36.23 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   36.24 +===========================================================================
   36.25 +*/
   36.26 +
   36.27 +uniform sampler2D	u_NormalMap;
   36.28 +uniform sampler2D	u_CurrentMap;
   36.29 +#if defined(r_heatHazeFix)
   36.30 +uniform sampler2D	u_ContrastMap;
   36.31 +#endif
   36.32 +uniform int			u_AlphaTest;
   36.33 +
   36.34 +varying vec2		var_TexNormal;
   36.35 +varying float		var_Deform;
   36.36 +
   36.37 +void	main()
   36.38 +{
   36.39 +	vec4 color0, color1;
   36.40 +
   36.41 +	// compute normal in tangent space from normalmap
   36.42 +	color0 = texture2D(u_NormalMap, var_TexNormal).rgba;
   36.43 +	vec3 N = 2.0 * (color0.rgb.xyz - 0.5);
   36.44 +
   36.45 +	// calculate the screen texcoord in the 0.0 to 1.0 range
   36.46 +	vec2 st = gl_FragCoord.st * r_FBufScale;
   36.47 +
   36.48 +	if(u_AlphaTest == ATEST_GT_0 && color0.a <= 0.0)
   36.49 +	{
   36.50 +		discard;
   36.51 +		return;
   36.52 +	}
   36.53 +	else if(u_AlphaTest == ATEST_LT_128 && color0.a >= 0.5)
   36.54 +	{
   36.55 +		discard;
   36.56 +		return;
   36.57 +	}
   36.58 +	else if(u_AlphaTest == ATEST_GE_128 && color0.a < 0.5)
   36.59 +	{
   36.60 +		discard;
   36.61 +		return;
   36.62 +	}
   36.63 +	
   36.64 +	// offset by the scaled normal and clamp it to 0.0 - 1.0
   36.65 +	st += N.xy * var_Deform;
   36.66 +	st = clamp(st, 0.0, 1.0);
   36.67 +	
   36.68 +	// scale by the screen non-power-of-two-adjust
   36.69 +	st *= r_NPOTScale;
   36.70 +	
   36.71 +#if defined(r_heatHazeFix)
   36.72 +	// check if the distortion got too far
   36.73 +	float vis = texture2D(u_ContrastMap, st).r;
   36.74 +	if(vis > 0.0)
   36.75 +	{
   36.76 +		color0 = texture2D(u_CurrentMap, st);
   36.77 +		color1 = vec4(0.0, 1.0, 0.0, color0.a);
   36.78 +	}
   36.79 +	else
   36.80 +	{
   36.81 +		// reset st and don't offset
   36.82 +		st = gl_FragCoord.st * r_FBufScale * r_NPOTScale;
   36.83 +		
   36.84 +		color0 = texture2D(u_CurrentMap, st);
   36.85 +		color1 = vec4(1.0, 0.0, 0.0, color0.a);
   36.86 +	}
   36.87 +#else
   36.88 +	color0 = texture2D(u_CurrentMap, st);
   36.89 +#endif
   36.90 +	
   36.91 +	gl_FragColor = color0;
   36.92 +}
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/glsl/heatHaze_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    37.3 @@ -0,0 +1,88 @@
    37.4 +/*
    37.5 +===========================================================================
    37.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    37.7 +Copyright (C) 2006 defconx          <defcon-x@ns-co.net>
    37.8 +
    37.9 +This file is part of XreaL source code.
   37.10 +
   37.11 +XreaL source code is free software; you can redistribute it
   37.12 +and/or modify it under the terms of the GNU General Public License as
   37.13 +published by the Free Software Foundation; either version 2 of the License,
   37.14 +or (at your option) any later version.
   37.15 +
   37.16 +XreaL source code is distributed in the hope that it will be
   37.17 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   37.18 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   37.19 +GNU General Public License for more details.
   37.20 +
   37.21 +You should have received a copy of the GNU General Public License
   37.22 +along with XreaL source code; if not, write to the Free Software
   37.23 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   37.24 +===========================================================================
   37.25 +*/
   37.26 +
   37.27 +attribute vec4		attr_Position;
   37.28 +attribute vec4		attr_TexCoord0;
   37.29 +#if defined(r_VertexSkinning)
   37.30 +attribute vec4		attr_BoneIndexes;
   37.31 +attribute vec4		attr_BoneWeights;
   37.32 +uniform int			u_VertexSkinning;
   37.33 +uniform mat4		u_BoneMatrix[MAX_GLSL_BONES];
   37.34 +#endif
   37.35 +
   37.36 +uniform mat4		u_NormalTextureMatrix;
   37.37 +uniform mat4		u_ProjectionMatrixTranspose;
   37.38 +uniform mat4		u_ModelViewMatrixTranspose;
   37.39 +uniform mat4		u_ModelViewProjectionMatrix;
   37.40 +
   37.41 +uniform float		u_DeformMagnitude;
   37.42 +
   37.43 +varying vec2		var_TexNormal;
   37.44 +varying float		var_Deform;
   37.45 +
   37.46 +void	main()
   37.47 +{
   37.48 +	vec4            deformVec;
   37.49 +    float           d1, d2;	
   37.50 +
   37.51 +#if defined(r_VertexSkinning)
   37.52 +	if(bool(u_VertexSkinning))
   37.53 +	{
   37.54 +		vec4 vertex = vec4(0.0);
   37.55 +		
   37.56 +		for(int i = 0; i < 4; i++)
   37.57 +		{
   37.58 +			int boneIndex = int(attr_BoneIndexes[i]);
   37.59 +			float boneWeight = attr_BoneWeights[i];
   37.60 +			mat4  boneMatrix = u_BoneMatrix[boneIndex];
   37.61 +			
   37.62 +			vertex += (boneMatrix * attr_Position) * boneWeight;
   37.63 +		}
   37.64 +
   37.65 +		// transform vertex position into homogenous clip-space
   37.66 +		gl_Position = u_ModelViewProjectionMatrix * vertex;
   37.67 +		
   37.68 +		// take the deform magnitude and scale it by the projection distance
   37.69 +		deformVec = vec4(1, 0, 0, 1);
   37.70 +		deformVec.z = dot(u_ModelViewMatrixTranspose[2], vertex);
   37.71 +	}
   37.72 +	else
   37.73 +#endif
   37.74 +	{
   37.75 +		// transform vertex position into homogenous clip-space
   37.76 +		gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   37.77 +		
   37.78 +		// take the deform magnitude and scale it by the projection distance
   37.79 +		deformVec = vec4(1, 0, 0, 1);
   37.80 +		deformVec.z = dot(u_ModelViewMatrixTranspose[2], attr_Position);
   37.81 +	}
   37.82 +	
   37.83 +	// transform normalmap texcoords
   37.84 +	var_TexNormal = (u_NormalTextureMatrix * attr_TexCoord0).st;
   37.85 +
   37.86 +	d1 = dot(u_ProjectionMatrixTranspose[0],  deformVec);
   37.87 +    d2 = dot(u_ProjectionMatrixTranspose[3],  deformVec);
   37.88 +	
   37.89 +	// clamp the distance so the the deformations don't get too wacky near the view
   37.90 +	var_Deform = min(d1 * (1.0 / max(d2, 1.0)), 0.02) * u_DeformMagnitude;
   37.91 +}
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/glsl/lightMapping_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    38.3 @@ -0,0 +1,61 @@
    38.4 +/*
    38.5 +===========================================================================
    38.6 +Copyright (C) 2008-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    38.7 +
    38.8 +This file is part of XreaL source code.
    38.9 +
   38.10 +XreaL source code is free software; you can redistribute it
   38.11 +and/or modify it under the terms of the GNU General Public License as
   38.12 +published by the Free Software Foundation; either version 2 of the License,
   38.13 +or (at your option) any later version.
   38.14 +
   38.15 +XreaL source code is distributed in the hope that it will be
   38.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   38.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   38.18 +GNU General Public License for more details.
   38.19 +
   38.20 +You should have received a copy of the GNU General Public License
   38.21 +along with XreaL source code; if not, write to the Free Software
   38.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   38.23 +===========================================================================
   38.24 +*/
   38.25 +
   38.26 +uniform sampler2D	u_DiffuseMap;
   38.27 +uniform sampler2D	u_LightMap;
   38.28 +uniform int			u_AlphaTest;
   38.29 +
   38.30 +varying vec2		var_TexDiffuse;
   38.31 +varying vec2		var_TexLight;
   38.32 +
   38.33 +
   38.34 +void	main()
   38.35 +{
   38.36 +	// compute the diffuse term
   38.37 +	vec4 diffuse = texture2D(u_DiffuseMap, var_TexDiffuse);
   38.38 +	if(u_AlphaTest == ATEST_GT_0 && diffuse.a <= 0.0)
   38.39 +	{
   38.40 +		discard;
   38.41 +		return;
   38.42 +	}
   38.43 +	else if(u_AlphaTest == ATEST_LT_128 && diffuse.a >= 0.5)
   38.44 +	{
   38.45 +		discard;
   38.46 +		return;
   38.47 +	}
   38.48 +	else if(u_AlphaTest == ATEST_GE_128 && diffuse.a < 0.5)
   38.49 +	{
   38.50 +		discard;
   38.51 +		return;
   38.52 +	}
   38.53 +
   38.54 +#if defined(r_showLightMaps)
   38.55 +	gl_FragColor = texture2D(u_LightMap, var_TexLight);
   38.56 +#else
   38.57 +	// compute light color from object space lightmap
   38.58 +	vec3 lightColor = texture2D(u_LightMap, var_TexLight).rgb;
   38.59 +	
   38.60 +	diffuse.rgb *= lightColor;
   38.61 +	
   38.62 +	gl_FragColor = diffuse;
   38.63 +#endif
   38.64 +}
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/glsl/lightMapping_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    39.3 @@ -0,0 +1,49 @@
    39.4 +/*
    39.5 +===========================================================================
    39.6 +Copyright (C) 2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    39.7 +
    39.8 +This file is part of XreaL source code.
    39.9 +
   39.10 +XreaL source code is free software; you can redistribute it
   39.11 +and/or modify it under the terms of the GNU General Public License as
   39.12 +published by the Free Software Foundation; either version 2 of the License,
   39.13 +or (at your option) any later version.
   39.14 +
   39.15 +XreaL source code is distributed in the hope that it will be
   39.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   39.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   39.18 +GNU General Public License for more details.
   39.19 +
   39.20 +You should have received a copy of the GNU General Public License
   39.21 +along with XreaL source code; if not, write to the Free Software
   39.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   39.23 +===========================================================================
   39.24 +*/
   39.25 +
   39.26 +attribute vec4		attr_Position;
   39.27 +attribute vec4		attr_TexCoord0;
   39.28 +attribute vec4		attr_TexCoord1;
   39.29 +
   39.30 +uniform mat4		u_DiffuseTextureMatrix;
   39.31 +uniform mat4		u_ModelViewProjectionMatrix;
   39.32 +
   39.33 +varying vec2		var_TexDiffuse;
   39.34 +varying vec2		var_TexLight;
   39.35 +
   39.36 +void	main()
   39.37 +{
   39.38 +	// transform vertex position into homogenous clip-space
   39.39 +#if 1
   39.40 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   39.41 +#else
   39.42 +	gl_Position.xy = attr_TexCoord1 * 2.0 - 1.0;
   39.43 +	gl_Position.z = 0.0;
   39.44 +	gl_Position.w = 1.0;
   39.45 +#endif
   39.46 +	
   39.47 +	// transform diffusemap texcoords
   39.48 +	var_TexDiffuse = (u_DiffuseTextureMatrix * attr_TexCoord0).st;
   39.49 +	
   39.50 +	// transform lightmap texcoords
   39.51 +	var_TexLight = attr_TexCoord1.st;
   39.52 +}
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/glsl/lightVolume_omni_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    40.3 @@ -0,0 +1,113 @@
    40.4 +/*
    40.5 +===========================================================================
    40.6 +Copyright (C) 2007 Robert Beckebans <trebor_7@users.sourceforge.net>
    40.7 +
    40.8 +This file is part of XreaL source code.
    40.9 +
   40.10 +XreaL source code is free software; you can redistribute it
   40.11 +and/or modify it under the terms of the GNU General Public License as
   40.12 +published by the Free Software Foundation; either version 2 of the License,
   40.13 +or (at your option) any later version.
   40.14 +
   40.15 +XreaL source code is distributed in the hope that it will be
   40.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   40.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   40.18 +GNU General Public License for more details.
   40.19 +
   40.20 +You should have received a copy of the GNU General Public License
   40.21 +along with XreaL source code; if not, write to the Free Software
   40.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   40.23 +===========================================================================
   40.24 +*/
   40.25 +
   40.26 +uniform sampler2D	u_AttenuationMapXY;
   40.27 +uniform sampler2D	u_AttenuationMapZ;
   40.28 +uniform samplerCube	u_ShadowMap;
   40.29 +uniform vec3		u_ViewOrigin;
   40.30 +uniform vec3		u_LightOrigin;
   40.31 +uniform vec3		u_LightColor;
   40.32 +uniform float		u_LightRadius;
   40.33 +uniform float       u_LightScale;
   40.34 +uniform mat4		u_LightAttenuationMatrix;
   40.35 +uniform int			u_ShadowCompare;
   40.36 +uniform mat4		u_ModelMatrix;
   40.37 +
   40.38 +varying vec3		var_Position;
   40.39 +varying vec2		var_TexDiffuse;
   40.40 +varying vec3		var_TexAttenXYZ;
   40.41 +
   40.42 +void	main()
   40.43 +{
   40.44 +	// compute incident ray in world space
   40.45 +	vec3 I = normalize(u_ViewOrigin - var_Position);
   40.46 +	//vec3 I = normalize(var_Position - u_ViewOrigin);
   40.47 +	
   40.48 +	vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
   40.49 +	
   40.50 +	int steps = 40;
   40.51 +	float stepSize = u_LightRadius / float(steps);
   40.52 +	
   40.53 +	for(int i = 0; i < steps; i++)
   40.54 +	{
   40.55 +		vec3 P = var_Position + (I * stepSize * float(i));
   40.56 +	
   40.57 +		// compute attenuation
   40.58 +		vec3 texAttenXYZ		= (u_LightAttenuationMatrix * vec4(P, 1.0)).xyz;
   40.59 +		vec3 attenuationXY		= texture2D(u_AttenuationMapXY, texAttenXYZ.xy).rgb;
   40.60 +		vec3 attenuationZ		= texture2D(u_AttenuationMapZ, vec2(texAttenXYZ.z, 0)).rgb;
   40.61 +		
   40.62 +		float shadow = 1.0;
   40.63 +
   40.64 +		#if defined(VSM)
   40.65 +		if(bool(u_ShadowCompare))
   40.66 +		{
   40.67 +			// compute incident ray
   40.68 +			vec3 I = P - u_LightOrigin;
   40.69 +			
   40.70 +			vec4 shadowMoments = textureCube(u_ShadowMap, I);
   40.71 +			
   40.72 +			#if defined(VSM_CLAMP)
   40.73 +			// convert to [-1, 1] vector space
   40.74 +			shadowMoments = 0.5 * (shadowMoments + 1.0);
   40.75 +			#endif
   40.76 +	
   40.77 +			float shadowDistance = shadowMoments.r;
   40.78 +			float shadowDistanceSquared = shadowMoments.g;
   40.79 +		
   40.80 +			const float	SHADOW_BIAS = 0.001;
   40.81 +			float vertexDistance = length(I) / u_LightRadius - SHADOW_BIAS;
   40.82 +	
   40.83 +			// standard shadow map comparison
   40.84 +			shadow = vertexDistance <= shadowDistance ? 1.0 : 0.0;
   40.85 +	
   40.86 +			// variance shadow mapping
   40.87 +			float E_x2 = shadowDistanceSquared;
   40.88 +			float Ex_2 = shadowDistance * shadowDistance;
   40.89 +	
   40.90 +			// AndyTX: VSM_EPSILON is there to avoid some ugly numeric instability with fp16
   40.91 +			float variance = min(max(E_x2 - Ex_2, 0.0) + VSM_EPSILON, 1.0);
   40.92 +	
   40.93 +			float mD = shadowDistance - vertexDistance;
   40.94 +			float mD_2 = mD * mD;
   40.95 +			float p = variance / (variance + mD_2);
   40.96 +	
   40.97 +			color.rgb += attenuationXY * attenuationZ * max(shadow, p);
   40.98 +		}
   40.99 +		
  40.100 +		if(shadow <= 0.0)
  40.101 +		{
  40.102 +			continue;
  40.103 +		}
  40.104 +		else
  40.105 +		#endif
  40.106 +		{
  40.107 +			color.rgb += attenuationXY * attenuationZ;
  40.108 +		}
  40.109 +	}
  40.110 +	
  40.111 +	color.rgb /= float(steps);
  40.112 +	color.rgb *= u_LightColor;
  40.113 +	//color.rgb *= u_LightScale;
  40.114 +
  40.115 +	gl_FragColor = color;
  40.116 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/glsl/lightVolume_omni_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    41.3 @@ -0,0 +1,38 @@
    41.4 +/*
    41.5 +===========================================================================
    41.6 +Copyright (C) 2007-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    41.7 +
    41.8 +This file is part of XreaL source code.
    41.9 +
   41.10 +XreaL source code is free software; you can redistribute it
   41.11 +and/or modify it under the terms of the GNU General Public License as
   41.12 +published by the Free Software Foundation; either version 2 of the License,
   41.13 +or (at your option) any later version.
   41.14 +
   41.15 +XreaL source code is distributed in the hope that it will be
   41.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   41.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   41.18 +GNU General Public License for more details.
   41.19 +
   41.20 +You should have received a copy of the GNU General Public License
   41.21 +along with XreaL source code; if not, write to the Free Software
   41.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   41.23 +===========================================================================
   41.24 +*/
   41.25 +
   41.26 +attribute vec4		attr_Position;
   41.27 +attribute vec4		attr_TexCoord0;
   41.28 +
   41.29 +uniform mat4		u_ModelMatrix;
   41.30 +uniform mat4		u_ModelViewProjectionMatrix;
   41.31 +
   41.32 +varying vec3		var_Position;
   41.33 +
   41.34 +void	main()
   41.35 +{
   41.36 +	// transform vertex position into homogenous clip-space
   41.37 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   41.38 +	
   41.39 +	// transform position into world space
   41.40 +	var_Position = (u_ModelMatrix * attr_Position).xyz;
   41.41 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/glsl/liquid_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    42.3 @@ -0,0 +1,198 @@
    42.4 +/*
    42.5 +===========================================================================
    42.6 +Copyright (C) 2007-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    42.7 +
    42.8 +This file is part of XreaL source code.
    42.9 +
   42.10 +XreaL source code is free software; you can redistribute it
   42.11 +and/or modify it under the terms of the GNU General Public License as
   42.12 +published by the Free Software Foundation; either version 2 of the License,
   42.13 +or (at your option) any later version.
   42.14 +
   42.15 +XreaL source code is distributed in the hope that it will be
   42.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   42.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   42.18 +GNU General Public License for more details.
   42.19 +
   42.20 +You should have received a copy of the GNU General Public License
   42.21 +along with XreaL source code; if not, write to the Free Software
   42.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   42.23 +===========================================================================
   42.24 +*/
   42.25 +
   42.26 +uniform sampler2D	u_CurrentMap;
   42.27 +uniform sampler2D	u_PortalMap;
   42.28 +uniform sampler2D	u_DepthMap;
   42.29 +uniform sampler2D	u_NormalMap;
   42.30 +uniform vec3		u_ViewOrigin;
   42.31 +uniform float		u_FogDensity;
   42.32 +uniform vec3		u_FogColor;
   42.33 +uniform float		u_RefractionIndex;
   42.34 +uniform float		u_FresnelPower;
   42.35 +uniform float		u_FresnelScale;
   42.36 +uniform float		u_FresnelBias;
   42.37 +uniform float		u_NormalScale;
   42.38 +uniform mat4		u_ModelMatrix;
   42.39 +uniform mat4		u_UnprojectMatrix;
   42.40 +
   42.41 +varying vec3		var_Position;
   42.42 +varying vec2		var_TexNormal;
   42.43 +varying vec3		var_Tangent;
   42.44 +varying vec3		var_Binormal;
   42.45 +varying vec3		var_Normal;
   42.46 +varying vec4		var_LightColor;
   42.47 +varying vec3		var_LightDirection;
   42.48 +
   42.49 +#if defined(r_ParallaxMapping)
   42.50 +float RayIntersectDisplaceMap(vec2 dp, vec2 ds)
   42.51 +{
   42.52 +	const int linearSearchSteps = 16;
   42.53 +	const int binarySearchSteps = 6;
   42.54 +
   42.55 +	float depthStep = 1.0 / float(linearSearchSteps);
   42.56 +
   42.57 +	// current size of search window
   42.58 +	float size = depthStep;
   42.59 +
   42.60 +	// current depth position
   42.61 +	float depth = 0.0;
   42.62 +
   42.63 +	// best match found (starts with last position 1.0)
   42.64 +	float bestDepth = 1.0;
   42.65 +
   42.66 +	// search front to back for first point inside object
   42.67 +	for(int i = 0; i < linearSearchSteps - 1; ++i)
   42.68 +	{
   42.69 +		depth += size;
   42.70 +		
   42.71 +		vec4 t = texture2D(u_NormalMap, dp + ds * depth);
   42.72 +
   42.73 +		if(bestDepth > 0.996)		// if no depth found yet
   42.74 +			if(depth >= t.w)
   42.75 +				bestDepth = depth;	// store best depth
   42.76 +	}
   42.77 +
   42.78 +	depth = bestDepth;
   42.79 +	
   42.80 +	// recurse around first point (depth) for closest match
   42.81 +	for(int i = 0; i < binarySearchSteps; ++i)
   42.82 +	{
   42.83 +		size *= 0.5;
   42.84 +
   42.85 +		vec4 t = texture2D(u_NormalMap, dp + ds * depth);
   42.86 +		
   42.87 +		if(depth >= t.w)
   42.88 +		#ifdef RM_DOUBLEDEPTH
   42.89 +			if(depth <= t.z)
   42.90 +		#endif
   42.91 +			{
   42.92 +				bestDepth = depth;
   42.93 +				depth -= 2.0 * size;
   42.94 +			}
   42.95 +
   42.96 +		depth += size;
   42.97 +	}
   42.98 +
   42.99 +	return bestDepth;
  42.100 +}
  42.101 +#endif
  42.102 +
  42.103 +
  42.104 +void	main()
  42.105 +{
  42.106 +	// compute incident ray
  42.107 +	vec3 I = normalize(u_ViewOrigin - var_Position);
  42.108 +	
  42.109 +	mat3 tangentToWorldMatrix;
  42.110 +	if(gl_FrontFacing)
  42.111 +		tangentToWorldMatrix = mat3(-var_Tangent.xyz, -var_Binormal.xyz, -var_Normal.xyz);
  42.112 +	else
  42.113 +		tangentToWorldMatrix = mat3(var_Tangent.xyz, var_Binormal.xyz, var_Normal.xyz);
  42.114 +	
  42.115 +	mat3 worldToTangentMatrix;
  42.116 +#if defined(GLHW_ATI) || defined(GLHW_ATI_DX10) || defined(MESA)
  42.117 +	worldToTangentMatrix = mat3(tangentToWorldMatrix[0][0], tangentToWorldMatrix[1][0], tangentToWorldMatrix[2][0],
  42.118 +								tangentToWorldMatrix[0][1], tangentToWorldMatrix[1][1], tangentToWorldMatrix[2][1], 
  42.119 +								tangentToWorldMatrix[0][2], tangentToWorldMatrix[1][2], tangentToWorldMatrix[2][2]);
  42.120 +#else
  42.121 +	worldToTangentMatrix = transpose(tangentToWorldMatrix);
  42.122 +#endif
  42.123 +
  42.124 +	// calculate the screen texcoord in the 0.0 to 1.0 range
  42.125 +	vec2 texScreen = gl_FragCoord.st * r_FBufScale * r_NPOTScale;
  42.126 +	vec2 texNormal = var_TexNormal.st;
  42.127 +
  42.128 +#if defined(r_ParallaxMapping)
  42.129 +	// compute view direction in tangent space
  42.130 +	vec3 V = worldToTangentMatrix * (I);
  42.131 +	V = normalize(V);
  42.132 +	
  42.133 +	// ray intersect in view direction
  42.134 +	
  42.135 +	// size and start position of search in texture space
  42.136 +	//vec2 S = V.xy * -u_DepthScale / V.z;
  42.137 +	vec2 S = V.xy * -0.03 / V.z;
  42.138 +		
  42.139 +	float depth = RayIntersectDisplaceMap(texNormal, S);
  42.140 +	
  42.141 +	// compute texcoords offset
  42.142 +	vec2 texOffset = S * depth;
  42.143 +	
  42.144 +	texScreen.st += texOffset;
  42.145 +	texNormal.st += texOffset;
  42.146 +#endif
  42.147 +
  42.148 +	// compute normals
  42.149 +	
  42.150 +	vec3 N = normalize(var_Normal);
  42.151 +
  42.152 +	vec3 N2 = 2.0 * (texture2D(u_NormalMap, texNormal).xyz - 0.5);
  42.153 +	N2 = tangentToWorldMatrix * N2;
  42.154 +			
  42.155 +	// compute fresnel term
  42.156 +	float fresnel = clamp(u_FresnelBias + pow(1.0 - dot(I, N), u_FresnelPower) * 
  42.157 +			u_FresnelScale, 0.0, 1.0);
  42.158 +
  42.159 +	texScreen += u_NormalScale * N2.xy;
  42.160 +
  42.161 +	vec3 refractColor = texture2D(u_CurrentMap, texScreen).rgb;
  42.162 +	vec3 reflectColor = texture2D(u_PortalMap, texScreen).rgb;
  42.163 +	
  42.164 +	vec4 color;
  42.165 +
  42.166 +	color.rgb = mix(refractColor, reflectColor, fresnel);
  42.167 +	color.a = 1.0;
  42.168 +
  42.169 +	if(u_FogDensity > 0.0)
  42.170 +	{
  42.171 +		// reconstruct vertex position in world space
  42.172 +		float depth = texture2D(u_DepthMap, texScreen).r;
  42.173 +		vec4 P = u_UnprojectMatrix * vec4(gl_FragCoord.xy, depth, 1.0);
  42.174 +		P.xyz /= P.w;
  42.175 +
  42.176 +		// calculate fog distance
  42.177 +		float fogDistance = distance(P.xyz, var_Position);
  42.178 +	
  42.179 +		// calculate fog exponent
  42.180 +		float fogExponent = fogDistance * u_FogDensity;
  42.181 +	
  42.182 +		// calculate fog factor
  42.183 +		float fogFactor = exp2(-abs(fogExponent));
  42.184 +		
  42.185 +		color.rgb = mix(u_FogColor, color.rgb, fogFactor);
  42.186 +	}
  42.187 +	
  42.188 +	vec3 L = normalize(var_LightDirection);
  42.189 +	
  42.190 +	// compute half angle in world space
  42.191 +	vec3 H = normalize(L + I);
  42.192 +	
  42.193 +	// compute the light term
  42.194 +	vec3 light = var_LightColor.rgb * clamp(dot(N2, L), 0.0, 1.0);
  42.195 +	
  42.196 +	// compute the specular term
  42.197 +	vec3 specular = reflectColor * var_LightColor.rgb * pow(clamp(dot(N2, H), 0.0, 1.0), r_SpecularExponent) * r_SpecularScale;
  42.198 +	color.rgb += specular;
  42.199 +	
  42.200 +	gl_FragColor = color;
  42.201 +}
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/glsl/liquid_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    43.3 @@ -0,0 +1,63 @@
    43.4 +/*
    43.5 +===========================================================================
    43.6 +Copyright (C) 2007-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    43.7 +
    43.8 +This file is part of XreaL source code.
    43.9 +
   43.10 +XreaL source code is free software; you can redistribute it
   43.11 +and/or modify it under the terms of the GNU General Public License as
   43.12 +published by the Free Software Foundation; either version 2 of the License,
   43.13 +or (at your option) any later version.
   43.14 +
   43.15 +XreaL source code is distributed in the hope that it will be
   43.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   43.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   43.18 +GNU General Public License for more details.
   43.19 +
   43.20 +You should have received a copy of the GNU General Public License
   43.21 +along with XreaL source code; if not, write to the Free Software
   43.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   43.23 +===========================================================================
   43.24 +*/
   43.25 +
   43.26 +attribute vec4		attr_Position;
   43.27 +attribute vec4		attr_TexCoord0;
   43.28 +attribute vec3		attr_Tangent;
   43.29 +attribute vec3		attr_Binormal;
   43.30 +attribute vec3		attr_Normal;
   43.31 +attribute vec4		attr_Color;
   43.32 +attribute vec3		attr_LightDirection;
   43.33 +
   43.34 +uniform mat4		u_NormalTextureMatrix;
   43.35 +uniform mat4		u_ModelMatrix;
   43.36 +uniform mat4		u_ModelViewProjectionMatrix;
   43.37 +
   43.38 +varying vec3		var_Position;
   43.39 +varying vec2		var_TexNormal;
   43.40 +varying vec3		var_Tangent;
   43.41 +varying vec3		var_Binormal;
   43.42 +varying vec3		var_Normal;
   43.43 +varying vec4		var_LightColor;
   43.44 +varying vec3		var_LightDirection;
   43.45 +
   43.46 +void	main()
   43.47 +{
   43.48 +	// transform vertex position into homogenous clip-space
   43.49 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   43.50 +	
   43.51 +	// transform position into world space
   43.52 +	var_Position = (u_ModelMatrix * attr_Position).xyz;
   43.53 +	
   43.54 +	// transform normalmap texcoords
   43.55 +	var_TexNormal = (u_NormalTextureMatrix * attr_TexCoord0).st;
   43.56 +	
   43.57 +	var_Tangent.xyz = (u_ModelMatrix * vec4(attr_Tangent, 0.0)).xyz;
   43.58 +	var_Binormal.xyz = (u_ModelMatrix * vec4(attr_Binormal, 0.0)).xyz;
   43.59 +	
   43.60 +	// transform normal into world space
   43.61 +	var_Normal = (u_ModelMatrix * vec4(attr_Normal, 0.0)).xyz;
   43.62 +	
   43.63 +	var_LightColor = attr_Color;
   43.64 +	var_LightDirection = attr_LightDirection;
   43.65 +}
   43.66 +
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/glsl/portal_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    44.3 @@ -0,0 +1,46 @@
    44.4 +/*
    44.5 +===========================================================================
    44.6 +Copyright (C) 2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    44.7 +
    44.8 +This file is part of XreaL source code.
    44.9 +
   44.10 +XreaL source code is free software; you can redistribute it
   44.11 +and/or modify it under the terms of the GNU General Public License as
   44.12 +published by the Free Software Foundation; either version 2 of the License,
   44.13 +or (at your option) any later version.
   44.14 +
   44.15 +XreaL source code is distributed in the hope that it will be
   44.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   44.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   44.18 +GNU General Public License for more details.
   44.19 +
   44.20 +You should have received a copy of the GNU General Public License
   44.21 +along with XreaL source code; if not, write to the Free Software
   44.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   44.23 +===========================================================================
   44.24 +*/
   44.25 +
   44.26 +uniform sampler2D	u_CurrentMap;
   44.27 +uniform float		u_PortalRange;
   44.28 +
   44.29 +varying vec3		var_Position;
   44.30 +varying vec4		var_Color;
   44.31 +
   44.32 +void	main()
   44.33 +{
   44.34 +	// calculate the screen texcoord in the 0.0 to 1.0 range
   44.35 +	vec2 st = gl_FragCoord.st * r_FBufScale;
   44.36 +	
   44.37 +	// scale by the screen non-power-of-two-adjust
   44.38 +	st *= r_NPOTScale;
   44.39 +	
   44.40 +	vec4 color = texture2D(u_CurrentMap, st);
   44.41 +	color *= var_Color;
   44.42 +	
   44.43 +	float len = length(var_Position);
   44.44 +
   44.45 +	len /= u_PortalRange;
   44.46 +	color.rgb *= 1.0 - clamp(len, 0.0, 1.0);
   44.47 +
   44.48 +	gl_FragColor = color;
   44.49 +}
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/glsl/portal_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    45.3 @@ -0,0 +1,42 @@
    45.4 +/*
    45.5 +===========================================================================
    45.6 +Copyright (C) 2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    45.7 +
    45.8 +This file is part of XreaL source code.
    45.9 +
   45.10 +XreaL source code is free software; you can redistribute it
   45.11 +and/or modify it under the terms of the GNU General Public License as
   45.12 +published by the Free Software Foundation; either version 2 of the License,
   45.13 +or (at your option) any later version.
   45.14 +
   45.15 +XreaL source code is distributed in the hope that it will be
   45.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   45.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   45.18 +GNU General Public License for more details.
   45.19 +
   45.20 +You should have received a copy of the GNU General Public License
   45.21 +along with XreaL source code; if not, write to the Free Software
   45.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   45.23 +===========================================================================
   45.24 +*/
   45.25 +
   45.26 +attribute vec4		attr_Position;
   45.27 +attribute vec4		attr_Color;
   45.28 +
   45.29 +uniform mat4		u_ModelViewMatrix;
   45.30 +uniform mat4		u_ModelViewProjectionMatrix;
   45.31 +
   45.32 +varying vec3		var_Position;
   45.33 +varying vec4		var_Color;
   45.34 +
   45.35 +void	main()
   45.36 +{
   45.37 +	// transform vertex position into homogenous clip-space
   45.38 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   45.39 +	
   45.40 +	// transform vertex position into camera space
   45.41 +	var_Position = (u_ModelViewMatrix * attr_Position).xyz;
   45.42 +	
   45.43 +	// assign color
   45.44 +	var_Color = attr_Color;
   45.45 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/glsl/reflection_CB_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    46.3 @@ -0,0 +1,69 @@
    46.4 +/*
    46.5 +===========================================================================
    46.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    46.7 +
    46.8 +This file is part of XreaL source code.
    46.9 +
   46.10 +XreaL source code is free software; you can redistribute it
   46.11 +and/or modify it under the terms of the GNU General Public License as
   46.12 +published by the Free Software Foundation; either version 2 of the License,
   46.13 +or (at your option) any later version.
   46.14 +
   46.15 +XreaL source code is distributed in the hope that it will be
   46.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   46.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   46.18 +GNU General Public License for more details.
   46.19 +
   46.20 +You should have received a copy of the GNU General Public License
   46.21 +along with XreaL source code; if not, write to the Free Software
   46.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   46.23 +===========================================================================
   46.24 +*/
   46.25 +
   46.26 +uniform samplerCube	u_ColorMap;
   46.27 +uniform sampler2D	u_NormalMap;
   46.28 +uniform vec3		u_ViewOrigin;
   46.29 +uniform mat4		u_ModelMatrix;
   46.30 +
   46.31 +varying vec3		var_Position;
   46.32 +varying vec2		var_TexNormal;
   46.33 +varying vec4		var_Tangent;
   46.34 +varying vec4		var_Binormal;
   46.35 +varying vec4		var_Normal;
   46.36 +
   46.37 +void	main()
   46.38 +{
   46.39 +	vec3 I, N, R;
   46.40 +	vec4 reflectColor;
   46.41 +
   46.42 +	// compute incident ray in world space
   46.43 +	I = normalize(var_Position - u_ViewOrigin);
   46.44 +	
   46.45 +	// compute normal in tangent space from normalmap
   46.46 +	N = 2.0 * (texture2D(u_NormalMap, var_TexNormal.st).xyz - 0.5);
   46.47 +	#if defined(r_NormalScale)
   46.48 +	N.z *= r_NormalScale;
   46.49 +	normalize(N);
   46.50 +	#endif
   46.51 +		
   46.52 +	// invert tangent space for twosided surfaces
   46.53 +	mat3 tangentToWorldMatrix;
   46.54 +	if(gl_FrontFacing)
   46.55 +		tangentToWorldMatrix = mat3(-var_Tangent.xyz, -var_Binormal.xyz, -var_Normal.xyz);
   46.56 +	else
   46.57 +		tangentToWorldMatrix = mat3(var_Tangent.xyz, var_Binormal.xyz, var_Normal.xyz);
   46.58 +	
   46.59 +	// transform normal into world space
   46.60 +	N = tangentToWorldMatrix * N;
   46.61 +	
   46.62 +	// compute reflection ray
   46.63 +	R = reflect(I, N);
   46.64 +	
   46.65 +	// compute reflection color
   46.66 +	reflectColor = textureCube(u_ColorMap, R).rgba;
   46.67 +
   46.68 +	// compute final color
   46.69 +	vec4 color = reflectColor;
   46.70 +	
   46.71 +	gl_FragColor = color;
   46.72 +}
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/glsl/reflection_CB_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    47.3 @@ -0,0 +1,95 @@
    47.4 +/*
    47.5 +===========================================================================
    47.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    47.7 +
    47.8 +This file is part of XreaL source code.
    47.9 +
   47.10 +XreaL source code is free software; you can redistribute it
   47.11 +and/or modify it under the terms of the GNU General Public License as
   47.12 +published by the Free Software Foundation; either version 2 of the License,
   47.13 +or (at your option) any later version.
   47.14 +
   47.15 +XreaL source code is distributed in the hope that it will be
   47.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   47.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   47.18 +GNU General Public License for more details.
   47.19 +
   47.20 +You should have received a copy of the GNU General Public License
   47.21 +along with XreaL source code; if not, write to the Free Software
   47.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   47.23 +===========================================================================
   47.24 +*/
   47.25 +
   47.26 +attribute vec4		attr_Position;
   47.27 +attribute vec4		attr_TexCoord0;
   47.28 +attribute vec3		attr_Tangent;
   47.29 +attribute vec3		attr_Binormal;
   47.30 +attribute vec3		attr_Normal;
   47.31 +#if defined(r_VertexSkinning)
   47.32 +attribute vec4		attr_BoneIndexes;
   47.33 +attribute vec4		attr_BoneWeights;
   47.34 +uniform int			u_VertexSkinning;
   47.35 +uniform mat4		u_BoneMatrix[MAX_GLSL_BONES];
   47.36 +#endif
   47.37 +
   47.38 +uniform mat4		u_NormalTextureMatrix;
   47.39 +uniform mat4		u_ModelMatrix;
   47.40 +uniform mat4		u_ModelViewProjectionMatrix;
   47.41 +
   47.42 +varying vec3		var_Position;
   47.43 +varying vec2		var_TexNormal;
   47.44 +varying vec4		var_Tangent;
   47.45 +varying vec4		var_Binormal;
   47.46 +varying vec4		var_Normal;
   47.47 +
   47.48 +void	main()
   47.49 +{
   47.50 +#if defined(r_VertexSkinning)
   47.51 +	if(bool(u_VertexSkinning))
   47.52 +	{
   47.53 +		vec4 vertex = vec4(0.0);
   47.54 +		vec3 tangent = vec3(0.0);
   47.55 +		vec3 binormal = vec3(0.0);
   47.56 +		vec3 normal = vec3(0.0);
   47.57 +
   47.58 +		for(int i = 0; i < 4; i++)
   47.59 +		{
   47.60 +			int boneIndex = int(attr_BoneIndexes[i]);
   47.61 +			float boneWeight = attr_BoneWeights[i];
   47.62 +			mat4  boneMatrix = u_BoneMatrix[boneIndex];
   47.63 +			
   47.64 +			vertex += (boneMatrix * attr_Position) * boneWeight;
   47.65 +		
   47.66 +			tangent += (boneMatrix * vec4(attr_Tangent, 0.0)).xyz * boneWeight;
   47.67 +			binormal += (boneMatrix * vec4(attr_Binormal, 0.0)).xyz * boneWeight;
   47.68 +			normal += (boneMatrix * vec4(attr_Normal, 0.0)).xyz * boneWeight;
   47.69 +		}
   47.70 +
   47.71 +		// transform vertex position into homogenous clip-space
   47.72 +		gl_Position = u_ModelViewProjectionMatrix * vertex;
   47.73 +		
   47.74 +		// transform position into world space
   47.75 +		var_Position = (u_ModelMatrix * vertex).xyz;
   47.76 +		
   47.77 +		var_Tangent.xyz = (u_ModelMatrix * vec4(tangent, 0.0)).xyz;
   47.78 +		var_Binormal.xyz = (u_ModelMatrix * vec4(binormal, 0.0)).xyz;
   47.79 +		var_Normal.xyz = (u_ModelMatrix * vec4(normal, 0.0)).xyz;
   47.80 +	}
   47.81 +	else
   47.82 +#endif
   47.83 +	{
   47.84 +		// transform vertex position into homogenous clip-space
   47.85 +		gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   47.86 +		
   47.87 +		// transform position into world space
   47.88 +		var_Position = (u_ModelMatrix * attr_Position).xyz;
   47.89 +	
   47.90 +		var_Tangent.xyz = (u_ModelMatrix * vec4(attr_Tangent, 0.0)).xyz;
   47.91 +		var_Binormal.xyz = (u_ModelMatrix * vec4(attr_Binormal, 0.0)).xyz;
   47.92 +		var_Normal.xyz = (u_ModelMatrix * vec4(attr_Normal, 0.0)).xyz;
   47.93 +	}
   47.94 +	
   47.95 +	// transform normalmap texcoords
   47.96 +	var_TexNormal = (u_NormalTextureMatrix * attr_TexCoord0).st;
   47.97 +}
   47.98 +
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/glsl/reflection_C_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    48.3 @@ -0,0 +1,47 @@
    48.4 +/*
    48.5 +===========================================================================
    48.6 +Copyright (C) 2006 Robert Beckebans <trebor_7@users.sourceforge.net>
    48.7 +
    48.8 +This file is part of XreaL source code.
    48.9 +
   48.10 +XreaL source code is free software; you can redistribute it
   48.11 +and/or modify it under the terms of the GNU General Public License as
   48.12 +published by the Free Software Foundation; either version 2 of the License,
   48.13 +or (at your option) any later version.
   48.14 +
   48.15 +XreaL source code is distributed in the hope that it will be
   48.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   48.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   48.18 +GNU General Public License for more details.
   48.19 +
   48.20 +You should have received a copy of the GNU General Public License
   48.21 +along with XreaL source code; if not, write to the Free Software
   48.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   48.23 +===========================================================================
   48.24 +*/
   48.25 +
   48.26 +uniform samplerCube	u_ColorMap;
   48.27 +uniform vec3		u_ViewOrigin;
   48.28 +
   48.29 +varying vec3		var_Position;
   48.30 +varying vec3		var_Normal;
   48.31 +
   48.32 +void	main()
   48.33 +{
   48.34 +	// compute incident ray
   48.35 +	vec3 I = normalize(var_Position - u_ViewOrigin);
   48.36 +	
   48.37 +	// compute normal
   48.38 +	vec3 N = normalize(var_Normal);
   48.39 +	
   48.40 +	// compute reflection ray
   48.41 +	vec3 R = reflect(I, N);
   48.42 +	
   48.43 +	// compute reflection color
   48.44 +	vec4 reflectColor = textureCube(u_ColorMap, R).rgba;
   48.45 +
   48.46 +	// compute final color
   48.47 +	vec4 color = reflectColor;
   48.48 +	
   48.49 +	gl_FragColor = color;
   48.50 +}
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/glsl/reflection_C_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    49.3 @@ -0,0 +1,78 @@
    49.4 +/*
    49.5 +===========================================================================
    49.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    49.7 +
    49.8 +This file is part of XreaL source code.
    49.9 +
   49.10 +XreaL source code is free software; you can redistribute it
   49.11 +and/or modify it under the terms of the GNU General Public License as
   49.12 +published by the Free Software Foundation; either version 2 of the License,
   49.13 +or (at your option) any later version.
   49.14 +
   49.15 +XreaL source code is distributed in the hope that it will be
   49.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   49.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   49.18 +GNU General Public License for more details.
   49.19 +
   49.20 +You should have received a copy of the GNU General Public License
   49.21 +along with XreaL source code; if not, write to the Free Software
   49.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   49.23 +===========================================================================
   49.24 +*/
   49.25 +
   49.26 +attribute vec4		attr_Position;
   49.27 +attribute vec3		attr_Normal;
   49.28 +#if defined(r_VertexSkinning)
   49.29 +attribute vec4		attr_BoneIndexes;
   49.30 +attribute vec4		attr_BoneWeights;
   49.31 +uniform int			u_VertexSkinning;
   49.32 +uniform mat4		u_BoneMatrix[MAX_GLSL_BONES];
   49.33 +#endif
   49.34 +
   49.35 +uniform mat4		u_ModelMatrix;
   49.36 +uniform mat4		u_ModelViewProjectionMatrix;
   49.37 +
   49.38 +varying vec3		var_Position;
   49.39 +varying vec3		var_Normal;
   49.40 +
   49.41 +void	main()
   49.42 +{
   49.43 +#if defined(r_VertexSkinning)
   49.44 +	if(bool(u_VertexSkinning))
   49.45 +	{
   49.46 +		vec4 vertex = vec4(0.0);
   49.47 +		vec3 normal = vec3(0.0);
   49.48 +
   49.49 +		for(int i = 0; i < 4; i++)
   49.50 +		{
   49.51 +			int boneIndex = int(attr_BoneIndexes[i]);
   49.52 +			float boneWeight = attr_BoneWeights[i];
   49.53 +			mat4  boneMatrix = u_BoneMatrix[boneIndex];
   49.54 +			
   49.55 +			vertex += (boneMatrix * attr_Position) * boneWeight;
   49.56 +			normal += (boneMatrix * vec4(attr_Normal, 0.0)).xyz * boneWeight;
   49.57 +		}
   49.58 +
   49.59 +		// transform vertex position into homogenous clip-space
   49.60 +		gl_Position = u_ModelViewProjectionMatrix * vertex;
   49.61 +		
   49.62 +		// transform position into world space
   49.63 +		var_Position = (u_ModelMatrix * vertex).xyz;
   49.64 +	
   49.65 +		// transform normal into world space
   49.66 +		var_Normal = (u_ModelMatrix * vec4(normal, 0.0)).xyz;
   49.67 +	}
   49.68 +	else
   49.69 +#endif
   49.70 +	{
   49.71 +		// transform vertex position into homogenous clip-space
   49.72 +		gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   49.73 +	
   49.74 +		// transform position into world space
   49.75 +		var_Position = (u_ModelMatrix * attr_Position).xyz;
   49.76 +	
   49.77 +		// transform normal into world space
   49.78 +		var_Normal = (u_ModelMatrix * vec4(attr_Normal, 0.0)).xyz;
   49.79 +	}
   49.80 +}
   49.81 +
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/glsl/refraction_C_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    50.3 @@ -0,0 +1,61 @@
    50.4 +/*
    50.5 +===========================================================================
    50.6 +Copyright (C) 2006 Robert Beckebans <trebor_7@users.sourceforge.net>
    50.7 +
    50.8 +This file is part of XreaL source code.
    50.9 +
   50.10 +XreaL source code is free software; you can redistribute it
   50.11 +and/or modify it under the terms of the GNU General Public License as
   50.12 +published by the Free Software Foundation; either version 2 of the License,
   50.13 +or (at your option) any later version.
   50.14 +
   50.15 +XreaL source code is distributed in the hope that it will be
   50.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   50.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   50.18 +GNU General Public License for more details.
   50.19 +
   50.20 +You should have received a copy of the GNU General Public License
   50.21 +along with XreaL source code; if not, write to the Free Software
   50.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   50.23 +===========================================================================
   50.24 +*/
   50.25 +
   50.26 +uniform samplerCube	u_ColorMap;
   50.27 +uniform vec3		u_ViewOrigin;
   50.28 +uniform float		u_RefractionIndex;
   50.29 +uniform float		u_FresnelPower;
   50.30 +uniform float		u_FresnelScale;
   50.31 +uniform float		u_FresnelBias;
   50.32 +
   50.33 +varying vec3		var_Position;
   50.34 +varying vec3		var_Normal;
   50.35 +
   50.36 +void	main()
   50.37 +{
   50.38 +	// compute incident ray
   50.39 +	vec3 I = normalize(var_Position - u_ViewOrigin);
   50.40 +	
   50.41 +	// compute normal
   50.42 +	vec3 N = normalize(var_Normal);
   50.43 +	
   50.44 +	// compute reflection ray
   50.45 +	vec3 R = reflect(I, N);
   50.46 +	
   50.47 +	// compute refraction ray
   50.48 +	vec3 T = refract(I, N, u_RefractionIndex);
   50.49 +			
   50.50 +	// compute fresnel term
   50.51 +	float fresnel = u_FresnelBias + pow(1.0 - dot(I, N), u_FresnelPower) * u_FresnelScale;
   50.52 +
   50.53 +	vec3 reflectColor = textureCube(u_ColorMap, R).rgb;
   50.54 +	vec3 refractColor = textureCube(u_ColorMap, T).rgb;
   50.55 +
   50.56 +	// compute final color
   50.57 +	vec4 color;
   50.58 +	color.r = (1.0 - fresnel) * refractColor.r + reflectColor.r * fresnel;
   50.59 +	color.g = (1.0 - fresnel) * refractColor.g + reflectColor.g * fresnel;
   50.60 +	color.b = (1.0 - fresnel) * refractColor.b + reflectColor.b * fresnel;
   50.61 +	color.a = 1.0;
   50.62 +	
   50.63 +	gl_FragColor = color;
   50.64 +}
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/glsl/refraction_C_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    51.3 @@ -0,0 +1,78 @@
    51.4 +/*
    51.5 +===========================================================================
    51.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    51.7 +
    51.8 +This file is part of XreaL source code.
    51.9 +
   51.10 +XreaL source code is free software; you can redistribute it
   51.11 +and/or modify it under the terms of the GNU General Public License as
   51.12 +published by the Free Software Foundation; either version 2 of the License,
   51.13 +or (at your option) any later version.
   51.14 +
   51.15 +XreaL source code is distributed in the hope that it will be
   51.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   51.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   51.18 +GNU General Public License for more details.
   51.19 +
   51.20 +You should have received a copy of the GNU General Public License
   51.21 +along with XreaL source code; if not, write to the Free Software
   51.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   51.23 +===========================================================================
   51.24 +*/
   51.25 +
   51.26 +attribute vec4		attr_Position;
   51.27 +attribute vec3		attr_Normal;
   51.28 +#if defined(r_VertexSkinning)
   51.29 +attribute vec4		attr_BoneIndexes;
   51.30 +attribute vec4		attr_BoneWeights;
   51.31 +uniform int			u_VertexSkinning;
   51.32 +uniform mat4		u_BoneMatrix[MAX_GLSL_BONES];
   51.33 +#endif
   51.34 +
   51.35 +uniform mat4		u_ModelMatrix;
   51.36 +uniform mat4		u_ModelViewProjectionMatrix;
   51.37 +
   51.38 +varying vec3		var_Position;
   51.39 +varying vec3		var_Normal;
   51.40 +
   51.41 +void	main()
   51.42 +{
   51.43 +#if defined(r_VertexSkinning)
   51.44 +	if(bool(u_VertexSkinning))
   51.45 +	{
   51.46 +		vec4 vertex = vec4(0.0);
   51.47 +		vec3 normal = vec3(0.0);
   51.48 +
   51.49 +		for(int i = 0; i < 4; i++)
   51.50 +		{
   51.51 +			int boneIndex = int(attr_BoneIndexes[i]);
   51.52 +			float boneWeight = attr_BoneWeights[i];
   51.53 +			mat4  boneMatrix = u_BoneMatrix[boneIndex];
   51.54 +			
   51.55 +			vertex += (boneMatrix * attr_Position) * boneWeight;
   51.56 +			normal += (boneMatrix * vec4(attr_Normal, 0.0)).xyz * boneWeight;
   51.57 +		}
   51.58 +
   51.59 +		// transform vertex position into homogenous clip-space
   51.60 +		gl_Position = u_ModelViewProjectionMatrix * vertex;
   51.61 +		
   51.62 +		// transform position into world space
   51.63 +		var_Position = (u_ModelMatrix * vertex).xyz;
   51.64 +	
   51.65 +		// transform normal into world space
   51.66 +		var_Normal = (u_ModelMatrix * vec4(normal, 0.0)).xyz;
   51.67 +	}
   51.68 +	else
   51.69 +#endif
   51.70 +	{
   51.71 +		// transform vertex position into homogenous clip-space
   51.72 +		gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   51.73 +	
   51.74 +		// transform position into world space
   51.75 +		var_Position = (u_ModelMatrix * attr_Position).xyz;
   51.76 +	
   51.77 +		// transform normal into world space
   51.78 +		var_Normal = (u_ModelMatrix * vec4(attr_Normal, 0.0)).xyz;
   51.79 +	}
   51.80 +}
   51.81 +
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/glsl/rotoscope_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    52.3 @@ -0,0 +1,165 @@
    52.4 +/*
    52.5 +===========================================================================
    52.6 +Copyright (C) 2006 Robert Beckebans <trebor_7@users.sourceforge.net>
    52.7 +
    52.8 +This file is part of XreaL source code.
    52.9 +
   52.10 +XreaL source code is free software; you can redistribute it
   52.11 +and/or modify it under the terms of the GNU General Public License as
   52.12 +published by the Free Software Foundation; either version 2 of the License,
   52.13 +or (at your option) any later version.
   52.14 +
   52.15 +XreaL source code is distributed in the hope that it will be
   52.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   52.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   52.18 +GNU General Public License for more details.
   52.19 +
   52.20 +You should have received a copy of the GNU General Public License
   52.21 +along with XreaL source code; if not, write to the Free Software
   52.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   52.23 +===========================================================================
   52.24 +*/
   52.25 +
   52.26 +uniform sampler2D	u_ColorMap;
   52.27 +uniform float		u_BlurMagnitude;
   52.28 +
   52.29 +void	main()
   52.30 +{
   52.31 +	vec2 st00 = gl_FragCoord.st;
   52.32 +
   52.33 +	// calculate the screen texcoord in the 0.0 to 1.0 range
   52.34 +	st00 *= r_FBufScale;
   52.35 +	
   52.36 +	// scale by the screen non-power-of-two-adjust
   52.37 +	st00 *= r_NPOTScale;
   52.38 +	
   52.39 +	// set so a magnitude of 1 is approximately 1 pixel with 640x480
   52.40 +	//vec2 deform = vec2(u_BlurMagnitude * 0.0016, u_BlurMagnitude * 0.00213333);
   52.41 +	vec2 deform = u_BlurMagnitude * r_FBufScale;
   52.42 +	
   52.43 +	// fragment offsets
   52.44 +	vec2 offset01 = vec2(-0.5, -0.5);
   52.45 +	vec2 offset02 = vec2(-0.5,  0.0);
   52.46 +	vec2 offset03 = vec2(-0.5,  0.5);
   52.47 +	vec2 offset04 = vec2( 0.5, -0.5);
   52.48 +	vec2 offset05 = vec2( 0.5,  0.0);
   52.49 +	vec2 offset06 = vec2( 0.5,  0.5);
   52.50 +	vec2 offset07 = vec2( 0.0, -0.5);
   52.51 +	vec2 offset08 = vec2( 0.0,  0.5);
   52.52 +	
   52.53 +	// calculate our offset texture coordinates
   52.54 +	vec2 st01 = st00 + offset01 * deform;
   52.55 +	vec2 st02 = st00 + offset02 * deform;
   52.56 +	vec2 st03 = st00 + offset03 * deform;
   52.57 +	vec2 st04 = st00 + offset04 * deform;
   52.58 +	vec2 st05 = st00 + offset05 * deform;
   52.59 +	vec2 st06 = st00 + offset06 * deform;
   52.60 +	vec2 st07 = st00 + offset07 * deform;
   52.61 +	vec2 st08 = st00 + offset08 * deform;
   52.62 +	
   52.63 +	// base color
   52.64 +	vec4 c00 = texture2D(u_ColorMap, st00);
   52.65 +
   52.66 +	// sample the current render for each coordinate
   52.67 +	vec4 c01 = texture2D(u_ColorMap, st01);
   52.68 +	vec4 c02 = texture2D(u_ColorMap, st02);
   52.69 +	vec4 c03 = texture2D(u_ColorMap, st03);
   52.70 +	vec4 c04 = texture2D(u_ColorMap, st04);
   52.71 +	vec4 c05 = texture2D(u_ColorMap, st05);
   52.72 +	vec4 c06 = texture2D(u_ColorMap, st06);
   52.73 +	vec4 c07 = texture2D(u_ColorMap, st07);
   52.74 +	vec4 c08 = texture2D(u_ColorMap, st08);
   52.75 +	
   52.76 +	// each of them have a scale value of two in
   52.77 +	vec4 xedge = c02 * 2.0 - c05 * 2.0;
   52.78 +	vec4 yedge = c07 * 2.0 - c08 * 2.0;
   52.79 +	
   52.80 +	xedge = xedge + c01 + c03 - c04 - c06;
   52.81 +	yedge = yedge + c01 - c03 + c04 - c06;
   52.82 +
   52.83 +	// square each and add and take the sqrt
   52.84 +	xedge *= xedge;
   52.85 +	yedge *= yedge;
   52.86 +	
   52.87 +	vec4 tmp = xedge + yedge;
   52.88 +	tmp.x = max(tmp.x, tmp.y);
   52.89 +	tmp.x = max(tmp.x, tmp.z);
   52.90 +	
   52.91 +	// write result from edge detection into sobel variable
   52.92 +	vec4 sobel = vec4(pow(tmp.x, 0.5), 0, 0, 0);
   52.93 +	
   52.94 +	//
   52.95 +	// normalize the color hue
   52.96 +	//
   52.97 +	vec4 hue;
   52.98 +	
   52.99 +	// calculate [sum RGB]
  52.100 +	hue.x = c00.x + c00.y + c00.z;
  52.101 +
  52.102 +	// calculate 1 / [sum RGB]
  52.103 +	hue.y = 1.0 / hue.x;
  52.104 +	
  52.105 +	// multiply pixel color with 1 / [sum RGB]
  52.106 +	c00 *= hue.y;
  52.107 +	
  52.108 +	//
  52.109 +	// calculate the pixel intensity
  52.110 +	// make everything with [sum RGB] < .2 black
  52.111 +	//
  52.112 +	
  52.113 +	// define darktones ([sum RGB] > .2) and store in channel z
  52.114 +	if(hue.x >= 0.2)
  52.115 +		hue.z = 1.0;
  52.116 +	else
  52.117 +		hue.z = 0.0;
  52.118 +		
  52.119 +	// darktones will be normalized HUE * 0.5
  52.120 +	hue.z *= 0.5;
  52.121 +	
  52.122 +	// define midtones ([sum RGB] >.8) and store in channel y
  52.123 +	if(hue.x >= 0.8)
  52.124 +		hue.y = 1.0;
  52.125 +	else
  52.126 +		hue.y = 0.0;
  52.127 +		
  52.128 +	// midtones will be normalized HUE * (0.5 + 0.5)
  52.129 +	hue.y *= (0.5 + 0.5);
  52.130 +	
  52.131 +	// define brighttones ([sum RGB] > 1.5) and store in channel x
  52.132 +	if(hue.x >= 1.5)
  52.133 +		hue.x = 1.0;
  52.134 +	else
  52.135 +		hue.x = 0.0;
  52.136 +		
  52.137 +	// brighttones will be normalized HUE * (0.5 + 0.5 + 1.5)
  52.138 +	hue.x *= (0.5 + 0.5 + 1.5);
  52.139 +
  52.140 +	// sum darktones + midtones + brighttones to calculate final pixel intensity
  52.141 +	hue.x += hue.y + hue.z;
  52.142 +
  52.143 +	// multiply pixel color with rotoscope intensity
  52.144 +	c00 *= hue.x;
  52.145 +
  52.146 +	// generate edge mask -> make 1 for all regions not belonging to an edge
  52.147 +	// use 0.8 as threshold for edge detection
  52.148 +	if(sobel.x < 0.8)
  52.149 +		sobel.x = 1.0;
  52.150 +	else
  52.151 +		sobel.x = 0.0;
  52.152 +
  52.153 +	// blend white into edge artifacts (occuring in bright areas)
  52.154 +	// find pixels with intensity > 2.5
  52.155 +	if(hue.x >= 2.5)
  52.156 +		sobel.y = 1.0;
  52.157 +	else
  52.158 +		sobel.y = 0.0;
  52.159 +
  52.160 +	// set the edge mask to 1 in such areas
  52.161 +	sobel.x = max(sobel.x, sobel.y);
  52.162 +	
  52.163 +	// multiply cleaned up edge mask with final color image
  52.164 +	c00 *= sobel.x;
  52.165 +	
  52.166 +	// transfer image to output
  52.167 +	gl_FragColor = c00;
  52.168 +}
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/glsl/rotoscope_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    53.3 @@ -0,0 +1,31 @@
    53.4 +/*
    53.5 +===========================================================================
    53.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    53.7 +
    53.8 +This file is part of XreaL source code.
    53.9 +
   53.10 +XreaL source code is free software; you can redistribute it
   53.11 +and/or modify it under the terms of the GNU General Public License as
   53.12 +published by the Free Software Foundation; either version 2 of the License,
   53.13 +or (at your option) any later version.
   53.14 +
   53.15 +XreaL source code is distributed in the hope that it will be
   53.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   53.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   53.18 +GNU General Public License for more details.
   53.19 +
   53.20 +You should have received a copy of the GNU General Public License
   53.21 +along with XreaL source code; if not, write to the Free Software
   53.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   53.23 +===========================================================================
   53.24 +*/
   53.25 +
   53.26 +attribute vec4		attr_Position;
   53.27 +
   53.28 +uniform mat4		u_ModelViewProjectionMatrix;
   53.29 +
   53.30 +void	main()
   53.31 +{
   53.32 +	// transform vertex position into homogenous clip-space
   53.33 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   53.34 +}
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/glsl/screenSpaceAmbientOcclusion_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    54.3 @@ -0,0 +1,70 @@
    54.4 +/*
    54.5 +===========================================================================
    54.6 +Copyright (C) 2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    54.7 +
    54.8 +This file is part of XreaL source code.
    54.9 +
   54.10 +XreaL source code is free software; you can redistribute it
   54.11 +and/or modify it under the terms of the GNU General Public License as
   54.12 +published by the Free Software Foundation; either version 2 of the License,
   54.13 +or (at your option) any later version.
   54.14 +
   54.15 +XreaL source code is distributed in the hope that it will be
   54.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   54.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   54.18 +GNU General Public License for more details.
   54.19 +
   54.20 +You should have received a copy of the GNU General Public License
   54.21 +along with XreaL source code; if not, write to the Free Software
   54.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   54.23 +===========================================================================
   54.24 +*/
   54.25 +
   54.26 +uniform sampler2D	u_CurrentMap;
   54.27 +uniform sampler2D	u_DepthMap;
   54.28 +//uniform vec3		u_ViewOrigin;
   54.29 +//uniform vec3		u_SSAOJitter[32];
   54.30 +//uniform float		u_SSAORadius;
   54.31 +//uniform mat4		u_UnprojectMatrix;
   54.32 +//uniform mat4		u_ProjectMatrix;
   54.33 +
   54.34 +float  ReadDepth(vec2 st)
   54.35 +{
   54.36 +	vec2 camerarange = vec2(4.0, 4096.0);
   54.37 +	
   54.38 +	return (2.0 * camerarange.x) / (camerarange.y + camerarange.x - texture2D(u_DepthMap, st).x * (camerarange.y - camerarange.x));	
   54.39 +}
   54.40 +
   54.41 +
   54.42 +void	main()
   54.43 +{
   54.44 +	// calculate the screen texcoord in the 0.0 to 1.0 range
   54.45 +	vec2 st = gl_FragCoord.st * r_FBufScale;
   54.46 +	
   54.47 +	// scale by the screen non-power-of-two-adjust
   54.48 +	st *= r_NPOTScale;
   54.49 +
   54.50 +	float depth =  ReadDepth(st);
   54.51 +	float d;
   54.52 +
   54.53 +	float aoCap = 1.0;
   54.54 +	float ao = 0.0;
   54.55 +	
   54.56 +	float aoMultiplier = 1000.0;
   54.57 +	float depthTolerance = 0.0001;
   54.58 +	
   54.59 +	float tap = 3.0;
   54.60 +	float taps = tap * 2.0 + 1.0;
   54.61 +	for(float i = -tap; i < tap; i++)
   54.62 +    {
   54.63 +	    for(float j = -tap; j < tap; j++)
   54.64 +	    {
   54.65 +			d = ReadDepth(st + vec2(j, i) * r_FBufScale);
   54.66 +			ao += min(aoCap, max(0.0, depth -d -depthTolerance) * aoMultiplier);
   54.67 +		}
   54.68 +	}
   54.69 +	
   54.70 +	ao /= (taps * taps);
   54.71 +	
   54.72 +	gl_FragColor = vec4(1.0 - ao) * texture2D(u_CurrentMap, st);
   54.73 +}
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/glsl/screenSpaceAmbientOcclusion_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    55.3 @@ -0,0 +1,31 @@
    55.4 +/*
    55.5 +===========================================================================
    55.6 +Copyright (C) 2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    55.7 +
    55.8 +This file is part of XreaL source code.
    55.9 +
   55.10 +XreaL source code is free software; you can redistribute it
   55.11 +and/or modify it under the terms of the GNU General Public License as
   55.12 +published by the Free Software Foundation; either version 2 of the License,
   55.13 +or (at your option) any later version.
   55.14 +
   55.15 +XreaL source code is distributed in the hope that it will be
   55.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   55.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   55.18 +GNU General Public License for more details.
   55.19 +
   55.20 +You should have received a copy of the GNU General Public License
   55.21 +along with XreaL source code; if not, write to the Free Software
   55.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   55.23 +===========================================================================
   55.24 +*/
   55.25 +
   55.26 +attribute vec4		attr_Position;
   55.27 +
   55.28 +uniform mat4		u_ModelViewProjectionMatrix;
   55.29 +
   55.30 +void	main()
   55.31 +{
   55.32 +	// transform vertex position into homogenous clip-space
   55.33 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   55.34 +}
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/glsl/screen_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    56.3 @@ -0,0 +1,39 @@
    56.4 +/*
    56.5 +===========================================================================
    56.6 +Copyright (C) 2006 Robert Beckebans <trebor_7@users.sourceforge.net>
    56.7 +
    56.8 +This file is part of XreaL source code.
    56.9 +
   56.10 +XreaL source code is free software; you can redistribute it
   56.11 +and/or modify it under the terms of the GNU General Public License as
   56.12 +published by the Free Software Foundation; either version 2 of the License,
   56.13 +or (at your option) any later version.
   56.14 +
   56.15 +XreaL source code is distributed in the hope that it will be
   56.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   56.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   56.18 +GNU General Public License for more details.
   56.19 +
   56.20 +You should have received a copy of the GNU General Public License
   56.21 +along with XreaL source code; if not, write to the Free Software
   56.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   56.23 +===========================================================================
   56.24 +*/
   56.25 +
   56.26 +uniform sampler2D	u_CurrentMap;
   56.27 +
   56.28 +varying vec4		var_Color;
   56.29 +
   56.30 +void	main()
   56.31 +{
   56.32 +	// calculate the screen texcoord in the 0.0 to 1.0 range
   56.33 +	vec2 st = gl_FragCoord.st * r_FBufScale;
   56.34 +	
   56.35 +	// scale by the screen non-power-of-two-adjust
   56.36 +	st *= r_NPOTScale;
   56.37 +	
   56.38 +	vec4 color = texture2D(u_CurrentMap, st);
   56.39 +	color *= var_Color;
   56.40 +
   56.41 +	gl_FragColor = color;
   56.42 +}
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/glsl/screen_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    57.3 @@ -0,0 +1,37 @@
    57.4 +/*
    57.5 +===========================================================================
    57.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    57.7 +
    57.8 +This file is part of XreaL source code.
    57.9 +
   57.10 +XreaL source code is free software; you can redistribute it
   57.11 +and/or modify it under the terms of the GNU General Public License as
   57.12 +published by the Free Software Foundation; either version 2 of the License,
   57.13 +or (at your option) any later version.
   57.14 +
   57.15 +XreaL source code is distributed in the hope that it will be
   57.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   57.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   57.18 +GNU General Public License for more details.
   57.19 +
   57.20 +You should have received a copy of the GNU General Public License
   57.21 +along with XreaL source code; if not, write to the Free Software
   57.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   57.23 +===========================================================================
   57.24 +*/
   57.25 +
   57.26 +attribute vec4		attr_Position;
   57.27 +attribute vec4		attr_Color;
   57.28 +
   57.29 +uniform mat4		u_ModelViewProjectionMatrix;
   57.30 +
   57.31 +varying vec4		var_Color;
   57.32 +
   57.33 +void	main()
   57.34 +{
   57.35 +	// transform vertex position into homogenous clip-space
   57.36 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   57.37 +	
   57.38 +	// assign color
   57.39 +	var_Color = attr_Color;
   57.40 +}
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/glsl/shadowExtrude_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    58.3 @@ -0,0 +1,28 @@
    58.4 +/*
    58.5 +===========================================================================
    58.6 +Copyright (C) 2006 Robert Beckebans <trebor_7@users.sourceforge.net>
    58.7 +
    58.8 +This file is part of XreaL source code.
    58.9 +
   58.10 +XreaL source code is free software; you can redistribute it
   58.11 +and/or modify it under the terms of the GNU General Public License as
   58.12 +published by the Free Software Foundation; either version 2 of the License,
   58.13 +or (at your option) any later version.
   58.14 +
   58.15 +XreaL source code is distributed in the hope that it will be
   58.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   58.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   58.18 +GNU General Public License for more details.
   58.19 +
   58.20 +You should have received a copy of the GNU General Public License
   58.21 +along with XreaL source code; if not, write to the Free Software
   58.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   58.23 +===========================================================================
   58.24 +*/
   58.25 +
   58.26 +varying vec4		var_Color;
   58.27 +
   58.28 +void	main()
   58.29 +{
   58.30 +	gl_FragColor = var_Color;
   58.31 +}
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/glsl/shadowExtrude_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    59.3 @@ -0,0 +1,47 @@
    59.4 +/*
    59.5 +===========================================================================
    59.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    59.7 +
    59.8 +This file is part of XreaL source code.
    59.9 +
   59.10 +XreaL source code is free software; you can redistribute it
   59.11 +and/or modify it under the terms of the GNU General Public License as
   59.12 +published by the Free Software Foundation; either version 2 of the License,
   59.13 +or (at your option) any later version.
   59.14 +
   59.15 +XreaL source code is distributed in the hope that it will be
   59.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   59.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   59.18 +GNU General Public License for more details.
   59.19 +
   59.20 +You should have received a copy of the GNU General Public License
   59.21 +along with XreaL source code; if not, write to the Free Software
   59.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   59.23 +===========================================================================
   59.24 +*/
   59.25 +
   59.26 +attribute vec4		attr_Position;
   59.27 +attribute vec4		attr_Color;
   59.28 +
   59.29 +uniform vec3		u_LightOrigin;
   59.30 +uniform mat4		u_ModelViewProjectionMatrix;
   59.31 +
   59.32 +varying vec4		var_Color;
   59.33 +
   59.34 +void	main()
   59.35 +{
   59.36 +	if(attr_Position.w == 1.0)
   59.37 +	{
   59.38 +		// transform vertex position into homogenous clip-space
   59.39 +		gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   59.40 +	}
   59.41 +	else
   59.42 +	{
   59.43 +		// project vertex position to infinity
   59.44 +		vec4 vertex = vec4((attr_Position.xyz - u_LightOrigin), 0.0);
   59.45 +		gl_Position	= u_ModelViewProjectionMatrix * vertex;
   59.46 +	}
   59.47 +	
   59.48 +	// assign color
   59.49 +	var_Color = attr_Color;
   59.50 +}
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/glsl/shadowFill_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    60.3 @@ -0,0 +1,73 @@
    60.4 +/*
    60.5 +===========================================================================
    60.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    60.7 +
    60.8 +This file is part of XreaL source code.
    60.9 +
   60.10 +XreaL source code is free software; you can redistribute it
   60.11 +and/or modify it under the terms of the GNU General Public License as
   60.12 +published by the Free Software Foundation; either version 2 of the License,
   60.13 +or (at your option) any later version.
   60.14 +
   60.15 +XreaL source code is distributed in the hope that it will be
   60.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   60.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   60.18 +GNU General Public License for more details.
   60.19 +
   60.20 +You should have received a copy of the GNU General Public License
   60.21 +along with XreaL source code; if not, write to the Free Software
   60.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   60.23 +===========================================================================
   60.24 +*/
   60.25 +
   60.26 +uniform sampler2D	u_ColorMap;
   60.27 +uniform int			u_AlphaTest;
   60.28 +uniform vec3		u_LightOrigin;
   60.29 +uniform float       u_LightRadius;
   60.30 +
   60.31 +varying vec3		var_Position;
   60.32 +varying vec2		var_Tex;
   60.33 +varying vec4		var_Color;
   60.34 +
   60.35 +void	main()
   60.36 +{
   60.37 +	vec4 color = texture2D(u_ColorMap, var_Tex);
   60.38 +	if(u_AlphaTest == ATEST_GT_0 && color.a <= 0.0)
   60.39 +	{
   60.40 +		discard;
   60.41 +		return;
   60.42 +	}
   60.43 +	else if(u_AlphaTest == ATEST_LT_128 && color.a >= 0.5)
   60.44 +	{
   60.45 +		discard;
   60.46 +		return;
   60.47 +	}
   60.48 +	else if(u_AlphaTest == ATEST_GE_128 && color.a < 0.5)
   60.49 +	{
   60.50 +		discard;
   60.51 +		return;
   60.52 +	}
   60.53 +	
   60.54 +#if defined(VSM)
   60.55 +	
   60.56 +	float distance = length(var_Position - u_LightOrigin) / u_LightRadius;
   60.57 +	float distanceSquared = distance * distance;
   60.58 +
   60.59 +	// shadowmap can be float RGBA or luminance alpha so store distanceSquared into alpha
   60.60 +	
   60.61 +#if defined(VSM_CLAMP)
   60.62 +	// convert to [0,1] color space
   60.63 +	gl_FragColor = vec4(distance, 0.0 , 0.0, distanceSquared) * 0.5 + 0.5;
   60.64 +#else
   60.65 +	gl_FragColor = vec4(distance, 0.0, 0.0, distanceSquared);
   60.66 +#endif
   60.67 +
   60.68 +#elif defined(ESM)
   60.69 +	
   60.70 +	float distance = (length(var_Position - u_LightOrigin) / u_LightRadius) * r_ShadowMapDepthScale;// ;
   60.71 +	
   60.72 +	gl_FragColor = vec4(0.0, 0.0, 0.0, distance);
   60.73 +#else
   60.74 +	gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
   60.75 +#endif
   60.76 +}
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/glsl/shadowFill_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    61.3 @@ -0,0 +1,78 @@
    61.4 +/*
    61.5 +===========================================================================
    61.6 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    61.7 +
    61.8 +This file is part of XreaL source code.
    61.9 +
   61.10 +XreaL source code is free software; you can redistribute it
   61.11 +and/or modify it under the terms of the GNU General Public License as
   61.12 +published by the Free Software Foundation; either version 2 of the License,
   61.13 +or (at your option) any later version.
   61.14 +
   61.15 +XreaL source code is distributed in the hope that it will be
   61.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   61.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   61.18 +GNU General Public License for more details.
   61.19 +
   61.20 +You should have received a copy of the GNU General Public License
   61.21 +along with XreaL source code; if not, write to the Free Software
   61.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   61.23 +===========================================================================
   61.24 +*/
   61.25 +
   61.26 +attribute vec4		attr_Position;
   61.27 +attribute vec4		attr_TexCoord0;
   61.28 +attribute vec4		attr_Color;
   61.29 +#if defined(r_VertexSkinning)
   61.30 +attribute vec4		attr_BoneIndexes;
   61.31 +attribute vec4		attr_BoneWeights;
   61.32 +uniform int			u_VertexSkinning;
   61.33 +uniform mat4		u_BoneMatrix[MAX_GLSL_BONES];
   61.34 +#endif
   61.35 +
   61.36 +uniform mat4		u_ColorTextureMatrix;
   61.37 +uniform mat4		u_ModelMatrix;
   61.38 +uniform mat4		u_ModelViewProjectionMatrix;
   61.39 +
   61.40 +varying vec3		var_Position;
   61.41 +varying vec2		var_Tex;
   61.42 +varying vec4		var_Color;
   61.43 +
   61.44 +void	main()
   61.45 +{
   61.46 +#if defined(r_VertexSkinning)
   61.47 +	if(bool(u_VertexSkinning))
   61.48 +	{
   61.49 +		vec4 vertex = vec4(0.0);
   61.50 +		
   61.51 +		for(int i = 0; i < 4; i++)
   61.52 +		{
   61.53 +			int boneIndex = int(attr_BoneIndexes[i]);
   61.54 +			float boneWeight = attr_BoneWeights[i];
   61.55 +			mat4  boneMatrix = u_BoneMatrix[boneIndex];
   61.56 +			
   61.57 +			vertex += (boneMatrix * attr_Position) * boneWeight;
   61.58 +		}
   61.59 +
   61.60 +		// transform vertex position into homogenous clip-space
   61.61 +		gl_Position = u_ModelViewProjectionMatrix * vertex;
   61.62 +		
   61.63 +		// transform position into world space
   61.64 +		var_Position = (u_ModelMatrix * vertex).xyz;
   61.65 +	}
   61.66 +	else
   61.67 +#endif
   61.68 +	{
   61.69 +		// transform vertex position into homogenous clip-space
   61.70 +		gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   61.71 +		
   61.72 +		// transform position into world space
   61.73 +		var_Position = (u_ModelMatrix * attr_Position).xyz;
   61.74 +	}
   61.75 +	
   61.76 +	// transform texcoords
   61.77 +	var_Tex = (u_ColorTextureMatrix * attr_TexCoord0).st;
   61.78 +	
   61.79 +	// assign color
   61.80 +	var_Color = attr_Color;
   61.81 +}
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/glsl/skybox_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    62.3 @@ -0,0 +1,34 @@
    62.4 +/*
    62.5 +===========================================================================
    62.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    62.7 +
    62.8 +This file is part of XreaL source code.
    62.9 +
   62.10 +XreaL source code is free software; you can redistribute it
   62.11 +and/or modify it under the terms of the GNU General Public License as
   62.12 +published by the Free Software Foundation; either version 2 of the License,
   62.13 +or (at your option) any later version.
   62.14 +
   62.15 +XreaL source code is distributed in the hope that it will be
   62.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   62.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   62.18 +GNU General Public License for more details.
   62.19 +
   62.20 +You should have received a copy of the GNU General Public License
   62.21 +along with XreaL source code; if not, write to the Free Software
   62.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   62.23 +===========================================================================
   62.24 +*/
   62.25 +
   62.26 +uniform samplerCube	u_ColorMap;
   62.27 +uniform vec3		u_ViewOrigin;
   62.28 +
   62.29 +varying vec3		var_Position;
   62.30 +
   62.31 +void	main()
   62.32 +{
   62.33 +	// compute incident ray
   62.34 +	vec3 I = normalize(var_Position - u_ViewOrigin);
   62.35 +	
   62.36 +	gl_FragColor = textureCube(u_ColorMap, I).rgba;
   62.37 +}
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/glsl/skybox_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    63.3 @@ -0,0 +1,38 @@
    63.4 +/*
    63.5 +===========================================================================
    63.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    63.7 +
    63.8 +This file is part of XreaL source code.
    63.9 +
   63.10 +XreaL source code is free software; you can redistribute it
   63.11 +and/or modify it under the terms of the GNU General Public License as
   63.12 +published by the Free Software Foundation; either version 2 of the License,
   63.13 +or (at your option) any later version.
   63.14 +
   63.15 +XreaL source code is distributed in the hope that it will be
   63.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   63.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   63.18 +GNU General Public License for more details.
   63.19 +
   63.20 +You should have received a copy of the GNU General Public License
   63.21 +along with XreaL source code; if not, write to the Free Software
   63.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   63.23 +===========================================================================
   63.24 +*/
   63.25 +
   63.26 +attribute vec4		attr_Position;
   63.27 +
   63.28 +uniform mat4		u_ModelMatrix;
   63.29 +uniform mat4		u_ModelViewProjectionMatrix;
   63.30 +
   63.31 +varying vec3		var_Position;
   63.32 +
   63.33 +void	main()
   63.34 +{
   63.35 +	// transform vertex position into homogenous clip-space
   63.36 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   63.37 +	
   63.38 +	// transform position into world space
   63.39 +	var_Position = (u_ModelMatrix * attr_Position).xyz;
   63.40 +}
   63.41 +
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/glsl/toneMapping_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    64.3 @@ -0,0 +1,100 @@
    64.4 +/*
    64.5 +===========================================================================
    64.6 +Copyright (C) 2008-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    64.7 +
    64.8 +This file is part of XreaL source code.
    64.9 +
   64.10 +XreaL source code is free software; you can redistribute it
   64.11 +and/or modify it under the terms of the GNU General Public License as
   64.12 +published by the Free Software Foundation; either version 2 of the License,
   64.13 +or (at your option) any later version.
   64.14 +
   64.15 +XreaL source code is distributed in the hope that it will be
   64.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   64.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   64.18 +GNU General Public License for more details.
   64.19 +
   64.20 +You should have received a copy of the GNU General Public License
   64.21 +along with XreaL source code; if not, write to the Free Software
   64.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   64.23 +===========================================================================
   64.24 +*/
   64.25 +
   64.26 +uniform sampler2D	u_CurrentMap;
   64.27 +uniform float		u_HDRKey;
   64.28 +uniform float		u_HDRAverageLuminance;
   64.29 +uniform float		u_HDRMaxLuminance;
   64.30 +
   64.31 +const vec4			LUMINANCE_VECTOR = vec4(0.2125, 0.7154, 0.0721, 0.0);
   64.32 +const vec3			BLUE_SHIFT_VECTOR = vec3(1.05, 0.97, 1.27); 
   64.33 +
   64.34 +void	main()
   64.35 +{
   64.36 +	// calculate the screen texcoord in the 0.0 to 1.0 range
   64.37 +	vec2 st = gl_FragCoord.st * r_FBufScale;
   64.38 +	
   64.39 +	// scale by the screen non-power-of-two-adjust
   64.40 +	st *= r_NPOTScale;
   64.41 +	
   64.42 +	vec4 color = texture2D(u_CurrentMap, st);
   64.43 +	
   64.44 +	// see http://www.gamedev.net/reference/articles/article2208.asp
   64.45 +	// for Mathematics of Reinhard's Photographic Tone Reproduction Operator
   64.46 +	
   64.47 +	// get the luminance of the current pixel
   64.48 +	float Y = dot(LUMINANCE_VECTOR, color);
   64.49 +	
   64.50 +	// calculate the relative luminance
   64.51 +	float Yr = u_HDRKey * Y / u_HDRAverageLuminance;
   64.52 +
   64.53 +	float Ymax = u_HDRMaxLuminance;
   64.54 +
   64.55 +#if defined(r_HDRToneMappingOperator_0)
   64.56 +	
   64.57 +	// simple tone map operator
   64.58 +	float L = Yr / (1.0 + Yr);
   64.59 +	
   64.60 +#elif defined(r_HDRToneMappingOperator_1)
   64.61 +	
   64.62 +	float L = 1.0 - exp(-Yr);
   64.63 +
   64.64 +#elif defined(r_HDRToneMappingOperator_2)
   64.65 +
   64.66 +	float Cmax = color.r;
   64.67 +	if(color.g > Cmax)
   64.68 +		Cmax = color.g;
   64.69 +	if(color.b > Cmax)
   64.70 +		Cmax = color.b;
   64.71 +
   64.72 +	float L = 1.0 - exp(-Yr * Cmax);
   64.73 +
   64.74 +	if(Cmax > 0.0)
   64.75 +	{
   64.76 +		L = L / Cmax;
   64.77 +	}
   64.78 +	else
   64.79 +	{
   64.80 +		L = 0.0;
   64.81 +	}
   64.82 +
   64.83 +#elif defined(r_HDRToneMappingOperator_3)
   64.84 +	
   64.85 +	float L = Yr / (1.0 + Yr) * (1.0 + Yr / (Ymax * Ymax));
   64.86 +	
   64.87 +#else
   64.88 +	
   64.89 +	// recommended by Wolgang Engel
   64.90 +	float L = Yr * (1.0 + Yr / (Ymax * Ymax)) / (1.0 + Yr);
   64.91 +#endif
   64.92 +	
   64.93 +	color.rgb *= L;
   64.94 +	
   64.95 +#if defined(r_HDRGamma)
   64.96 +	float gamma = 1.0 / r_HDRGamma;
   64.97 +	color.r = pow(color.r, gamma);
   64.98 +	color.g = pow(color.g, gamma);
   64.99 +	color.b = pow(color.b, gamma);
  64.100 +#endif
  64.101 +	
  64.102 +	gl_FragColor = color;
  64.103 +}
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/glsl/toneMapping_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    65.3 @@ -0,0 +1,31 @@
    65.4 +/*
    65.5 +===========================================================================
    65.6 +Copyright (C) 2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    65.7 +
    65.8 +This file is part of XreaL source code.
    65.9 +
   65.10 +XreaL source code is free software; you can redistribute it
   65.11 +and/or modify it under the terms of the GNU General Public License as
   65.12 +published by the Free Software Foundation; either version 2 of the License,
   65.13 +or (at your option) any later version.
   65.14 +
   65.15 +XreaL source code is distributed in the hope that it will be
   65.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   65.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   65.18 +GNU General Public License for more details.
   65.19 +
   65.20 +You should have received a copy of the GNU General Public License
   65.21 +along with XreaL source code; if not, write to the Free Software
   65.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   65.23 +===========================================================================
   65.24 +*/
   65.25 +
   65.26 +attribute vec4		attr_Position;
   65.27 +
   65.28 +uniform mat4		u_ModelViewProjectionMatrix;
   65.29 +
   65.30 +void	main()
   65.31 +{
   65.32 +	// transform vertex position into homogenous clip-space
   65.33 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   65.34 +}
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/glsl/uniformFog_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    66.3 @@ -0,0 +1,55 @@
    66.4 +/*
    66.5 +===========================================================================
    66.6 +Copyright (C) 2007 Robert Beckebans <trebor_7@users.sourceforge.net>
    66.7 +
    66.8 +This file is part of XreaL source code.
    66.9 +
   66.10 +XreaL source code is free software; you can redistribute it
   66.11 +and/or modify it under the terms of the GNU General Public License as
   66.12 +published by the Free Software Foundation; either version 2 of the License,
   66.13 +or (at your option) any later version.
   66.14 +
   66.15 +XreaL source code is distributed in the hope that it will be
   66.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   66.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   66.18 +GNU General Public License for more details.
   66.19 +
   66.20 +You should have received a copy of the GNU General Public License
   66.21 +along with XreaL source code; if not, write to the Free Software
   66.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   66.23 +===========================================================================
   66.24 +*/
   66.25 +
   66.26 +uniform sampler2D	u_DepthMap;
   66.27 +uniform vec3		u_ViewOrigin;
   66.28 +uniform float		u_FogDensity;
   66.29 +uniform vec3		u_FogColor;
   66.30 +uniform mat4		u_UnprojectMatrix;
   66.31 +
   66.32 +//varying vec3		var_Position;
   66.33 +
   66.34 +void	main()
   66.35 +{
   66.36 +	// calculate the screen texcoord in the 0.0 to 1.0 range
   66.37 +	vec2 st = gl_FragCoord.st * r_FBufScale;
   66.38 +	
   66.39 +	// scale by the screen non-power-of-two-adjust
   66.40 +	st *= r_NPOTScale;
   66.41 +	
   66.42 +	// reconstruct vertex position in world space
   66.43 +	float depth = texture2D(u_DepthMap, st).r;
   66.44 +	vec4 P = u_UnprojectMatrix * vec4(gl_FragCoord.xy, depth, 1.0);
   66.45 +	P.xyz /= P.w;
   66.46 +
   66.47 +	// calculate fog distance
   66.48 +	float fogDistance = distance(P.xyz, u_ViewOrigin);
   66.49 +	
   66.50 +	// calculate fog exponent
   66.51 +	float fogExponent = fogDistance * u_FogDensity;
   66.52 +	
   66.53 +	// calculate fog factor
   66.54 +	float fogFactor = exp2(-abs(fogExponent));
   66.55 +	
   66.56 +	// lerp between FBO color and fog color with GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA. GLS_DSTBLEND_SRC_ALPHA
   66.57 +	gl_FragColor = vec4(u_FogColor, fogFactor);
   66.58 +}
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/glsl/uniformFog_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    67.3 @@ -0,0 +1,31 @@
    67.4 +/*
    67.5 +===========================================================================
    67.6 +Copyright (C) 2007-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    67.7 +
    67.8 +This file is part of XreaL source code.
    67.9 +
   67.10 +XreaL source code is free software; you can redistribute it
   67.11 +and/or modify it under the terms of the GNU General Public License as
   67.12 +published by the Free Software Foundation; either version 2 of the License,
   67.13 +or (at your option) any later version.
   67.14 +
   67.15 +XreaL source code is distributed in the hope that it will be
   67.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   67.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   67.18 +GNU General Public License for more details.
   67.19 +
   67.20 +You should have received a copy of the GNU General Public License
   67.21 +along with XreaL source code; if not, write to the Free Software
   67.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   67.23 +===========================================================================
   67.24 +*/
   67.25 +
   67.26 +attribute vec4		attr_Position;
   67.27 +
   67.28 +uniform mat4		u_ModelViewProjectionMatrix;
   67.29 +
   67.30 +void	main()
   67.31 +{
   67.32 +	// transform vertex position into homogenous clip-space
   67.33 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   67.34 +}
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/glsl/vertexLighting_DBS_entity_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    68.3 @@ -0,0 +1,216 @@
    68.4 +/*
    68.5 +===========================================================================
    68.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    68.7 +
    68.8 +This file is part of XreaL source code.
    68.9 +
   68.10 +XreaL source code is free software; you can redistribute it
   68.11 +and/or modify it under the terms of the GNU General Public License as
   68.12 +published by the Free Software Foundation; either version 2 of the License,
   68.13 +or (at your option) any later version.
   68.14 +
   68.15 +XreaL source code is distributed in the hope that it will be
   68.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   68.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   68.18 +GNU General Public License for more details.
   68.19 +
   68.20 +You should have received a copy of the GNU General Public License
   68.21 +along with XreaL source code; if not, write to the Free Software
   68.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   68.23 +===========================================================================
   68.24 +*/
   68.25 +
   68.26 +uniform sampler2D	u_DiffuseMap;
   68.27 +uniform sampler2D	u_NormalMap;
   68.28 +uniform sampler2D	u_SpecularMap;
   68.29 +uniform int			u_AlphaTest;
   68.30 +uniform vec3		u_ViewOrigin;
   68.31 +uniform vec3		u_AmbientColor;
   68.32 +uniform vec3		u_LightDir;
   68.33 +uniform vec3		u_LightColor;
   68.34 +uniform float		u_SpecularExponent;
   68.35 +uniform int			u_ParallaxMapping;
   68.36 +uniform float		u_DepthScale;
   68.37 +uniform int         u_PortalClipping;
   68.38 +uniform vec4		u_PortalPlane;
   68.39 +
   68.40 +varying vec3		var_Position;
   68.41 +varying vec2		var_TexDiffuse;
   68.42 +#if defined(r_NormalMapping)
   68.43 +varying vec2		var_TexNormal;
   68.44 +varying vec2		var_TexSpecular;
   68.45 +varying vec3		var_Tangent;
   68.46 +varying vec3		var_Binormal;
   68.47 +#endif
   68.48 +varying vec3		var_Normal;
   68.49 +
   68.50 +#if defined(r_ParallaxMapping)
   68.51 +float RayIntersectDisplaceMap(vec2 dp, vec2 ds)
   68.52 +{
   68.53 +	const int linearSearchSteps = 16;
   68.54 +	const int binarySearchSteps = 6;
   68.55 +
   68.56 +	float depthStep = 1.0 / float(linearSearchSteps);
   68.57 +
   68.58 +	// current size of search window
   68.59 +	float size = depthStep;
   68.60 +
   68.61 +	// current depth position
   68.62 +	float depth = 0.0;
   68.63 +
   68.64 +	// best match found (starts with last position 1.0)
   68.65 +	float bestDepth = 1.0;
   68.66 +
   68.67 +	// search front to back for first point inside object
   68.68 +	for(int i = 0; i < linearSearchSteps - 1; ++i)
   68.69 +	{
   68.70 +		depth += size;
   68.71 +		
   68.72 +		vec4 t = texture2D(u_NormalMap, dp + ds * depth);
   68.73 +
   68.74 +		if(bestDepth > 0.996)		// if no depth found yet
   68.75 +			if(depth >= t.w)
   68.76 +				bestDepth = depth;	// store best depth
   68.77 +	}
   68.78 +
   68.79 +	depth = bestDepth;
   68.80 +	
   68.81 +	// recurse around first point (depth) for closest match
   68.82 +	for(int i = 0; i < binarySearchSteps; ++i)
   68.83 +	{
   68.84 +		size *= 0.5;
   68.85 +
   68.86 +		vec4 t = texture2D(u_NormalMap, dp + ds * depth);
   68.87 +		
   68.88 +		if(depth >= t.w)
   68.89 +		#ifdef RM_DOUBLEDEPTH
   68.90 +			if(depth <= t.z)
   68.91 +		#endif
   68.92 +			{
   68.93 +				bestDepth = depth;
   68.94 +				depth -= 2.0 * size;
   68.95 +			}
   68.96 +
   68.97 +		depth += size;
   68.98 +	}
   68.99 +
  68.100 +	return bestDepth;
  68.101 +}
  68.102 +#endif
  68.103 +
  68.104 +void	main()
  68.105 +{
  68.106 +	if(bool(u_PortalClipping))
  68.107 +	{
  68.108 +		float dist = dot(var_Position.xyz, u_PortalPlane.xyz) - u_PortalPlane.w;
  68.109 +		if(dist < 0.0)
  68.110 +		{
  68.111 +			discard;
  68.112 +			return;
  68.113 +		}
  68.114 +	}
  68.115 +
  68.116 +#if defined(r_NormalMapping)
  68.117 +	// invert tangent space for two sided surfaces
  68.118 +	mat3 tangentToWorldMatrix;
  68.119 +	if(gl_FrontFacing)
  68.120 +		tangentToWorldMatrix = mat3(-var_Tangent.xyz, -var_Binormal.xyz, -var_Normal.xyz);
  68.121 +	else
  68.122 +		tangentToWorldMatrix = mat3(var_Tangent.xyz, var_Binormal.xyz, var_Normal.xyz);
  68.123 +	
  68.124 +	// compute view direction in world space
  68.125 +	vec3 I = normalize(u_ViewOrigin - var_Position);
  68.126 +#endif
  68.127 +	
  68.128 +	vec2 texDiffuse = var_TexDiffuse.st;
  68.129 +#if defined(r_NormalMapping)
  68.130 +	vec2 texNormal = var_TexNormal.st;
  68.131 +	vec2 texSpecular = var_TexSpecular.st;
  68.132 +#endif
  68.133 +
  68.134 +#if defined(r_ParallaxMapping)
  68.135 +	if(bool(u_ParallaxMapping))
  68.136 +	{
  68.137 +		// ray intersect in view direction
  68.138 +		
  68.139 +		mat3 worldToTangentMatrix;
  68.140 +		#if defined(GLHW_ATI) || defined(GLHW_ATI_DX10)
  68.141 +		worldToTangentMatrix = mat3(tangentToWorldMatrix[0][0], tangentToWorldMatrix[1][0], tangentToWorldMatrix[2][0],
  68.142 +									tangentToWorldMatrix[0][1], tangentToWorldMatrix[1][1], tangentToWorldMatrix[2][1], 
  68.143 +									tangentToWorldMatrix[0][2], tangentToWorldMatrix[1][2], tangentToWorldMatrix[2][2]);
  68.144 +		#else
  68.145 +		worldToTangentMatrix = transpose(tangentToWorldMatrix);
  68.146 +		#endif
  68.147 +	
  68.148 +		// compute view direction in tangent space
  68.149 +		vec3 V = worldToTangentMatrix * (u_ViewOrigin - var_Position.xyz);
  68.150 +		V = normalize(V);
  68.151 +		
  68.152 +		// size and start position of search in texture space
  68.153 +		vec2 S = V.xy * -u_DepthScale / V.z;
  68.154 +			
  68.155 +		float depth = RayIntersectDisplaceMap(texNormal, S);
  68.156 +		
  68.157 +		// compute texcoords offset
  68.158 +		vec2 texOffset = S * depth;
  68.159 +		
  68.160 +		texDiffuse.st += texOffset;
  68.161 +		texNormal.st += texOffset;
  68.162 +		texSpecular.st += texOffset;
  68.163 +	}
  68.164 +#endif
  68.165 +
  68.166 +	// compute the diffuse term
  68.167 +	vec4 diffuse = texture2D(u_DiffuseMap, texDiffuse);
  68.168 +	if(u_AlphaTest == ATEST_GT_0 && diffuse.a <= 0.0)
  68.169 +	{
  68.170 +		discard;
  68.171 +		return;
  68.172 +	}
  68.173 +	else if(u_AlphaTest == ATEST_LT_128 && diffuse.a >= 0.5)
  68.174 +	{
  68.175 +		discard;
  68.176 +		return;
  68.177 +	}
  68.178 +	else if(u_AlphaTest == ATEST_GE_128 && diffuse.a < 0.5)
  68.179 +	{
  68.180 +		discard;
  68.181 +		return;
  68.182 +	}
  68.183 +
  68.184 +#if defined(r_NormalMapping)
  68.185 +	// compute normal in world space from normalmap
  68.186 +	vec3 N = tangentToWorldMatrix * (2.0 * (texture2D(u_NormalMap, texNormal).xyz - 0.5));
  68.187 +	
  68.188 +	// compute light direction in world space
  68.189 +	vec3 L = u_LightDir;
  68.190 +	
  68.191 +	// compute half angle in world space
  68.192 +	vec3 H = normalize(L + I);
  68.193 +	
  68.194 +	// compute the specular term
  68.195 +	vec3 specular = texture2D(u_SpecularMap, texSpecular).rgb * u_LightColor * pow(clamp(dot(N, H), 0.0, 1.0), r_SpecularExponent) * r_SpecularScale;
  68.196 +	
  68.197 +	// compute the light term
  68.198 +	vec3 light = u_AmbientColor + u_LightColor * clamp(dot(N, L), 0.0, 1.0);
  68.199 +	clamp(light, 0.0, 1.0);
  68.200 +	
  68.201 +	// compute final color
  68.202 +	vec4 color = diffuse;
  68.203 +	color.rgb *= light;
  68.204 +	color.rgb += specular;
  68.205 +	
  68.206 +	gl_FragColor = color;
  68.207 +#else
  68.208 +	
  68.209 +	vec3 N;
  68.210 +	if(gl_FrontFacing)
  68.211 +		N = -normalize(var_Normal);
  68.212 +	else
  68.213 +		N = normalize(var_Normal);
  68.214 +	
  68.215 +	vec3 L = u_LightDir;
  68.216 +	
  68.217 +	gl_FragColor = vec4(diffuse.rgb * (u_AmbientColor + u_LightColor * clamp(dot(N, L), 0.0, 1.0)), diffuse.a);
  68.218 +#endif
  68.219 +}
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/glsl/vertexLighting_DBS_entity_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    69.3 @@ -0,0 +1,118 @@
    69.4 +/*
    69.5 +===========================================================================
    69.6 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    69.7 +
    69.8 +This file is part of XreaL source code.
    69.9 +
   69.10 +XreaL source code is free software; you can redistribute it
   69.11 +and/or modify it under the terms of the GNU General Public License as
   69.12 +published by the Free Software Foundation; either version 2 of the License,
   69.13 +or (at your option) any later version.
   69.14 +
   69.15 +XreaL source code is distributed in the hope that it will be
   69.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   69.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   69.18 +GNU General Public License for more details.
   69.19 +
   69.20 +You should have received a copy of the GNU General Public License
   69.21 +along with XreaL source code; if not, write to the Free Software
   69.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   69.23 +===========================================================================
   69.24 +*/
   69.25 +
   69.26 +attribute vec4		attr_Position;
   69.27 +attribute vec4		attr_TexCoord0;
   69.28 +attribute vec3		attr_Tangent;
   69.29 +attribute vec3		attr_Binormal;
   69.30 +attribute vec3		attr_Normal;
   69.31 +#if defined(r_VertexSkinning)
   69.32 +attribute vec4		attr_BoneIndexes;
   69.33 +attribute vec4		attr_BoneWeights;
   69.34 +uniform int			u_VertexSkinning;
   69.35 +uniform mat4		u_BoneMatrix[MAX_GLSL_BONES];
   69.36 +#endif
   69.37 +
   69.38 +uniform mat4		u_DiffuseTextureMatrix;
   69.39 +uniform mat4		u_NormalTextureMatrix;
   69.40 +uniform mat4		u_SpecularTextureMatrix;
   69.41 +uniform mat4		u_ModelMatrix;
   69.42 +uniform mat4		u_ModelViewProjectionMatrix;
   69.43 +
   69.44 +varying vec3		var_Position;
   69.45 +varying vec2		var_TexDiffuse;
   69.46 +#if defined(r_NormalMapping)
   69.47 +varying vec2		var_TexNormal;
   69.48 +varying vec2		var_TexSpecular;
   69.49 +varying vec3		var_Tangent;
   69.50 +varying vec3		var_Binormal;
   69.51 +#endif
   69.52 +varying vec3		var_Normal;
   69.53 +
   69.54 +
   69.55 +void	main()
   69.56 +{
   69.57 +#if defined(r_VertexSkinning)
   69.58 +	if(bool(u_VertexSkinning))
   69.59 +	{
   69.60 +		vec4 vertex = vec4(0.0);
   69.61 +		vec3 tangent = vec3(0.0);
   69.62 +		vec3 binormal = vec3(0.0);
   69.63 +		vec3 normal = vec3(0.0);
   69.64 +
   69.65 +		for(int i = 0; i < 4; i++)
   69.66 +		{
   69.67 +			int boneIndex = int(attr_BoneIndexes[i]);
   69.68 +			float boneWeight = attr_BoneWeights[i];
   69.69 +			mat4  boneMatrix = u_BoneMatrix[boneIndex];
   69.70 +			
   69.71 +			vertex += (boneMatrix * attr_Position) * boneWeight;
   69.72 +		
   69.73 +			#if defined(r_NormalMapping)
   69.74 +			tangent += (boneMatrix * vec4(attr_Tangent, 0.0)).xyz * boneWeight;
   69.75 +			binormal += (boneMatrix * vec4(attr_Binormal, 0.0)).xyz * boneWeight;
   69.76 +			#endif
   69.77 +			
   69.78 +			normal += (boneMatrix * vec4(attr_Normal, 0.0)).xyz * boneWeight;
   69.79 +		}
   69.80 +
   69.81 +		// transform vertex position into homogenous clip-space
   69.82 +		gl_Position = u_ModelViewProjectionMatrix * vertex;
   69.83 +		
   69.84 +		// transform position into world space
   69.85 +		var_Position = (u_ModelMatrix * vertex).xyz;
   69.86 +		
   69.87 +		#if defined(r_NormalMapping)
   69.88 +		var_Tangent.xyz = (u_ModelMatrix * vec4(tangent, 0.0)).xyz;
   69.89 +		var_Binormal.xyz = (u_ModelMatrix * vec4(binormal, 0.0)).xyz;
   69.90 +		#endif
   69.91 +		
   69.92 +		var_Normal.xyz = (u_ModelMatrix * vec4(normal, 0.0)).xyz;
   69.93 +	}
   69.94 +	else
   69.95 +#endif
   69.96 +	{
   69.97 +		// transform vertex position into homogenous clip-space
   69.98 +		gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   69.99 +	
  69.100 +		// transform position into world space
  69.101 +		var_Position = (u_ModelMatrix * attr_Position).xyz;
  69.102 +	
  69.103 +		#if defined(r_NormalMapping)
  69.104 +		var_Tangent.xyz = (u_ModelMatrix * vec4(attr_Tangent, 0.0)).xyz;
  69.105 +		var_Binormal.xyz = (u_ModelMatrix * vec4(attr_Binormal, 0.0)).xyz;
  69.106 +		#endif
  69.107 +		
  69.108 +		var_Normal.xyz = (u_ModelMatrix * vec4(attr_Normal, 0.0)).xyz;
  69.109 +	}
  69.110 +
  69.111 +	// transform diffusemap texcoords
  69.112 +	var_TexDiffuse = (u_DiffuseTextureMatrix * attr_TexCoord0).st;
  69.113 +	
  69.114 +#if defined(r_NormalMapping)
  69.115 +	// transform normalmap texcoords
  69.116 +	var_TexNormal = (u_NormalTextureMatrix * attr_TexCoord0).st;
  69.117 +	
  69.118 +	// transform specularmap texture coords
  69.119 +	var_TexSpecular = (u_SpecularTextureMatrix * attr_TexCoord0).st;
  69.120 +#endif
  69.121 +}
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/glsl/vertexLighting_DBS_world_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    70.3 @@ -0,0 +1,225 @@
    70.4 +/*
    70.5 +===========================================================================
    70.6 +Copyright (C) 2008-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    70.7 +
    70.8 +This file is part of XreaL source code.
    70.9 +
   70.10 +XreaL source code is free software; you can redistribute it
   70.11 +and/or modify it under the terms of the GNU General Public License as
   70.12 +published by the Free Software Foundation; either version 2 of the License,
   70.13 +or (at your option) any later version.
   70.14 +
   70.15 +XreaL source code is distributed in the hope that it will be
   70.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   70.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   70.18 +GNU General Public License for more details.
   70.19 +
   70.20 +You should have received a copy of the GNU General Public License
   70.21 +along with XreaL source code; if not, write to the Free Software
   70.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   70.23 +===========================================================================
   70.24 +*/
   70.25 +
   70.26 +uniform sampler2D	u_DiffuseMap;
   70.27 +uniform sampler2D	u_NormalMap;
   70.28 +uniform sampler2D	u_SpecularMap;
   70.29 +uniform int			u_AlphaTest;
   70.30 +uniform vec3		u_ViewOrigin;
   70.31 +uniform int			u_ParallaxMapping;
   70.32 +uniform float		u_DepthScale;
   70.33 +uniform int         u_PortalClipping;
   70.34 +uniform vec4		u_PortalPlane;
   70.35 +
   70.36 +varying vec3		var_Position;
   70.37 +varying vec4		var_TexDiffuseNormal;
   70.38 +varying vec2		var_TexSpecular;
   70.39 +varying vec4		var_LightColor;
   70.40 +#if !defined(COMPAT_Q3A)
   70.41 +varying vec3		var_LightDirection;
   70.42 +#endif
   70.43 +varying vec3		var_Tangent;
   70.44 +varying vec3		var_Binormal;
   70.45 +varying vec3		var_Normal;
   70.46 +
   70.47 +#if defined(r_ParallaxMapping)
   70.48 +float RayIntersectDisplaceMap(vec2 dp, vec2 ds)
   70.49 +{
   70.50 +	const int linearSearchSteps = 16;
   70.51 +	const int binarySearchSteps = 6;
   70.52 +
   70.53 +	float depthStep = 1.0 / float(linearSearchSteps);
   70.54 +
   70.55 +	// current size of search window
   70.56 +	float size = depthStep;
   70.57 +
   70.58 +	// current depth position
   70.59 +	float depth = 0.0;
   70.60 +
   70.61 +	// best match found (starts with last position 1.0)
   70.62 +	float bestDepth = 1.0;
   70.63 +
   70.64 +	// search front to back for first point inside object
   70.65 +	for(int i = 0; i < linearSearchSteps - 1; ++i)
   70.66 +	{
   70.67 +		depth += size;
   70.68 +		
   70.69 +		vec4 t = texture2D(u_NormalMap, dp + ds * depth);
   70.70 +
   70.71 +		if(bestDepth > 0.996)		// if no depth found yet
   70.72 +			if(depth >= t.w)
   70.73 +				bestDepth = depth;	// store best depth
   70.74 +	}
   70.75 +
   70.76 +	depth = bestDepth;
   70.77 +	
   70.78 +	// recurse around first point (depth) for closest match
   70.79 +	for(int i = 0; i < binarySearchSteps; ++i)
   70.80 +	{
   70.81 +		size *= 0.5;
   70.82 +
   70.83 +		vec4 t = texture2D(u_NormalMap, dp + ds * depth);
   70.84 +		
   70.85 +		if(depth >= t.w)
   70.86 +		#ifdef RM_DOUBLEDEPTH
   70.87 +			if(depth <= t.z)
   70.88 +		#endif
   70.89 +			{
   70.90 +				bestDepth = depth;
   70.91 +				depth -= 2.0 * size;
   70.92 +			}
   70.93 +
   70.94 +		depth += size;
   70.95 +	}
   70.96 +
   70.97 +	return bestDepth;
   70.98 +}
   70.99 +#endif
  70.100 +
  70.101 +void	main()
  70.102 +{
  70.103 +	if(bool(u_PortalClipping))
  70.104 +	{
  70.105 +		float dist = dot(var_Position.xyz, u_PortalPlane.xyz) - u_PortalPlane.w;
  70.106 +		if(dist < 0.0)
  70.107 +		{
  70.108 +			discard;
  70.109 +			return;
  70.110 +		}
  70.111 +	}
  70.112 +
  70.113 +#if defined(r_NormalMapping)
  70.114 +	// construct object-space-to-tangent-space 3x3 matrix
  70.115 +	mat3 objectToTangentMatrix;
  70.116 +	if(gl_FrontFacing)
  70.117 +	{
  70.118 +		objectToTangentMatrix = mat3( -var_Tangent.x, -var_Binormal.x, -var_Normal.x,
  70.119 +							-var_Tangent.y, -var_Binormal.y, -var_Normal.y,
  70.120 +							-var_Tangent.z, -var_Binormal.z, -var_Normal.z	);
  70.121 +	}
  70.122 +	else
  70.123 +	{
  70.124 +		objectToTangentMatrix = mat3(	var_Tangent.x, var_Binormal.x, var_Normal.x,
  70.125 +							var_Tangent.y, var_Binormal.y, var_Normal.y,
  70.126 +							var_Tangent.z, var_Binormal.z, var_Normal.z	);
  70.127 +	}
  70.128 +	
  70.129 +	// compute view direction in tangent space
  70.130 +	vec3 V = normalize(objectToTangentMatrix * (u_ViewOrigin - var_Position));
  70.131 +#endif
  70.132 +	
  70.133 +	vec2 texDiffuse = var_TexDiffuseNormal.st;
  70.134 +
  70.135 +#if defined(r_NormalMapping)
  70.136 +	vec2 texNormal = var_TexDiffuseNormal.pq;
  70.137 +	vec2 texSpecular = var_TexSpecular.st;
  70.138 +#endif
  70.139 +
  70.140 +#if defined(r_ParallaxMapping)
  70.141 +	if(bool(u_ParallaxMapping))
  70.142 +	{
  70.143 +		// ray intersect in view direction
  70.144 +		
  70.145 +		// size and start position of search in texture space
  70.146 +		vec2 S = V.xy * -u_DepthScale / V.z;
  70.147 +			
  70.148 +		float depth = RayIntersectDisplaceMap(texNormal, S);
  70.149 +		
  70.150 +		// compute texcoords offset
  70.151 +		vec2 texOffset = S * depth;
  70.152 +		
  70.153 +		texDiffuse.st += texOffset;
  70.154 +		texNormal.st += texOffset;
  70.155 +		texSpecular.st += texOffset;
  70.156 +	}
  70.157 +#endif
  70.158 +
  70.159 +	// compute the diffuse term
  70.160 +	vec4 diffuse = texture2D(u_DiffuseMap, texDiffuse);
  70.161 +	if(u_AlphaTest == ATEST_GT_0 && diffuse.a <= 0.0)
  70.162 +	{
  70.163 +		discard;
  70.164 +		return;
  70.165 +	}
  70.166 +	else if(u_AlphaTest == ATEST_LT_128 && diffuse.a >= 0.5)
  70.167 +	{
  70.168 +		discard;
  70.169 +		return;
  70.170 +	}
  70.171 +	else if(u_AlphaTest == ATEST_GE_128 && diffuse.a < 0.5)
  70.172 +	{
  70.173 +		discard;
  70.174 +		return;
  70.175 +	}
  70.176 +
  70.177 +#if defined(r_NormalMapping)
  70.178 +
  70.179 +	// compute normal in tangent space from normalmap
  70.180 +	vec3 N = 2.0 * (texture2D(u_NormalMap, texNormal).xyz - 0.5);
  70.181 +	#if defined(r_NormalScale)
  70.182 +	N.z *= r_NormalScale;
  70.183 +	normalize(N);
  70.184 +	#endif
  70.185 +
  70.186 +#if defined(COMPAT_Q3A)
  70.187 +	// fake bump mapping
  70.188 + 	vec3 L = N;
  70.189 +#else
  70.190 +	// compute light direction in tangent space
  70.191 +	vec3 L = normalize(objectToTangentMatrix * var_LightDirection);
  70.192 +#endif
  70.193 + 
  70.194 + 	// compute half angle in tangent space
  70.195 +	vec3 H = normalize(L + V);
  70.196 +	
  70.197 +	// compute the light term
  70.198 +	vec3 light = var_LightColor.rgb * clamp(dot(N, L), 0.0, 1.0);
  70.199 +	
  70.200 +	// compute the specular term
  70.201 +	vec3 specular = texture2D(u_SpecularMap, texSpecular).rgb * var_LightColor.rgb * pow(clamp(dot(N, H), 0.0, 1.0), r_SpecularExponent) * r_SpecularScale;
  70.202 +	
  70.203 +	// compute final color
  70.204 +	vec4 color = diffuse;
  70.205 +	color.rgb *= light;
  70.206 +	color.rgb += specular;
  70.207 +	
  70.208 +//	color.rgb *= var_Color.rgb;	// apply model paint color for terrain blending
  70.209 +	
  70.210 +//	color.rgb = var_LightDirection.rgb;
  70.211 +	gl_FragColor = color;
  70.212 +
  70.213 +#elif defined(COMPAT_Q3A)
  70.214 +
  70.215 +	gl_FragColor = vec4(diffuse.rgb * var_LightColor.rgb, diffuse.a);
  70.216 +
  70.217 +#else
  70.218 +	vec3 N;
  70.219 +	if(gl_FrontFacing)
  70.220 +		N = -normalize(var_Normal);
  70.221 +	else
  70.222 +		N = normalize(var_Normal);
  70.223 +	
  70.224 +	vec3 L = normalize(var_LightDirection);
  70.225 +	
  70.226 +	gl_FragColor = vec4(diffuse.rgb * var_LightColor.rgb * clamp(dot(N, L), 0.0, 1.0), diffuse.a);
  70.227 +#endif
  70.228 +}
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/glsl/vertexLighting_DBS_world_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    71.3 @@ -0,0 +1,101 @@
    71.4 +/*
    71.5 +===========================================================================
    71.6 +Copyright (C) 2008-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    71.7 +
    71.8 +This file is part of XreaL source code.
    71.9 +
   71.10 +XreaL source code is free software; you can redistribute it
   71.11 +and/or modify it under the terms of the GNU General Public License as
   71.12 +published by the Free Software Foundation; either version 2 of the License,
   71.13 +or (at your option) any later version.
   71.14 +
   71.15 +XreaL source code is distributed in the hope that it will be
   71.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   71.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   71.18 +GNU General Public License for more details.
   71.19 +
   71.20 +You should have received a copy of the GNU General Public License
   71.21 +along with XreaL source code; if not, write to the Free Software
   71.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   71.23 +===========================================================================
   71.24 +*/
   71.25 +
   71.26 +attribute vec4		attr_Position;
   71.27 +attribute vec4		attr_TexCoord0;
   71.28 +attribute vec3		attr_Tangent;
   71.29 +attribute vec3		attr_Binormal;
   71.30 +attribute vec3		attr_Normal;
   71.31 +attribute vec4		attr_Color;
   71.32 +#if !defined(COMPAT_Q3A)
   71.33 +attribute vec3		attr_LightDirection;
   71.34 +#endif
   71.35 +
   71.36 +uniform mat4		u_DiffuseTextureMatrix;
   71.37 +uniform mat4		u_NormalTextureMatrix;
   71.38 +uniform mat4		u_SpecularTextureMatrix;
   71.39 +uniform int			u_InverseVertexColor;
   71.40 +uniform mat4		u_ModelViewProjectionMatrix;
   71.41 +uniform int			u_ColorGen;
   71.42 +uniform int			u_AlphaGen;
   71.43 +uniform vec4		u_Color;
   71.44 +
   71.45 +varying vec3		var_Position;
   71.46 +varying vec4		var_TexDiffuseNormal;
   71.47 +varying vec2		var_TexSpecular;
   71.48 +varying vec4		var_LightColor;
   71.49 +#if !defined(COMPAT_Q3A)
   71.50 +varying vec3		var_LightDirection;
   71.51 +#endif
   71.52 +varying vec3		var_Tangent;
   71.53 +varying vec3		var_Binormal;
   71.54 +varying vec3		var_Normal;
   71.55 +
   71.56 +void	main()
   71.57 +{
   71.58 +	// transform vertex position into homogenous clip-space
   71.59 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   71.60 +	
   71.61 +	// assign position in object space
   71.62 +	var_Position = attr_Position.xyz;
   71.63 +	
   71.64 +	// transform diffusemap texcoords
   71.65 +	var_TexDiffuseNormal.st = (u_DiffuseTextureMatrix * attr_TexCoord0).st;
   71.66 +	
   71.67 +#if defined(r_NormalMapping)
   71.68 +	// transform normalmap texcoords
   71.69 +	var_TexDiffuseNormal.pq = (u_NormalTextureMatrix * attr_TexCoord0).st;
   71.70 +	
   71.71 +	// transform specularmap texture coords
   71.72 +	var_TexSpecular = (u_SpecularTextureMatrix * attr_TexCoord0).st;
   71.73 +#endif
   71.74 +	
   71.75 +#if !defined(COMPAT_Q3A)
   71.76 +	// assign vertex to light vector in object space
   71.77 +	var_LightDirection = attr_LightDirection;
   71.78 +#endif
   71.79 +	
   71.80 +	// assign color
   71.81 +	if(u_ColorGen == CGEN_VERTEX)
   71.82 +	{
   71.83 +		var_LightColor.r = attr_Color.r;
   71.84 +		var_LightColor.g = attr_Color.g;
   71.85 +		var_LightColor.b = attr_Color.b;
   71.86 +	}
   71.87 +	else if(u_ColorGen == CGEN_ONE_MINUS_VERTEX)
   71.88 +	{
   71.89 +		var_LightColor.r = 1.0 - attr_Color.r;
   71.90 +		var_LightColor.g = 1.0 - attr_Color.g;
   71.91 +		var_LightColor.b = 1.0 - attr_Color.b;
   71.92 +	}
   71.93 +	else
   71.94 +	{
   71.95 +		var_LightColor.rgb = u_Color.rgb;
   71.96 +	}
   71.97 +	
   71.98 +#if defined(r_NormalMapping)
   71.99 +	var_Tangent = attr_Tangent;
  71.100 +	var_Binormal = attr_Binormal;
  71.101 +#endif
  71.102 +
  71.103 +	var_Normal = attr_Normal;
  71.104 +}
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/glsl/volumetricFog_fp.glsl	Wed Jun 10 09:31:46 2009 +0800
    72.3 @@ -0,0 +1,119 @@
    72.4 +/*
    72.5 +===========================================================================
    72.6 +Copyright (C) 2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    72.7 +
    72.8 +This file is part of XreaL source code.
    72.9 +
   72.10 +XreaL source code is free software; you can redistribute it
   72.11 +and/or modify it under the terms of the GNU General Public License as
   72.12 +published by the Free Software Foundation; either version 2 of the License,
   72.13 +or (at your option) any later version.
   72.14 +
   72.15 +XreaL source code is distributed in the hope that it will be
   72.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   72.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   72.18 +GNU General Public License for more details.
   72.19 +
   72.20 +You should have received a copy of the GNU General Public License
   72.21 +along with XreaL source code; if not, write to the Free Software
   72.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   72.23 +===========================================================================
   72.24 +*/
   72.25 +
   72.26 +uniform sampler2D	u_DepthMap;			// raw depth in red channel
   72.27 +uniform sampler2D	u_DepthMapBack;		// color encoded depth
   72.28 +uniform sampler2D	u_DepthMapFront;	// color encoded depth
   72.29 +uniform vec3		u_ViewOrigin;
   72.30 +uniform float		u_FogDensity;
   72.31 +uniform vec3		u_FogColor;
   72.32 +uniform mat4		u_UnprojectMatrix;
   72.33 +
   72.34 +
   72.35 +float DecodeDepth(vec4 color)
   72.36 +{
   72.37 +	float depth;
   72.38 +	
   72.39 +	const vec4 bitShifts = vec4(1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0); 	// gl_FragCoord.z with 32 bit precision
   72.40 +//	const vec4 bitShifts = vec4(1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0, 0.0); 								// gl_FragCoord.z with 24 bit precision
   72.41 +	
   72.42 +	depth = dot(color, bitShifts);
   72.43 +	
   72.44 +	return depth;
   72.45 +}
   72.46 +
   72.47 +void	main()
   72.48 +{
   72.49 +	// calculate the screen texcoord in the 0.0 to 1.0 range
   72.50 +	vec2 st = gl_FragCoord.st * r_FBufScale;
   72.51 +	
   72.52 +	// scale by the screen non-power-of-two-adjust
   72.53 +	st *= r_NPOTScale;
   72.54 +	
   72.55 +	// calculate fog volume depth
   72.56 +	float fogDepth;
   72.57 +	
   72.58 +	float depthSolid = texture2D(u_DepthMap, st).r;
   72.59 +	
   72.60 +//#if 0 //defined(GLHW_ATI_DX10) || defined(GLHW_NV_DX10)
   72.61 +//
   72.62 +//	float depthBack = texture2D(u_DepthMapBack, st).a;
   72.63 +//	float depthFront = texture2D(u_DepthMapFront, st).a;
   72.64 +//#else
   72.65 +	float depthBack = DecodeDepth(texture2D(u_DepthMapBack, st));
   72.66 +	float depthFront = DecodeDepth(texture2D(u_DepthMapFront, st));
   72.67 +//#endif
   72.68 +
   72.69 +	if(depthSolid < depthFront)
   72.70 +	{
   72.71 +		discard;
   72.72 +		return;
   72.73 +	}
   72.74 +	
   72.75 +	if(depthSolid < depthBack)
   72.76 +	{
   72.77 +		depthBack = depthSolid;
   72.78 +	}
   72.79 +	
   72.80 +	fogDepth = depthSolid;
   72.81 +	
   72.82 +//#if 1
   72.83 +	// reconstruct vertex position in world space
   72.84 +	vec4 posBack = u_UnprojectMatrix * vec4(gl_FragCoord.xy, depthBack, 1.0);
   72.85 +	posBack.xyz /= posBack.w;
   72.86 +	
   72.87 +	vec4 posFront = u_UnprojectMatrix * vec4(gl_FragCoord.xy, depthFront, 1.0);
   72.88 +	posFront.xyz /= posFront.w;
   72.89 +	
   72.90 +	if(posFront.w <= 0.0)
   72.91 +	{
   72.92 +		// we might be in the volume
   72.93 +		posFront = vec4(u_ViewOrigin, 1.0);
   72.94 +	}
   72.95 +
   72.96 +	// calculate fog distance
   72.97 +	//if(depthFront < 
   72.98 +	float fogDistance = distance(posBack, posFront);
   72.99 +	//float fogDistance = abs(depthBack - depthFront);
  72.100 +	
  72.101 +/*
  72.102 +#elif 0
  72.103 +	vec4 P = u_UnprojectMatrix * vec4(gl_FragCoord.xy, depthBack - depthFront, 1.0);
  72.104 +	P.xyz /= P.w;
  72.105 +
  72.106 +	// calculate fog distance
  72.107 +	float fogDistance = distance(P.xyz, u_ViewOrigin);
  72.108 +	
  72.109 +#else
  72.110 +	float fogDistance = depthBack - depthFront;
  72.111 +#endif
  72.112 +*/
  72.113 +	
  72.114 +	// calculate fog exponent
  72.115 +	float fogExponent = fogDistance * u_FogDensity;
  72.116 +	
  72.117 +	// calculate fog factor
  72.118 +	float fogFactor = exp2(-abs(fogExponent));
  72.119 +
  72.120 +	// lerp between FBO color and fog color with GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA. GLS_DSTBLEND_SRC_ALPHA
  72.121 +	gl_FragColor = vec4(u_FogColor, fogFactor);
  72.122 +}
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/glsl/volumetricFog_vp.glsl	Wed Jun 10 09:31:46 2009 +0800
    73.3 @@ -0,0 +1,31 @@
    73.4 +/*
    73.5 +===========================================================================
    73.6 +Copyright (C) 2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    73.7 +
    73.8 +This file is part of XreaL source code.
    73.9 +
   73.10 +XreaL source code is free software; you can redistribute it
   73.11 +and/or modify it under the terms of the GNU General Public License as
   73.12 +published by the Free Software Foundation; either version 2 of the License,
   73.13 +or (at your option) any later version.
   73.14 +
   73.15 +XreaL source code is distributed in the hope that it will be
   73.16 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   73.17 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   73.18 +GNU General Public License for more details.
   73.19 +
   73.20 +You should have received a copy of the GNU General Public License
   73.21 +along with XreaL source code; if not, write to the Free Software
   73.22 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   73.23 +===========================================================================
   73.24 +*/
   73.25 +
   73.26 +attribute vec4		attr_Position;
   73.27 +
   73.28 +uniform mat4		u_ModelViewProjectionMatrix;
   73.29 +
   73.30 +void	main()
   73.31 +{
   73.32 +	// transform vertex position into homogenous clip-space
   73.33 +	gl_Position = u_ModelViewProjectionMatrix * attr_Position;
   73.34 +}
    74.1 --- a/src/client/cl_cgame.c	Sat Jun 06 03:54:16 2009 +0800
    74.2 +++ b/src/client/cl_cgame.c	Wed Jun 10 09:31:46 2009 +0800
    74.3 @@ -567,7 +567,7 @@
    74.4  		re.LoadWorld( VMA(1) );
    74.5  		return 0; 
    74.6  	case CG_R_REGISTERMODEL:
    74.7 -		return re.RegisterModel( VMA(1) );
    74.8 +		return re.RegisterModel( VMA(1), qfalse );
    74.9  	case CG_R_REGISTERSKIN:
   74.10  		return re.RegisterSkin( VMA(1) );
   74.11  	case CG_R_REGISTERSHADER:
    75.1 --- a/src/client/cl_cin.c	Sat Jun 06 03:54:16 2009 +0800
    75.2 +++ b/src/client/cl_cin.c	Wed Jun 10 09:31:46 2009 +0800
    75.3 @@ -992,19 +992,6 @@
    75.4  
    75.5          cinTable[currentHandle].drawX = cinTable[currentHandle].CIN_WIDTH;
    75.6          cinTable[currentHandle].drawY = cinTable[currentHandle].CIN_HEIGHT;
    75.7 -        
    75.8 -	// rage pro is very slow at 512 wide textures, voodoo can't do it at all
    75.9 -	if ( cls.glconfig.hardwareType == GLHW_RAGEPRO || cls.glconfig.maxTextureSize <= 256) {
   75.10 -                if (cinTable[currentHandle].drawX>256) {
   75.11 -                        cinTable[currentHandle].drawX = 256;
   75.12 -                }
   75.13 -                if (cinTable[currentHandle].drawY>256) {
   75.14 -                        cinTable[currentHandle].drawY = 256;
   75.15 -                }
   75.16 -		if (cinTable[currentHandle].CIN_WIDTH != 256 || cinTable[currentHandle].CIN_HEIGHT != 256) {
   75.17 -			Com_Printf("HACK: approxmimating cinematic for Rage Pro or Voodoo\n");
   75.18 -		}
   75.19 -	}
   75.20  }
   75.21  
   75.22  /******************************************************************************
    76.1 --- a/src/client/cl_ui.c	Sat Jun 06 03:54:16 2009 +0800
    76.2 +++ b/src/client/cl_ui.c	Wed Jun 10 09:31:46 2009 +0800
    76.3 @@ -804,7 +804,7 @@
    76.4  		return FS_Seek( args[1], args[2], args[3] );
    76.5  	
    76.6  	case UI_R_REGISTERMODEL:
    76.7 -		return re.RegisterModel( VMA(1) );
    76.8 +		return re.RegisterModel( VMA(1), qfalse );
    76.9  
   76.10  	case UI_R_REGISTERSKIN:
   76.11  		return re.RegisterSkin( VMA(1) );
    77.1 --- a/src/client/client.h	Sat Jun 06 03:54:16 2009 +0800
    77.2 +++ b/src/client/client.h	Wed Jun 10 09:31:46 2009 +0800
    77.3 @@ -341,7 +341,7 @@
    77.4  	netadr_t	authorizeServer;
    77.5  
    77.6  	// rendering info
    77.7 -	glconfig_t	glconfig;
    77.8 +	glConfig_t	glconfig;
    77.9  	qhandle_t	charSetShader;
   77.10  	qhandle_t	whiteShader;
   77.11  	qhandle_t	consoleShader;
    78.1 --- a/src/qcommon/q_math.c	Sat Jun 06 03:54:16 2009 +0800
    78.2 +++ b/src/qcommon/q_math.c	Wed Jun 10 09:31:46 2009 +0800
    78.3 @@ -35,6 +35,13 @@
    78.4  vec3_t	vec3_origin = {0,0,0};
    78.5  vec3_t	axisDefault[3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
    78.6  
    78.7 +quat_t          quatIdentity = { 0, 0, 0, 1 };
    78.8 +
    78.9 +matrix_t matrixIdentity = {	1, 0, 0, 0,
   78.10 +							0, 1, 0, 0,
   78.11 +							0, 0, 1, 0,
   78.12 +							0, 0, 0, 1};
   78.13 +
   78.14  
   78.15  vec4_t		colorBlack	= {0, 0, 0, 1};
   78.16  vec4_t		colorRed	= {1, 0, 0, 1};
   78.17 @@ -163,6 +170,19 @@
   78.18  
   78.19  //=======================================================
   78.20  
   78.21 +byte ClampByte(int i)
   78.22 +{
   78.23 +	if(i < 0)
   78.24 +	{
   78.25 +		return 0;
   78.26 +	}
   78.27 +	if(i > 255)
   78.28 +	{
   78.29 +		return 255;
   78.30 +	}
   78.31 +	return i;
   78.32 +}
   78.33 +
   78.34  signed char ClampChar( int i ) {
   78.35  	if ( i < -128 ) {
   78.36  		return -128;
   78.37 @@ -259,6 +279,29 @@
   78.38  	return max;
   78.39  }
   78.40  
   78.41 +void ClampColor(vec4_t color)
   78.42 +{
   78.43 +	int             i;
   78.44 +
   78.45 +	for(i = 0; i < 4; i++)
   78.46 +	{
   78.47 +		if(color[i] < 0)
   78.48 +			color[i] = 0;
   78.49 +
   78.50 +		if(color[i] > 1)
   78.51 +			color[i] = 1;
   78.52 +	}
   78.53 +}
   78.54 +
   78.55 +int NearestPowerOfTwo(int val)
   78.56 +{
   78.57 +	int             answer;
   78.58 +
   78.59 +	for(answer = 1; answer < val; answer <<= 1)
   78.60 +		;
   78.61 +	return answer;
   78.62 +}
   78.63 +
   78.64  
   78.65  /*
   78.66  =====================
   78.67 @@ -1593,3 +1636,1162 @@
   78.68  
   78.69  	return (int)( (unsigned int)fi.ui >> 31 );
   78.70  }
   78.71 +
   78.72 +// *INDENT-OFF*
   78.73 +void MatrixIdentity(matrix_t m)
   78.74 +{
   78.75 +    m[ 0] = 1;      m[ 4] = 0;      m[ 8] = 0;      m[12] = 0;
   78.76 +	m[ 1] = 0;      m[ 5] = 1;      m[ 9] = 0;      m[13] = 0;
   78.77 +	m[ 2] = 0;      m[ 6] = 0;      m[10] = 1;      m[14] = 0;
   78.78 +	m[ 3] = 0;      m[ 7] = 0;      m[11] = 0;      m[15] = 1;
   78.79 +}
   78.80 +
   78.81 +void MatrixClear(matrix_t m)
   78.82 +{
   78.83 +    m[ 0] = 0;      m[ 4] = 0;      m[ 8] = 0;      m[12] = 0;
   78.84 +	m[ 1] = 0;      m[ 5] = 0;      m[ 9] = 0;      m[13] = 0;
   78.85 +	m[ 2] = 0;      m[ 6] = 0;      m[10] = 0;      m[14] = 0;
   78.86 +	m[ 3] = 0;      m[ 7] = 0;      m[11] = 0;      m[15] = 0;
   78.87 +}
   78.88 +
   78.89 +
   78.90 +void MatrixCopy(const matrix_t in, matrix_t out)
   78.91 +{
   78.92 +#if id386_sse && defined __GNUC__ && 0
   78.93 +	asm volatile
   78.94 +	(
   78.95 +	"movups         (%%edx),        %%xmm0\n"
   78.96 +	"movups         0x10(%%edx),    %%xmm1\n"
   78.97 +	"movups         0x20(%%edx),    %%xmm2\n"
   78.98 +	"movups         0x30(%%edx),    %%xmm3\n"
   78.99 +
  78.100 +	"movups         %%xmm0,         (%%eax)\n"
  78.101 +	"movups         %%xmm1,         0x10(%%eax)\n"
  78.102 +	"movups         %%xmm2,         0x20(%%eax)\n"
  78.103 +	"movups         %%xmm3,         0x30(%%eax)\n"
  78.104 +	:
  78.105 +	: "a"( out ), "d"( in )
  78.106 +	: "memory"
  78.107 +		);
  78.108 +#elif id386_3dnow && defined __GNUC__
  78.109 +	asm volatile
  78.110 +	(
  78.111 +	"femms\n"
  78.112 +	"movq           (%%edx),        %%mm0\n"
  78.113 +	"movq           8(%%edx),       %%mm1\n"
  78.114 +	"movq           16(%%edx),      %%mm2\n"
  78.115 +	"movq           24(%%edx),      %%mm3\n"
  78.116 +	"movq           32(%%edx),      %%mm4\n"
  78.117 +	"movq           40(%%edx),      %%mm5\n"
  78.118 +	"movq           48(%%edx),      %%mm6\n"
  78.119 +	"movq           56(%%edx),      %%mm7\n"
  78.120 +
  78.121 +	"movq           %%mm0,          (%%eax)\n"
  78.122 +	"movq           %%mm1,          8(%%eax)\n"
  78.123 +	"movq           %%mm2,          16(%%eax)\n"
  78.124 +	"movq           %%mm3,          24(%%eax)\n"
  78.125 +	"movq           %%mm4,          32(%%eax)\n"
  78.126 +	"movq           %%mm5,          40(%%eax)\n"
  78.127 +	"movq           %%mm6,          48(%%eax)\n"
  78.128 +	"movq           %%mm7,          56(%%eax)\n"
  78.129 +	"femms\n"
  78.130 +	:
  78.131 +	: "a"(out), "d"(in)
  78.132 +	: "memory"
  78.133 +	);
  78.134 +#else
  78.135 +        out[ 0] = in[ 0];       out[ 4] = in[ 4];       out[ 8] = in[ 8];       out[12] = in[12];
  78.136 +        out[ 1] = in[ 1];       out[ 5] = in[ 5];       out[ 9] = in[ 9];       out[13] = in[13];
  78.137 +		out[ 2] = in[ 2];       out[ 6] = in[ 6];       out[10] = in[10];       out[14] = in[14];
  78.138 +		out[ 3] = in[ 3];       out[ 7] = in[ 7];       out[11] = in[11];       out[15] = in[15];
  78.139 +#endif
  78.140 +}
  78.141 +
  78.142 +qboolean MatrixCompare(const matrix_t a, const matrix_t b)
  78.143 +{
  78.144 +	return (a[ 0] == b[ 0] && a[ 4] == b[ 4] && a[ 8] == b[ 8] && a[12] == b[12] &&
  78.145 +            a[ 1] == b[ 1] && a[ 5] == b[ 5] && a[ 9] == b[ 9] && a[13] == b[13] &&
  78.146 +		    a[ 2] == b[ 2] && a[ 6] == b[ 6] && a[10] == b[10] && a[14] == b[14] &&
  78.147 +		    a[ 3] == b[ 3] && a[ 7] == b[ 7] && a[11] == b[11] && a[15] == b[15]);
  78.148 +}
  78.149 +
  78.150 +void MatrixTransposeIntoXMM(const matrix_t m)
  78.151 +{
  78.152 +#if id386_sse && defined __GNUC__ && 0
  78.153 +        asm volatile
  78.154 +        (                                                                               // reg[0]                       | reg[1]                | reg[2]                | reg[3]
  78.155 +        // load transpose into XMM registers
  78.156 +        "movlps         (%%eax),        %%xmm4\n"               // m[0][0]                      | m[0][1]               | -                     | -
  78.157 +        "movhps         16(%%eax),      %%xmm4\n"               // m[0][0]                      | m[0][1]               | m[1][0]               | m[1][1]
  78.158 +
  78.159 +        "movlps         32(%%eax),      %%xmm3\n"               // m[2][0]                      | m[2][1]               | -                     | -
  78.160 +        "movhps         48(%%eax),      %%xmm3\n"               // m[2][0]                      | m[2][1]               | m[3][0]               | m[3][1]
  78.161 +
  78.162 +        "movups         %%xmm4,         %%xmm5\n"               // m[0][0]                      | m[0][1]               | m[1][0]               | m[1][1]
  78.163 +
  78.164 +        // 0x88 = 10 00 | 10 00 <-> 00 10 | 00 10          xmm4[00]                       xmm4[10]                xmm3[00]                xmm3[10]
  78.165 +        "shufps         $0x88, %%xmm3,  %%xmm4\n"       // m[0][0]                      | m[1][0]               | m[2][0]               | m[3][0]
  78.166 +
  78.167 +        // 0xDD = 11 01 | 11 01 <-> 01 11 | 01 11          xmm5[01]                       xmm5[11]                xmm3[01]                xmm3[11]
  78.168 +        "shufps         $0xDD, %%xmm3,  %%xmm5\n"       // m[0][1]                      | m[1][1]               | m[2][1]               | m[3][1]
  78.169 +
  78.170 +        "movlps         8(%%eax),       %%xmm6\n"               // m[0][2]                      | m[0][3]               | -                     | -
  78.171 +        "movhps         24(%%eax),      %%xmm6\n"               // m[0][2]                      | m[0][3]               | m[1][2]               | m[1][3]
  78.172 +
  78.173 +        "movlps         40(%%eax),      %%xmm3\n"               // m[2][2]                      | m[2][3]               | -                     | -
  78.174 +        "movhps         56(%%eax),      %%xmm3\n"               // m[2][2]                      | m[2][3]               | m[3][2]               | m[3][3]
  78.175 +
  78.176 +        "movups         %%xmm6,         %%xmm7\n"               // m[0][2]                      | m[0][3]               | m[1][2]               | m[1][3]
  78.177 +
  78.178 +        // 0x88 = 10 00 | 10 00 <-> 00 10 | 00 10          xmm6[00]                       xmm6[10]                xmm3[00]                xmm3[10]
  78.179 +        "shufps         $0x88, %%xmm3,  %%xmm6\n"       // m[0][2]                      | m[1][2]               | m[2][2]               | m[3][2]
  78.180 +
  78.181 +        // 0xDD = 11 01 | 11 01 <-> 01 11 | 01 11          xmm7[01]                       xmm7[11]                xmm3[01]                xmm3[11]
  78.182 +        "shufps         $0xDD, %%xmm3,  %%xmm7\n"       // m[0][3]                      | m[1][3]               | m[2][3]               | m[3][3]
  78.183 +	:
  78.184 +	: "a"( m )
  78.185 +	: "memory"
  78.186 +		);
  78.187 +#endif
  78.188 +}
  78.189 +
  78.190 +void MatrixTranspose(const matrix_t in, matrix_t out)
  78.191 +{
  78.192 +#if id386_sse && defined __GNUC__ && 0
  78.193 +        // transpose the matrix into the xmm4-7
  78.194 +        MatrixTransposeIntoXMM(in);
  78.195 +
  78.196 +        asm volatile
  78.197 +				(
  78.198 +				"movups         %%xmm4,         (%%eax)\n"
  78.199 +				"movups         %%xmm5,         0x10(%%eax)\n"
  78.200 +				"movups         %%xmm6,         0x20(%%eax)\n"
  78.201 +				"movups         %%xmm7,         0x30(%%eax)\n"
  78.202 +	:
  78.203 +	: "a"( out )
  78.204 +	: "memory"
  78.205 +				);
  78.206 +#else
  78.207 +	out[ 0] = in[ 0];       out[ 1] = in[ 4];       out[ 2] = in[ 8];       out[ 3] = in[12];
  78.208 +	out[ 4] = in[ 1];       out[ 5] = in[ 5];       out[ 6] = in[ 9];       out[ 7] = in[13];
  78.209 +	out[ 8] = in[ 2];       out[ 9] = in[ 6];       out[10] = in[10];       out[11] = in[14];
  78.210 +	out[12] = in[ 3];       out[13] = in[ 7];       out[14] = in[11];       out[15] = in[15];
  78.211 +#endif
  78.212 +}
  78.213 +
  78.214 +
  78.215 +// helper functions for MatrixInverse from GtkRadiant C mathlib
  78.216 +static float m3_det( matrix3x3_t mat )
  78.217 +{
  78.218 +  float det;
  78.219 +
  78.220 +  det = mat[0] * ( mat[4]*mat[8] - mat[7]*mat[5] )
  78.221 +    - mat[1] * ( mat[3]*mat[8] - mat[6]*mat[5] )
  78.222 +    + mat[2] * ( mat[3]*mat[7] - mat[6]*mat[4] );
  78.223 +
  78.224 +  return( det );
  78.225 +}
  78.226 +
  78.227 +static int m3_inverse( matrix3x3_t mr, matrix3x3_t ma )
  78.228 +{
  78.229 +  float det = m3_det( ma );
  78.230 +
  78.231 +  if (det == 0 )
  78.232 +  {
  78.233 +    return 1;
  78.234 +  }
  78.235 +
  78.236 +
  78.237 +  mr[0] =    ma[4]*ma[8] - ma[5]*ma[7]   / det;
  78.238 +  mr[1] = -( ma[1]*ma[8] - ma[7]*ma[2] ) / det;
  78.239 +  mr[2] =    ma[1]*ma[5] - ma[4]*ma[2]   / det;
  78.240 +
  78.241 +  mr[3] = -( ma[3]*ma[8] - ma[5]*ma[6] ) / det;
  78.242 +  mr[4] =    ma[0]*ma[8] - ma[6]*ma[2]   / det;
  78.243 +  mr[5] = -( ma[0]*ma[5] - ma[3]*ma[2] ) / det;
  78.244 +
  78.245 +  mr[6] =    ma[3]*ma[7] - ma[6]*ma[4]   / det;
  78.246 +  mr[7] = -( ma[0]*ma[7] - ma[6]*ma[1] ) / det;
  78.247 +  mr[8] =    ma[0]*ma[4] - ma[1]*ma[3]   / det;
  78.248 +
  78.249 +  return 0;
  78.250 +}
  78.251 +
  78.252 +static void m4_submat( matrix_t mr, matrix3x3_t mb, int i, int j )
  78.253 +{
  78.254 +  int ti, tj, idst = 0, jdst = 0;
  78.255 +
  78.256 +  for ( ti = 0; ti < 4; ti++ )
  78.257 +  {
  78.258 +    if ( ti < i )
  78.259 +      idst = ti;
  78.260 +    else
  78.261 +      if ( ti > i )
  78.262 +        idst = ti-1;
  78.263 +
  78.264 +      for ( tj = 0; tj < 4; tj++ )
  78.265 +      {
  78.266 +        if ( tj < j )
  78.267 +          jdst = tj;
  78.268 +        else
  78.269 +          if ( tj > j )
  78.270 +            jdst = tj-1;
  78.271 +
  78.272 +          if ( ti != i && tj != j )
  78.273 +            mb[idst*3 + jdst] = mr[ti*4 + tj ];
  78.274 +      }
  78.275 +  }
  78.276 +}
  78.277 +
  78.278 +static float m4_det( matrix_t mr )
  78.279 +{
  78.280 +  float  det, result = 0, i = 1;
  78.281 +  matrix3x3_t msub3;
  78.282 +  int     n;
  78.283 +
  78.284 +  for ( n = 0; n < 4; n++, i *= -1 )
  78.285 +  {
  78.286 +    m4_submat( mr, msub3, 0, n );
  78.287 +
  78.288 +    det     = m3_det( msub3 );
  78.289 +    result += mr[n] * det * i;
  78.290 +  }
  78.291 +
  78.292 +  return result;
  78.293 +}
  78.294 +
  78.295 +qboolean MatrixInverse(matrix_t matrix)
  78.296 +{
  78.297 +  float  mdet = m4_det(matrix);
  78.298 +  matrix3x3_t mtemp;
  78.299 +  int     i, j, sign;
  78.300 +  matrix_t m4x4_temp;
  78.301 +
  78.302 +#if 0
  78.303 +  if ( fabs( mdet ) < 0.0000000001 )
  78.304 +    return qtrue;
  78.305 +#endif
  78.306 +
  78.307 +  MatrixCopy(matrix, m4x4_temp);
  78.308 +
  78.309 +  for ( i = 0; i < 4; i++ )
  78.310 +    for ( j = 0; j < 4; j++ )
  78.311 +    {
  78.312 +      sign = 1 - ( (i +j) % 2 ) * 2;
  78.313 +
  78.314 +      m4_submat( m4x4_temp, mtemp, i, j );
  78.315 +
  78.316 +	  // FIXME: try using * inverse det and see if speed/accuracy are good enough
  78.317 +      matrix[i+j*4] = ( m3_det( mtemp ) * sign ) / mdet;
  78.318 +    }
  78.319 +
  78.320 +  return qfalse;
  78.321 +}
  78.322 +
  78.323 +void MatrixSetupXRotation(matrix_t m, vec_t degrees)
  78.324 +{
  78.325 +	vec_t a = DEG2RAD(degrees);
  78.326 +
  78.327 +	m[ 0] = 1;      m[ 4] = 0;              m[ 8] = 0;              m[12] = 0;
  78.328 +	m[ 1] = 0;      m[ 5] = cos(a);         m[ 9] =-sin(a);         m[13] = 0;
  78.329 +	m[ 2] = 0;      m[ 6] = sin(a);         m[10] = cos(a);         m[14] = 0;
  78.330 +	m[ 3] = 0;      m[ 7] = 0;              m[11] = 0;              m[15] = 1;
  78.331 +}
  78.332 +
  78.333 +void MatrixSetupYRotation(matrix_t m, vec_t degrees)
  78.334 +{
  78.335 +	vec_t a = DEG2RAD(degrees);
  78.336 +
  78.337 +	m[ 0] = cos(a);         m[ 4] = 0;      m[ 8] = sin(a);         m[12] = 0;
  78.338 +	m[ 1] = 0;              m[ 5] = 1;      m[ 9] = 0;              m[13] = 0;
  78.339 +	m[ 2] =-sin(a);         m[ 6] = 0;      m[10] = cos(a);         m[14] = 0;
  78.340 +	m[ 3] = 0;              m[ 7] = 0;      m[11] = 0;              m[15] = 1;
  78.341 +}
  78.342 +
  78.343 +void MatrixSetupZRotation(matrix_t m, vec_t degrees)
  78.344 +{
  78.345 +	vec_t a = DEG2RAD(degrees);
  78.346 +
  78.347 +	m[ 0] = cos(a);         m[ 4] =-sin(a);         m[ 8] = 0;      m[12] = 0;
  78.348 +	m[ 1] = sin(a);         m[ 5] = cos(a);         m[ 9] = 0;      m[13] = 0;
  78.349 +	m[ 2] = 0;              m[ 6] = 0;              m[10] = 1;      m[14] = 0;
  78.350 +	m[ 3] = 0;              m[ 7] = 0;              m[11] = 0;      m[15] = 1;
  78.351 +}
  78.352 +
  78.353 +void MatrixSetupTranslation(matrix_t m, vec_t x, vec_t y, vec_t z)
  78.354 +{
  78.355 +	m[ 0] = 1;      m[ 4] = 0;      m[ 8] = 0;      m[12] = x;
  78.356 +	m[ 1] = 0;      m[ 5] = 1;      m[ 9] = 0;      m[13] = y;
  78.357 +	m[ 2] = 0;      m[ 6] = 0;      m[10] = 1;      m[14] = z;
  78.358 +	m[ 3] = 0;      m[ 7] = 0;      m[11] = 0;      m[15] = 1;
  78.359 +}
  78.360 +
  78.361 +void MatrixSetupScale(matrix_t m, vec_t x, vec_t y, vec_t z)
  78.362 +{
  78.363 +	m[ 0] = x;      m[ 4] = 0;      m[ 8] = 0;      m[12] = 0;
  78.364 +	m[ 1] = 0;      m[ 5] = y;      m[ 9] = 0;      m[13] = 0;
  78.365 +	m[ 2] = 0;      m[ 6] = 0;      m[10] = z;      m[14] = 0;
  78.366 +	m[ 3] = 0;      m[ 7] = 0;      m[11] = 0;      m[15] = 1;
  78.367 +}
  78.368 +
  78.369 +void MatrixSetupShear(matrix_t m, vec_t x, vec_t y)
  78.370 +{
  78.371 +	m[ 0] = 1;      m[ 4] = x;      m[ 8] = 0;      m[12] = 0;
  78.372 +	m[ 1] = y;      m[ 5] = 1;      m[ 9] = 0;      m[13] = 0;
  78.373 +	m[ 2] = 0;      m[ 6] = 0;      m[10] = 1;      m[14] = 0;
  78.374 +	m[ 3] = 0;      m[ 7] = 0;      m[11] = 0;      m[15] = 1;
  78.375 +}
  78.376 +
  78.377 +void MatrixMultiply2(matrix_t m, const matrix_t m2)
  78.378 +{
  78.379 +	matrix_t        tmp;
  78.380 +
  78.381 +	MatrixCopy(m, tmp);
  78.382 +	MatrixMultiply(tmp, m2, m);
  78.383 +}
  78.384 +
  78.385 +void MatrixMultiplyRotation(matrix_t m, vec_t pitch, vec_t yaw, vec_t roll)
  78.386 +{
  78.387 +	matrix_t        tmp, rot;
  78.388 +
  78.389 +	MatrixCopy(m, tmp);
  78.390 +	MatrixFromAngles(rot, pitch, yaw, roll);
  78.391 +
  78.392 +	MatrixMultiply(tmp, rot, m);
  78.393 +}
  78.394 +
  78.395 +void MatrixMultiplyZRotation(matrix_t m, vec_t degrees)
  78.396 +{
  78.397 +	matrix_t        tmp, rot;
  78.398 +
  78.399 +	MatrixCopy(m, tmp);
  78.400 +	MatrixSetupZRotation(rot, degrees);
  78.401 +
  78.402 +	MatrixMultiply(tmp, rot, m);
  78.403 +}
  78.404 +
  78.405 +void MatrixMultiplyTranslation(matrix_t m, vec_t x, vec_t y, vec_t z)
  78.406 +{
  78.407 +#if 1
  78.408 +	matrix_t        tmp, trans;
  78.409 +
  78.410 +	MatrixCopy(m, tmp);
  78.411 +	MatrixSetupTranslation(trans, x, y, z);
  78.412 +	MatrixMultiply(tmp, trans, m);
  78.413 +#else
  78.414 +	m[12] += m[ 0] * x + m[ 4] * y + m[ 8] * z;
  78.415 +	m[13] += m[ 1] * x + m[ 5] * y + m[ 9] * z;
  78.416 +	m[14] += m[ 2] * x + m[ 6] * y + m[10] * z;
  78.417 +	m[15] += m[ 3] * x + m[ 7] * y + m[11] * z;
  78.418 +#endif
  78.419 +}
  78.420 +
  78.421 +void MatrixMultiplyScale(matrix_t m, vec_t x, vec_t y, vec_t z)
  78.422 +{
  78.423 +#if 0
  78.424 +	matrix_t        tmp, scale;
  78.425 +
  78.426 +	MatrixCopy(m, tmp);
  78.427 +	MatrixSetupScale(scale, x, y, z);
  78.428 +	MatrixMultiply(tmp, scale, m);
  78.429 +#else
  78.430 +	m[ 0] *= x;     m[ 4] *= y;        m[ 8] *= z;
  78.431 +	m[ 1] *= x;     m[ 5] *= y;        m[ 9] *= z;
  78.432 +	m[ 2] *= x;     m[ 6] *= y;        m[10] *= z;
  78.433 +	m[ 3] *= x;     m[ 7] *= y;        m[11] *= z;
  78.434 +#endif
  78.435 +}
  78.436 +
  78.437 +void MatrixMultiplyShear(matrix_t m, vec_t x, vec_t y)
  78.438 +{
  78.439 +	matrix_t        tmp, shear;
  78.440 +
  78.441 +	MatrixCopy(m, tmp);
  78.442 +	MatrixSetupShear(shear, x, y);
  78.443 +	MatrixMultiply(tmp, shear, m);
  78.444 +}
  78.445 +
  78.446 +void MatrixToAngles(const matrix_t m, vec3_t angles)
  78.447 +{
  78.448 +#if 1
  78.449 +	double          theta;
  78.450 +	double          cp;
  78.451 +	double          sp;
  78.452 +
  78.453 +	sp = m[2];
  78.454 +
  78.455 +	// cap off our sin value so that we don't get any NANs
  78.456 +	if(sp > 1.0)
  78.457 +	{
  78.458 +		sp = 1.0;
  78.459 +	}
  78.460 +	else if(sp < -1.0)
  78.461 +	{
  78.462 +		sp = -1.0;
  78.463 +	}
  78.464 +
  78.465 +	theta = -asin(sp);
  78.466 +	cp = cos(theta);
  78.467 +
  78.468 +	if(cp > 8192 * FLT_EPSILON)
  78.469 +	{
  78.470 +		angles[PITCH] = RAD2DEG(theta);
  78.471 +		angles[YAW] = RAD2DEG(atan2(m[1], m[0]));
  78.472 +		angles[ROLL] = RAD2DEG(atan2(m[6], m[10]));
  78.473 +	}
  78.474 +	else
  78.475 +	{
  78.476 +		angles[PITCH] = RAD2DEG(theta);
  78.477 +		angles[YAW] = RAD2DEG(-atan2(m[4], m[5]));
  78.478 +		angles[ROLL] = 0;
  78.479 +	}
  78.480 +#else
  78.481 +	double          a;
  78.482 +	double          ca;
  78.483 +
  78.484 +	a = asin(-m[2]);
  78.485 +	ca = cos(a);
  78.486 +
  78.487 +	if(fabs(ca) > 0.005)		// Gimbal lock?
  78.488 +	{
  78.489 +		angles[PITCH] = RAD2DEG(atan2(m[6] / ca, m[10] / ca));
  78.490 +		angles[YAW] = RAD2DEG(a);
  78.491 +		angles[ROLL] = RAD2DEG(atan2(m[1] / ca, m[0] / ca));
  78.492 +	}
  78.493 +	else
  78.494 +	{
  78.495 +		// Gimbal lock has occurred
  78.496 +		angles[PITCH] = RAD2DEG(atan2(-m[9], m[5]));
  78.497 +		angles[YAW] = RAD2DEG(a);
  78.498 +		angles[ROLL] = 0;
  78.499 +	}
  78.500 +#endif
  78.501 +}
  78.502 +
  78.503 +
  78.504 +void MatrixFromAngles(matrix_t m, vec_t pitch, vec_t yaw, vec_t roll)
  78.505 +{
  78.506 +	static float    sr, sp, sy, cr, cp, cy;
  78.507 +
  78.508 +    // static to help MS compiler fp bugs
  78.509 +	sp = sin(DEG2RAD(pitch));
  78.510 +	cp = cos(DEG2RAD(pitch));
  78.511 +
  78.512 +	sy = sin(DEG2RAD(yaw));
  78.513 +	cy = cos(DEG2RAD(yaw));
  78.514 +
  78.515 +	sr = sin(DEG2RAD(roll));
  78.516 +	cr = cos(DEG2RAD(roll));
  78.517 +
  78.518 +	m[ 0] = cp*cy;  m[ 4] = (sr*sp*cy+cr*-sy);      m[ 8] = (cr*sp*cy+-sr*-sy);     m[12] = 0;
  78.519 +	m[ 1] = cp*sy;  m[ 5] = (sr*sp*sy+cr*cy);       m[ 9] = (cr*sp*sy+-sr*cy);      m[13] = 0;
  78.520 +	m[ 2] = -sp;    m[ 6] = sr*cp;                  m[10] = cr*cp;                  m[14] = 0;
  78.521 +	m[ 3] = 0;      m[ 7] = 0;                      m[11] = 0;                      m[15] = 1;
  78.522 +}
  78.523 +
  78.524 +void MatrixFromVectorsFLU(matrix_t m, const vec3_t forward, const vec3_t left, const vec3_t up)
  78.525 +{
  78.526 +    m[ 0] = forward[0];     m[ 4] = left[0];        m[ 8] = up[0];  m[12] = 0;
  78.527 +	m[ 1] = forward[1];     m[ 5] = left[1];        m[ 9] = up[1];  m[13] = 0;
  78.528 +	m[ 2] = forward[2];     m[ 6] = left[2];        m[10] = up[2];  m[14] = 0;
  78.529 +	m[ 3] = 0;              m[ 7] = 0;              m[11] = 0;      m[15] = 1;
  78.530 +}
  78.531 +
  78.532 +void MatrixFromVectorsFRU(matrix_t m, const vec3_t forward, const vec3_t right, const vec3_t up)
  78.533 +{
  78.534 +    m[ 0] = forward[0];     m[ 4] =-right[0];       m[ 8] = up[0];  m[12] = 0;
  78.535 +	m[ 1] = forward[1];     m[ 5] =-right[1];       m[ 9] = up[1];  m[13] = 0;
  78.536 +	m[ 2] = forward[2];     m[ 6] =-right[2];       m[10] = up[2];  m[14] = 0;
  78.537 +	m[ 3] = 0;              m[ 7] = 0;              m[11] = 0;      m[15] = 1;
  78.538 +}
  78.539 +
  78.540 +void MatrixFromQuat(matrix_t m, const quat_t q)
  78.541 +{
  78.542 +#if 1
  78.543 +	/*
  78.544 +	From Quaternion to Matrix and Back
  78.545 +	February 27th 2005
  78.546 +	J.M.P. van Waveren
  78.547 +
  78.548 +	http://www.intel.com/cd/ids/developer/asmo-na/eng/293748.htm
  78.549 +	*/
  78.550 +	float			x2, y2, z2, w2;
  78.551 +	float			yy2, xy2;
  78.552 +	float			xz2, yz2, zz2;
  78.553 +	float			wz2, wy2, wx2, xx2;
  78.554 +
  78.555 +	x2 = q[0] + q[0];
  78.556 +	y2 = q[1] + q[1];
  78.557 +	z2 = q[2] + q[2];
  78.558 +	w2 = q[3] + q[3];
  78.559 +
  78.560 +	yy2 = q[1] * y2;
  78.561 +	xy2 = q[0] * y2;
  78.562 +
  78.563 +	xz2 = q[0] * z2;
  78.564 +	yz2 = q[1] * z2;
  78.565 +	zz2 = q[2] * z2;
  78.566 +
  78.567 +	wz2 = q[3] * z2;
  78.568 +	wy2 = q[3] * y2;
  78.569 +	wx2 = q[3] * x2;
  78.570 +	xx2 = q[0] * x2;
  78.571 +
  78.572 +	m[ 0] = - yy2 - zz2 + 1.0f;
  78.573 +	m[ 1] =   xy2 + wz2;
  78.574 +	m[ 2] =   xz2 - wy2;
  78.575 +
  78.576 +	m[ 4] =   xy2 - wz2;
  78.577 +	m[ 5] = - xx2 - zz2 + 1.0f;
  78.578 +	m[ 6] =   yz2 + wx2;
  78.579 +
  78.580 +	m[ 8] =   xz2 + wy2;
  78.581 +	m[ 9] =   yz2 - wx2;
  78.582 +	m[10] = - xx2 - yy2 + 1.0f;
  78.583 +
  78.584 +	m[ 3] = m[ 7] = m[11] = m[12] = m[13] = m[14] = 0;
  78.585 +    m[15] = 1;
  78.586 +
  78.587 +#else
  78.588 +	/*
  78.589 +	http://www.gamedev.net/reference/articles/article1691.asp#Q54
  78.590 +	Q54. How do I convert a quaternion to a rotation matrix?
  78.591 +
  78.592 +	Assuming that a quaternion has been created in the form:
  78.593 +
  78.594 +    Q = |X Y Z W|
  78.595 +
  78.596 +    Then the quaternion can then be converted into a 4x4 rotation
  78.597 +    matrix using the following expression (Warning: you might have to
  78.598 +    transpose this matrix if you (do not) follow the OpenGL order!):
  78.599 +
  78.600 +         ?        2     2                                      ?
  78.601 +         ? 1 - (2Y  + 2Z )   2XY - 2ZW         2XZ + 2YW       ?
  78.602 +         ?                                                     ?
  78.603 +         ?                          2     2                    ?
  78.604 +     M = ? 2XY + 2ZW         1 - (2X  + 2Z )   2YZ - 2XW       ?
  78.605 +         ?                                                     ?
  78.606 +         ?                                            2     2  ?
  78.607 +         ? 2XZ - 2YW         2YZ + 2XW         1 - (2X  + 2Y ) ?
  78.608 +         ?                                                     ?
  78.609 +	*/
  78.610 +
  78.611 +	// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm
  78.612 +
  78.613 +	float			xx, xy, xz, xw, yy, yz, yw, zz, zw;
  78.614 +
  78.615 +	xx = q[0] * q[0];
  78.616 +    xy = q[0] * q[1];
  78.617 +    xz = q[0] * q[2];
  78.618 +    xw = q[0] * q[3];
  78.619 +    yy = q[1] * q[1];
  78.620 +    yz = q[1] * q[2];
  78.621 +    yw = q[1] * q[3];
  78.622 +    zz = q[2] * q[2];
  78.623 +    zw = q[2] * q[3];
  78.624 +
  78.625 +    m[ 0] = 1 - 2 * ( yy + zz );
  78.626 +    m[ 1] =     2 * ( xy + zw );
  78.627 +    m[ 2] =     2 * ( xz - yw );
  78.628 +    m[ 4] =     2 * ( xy - zw );
  78.629 +    m[ 5] = 1 - 2 * ( xx + zz );
  78.630 +    m[ 6] =     2 * ( yz + xw );
  78.631 +    m[ 8] =     2 * ( xz + yw );
  78.632 +    m[ 9] =     2 * ( yz - xw );
  78.633 +    m[10] = 1 - 2 * ( xx + yy );
  78.634 +
  78.635 +    m[ 3] = m[ 7] = m[11] = m[12] = m[13] = m[14] = 0;
  78.636 +    m[15] = 1;
  78.637 +#endif
  78.638 +}
  78.639 +
  78.640 +void MatrixFromPlanes(matrix_t m, const vec4_t left, const vec4_t right, const vec4_t bottom, const vec4_t top, const vec4_t front, const vec4_t back)
  78.641 +{
  78.642 +	m[ 0] = (right[0] - left[0]) / 2;
  78.643 +	m[ 1] = (top[0] - bottom[0]) / 2;
  78.644 +	m[ 2] = (back[0] - front[0]) / 2;
  78.645 +	m[ 3] = right[0] - (right[0] - left[0]) / 2;
  78.646 +	m[ 4] = (right[1] - left[1]) / 2;
  78.647 +	m[ 5] = (top[1] - bottom[1]) / 2;
  78.648 +	m[ 6] = (back[1] - front[1]) / 2;
  78.649 +	m[ 7] = right[1] - (right[1] - left[1]) / 2;
  78.650 +	m[ 8] = (right[1] - left[1]) / 2;
  78.651 +	m[ 9] = (top[1] - bottom[1]) / 2;
  78.652 +	m[10] = (back[1] - front[1]) / 2;
  78.653 +	m[11] = right[1] - (right[1] - left[1]) / 2;
  78.654 +	m[12] = (right[1] - left[1]) / 2;
  78.655 +	m[13] = (top[1] - bottom[1]) / 2;
  78.656 +	m[14] = (back[1] - front[1]) / 2;
  78.657 +	m[15] = right[1] - (right[1] - left[1]) / 2;
  78.658 +}
  78.659 +
  78.660 +void MatrixToVectorsFLU(const matrix_t m, vec3_t forward, vec3_t left, vec3_t up)
  78.661 +{
  78.662 +	if(forward)
  78.663 +	{
  78.664 +		forward[0] = m[ 0];     // cp*cy;
  78.665 +		forward[1] = m[ 1];     // cp*sy;
  78.666 +		forward[2] = m[ 2];     //-sp;
  78.667 +	}
  78.668 +
  78.669 +    if(left)
  78.670 +    {
  78.671 +		left[0] = m[ 4];        // sr*sp*cy+cr*-sy;
  78.672 +		left[1] = m[ 5];        // sr*sp*sy+cr*cy;
  78.673 +		left[2] = m[ 6];        // sr*cp;
  78.674 +    }
  78.675 +
  78.676 +	if(up)
  78.677 +	{
  78.678 +		up[0] = m[ 8];  // cr*sp*cy+-sr*-sy;
  78.679 +		up[1] = m[ 9];  // cr*sp*sy+-sr*cy;
  78.680 +		up[2] = m[10];  // cr*cp;
  78.681 +	}
  78.682 +}
  78.683 +
  78.684 +void MatrixToVectorsFRU(const matrix_t m, vec3_t forward, vec3_t right, vec3_t up)
  78.685 +{
  78.686 +	if(forward)
  78.687 +	{
  78.688 +		forward[0] = m[ 0];
  78.689 +		forward[1] = m[ 1];
  78.690 +		forward[2] = m[ 2];
  78.691 +	}
  78.692 +
  78.693 +	if(right)
  78.694 +	{
  78.695 +		right[0] =-m[ 4];
  78.696 +		right[1] =-m[ 5];
  78.697 +		right[2] =-m[ 6];
  78.698 +	}
  78.699 +
  78.700 +	if(up)
  78.701 +	{
  78.702 +		up[0] = m[ 8];
  78.703 +		up[1] = m[ 9];
  78.704 +		up[2] = m[10];
  78.705 +	}
  78.706 +}
  78.707 +
  78.708 +void MatrixSetupTransform(matrix_t m, const vec3_t forward, const vec3_t left, const vec3_t up, const vec3_t origin)
  78.709 +{
  78.710 +	m[ 0] = forward[0];     m[ 4] = left[0];        m[ 8] = up[0];  m[12] = origin[0];
  78.711 +	m[ 1] = forward[1];     m[ 5] = left[1];        m[ 9] = up[1];  m[13] = origin[1];
  78.712 +	m[ 2] = forward[2];     m[ 6] = left[2];        m[10] = up[2];  m[14] = origin[2];
  78.713 +	m[ 3] = 0;              m[ 7] = 0;              m[11] = 0;      m[15] = 1;
  78.714 +}
  78.715 +
  78.716 +void MatrixSetupTransformFromRotation(matrix_t m, const matrix_t rot, const vec3_t origin)
  78.717 +{
  78.718 +	m[ 0] = rot[ 0];     m[ 4] = rot[ 4];        m[ 8] = rot[ 8];  m[12] = origin[0];
  78.719 +	m[ 1] = rot[ 1];     m[ 5] = rot[ 5];        m[ 9] = rot[ 9];  m[13] = origin[1];
  78.720 +	m[ 2] = rot[ 2];     m[ 6] = rot[ 6];        m[10] = rot[10];  m[14] = origin[2];
  78.721 +	m[ 3] = 0;           m[ 7] = 0;              m[11] = 0;        m[15] = 1;
  78.722 +}
  78.723 +
  78.724 +void MatrixSetupTransformFromQuat(matrix_t m, const quat_t quat, const vec3_t origin)
  78.725 +{
  78.726 +	matrix_t        rot;
  78.727 +
  78.728 +	MatrixFromQuat(rot, quat);
  78.729 +
  78.730 +	m[ 0] = rot[ 0];     m[ 4] = rot[ 4];        m[ 8] = rot[ 8];  m[12] = origin[0];
  78.731 +	m[ 1] = rot[ 1];     m[ 5] = rot[ 5];        m[ 9] = rot[ 9];  m[13] = origin[1];
  78.732 +	m[ 2] = rot[ 2];     m[ 6] = rot[ 6];        m[10] = rot[10];  m[14] = origin[2];
  78.733 +	m[ 3] = 0;           m[ 7] = 0;              m[11] = 0;        m[15] = 1;
  78.734 +}
  78.735 +
  78.736 +void MatrixAffineInverse(const matrix_t in, matrix_t out)
  78.737 +{
  78.738 +#if 0
  78.739 +		MatrixCopy(in, out);
  78.740 +		MatrixInverse(out);
  78.741 +#else
  78.742 +        // Tr3B - cleaned up
  78.743 +        out[ 0] = in[ 0];       out[ 4] = in[ 1];       out[ 8] = in[ 2];
  78.744 +        out[ 1] = in[ 4];       out[ 5] = in[ 5];       out[ 9] = in[ 6];
  78.745 +		out[ 2] = in[ 8];       out[ 6] = in[ 9];       out[10] = in[10];
  78.746 +		out[ 3] = 0;            out[ 7] = 0;            out[11] = 0;            out[15] = 1;
  78.747 +
  78.748 +		out[12] = -( in[12] * out[ 0] + in[13] * out[ 4] + in[14] * out[ 8] );
  78.749 +		out[13] = -( in[12] * out[ 1] + in[13] * out[ 5] + in[14] * out[ 9] );
  78.750 +		out[14] = -( in[12] * out[ 2] + in[13] * out[ 6] + in[14] * out[10] );
  78.751 +#endif
  78.752 +}
  78.753 +
  78.754 +void MatrixTransformNormal(const matrix_t m, const vec3_t in, vec3_t out)
  78.755 +{
  78.756 +	out[ 0] = m[ 0] * in[ 0] + m[ 4] * in[ 1] + m[ 8] * in[ 2];
  78.757 +	out[ 1] = m[ 1] * in[ 0] + m[ 5] * in[ 1] + m[ 9] * in[ 2];
  78.758 +	out[ 2] = m[ 2] * in[ 0] + m[ 6] * in[ 1] + m[10] * in[ 2];
  78.759 +}
  78.760 +
  78.761 +void MatrixTransformNormal2(const matrix_t m, vec3_t inout)
  78.762 +{
  78.763 +	vec3_t          tmp;
  78.764 +
  78.765 +	tmp[ 0] = m[ 0] * inout[ 0] + m[ 4] * inout[ 1] + m[ 8] * inout[ 2];
  78.766 +	tmp[ 1] = m[ 1] * inout[ 0] + m[ 5] * inout[ 1] + m[ 9] * inout[ 2];
  78.767 +	tmp[ 2] = m[ 2] * inout[ 0] + m[ 6] * inout[ 1] + m[10] * inout[ 2];
  78.768 +
  78.769 +	VectorCopy(tmp, inout);
  78.770 +}
  78.771 +
  78.772 +void MatrixTransformPoint(const matrix_t m, const vec3_t in, vec3_t out)
  78.773 +{
  78.774 +	out[ 0] = m[ 0] * in[ 0] + m[ 4] * in[ 1] + m[ 8] * in[ 2] + m[12];
  78.775 +	out[ 1] = m[ 1] * in[ 0] + m[ 5] * in[ 1] + m[ 9] * in[ 2] + m[13];
  78.776 +	out[ 2] = m[ 2] * in[ 0] + m[ 6] * in[ 1] + m[10] * in[ 2] + m[14];
  78.777 +}
  78.778 +
  78.779 +void MatrixTransformPoint2(const matrix_t m, vec3_t inout)
  78.780 +{
  78.781 +	vec3_t          tmp;
  78.782 +
  78.783 +	tmp[ 0] = m[ 0] * inout[ 0] + m[ 4] * inout[ 1] + m[ 8] * inout[ 2] + m[12];
  78.784 +	tmp[ 1] = m[ 1] * inout[ 0] + m[ 5] * inout[ 1] + m[ 9] * inout[ 2] + m[13];
  78.785 +	tmp[ 2] = m[ 2] * inout[ 0] + m[ 6] * inout[ 1] + m[10] * inout[ 2] + m[14];
  78.786 +
  78.787 +	VectorCopy(tmp, inout);
  78.788 +}
  78.789 +
  78.790 +void MatrixTransform4(const matrix_t m, const vec4_t in, vec4_t out)
  78.791 +{
  78.792 +#if id386_sse
  78.793 +//#error MatrixTransform4
  78.794 +
  78.795 +	__m128			_t0, _t1, _t2, _x, _y, _z, _w, _m0, _m1, _m2, _m3;
  78.796 +
  78.797 +	_m0 = _mm_loadu_ps(&m[0]);
  78.798 +	_m1 = _mm_loadu_ps(&m[4]);
  78.799 +	_m2 = _mm_loadu_ps(&m[8]);
  78.800 +	_m3 = _mm_loadu_ps(&m[12]);
  78.801 +
  78.802 +	_t0 = _mm_loadu_ps(in);
  78.803 +	_x = _mm_shuffle_ps(_t0, _t0, _MM_SHUFFLE(0, 0, 0, 0));
  78.804 +	_y = _mm_shuffle_ps(_t0, _t0, _MM_SHUFFLE(1, 1, 1, 1));
  78.805 +	_z = _mm_shuffle_ps(_t0, _t0, _MM_SHUFFLE(2, 2, 2, 2));
  78.806 +	_w = _mm_shuffle_ps(_t0, _t0, _MM_SHUFFLE(3, 3, 3, 3));
  78.807 +
  78.808 +	_t0 = _mm_mul_ps(_m3, _w);
  78.809 +	_t1 = _mm_mul_ps(_m2, _z);
  78.810 +	_t0 = _mm_add_ps(_t0, _t1);
  78.811 +
  78.812 +	_t1 = _mm_mul_ps(_m1, _y);
  78.813 +	_t2 = _mm_mul_ps(_m0, _x);
  78.814 +	_t1 = _mm_add_ps(_t1, _t2);
  78.815 +
  78.816 +	_t0 = _mm_add_ps(_t0, _t1);
  78.817 +
  78.818 +	_mm_storeu_ps(out, _t0);
  78.819 +#else
  78.820 +	out[ 0] = m[ 0] * in[ 0] + m[ 4] * in[ 1] + m[ 8] * in[ 2] + m[12] * in[ 3];
  78.821 +	out[ 1] = m[ 1] * in[ 0] + m[ 5] * in[ 1] + m[ 9] * in[ 2] + m[13] * in[ 3];
  78.822 +	out[ 2] = m[ 2] * in[ 0] + m[ 6] * in[ 1] + m[10] * in[ 2] + m[14] * in[ 3];
  78.823 +	out[ 3] = m[ 3] * in[ 0] + m[ 7] * in[ 1] + m[11] * in[ 2] + m[15] * in[ 3];
  78.824 +#endif
  78.825 +}
  78.826 +
  78.827 +
  78.828 +/*
  78.829 +replacement for glFrustum
  78.830 +see glspec30.pdf chapter 2.12 Coordinate Transformations
  78.831 +*/
  78.832 +void MatrixSetupPerspectiveProjection(matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near, vec_t far)
  78.833 +{
  78.834 +	m[0] = (2 * near) / (right - left);	m[4] = 0;							m[8] = (right + left) / (right - left);		m[12] = 0;
  78.835 +	m[1] = 0;							m[5] = (2 * near) / (top - bottom);	m[9] = (top + bottom) / (top - bottom);		m[13] = 0;
  78.836 +	m[2] = 0;							m[6] = 0;							m[10] = -(far + near) / (far - near);		m[14] = (-2 * far * near) / (far - near);
  78.837 +	m[3] = 0;							m[7] = 0;							m[11] = -1;									m[15] = 0;
  78.838 +}
  78.839 +
  78.840 +/*
  78.841 +replacement for glOrtho
  78.842 +see glspec30.pdf chapter 2.12 Coordinate Transformations
  78.843 +*/
  78.844 +void MatrixSetupOrthogonalProjection(matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near, vec_t far)
  78.845 +{
  78.846 +	m[0] = 2 / (right - left);	m[4] = 0;					m[8] = 0;					m[12] = -(right + left) / (right - left);
  78.847 +	m[1] = 0;					m[5] = 2 / (top - bottom);	m[9] = 0;					m[13] = -(top + bottom) / (top - bottom);
  78.848 +	m[2] = 0;					m[6] = 0;					m[10] = -2 / (far - near);	m[14] = -(far + near) / (far - near);
  78.849 +	m[3] = 0;					m[7] = 0;					m[11] = 0;					m[15] = 1;
  78.850 +}
  78.851 +
  78.852 +// *INDENT-ON*
  78.853 +
  78.854 +
  78.855 +vec_t QuatNormalize(quat_t q)
  78.856 +{
  78.857 +	float           length, ilength;
  78.858 +
  78.859 +	length = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3];
  78.860 +	length = sqrt(length);
  78.861 +
  78.862 +	if(length)
  78.863 +	{
  78.864 +		ilength = 1 / length;
  78.865 +		q[0] *= ilength;
  78.866 +		q[1] *= ilength;
  78.867 +		q[2] *= ilength;
  78.868 +		q[3] *= ilength;
  78.869 +	}
  78.870 +
  78.871 +	return length;
  78.872 +}
  78.873 +
  78.874 +void QuatFromAngles(quat_t q, vec_t pitch, vec_t yaw, vec_t roll)
  78.875 +{
  78.876 +#if 1
  78.877 +	matrix_t        tmp;
  78.878 +
  78.879 +	MatrixFromAngles(tmp, pitch, yaw, roll);
  78.880 +	QuatFromMatrix(q, tmp);
  78.881 +#else
  78.882 +	static float    sr, sp, sy, cr, cp, cy;
  78.883 +
  78.884 +	// static to help MS compiler fp bugs
  78.885 +	sp = sin(DEG2RAD(pitch));
  78.886 +	cp = cos(DEG2RAD(pitch));
  78.887 +
  78.888 +	sy = sin(DEG2RAD(yaw));
  78.889 +	cy = cos(DEG2RAD(yaw));
  78.890 +
  78.891 +	sr = sin(DEG2RAD(roll));
  78.892 +	cr = cos(DEG2RAD(roll));
  78.893 +
  78.894 +	q[0] = sr * cp * cy - cr * sp * sy;	// x
  78.895 +	q[1] = cr * sp * cy + sr * cp * sy;	// y
  78.896 +	q[2] = cr * cp * sy - sr * sp * cy;	// z
  78.897 +	q[3] = cr * cp * cy + sr * sp * sy;	// w
  78.898 +#endif
  78.899 +}
  78.900 +
  78.901 +void QuatFromMatrix(quat_t q, const matrix_t m)
  78.902 +{
  78.903 +#if 1
  78.904 +	/*
  78.905 +	   From Quaternion to Matrix and Back
  78.906 +	   February 27th 2005
  78.907 +	   J.M.P. van Waveren
  78.908 +
  78.909 +	   http://www.intel.com/cd/ids/developer/asmo-na/eng/293748.htm
  78.910 +	 */
  78.911 +	float           t, s;
  78.912 +
  78.913 +	if(m[0] + m[5] + m[10] > 0.0f)
  78.914 +	{
  78.915 +		t = m[0] + m[5] + m[10] + 1.0f;
  78.916 +		s = 0.5f / sqrt(t);
  78.917 +
  78.918 +		q[3] = s * t;
  78.919 +		q[2] = (m[1] - m[4]) * s;
  78.920 +		q[1] = (m[8] - m[2]) * s;
  78.921 +		q[0] = (m[6] - m[9]) * s;
  78.922 +	}
  78.923 +	else if(m[0] > m[5] && m[0] > m[10])
  78.924 +	{
  78.925 +		t = m[0] - m[5] - m[10] + 1.0f;
  78.926 +		s = 0.5f / sqrt(t);
  78.927 +
  78.928 +		q[0] = s * t;
  78.929 +		q[1] = (m[1] + m[4]) * s;
  78.930 +		q[2] = (m[8] + m[2]) * s;
  78.931 +		q[3] = (m[6] - m[9]) * s;
  78.932 +	}
  78.933 +	else if(m[5] > m[10])
  78.934 +	{
  78.935 +		t = -m[0] + m[5] - m[10] + 1.0f;
  78.936 +		s = 0.5f / sqrt(t);
  78.937 +
  78.938 +		q[1] = s * t;
  78.939 +		q[0] = (m[1] + m[4]) * s;
  78.940 +		q[3] = (m[8] - m[2]) * s;
  78.941 +		q[2] = (m[6] + m[9]) * s;
  78.942 +	}
  78.943 +	else
  78.944 +	{
  78.945 +		t = -m[0] - m[5] + m[10] + 1.0f;
  78.946 +		s = 0.5f / sqrt(t);
  78.947 +
  78.948 +		q[2] = s * t;
  78.949 +		q[3] = (m[1] - m[4]) * s;
  78.950 +		q[0] = (m[8] + m[2]) * s;
  78.951 +		q[1] = (m[6] + m[9]) * s;
  78.952 +	}
  78.953 +
  78.954 +#else
  78.955 +	float           trace;
  78.956 +
  78.957 +	// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
  78.958 +
  78.959 +	trace = 1.0f + m[0] + m[5] + m[10];
  78.960 +
  78.961 +	if(trace > 0.0f)
  78.962 +	{
  78.963 +		vec_t           s = 0.5f / sqrt(trace);
  78.964 +
  78.965 +		q[0] = (m[6] - m[9]) * s;
  78.966 +		q[1] = (m[8] - m[2]) * s;
  78.967 +		q[2] = (m[1] - m[4]) * s;
  78.968 +		q[3] = 0.25f / s;
  78.969 +	}
  78.970 +	else
  78.971 +	{
  78.972 +		if(m[0] > m[5] && m[0] > m[10])
  78.973 +		{
  78.974 +			// column 0
  78.975 +			float           s = sqrt(1.0f + m[0] - m[5] - m[10]) * 2.0f;
  78.976 +
  78.977 +			q[0] = 0.25f * s;
  78.978 +			q[1] = (m[4] + m[1]) / s;
  78.979 +			q[2] = (m[8] + m[2]) / s;
  78.980 +			q[3] = (m[9] - m[6]) / s;
  78.981 +		}
  78.982 +		else if(m[5] > m[10])
  78.983 +		{
  78.984 +			// column 1
  78.985 +			float           s = sqrt(1.0f + m[5] - m[0] - m[10]) * 2.0f;
  78.986 +
  78.987 +			q[0] = (m[4] + m[1]) / s;
  78.988 +			q[1] = 0.25f * s;
  78.989 +			q[2] = (m[9] + m[6]) / s;
  78.990 +			q[3] = (m[8] - m[2]) / s;
  78.991 +		}
  78.992 +		else
  78.993 +		{
  78.994 +			// column 2
  78.995 +			float           s = sqrt(1.0f + m[10] - m[0] - m[5]) * 2.0f;
  78.996 +
  78.997 +			q[0] = (m[8] + m[2]) / s;
  78.998 +			q[1] = (m[9] + m[6]) / s;
  78.999 +			q[2] = 0.25f * s;
 78.1000 +			q[3] = (m[4] - m[1]) / s;
 78.1001 +		}
 78.1002 +	}
 78.1003 +
 78.1004 +	QuatNormalize(q);
 78.1005 +#endif
 78.1006 +}
 78.1007 +
 78.1008 +void QuatToVectorsFLU(const quat_t q, vec3_t forward, vec3_t left, vec3_t up)
 78.1009 +{
 78.1010 +	matrix_t        tmp;
 78.1011 +
 78.1012 +	MatrixFromQuat(tmp, q);
 78.1013 +	MatrixToVectorsFRU(tmp, forward, left, up);
 78.1014 +}
 78.1015 +
 78.1016 +void QuatToVectorsFRU(const quat_t q, vec3_t forward, vec3_t right, vec3_t up)
 78.1017 +{
 78.1018 +	matrix_t        tmp;
 78.1019 +
 78.1020 +	MatrixFromQuat(tmp, q);
 78.1021 +	MatrixToVectorsFRU(tmp, forward, right, up);
 78.1022 +}
 78.1023 +
 78.1024 +void QuatToAxis(const quat_t q, vec3_t axis[3])
 78.1025 +{
 78.1026 +	matrix_t        tmp;
 78.1027 +
 78.1028 +	MatrixFromQuat(tmp, q);
 78.1029 +	MatrixToVectorsFLU(tmp, axis[0], axis[1], axis[2]);
 78.1030 +}
 78.1031 +
 78.1032 +void QuatToAngles(const quat_t q, vec3_t angles)
 78.1033 +{
 78.1034 +	quat_t          q2;
 78.1035 +
 78.1036 +	q2[0] = q[0] * q[0];
 78.1037 +	q2[1] = q[1] * q[1];
 78.1038 +	q2[2] = q[2] * q[2];
 78.1039 +	q2[3] = q[3] * q[3];
 78.1040 +
 78.1041 +	angles[PITCH] = RAD2DEG(asin(-2 * (q[2] * q[0] - q[3] * q[1])));
 78.1042 +	angles[YAW] = RAD2DEG(atan2(2 * (q[2] * q[3] + q[0] * q[1]), (q2[2] - q2[3] - q2[0] + q2[1])));
 78.1043 +	angles[ROLL] = RAD2DEG(atan2(2 * (q[3] * q[0] + q[2] * q[1]), (-q2[2] - q2[3] + q2[0] + q2[1])));
 78.1044 +}
 78.1045 +
 78.1046 +
 78.1047 +void QuatMultiply0(quat_t qa, const quat_t qb)
 78.1048 +{
 78.1049 +	quat_t          tmp;
 78.1050 +
 78.1051 +	QuatCopy(qa, tmp);
 78.1052 +	QuatMultiply1(tmp, qb, qa);
 78.1053 +}
 78.1054 +
 78.1055 +void QuatMultiply1(const quat_t qa, const quat_t qb, quat_t qc)
 78.1056 +{
 78.1057 +	/*
 78.1058 +	   from matrix and quaternion faq
 78.1059 +	   x = w1x2 + x1w2 + y1z2 - z1y2
 78.1060 +	   y = w1y2 + y1w2 + z1x2 - x1z2
 78.1061 +	   z = w1z2 + z1w2 + x1y2 - y1x2
 78.1062 +
 78.1063 +	   w = w1w2 - x1x2 - y1y2 - z1z2
 78.1064 +	 */
 78.1065 +
 78.1066 +	qc[0] = qa[3] * qb[0] + qa[0] * qb[3] + qa[1] * qb[2] - qa[2] * qb[1];
 78.1067 +	qc[1] = qa[3] * qb[1] + qa[1] * qb[3] + qa[2] * qb[0] - qa[0] * qb[2];
 78.1068 +	qc[2] = qa[3] * qb[2] + qa[2] * qb[3] + qa[0] * qb[1] - qa[1] * qb[0];
 78.1069 +	qc[3] = qa[3] * qb[3] - qa[0] * qb[0] - qa[1] * qb[1] - qa[2] * qb[2];
 78.1070 +}
 78.1071 +
 78.1072 +void QuatMultiply2(const quat_t qa, const quat_t qb, quat_t qc)
 78.1073 +{
 78.1074 +	qc[0] = qa[3] * qb[0] + qa[0] * qb[3] + qa[1] * qb[2] + qa[2] * qb[1];
 78.1075 +	qc[1] = qa[3] * qb[1] - qa[1] * qb[3] - qa[2] * qb[0] + qa[0] * qb[2];
 78.1076 +	qc[2] = qa[3] * qb[2] - qa[2] * qb[3] - qa[0] * qb[1] + qa[1] * qb[0];
 78.1077 +	qc[3] = qa[3] * qb[3] - qa[0] * qb[0] - qa[1] * qb[1] + qa[2] * qb[2];
 78.1078 +}
 78.1079 +
 78.1080 +void QuatMultiply3(const quat_t qa, const quat_t qb, quat_t qc)
 78.1081 +{
 78.1082 +	qc[0] = qa[3] * qb[0] + qa[0] * qb[3] + qa[1] * qb[2] + qa[2] * qb[1];
 78.1083 +	qc[1] = -qa[3] * qb[1] + qa[1] * qb[3] - qa[2] * qb[0] + qa[0] * qb[2];
 78.1084 +	qc[2] = -qa[3] * qb[2] + qa[2] * qb[3] - qa[0] * qb[1] + qa[1] * qb[0];
 78.1085 +	qc[3] = -qa[3] * qb[3] + qa[0] * qb[0] - qa[1] * qb[1] + qa[2] * qb[2];
 78.1086 +}
 78.1087 +
 78.1088 +void QuatMultiply4(const quat_t qa, const quat_t qb, quat_t qc)
 78.1089 +{
 78.1090 +	qc[0] = qa[3] * qb[0] - qa[0] * qb[3] - qa[1] * qb[2] - qa[2] * qb[1];
 78.1091 +	qc[1] = -qa[3] * qb[1] - qa[1] * qb[3] + qa[2] * qb[0] - qa[0] * qb[2];
 78.1092 +	qc[2] = -qa[3] * qb[2] - qa[2] * qb[3] + qa[0] * qb[1] - qa[1] * qb[0];
 78.1093 +	qc[3] = -qa[3] * qb[3] - qa[0] * qb[0] + qa[1] * qb[1] - qa[2] * qb[2];
 78.1094 +}
 78.1095 +
 78.1096 +void QuatSlerp(const quat_t from, const quat_t to, float frac, quat_t out)
 78.1097 +{
 78.1098 +#if 0
 78.1099 +	quat_t          to1;
 78.1100 +	double          omega, cosom, sinom, scale0, scale1;
 78.1101 +
 78.1102 +	cosom = from[0] * to[0] + from[1] * to[1] + from[2] * to[2] + from[3] * to[3];
 78.1103 +
 78.1104 +	if(cosom < 0.0)
 78.1105 +	{
 78.1106 +		cosom = -cosom;
 78.1107 +
 78.1108 +		QuatCopy(to, to1);
 78.1109 +		QuatAntipodal(to1);
 78.1110 +	}
 78.1111 +	else
 78.1112 +	{
 78.1113 +		QuatCopy(to, to1);
 78.1114 +	}
 78.1115 +
 78.1116 +	if((1.0 - cosom) > 0)
 78.1117 +	{
 78.1118 +		omega = acos(cosom);
 78.1119 +		sinom = sin(omega);
 78.1120 +		scale0 = sin((1.0 - frac) * omega) / sinom;
 78.1121 +		scale1 = sin(frac * omega) / sinom;
 78.1122 +	}
 78.1123 +	else
 78.1124 +	{
 78.1125 +		scale0 = 1.0 - frac;
 78.1126 +		scale1 = frac;
 78.1127 +	}
 78.1128 +
 78.1129 +	out[0] = scale0 * from[0] + scale1 * to1[0];
 78.1130 +	out[1] = scale0 * from[1] + scale1 * to1[1];
 78.1131 +	out[2] = scale0 * from[2] + scale1 * to1[2];
 78.1132 +	out[3] = scale0 * from[3] + scale1 * to1[3];
 78.1133 +#else
 78.1134 +	/*
 78.1135 +	   Slerping Clock Cycles
 78.1136 +	   February 27th 2005
 78.1137 +	   J.M.P. van Waveren
 78.1138 +
 78.1139 +	   http://www.intel.com/cd/ids/developer/asmo-na/eng/293747.htm
 78.1140 +	 */
 78.1141 +	float           cosom, absCosom, sinom, sinSqr, omega, scale0, scale1;
 78.1142 +
 78.1143 +	if(frac <= 0.0f)
 78.1144 +	{
 78.1145 +		QuatCopy(from, out);
 78.1146 +		return;
 78.1147 +	}
 78.1148 +
 78.1149 +	if(frac >= 1.0f)
 78.1150 +	{
 78.1151 +		QuatCopy(to, out);
 78.1152 +		return;
 78.1153 +	}
 78.1154 +
 78.1155 +	if(QuatCompare(from, to))
 78.1156 +	{
 78.1157 +		QuatCopy(from, out);
 78.1158 +		return;
 78.1159 +	}
 78.1160 +
 78.1161 +	cosom = from[0] * to[0] + from[1] * to[1] + from[2] * to[2] + from[3] * to[3];
 78.1162 +	absCosom = fabs(cosom);
 78.1163 +
 78.1164 +	if((1.0f - absCosom) > 1e-6f)
 78.1165 +	{
 78.1166 +		sinSqr = 1.0f - absCosom * absCosom;
 78.1167 +		sinom = 1.0f / sqrt(sinSqr);
 78.1168 +		omega = atan2(sinSqr * sinom, absCosom);
 78.1169 +
 78.1170 +		scale0 = sin((1.0f - frac) * omega) * sinom;
 78.1171 +		scale1 = sin(frac * omega) * sinom;
 78.1172 +	}
 78.1173 +	else
 78.1174 +	{
 78.1175 +		scale0 = 1.0f - frac;
 78.1176 +		scale1 = frac;
 78.1177 +	}
 78.1178 +
 78.1179 +	scale1 = (cosom >= 0.0f) ? scale1 : -scale1;
 78.1180 +
 78.1181 +	out[0] = scale0 * from[0] + scale1 * to[0];
 78.1182 +	out[1] = scale0 * from[1] + scale1 * to[1];
 78.1183 +	out[2] = scale0 * from[2] + scale1 * to[2];
 78.1184 +	out[3] = scale0 * from[3] + scale1 * to[3];
 78.1185 +#endif
 78.1186 +}
 78.1187 +
 78.1188 +void QuatTransformVector(const quat_t q, const vec3_t in, vec3_t out)
 78.1189 +{
 78.1190 +	matrix_t        m;
 78.1191 +
 78.1192 +	MatrixFromQuat(m, q);
 78.1193 +	MatrixTransformNormal(m, in, out);
 78.1194 +}
 78.1195 +
 78.1196 +void ZeroBounds(vec3_t mins, vec3_t maxs)
 78.1197 +{
 78.1198 +	mins[0] = mins[1] = mins[2] = 0;
 78.1199 +	maxs[0] = maxs[1] = maxs[2] = 0;
 78.1200 +}
 78.1201 +
 78.1202 +void BoundsAdd(vec3_t mins, vec3_t maxs, const vec3_t mins2, const vec3_t maxs2)
 78.1203 +{
 78.1204 +	if(mins2[0] < mins[0])
 78.1205 +	{
 78.1206 +		mins[0] = mins2[0];
 78.1207 +	}
 78.1208 +	if(mins2[1] < mins[1])
 78.1209 +	{
 78.1210 +		mins[1] = mins2[1];
 78.1211 +	}
 78.1212 +	if(mins2[2] < mins[2])
 78.1213 +	{
 78.1214 +		mins[2] = mins2[2];
 78.1215 +	}
 78.1216 +
 78.1217 +	if(maxs2[0] > maxs[0])
 78.1218 +	{
 78.1219 +		maxs[0] = maxs2[0];
 78.1220 +	}
 78.1221 +	if(maxs2[1] > maxs[1])
 78.1222 +	{
 78.1223 +		maxs[1] = maxs2[1];
 78.1224 +	}
 78.1225 +	if(maxs2[2] > maxs[2])
 78.1226 +	{
 78.1227 +		maxs[2] = maxs2[2];
 78.1228 +	}
 78.1229 +}
    79.1 --- a/src/qcommon/q_shared.c	Sat Jun 06 03:54:16 2009 +0800
    79.2 +++ b/src/qcommon/q_shared.c	Wed Jun 10 09:31:46 2009 +0800
    79.3 @@ -24,6 +24,204 @@
    79.4  // q_shared.c -- stateless support routines that are included in each code dll
    79.5  #include "q_shared.h"
    79.6  
    79.7 +
    79.8 +
    79.9 +
   79.10 +
   79.11 +
   79.12 +/*
   79.13 +============================================================================
   79.14 +
   79.15 +GROWLISTS
   79.16 +
   79.17 +============================================================================
   79.18 +*/
   79.19 +
   79.20 +// malloc / free all in one place for debugging
   79.21 +//extern          "C" void *Com_Allocate(int bytes);
   79.22 +//extern          "C" void Com_Dealloc(void *ptr);
   79.23 +
   79.24 +void Com_InitGrowList(growList_t * list, int maxElements)
   79.25 +{
   79.26 +	list->maxElements = maxElements;
   79.27 +	list->currentElements = 0;
   79.28 +	list->elements = (void **)Com_Allocate(list->maxElements * sizeof(void *));
   79.29 +}
   79.30 +
   79.31 +void Com_DestroyGrowList(growList_t * list)
   79.32 +{
   79.33 +	Com_Dealloc(list->elements);
   79.34 +	memset(list, 0, sizeof(*list));
   79.35 +}
   79.36 +
   79.37 +int Com_AddToGrowList(growList_t * list, void *data)
   79.38 +{
   79.39 +	void          **old;
   79.40 +
   79.41 +	if(list->currentElements != list->maxElements)
   79.42 +	{
   79.43 +		list->elements[list->currentElements] = data;
   79.44 +		return list->currentElements++;
   79.45 +	}
   79.46 +
   79.47 +	// grow, reallocate and move
   79.48 +	old = list->elements;
   79.49 +
   79.50 +	if(list->maxElements < 0)
   79.51 +	{
   79.52 +		Com_Error(ERR_FATAL, "Com_AddToGrowList: maxElements = %i", list->maxElements);
   79.53 +	}
   79.54 +
   79.55 +	if(list->maxElements == 0)
   79.56 +	{
   79.57 +		// initialize the list to hold 100 elements
   79.58 +		Com_InitGrowList(list, 100);
   79.59 +		return Com_AddToGrowList(list, data);
   79.60 +	}
   79.61 +
   79.62 +	list->maxElements *= 2;
   79.63 +
   79.64 +//  Com_DPrintf("Resizing growlist to %i maxElements\n", list->maxElements);
   79.65 +
   79.66 +	list->elements = (void **)Com_Allocate(list->maxElements * sizeof(void *));
   79.67 +
   79.68 +	if(!list->elements)
   79.69 +	{
   79.70 +		Com_Error(ERR_DROP, "Growlist alloc failed");
   79.71 +	}
   79.72 +
   79.73 +	Com_Memcpy(list->elements, old, list->currentElements * sizeof(void *));
   79.74 +
   79.75 +	Com_Dealloc(old);
   79.76 +
   79.77 +	return Com_AddToGrowList(list, data);
   79.78 +}
   79.79 +
   79.80 +void           *Com_GrowListElement(const growList_t * list, int index)
   79.81 +{
   79.82 +	if(index < 0 || index >= list->currentElements)
   79.83 +	{
   79.84 +		Com_Error(ERR_DROP, "Com_GrowListElement: %i out of range of %i", index, list->currentElements);
   79.85 +	}
   79.86 +	return list->elements[index];
   79.87 +}
   79.88 +
   79.89 +int Com_IndexForGrowListElement(const growList_t * list, const void *element)
   79.90 +{
   79.91 +	int             i;
   79.92 +
   79.93 +	for(i = 0; i < list->currentElements; i++)
   79.94 +	{
   79.95 +		if(list->elements[i] == element)
   79.96 +		{
   79.97 +			return i;
   79.98 +		}
   79.99 +	}
  79.100 +	return -1;
  79.101 +}
  79.102 +
  79.103 +//=============================================================================
  79.104 +
  79.105 +memStream_t *AllocMemStream(byte *buffer, int bufSize)
  79.106 +{
  79.107 +	memStream_t		*s;
  79.108 +
  79.109 +	if(buffer == NULL || bufSize <= 0)
  79.110 +		return NULL;
  79.111 +
  79.112 +	s = Com_Allocate(sizeof(memStream_t));
  79.113 +	if(s == NULL)
  79.114 +		return NULL;
  79.115 +
  79.116 +	Com_Memset(s, 0, sizeof(memStream_t));
  79.117 +
  79.118 +	s->buffer 	= buffer;
  79.119 +	s->curPos 	= buffer;
  79.120 +	s->bufSize	= bufSize;
  79.121 +	s->flags	= 0;
  79.122 +
  79.123 +	return s;
  79.124 +}
  79.125 +
  79.126 +void FreeMemStream(memStream_t * s)
  79.127 +{
  79.128 +	Com_Dealloc(s);
  79.129 +}
  79.130 +
  79.131 +int MemStreamRead(memStream_t *s, void *buffer, int len)
  79.132 +{
  79.133 +	int				ret = 1;
  79.134 +
  79.135 +	if(s == NULL || buffer == NULL)
  79.136 +		return 0;
  79.137 +
  79.138 +	if(s->curPos + len > s->buffer + s->bufSize)
  79.139 +	{
  79.140 +		s->flags |= MEMSTREAM_FLAGS_EOF;
  79.141 +		len = s->buffer + s->bufSize - s->curPos;
  79.142 +		ret = 0;
  79.143 +
  79.144 +		Com_Error(ERR_FATAL, "MemStreamRead: EOF reached");
  79.145 +	}
  79.146 +
  79.147 +	Com_Memcpy(buffer, s->curPos, len);
  79.148 +	s->curPos += len;
  79.149 +
  79.150 +	return ret;
  79.151 +}
  79.152 +
  79.153 +int MemStreamGetC(memStream_t *s)
  79.154 +{
  79.155 +	int				c = 0;
  79.156 +
  79.157 +	if(s == NULL)
  79.158 +		return -1;
  79.159 +
  79.160 +	if(MemStreamRead(s, &c, 1) == 0)
  79.161 +		return -1;
  79.162 +
  79.163 +	return c;
  79.164 +}
  79.165 +
  79.166 +int MemStreamGetLong(memStream_t * s)
  79.167 +{
  79.168 +	int				c = 0;
  79.169 +
  79.170 +	if(s == NULL)
  79.171 +		return -1;
  79.172 +
  79.173 +	if(MemStreamRead(s, &c, 4) == 0)
  79.174 +		return -1;
  79.175 +
  79.176 +	return LittleLong(c);
  79.177 +}
  79.178 +
  79.179 +int MemStreamGetShort(memStream_t * s)
  79.180 +{
  79.181 +	int				c = 0;
  79.182 +
  79.183 +	if(s == NULL)
  79.184 +		return -1;
  79.185 +
  79.186 +	if(MemStreamRead(s, &c, 2) == 0)
  79.187 +		return -1;
  79.188 +
  79.189 +	return LittleShort(c);
  79.190 +}
  79.191 +
  79.192 +float MemStreamGetFloat(memStream_t * s)
  79.193 +{
  79.194 +	floatint_t		c;
  79.195 +
  79.196 +	if(s == NULL)
  79.197 +		return -1;
  79.198 +
  79.199 +	if(MemStreamRead(s, &c.i, 4) == 0)
  79.200 +		return -1;
  79.201 +
  79.202 +	return LittleFloat(c.f);
  79.203 +}
  79.204 +
  79.205  float Com_Clamp( float min, float max, float value ) {
  79.206  	if ( value < min ) {
  79.207  		return min;
  79.208 @@ -942,6 +1140,45 @@
  79.209  }
  79.210  
  79.211  
  79.212 +/*
  79.213 +=============
  79.214 +Q_strreplace
  79.215 +
  79.216 +replaces content of find by replace in dest
  79.217 +=============
  79.218 +*/
  79.219 +qboolean Q_strreplace(char *dest, int destsize, const char *find, const char *replace)
  79.220 +{
  79.221 +	int             lstart, lfind, lreplace, lend;
  79.222 +	char           *s;
  79.223 +	char            backup[32000];	// big, but small enough to fit in PPC stack
  79.224 +
  79.225 +	lend = strlen(dest);
  79.226 +	if(lend >= destsize)
  79.227 +	{
  79.228 +		Com_Error(ERR_FATAL, "Q_strreplace: already overflowed");
  79.229 +	}
  79.230 +
  79.231 +	s = strstr(dest, find);
  79.232 +	if(!s)
  79.233 +	{
  79.234 +		return qfalse;
  79.235 +	}
  79.236 +	else
  79.237 +	{
  79.238 +		Q_strncpyz(backup, dest, lend + 1);
  79.239 +		lstart = s - dest;
  79.240 +		lfind = strlen(find);
  79.241 +		lreplace = strlen(replace);
  79.242 +
  79.243 +		strncpy(s, replace, destsize - lstart - 1);
  79.244 +		strncpy(s + lreplace, backup + lstart + lfind, destsize - lstart - lreplace - 1);
  79.245 +
  79.246 +		return qtrue;
  79.247 +	}
  79.248 +}
  79.249 +
  79.250 +
  79.251  int Q_PrintStrlen( const char *string ) {
  79.252  	int			len;
  79.253  	const char	*p;
    80.1 --- a/src/qcommon/q_shared.h	Sat Jun 06 03:54:16 2009 +0800
    80.2 +++ b/src/qcommon/q_shared.h	Wed Jun 10 09:31:46 2009 +0800
    80.3 @@ -109,6 +109,7 @@
    80.4  #include <time.h>
    80.5  #include <ctype.h>
    80.6  #include <limits.h>
    80.7 +#include <float.h>
    80.8  
    80.9  // vsnprintf is ISO/IEC 9899:1999
   80.10  // abstracting this to make it portable
   80.11 @@ -169,6 +170,10 @@
   80.12  #define NULL ((void *)0)
   80.13  #endif
   80.14  
   80.15 +#ifndef BIT
   80.16 +#define BIT(x)				(1 << x)
   80.17 +#endif
   80.18 +
   80.19  #define	MAX_QINT			0x7fffffff
   80.20  #define	MIN_QINT			(-MAX_QINT-1)
   80.21  
   80.22 @@ -178,6 +183,15 @@
   80.23  #define	YAW					1		// left / right
   80.24  #define	ROLL				2		// fall over
   80.25  
   80.26 +// plane sides
   80.27 +typedef enum
   80.28 +{
   80.29 +	SIDE_FRONT = 0,
   80.30 +	SIDE_BACK = 1,
   80.31 +	SIDE_ON = 2,
   80.32 +	SIDE_CROSS = 3
   80.33 +} planeSide_t;
   80.34 +
   80.35  // the game guarantees that no string from the network will ever
   80.36  // exceed MAX_STRING_CHARS
   80.37  #define	MAX_STRING_CHARS	1024	// max length of a string passed to Cmd_TokenizeString
   80.38 @@ -284,6 +298,9 @@
   80.39  #define Com_Memset memset
   80.40  #define Com_Memcpy memcpy
   80.41  
   80.42 +#define Com_Allocate malloc
   80.43 +#define Com_Dealloc free
   80.44 +
   80.45  #define CIN_system	1
   80.46  #define CIN_loop	2
   80.47  #define	CIN_hold	4
   80.48 @@ -304,6 +321,8 @@
   80.49  typedef vec_t vec3_t[3];
   80.50  typedef vec_t vec3a_t[4] ALIGNED(16);
   80.51  typedef vec_t quat_t[4] ALIGNED(16);
   80.52 +typedef vec_t matrix3x3_t[9];
   80.53 +typedef vec3_t  axis_t[3];
   80.54  typedef vec_t matrix_t[16] ALIGNED(16);
   80.55  #if id386_sse >= 1
   80.56  #define vec3aLoad(vec3a)       v4fLoadA(vec3a)
   80.57 @@ -374,6 +393,8 @@
   80.58  #define COLOR_CYAN		'5'
   80.59  #define COLOR_MAGENTA	'6'
   80.60  #define COLOR_WHITE		'7'
   80.61 +
   80.62 +#define MAX_CCODES	7
   80.63  #define ColorIndex(c)	( ( (c) - '0' ) & 7 )
   80.64  
   80.65  #define S_COLOR_BLACK	"^0"
   80.66 @@ -393,15 +414,35 @@
   80.67  #define DEG2RAD( a ) ( ( (a) * M_PI ) / 180.0F )
   80.68  #define RAD2DEG( a ) ( ( (a) * 180.0f ) / M_PI )
   80.69  
   80.70 +#define Q_max(a, b)      ((a) > (b) ? (a) : (b))
   80.71 +#define Q_min(a, b)      ((a) < (b) ? (a) : (b))
   80.72 +#define Q_bound(a, b, c) (Q_max(a, Q_min(b, c)))
   80.73 +#define Q_clamp(a, b, c) ((b) >= (c) ? (a)=(b) : (a) < (b) ? (a)=(b) : (a) > (c) ? (a)=(c) : (a))
   80.74 +#define Q_lerp(from, to, frac) (from + ((to - from) * frac))
   80.75 +
   80.76  struct cplane_s;
   80.77  
   80.78  extern	vec3_t	vec3_origin;
   80.79  extern	vec3_t	axisDefault[3];
   80.80 +extern matrix_t matrixIdentity;
   80.81 +extern quat_t   quatIdentity;
   80.82  
   80.83  #define	nanmask (255<<23)
   80.84  
   80.85  #define	IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
   80.86  
   80.87 +static ID_INLINE long Q_ftol(float f)
   80.88 +{
   80.89 +#if id386_sse && defined(_MSC_VER)
   80.90 +	static int      tmp;
   80.91 +	__asm fld f
   80.92 +	__asm fistp tmp
   80.93 +	__asm mov eax, tmp
   80.94 +#else
   80.95 +	return (long)f;
   80.96 +#endif
   80.97 +}
   80.98 +
   80.99  #if idppc
  80.100  
  80.101  static ID_INLINE float Q_rsqrt( float number ) {
  80.102 @@ -431,6 +472,25 @@
  80.103  float Q_rsqrt( float f );		// reciprocal square root
  80.104  #endif
  80.105  
  80.106 +static ID_INLINE vec_t Q_recip(vec_t in)
  80.107 +{
  80.108 +#if id386_3dnow && defined __GNUC__ && 0
  80.109 +	vec_t           out;
  80.110 +
  80.111 +	femms();
  80.112 +	asm volatile    ("movd		(%%eax),	%%mm0\n" "pfrcp		%%mm0,		%%mm1\n"	// (approx)
  80.113 +					 "pfrcpit1	%%mm1,		%%mm0\n"	// (intermediate)
  80.114 +					 "pfrcpit2	%%mm1,		%%mm0\n"	// (full 24-bit)
  80.115 +					 // out = mm0[low]
  80.116 +					 "movd		%%mm0,		(%%edx)\n"::"a" (&in), "d"(&out):"memory");
  80.117 +
  80.118 +	femms();
  80.119 +	return out;
  80.120 +#else
  80.121 +	return ((float)(1.0f / (in)));
  80.122 +#endif
  80.123 +}
  80.124 +
  80.125  #define SQRTFAST( x ) ( (x) * Q_rsqrt( x ) )
  80.126  
  80.127  signed char ClampChar( int i );
  80.128 @@ -450,7 +510,17 @@
  80.129  #define	VectorMA(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s))
  80.130  #define VectorLerp( f, s, e, r ) ((r)[0]=(s)[0]+(f)*((e)[0]-(s)[0]),\
  80.131    (r)[1]=(s)[1]+(f)*((e)[1]-(s)[1]),\
  80.132 -  (r)[2]=(s)[2]+(f)*((e)[2]-(s)[2])) 
  80.133 +  (r)[2]=(s)[2]+(f)*((e)[2]-(s)[2]))
  80.134 +
  80.135 +#define DotProduct4(x,y)		((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])
  80.136 +#define VectorSubtract4(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3])
  80.137 +#define VectorAdd4(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3])
  80.138 +#define VectorCopy4(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
  80.139 +#define	VectorScale4(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s))
  80.140 +#define	VectorMA4(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s),(o)[3]=(v)[3]+(b)[3]*(s))
  80.141 +#define VectorClear4(a)			((a)[0]=(a)[1]=(a)[2]=(a)[3]=0)
  80.142 +#define VectorNegate4(a,b)		((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2],(b)[3]=-(a)[3])
  80.143 +#define VectorSet4(v,x,y,z,w)	((v)[0]=(x),(v)[1]=(y),(v)[2]=(z),(v)[3]=(w))
  80.144  
  80.145  #else
  80.146  
  80.147 @@ -491,6 +561,27 @@
  80.148  #define SnapVector(v) ( (v)[0] = Floor( (v)[0] ), (v)[1] = Floor( (v)[1] ), \
  80.149  			(v)[2]=Floor((v)[2]))
  80.150  
  80.151 +float           RadiusFromBounds(const vec3_t mins, const vec3_t maxs);
  80.152 +void            ZeroBounds(vec3_t mins, vec3_t maxs);
  80.153 +void            ClearBounds(vec3_t mins, vec3_t maxs);
  80.154 +void            AddPointToBounds(const vec3_t v, vec3_t mins, vec3_t maxs);
  80.155 +void            BoundsAdd(vec3_t mins, vec3_t maxs, const vec3_t mins2, const vec3_t maxs2);
  80.156 +qboolean        BoundsIntersect(const vec3_t mins, const vec3_t maxs, const vec3_t mins2, const vec3_t maxs2);
  80.157 +qboolean        BoundsIntersectSphere(const vec3_t mins, const vec3_t maxs, const vec3_t origin, vec_t radius);
  80.158 +qboolean        BoundsIntersectPoint(const vec3_t mins, const vec3_t maxs, const vec3_t origin);
  80.159 +
  80.160 +static ID_INLINE void BoundsToCorners(const vec3_t mins, const vec3_t maxs, vec3_t corners[8])
  80.161 +{
  80.162 +	VectorSet(corners[0], mins[0], maxs[1], maxs[2]);
  80.163 +	VectorSet(corners[1], maxs[0], maxs[1], maxs[2]);
  80.164 +	VectorSet(corners[2], maxs[0], mins[1], maxs[2]);
  80.165 +	VectorSet(corners[3], mins[0], mins[1], maxs[2]);
  80.166 +	VectorSet(corners[4], mins[0], maxs[1], mins[2]);
  80.167 +	VectorSet(corners[5], maxs[0], maxs[1], mins[2]);
  80.168 +	VectorSet(corners[6], maxs[0], mins[1], mins[2]);
  80.169 +	VectorSet(corners[7], mins[0], mins[1], mins[2]);
  80.170 +}
  80.171 +
  80.172  // just in case you do't want to use the macros
  80.173  vec_t _DotProduct( const vec3_t v1, const vec3_t v2 );
  80.174  void _VectorSubtract( const vec3_t veca, const vec3_t vecb, vec3_t out );
  80.175 @@ -516,6 +607,15 @@
  80.176  	return 1;
  80.177  }
  80.178  
  80.179 +static ID_INLINE int VectorCompare4(const vec4_t v1, const vec4_t v2)
  80.180 +{
  80.181 +	if(v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2] || v1[3] != v2[3])
  80.182 +	{
  80.183 +		return 0;
  80.184 +	}
  80.185 +	return 1;
  80.186 +}
  80.187 +
  80.188  static ID_INLINE int VectorCompareEpsilon(
  80.189  		const vec3_t v1, const vec3_t v2, float epsilon )
  80.190  {
  80.191 @@ -603,6 +703,8 @@
  80.192  void Vector4Scale( const vec4_t in, vec_t scale, vec4_t out );
  80.193  void VectorRotate( vec3_t in, vec3_t matrix[3], vec3_t out );
  80.194  int Q_log2(int val);
  80.195 +int NearestPowerOfTwo(int val);
  80.196 +void ClampColor(vec4_t color);
  80.197  
  80.198  float Q_acos(float c);
  80.199  
  80.200 @@ -648,7 +750,51 @@
  80.201  
  80.202  //int	PlaneTypeForNormal (vec3_t normal);
  80.203  
  80.204 -void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]);
  80.205 +
  80.206 +void            MatrixIdentity(matrix_t m);
  80.207 +void            MatrixClear(matrix_t m);
  80.208 +void            MatrixCopy(const matrix_t in, matrix_t out);
  80.209 +qboolean        MatrixCompare(const matrix_t a, const matrix_t b);
  80.210 +void            MatrixTransposeIntoXMM(const matrix_t m);
  80.211 +void            MatrixTranspose(const matrix_t in, matrix_t out);
  80.212 +
  80.213 +// invert any m4x4 using Kramer's rule.. return qtrue if matrix is singular, else return qfalse
  80.214 +qboolean        MatrixInverse(matrix_t m);
  80.215 +void            MatrixSetupXRotation(matrix_t m, vec_t degrees);
  80.216 +void            MatrixSetupYRotation(matrix_t m, vec_t degrees);
  80.217 +void            MatrixSetupZRotation(matrix_t m, vec_t degrees);
  80.218 +void            MatrixSetupTranslation(matrix_t m, vec_t x, vec_t y, vec_t z);
  80.219 +void            MatrixSetupScale(matrix_t m, vec_t x, vec_t y, vec_t z);
  80.220 +void            MatrixSetupShear(matrix_t m, vec_t x, vec_t y);
  80.221 +void            MatrixMultiply2(matrix_t m, const matrix_t m2);
  80.222 +void            MatrixMultiplyRotation(matrix_t m, vec_t pitch, vec_t yaw, vec_t roll);
  80.223 +void            MatrixMultiplyZRotation(matrix_t m, vec_t degrees);
  80.224 +void            MatrixMultiplyTranslation(matrix_t m, vec_t x, vec_t y, vec_t z);
  80.225 +void            MatrixMultiplyScale(matrix_t m, vec_t x, vec_t y, vec_t z);
  80.226 +void            MatrixMultiplyShear(matrix_t m, vec_t x, vec_t y);
  80.227 +void            MatrixToAngles(const matrix_t m, vec3_t angles);
  80.228 +void            MatrixFromAngles(matrix_t m, vec_t pitch, vec_t yaw, vec_t roll);
  80.229 +void            MatrixFromVectorsFLU(matrix_t m, const vec3_t forward, const vec3_t left, const vec3_t up);
  80.230 +void            MatrixFromVectorsFRU(matrix_t m, const vec3_t forward, const vec3_t right, const vec3_t up);
  80.231 +void            MatrixFromQuat(matrix_t m, const quat_t q);
  80.232 +void            MatrixFromPlanes(matrix_t m, const vec4_t left, const vec4_t right, const vec4_t bottom, const vec4_t top,
  80.233 +								 const vec4_t front, const vec4_t back);
  80.234 +void            MatrixToVectorsFLU(const matrix_t m, vec3_t forward, vec3_t left, vec3_t up);
  80.235 +void            MatrixToVectorsFRU(const matrix_t m, vec3_t forward, vec3_t right, vec3_t up);
  80.236 +void            MatrixSetupTransform(matrix_t m, const vec3_t forward, const vec3_t left, const vec3_t up, const vec3_t origin);
  80.237 +void            MatrixSetupTransformFromRotation(matrix_t m, const matrix_t rot, const vec3_t origin);
  80.238 +void            MatrixSetupTransformFromQuat(matrix_t m, const quat_t quat, const vec3_t origin);
  80.239 +void            MatrixAffineInverse(const matrix_t in, matrix_t out);
  80.240 +void            MatrixTransformNormal(const matrix_t m, const vec3_t in, vec3_t out);
  80.241 +void            MatrixTransformNormal2(const matrix_t m, vec3_t inout);
  80.242 +void            MatrixTransformPoint(const matrix_t m, const vec3_t in, vec3_t out);
  80.243 +void            MatrixTransformPoint2(const matrix_t m, vec3_t inout);
  80.244 +void            MatrixTransform4(const matrix_t m, const vec4_t in, vec4_t out);
  80.245 +void            MatrixSetupPerspectiveProjection(matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near,
  80.246 +												 vec_t far);
  80.247 +void            MatrixSetupOrthogonalProjection(matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near,
  80.248 +												vec_t far);
  80.249 +
  80.250  void VectorMatrixMultiply( const vec3_t p, vec3_t m[ 3 ], vec3_t out );
  80.251  void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
  80.252  void PerpendicularVector( vec3_t dst, const vec3_t src );
  80.253 @@ -685,6 +831,153 @@
  80.254  float rint( float v );
  80.255  #endif
  80.256  
  80.257 +
  80.258 +#define QuatSet(q,x,y,z,w)	((q)[0]=(x),(q)[1]=(y),(q)[2]=(z),(q)[3]=(w))
  80.259 +#define QuatCopy(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
  80.260 +
  80.261 +#define QuatCompare(a,b)	((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3])
  80.262 +
  80.263 +static ID_INLINE void QuatClear(quat_t q)
  80.264 +{
  80.265 +	q[0] = 0;
  80.266 +	q[1] = 0;
  80.267 +	q[2] = 0;
  80.268 +	q[3] = 1;
  80.269 +}
  80.270 +
  80.271 +/*
  80.272 +static ID_INLINE int QuatCompare(const quat_t a, const quat_t b)
  80.273 +{
  80.274 +	if(a[0] != b[0] || a[1] != b[1] || a[2] != b[2] || a[3] != b[3])
  80.275 +	{
  80.276 +		return 0;
  80.277 +	}
  80.278 +	return 1;
  80.279 +}
  80.280 +*/
  80.281 +
  80.282 +static ID_INLINE void QuatCalcW(quat_t q)
  80.283 +{
  80.284 +#if 1
  80.285 +	vec_t           term = 1.0f - (q[0] * q[0] + q[1] * q[1] + q[2] * q[2]);
  80.286 +
  80.287 +	if(term < 0.0)
  80.288 +		q[3] = 0.0;
  80.289 +	else
  80.290 +		q[3] = -sqrt(term);
  80.291 +#else
  80.292 +	q[3] = sqrt(fabs(1.0f - (q[0] * q[0] + q[1] * q[1] + q[2] * q[2])));
  80.293 +#endif
  80.294 +}
  80.295 +
  80.296 +static ID_INLINE void QuatInverse(quat_t q)
  80.297 +{
  80.298 +	q[0] = -q[0];
  80.299 +	q[1] = -q[1];
  80.300 +	q[2] = -q[2];
  80.301 +}
  80.302 +
  80.303 +static ID_INLINE void QuatAntipodal(quat_t q)
  80.304 +{
  80.305 +	q[0] = -q[0];
  80.306 +	q[1] = -q[1];
  80.307 +	q[2] = -q[2];
  80.308 +	q[3] = -q[3];
  80.309 +}
  80.310 +
  80.311 +static ID_INLINE vec_t QuatLength(const quat_t q)
  80.312 +{
  80.313 +	return (vec_t) sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
  80.314 +}
  80.315 +
  80.316 +vec_t           QuatNormalize(quat_t q);
  80.317 +
  80.318 +void            QuatFromAngles(quat_t q, vec_t pitch, vec_t yaw, vec_t roll);
  80.319 +
  80.320 +static ID_INLINE void AnglesToQuat(const vec3_t angles, quat_t q)
  80.321 +{
  80.322 +	QuatFromAngles(q, angles[PITCH], angles[YAW], angles[ROLL]);
  80.323 +}
  80.324 +
  80.325 +void            QuatFromMatrix(quat_t q, const matrix_t m);
  80.326 +void            QuatToVectorsFLU(const quat_t quat, vec3_t forward, vec3_t left, vec3_t up);
  80.327 +void            QuatToVectorsFRU(const quat_t quat, vec3_t forward, vec3_t right, vec3_t up);
  80.328 +void            QuatToAxis(const quat_t q, vec3_t axis[3]);
  80.329 +void            QuatToAngles(const quat_t q, vec3_t angles);
  80.330 +
  80.331 +// Quaternion multiplication, analogous to the matrix multiplication routines.
  80.332 +
  80.333 +// qa = rotate by qa, then qb
  80.334 +void            QuatMultiply0(quat_t qa, const quat_t qb);
  80.335 +
  80.336 +// qc = rotate by qa, then qb
  80.337 +void            QuatMultiply1(const quat_t qa, const quat_t qb, quat_t qc);
  80.338 +
  80.339 +// qc = rotate by qa, then by inverse of qb
  80.340 +void            QuatMultiply2(const quat_t qa, const quat_t qb, quat_t qc);
  80.341 +
  80.342 +// qc = rotate by inverse of qa, then by qb
  80.343 +void            QuatMultiply3(const quat_t qa, const quat_t qb, quat_t qc);
  80.344 +
  80.345 +// qc = rotate by inverse of qa, then by inverse of qb
  80.346 +void            QuatMultiply4(const quat_t qa, const quat_t qb, quat_t qc);
  80.347 +
  80.348 +
  80.349 +void            QuatSlerp(const quat_t from, const quat_t to, float frac, quat_t out);
  80.350 +void            QuatTransformVector(const quat_t q, const vec3_t in, vec3_t out);
  80.351 +
  80.352 +//=============================================
  80.353 +
  80.354 +typedef struct
  80.355 +{
  80.356 +	qboolean        frameMemory;
  80.357 +	int             currentElements;
  80.358 +	int             maxElements;	// will reallocate and move when exceeded
  80.359 +	void          **elements;
  80.360 +} growList_t;
  80.361 +
  80.362 +// you don't need to init the growlist if you don't mind it growing and moving
  80.363 +// the list as it expands
  80.364 +void            Com_InitGrowList(growList_t * list, int maxElements);
  80.365 +void            Com_DestroyGrowList(growList_t * list);
  80.366 +int             Com_AddToGrowList(growList_t * list, void *data);
  80.367 +void           *Com_GrowListElement(const growList_t * list, int index);
  80.368 +int             Com_IndexForGrowListElement(const growList_t * list, const void *element);
  80.369 +
  80.370 +
  80.371 +//=============================================================================
  80.372 +
  80.373 +enum
  80.374 +{
  80.375 +	MEMSTREAM_SEEK_SET,
  80.376 +	MEMSTREAM_SEEK_CUR,
  80.377 +	MEMSTREAM_SEEK_END
  80.378 +};
  80.379 +
  80.380 +enum
  80.381 +{
  80.382 +	MEMSTREAM_FLAGS_EOF = BIT(0),
  80.383 +	MEMSTREAM_FLAGS_ERR = BIT(1),
  80.384 +};
  80.385 +
  80.386 +// helper struct for reading binary file formats
  80.387 +typedef struct memStream_s
  80.388 +{
  80.389 +	byte           *buffer;
  80.390 +	int				bufSize;
  80.391 +	byte           *curPos;
  80.392 +	int             flags;
  80.393 +}
  80.394 +memStream_t;
  80.395 +
  80.396 +memStream_t    *AllocMemStream(byte *buffer, int bufSize);
  80.397 +void			FreeMemStream(memStream_t * s);
  80.398 +int				MemStreamRead(memStream_t *s, void *buffer, int len);
  80.399 +int				MemStreamGetC(memStream_t *s);
  80.400 +int				MemStreamGetLong(memStream_t * s);
  80.401 +int				MemStreamGetShort(memStream_t * s);
  80.402 +float			MemStreamGetFloat(memStream_t * s);
  80.403 +
  80.404  //=============================================
  80.405  
  80.406  float Com_Clamp( float min, float max, float value );
  80.407 @@ -777,6 +1070,7 @@
  80.408  // buffer size safe library replacements
  80.409  void	Q_strncpyz( char *dest, const char *src, int destsize );
  80.410  void	Q_strcat( char *dest, int size, const char *src );
  80.411 +qboolean Q_strreplace(char *dest, int destsize, const char *find, const char *replace);
  80.412  
  80.413  // strlen that discounts Quake color sequences
  80.414  int Q_PrintStrlen( const char *string );
    81.1 --- a/src/qcommon/qfiles.h	Sat Jun 06 03:54:16 2009 +0800
    81.2 +++ b/src/qcommon/qfiles.h	Wed Jun 10 09:31:46 2009 +0800
    81.3 @@ -36,8 +36,9 @@
    81.4  #endif
    81.5  
    81.6  // surface geometry should not exceed these limits
    81.7 -#define	SHADER_MAX_VERTEXES	1000
    81.8 -#define	SHADER_MAX_INDEXES	(6*SHADER_MAX_VERTEXES)
    81.9 +#define	SHADER_MAX_VERTEXES	100000
   81.10 +#define	SHADER_MAX_INDEXES	(SHADER_MAX_VERTEXES * 6)
   81.11 +#define SHADER_MAX_TRIANGLES (SHADER_MAX_INDEXES / 3)
   81.12  
   81.13  
   81.14  // the maximum size of game relative pathnames
   81.15 @@ -392,6 +393,119 @@
   81.16  
   81.17  #endif
   81.18  
   81.19 +
   81.20 +/*
   81.21 +========================================================================
   81.22 +
   81.23 +Actor X - .PSK / .PSA skeletal triangle model file format
   81.24 +
   81.25 +========================================================================
   81.26 +*/
   81.27 +
   81.28 +#define PSK_IDENTSTRING		"ACTRHEAD"
   81.29 +#define PSK_IDENTLEN		8
   81.30 +#define PSK_VERSION			1
   81.31 +
   81.32 +
   81.33 +typedef struct
   81.34 +{
   81.35 +	char            ident[20];
   81.36 +	int             flags;
   81.37 +
   81.38 +	int				dataSize;	// sizeof(struct)
   81.39 +	int				numData;	// number of structs put into this data chunk
   81.40 +} axChunkHeader_t;
   81.41 +
   81.42 +typedef struct
   81.43 +{
   81.44 +	float			point[3];
   81.45 +} axPoint_t;
   81.46 +
   81.47 +typedef struct
   81.48 +{
   81.49 +	unsigned short	pointIndex;
   81.50 +	unsigned short	unknownA;
   81.51 +	float			st[2];
   81.52 +	byte			materialIndex;
   81.53 +	byte			reserved;		// we don't care about this one
   81.54 +	unsigned short	unknownB;
   81.55 +} axVertex_t;
   81.56 +
   81.57 +typedef struct
   81.58 +{
   81.59 +	unsigned short	indexes[3];
   81.60 +	byte			materialIndex;
   81.61 +	byte			materialIndex2;
   81.62 +	unsigned int	smoothingGroups;
   81.63 +} axTriangle_t;
   81.64 +
   81.65 +typedef struct
   81.66 +{
   81.67 +	char            name[64];
   81.68 +	int             shaderIndex;	// for in-game use
   81.69 +	unsigned int	polyFlags;
   81.70 +	int				auxMaterial;
   81.71 +	unsigned int	auxFlags;
   81.72 +	int				lodBias;
   81.73 +	int				lodStyle;
   81.74 +} axMaterial_t;
   81.75 +
   81.76 +typedef struct
   81.77 +{
   81.78 +	float			quat[4];		// x y z w
   81.79 +	float			position[3];	// x y z
   81.80 +
   81.81 +	float			length;
   81.82 +	float			xSize;
   81.83 +	float			ySize;
   81.84 +	float			zSize;
   81.85 +} axBone_t;
   81.86 +
   81.87 +typedef struct
   81.88 +{
   81.89 +	char			name[64];
   81.90 +	unsigned int	flags;
   81.91 +	int				numChildren;
   81.92 +	int				parentIndex;
   81.93 +	axBone_t		bone;
   81.94 +} axReferenceBone_t;
   81.95 +
   81.96 +typedef struct
   81.97 +{
   81.98 +	float			weight;
   81.99 +	unsigned int	pointIndex;
  81.100 +	unsigned int	boneIndex;
  81.101 +} axBoneWeight_t;
  81.102 +
  81.103 +typedef struct
  81.104 +{
  81.105 +	char			name[64];
  81.106 +	char			group[64];
  81.107 +
  81.108 +	int				numBones;		// same as numChannels
  81.109 +	int				rootInclude;
  81.110 +
  81.111 +	int				keyCompressionStyle;
  81.112 +	int				keyQuotum;
  81.113 +	float			keyReduction;
  81.114 +
  81.115 +	float			trackTime;
  81.116 +
  81.117 +	float			frameRate;
  81.118 +
  81.119 +	int				startBoneIndex;
  81.120 +
  81.121 +	int				firstRawFrame;
  81.122 +	int				numRawFrames;
  81.123 +} axAnimationInfo_t;
  81.124 +
  81.125 +typedef struct
  81.126 +{
  81.127 +	float			position[3];
  81.128 +	float			quat[4];
  81.129 +	float			time;
  81.130 +} axAnimationKey_t;
  81.131 +
  81.132  /*
  81.133  ==============================================================================
  81.134  
  81.135 @@ -538,6 +652,23 @@
  81.136  	int			visibleSide;	// the brush side that ray tests need to clip against (-1 == none)
  81.137  } dfog_t;
  81.138  
  81.139 +// light grid
  81.140 +#if defined(COMPAT_Q3A)
  81.141 +typedef struct
  81.142 +{
  81.143 +	byte            ambient[3];
  81.144 +	byte            directed[3];
  81.145 +	byte            latLong[2];
  81.146 +} dgridPoint_t;
  81.147 +#else
  81.148 +typedef struct
  81.149 +{
  81.150 +	float           ambient[3];
  81.151 +	float           directed[3];
  81.152 +	byte            latLong[2];
  81.153 +} dgridPoint_t;
  81.154 +#endif
  81.155 +
  81.156  typedef struct {
  81.157  	vec3_t		xyz;
  81.158  	float		st[2];
  81.159 @@ -553,7 +684,8 @@
  81.160  	MST_PLANAR,
  81.161  	MST_PATCH,
  81.162  	MST_TRIANGLE_SOUP,
  81.163 -	MST_FLARE
  81.164 +	MST_FLARE,
  81.165 +	MST_FOLIAGE
  81.166  } mapSurfaceType_t;
  81.167  
  81.168  typedef struct {
    82.1 --- a/src/qcommon/surfaceflags.h	Sat Jun 06 03:54:16 2009 +0800
    82.2 +++ b/src/qcommon/surfaceflags.h	Wed Jun 10 09:31:46 2009 +0800
    82.3 @@ -89,3 +89,7 @@
    82.4  #define	SURF_NOALIENBUILD	0x80000  //disallow alien building
    82.5  #define	SURF_NOHUMANBUILD	0x100000 //disallow alien building
    82.6  #define	SURF_NOBUILD			0x200000 //disallow alien building
    82.7 +
    82.8 +// xreal compat
    82.9 +#define	SURF_COLLISION			0x4000000	// don't draw but use for per polygon collision detection
   82.10 +#define SURF_WALLWALK			0x8000000	// allows player to walk on walls
    83.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.2 +++ b/src/renderer/qgl.c	Wed Jun 10 09:31:46 2009 +0800
    83.3 @@ -0,0 +1,1031 @@
    83.4 +/*
    83.5 +===========================================================================
    83.6 +Copyright (C) 1999-2005 Id Software, Inc.
    83.7 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    83.8 +
    83.9 +This file is part of XreaL source code.
   83.10 +
   83.11 +XreaL source code is free software; you can redistribute it
   83.12 +and/or modify it under the terms of the GNU General Public License as
   83.13 +published by the Free Software Foundation; either version 2 of the License,
   83.14 +or (at your option) any later version.
   83.15 +
   83.16 +XreaL source code is distributed in the hope that it will be
   83.17 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   83.18 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   83.19 +GNU General Public License for more details.
   83.20 +
   83.21 +You should have received a copy of the GNU General Public License
   83.22 +along with XreaL source code; if not, write to the Free Software
   83.23 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   83.24 +===========================================================================
   83.25 +*/
   83.26 +/*
   83.27 +** QGL.C
   83.28 +**
   83.29 +** This file implements the operating system binding of GL to QGL function
   83.30 +** pointers.  When doing a port of XreaL you must implement the following
   83.31 +** two functions:
   83.32 +**
   83.33 +** QGL_Init() - loads libraries, assigns function pointers, etc.
   83.34 +** QGL_Shutdown() - unloads libraries, NULLs function pointers
   83.35 +*/
   83.36 +
   83.37 +#include "SDL.h"
   83.38 +#include "SDL_loadso.h"
   83.39 +
   83.40 +#include "qgl.h"
   83.41 +#include "tr_local.h"
   83.42 +
   83.43 +
   83.44 +// OpenGL 2.x core API
   83.45 +void            (APIENTRY * qglBindTexture) (GLenum target, GLuint texture);
   83.46 +void            (APIENTRY * qglBlendFunc) (GLenum sfactor, GLenum dfactor);
   83.47 +void            (APIENTRY * qglClear) (GLbitfield mask);
   83.48 +void            (APIENTRY * qglClearColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
   83.49 +void            (APIENTRY * qglClearDepth) (GLclampd depth);
   83.50 +void            (APIENTRY * qglClearStencil) (GLint s);
   83.51 +void            (APIENTRY * qglColorMask) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
   83.52 +void            (APIENTRY * qglCopyPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
   83.53 +void            (APIENTRY * qglCopyTexImage1D) (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y,
   83.54 +												GLsizei width, GLint border);
   83.55 +void            (APIENTRY * qglCopyTexImage2D) (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y,
   83.56 +												GLsizei width, GLsizei height, GLint border);
   83.57 +void            (APIENTRY * qglCopyTexSubImage1D) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
   83.58 +void            (APIENTRY * qglCopyTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
   83.59 +												   GLsizei width, GLsizei height);
   83.60 +void            (APIENTRY * qglCullFace) (GLenum mode);
   83.61 +void            (APIENTRY * qglDeleteTextures) (GLsizei n, const GLuint * textures);
   83.62 +void            (APIENTRY * qglDepthFunc) (GLenum func);
   83.63 +void            (APIENTRY * qglDepthMask) (GLboolean flag);
   83.64 +void            (APIENTRY * qglDepthRange) (GLclampd zNear, GLclampd zFar);
   83.65 +void            (APIENTRY * qglDisable) (GLenum cap);
   83.66 +void            (APIENTRY * qglDrawArrays) (GLenum mode, GLint first, GLsizei count);
   83.67 +void            (APIENTRY * qglDrawBuffer) (GLenum mode);
   83.68 +void            (APIENTRY * qglDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid * indices);
   83.69 +void            (APIENTRY * qglEnable) (GLenum cap);
   83.70 +void            (APIENTRY * qglFinish) (void);
   83.71 +void            (APIENTRY * qglFlush) (void);
   83.72 +void            (APIENTRY * qglFrontFace) (GLenum mode);
   83.73 +void            (APIENTRY * qglGenTextures) (GLsizei n, GLuint * textures);
   83.74 +void            (APIENTRY * qglGetBooleanv) (GLenum pname, GLboolean * params);
   83.75 +
   83.76 +GLenum(APIENTRY * qglGetError) (void);
   83.77 +void            (APIENTRY * qglGetFloatv) (GLenum pname, GLfloat * params);
   83.78 +void            (APIENTRY * qglGetIntegerv) (GLenum pname, GLint * params);
   83.79 +const GLubyte  *(APIENTRY * qglGetString) (GLenum name);
   83.80 +void            (APIENTRY * qglGetTexParameterfv) (GLenum target, GLenum pname, GLfloat * params);
   83.81 +void            (APIENTRY * qglGetTexParameteriv) (GLenum target, GLenum pname, GLint * params);
   83.82 +void            (APIENTRY * qglHint) (GLenum target, GLenum mode);
   83.83 +
   83.84 +GLboolean(APIENTRY * qglIsEnabled) (GLenum cap);
   83.85 +GLboolean(APIENTRY * qglIsTexture) (GLuint texture);
   83.86 +void            (APIENTRY * qglLineWidth) (GLfloat width);
   83.87 +void            (APIENTRY * qglPolygonMode) (GLenum face, GLenum mode);
   83.88 +void            (APIENTRY * qglPolygonOffset) (GLfloat factor, GLfloat units);
   83.89 +void            (APIENTRY * qglReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
   83.90 +											GLvoid * pixels);
   83.91 +void            (APIENTRY * qglScissor) (GLint x, GLint y, GLsizei width, GLsizei height);
   83.92 +void            (APIENTRY * qglSelectBuffer) (GLsizei size, GLuint * buffer);
   83.93 +void            (APIENTRY * qglShadeModel) (GLenum mode);
   83.94 +void            (APIENTRY * qglStencilFunc) (GLenum func, GLint ref, GLuint mask);
   83.95 +void            (APIENTRY * qglStencilMask) (GLuint mask);
   83.96 +void            (APIENTRY * qglStencilOp) (GLenum fail, GLenum zfail, GLenum zpass);
   83.97 +void            (APIENTRY * qglTexImage1D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border,
   83.98 +											GLenum format, GLenum type, const GLvoid * pixels);
   83.99 +void            (APIENTRY * qglTexImage2D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
  83.100 +											GLint border, GLenum format, GLenum type, const GLvoid * pixels);
  83.101 +void            (APIENTRY * qglTexParameterf) (GLenum target, GLenum pname, GLfloat param);
  83.102 +void            (APIENTRY * qglTexParameterfv) (GLenum target, GLenum pname, const GLfloat * params);
  83.103 +void            (APIENTRY * qglTexParameteri) (GLenum target, GLenum pname, GLint param);
  83.104 +void            (APIENTRY * qglTexParameteriv) (GLenum target, GLenum pname, const GLint * params);
  83.105 +void            (APIENTRY * qglTexSubImage1D) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format,
  83.106 +											   GLenum type, const GLvoid * pixels);
  83.107 +void            (APIENTRY * qglTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
  83.108 +											   GLsizei height, GLenum format, GLenum type, const GLvoid * pixels);
  83.109 +void            (APIENTRY * qglViewport) (GLint x, GLint y, GLsizei width, GLsizei height);
  83.110 +
  83.111 +
  83.112 +#if defined(WIN32)
  83.113 +// WGL_ARB_create_context
  83.114 +HGLRC(APIENTRY * qwglCreateContextAttribsARB) (HDC hdC, HGLRC hShareContext, const int *attribList);
  83.115 +#endif
  83.116 +
  83.117 +#if 0 //defined(__linux__)
  83.118 +// GLX_ARB_create_context
  83.119 +GLXContext      (APIENTRY * qglXCreateContextAttribsARB) (Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
  83.120 +#endif
  83.121 +
  83.122 +
  83.123 +static void     (APIENTRY * dllBindTexture) (GLenum target, GLuint texture);
  83.124 +static void     (APIENTRY * dllBlendFunc) (GLenum sfactor, GLenum dfactor);
  83.125 +static void     (APIENTRY * dllClear) (GLbitfield mask);
  83.126 +static void     (APIENTRY * dllClearColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
  83.127 +static void     (APIENTRY * dllClearDepth) (GLclampd depth);
  83.128 +static void     (APIENTRY * dllClearStencil) (GLint s);
  83.129 +static void     (APIENTRY * dllColorMask) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
  83.130 +static void     (APIENTRY * dllCopyPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
  83.131 +static void     (APIENTRY * dllCopyTexImage1D) (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y,
  83.132 +												GLsizei width, GLint border);
  83.133 +static void     (APIENTRY * dllCopyTexImage2D) (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y,
  83.134 +												GLsizei width, GLsizei height, GLint border);
  83.135 +static void     (APIENTRY * dllCopyTexSubImage1D) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
  83.136 +static void     (APIENTRY * dllCopyTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
  83.137 +												   GLsizei width, GLsizei height);
  83.138 +static void     (APIENTRY * dllCullFace) (GLenum mode);
  83.139 +static void     (APIENTRY * dllDeleteTextures) (GLsizei n, const GLuint * textures);
  83.140 +static void     (APIENTRY * dllDepthFunc) (GLenum func);
  83.141 +static void     (APIENTRY * dllDepthMask) (GLboolean flag);
  83.142 +static void     (APIENTRY * dllDepthRange) (GLclampd zNear, GLclampd zFar);
  83.143 +static void     (APIENTRY * dllDisable) (GLenum cap);
  83.144 +static void     (APIENTRY * dllDrawArrays) (GLenum mode, GLint first, GLsizei count);
  83.145 +static void     (APIENTRY * dllDrawBuffer) (GLenum mode);
  83.146 +static void     (APIENTRY * dllDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid * indices);
  83.147 +static void     (APIENTRY * dllEnable) (GLenum cap);
  83.148 +static void     (APIENTRY * dllFinish) (void);
  83.149 +static void     (APIENTRY * dllFlush) (void);
  83.150 +static void     (APIENTRY * dllFrontFace) (GLenum mode);
  83.151 +static void     (APIENTRY * dllGenTextures) (GLsizei n, GLuint * textures);
  83.152 +static void     (APIENTRY * dllGetBooleanv) (GLenum pname, GLboolean * params);
  83.153 +static void     (APIENTRY * dllGetDoublev) (GLenum pname, GLdouble * params);
  83.154 +
  83.155 +GLenum(APIENTRY * dllGetError) (void);
  83.156 +static void     (APIENTRY * dllGetFloatv) (GLenum pname, GLfloat * params);
  83.157 +static void     (APIENTRY * dllGetIntegerv) (GLenum pname, GLint * params);
  83.158 +const GLubyte  *(APIENTRY * dllGetString) (GLenum name);
  83.159 +static void     (APIENTRY * dllGetTexParameterfv) (GLenum target, GLenum pname, GLfloat * params);
  83.160 +static void     (APIENTRY * dllGetTexParameteriv) (GLenum target, GLenum pname, GLint * params);
  83.161 +static void     (APIENTRY * dllHint) (GLenum target, GLenum mode);
  83.162 +
  83.163 +GLboolean(APIENTRY * dllIsEnabled) (GLenum cap);
  83.164 +GLboolean(APIENTRY * dllIsTexture) (GLuint texture);
  83.165 +static void     (APIENTRY * dllLineWidth) (GLfloat width);
  83.166 +static void     (APIENTRY * dllPolygonMode) (GLenum face, GLenum mode);
  83.167 +static void     (APIENTRY * dllPolygonOffset) (GLfloat factor, GLfloat units);
  83.168 +static void     (APIENTRY * dllReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
  83.169 +											GLvoid * pixels);
  83.170 +static void     (APIENTRY * dllScissor) (GLint x, GLint y, GLsizei width, GLsizei height);
  83.171 +static void     (APIENTRY * dllStencilFunc) (GLenum func, GLint ref, GLuint mask);
  83.172 +static void     (APIENTRY * dllStencilMask) (GLuint mask);
  83.173 +static void     (APIENTRY * dllStencilOp) (GLenum fail, GLenum zfail, GLenum zpass);
  83.174 +static void     (APIENTRY * dllTexImage1D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border,
  83.175 +											GLenum format, GLenum type, const GLvoid * pixels);
  83.176 +static void     (APIENTRY * dllTexImage2D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
  83.177 +											GLint border, GLenum format, GLenum type, const GLvoid * pixels);
  83.178 +static void     (APIENTRY * dllTexParameterf) (GLenum target, GLenum pname, GLfloat param);
  83.179 +static void     (APIENTRY * dllTexParameterfv) (GLenum target, GLenum pname, const GLfloat * params);
  83.180 +static void     (APIENTRY * dllTexParameteri) (GLenum target, GLenum pname, GLint param);
  83.181 +static void     (APIENTRY * dllTexParameteriv) (GLenum target, GLenum pname, const GLint * params);
  83.182 +static void     (APIENTRY * dllTexSubImage1D) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format,
  83.183 +											   GLenum type, const GLvoid * pixels);
  83.184 +static void     (APIENTRY * dllTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
  83.185 +											   GLsizei height, GLenum format, GLenum type, const GLvoid * pixels);
  83.186 +static void     (APIENTRY * dllViewport) (GLint x, GLint y, GLsizei width, GLsizei height);
  83.187 +
  83.188 +static FILE    *log_fp = NULL;
  83.189 +
  83.190 +static const char *BooleanToString(GLboolean b)
  83.191 +{
  83.192 +	if(b == GL_FALSE)
  83.193 +		return "GL_FALSE";
  83.194 +	else if(b == GL_TRUE)
  83.195 +		return "GL_TRUE";
  83.196 +	else
  83.197 +		return "OUT OF RANGE FOR BOOLEAN";
  83.198 +}
  83.199 +
  83.200 +static const char *FuncToString(GLenum f)
  83.201 +{
  83.202 +	switch (f)
  83.203 +	{
  83.204 +		case GL_ALWAYS:
  83.205 +			return "GL_ALWAYS";
  83.206 +		case GL_NEVER:
  83.207 +			return "GL_NEVER";
  83.208 +		case GL_LEQUAL:
  83.209 +			return "GL_LEQUAL";
  83.210 +		case GL_LESS:
  83.211 +			return "GL_LESS";
  83.212 +		case GL_EQUAL:
  83.213 +			return "GL_EQUAL";
  83.214 +		case GL_GREATER:
  83.215 +			return "GL_GREATER";
  83.216 +		case GL_GEQUAL:
  83.217 +			return "GL_GEQUAL";
  83.218 +		case GL_NOTEQUAL:
  83.219 +			return "GL_NOTEQUAL";
  83.220 +		default:
  83.221 +			return "!!! UNKNOWN !!!";
  83.222 +	}
  83.223 +}
  83.224 +
  83.225 +static const char *PrimToString(GLenum mode)
  83.226 +{
  83.227 +	static char     prim[1024];
  83.228 +
  83.229 +	if(mode == GL_TRIANGLES)
  83.230 +		strcpy(prim, "GL_TRIANGLES");
  83.231 +	else if(mode == GL_TRIANGLE_STRIP)
  83.232 +		strcpy(prim, "GL_TRIANGLE_STRIP");
  83.233 +	else if(mode == GL_TRIANGLE_FAN)
  83.234 +		strcpy(prim, "GL_TRIANGLE_FAN");
  83.235 +	else if(mode == GL_QUADS)
  83.236 +		strcpy(prim, "GL_QUADS");
  83.237 +	else if(mode == GL_QUAD_STRIP)
  83.238 +		strcpy(prim, "GL_QUAD_STRIP");
  83.239 +	else if(mode == GL_POLYGON)
  83.240 +		strcpy(prim, "GL_POLYGON");
  83.241 +	else if(mode == GL_POINTS)
  83.242 +		strcpy(prim, "GL_POINTS");
  83.243 +	else if(mode == GL_LINES)
  83.244 +		strcpy(prim, "GL_LINES");
  83.245 +	else if(mode == GL_LINE_STRIP)
  83.246 +		strcpy(prim, "GL_LINE_STRIP");
  83.247 +	else if(mode == GL_LINE_LOOP)
  83.248 +		strcpy(prim, "GL_LINE_LOOP");
  83.249 +	else
  83.250 +		sprintf(prim, "0x%x", mode);
  83.251 +
  83.252 +	return prim;
  83.253 +}
  83.254 +
  83.255 +static const char *CapToString(GLenum cap)
  83.256 +{
  83.257 +	static char     buffer[1024];
  83.258 +
  83.259 +	switch (cap)
  83.260 +	{
  83.261 +		case GL_TEXTURE_2D:
  83.262 +			return "GL_TEXTURE_2D";
  83.263 +		case GL_BLEND:
  83.264 +			return "GL_BLEND";
  83.265 +		case GL_DEPTH_TEST:
  83.266 +			return "GL_DEPTH_TEST";
  83.267 +		case GL_CULL_FACE:
  83.268 +			return "GL_CULL_FACE";
  83.269 +		case GL_CLIP_PLANE0:
  83.270 +			return "GL_CLIP_PLANE0";
  83.271 +		case GL_COLOR_ARRAY:
  83.272 +			return "GL_COLOR_ARRAY";
  83.273 +		case GL_TEXTURE_COORD_ARRAY:
  83.274 +			return "GL_TEXTURE_COORD_ARRAY";
  83.275 +		case GL_VERTEX_ARRAY:
  83.276 +			return "GL_VERTEX_ARRAY";
  83.277 +		case GL_ALPHA_TEST:
  83.278 +			return "GL_ALPHA_TEST";
  83.279 +		case GL_STENCIL_TEST:
  83.280 +			return "GL_STENCIL_TEST";
  83.281 +		default:
  83.282 +			sprintf(buffer, "0x%x", cap);
  83.283 +	}
  83.284 +
  83.285 +	return buffer;
  83.286 +}
  83.287 +
  83.288 +static const char *TypeToString(GLenum t)
  83.289 +{
  83.290 +	switch (t)
  83.291 +	{
  83.292 +		case GL_BYTE:
  83.293 +			return "GL_BYTE";
  83.294 +		case GL_UNSIGNED_BYTE:
  83.295 +			return "GL_UNSIGNED_BYTE";
  83.296 +		case GL_SHORT:
  83.297 +			return "GL_SHORT";
  83.298 +		case GL_UNSIGNED_SHORT:
  83.299 +			return "GL_UNSIGNED_SHORT";
  83.300 +		case GL_INT:
  83.301 +			return "GL_INT";
  83.302 +		case GL_UNSIGNED_INT:
  83.303 +			return "GL_UNSIGNED_INT";
  83.304 +		case GL_FLOAT:
  83.305 +			return "GL_FLOAT";
  83.306 +		case GL_DOUBLE:
  83.307 +			return "GL_DOUBLE";
  83.308 +		default:
  83.309 +			return "!!! UNKNOWN !!!";
  83.310 +	}
  83.311 +}
  83.312 +
  83.313 +static void APIENTRY logBindTexture(GLenum target, GLuint texture)
  83.314 +{
  83.315 +	fprintf(log_fp, "glBindTexture( 0x%x, %u )\n", target, texture);
  83.316 +	dllBindTexture(target, texture);
  83.317 +}
  83.318 +
  83.319 +static void BlendToName(char *n, GLenum f)
  83.320 +{
  83.321 +	switch (f)
  83.322 +	{
  83.323 +		case GL_ONE:
  83.324 +			strcpy(n, "GL_ONE");
  83.325 +			break;
  83.326 +		case GL_ZERO:
  83.327 +			strcpy(n, "GL_ZERO");
  83.328 +			break;
  83.329 +		case GL_SRC_ALPHA:
  83.330 +			strcpy(n, "GL_SRC_ALPHA");
  83.331 +			break;
  83.332 +		case GL_ONE_MINUS_SRC_ALPHA:
  83.333 +			strcpy(n, "GL_ONE_MINUS_SRC_ALPHA");
  83.334 +			break;
  83.335 +		case GL_DST_COLOR:
  83.336 +			strcpy(n, "GL_DST_COLOR");
  83.337 +			break;
  83.338 +		case GL_ONE_MINUS_DST_COLOR:
  83.339 +			strcpy(n, "GL_ONE_MINUS_DST_COLOR");
  83.340 +			break;
  83.341 +		case GL_DST_ALPHA:
  83.342 +			strcpy(n, "GL_DST_ALPHA");
  83.343 +			break;
  83.344 +		default:
  83.345 +			sprintf(n, "0x%x", f);
  83.346 +	}
  83.347 +}
  83.348 +static void APIENTRY logBlendFunc(GLenum sfactor, GLenum dfactor)
  83.349 +{
  83.350 +	char            sf[128], df[128];
  83.351 +
  83.352 +	BlendToName(sf, sfactor);
  83.353 +	BlendToName(df, dfactor);
  83.354 +
  83.355 +	fprintf(log_fp, "glBlendFunc( %s, %s )\n", sf, df);
  83.356 +	dllBlendFunc(sfactor, dfactor);
  83.357 +}
  83.358 +
  83.359 +static void APIENTRY logClear(GLbitfield mask)
  83.360 +{
  83.361 +	fprintf(log_fp, "glClear( 0x%x = ", mask);
  83.362 +
  83.363 +	if(mask & GL_COLOR_BUFFER_BIT)
  83.364 +		fprintf(log_fp, "GL_COLOR_BUFFER_BIT ");
  83.365 +	if(mask & GL_DEPTH_BUFFER_BIT)
  83.366 +		fprintf(log_fp, "GL_DEPTH_BUFFER_BIT ");
  83.367 +	if(mask & GL_STENCIL_BUFFER_BIT)
  83.368 +		fprintf(log_fp, "GL_STENCIL_BUFFER_BIT ");
  83.369 +	if(mask & GL_ACCUM_BUFFER_BIT)
  83.370 +		fprintf(log_fp, "GL_ACCUM_BUFFER_BIT ");
  83.371 +
  83.372 +	fprintf(log_fp, ")\n");
  83.373 +	dllClear(mask);
  83.374 +}
  83.375 +
  83.376 +static void APIENTRY logClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
  83.377 +{
  83.378 +	fprintf(log_fp, "glClearColor\n");
  83.379 +	dllClearColor(red, green, blue, alpha);
  83.380 +}
  83.381 +
  83.382 +static void APIENTRY logClearDepth(GLclampd depth)
  83.383 +{
  83.384 +	fprintf(log_fp, "glClearDepth( %f )\n", (float)depth);
  83.385 +	dllClearDepth(depth);
  83.386 +}
  83.387 +
  83.388 +static void APIENTRY logClearStencil(GLint s)
  83.389 +{
  83.390 +	fprintf(log_fp, "glClearStencil( %d )\n", s);
  83.391 +	dllClearStencil(s);
  83.392 +}
  83.393 +
  83.394 +
  83.395 +
  83.396 +#define SIG( x ) fprintf( log_fp, x "\n" )
  83.397 +
  83.398 +
  83.399 +static void APIENTRY logColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
  83.400 +{
  83.401 +	SIG("glColorMask");
  83.402 +	dllColorMask(red, green, blue, alpha);
  83.403 +}
  83.404 +
  83.405 +static void APIENTRY logCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
  83.406 +{
  83.407 +	SIG("glCopyPixels");
  83.408 +	dllCopyPixels(x, y, width, height, type);
  83.409 +}
  83.410 +
  83.411 +static void APIENTRY logCopyTexImage1D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width,
  83.412 +									   GLint border)
  83.413 +{
  83.414 +	SIG("glCopyTexImage1D");
  83.415 +	dllCopyTexImage1D(target, level, internalFormat, x, y, width, border);
  83.416 +}
  83.417 +
  83.418 +static void APIENTRY logCopyTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width,
  83.419 +									   GLsizei height, GLint border)
  83.420 +{
  83.421 +	SIG("glCopyTexImage2D");
  83.422 +	dllCopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
  83.423 +}
  83.424 +
  83.425 +static void APIENTRY logCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width)
  83.426 +{
  83.427 +	SIG("glCopyTexSubImage1D");
  83.428 +	dllCopyTexSubImage1D(target, level, xoffset, x, y, width);
  83.429 +}
  83.430 +
  83.431 +static void APIENTRY logCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
  83.432 +										  GLsizei width, GLsizei height)
  83.433 +{
  83.434 +	SIG("glCopyTexSubImage2D");
  83.435 +	dllCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
  83.436 +}
  83.437 +
  83.438 +static void APIENTRY logCullFace(GLenum mode)
  83.439 +{
  83.440 +	fprintf(log_fp, "glCullFace( %s )\n", (mode == GL_FRONT) ? "GL_FRONT" : "GL_BACK");
  83.441 +	dllCullFace(mode);
  83.442 +}
  83.443 +
  83.444 +static void APIENTRY logDeleteTextures(GLsizei n, const GLuint * textures)
  83.445 +{
  83.446 +	SIG("glDeleteTextures");
  83.447 +	dllDeleteTextures(n, textures);
  83.448 +}
  83.449 +
  83.450 +static void APIENTRY logDepthFunc(GLenum func)
  83.451 +{
  83.452 +	fprintf(log_fp, "glDepthFunc( %s )\n", FuncToString(func));
  83.453 +	dllDepthFunc(func);
  83.454 +}
  83.455 +
  83.456 +static void APIENTRY logDepthMask(GLboolean flag)
  83.457 +{
  83.458 +	fprintf(log_fp, "glDepthMask( %s )\n", BooleanToString(flag));
  83.459 +	dllDepthMask(flag);
  83.460 +}
  83.461 +
  83.462 +static void APIENTRY logDepthRange(GLclampd zNear, GLclampd zFar)
  83.463 +{
  83.464 +	fprintf(log_fp, "glDepthRange( %f, %f )\n", (float)zNear, (float)zFar);
  83.465 +	dllDepthRange(zNear, zFar);
  83.466 +}
  83.467 +
  83.468 +static void APIENTRY logDisable(GLenum cap)
  83.469 +{
  83.470 +	fprintf(log_fp, "glDisable( %s )\n", CapToString(cap));
  83.471 +	dllDisable(cap);
  83.472 +}
  83.473 +
  83.474 +static void APIENTRY logDrawArrays(GLenum mode, GLint first, GLsizei count)
  83.475 +{
  83.476 +	SIG("glDrawArrays");
  83.477 +	dllDrawArrays(mode, first, count);
  83.478 +}
  83.479 +
  83.480 +static void APIENTRY logDrawBuffer(GLenum mode)
  83.481 +{
  83.482 +	SIG("glDrawBuffer");
  83.483 +	dllDrawBuffer(mode);
  83.484 +}
  83.485 +
  83.486 +static void APIENTRY logDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
  83.487 +{
  83.488 +	fprintf(log_fp, "glDrawElements( %s, %d, %s, MEM )\n", PrimToString(mode), count, TypeToString(type));
  83.489 +	dllDrawElements(mode, count, type, indices);
  83.490 +}
  83.491 +
  83.492 +static void APIENTRY logEnable(GLenum cap)
  83.493 +{
  83.494 +	fprintf(log_fp, "glEnable( %s )\n", CapToString(cap));
  83.495 +	dllEnable(cap);
  83.496 +}
  83.497 +
  83.498 +static void APIENTRY logFinish(void)
  83.499 +{
  83.500 +	SIG("glFinish");
  83.501 +	dllFinish();
  83.502 +}
  83.503 +
  83.504 +static void APIENTRY logFlush(void)
  83.505 +{
  83.506 +	SIG("glFlush");
  83.507 +	dllFlush();
  83.508 +}
  83.509 +
  83.510 +static void APIENTRY logFrontFace(GLenum mode)
  83.511 +{
  83.512 +	SIG("glFrontFace");
  83.513 +	dllFrontFace(mode);
  83.514 +}
  83.515 +
  83.516 +static void APIENTRY logGenTextures(GLsizei n, GLuint * textures)
  83.517 +{
  83.518 +	SIG("glGenTextures");
  83.519 +	dllGenTextures(n, textures);
  83.520 +}
  83.521 +
  83.522 +static void APIENTRY logGetBooleanv(GLenum pname, GLboolean * params)
  83.523 +{
  83.524 +	SIG("glGetBooleanv");
  83.525 +	dllGetBooleanv(pname, params);
  83.526 +}
  83.527 +
  83.528 +static GLenum APIENTRY logGetError(void)
  83.529 +{
  83.530 +	SIG("glGetError");
  83.531 +	return dllGetError();
  83.532 +}
  83.533 +
  83.534 +static void APIENTRY logGetFloatv(GLenum pname, GLfloat * params)
  83.535 +{
  83.536 +	SIG("glGetFloatv");
  83.537 +	dllGetFloatv(pname, params);
  83.538 +}
  83.539 +
  83.540 +static void APIENTRY logGetIntegerv(GLenum pname, GLint * params)
  83.541 +{
  83.542 +	SIG("glGetIntegerv");
  83.543 +	dllGetIntegerv(pname, params);
  83.544 +}
  83.545 +
  83.546 +static const GLubyte *APIENTRY logGetString(GLenum name)
  83.547 +{
  83.548 +	SIG("glGetString");
  83.549 +	return dllGetString(name);
  83.550 +}
  83.551 +
  83.552 +static void APIENTRY logGetTexParameterfv(GLenum target, GLenum pname, GLfloat * params)
  83.553 +{
  83.554 +	SIG("glGetTexParameterfv");
  83.555 +	dllGetTexParameterfv(target, pname, params);
  83.556 +}
  83.557 +
  83.558 +static void APIENTRY logGetTexParameteriv(GLenum target, GLenum pname, GLint * params)
  83.559 +{
  83.560 +	SIG("glGetTexParameteriv");
  83.561 +	dllGetTexParameteriv(target, pname, params);
  83.562 +}
  83.563 +
  83.564 +static void APIENTRY logHint(GLenum target, GLenum mode)
  83.565 +{
  83.566 +	fprintf(log_fp, "glHint( 0x%x, 0x%x )\n", target, mode);
  83.567 +	dllHint(target, mode);
  83.568 +}
  83.569 +
  83.570 +static GLboolean APIENTRY logIsEnabled(GLenum cap)
  83.571 +{
  83.572 +	SIG("glIsEnabled");
  83.573 +	return dllIsEnabled(cap);
  83.574 +}
  83.575 +
  83.576 +static GLboolean APIENTRY logIsTexture(GLuint texture)
  83.577 +{
  83.578 +	SIG("glIsTexture");
  83.579 +	return dllIsTexture(texture);
  83.580 +}
  83.581 +
  83.582 +static void APIENTRY logLineWidth(GLfloat width)
  83.583 +{
  83.584 +	SIG("glLineWidth");
  83.585 +	dllLineWidth(width);
  83.586 +}
  83.587 +
  83.588 +static void APIENTRY logPolygonMode(GLenum face, GLenum mode)
  83.589 +{
  83.590 +	fprintf(log_fp, "glPolygonMode( 0x%x, 0x%x )\n", face, mode);
  83.591 +	dllPolygonMode(face, mode);
  83.592 +}
  83.593 +
  83.594 +static void APIENTRY logPolygonOffset(GLfloat factor, GLfloat units)
  83.595 +{
  83.596 +	SIG("glPolygonOffset");
  83.597 +	dllPolygonOffset(factor, units);
  83.598 +}
  83.599 +
  83.600 +static void APIENTRY logReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels)
  83.601 +{
  83.602 +	SIG("glReadPixels");
  83.603 +	dllReadPixels(x, y, width, height, format, type, pixels);
  83.604 +}
  83.605 +
  83.606 +static void APIENTRY logScissor(GLint x, GLint y, GLsizei width, GLsizei height)
  83.607 +{
  83.608 +	fprintf(log_fp, "glScissor( %d, %d, %d, %d )\n", x, y, width, height);
  83.609 +	dllScissor(x, y, width, height);
  83.610 +}
  83.611 +
  83.612 +static void APIENTRY logStencilFunc(GLenum func, GLint ref, GLuint mask)
  83.613 +{
  83.614 +	SIG("glStencilFunc");
  83.615 +	dllStencilFunc(func, ref, mask);
  83.616 +}
  83.617 +
  83.618 +static void APIENTRY logStencilMask(GLuint mask)
  83.619 +{
  83.620 +	SIG("glStencilMask");
  83.621 +	dllStencilMask(mask);
  83.622 +}
  83.623 +
  83.624 +static void APIENTRY logStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
  83.625 +{
  83.626 +	SIG("glStencilOp");
  83.627 +	dllStencilOp(fail, zfail, zpass);
  83.628 +}
  83.629 +
  83.630 +static void APIENTRY logTexImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format,
  83.631 +								   GLenum type, const void *pixels)
  83.632 +{
  83.633 +	SIG("glTexImage1D");
  83.634 +	dllTexImage1D(target, level, internalformat, width, border, format, type, pixels);
  83.635 +}
  83.636 +static void APIENTRY logTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border,
  83.637 +								   GLenum format, GLenum type, const void *pixels)
  83.638 +{
  83.639 +	SIG("glTexImage2D");
  83.640 +	dllTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
  83.641 +}
  83.642 +
  83.643 +static void APIENTRY logTexParameterf(GLenum target, GLenum pname, GLfloat param)
  83.644 +{
  83.645 +	fprintf(log_fp, "glTexParameterf( 0x%x, 0x%x, %f )\n", target, pname, param);
  83.646 +	dllTexParameterf(target, pname, param);
  83.647 +}
  83.648 +
  83.649 +static void APIENTRY logTexParameterfv(GLenum target, GLenum pname, const GLfloat * params)
  83.650 +{
  83.651 +	SIG("glTexParameterfv");
  83.652 +	dllTexParameterfv(target, pname, params);
  83.653 +}
  83.654 +
  83.655 +static void APIENTRY logTexParameteri(GLenum target, GLenum pname, GLint param)
  83.656 +{
  83.657 +	fprintf(log_fp, "glTexParameteri( 0x%x, 0x%x, 0x%x )\n", target, pname, param);
  83.658 +	dllTexParameteri(target, pname, param);
  83.659 +}
  83.660 +
  83.661 +static void APIENTRY logTexParameteriv(GLenum target, GLenum pname, const GLint * params)
  83.662 +{
  83.663 +	SIG("glTexParameteriv");
  83.664 +	dllTexParameteriv(target, pname, params);
  83.665 +}
  83.666 +
  83.667 +static void APIENTRY logTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type,
  83.668 +									  const void *pixels)
  83.669 +{
  83.670 +	SIG("glTexSubImage1D");
  83.671 +	dllTexSubImage1D(target, level, xoffset, width, format, type, pixels);
  83.672 +}
  83.673 +
  83.674 +static void APIENTRY logTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
  83.675 +									  GLenum format, GLenum type, const void *pixels)
  83.676 +{
  83.677 +	SIG("glTexSubImage2D");
  83.678 +	dllTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
  83.679 +}
  83.680 +
  83.681 +static void APIENTRY logViewport(GLint x, GLint y, GLsizei width, GLsizei height)
  83.682 +{
  83.683 +	fprintf(log_fp, "glViewport( %d, %d, %d, %d )\n", x, y, width, height);
  83.684 +	dllViewport(x, y, width, height);
  83.685 +}
  83.686 +
  83.687 +/*
  83.688 +** QGL_Shutdown
  83.689 +**
  83.690 +** Unloads the specified DLL then nulls out all the proc pointers.  This
  83.691 +** is only called during a hard shutdown of the OGL subsystem (e.g. vid_restart).
  83.692 +*/
  83.693 +// *INDENT-OFF*
  83.694 +void QGL_Shutdown(void)
  83.695 +{
  83.696 +	ri.Printf(PRINT_ALL, "...shutting down QGL\n");
  83.697 +
  83.698 +	qglBindTexture               = NULL;
  83.699 +	qglBlendFunc                 = NULL;
  83.700 +	qglClear                     = NULL;
  83.701 +	qglClearColor                = NULL;
  83.702 +	qglClearDepth                = NULL;
  83.703 +	qglClearStencil              = NULL;
  83.704 +	qglColorMask                 = NULL;
  83.705 +	qglCopyPixels                = NULL;
  83.706 +	qglCopyTexImage1D            = NULL;
  83.707 +	qglCopyTexImage2D            = NULL;
  83.708 +	qglCopyTexSubImage1D         = NULL;
  83.709 +	qglCopyTexSubImage2D         = NULL;
  83.710 +	qglCullFace                  = NULL;
  83.711 +	qglDeleteTextures            = NULL;
  83.712 +	qglDepthFunc                 = NULL;
  83.713 +	qglDepthMask                 = NULL;
  83.714 +	qglDepthRange                = NULL;
  83.715 +	qglDisable                   = NULL;
  83.716 +	qglDrawArrays                = NULL;
  83.717 +	qglDrawBuffer                = NULL;
  83.718 +	qglDrawElements              = NULL;
  83.719 +	qglEnable                    = NULL;
  83.720 +	qglFinish                    = NULL;
  83.721 +	qglFlush                     = NULL;
  83.722 +	qglFrontFace                 = NULL;
  83.723 +	qglGenTextures               = NULL;
  83.724 +	qglGetBooleanv               = NULL;
  83.725 +	qglGetError                  = NULL;
  83.726 +	qglGetFloatv                 = NULL;
  83.727 +	qglGetIntegerv               = NULL;
  83.728 +	qglGetString                 = NULL;
  83.729 +	qglGetTexParameterfv         = NULL;
  83.730 +	qglGetTexParameteriv         = NULL;
  83.731 +	qglHint                      = NULL;
  83.732 +	qglIsEnabled                 = NULL;
  83.733 +	qglIsTexture                 = NULL;
  83.734 +	qglLineWidth                 = NULL;
  83.735 +	qglPolygonMode               = NULL;
  83.736 +	qglPolygonOffset             = NULL;
  83.737 +	qglReadPixels                = NULL;
  83.738 +	qglScissor                   = NULL;
  83.739 +	qglStencilFunc               = NULL;
  83.740 +	qglStencilMask               = NULL;
  83.741 +	qglStencilOp                 = NULL;
  83.742 +	qglTexImage1D                = NULL;
  83.743 +	qglTexImage2D                = NULL;
  83.744 +	qglTexParameterf             = NULL;
  83.745 +	qglTexParameterfv            = NULL;
  83.746 +	qglTexParameteri             = NULL;
  83.747 +	qglTexParameteriv            = NULL;
  83.748 +	qglTexSubImage1D             = NULL;
  83.749 +	qglTexSubImage2D             = NULL;
  83.750 +	qglViewport                  = NULL;
  83.751 +}
  83.752 +// *INDENT-ON*
  83.753 +
  83.754 +#define GPA(a) SDL_GL_GetProcAddress(a)
  83.755 +
  83.756 +qboolean GLimp_sdl_init_video(void)
  83.757 +{
  83.758 +	if(!SDL_WasInit(SDL_INIT_VIDEO))
  83.759 +	{
  83.760 +		ri.Printf(PRINT_ALL, "Calling SDL_Init(SDL_INIT_VIDEO)...\n");
  83.761 +		if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) == -1)
  83.762 +		{
  83.763 +			ri.Printf(PRINT_ALL, "SDL_Init(SDL_INIT_VIDEO) failed: %s\n", SDL_GetError());
  83.764 +			return qfalse;
  83.765 +		}
  83.766 +		ri.Printf(PRINT_ALL, "SDL_Init(SDL_INIT_VIDEO) passed.\n");
  83.767 +	}
  83.768 +
  83.769 +	return qtrue;
  83.770 +}
  83.771 +
  83.772 +/*
  83.773 +** QGL_Init
  83.774 +**
  83.775 +** This is responsible for binding our qgl function pointers to
  83.776 +** the appropriate GL stuff.  In Windows this means doing a
  83.777 +** LoadLibrary and a bunch of calls to GetProcAddress.  On other
  83.778 +** operating systems we need to do the right thing, whatever that
  83.779 +** might be.
  83.780 +*/
  83.781 +// *INDENT-OFF*
  83.782 +int QGL_Init()
  83.783 +{
  83.784 +	ri.Printf(PRINT_ALL, "...initializing QGL\n");
  83.785 +
  83.786 +	if(GLimp_sdl_init_video() == qfalse)
  83.787 +		return qfalse;
  83.788 +
  83.789 +	qglBindTexture               = dllBindTexture = GPA( "glBindTexture" );
  83.790 +	qglBlendFunc                 = dllBlendFunc = GPA( "glBlendFunc" );
  83.791 +	qglClear                     = dllClear = GPA( "glClear" );
  83.792 +	qglClearColor                = dllClearColor = GPA( "glClearColor" );
  83.793 +	qglClearDepth                = dllClearDepth = GPA( "glClearDepth" );
  83.794 +	qglClearStencil              = dllClearStencil = GPA( "glClearStencil" );
  83.795 +	qglColorMask                 = dllColorMask = GPA( "glColorMask" );
  83.796 +	qglCopyPixels                = dllCopyPixels = GPA( "glCopyPixels" );
  83.797 +	qglCopyTexImage1D            = dllCopyTexImage1D = GPA( "glCopyTexImage1D" );
  83.798 +	qglCopyTexImage2D            = dllCopyTexImage2D = GPA( "glCopyTexImage2D" );
  83.799 +	qglCopyTexSubImage1D         = dllCopyTexSubImage1D = GPA( "glCopyTexSubImage1D" );
  83.800 +	qglCopyTexSubImage2D         = dllCopyTexSubImage2D = GPA( "glCopyTexSubImage2D" );
  83.801 +	qglCullFace                  = dllCullFace = GPA( "glCullFace" );
  83.802 +	qglDeleteTextures            = dllDeleteTextures = GPA( "glDeleteTextures" );
  83.803 +	qglDepthFunc                 = dllDepthFunc = GPA( "glDepthFunc" );
  83.804 +	qglDepthMask                 = dllDepthMask = GPA( "glDepthMask" );
  83.805 +	qglDepthRange                = dllDepthRange = GPA( "glDepthRange" );
  83.806 +	qglDisable                   = dllDisable = GPA( "glDisable" );
  83.807 +	qglDrawArrays                = dllDrawArrays = GPA( "glDrawArrays" );
  83.808 +	qglDrawBuffer                = dllDrawBuffer = GPA( "glDrawBuffer" );
  83.809 +	qglDrawElements              = dllDrawElements = GPA( "glDrawElements" );
  83.810 +	qglEnable                    = dllEnable                    = GPA( "glEnable" );
  83.811 +	qglFinish                    = dllFinish                    = GPA( "glFinish" );
  83.812 +	qglFlush                     = dllFlush                     = GPA( "glFlush" );
  83.813 +	qglFrontFace                 = dllFrontFace                 = GPA( "glFrontFace" );
  83.814 +	qglGenTextures               = dllGenTextures               = GPA( "glGenTextures" );
  83.815 +	qglGetBooleanv               = dllGetBooleanv               = GPA( "glGetBooleanv" );
  83.816 +	qglGetError                  = dllGetError                  = GPA( "glGetError" );
  83.817 +	qglGetFloatv                 = dllGetFloatv                 = GPA( "glGetFloatv" );
  83.818 +	qglGetIntegerv               = dllGetIntegerv               = GPA( "glGetIntegerv" );
  83.819 +	qglGetString                 = dllGetString                 = GPA( "glGetString" );
  83.820 +	qglGetTexParameterfv         = dllGetTexParameterfv         = GPA( "glGetTexParameterfv" );
  83.821 +	qglGetTexParameteriv         = dllGetTexParameteriv         = GPA( "glGetTexParameteriv" );
  83.822 +	qglHint                      = dllHint                      = GPA( "glHint" );
  83.823 +	qglIsEnabled                 = dllIsEnabled                 = GPA( "glIsEnabled" );
  83.824 +	qglIsTexture                 = dllIsTexture                 = GPA( "glIsTexture" );
  83.825 +	qglLineWidth                 = dllLineWidth                 = GPA( "glLineWidth" );
  83.826 +	qglPolygonMode               = dllPolygonMode               = GPA( "glPolygonMode" );
  83.827 +	qglPolygonOffset             = dllPolygonOffset             = GPA( "glPolygonOffset" );
  83.828 +	qglReadPixels                = dllReadPixels                = GPA( "glReadPixels" );
  83.829 +	qglScissor                   = dllScissor                   = GPA( "glScissor" );
  83.830 +	qglStencilFunc               = dllStencilFunc               = GPA( "glStencilFunc" );
  83.831 +	qglStencilMask               = dllStencilMask               = GPA( "glStencilMask" );
  83.832 +	qglStencilOp                 = dllStencilOp                 = GPA( "glStencilOp" );
  83.833 +	qglTexImage1D                = dllTexImage1D                = GPA( "glTexImage1D" );
  83.834 +	qglTexImage2D                = dllTexImage2D                = GPA( "glTexImage2D" );
  83.835 +	qglTexParameterf             = dllTexParameterf             = GPA( "glTexParameterf" );
  83.836 +	qglTexParameterfv            = dllTexParameterfv            = GPA( "glTexParameterfv" );
  83.837 +	qglTexParameteri             = dllTexParameteri             = GPA( "glTexParameteri" );
  83.838 +	qglTexParameteriv            = dllTexParameteriv            = GPA( "glTexParameteriv" );
  83.839 +	qglTexSubImage1D             = dllTexSubImage1D             = GPA( "glTexSubImage1D" );
  83.840 +	qglTexSubImage2D             = dllTexSubImage2D             = GPA( "glTexSubImage2D" );
  83.841 +	qglViewport                  = dllViewport                  = GPA( "glViewport" );
  83.842 +
  83.843 +	// check logging
  83.844 +	QGL_EnableLogging(r_logFile->integer);
  83.845 +
  83.846 +	return qtrue;
  83.847 +}
  83.848 +// *INDENT-ON*
  83.849 +
  83.850 +// *INDENT-OFF*
  83.851 +void QGL_EnableLogging(int enable)
  83.852 +{
  83.853 +	// fixed for new countdown
  83.854 +	static qboolean isEnabled = qfalse;	// init
  83.855 +
  83.856 +	// return if we're already active
  83.857 +	if(isEnabled && enable)
  83.858 +	{
  83.859 +		// decrement log counter and stop if it has reached 0
  83.860 +		ri.Cvar_Set("r_logFile", va("%d", r_logFile->integer - 1));
  83.861 +		if(r_logFile->integer)
  83.862 +		{
  83.863 +			return;
  83.864 +		}
  83.865 +		enable = qfalse;
  83.866 +	}
  83.867 +
  83.868 +	// return if we're already disabled
  83.869 +	if(!enable && !isEnabled)
  83.870 +		return;
  83.871 +
  83.872 +	isEnabled = enable;
  83.873 +
  83.874 +	// old code starts here
  83.875 +	if(enable)
  83.876 +	{
  83.877 +		if(!log_fp)
  83.878 +		{
  83.879 +			struct tm      *newtime;
  83.880 +			time_t          aclock;
  83.881 +			char            buffer[1024];
  83.882 +			cvar_t         *basedir;
  83.883 +
  83.884 +			time(&aclock);
  83.885 +			newtime = localtime(&aclock);
  83.886 +
  83.887 +			asctime(newtime);
  83.888 +
  83.889 +			basedir = ri.Cvar_Get("fs_basepath", "", 0);	// FIXME: userdir?
  83.890 +			assert(basedir);
  83.891 +			Com_sprintf(buffer, sizeof(buffer), "%s/gl.log", basedir->string);
  83.892 +			log_fp = fopen(buffer, "wt");
  83.893 +			assert(log_fp);
  83.894 +			ri.Printf(PRINT_ALL, "QGL_EnableLogging(%d): writing %s\n", r_logFile->integer, buffer);
  83.895 +
  83.896 +			fprintf(log_fp, "%s\n", asctime(newtime));
  83.897 +		}
  83.898 +
  83.899 +		qglBindTexture               = logBindTexture;
  83.900 +		qglBlendFunc                 = logBlendFunc;
  83.901 +		qglClear                     = logClear;
  83.902 +		qglClearColor                = logClearColor;
  83.903 +		qglClearDepth                = logClearDepth;
  83.904 +		qglClearStencil              = logClearStencil;
  83.905 +		qglColorMask                 = logColorMask;
  83.906 +		qglCopyPixels                = logCopyPixels;
  83.907 +		qglCopyTexImage1D            = logCopyTexImage1D;
  83.908 +		qglCopyTexImage2D            = logCopyTexImage2D;
  83.909 +		qglCopyTexSubImage1D         = logCopyTexSubImage1D;
  83.910 +		qglCopyTexSubImage2D         = logCopyTexSubImage2D;
  83.911 +		qglCullFace                  = logCullFace;
  83.912 +		qglDeleteTextures            = logDeleteTextures;
  83.913 +		qglDepthFunc                 = logDepthFunc;
  83.914 +		qglDepthMask                 = logDepthMask;
  83.915 +		qglDepthRange                = logDepthRange;
  83.916 +		qglDisable                   = logDisable;
  83.917 +		qglDrawArrays                = logDrawArrays;
  83.918 +		qglDrawBuffer                = logDrawBuffer;
  83.919 +		qglDrawElements              = logDrawElements;
  83.920 +		qglEnable                    = logEnable;
  83.921 +		qglFinish                    = logFinish;
  83.922 +		qglFlush                     = logFlush;
  83.923 +		qglFrontFace                 = logFrontFace;
  83.924 +		qglGenTextures               = logGenTextures;
  83.925 +		qglGetBooleanv               = logGetBooleanv;
  83.926 +		qglGetError                  = logGetError;
  83.927 +		qglGetFloatv                 = logGetFloatv;
  83.928 +		qglGetIntegerv               = logGetIntegerv;
  83.929 +		qglGetString                 = logGetString;
  83.930 +		qglGetTexParameterfv         = logGetTexParameterfv;
  83.931 +		qglGetTexParameteriv         = logGetTexParameteriv;
  83.932 +		qglHint                      = logHint;
  83.933 +		qglIsEnabled                 = logIsEnabled;
  83.934 +		qglIsTexture                 = logIsTexture;
  83.935 +		qglLineWidth                 = logLineWidth;
  83.936 +		qglPolygonMode               = logPolygonMode;
  83.937 +		qglPolygonOffset             = logPolygonOffset;
  83.938 +		qglReadPixels                = logReadPixels;
  83.939 +		qglScissor                   = logScissor;
  83.940 +		qglStencilFunc               = logStencilFunc;
  83.941 +		qglStencilMask               = logStencilMask;
  83.942 +		qglStencilOp                 = logStencilOp;
  83.943 +		qglTexImage1D                = logTexImage1D;
  83.944 +		qglTexImage2D                = logTexImage2D;
  83.945 +		qglTexParameterf             = logTexParameterf;
  83.946 +		qglTexParameterfv            = logTexParameterfv;
  83.947 +		qglTexParameteri             = logTexParameteri;
  83.948 +		qglTexParameteriv            = logTexParameteriv;
  83.949 +		qglTexSubImage1D             = logTexSubImage1D;
  83.950 +		qglTexSubImage2D             = logTexSubImage2D;
  83.951 +		qglViewport                  = logViewport;
  83.952 +	}
  83.953 +	else
  83.954 +	{
  83.955 +		if(log_fp)
  83.956 +		{
  83.957 +			fprintf(log_fp, "*** CLOSING LOG ***\n");
  83.958 +			fclose(log_fp);
  83.959 +			log_fp = NULL;
  83.960 +		}
  83.961 +		qglBindTexture               = dllBindTexture;
  83.962 +		qglBlendFunc                 = dllBlendFunc;
  83.963 +		qglClear                     = dllClear;
  83.964 +		qglClearColor                = dllClearColor;
  83.965 +		qglClearDepth                = dllClearDepth;
  83.966 +		qglClearStencil              = dllClearStencil;
  83.967 +		qglColorMask                 = dllColorMask;
  83.968 +		qglCopyPixels                = dllCopyPixels;
  83.969 +		qglCopyTexImage1D            = dllCopyTexImage1D;
  83.970 +		qglCopyTexImage2D            = dllCopyTexImage2D;
  83.971 +		qglCopyTexSubImage1D         = dllCopyTexSubImage1D;
  83.972 +		qglCopyTexSubImage2D         = dllCopyTexSubImage2D;
  83.973 +		qglCullFace                  = dllCullFace;
  83.974 +		qglDeleteTextures            = dllDeleteTextures;
  83.975 +		qglDepthFunc                 = dllDepthFunc;
  83.976 +		qglDepthMask                 = dllDepthMask;
  83.977 +		qglDepthRange                = dllDepthRange;
  83.978 +		qglDisable                   = dllDisable;
  83.979 +		qglDrawArrays                = dllDrawArrays;
  83.980 +		qglDrawBuffer                = dllDrawBuffer;
  83.981 +		qglDrawElements              = dllDrawElements;
  83.982 +		qglEnable                    = dllEnable;
  83.983 +		qglFinish                    = dllFinish;
  83.984 +		qglFlush                     = dllFlush;
  83.985 +		qglFrontFace                 = dllFrontFace;
  83.986 +		qglGenTextures               = dllGenTextures;
  83.987 +		qglGetBooleanv               = dllGetBooleanv;
  83.988 +		qglGetError                  = dllGetError;
  83.989 +		qglGetFloatv                 = dllGetFloatv;
  83.990 +		qglGetIntegerv               = dllGetIntegerv;
  83.991 +		qglGetString                 = dllGetString;
  83.992 +		qglGetTexParameterfv         = dllGetTexParameterfv;
  83.993 +		qglGetTexParameteriv         = dllGetTexParameteriv;
  83.994 +		qglHint                      = dllHint;
  83.995 +		qglIsEnabled                 = dllIsEnabled;
  83.996 +		qglIsTexture                 = dllIsTexture;
  83.997 +		qglLineWidth                 = dllLineWidth;
  83.998 +		qglPolygonMode               = dllPolygonMode;
  83.999 +		qglPolygonOffset             = dllPolygonOffset;
 83.1000 +		qglReadPixels                = dllReadPixels;
 83.1001 +		qglScissor                   = dllScissor;
 83.1002 +		qglStencilFunc               = dllStencilFunc;
 83.1003 +		qglStencilMask               = dllStencilMask;
 83.1004 +		qglStencilOp                 = dllStencilOp;
 83.1005 +		qglTexImage1D                = dllTexImage1D;
 83.1006 +		qglTexImage2D                = dllTexImage2D;
 83.1007 +		qglTexParameterf             = dllTexParameterf;
 83.1008 +		qglTexParameterfv            = dllTexParameterfv;
 83.1009 +		qglTexParameteri             = dllTexParameteri;
 83.1010 +		qglTexParameteriv            = dllTexParameteriv;
 83.1011 +		qglTexSubImage1D             = dllTexSubImage1D ;
 83.1012 +		qglTexSubImage2D             = dllTexSubImage2D;
 83.1013 +		qglViewport                  = dllViewport;
 83.1014 +	}
 83.1015 +}
 83.1016 +// *INDENT-ON*
 83.1017 +
 83.1018 +
 83.1019 +/*
 83.1020 +===============
 83.1021 +GLimp_LogComment
 83.1022 +===============
 83.1023 +*/
 83.1024 +void GLimp_LogComment(char *comment)
 83.1025 +{
 83.1026 +	if(log_fp)
 83.1027 +	{
 83.1028 +		fprintf(log_fp, "%s", comment);
 83.1029 +	}
 83.1030 +}
 83.1031 +
 83.1032 +#ifdef _MSC_VER
 83.1033 +#pragma warning (default : 4113 4133 4047 )
 83.1034 +#endif
    84.1 --- a/src/renderer/qgl.h	Sat Jun 06 03:54:16 2009 +0800
    84.2 +++ b/src/renderer/qgl.h	Wed Jun 10 09:31:46 2009 +0800
    84.3 @@ -1,377 +1,386 @@
    84.4  /*
    84.5  ===========================================================================
    84.6  Copyright (C) 1999-2005 Id Software, Inc.
    84.7 -Copyright (C) 2000-2006 Tim Angus
    84.8 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    84.9  
   84.10 -This file is part of Tremfusion.
   84.11 +This file is part of XreaL source code.
   84.12  
   84.13 -Tremfusion is free software; you can redistribute it
   84.14 +XreaL source code is free software; you can redistribute it
   84.15  and/or modify it under the terms of the GNU General Public License as
   84.16  published by the Free Software Foundation; either version 2 of the License,
   84.17  or (at your option) any later version.
   84.18  
   84.19 -Tremfusion is distributed in the hope that it will be
   84.20 +XreaL source code is distributed in the hope that it will be
   84.21  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   84.22  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   84.23  GNU General Public License for more details.
   84.24  
   84.25  You should have received a copy of the GNU General Public License
   84.26 -along with Tremfusion; if not, write to the Free Software
   84.27 +along with XreaL source code; if not, write to the Free Software
   84.28  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   84.29  ===========================================================================
   84.30  */
   84.31 -/*
   84.32 -** QGL.H
   84.33 -*/
   84.34  
   84.35 +// qgl.h
   84.36  #ifndef __QGL_H__
   84.37  #define __QGL_H__
   84.38  
   84.39 -#include <SDL_opengl.h>
   84.40 +#ifdef USE_LOCAL_HEADERS
   84.41 +#	include "SDL_opengl.h"
   84.42 +#else
   84.43 +#	include <SDL_opengl.h>
   84.44 +#endif
   84.45  
   84.46 -extern void (APIENTRYP qglActiveTextureARB) (GLenum texture);
   84.47 -extern void (APIENTRYP qglClientActiveTextureARB) (GLenum texture);
   84.48 -extern void (APIENTRYP qglMultiTexCoord2fARB) (GLenum target, GLfloat s, GLfloat t);
   84.49  
   84.50 -extern void (APIENTRYP qglLockArraysEXT) (GLint first, GLsizei count);
   84.51 -extern void (APIENTRYP qglUnlockArraysEXT) (void);
   84.52 +int             QGL_Init(void);
   84.53 +void            QGL_Shutdown(void);
   84.54 +void            QGL_EnableLogging(int enable);
   84.55  
   84.56 +/*
   84.57 +	This interface is similar to OpenGL ES 2.0.
   84.58 +*/
   84.59  
   84.60 -//===========================================================================
   84.61 +// OpenGL 2.x core API
   84.62 +extern void     (APIENTRY * qglBindTexture) (GLenum target, GLuint texture);
   84.63 +extern void     (APIENTRY * qglBlendFunc) (GLenum sfactor, GLenum dfactor);
   84.64 +extern void     (APIENTRY * qglClear) (GLbitfield mask);
   84.65 +extern void     (APIENTRY * qglClearColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
   84.66 +extern void     (APIENTRY * qglClearDepth) (GLclampd depth);
   84.67 +extern void     (APIENTRY * qglClearStencil) (GLint s);
   84.68 +extern void     (APIENTRY * qglClipPlane) (GLenum plane, const GLdouble * equation);
   84.69 +extern void     (APIENTRY * qglColorMask) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
   84.70 +extern void     (APIENTRY * qglCopyPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
   84.71 +extern void     (APIENTRY * qglCopyTexImage1D) (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y,
   84.72 +												GLsizei width, GLint border);
   84.73 +extern void     (APIENTRY * qglCopyTexImage2D) (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y,
   84.74 +												GLsizei width, GLsizei height, GLint border);
   84.75 +extern void     (APIENTRY * qglCopyTexSubImage1D) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
   84.76 +extern void     (APIENTRY * qglCopyTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
   84.77 +												   GLsizei width, GLsizei height);
   84.78 +extern void     (APIENTRY * qglCullFace) (GLenum mode);
   84.79 +extern void     (APIENTRY * qglDeleteTextures) (GLsizei n, const GLuint * textures);
   84.80 +extern void     (APIENTRY * qglDepthFunc) (GLenum func);
   84.81 +extern void     (APIENTRY * qglDepthMask) (GLboolean flag);
   84.82 +extern void     (APIENTRY * qglDepthRange) (GLclampd zNear, GLclampd zFar);
   84.83 +extern void     (APIENTRY * qglDisable) (GLenum cap);
   84.84 +extern void     (APIENTRY * qglDrawArrays) (GLenum mode, GLint first, GLsizei count);
   84.85 +extern void     (APIENTRY * qglDrawBuffer) (GLenum mode);
   84.86 +extern void     (APIENTRY * qglDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid * indices);
   84.87 +extern void     (APIENTRY * qglEnable) (GLenum cap);
   84.88 +extern void     (APIENTRY * qglFinish) (void);
   84.89 +extern void     (APIENTRY * qglFlush) (void);
   84.90 +extern void     (APIENTRY * qglFrontFace) (GLenum mode);
   84.91 +extern void     (APIENTRY * qglGenTextures) (GLsizei n, GLuint * textures);
   84.92 +extern void     (APIENTRY * qglGetBooleanv) (GLenum pname, GLboolean * params);
   84.93 +extern          GLenum(APIENTRY * qglGetError) (void);
   84.94 +extern void     (APIENTRY * qglGetFloatv) (GLenum pname, GLfloat * params);
   84.95 +extern void     (APIENTRY * qglGetIntegerv) (GLenum pname, GLint * params);
   84.96 +extern const GLubyte *(APIENTRY * qglGetString) (GLenum name);
   84.97 +extern void     (APIENTRY * qglGetTexParameterfv) (GLenum target, GLenum pname, GLfloat * params);
   84.98 +extern void     (APIENTRY * qglGetTexParameteriv) (GLenum target, GLenum pname, GLint * params);
   84.99 +extern void     (APIENTRY * qglHint) (GLenum target, GLenum mode);
  84.100 +extern          GLboolean(APIENTRY * qglIsEnabled) (GLenum cap);
  84.101 +extern          GLboolean(APIENTRY * qglIsTexture) (GLuint texture);
  84.102 +extern void     (APIENTRY * qglLineWidth) (GLfloat width);
  84.103 +extern void     (APIENTRY * qglPolygonMode) (GLenum face, GLenum mode);
  84.104 +extern void     (APIENTRY * qglPolygonOffset) (GLfloat factor, GLfloat units);
  84.105 +extern void     (APIENTRY * qglReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
  84.106 +											GLvoid * pixels);
  84.107 +extern void     (APIENTRY * qglScissor) (GLint x, GLint y, GLsizei width, GLsizei height);
  84.108 +extern void     (APIENTRY * qglStencilFunc) (GLenum func, GLint ref, GLuint mask);
  84.109 +extern void     (APIENTRY * qglStencilMask) (GLuint mask);
  84.110 +extern void     (APIENTRY * qglStencilOp) (GLenum fail, GLenum zfail, GLenum zpass);
  84.111 +extern void     (APIENTRY * qglTexImage1D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border,
  84.112 +											GLenum format, GLenum type, const GLvoid * pixels);
  84.113 +extern void     (APIENTRY * qglTexImage2D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
  84.114 +											GLint border, GLenum format, GLenum type, const GLvoid * pixels);
  84.115 +extern void     (APIENTRY * qglTexParameterf) (GLenum target, GLenum pname, GLfloat param);
  84.116 +extern void     (APIENTRY * qglTexParameterfv) (GLenum target, GLenum pname, const GLfloat * params);
  84.117 +extern void     (APIENTRY * qglTexParameteri) (GLenum target, GLenum pname, GLint param);
  84.118 +extern void     (APIENTRY * qglTexParameteriv) (GLenum target, GLenum pname, const GLint * params);
  84.119 +extern void     (APIENTRY * qglTexSubImage1D) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format,
  84.120 +											   GLenum type, const GLvoid * pixels);
  84.121 +extern void     (APIENTRY * qglTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
  84.122 +											   GLsizei height, GLenum format, GLenum type, const GLvoid * pixels);
  84.123 +extern void     (APIENTRY * qglViewport) (GLint x, GLint y, GLsizei width, GLsizei height);
  84.124  
  84.125 -#define qglAccum glAccum
  84.126 -#define qglAlphaFunc glAlphaFunc
  84.127 -#define qglAreTexturesResident glAreTexturesResident
  84.128 -#define qglArrayElement glArrayElement
  84.129 -#define qglBegin glBegin
  84.130 -#define qglBindTexture glBindTexture
  84.131 -#define qglBitmap glBitmap
  84.132 -#define qglBlendFunc glBlendFunc
  84.133 -#define qglCallList glCallList
  84.134 -#define qglCallLists glCallLists
  84.135 -#define qglClear glClear
  84.136 -#define qglClearAccum glClearAccum
  84.137 -#define qglClearColor glClearColor
  84.138 -#define qglClearDepth glClearDepth
  84.139 -#define qglClearIndex glClearIndex
  84.140 -#define qglClearStencil glClearStencil
  84.141 -#define qglClipPlane glClipPlane
  84.142 -#define qglColor3b glColor3b
  84.143 -#define qglColor3bv glColor3bv
  84.144 -#define qglColor3d glColor3d
  84.145 -#define qglColor3dv glColor3dv
  84.146 -#define qglColor3f glColor3f
  84.147 -#define qglColor3fv glColor3fv
  84.148 -#define qglColor3i glColor3i
  84.149 -#define qglColor3iv glColor3iv
  84.150 -#define qglColor3s glColor3s
  84.151 -#define qglColor3sv glColor3sv
  84.152 -#define qglColor3ub glColor3ub
  84.153 -#define qglColor3ubv glColor3ubv
  84.154 -#define qglColor3ui glColor3ui
  84.155 -#define qglColor3uiv glColor3uiv
  84.156 -#define qglColor3us glColor3us
  84.157 -#define qglColor3usv glColor3usv
  84.158 -#define qglColor4b glColor4b
  84.159 -#define qglColor4bv glColor4bv
  84.160 -#define qglColor4d glColor4d
  84.161 -#define qglColor4dv glColor4dv
  84.162 -#define qglColor4f glColor4f
  84.163 -#define qglColor4fv glColor4fv
  84.164 -#define qglColor4i glColor4i
  84.165 -#define qglColor4iv glColor4iv
  84.166 -#define qglColor4s glColor4s
  84.167 -#define qglColor4sv glColor4sv
  84.168 -#define qglColor4ub glColor4ub
  84.169 -#define qglColor4ubv glColor4ubv
  84.170 -#define qglColor4ui glColor4ui
  84.171 -#define qglColor4uiv glColor4uiv
  84.172 -#define qglColor4us glColor4us
  84.173 -#define qglColor4usv glColor4usv
  84.174 -#define qglColorMask glColorMask
  84.175 -#define qglColorMaterial glColorMaterial
  84.176 -#define qglColorPointer glColorPointer
  84.177 -#define qglCopyPixels glCopyPixels
  84.178 -#define qglCopyTexImage1D glCopyTexImage1D
  84.179 -#define qglCopyTexImage2D glCopyTexImage2D
  84.180 -#define qglCopyTexSubImage1D glCopyTexSubImage1D
  84.181 -#define qglCopyTexSubImage2D glCopyTexSubImage2D
  84.182 -#define qglCullFace glCullFace
  84.183 -#define qglDeleteLists glDeleteLists
  84.184 -#define qglDeleteTextures glDeleteTextures
  84.185 -#define qglDepthFunc glDepthFunc
  84.186 -#define qglDepthMask glDepthMask
  84.187 -#define qglDepthRange glDepthRange
  84.188 -#define qglDisable glDisable
  84.189 -#define qglDisableClientState glDisableClientState
  84.190 -#define qglDrawArrays glDrawArrays
  84.191 -#define qglDrawBuffer glDrawBuffer
  84.192 -#define qglDrawElements glDrawElements
  84.193 -#define qglDrawPixels glDrawPixels
  84.194 -#define qglEdgeFlag glEdgeFlag
  84.195 -#define qglEdgeFlagPointer glEdgeFlagPointer
  84.196 -#define qglEdgeFlagv glEdgeFlagv
  84.197 -#define qglEnable glEnable
  84.198 -#define qglEnableClientState glEnableClientState
  84.199 -#define qglEnd glEnd
  84.200 -#define qglEndList glEndList
  84.201 -#define qglEvalCoord1d glEvalCoord1d
  84.202 -#define qglEvalCoord1dv glEvalCoord1dv
  84.203 -#define qglEvalCoord1f glEvalCoord1f
  84.204 -#define qglEvalCoord1fv glEvalCoord1fv
  84.205 -#define qglEvalCoord2d glEvalCoord2d
  84.206 -#define qglEvalCoord2dv glEvalCoord2dv
  84.207 -#define qglEvalCoord2f glEvalCoord2f
  84.208 -#define qglEvalCoord2fv glEvalCoord2fv
  84.209 -#define qglEvalMesh1 glEvalMesh1
  84.210 -#define qglEvalMesh2 glEvalMesh2
  84.211 -#define qglEvalPoint1 glEvalPoint1
  84.212 -#define qglEvalPoint2 glEvalPoint2
  84.213 -#define qglFeedbackBuffer glFeedbackBuffer
  84.214 -#define qglFinish glFinish
  84.215 -#define qglFlush glFlush
  84.216 -#define qglFogf glFogf
  84.217 -#define qglFogfv glFogfv
  84.218 -#define qglFogi glFogi
  84.219 -#define qglFogiv glFogiv
  84.220 -#define qglFrontFace glFrontFace
  84.221 -#define qglFrustum glFrustum
  84.222 -#define qglGenLists glGenLists
  84.223 -#define qglGenTextures glGenTextures
  84.224 -#define qglGetBooleanv glGetBooleanv
  84.225 -#define qglGetClipPlane glGetClipPlane
  84.226 -#define qglGetDoublev glGetDoublev
  84.227 -#define qglGetError glGetError
  84.228 -#define qglGetFloatv glGetFloatv
  84.229 -#define qglGetIntegerv glGetIntegerv
  84.230 -#define qglGetLightfv glGetLightfv
  84.231 -#define qglGetLightiv glGetLightiv
  84.232 -#define qglGetMapdv glGetMapdv
  84.233 -#define qglGetMapfv glGetMapfv
  84.234 -#define qglGetMapiv glGetMapiv
  84.235 -#define qglGetMaterialfv glGetMaterialfv
  84.236 -#define qglGetMaterialiv glGetMaterialiv
  84.237 -#define qglGetPixelMapfv glGetPixelMapfv
  84.238 -#define qglGetPixelMapuiv glGetPixelMapuiv
  84.239 -#define qglGetPixelMapusv glGetPixelMapusv
  84.240 -#define qglGetPointerv glGetPointerv
  84.241 -#define qglGetPolygonStipple glGetPolygonStipple
  84.242 -#define qglGetString glGetString
  84.243 -#define qglGetTexGendv glGetTexGendv
  84.244 -#define qglGetTexGenfv glGetTexGenfv
  84.245 -#define qglGetTexGeniv glGetTexGeniv
  84.246 -#define qglGetTexImage glGetTexImage
  84.247 -#define qglGetTexLevelParameterfv glGetTexLevelParameterfv
  84.248 -#define qglGetTexLevelParameteriv glGetTexLevelParameteriv
  84.249 -#define qglGetTexParameterfv glGetTexParameterfv
  84.250 -#define qglGetTexParameteriv glGetTexParameteriv
  84.251 -#define qglHint glHint
  84.252 -#define qglIndexMask glIndexMask
  84.253 -#define qglIndexPointer glIndexPointer
  84.254 -#define qglIndexd glIndexd
  84.255 -#define qglIndexdv glIndexdv
  84.256 -#define qglIndexf glIndexf
  84.257 -#define qglIndexfv glIndexfv
  84.258 -#define qglIndexi glIndexi
  84.259 -#define qglIndexiv glIndexiv
  84.260 -#define qglIndexs glIndexs
  84.261 -#define qglIndexsv glIndexsv
  84.262 -#define qglIndexub glIndexub
  84.263 -#define qglIndexubv glIndexubv
  84.264 -#define qglInitNames glInitNames
  84.265 -#define qglInterleavedArrays glInterleavedArrays
  84.266 -#define qglIsEnabled glIsEnabled
  84.267 -#define qglIsList glIsList
  84.268 -#define qglIsTexture glIsTexture
  84.269 -#define qglLightModelf glLightModelf
  84.270 -#define qglLightModelfv glLightModelfv
  84.271 -#define qglLightModeli glLightModeli
  84.272 -#define qglLightModeliv glLightModeliv
  84.273 -#define qglLightf glLightf
  84.274 -#define qglLightfv glLightfv
  84.275 -#define qglLighti glLighti
  84.276 -#define qglLightiv glLightiv
  84.277 -#define qglLineStipple glLineStipple
  84.278 -#define qglLineWidth glLineWidth
  84.279 -#define qglListBase glListBase
  84.280 -#define qglLoadIdentity glLoadIdentity
  84.281 -#define qglLoadMatrixd glLoadMatrixd
  84.282 -#define qglLoadMatrixf glLoadMatrixf
  84.283 -#define qglLoadName glLoadName
  84.284 -#define qglLogicOp glLogicOp
  84.285 -#define qglMap1d glMap1d
  84.286 -#define qglMap1f glMap1f
  84.287 -#define qglMap2d glMap2d
  84.288 -#define qglMap2f glMap2f
  84.289 -#define qglMapGrid1d glMapGrid1d
  84.290 -#define qglMapGrid1f glMapGrid1f
  84.291 -#define qglMapGrid2d glMapGrid2d
  84.292 -#define qglMapGrid2f glMapGrid2f
  84.293 -#define qglMaterialf glMaterialf
  84.294 -#define qglMaterialfv glMaterialfv
  84.295 -#define qglMateriali glMateriali
  84.296 -#define qglMaterialiv glMaterialiv
  84.297 -#define qglMatrixMode glMatrixMode
  84.298 -#define qglMultMatrixd glMultMatrixd
  84.299 -#define qglMultMatrixf glMultMatrixf
  84.300 -#define qglNewList glNewList
  84.301 -#define qglNormal3b glNormal3b
  84.302 -#define qglNormal3bv glNormal3bv
  84.303 -#define qglNormal3d glNormal3d
  84.304 -#define qglNormal3dv glNormal3dv
  84.305 -#define qglNormal3f glNormal3f
  84.306 -#define qglNormal3fv glNormal3fv
  84.307 -#define qglNormal3i glNormal3i
  84.308 -#define qglNormal3iv glNormal3iv
  84.309 -#define qglNormal3s glNormal3s
  84.310 -#define qglNormal3sv glNormal3sv
  84.311 -#define qglNormalPointer glNormalPointer
  84.312 -#define qglOrtho glOrtho
  84.313 -#define qglPassThrough glPassThrough
  84.314 -#define qglPixelMapfv glPixelMapfv
  84.315 -#define qglPixelMapuiv glPixelMapuiv
  84.316 -#define qglPixelMapusv glPixelMapusv
  84.317 -#define qglPixelStoref glPixelStoref
  84.318 -#define qglPixelStorei glPixelStorei
  84.319 -#define qglPixelTransferf glPixelTransferf
  84.320 -#define qglPixelTransferi glPixelTransferi
  84.321 -#define qglPixelZoom glPixelZoom
  84.322 -#define qglPointSize glPointSize
  84.323 -#define qglPolygonMode glPolygonMode
  84.324 -#define qglPolygonOffset glPolygonOffset
  84.325 -#define qglPolygonStipple glPolygonStipple
  84.326 -#define qglPopAttrib glPopAttrib
  84.327 -#define qglPopClientAttrib glPopClientAttrib
  84.328 -#define qglPopMatrix glPopMatrix
  84.329 -#define qglPopName glPopName
  84.330 -#define qglPrioritizeTextures glPrioritizeTextures
  84.331 -#define qglPushAttrib glPushAttrib
  84.332 -#define qglPushClientAttrib glPushClientAttrib
  84.333 -#define qglPushMatrix glPushMatrix
  84.334 -#define qglPushName glPushName
  84.335 -#define qglRasterPos2d glRasterPos2d
  84.336 -#define qglRasterPos2dv glRasterPos2dv
  84.337 -#define qglRasterPos2f glRasterPos2f
  84.338 -#define qglRasterPos2fv glRasterPos2fv
  84.339 -#define qglRasterPos2i glRasterPos2i
  84.340 -#define qglRasterPos2iv glRasterPos2iv
  84.341 -#define qglRasterPos2s glRasterPos2s
  84.342 -#define qglRasterPos2sv glRasterPos2sv
  84.343 -#define qglRasterPos3d glRasterPos3d
  84.344 -#define qglRasterPos3dv glRasterPos3dv
  84.345 -#define qglRasterPos3f glRasterPos3f
  84.346 -#define qglRasterPos3fv glRasterPos3fv
  84.347 -#define qglRasterPos3i glRasterPos3i
  84.348 -#define qglRasterPos3iv glRasterPos3iv
  84.349 -#define qglRasterPos3s glRasterPos3s
  84.350 -#define qglRasterPos3sv glRasterPos3sv
  84.351 -#define qglRasterPos4d glRasterPos4d
  84.352 -#define qglRasterPos4dv glRasterPos4dv
  84.353 -#define qglRasterPos4f glRasterPos4f
  84.354 -#define qglRasterPos4fv glRasterPos4fv
  84.355 -#define qglRasterPos4i glRasterPos4i
  84.356 -#define qglRasterPos4iv glRasterPos4iv
  84.357 -#define qglRasterPos4s glRasterPos4s
  84.358 -#define qglRasterPos4sv glRasterPos4sv
  84.359 -#define qglReadBuffer glReadBuffer
  84.360 -#define qglReadPixels glReadPixels
  84.361 -#define qglRectd glRectd
  84.362 -#define qglRectdv glRectdv
  84.363 -#define qglRectf glRectf
  84.364 -#define qglRectfv glRectfv
  84.365 -#define qglRecti glRecti
  84.366 -#define qglRectiv glRectiv
  84.367 -#define qglRects glRects
  84.368 -#define qglRectsv glRectsv
  84.369 -#define qglRenderMode glRenderMode
  84.370 -#define qglRotated glRotated
  84.371 -#define qglRotatef glRotatef
  84.372 -#define qglScaled glScaled
  84.373 -#define qglScalef glScalef
  84.374 -#define qglScissor glScissor
  84.375 -#define qglSelectBuffer glSelectBuffer
  84.376 -#define qglShadeModel glShadeModel
  84.377 -#define qglStencilFunc glStencilFunc
  84.378 -#define qglStencilMask glStencilMask
  84.379 -#define qglStencilOp glStencilOp
  84.380 -#define qglTexCoord1d glTexCoord1d
  84.381 -#define qglTexCoord1dv glTexCoord1dv
  84.382 -#define qglTexCoord1f glTexCoord1f
  84.383 -#define qglTexCoord1fv glTexCoord1fv
  84.384 -#define qglTexCoord1i glTexCoord1i
  84.385 -#define qglTexCoord1iv glTexCoord1iv
  84.386 -#define qglTexCoord1s glTexCoord1s
  84.387 -#define qglTexCoord1sv glTexCoord1sv
  84.388 -#define qglTexCoord2d glTexCoord2d
  84.389 -#define qglTexCoord2dv glTexCoord2dv
  84.390 -#define qglTexCoord2f glTexCoord2f
  84.391 -#define qglTexCoord2fv glTexCoord2fv
  84.392 -#define qglTexCoord2i glTexCoord2i
  84.393 -#define qglTexCoord2iv glTexCoord2iv
  84.394 -#define qglTexCoord2s glTexCoord2s
  84.395 -#define qglTexCoord2sv glTexCoord2sv
  84.396 -#define qglTexCoord3d glTexCoord3d
  84.397 -#define qglTexCoord3dv glTexCoord3dv
  84.398 -#define qglTexCoord3f glTexCoord3f
  84.399 -#define qglTexCoord3fv glTexCoord3fv
  84.400 -#define qglTexCoord3i glTexCoord3i
  84.401 -#define qglTexCoord3iv glTexCoord3iv
  84.402 -#define qglTexCoord3s glTexCoord3s
  84.403 -#define qglTexCoord3sv glTexCoord3sv
  84.404 -#define qglTexCoord4d glTexCoord4d
  84.405 -#define qglTexCoord4dv glTexCoord4dv
  84.406 -#define qglTexCoord4f glTexCoord4f
  84.407 -#define qglTexCoord4fv glTexCoord4fv
  84.408 -#define qglTexCoord4i glTexCoord4i
  84.409 -#define qglTexCoord4iv glTexCoord4iv
  84.410 -#define qglTexCoord4s glTexCoord4s
  84.411 -#define qglTexCoord4sv glTexCoord4sv
  84.412 -#define qglTexCoordPointer glTexCoordPointer
  84.413 -#define qglTexEnvf glTexEnvf
  84.414 -#define qglTexEnvfv glTexEnvfv
  84.415 -#define qglTexEnvi glTexEnvi
  84.416 -#define qglTexEnviv glTexEnviv
  84.417 -#define qglTexGend glTexGend
  84.418 -#define qglTexGendv glTexGendv
  84.419 -#define qglTexGenf glTexGenf
  84.420 -#define qglTexGenfv glTexGenfv
  84.421 -#define qglTexGeni glTexGeni
  84.422 -#define qglTexGeniv glTexGeniv
  84.423 -#define qglTexImage1D glTexImage1D
  84.424 -#define qglTexImage2D glTexImage2D
  84.425 -#define qglTexParameterf glTexParameterf
  84.426 -#define qglTexParameterfv glTexParameterfv
  84.427 -#define qglTexParameteri glTexParameteri
  84.428 -#define qglTexParameteriv glTexParameteriv
  84.429 -#define qglTexSubImage1D glTexSubImage1D
  84.430 -#define qglTexSubImage2D glTexSubImage2D
  84.431 -#define qglTranslated glTranslated
  84.432 -#define qglTranslatef glTranslatef
  84.433 -#define qglVertex2d glVertex2d
  84.434 -#define qglVertex2dv glVertex2dv
  84.435 -#define qglVertex2f glVertex2f
  84.436 -#define qglVertex2fv glVertex2fv
  84.437 -#define qglVertex2i glVertex2i
  84.438 -#define qglVertex2iv glVertex2iv
  84.439 -#define qglVertex2s glVertex2s
  84.440 -#define qglVertex2sv glVertex2sv
  84.441 -#define qglVertex3d glVertex3d
  84.442 -#define qglVertex3dv glVertex3dv
  84.443 -#define qglVertex3f glVertex3f
  84.444 -#define qglVertex3fv glVertex3fv
  84.445 -#define qglVertex3i glVertex3i
  84.446 -#define qglVertex3iv glVertex3iv
  84.447 -#define qglVertex3s glVertex3s
  84.448 -#define qglVertex3sv glVertex3sv
  84.449 -#define qglVertex4d glVertex4d
  84.450 -#define qglVertex4dv glVertex4dv
  84.451 -#define qglVertex4f glVertex4f
  84.452 -#define qglVertex4fv glVertex4fv
  84.453 -#define qglVertex4i glVertex4i
  84.454 -#define qglVertex4iv glVertex4iv
  84.455 -#define qglVertex4s glVertex4s
  84.456 -#define qglVertex4sv glVertex4sv
  84.457 -#define qglVertexPointer glVertexPointer
  84.458 -#define qglViewport glViewport
  84.459  
  84.460 +// GL_ARB_multitexture
  84.461 +extern void     (APIENTRY * qglActiveTextureARB) (GLenum texture);
  84.462 +
  84.463 +// GL_ARB_texture_compression
  84.464 +#ifndef GL_ARB_texture_compression
  84.465 +#define GL_COMPRESSED_ALPHA_ARB           0x84E9
  84.466 +#define GL_COMPRESSED_LUMINANCE_ARB       0x84EA
  84.467 +#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
  84.468 +#define GL_COMPRESSED_INTENSITY_ARB       0x84EC
  84.469 +#define GL_COMPRESSED_RGB_ARB             0x84ED
  84.470 +#define GL_COMPRESSED_RGBA_ARB            0x84EE
  84.471 +#define GL_TEXTURE_COMPRESSION_HINT_ARB   0x84EF
  84.472 +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
  84.473 +#define GL_TEXTURE_COMPRESSED_ARB         0x86A1
  84.474 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
  84.475 +#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
  84.476  #endif
  84.477 +
  84.478 +extern void (APIENTRY * qglCompressedTexImage3DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
  84.479 +extern void (APIENTRY * qglCompressedTexImage2DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
  84.480 +extern void (APIENTRY * qglCompressedTexImage1DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
  84.481 +extern void (APIENTRY * qglCompressedTexSubImage3DARB) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
  84.482 +extern void (APIENTRY * qglCompressedTexSubImage2DARB) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
  84.483 +extern void (APIENTRY * qglCompressedTexSubImage1DARB) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
  84.484 +extern void (APIENTRY * qglGetCompressedTexImageARB) (GLenum target, GLint level, GLvoid *img);
  84.485 +
  84.486 +// GL_ARB_vertex_program
  84.487 +extern void     (APIENTRY * qglVertexAttrib4fARB) (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
  84.488 +extern void     (APIENTRY * qglVertexAttrib4fvARB) (GLuint, const GLfloat *);
  84.489 +extern void     (APIENTRY * qglVertexAttribPointerARB) (GLuint index, GLint size, GLenum type, GLboolean normalized,
  84.490 +														GLsizei stride, const GLvoid * pointer);
  84.491 +extern void     (APIENTRY * qglEnableVertexAttribArrayARB) (GLuint index);
  84.492 +extern void     (APIENTRY * qglDisableVertexAttribArrayARB) (GLuint index);
  84.493 +
  84.494 +// GL_ARB_vertex_buffer_object
  84.495 +extern void     (APIENTRY * qglBindBufferARB) (GLenum target, GLuint buffer);
  84.496 +extern void     (APIENTRY * qglDeleteBuffersARB) (GLsizei n, const GLuint * buffers);
  84.497 +extern void     (APIENTRY * qglGenBuffersARB) (GLsizei n, GLuint * buffers);
  84.498 +extern          GLboolean(APIENTRY * qglIsBufferARB) (GLuint buffer);
  84.499 +extern void     (APIENTRY * qglBufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage);
  84.500 +extern void     (APIENTRY * qglBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data);
  84.501 +extern void     (APIENTRY * qglGetBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data);
  84.502 +extern void     (APIENTRY * qglGetBufferParameterivARB) (GLenum target, GLenum pname, GLint * params);
  84.503 +extern void     (APIENTRY * qglGetBufferPointervARB) (GLenum target, GLenum pname, GLvoid * *params);
  84.504 +
  84.505 +// GL_ARB_occlusion_query
  84.506 +extern void     (APIENTRY * qglGenQueriesARB) (GLsizei n, GLuint * ids);
  84.507 +extern void     (APIENTRY * qglDeleteQueriesARB) (GLsizei n, const GLuint * ids);
  84.508 +extern          GLboolean(APIENTRY * qglIsQueryARB) (GLuint id);
  84.509 +extern void     (APIENTRY * qglBeginQueryARB) (GLenum target, GLuint id);
  84.510 +extern void     (APIENTRY * qglEndQueryARB) (GLenum target);
  84.511 +extern void     (APIENTRY * qglGetQueryivARB) (GLenum target, GLenum pname, GLint * params);
  84.512 +extern void     (APIENTRY * qglGetQueryObjectivARB) (GLuint id, GLenum pname, GLint * params);
  84.513 +extern void     (APIENTRY * qglGetQueryObjectuivARB) (GLuint id, GLenum pname, GLuint * params);
  84.514 +
  84.515 +// GL_ARB_shader_objects
  84.516 +extern void     (APIENTRY * qglDeleteObjectARB) (GLhandleARB obj);
  84.517 +extern          GLhandleARB(APIENTRY * qglGetHandleARB) (GLenum pname);
  84.518 +extern void     (APIENTRY * qglDetachObjectARB) (GLhandleARB containerObj, GLhandleARB attachedObj);
  84.519 +extern          GLhandleARB(APIENTRY * qglCreateShaderObjectARB) (GLenum shaderType);
  84.520 +extern void     (APIENTRY * qglShaderSourceARB) (GLhandleARB shaderObj, GLsizei count, const GLcharARB * *string,
  84.521 +												 const GLint * length);
  84.522 +extern void     (APIENTRY * qglCompileShaderARB) (GLhandleARB shaderObj);
  84.523 +extern          GLhandleARB(APIENTRY * qglCreateProgramObjectARB) (void);
  84.524 +extern void     (APIENTRY * qglAttachObjectARB) (GLhandleARB containerObj, GLhandleARB obj);
  84.525 +extern void     (APIENTRY * qglLinkProgramARB) (GLhandleARB programObj);
  84.526 +extern void     (APIENTRY * qglUseProgramObjectARB) (GLhandleARB programObj);
  84.527 +extern void     (APIENTRY * qglValidateProgramARB) (GLhandleARB programObj);
  84.528 +extern void     (APIENTRY * qglUniform1fARB) (GLint location, GLfloat v0);
  84.529 +extern void     (APIENTRY * qglUniform2fARB) (GLint location, GLfloat v0, GLfloat v1);
  84.530 +extern void     (APIENTRY * qglUniform3fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
  84.531 +extern void     (APIENTRY * qglUniform4fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
  84.532 +extern void     (APIENTRY * qglUniform1iARB) (GLint location, GLint v0);
  84.533 +extern void     (APIENTRY * qglUniform2iARB) (GLint location, GLint v0, GLint v1);
  84.534 +extern void     (APIENTRY * qglUniform3iARB) (GLint location, GLint v0, GLint v1, GLint v2);
  84.535 +extern void     (APIENTRY * qglUniform4iARB) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
  84.536 +extern void     (APIENTRY * qglUniform2fvARB) (GLint location, GLsizei count, const GLfloat * value);
  84.537 +extern void     (APIENTRY * qglUniform3fvARB) (GLint location, GLsizei count, const GLfloat * value);
  84.538 +extern void     (APIENTRY * qglUniform4fvARB) (GLint location, GLsizei count, const GLfloat * value);
  84.539 +extern void     (APIENTRY * qglUniform2ivARB) (GLint location, GLsizei count, const GLint * value);
  84.540 +extern void     (APIENTRY * qglUniform3ivARB) (GLint location, GLsizei count, const GLint * value);
  84.541 +extern void     (APIENTRY * qglUniform4ivARB) (GLint location, GLsizei count, const GLint * value);
  84.542 +extern void     (APIENTRY * qglUniformMatrix2fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
  84.543 +extern void     (APIENTRY * qglUniformMatrix3fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
  84.544 +extern void     (APIENTRY * qglUniformMatrix4fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
  84.545 +extern void     (APIENTRY * qglGetObjectParameterfvARB) (GLhandleARB obj, GLenum pname, GLfloat * params);
  84.546 +extern void     (APIENTRY * qglGetObjectParameterivARB) (GLhandleARB obj, GLenum pname, GLint * params);
  84.547 +extern void     (APIENTRY * qglGetInfoLogARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog);
  84.548 +extern void     (APIENTRY * qglGetAttachedObjectsARB) (GLhandleARB containerObj, GLsizei maxCount, GLsizei * count,
  84.549 +													   GLhandleARB * obj);
  84.550 +extern          GLint(APIENTRY * qglGetUniformLocationARB) (GLhandleARB programObj, const GLcharARB * name);
  84.551 +extern void     (APIENTRY * qglGetActiveUniformARB) (GLhandleARB programObj, GLuint index, GLsizei maxIndex, GLsizei * length,
  84.552 +													 GLint * size, GLenum * type, GLcharARB * name);
  84.553 +extern void     (APIENTRY * qglGetUniformfvARB) (GLhandleARB programObj, GLint location, GLfloat * params);
  84.554 +extern void     (APIENTRY * qglGetUniformivARB) (GLhandleARB programObj, GLint location, GLint * params);
  84.555 +extern void     (APIENTRY * qglGetShaderSourceARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * source);
  84.556 +
  84.557 +// GL_ARB_vertex_shader
  84.558 +extern void     (APIENTRY * qglBindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB * name);
  84.559 +extern void     (APIENTRY * qglGetActiveAttribARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length,
  84.560 +													GLint * size, GLenum * type, GLcharARB * name);
  84.561 +extern          GLint(APIENTRY * qglGetAttribLocationARB) (GLhandleARB programObj, const GLcharARB * name);
  84.562 +
  84.563 +// GL_ARB_draw_buffers
  84.564 +extern void     (APIENTRY * qglDrawBuffersARB) (GLsizei n, const GLenum * bufs);
  84.565 +
  84.566 +// GL_ARB_vertex_array_object
  84.567 +#ifndef GL_ARB_vertex_array_object
  84.568 +#define GL_VERTEX_ARRAY_BINDING           0x85B5
  84.569 +#endif
  84.570 +
  84.571 +extern void		(APIENTRY * qglBindVertexArray) (GLuint array);
  84.572 +extern void		(APIENTRY * qglDeleteVertexArrays) (GLsizei n, const GLuint *arrays);
  84.573 +extern void		(APIENTRY * qglGenVertexArrays) (GLsizei n, GLuint *arrays);
  84.574 +extern GLboolean (APIENTRY * qglIsVertexArray) (GLuint array);
  84.575 +
  84.576 +
  84.577 +
  84.578 +
  84.579 +#if defined(WIN32)
  84.580 +// WGL_ARB_create_context
  84.581 +#ifndef WGL_ARB_create_context
  84.582 +#define WGL_CONTEXT_DEBUG_BIT_ARB      0x0001
  84.583 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
  84.584 +#define WGL_CONTEXT_MAJOR_VERSION_ARB  0x2091
  84.585 +#define WGL_CONTEXT_MINOR_VERSION_ARB  0x2092
  84.586 +#define WGL_CONTEXT_LAYER_PLANE_ARB    0x2093
  84.587 +#define WGL_CONTEXT_FLAGS_ARB          0x2094
  84.588 +#define ERROR_INVALID_VERSION_ARB      0x2095
  84.589 +#endif
  84.590 +
  84.591 +extern          HGLRC(APIENTRY * qwglCreateContextAttribsARB) (HDC hdC, HGLRC hShareContext, const int *attribList);
  84.592 +#endif
  84.593 +
  84.594 +#if 0 //defined(__linux__)
  84.595 +// GLX_ARB_create_context
  84.596 +#ifndef GLX_ARB_create_context
  84.597 +#define GLX_CONTEXT_DEBUG_BIT_ARB          0x00000001
  84.598 +#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
  84.599 +#define GLX_CONTEXT_MAJOR_VERSION_ARB      0x2091
  84.600 +#define GLX_CONTEXT_MINOR_VERSION_ARB      0x2092
  84.601 +#define GLX_CONTEXT_FLAGS_ARB              0x2094
  84.602 +#endif
  84.603 +
  84.604 +extern GLXContext	(APIENTRY * qglXCreateContextAttribsARB) (Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
  84.605 +#endif
  84.606 +
  84.607 +// GL_EXT_texture3D
  84.608 +#ifndef GL_EXT_texture3D
  84.609 +#define GL_PACK_SKIP_IMAGES_EXT           0x806B
  84.610 +#define GL_PACK_IMAGE_HEIGHT_EXT          0x806C
  84.611 +#define GL_UNPACK_SKIP_IMAGES_EXT         0x806D
  84.612 +#define GL_UNPACK_IMAGE_HEIGHT_EXT        0x806E
  84.613 +#define GL_TEXTURE_3D_EXT                 0x806F
  84.614 +#define GL_PROXY_TEXTURE_3D_EXT           0x8070
  84.615 +#define GL_TEXTURE_DEPTH_EXT              0x8071
  84.616 +#define GL_TEXTURE_WRAP_R_EXT             0x8072
  84.617 +#define GL_MAX_3D_TEXTURE_SIZE_EXT        0x8073
  84.618 +#endif
  84.619 +
  84.620 +extern void		(APIENTRY * qglTexImage3DEXT) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
  84.621 +extern void		(APIENTRY * qglTexSubImage3DEXT) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
  84.622 +
  84.623 +// GL_EXT_texture_comression_s3tc
  84.624 +#ifndef GL_EXT_texture_compression_s3tc
  84.625 +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT   0x83F0
  84.626 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1
  84.627 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  0x83F2
  84.628 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  0x83F3
  84.629 +#endif
  84.630 +
  84.631 +// GL_EXT_stencil_two_side
  84.632 +extern void     (APIENTRY * qglActiveStencilFaceEXT) (GLenum face);
  84.633 +
  84.634 +// GL_EXT_depth_bounds_test
  84.635 +extern void     (APIENTRY * qglDepthBoundsEXT) (GLclampd zmin, GLclampd zmax);
  84.636 +
  84.637 +// GL_ATI_separate_stencil
  84.638 +extern void     (APIENTRY * qglStencilFuncSeparateATI) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
  84.639 +extern void     (APIENTRY * qglStencilOpSeparateATI) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
  84.640 +
  84.641 +// GL_EXT_framebuffer_object
  84.642 +#ifndef GL_EXT_framebuffer_object
  84.643 +#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
  84.644 +#define GL_MAX_RENDERBUFFER_SIZE_EXT      0x84E8
  84.645 +#define GL_FRAMEBUFFER_BINDING_EXT        0x8CA6
  84.646 +#define GL_RENDERBUFFER_BINDING_EXT       0x8CA7
  84.647 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
  84.648 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
  84.649 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
  84.650 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
  84.651 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
  84.652 +#define GL_FRAMEBUFFER_COMPLETE_EXT       0x8CD5
  84.653 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
  84.654 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
  84.655 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
  84.656 +#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
  84.657 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
  84.658 +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
  84.659 +#define GL_FRAMEBUFFER_UNSUPPORTED_EXT    0x8CDD
  84.660 +#define GL_MAX_COLOR_ATTACHMENTS_EXT      0x8CDF
  84.661 +#define GL_COLOR_ATTACHMENT0_EXT          0x8CE0
  84.662 +#define GL_COLOR_ATTACHMENT1_EXT          0x8CE1
  84.663 +#define GL_COLOR_ATTACHMENT2_EXT          0x8CE2
  84.664 +#define GL_COLOR_ATTACHMENT3_EXT          0x8CE3
  84.665 +#define GL_COLOR_ATTACHMENT4_EXT          0x8CE4
  84.666 +#define GL_COLOR_ATTACHMENT5_EXT          0x8CE5
  84.667 +#define GL_COLOR_ATTACHMENT6_EXT          0x8CE6
  84.668 +#define GL_COLOR_ATTACHMENT7_EXT          0x8CE7
  84.669 +#define GL_COLOR_ATTACHMENT8_EXT          0x8CE8
  84.670 +#define GL_COLOR_ATTACHMENT9_EXT          0x8CE9
  84.671 +#define GL_COLOR_ATTACHMENT10_EXT         0x8CEA
  84.672 +#define GL_COLOR_ATTACHMENT11_EXT         0x8CEB
  84.673 +#define GL_COLOR_ATTACHMENT12_EXT         0x8CEC
  84.674 +#define GL_COLOR_ATTACHMENT13_EXT         0x8CED
  84.675 +#define GL_COLOR_ATTACHMENT14_EXT         0x8CEE
  84.676 +#define GL_COLOR_ATTACHMENT15_EXT         0x8CEF
  84.677 +#define GL_DEPTH_ATTACHMENT_EXT           0x8D00
  84.678 +#define GL_STENCIL_ATTACHMENT_EXT         0x8D20
  84.679 +#define GL_FRAMEBUFFER_EXT                0x8D40
  84.680 +#define GL_RENDERBUFFER_EXT               0x8D41
  84.681 +#define GL_RENDERBUFFER_WIDTH_EXT         0x8D42
  84.682 +#define GL_RENDERBUFFER_HEIGHT_EXT        0x8D43
  84.683 +#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
  84.684 +#define GL_STENCIL_INDEX1_EXT             0x8D46
  84.685 +#define GL_STENCIL_INDEX4_EXT             0x8D47
  84.686 +#define GL_STENCIL_INDEX8_EXT             0x8D48
  84.687 +#define GL_STENCIL_INDEX16_EXT            0x8D49
  84.688 +#define GL_RENDERBUFFER_RED_SIZE_EXT      0x8D50
  84.689 +#define GL_RENDERBUFFER_GREEN_SIZE_EXT    0x8D51
  84.690 +#define GL_RENDERBUFFER_BLUE_SIZE_EXT     0x8D52
  84.691 +#define GL_RENDERBUFFER_ALPHA_SIZE_EXT    0x8D53
  84.692 +#define GL_RENDERBUFFER_DEPTH_SIZE_EXT    0x8D54
  84.693 +#define GL_RENDERBUFFER_STENCIL_SIZE_EXT  0x8D55
  84.694 +#endif
  84.695 +
  84.696 +extern          GLboolean(APIENTRY * qglIsRenderbufferEXT) (GLuint renderbuffer);
  84.697 +extern void     (APIENTRY * qglBindRenderbufferEXT) (GLenum target, GLuint renderbuffer);
  84.698 +extern void     (APIENTRY * qglDeleteRenderbuffersEXT) (GLsizei n, const GLuint * renderbuffers);
  84.699 +extern void     (APIENTRY * qglGenRenderbuffersEXT) (GLsizei n, GLuint * renderbuffers);
  84.700 +extern void     (APIENTRY * qglRenderbufferStorageEXT) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
  84.701 +extern void     (APIENTRY * qglGetRenderbufferParameterivEXT) (GLenum target, GLenum pname, GLint * params);
  84.702 +extern          GLboolean(APIENTRY * qglIsFramebufferEXT) (GLuint framebuffer);
  84.703 +extern void     (APIENTRY * qglBindFramebufferEXT) (GLenum target, GLuint framebuffer);
  84.704 +extern void     (APIENTRY * qglDeleteFramebuffersEXT) (GLsizei n, const GLuint * framebuffers);
  84.705 +extern void     (APIENTRY * qglGenFramebuffersEXT) (GLsizei n, GLuint * framebuffers);
  84.706 +extern          GLenum(APIENTRY * qglCheckFramebufferStatusEXT) (GLenum target);
  84.707 +extern void     (APIENTRY * qglFramebufferTexture1DEXT) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
  84.708 +														 GLint level);
  84.709 +extern void     (APIENTRY * qglFramebufferTexture2DEXT) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
  84.710 +														 GLint level);
  84.711 +extern void     (APIENTRY * qglFramebufferTexture3DEXT) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
  84.712 +														 GLint level, GLint zoffset);
  84.713 +extern void     (APIENTRY * qglFramebufferRenderbufferEXT) (GLenum target, GLenum attachment, GLenum renderbuffertarget,
  84.714 +															GLuint renderbuffer);
  84.715 +extern void     (APIENTRY * qglGetFramebufferAttachmentParameterivEXT) (GLenum target, GLenum attachment, GLenum pname,
  84.716 +																		GLint * params);
  84.717 +extern void     (APIENTRY * qglGenerateMipmapEXT) (GLenum target);
  84.718 +
  84.719 +// GL_EXT_packed_depth_stencil
  84.720 +#ifndef GL_EXT_packed_depth_stencil
  84.721 +#define GL_DEPTH_STENCIL_EXT              0x84F9
  84.722 +#define GL_UNSIGNED_INT_24_8_EXT          0x84FA
  84.723 +#define GL_DEPTH24_STENCIL8_EXT           0x88F0
  84.724 +#define GL_TEXTURE_STENCIL_SIZE_EXT       0x88F1
  84.725 +#endif
  84.726 +
  84.727 +// GL_EXT_framebuffer_blit
  84.728 +#ifndef GL_EXT_framebuffer_blit
  84.729 +#define GL_READ_FRAMEBUFFER_EXT           0x8CA8
  84.730 +#define GL_DRAW_FRAMEBUFFER_EXT           0x8CA9
  84.731 +#define GL_DRAW_FRAMEBUFFER_BINDING_EXT   GL_FRAMEBUFFER_BINDING_EXT
  84.732 +#define GL_READ_FRAMEBUFFER_BINDING_EXT   0x8CAA
  84.733 +#endif
  84.734 +
  84.735 +extern void		(APIENTRY * qglBlitFramebufferEXT) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
  84.736 +
  84.737 +
  84.738 +#endif							// __QGL_H__
    85.1 --- a/src/renderer/tr_animation.c	Sat Jun 06 03:54:16 2009 +0800
    85.2 +++ b/src/renderer/tr_animation.c	Wed Jun 10 09:31:46 2009 +0800
    85.3 @@ -1,307 +1,1602 @@
    85.4  /*
    85.5  ===========================================================================
    85.6  Copyright (C) 1999-2005 Id Software, Inc.
    85.7 -Copyright (C) 2000-2006 Tim Angus
    85.8 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    85.9  
   85.10 -This file is part of Tremfusion.
   85.11 +This file is part of XreaL source code.
   85.12  
   85.13 -Tremfusion is free software; you can redistribute it
   85.14 +XreaL source code is free software; you can redistribute it
   85.15  and/or modify it under the terms of the GNU General Public License as
   85.16  published by the Free Software Foundation; either version 2 of the License,
   85.17  or (at your option) any later version.
   85.18  
   85.19 -Tremfusion is distributed in the hope that it will be
   85.20 +XreaL source code is distributed in the hope that it will be
   85.21  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   85.22  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   85.23  GNU General Public License for more details.
   85.24  
   85.25  You should have received a copy of the GNU General Public License
   85.26 -along with Tremfusion; if not, write to the Free Software
   85.27 +along with XreaL source code; if not, write to the Free Software
   85.28  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   85.29  ===========================================================================
   85.30  */
   85.31 -
   85.32 +// tr_animation.c
   85.33  #include "tr_local.h"
   85.34  
   85.35  /*
   85.36 -
   85.37 +===========================================================================
   85.38  All bones should be an identity orientation to display the mesh exactly
   85.39  as it is specified.
   85.40  
   85.41 -For all other frames, the bones represent the transformation from the 
   85.42 +For all other frames, the bones represent the transformation from the
   85.43  orientation of the bone in the base frame to the orientation in this
   85.44  frame.
   85.45 -
   85.46 +===========================================================================
   85.47  */
   85.48  
   85.49 +static skelAnimation_t *R_AllocAnimation(void)
   85.50 +{
   85.51 +	skelAnimation_t *anim;
   85.52 +
   85.53 +	if(tr.numAnimations == MAX_ANIMATIONFILES)
   85.54 +	{
   85.55 +		return NULL;
   85.56 +	}
   85.57 +
   85.58 +	anim = ri.Hunk_Alloc(sizeof(*anim), h_low);
   85.59 +	anim->index = tr.numAnimations;
   85.60 +	tr.animations[tr.numAnimations] = anim;
   85.61 +	tr.numAnimations++;
   85.62 +
   85.63 +	return anim;
   85.64 +}
   85.65 +
   85.66  /*
   85.67 -==============
   85.68 -R_AddAnimSurfaces
   85.69 -==============
   85.70 +===============
   85.71 +R_InitAnimations
   85.72 +===============
   85.73  */
   85.74 -void R_AddAnimSurfaces( trRefEntity_t *ent ) {
   85.75 -	md4Header_t		*header;
   85.76 -	md4Surface_t	*surface;
   85.77 -	md4LOD_t		*lod;
   85.78 -	shader_t		*shader;
   85.79 -	int				i;
   85.80 +void R_InitAnimations(void)
   85.81 +{
   85.82 +	skelAnimation_t *anim;
   85.83  
   85.84 -	header = (md4Header_t *) tr.currentModel->md4;
   85.85 -	lod = (md4LOD_t *)( (byte *)header + header->ofsLODs );
   85.86 +	// leave a space for NULL animation
   85.87 +	tr.numAnimations = 0;
   85.88  
   85.89 -	surface = (md4Surface_t *)( (byte *)lod + lod->ofsSurfaces );
   85.90 -	for ( i = 0 ; i < lod->numSurfaces ; i++ ) {
   85.91 -		shader = R_GetShaderByHandle( surface->shaderIndex );
   85.92 -		R_AddDrawSurf( (void *)surface, shader, 0 /*fogNum*/, qfalse );
   85.93 -		surface = (md4Surface_t *)( (byte *)surface + surface->ofsEnd );
   85.94 +	anim = R_AllocAnimation();
   85.95 +	anim->type = AT_BAD;
   85.96 +	strcpy(anim->name, "<default animation>");
   85.97 +}
   85.98 +
   85.99 +static qboolean R_LoadMD5Anim(skelAnimation_t * skelAnim, void *buffer, int bufferSize, const char *name)
  85.100 +{
  85.101 +	int             i, j;
  85.102 +	md5Animation_t *anim;
  85.103 +	md5Frame_t     *frame;
  85.104 +	md5Channel_t   *channel;
  85.105 +	char           *token;
  85.106 +	int             version;
  85.107 +	char           *buf_p;
  85.108 +
  85.109 +	buf_p = buffer;
  85.110 +
  85.111 +	skelAnim->type = AT_MD5;
  85.112 +	skelAnim->md5 = anim = ri.Hunk_Alloc(sizeof(*anim), h_low);
  85.113 +
  85.114 +	// skip MD5Version indent string
  85.115 +	Com_ParseExt(&buf_p, qfalse);
  85.116 +
  85.117 +	// check version
  85.118 +	token = Com_ParseExt(&buf_p, qfalse);
  85.119 +	version = atoi(token);
  85.120 +	if(version != MD5_VERSION)
  85.121 +	{
  85.122 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: '%s' has wrong version (%i should be %i)\n", name, version, MD5_VERSION);
  85.123 +		return qfalse;
  85.124 +	}
  85.125 +
  85.126 +	// skip commandline <arguments string>
  85.127 +	token = Com_ParseExt(&buf_p, qtrue);
  85.128 +	token = Com_ParseExt(&buf_p, qtrue);
  85.129 +
  85.130 +	// parse numFrames <number>
  85.131 +	token = Com_ParseExt(&buf_p, qtrue);
  85.132 +	if(Q_stricmp(token, "numFrames"))
  85.133 +	{
  85.134 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected 'numFrames' found '%s' in model '%s'\n", token, name);
  85.135 +		return qfalse;
  85.136 +	}
  85.137 +	token = Com_ParseExt(&buf_p, qfalse);
  85.138 +	anim->numFrames = atoi(token);
  85.139 +
  85.140 +	// parse numJoints <number>
  85.141 +	token = Com_ParseExt(&buf_p, qtrue);
  85.142 +	if(Q_stricmp(token, "numJoints"))
  85.143 +	{
  85.144 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected 'numJoints' found '%s' in model '%s'\n", token, name);
  85.145 +		return qfalse;
  85.146 +	}
  85.147 +	token = Com_ParseExt(&buf_p, qfalse);
  85.148 +	anim->numChannels = atoi(token);
  85.149 +
  85.150 +	// parse frameRate <number>
  85.151 +	token = Com_ParseExt(&buf_p, qtrue);
  85.152 +	if(Q_stricmp(token, "frameRate"))
  85.153 +	{
  85.154 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected 'frameRate' found '%s' in model '%s'\n", token, name);
  85.155 +		return qfalse;
  85.156 +	}
  85.157 +	token = Com_ParseExt(&buf_p, qfalse);
  85.158 +	anim->frameRate = atoi(token);
  85.159 +
  85.160 +	// parse numAnimatedComponents <number>
  85.161 +	token = Com_ParseExt(&buf_p, qtrue);
  85.162 +	if(Q_stricmp(token, "numAnimatedComponents"))
  85.163 +	{
  85.164 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected 'numAnimatedComponents' found '%s' in model '%s'\n", token,
  85.165 +				  name);
  85.166 +		return qfalse;
  85.167 +	}
  85.168 +	token = Com_ParseExt(&buf_p, qfalse);
  85.169 +	anim->numAnimatedComponents = atoi(token);
  85.170 +
  85.171 +	// parse hierarchy {
  85.172 +	token = Com_ParseExt(&buf_p, qtrue);
  85.173 +	if(Q_stricmp(token, "hierarchy"))
  85.174 +	{
  85.175 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected 'hierarchy' found '%s' in model '%s'\n", token, name);
  85.176 +		return qfalse;
  85.177 +	}
  85.178 +	token = Com_ParseExt(&buf_p, qfalse);
  85.179 +	if(Q_stricmp(token, "{"))
  85.180 +	{
  85.181 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected '{' found '%s' in model '%s'\n", token, name);
  85.182 +		return qfalse;
  85.183 +	}
  85.184 +
  85.185 +	// parse all the channels
  85.186 +	anim->channels = ri.Hunk_Alloc(sizeof(md5Channel_t) * anim->numChannels, h_low);
  85.187 +
  85.188 +	for(i = 0, channel = anim->channels; i < anim->numChannels; i++, channel++)
  85.189 +	{
  85.190 +		token = Com_ParseExt(&buf_p, qtrue);
  85.191 +		Q_strncpyz(channel->name, token, sizeof(channel->name));
  85.192 +
  85.193 +		//ri.Printf(PRINT_ALL, "RE_RegisterAnimation: '%s' has channel '%s'\n", name, channel->name);
  85.194 +
  85.195 +		token = Com_ParseExt(&buf_p, qfalse);
  85.196 +		channel->parentIndex = atoi(token);
  85.197 +
  85.198 +		if(channel->parentIndex >= anim->numChannels)
  85.199 +		{
  85.200 +			ri.Error(ERR_DROP, "RE_RegisterAnimation: '%s' has channel '%s' with bad parent index %i while numBones is %i\n",
  85.201 +					 name, channel->name, channel->parentIndex, anim->numChannels);
  85.202 +		}
  85.203 +
  85.204 +		token = Com_ParseExt(&buf_p, qfalse);
  85.205 +		channel->componentsBits = atoi(token);
  85.206 +
  85.207 +		token = Com_ParseExt(&buf_p, qfalse);
  85.208 +		channel->componentsOffset = atoi(token);
  85.209 +	}
  85.210 +
  85.211 +	// parse }
  85.212 +	token = Com_ParseExt(&buf_p, qtrue);
  85.213 +	if(Q_stricmp(token, "}"))
  85.214 +	{
  85.215 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected '}' found '%s' in model '%s'\n", token, name);
  85.216 +		return qfalse;
  85.217 +	}
  85.218 +
  85.219 +
  85.220 +	// parse bounds {
  85.221 +	token = Com_ParseExt(&buf_p, qtrue);
  85.222 +	if(Q_stricmp(token, "bounds"))
  85.223 +	{
  85.224 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected 'bounds' found '%s' in model '%s'\n", token, name);
  85.225 +		return qfalse;
  85.226 +	}
  85.227 +	token = Com_ParseExt(&buf_p, qfalse);
  85.228 +	if(Q_stricmp(token, "{"))
  85.229 +	{
  85.230 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected '{' found '%s' in model '%s'\n", token, name);
  85.231 +		return qfalse;
  85.232 +	}
  85.233 +
  85.234 +	anim->frames = ri.Hunk_Alloc(sizeof(md5Frame_t) * anim->numFrames, h_low);
  85.235 +
  85.236 +	for(i = 0, frame = anim->frames; i < anim->numFrames; i++, frame++)
  85.237 +	{
  85.238 +		// skip (
  85.239 +		token = Com_ParseExt(&buf_p, qtrue);
  85.240 +		if(Q_stricmp(token, "("))
  85.241 +		{
  85.242 +			ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected '(' found '%s' in model '%s'\n", token, name);
  85.243 +			return qfalse;
  85.244 +		}
  85.245 +
  85.246 +		for(j = 0; j < 3; j++)
  85.247 +		{
  85.248 +			token = Com_ParseExt(&buf_p, qfalse);
  85.249 +			frame->bounds[0][j] = atof(token);
  85.250 +		}
  85.251 +
  85.252 +		// skip )
  85.253 +		token = Com_ParseExt(&buf_p, qfalse);
  85.254 +		if(Q_stricmp(token, ")"))
  85.255 +		{
  85.256 +			ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected ')' found '%s' in model '%s'\n", token, name);
  85.257 +			return qfalse;
  85.258 +		}
  85.259 +
  85.260 +		// skip (
  85.261 +		token = Com_ParseExt(&buf_p, qfalse);
  85.262 +		if(Q_stricmp(token, "("))
  85.263 +		{
  85.264 +			ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected '(' found '%s' in model '%s'\n", token, name);
  85.265 +			return qfalse;
  85.266 +		}
  85.267 +
  85.268 +		for(j = 0; j < 3; j++)
  85.269 +		{
  85.270 +			token = Com_ParseExt(&buf_p, qfalse);
  85.271 +			frame->bounds[1][j] = atof(token);
  85.272 +		}
  85.273 +
  85.274 +		// skip )
  85.275 +		token = Com_ParseExt(&buf_p, qfalse);
  85.276 +		if(Q_stricmp(token, ")"))
  85.277 +		{
  85.278 +			ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected ')' found '%s' in model '%s'\n", token, name);
  85.279 +			return qfalse;
  85.280 +		}
  85.281 +	}
  85.282 +
  85.283 +	// parse }
  85.284 +	token = Com_ParseExt(&buf_p, qtrue);
  85.285 +	if(Q_stricmp(token, "}"))
  85.286 +	{
  85.287 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected '}' found '%s' in model '%s'\n", token, name);
  85.288 +		return qfalse;
  85.289 +	}
  85.290 +
  85.291 +
  85.292 +	// parse baseframe {
  85.293 +	token = Com_ParseExt(&buf_p, qtrue);
  85.294 +	if(Q_stricmp(token, "baseframe"))
  85.295 +	{
  85.296 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected 'baseframe' found '%s' in model '%s'\n", token, name);
  85.297 +		return qfalse;
  85.298 +	}
  85.299 +	token = Com_ParseExt(&buf_p, qfalse);
  85.300 +	if(Q_stricmp(token, "{"))
  85.301 +	{
  85.302 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected '{' found '%s' in model '%s'\n", token, name);
  85.303 +		return qfalse;
  85.304 +	}
  85.305 +
  85.306 +	for(i = 0, channel = anim->channels; i < anim->numChannels; i++, channel++)
  85.307 +	{
  85.308 +		// skip (
  85.309 +		token = Com_ParseExt(&buf_p, qtrue);
  85.310 +		if(Q_stricmp(token, "("))
  85.311 +		{
  85.312 +			ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected '(' found '%s' in model '%s'\n", token, name);
  85.313 +			return qfalse;
  85.314 +		}
  85.315 +
  85.316 +		for(j = 0; j < 3; j++)
  85.317 +		{
  85.318 +			token = Com_ParseExt(&buf_p, qfalse);
  85.319 +			channel->baseOrigin[j] = atof(token);
  85.320 +		}
  85.321 +
  85.322 +		// skip )
  85.323 +		token = Com_ParseExt(&buf_p, qfalse);
  85.324 +		if(Q_stricmp(token, ")"))
  85.325 +		{
  85.326 +			ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected ')' found '%s' in model '%s'\n", token, name);
  85.327 +			return qfalse;
  85.328 +		}
  85.329 +
  85.330 +		// skip (
  85.331 +		token = Com_ParseExt(&buf_p, qfalse);
  85.332 +		if(Q_stricmp(token, "("))
  85.333 +		{
  85.334 +			ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected '(' found '%s' in model '%s'\n", token, name);
  85.335 +			return qfalse;
  85.336 +		}
  85.337 +
  85.338 +		for(j = 0; j < 3; j++)
  85.339 +		{
  85.340 +			token = Com_ParseExt(&buf_p, qfalse);
  85.341 +			channel->baseQuat[j] = atof(token);
  85.342 +		}
  85.343 +		QuatCalcW(channel->baseQuat);
  85.344 +
  85.345 +		// skip )
  85.346 +		token = Com_ParseExt(&buf_p, qfalse);
  85.347 +		if(Q_stricmp(token, ")"))
  85.348 +		{
  85.349 +			ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected ')' found '%s' in model '%s'\n", token, name);
  85.350 +			return qfalse;
  85.351 +		}
  85.352 +	}
  85.353 +
  85.354 +	// parse }
  85.355 +	token = Com_ParseExt(&buf_p, qtrue);
  85.356 +	if(Q_stricmp(token, "}"))
  85.357 +	{
  85.358 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected '}' found '%s' in model '%s'\n", token, name);
  85.359 +		return qfalse;
  85.360 +	}
  85.361 +
  85.362 +	for(i = 0, frame = anim->frames; i < anim->numFrames; i++, frame++)
  85.363 +	{
  85.364 +		// parse frame <number> {
  85.365 +		token = Com_ParseExt(&buf_p, qtrue);
  85.366 +		if(Q_stricmp(token, "frame"))
  85.367 +		{
  85.368 +			ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected 'baseframe' found '%s' in model '%s'\n", token, name);
  85.369 +			return qfalse;
  85.370 +		}
  85.371 +
  85.372 +		token = Com_ParseExt(&buf_p, qfalse);
  85.373 +		if(Q_stricmp(token, va("%i", i)))
  85.374 +		{
  85.375 +			ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected '%i' found '%s' in model '%s'\n", token, name);
  85.376 +			return qfalse;
  85.377 +		}
  85.378 +
  85.379 +		token = Com_ParseExt(&buf_p, qfalse);
  85.380 +		if(Q_stricmp(token, "{"))
  85.381 +		{
  85.382 +			ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected '{' found '%s' in model '%s'\n", token, name);
  85.383 +			return qfalse;
  85.384 +		}
  85.385 +
  85.386 +		frame->components = ri.Hunk_Alloc(sizeof(float) * anim->numAnimatedComponents, h_low);
  85.387 +		for(j = 0; j < anim->numAnimatedComponents; j++)
  85.388 +		{
  85.389 +			token = Com_ParseExt(&buf_p, qtrue);
  85.390 +			frame->components[j] = atof(token);
  85.391 +		}
  85.392 +
  85.393 +		// parse }
  85.394 +		token = Com_ParseExt(&buf_p, qtrue);
  85.395 +		if(Q_stricmp(token, "}"))
  85.396 +		{
  85.397 +			ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: expected '}' found '%s' in model '%s'\n", token, name);
  85.398 +			return qfalse;
  85.399 +		}
  85.400 +	}
  85.401 +
  85.402 +	// everything went ok
  85.403 +	return qtrue;
  85.404 +}
  85.405 +
  85.406 +
  85.407 +
  85.408 +static void GetChunkHeader(memStream_t *s, axChunkHeader_t * chunkHeader)
  85.409 +{
  85.410 +	int             i;
  85.411 +
  85.412 +	for(i = 0; i < 20; i++)
  85.413 +	{
  85.414 +		chunkHeader->ident[i] = MemStreamGetC(s);
  85.415 +	}
  85.416 +
  85.417 +	chunkHeader->flags = MemStreamGetLong(s);
  85.418 +	chunkHeader->dataSize = MemStreamGetLong(s);
  85.419 +	chunkHeader->numData = MemStreamGetLong(s);
  85.420 +}
  85.421 +
  85.422 +static void PrintChunkHeader(axChunkHeader_t * chunkHeader)
  85.423 +{
  85.424 +#if 0
  85.425 +	ri.Printf(PRINT_ALL, "----------------------\n");
  85.426 +	ri.Printf(PRINT_ALL, "R_LoadPSA: chunk header ident: '%s'\n", chunkHeader->ident);
  85.427 +	ri.Printf(PRINT_ALL, "R_LoadPSA: chunk header flags: %i\n", chunkHeader->flags);
  85.428 +	ri.Printf(PRINT_ALL, "R_LoadPSA: chunk header data size: %i\n", chunkHeader->dataSize);
  85.429 +	ri.Printf(PRINT_ALL, "R_LoadPSA: chunk header num items: %i\n", chunkHeader->numData);
  85.430 +#endif
  85.431 +}
  85.432 +
  85.433 +static void GetBone(memStream_t *s, axBone_t * bone)
  85.434 +{
  85.435 +	int             i;
  85.436 +
  85.437 +	for(i = 0; i < 4; i++)
  85.438 +	{
  85.439 +		bone->quat[i] = MemStreamGetFloat(s);
  85.440 +	}
  85.441 +
  85.442 +	for(i = 0; i < 3; i++)
  85.443 +	{
  85.444 +		bone->position[i] = MemStreamGetFloat(s);
  85.445 +	}
  85.446 +
  85.447 +	bone->length = MemStreamGetFloat(s);
  85.448 +
  85.449 +	bone->xSize = MemStreamGetFloat(s);
  85.450 +	bone->ySize = MemStreamGetFloat(s);
  85.451 +	bone->zSize = MemStreamGetFloat(s);
  85.452 +}
  85.453 +
  85.454 +static qboolean R_LoadPSA(skelAnimation_t * skelAnim, void *buffer, int bufferSize, const char *name)
  85.455 +{
  85.456 +	int             i, j, k;
  85.457 +	memStream_t    *stream;
  85.458 +	axChunkHeader_t	chunkHeader;
  85.459 +	int				numReferenceBones;
  85.460 +	axReferenceBone_t *refBone;
  85.461 +	axReferenceBone_t *refBones;
  85.462 +
  85.463 +	int				numSequences;
  85.464 +	axAnimationInfo_t *animInfo;
  85.465 +
  85.466 +	axAnimationKey_t *key;
  85.467 +
  85.468 +	psaAnimation_t *psa;
  85.469 +	skelAnimation_t *extraAnim;
  85.470 +	growList_t      extraAnims;
  85.471 +
  85.472 +	stream = AllocMemStream(buffer, bufferSize);
  85.473 +	GetChunkHeader(stream, &chunkHeader);
  85.474 +
  85.475 +	// check indent again
  85.476 +	if(Q_stricmpn(chunkHeader.ident, "ANIMHEAD", 8))
  85.477 +	{
  85.478 +		ri.Printf(PRINT_WARNING, "R_LoadPSA: '%s' has wrong chunk indent ('%s' should be '%s')\n", name, chunkHeader.ident, "ANIMHEAD");
  85.479 +		FreeMemStream(stream);
  85.480 +		return qfalse;
  85.481 +	}
  85.482 +
  85.483 +	PrintChunkHeader(&chunkHeader);
  85.484 +
  85.485 +	// read reference bones
  85.486 +	GetChunkHeader(stream, &chunkHeader);
  85.487 +	if(Q_stricmpn(chunkHeader.ident, "BONENAMES", 9))
  85.488 +	{
  85.489 +		ri.Printf(PRINT_WARNING, "R_LoadPSA: '%s' has wrong chunk indent ('%s' should be '%s')\n", name, chunkHeader.ident, "BONENAMES");
  85.490 +		FreeMemStream(stream);
  85.491 +		return qfalse;
  85.492 +	}
  85.493 +
  85.494 +	if(chunkHeader.dataSize != sizeof(axReferenceBone_t))
  85.495 +	{
  85.496 +		ri.Printf(PRINT_WARNING, "R_LoadPSA: '%s' has wrong chunk dataSize ('%i' should be '%i')\n", name, chunkHeader.dataSize, sizeof(axReferenceBone_t));
  85.497 +		FreeMemStream(stream);
  85.498 +		return qfalse;
  85.499 +	}
  85.500 +
  85.501 +	PrintChunkHeader(&chunkHeader);
  85.502 +
  85.503 +	numReferenceBones = chunkHeader.numData;
  85.504 +	if(numReferenceBones < 1)
  85.505 +	{
  85.506 +		ri.Printf(PRINT_WARNING, "R_LoadPSA: '%s' has no bones\n", name);
  85.507 +		FreeMemStream(stream);
  85.508 +		return qfalse;
  85.509 +	}
  85.510 +	if(numReferenceBones > MAX_BONES)
  85.511 +	{
  85.512 +		ri.Printf(PRINT_WARNING, "R_LoadPSA: '%s' has more than %i bones (%i)\n", name, MAX_BONES, numReferenceBones);
  85.513 +		FreeMemStream(stream);
  85.514 +		return qfalse;
  85.515 +	}
  85.516 +
  85.517 +	refBones = ri.Hunk_Alloc(numReferenceBones * sizeof(axReferenceBone_t), h_low);
  85.518 +	for(i = 0, refBone = refBones; i < numReferenceBones; i++, refBone++)
  85.519 +	{
  85.520 +		MemStreamRead(stream, refBone->name, sizeof(refBone->name));
  85.521 +
  85.522 +		refBone->flags = MemStreamGetLong(stream);
  85.523 +		refBone->numChildren = MemStreamGetLong(stream);
  85.524 +		refBone->parentIndex = MemStreamGetLong(stream);
  85.525 +
  85.526 +		if(i == 0)
  85.527 +		{
  85.528 +			refBone->parentIndex = -1;
  85.529 +		}
  85.530 +
  85.531 +		GetBone(stream, &refBone->bone);
  85.532 +
  85.533 +#if 0
  85.534 +		ri.Printf(PRINT_ALL, "R_LoadPSA: axReferenceBone_t(%i):\n"
  85.535 +				"axReferenceBone_t::name: '%s'\n"
  85.536 +				"axReferenceBone_t::flags: %i\n"
  85.537 +				"axReferenceBone_t::numChildren %i\n"
  85.538 +				"axReferenceBone_t::parentIndex: %i\n"
  85.539 +				"axReferenceBone_t::quat: %f %f %f %f\n"
  85.540 +				"axReferenceBone_t::position: %f %f %f\n"
  85.541 +				"axReferenceBone_t::length: %f\n"
  85.542 +				"axReferenceBone_t::xSize: %f\n"
  85.543 +				"axReferenceBone_t::ySize: %f\n"
  85.544 +				"axReferenceBone_t::zSize: %f\n",
  85.545 +				i,
  85.546 +				refBone->name,
  85.547 +				refBone->flags,
  85.548 +				refBone->numChildren,
  85.549 +				refBone->parentIndex,
  85.550 +				refBone->bone.quat[0], refBone->bone.quat[1], refBone->bone.quat[2], refBone->bone.quat[3],
  85.551 +				refBone->bone.position[0], refBone->bone.position[1], refBone->bone.position[2],
  85.552 +				refBone->bone.length,
  85.553 +				refBone->bone.xSize,
  85.554 +				refBone->bone.ySize,
  85.555 +				refBone->bone.zSize);
  85.556 +#endif
  85.557 +	}
  85.558 +
  85.559 +	// load animation info
  85.560 +	GetChunkHeader(stream, &chunkHeader);
  85.561 +	if(Q_stricmpn(chunkHeader.ident, "ANIMINFO", 8))
  85.562 +	{
  85.563 +		ri.Printf(PRINT_WARNING, "R_LoadPSA: '%s' has wrong chunk indent ('%s' should be '%s')\n", name, chunkHeader.ident, "ANIMINFO");
  85.564 +		FreeMemStream(stream);
  85.565 +		return qfalse;
  85.566 +	}
  85.567 +
  85.568 +	if(chunkHeader.dataSize != sizeof(axAnimationInfo_t))
  85.569 +	{
  85.570 +		ri.Printf(PRINT_WARNING, "R_LoadPSA: '%s' has wrong chunk dataSize ('%i' should be '%i')\n", name, chunkHeader.dataSize, sizeof(axAnimationInfo_t));
  85.571 +		FreeMemStream(stream);
  85.572 +		return qfalse;
  85.573 +	}
  85.574 +
  85.575 +	PrintChunkHeader(&chunkHeader);
  85.576 +
  85.577 +	numSequences = chunkHeader.numData;
  85.578 +	Com_InitGrowList(&extraAnims, numSequences -1);
  85.579 +	for(i = 0; i < numSequences; i++)
  85.580 +	{
  85.581 +		if(i == 0)
  85.582 +		{
  85.583 +			Q_strncpyz(skelAnim->name, name, sizeof(skelAnim->name));
  85.584 +			skelAnim->type = AT_PSA;
  85.585 +			skelAnim->psa = psa = ri.Hunk_Alloc(sizeof(*psa), h_low);
  85.586 +		}
  85.587 +		else
  85.588 +		{
  85.589 +			// allocate a new skelAnimation_t
  85.590 +			if((extraAnim = R_AllocAnimation()) == NULL)
  85.591 +			{
  85.592 +				ri.Printf(PRINT_WARNING, "R_LoadPSA: R_AllocAnimation() failed for '%s'\n", name);
  85.593 +				return qfalse;
  85.594 +			}
  85.595 +
  85.596 +			Q_strncpyz(extraAnim->name, name, sizeof(extraAnim->name));
  85.597 +			extraAnim->type = AT_PSA;
  85.598 +			extraAnim->psa = psa = ri.Hunk_Alloc(sizeof(*psa), h_low);
  85.599 +
  85.600 +			Com_AddToGrowList(&extraAnims, extraAnim);
  85.601 +		}
  85.602 +
  85.603 +		psa->numBones = numReferenceBones;
  85.604 +		psa->bones = refBones;
  85.605 +
  85.606 +		animInfo = &psa->info;
  85.607 +
  85.608 +		MemStreamRead(stream, animInfo->name, sizeof(animInfo->name));
  85.609 +		MemStreamRead(stream, animInfo->group, sizeof(animInfo->group));
  85.610 +
  85.611 +		animInfo->numBones = MemStreamGetLong(stream);
  85.612 +
  85.613 +		if(animInfo->numBones != numReferenceBones)
  85.614 +		{
  85.615 +			ri.Error(ERR_DROP, "R_LoadPSA: axAnimationInfo_t contains different number than reference bones exist: %i != %i for anim '%s'", animInfo->numBones, numReferenceBones, name);
  85.616 +		}
  85.617 +
  85.618 +		animInfo->rootInclude = MemStreamGetLong(stream);
  85.619 +
  85.620 +		animInfo->keyCompressionStyle = MemStreamGetLong(stream);
  85.621 +		animInfo->keyQuotum = MemStreamGetLong(stream);
  85.622 +		animInfo->keyReduction = MemStreamGetFloat(stream);
  85.623 +
  85.624 +		animInfo->trackTime = MemStreamGetFloat(stream);
  85.625 +
  85.626 +		animInfo->frameRate = MemStreamGetFloat(stream);
  85.627 +
  85.628 +		animInfo->startBoneIndex = MemStreamGetLong(stream);
  85.629 +
  85.630 +		animInfo->firstRawFrame = MemStreamGetLong(stream);
  85.631 +		animInfo->numRawFrames = MemStreamGetLong(stream);
  85.632 +
  85.633 +#if 0
  85.634 +		ri.Printf(PRINT_ALL, "R_LoadPSA: axAnimationInfo_t(%i):\n"
  85.635 +				"axAnimationInfo_t::name: '%s'\n"
  85.636 +				"axAnimationInfo_t::group: '%s'\n"
  85.637 +				"axAnimationInfo_t::numBones: %i\n"
  85.638 +				"axAnimationInfo_t::rootInclude: %i\n"
  85.639 +				"axAnimationInfo_t::keyCompressionStyle: %i\n"
  85.640 +				"axAnimationInfo_t::keyQuotum: %i\n"
  85.641 +				"axAnimationInfo_t::keyReduction: %f\n"
  85.642 +				"axAnimationInfo_t::trackTime: %f\n"
  85.643 +				"axAnimationInfo_t::frameRate: %f\n"
  85.644 +				"axAnimationInfo_t::startBoneIndex: %i\n"
  85.645 +				"axAnimationInfo_t::firstRawFrame: %i\n"
  85.646 +				"axAnimationInfo_t::numRawFrames: %i\n",
  85.647 +				i,
  85.648 +				animInfo->name,
  85.649 +				animInfo->group,
  85.650 +				animInfo->numBones,
  85.651 +				animInfo->rootInclude,
  85.652 +				animInfo->keyCompressionStyle,
  85.653 +				animInfo->keyQuotum,
  85.654 +				animInfo->keyReduction,
  85.655 +				animInfo->trackTime,
  85.656 +				animInfo->frameRate,
  85.657 +				animInfo->startBoneIndex,
  85.658 +				animInfo->firstRawFrame,
  85.659 +				animInfo->numRawFrames);
  85.660 +#endif
  85.661 +	}
  85.662 +
  85.663 +	// load the animation frame keys
  85.664 +	GetChunkHeader(stream, &chunkHeader);
  85.665 +	if(Q_stricmpn(chunkHeader.ident, "ANIMKEYS", 8))
  85.666 +	{
  85.667 +		ri.Printf(PRINT_WARNING, "R_LoadPSA: '%s' has wrong chunk indent ('%s' should be '%s')\n", name, chunkHeader.ident, "ANIMKEYS");
  85.668 +		FreeMemStream(stream);
  85.669 +		return qfalse;
  85.670 +	}
  85.671 +
  85.672 +	if(chunkHeader.dataSize != sizeof(axAnimationKey_t))
  85.673 +	{
  85.674 +		ri.Printf(PRINT_WARNING, "R_LoadPSA: '%s' has wrong chunk dataSize ('%i' should be '%i')\n", name, chunkHeader.dataSize, sizeof(axAnimationKey_t));
  85.675 +		FreeMemStream(stream);
  85.676 +		return qfalse;
  85.677 +	}
  85.678 +
  85.679 +	PrintChunkHeader(&chunkHeader);
  85.680 +
  85.681 +	for(i = 0; i < numSequences; i++)
  85.682 +	{
  85.683 +		if(i == 0)
  85.684 +		{
  85.685 +			psa = skelAnim->psa;
  85.686 +		}
  85.687 +		else
  85.688 +		{
  85.689 +			extraAnim = Com_GrowListElement(&extraAnims, i - 1);
  85.690 +			psa = extraAnim->psa;
  85.691 +		}
  85.692 +
  85.693 +		psa->numKeys = psa->info.numBones * psa->info.numRawFrames;
  85.694 +		psa->keys = ri.Hunk_Alloc(psa->numKeys * sizeof(axAnimationKey_t), h_low);
  85.695 +
  85.696 +		for(j = 0, key = &psa->keys[0]; j < psa->numKeys; j++, key++)
  85.697 +		{
  85.698 +			for(k = 0; k < 3; k++)
  85.699 +			{
  85.700 +				key->position[k] = MemStreamGetFloat(stream);
  85.701 +			}
  85.702 +
  85.703 +			// Tr3B: see R_LoadPSK ...
  85.704 +			if((j % psa->info.numBones) == 0)
  85.705 +			{
  85.706 +				key->quat[0] = MemStreamGetFloat(stream);
  85.707 +				key->quat[1] = -MemStreamGetFloat(stream);
  85.708 +				key->quat[2] = MemStreamGetFloat(stream);
  85.709 +				key->quat[3] = MemStreamGetFloat(stream);
  85.710 +			}
  85.711 +			else
  85.712 +			{
  85.713 +				key->quat[0] = -MemStreamGetFloat(stream);
  85.714 +				key->quat[1] = -MemStreamGetFloat(stream);
  85.715 +				key->quat[2] = -MemStreamGetFloat(stream);
  85.716 +				key->quat[3] = MemStreamGetFloat(stream);
  85.717 +			}
  85.718 +
  85.719 +			key->time = MemStreamGetFloat(stream);
  85.720 +		}
  85.721 +	}
  85.722 +
  85.723 +	Com_DestroyGrowList(&extraAnims);
  85.724 +	FreeMemStream(stream);
  85.725 +
  85.726 +	return qtrue;
  85.727 +}
  85.728 +
  85.729 +/*
  85.730 +===============
  85.731 +RE_RegisterAnimation
  85.732 +===============
  85.733 +*/
  85.734 +qhandle_t RE_RegisterAnimation(const char *name)
  85.735 +{
  85.736 +	int             i, j;
  85.737 +	qhandle_t       hAnim;
  85.738 +	skelAnimation_t *anim;
  85.739 +	char           *buffer;
  85.740 +	int             bufferLen;
  85.741 +	qboolean		loaded = qfalse;
  85.742 +
  85.743 +	if(!name || !name[0])
  85.744 +	{
  85.745 +		Com_Printf("Empty name passed to RE_RegisterAnimation\n");
  85.746 +		return 0;
  85.747 +	}
  85.748 +
  85.749 +	if(strlen(name) >= MAX_QPATH)
  85.750 +	{
  85.751 +		Com_Printf("Animation name exceeds MAX_QPATH\n");
  85.752 +		return 0;
  85.753 +	}
  85.754 +
  85.755 +	// search the currently loaded animations
  85.756 +	for(hAnim = 1; hAnim < tr.numAnimations; hAnim++)
  85.757 +	{
  85.758 +		anim = tr.animations[hAnim];
  85.759 +		if(!Q_stricmp(anim->name, name))
  85.760 +		{
  85.761 +			if(anim->type == AT_BAD)
  85.762 +			{
  85.763 +				return 0;
  85.764 +			}
  85.765 +			return hAnim;
  85.766 +		}
  85.767 +
  85.768 +		if(anim->type == AT_PSA && anim->psa)
  85.769 +		{
  85.770 +			const char *animName;
  85.771 +
  85.772 +			animName = strstr(name, "::");
  85.773 +			if(animName && *(animName + 2) && !Q_stricmp(anim->psa->info.name, animName))
  85.774 +			{
  85.775 +				return hAnim;
  85.776 +			}
  85.777 +		}
  85.778 +	}
  85.779 +
  85.780 +	// allocate a new model_t
  85.781 +	if((anim = R_AllocAnimation()) == NULL)
  85.782 +	{
  85.783 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: R_AllocAnimation() failed for '%s'\n", name);
  85.784 +		return 0;
  85.785 +	}
  85.786 +
  85.787 +	// only set the name after the animation has been successfully allocated
  85.788 +	Q_strncpyz(anim->name, name, sizeof(anim->name));
  85.789 +
  85.790 +	// make sure the render thread is stopped
  85.791 +	R_SyncRenderThread();
  85.792 +
  85.793 +	// load and parse the .md5anim file
  85.794 +	bufferLen = ri.FS_ReadFile(name, (void **)&buffer);
  85.795 +	if(!buffer)
  85.796 +	{
  85.797 +		return 0;
  85.798 +	}
  85.799 +
  85.800 +	if(!Q_stricmpn((const char *)buffer, "MD5Version", 10))
  85.801 +	{
  85.802 +		loaded = R_LoadMD5Anim(anim, buffer, bufferLen, name);
  85.803 +	}
  85.804 +	else if(!Q_stricmpn((const char *)buffer, "ANIMHEAD", 8))
  85.805 +	{
  85.806 +		loaded = R_LoadPSA(anim, buffer, bufferLen, name);
  85.807 +	}
  85.808 +	else
  85.809 +	{
  85.810 +		ri.Printf(PRINT_WARNING, "RE_RegisterAnimation: unknown fileid for '%s'\n", name);
  85.811 +	}
  85.812 +
  85.813 +	ri.FS_FreeFile(buffer);
  85.814 +
  85.815 +	if(!loaded)
  85.816 +	{
  85.817 +		ri.Printf(PRINT_WARNING, "couldn't load '%s'\n", name);
  85.818 +
  85.819 +		// we still keep the model_t around, so if the model name is asked for
  85.820 +		// again, we won't bother scanning the filesystem
  85.821 +		anim->type = AT_BAD;
  85.822 +	}
  85.823 +
  85.824 +	return anim->index;
  85.825 +}
  85.826 +
  85.827 +
  85.828 +/*
  85.829 +================
  85.830 +R_GetAnimationByHandle
  85.831 +================
  85.832 +*/
  85.833 +skelAnimation_t *R_GetAnimationByHandle(qhandle_t index)
  85.834 +{
  85.835 +	skelAnimation_t *anim;
  85.836 +
  85.837 +	// out of range gets the default animation
  85.838 +	if(index < 1 || index >= tr.numAnimations)
  85.839 +	{
  85.840 +		return tr.animations[0];
  85.841 +	}
  85.842 +
  85.843 +	anim = tr.animations[index];
  85.844 +
  85.845 +	return anim;
  85.846 +}
  85.847 +
  85.848 +/*
  85.849 +================
  85.850 +R_AnimationList_f
  85.851 +================
  85.852 +*/
  85.853 +void R_AnimationList_f(void)
  85.854 +{
  85.855 +	int             i;
  85.856 +	skelAnimation_t *anim;
  85.857 +
  85.858 +	for(i = 0; i < tr.numAnimations; i++)
  85.859 +	{
  85.860 +		anim = tr.animations[i];
  85.861 +
  85.862 +		if(anim->type == AT_PSA && anim->psa)
  85.863 +		{
  85.864 +			ri.Printf(PRINT_ALL, "'%s' : '%s'\n", anim->name, anim->psa->info.name);
  85.865 +		}
  85.866 +		else
  85.867 +		{
  85.868 +			ri.Printf(PRINT_ALL, "'%s'\n", anim->name);
  85.869 +		}
  85.870 +	}
  85.871 +	ri.Printf(PRINT_ALL, "%8i : Total animations\n", tr.numAnimations);
  85.872 +}
  85.873 +
  85.874 +/*
  85.875 +=============
  85.876 +R_CullMD5
  85.877 +=============
  85.878 +*/
  85.879 +static void R_CullMD5(trRefEntity_t * ent)
  85.880 +{
  85.881 +	int             i;
  85.882 +	md5Model_t     *model;
  85.883 +
  85.884 +	if(ent->e.skeleton.type == SK_INVALID)
  85.885 +	{
  85.886 +		// no properly set skeleton so use the bounding box by the model instead by the animations
  85.887 +		model = tr.currentModel->md5;
  85.888 +
  85.889 +		VectorCopy(model->bounds[0], ent->localBounds[0]);
  85.890 +		VectorCopy(model->bounds[1], ent->localBounds[1]);
  85.891 +	}
  85.892 +	else
  85.893 +	{
  85.894 +		// copy a bounding box in the current coordinate system provided by skeleton
  85.895 +		for(i = 0; i < 3; i++)
  85.896 +		{
  85.897 +			ent->localBounds[0][i] = ent->e.skeleton.bounds[0][i];
  85.898 +			ent->localBounds[1][i] = ent->e.skeleton.bounds[1][i];
  85.899 +		}
  85.900 +	}
  85.901 +
  85.902 +	switch (R_CullLocalBox(ent->localBounds))
  85.903 +	{
  85.904 +		case CULL_IN:
  85.905 +			tr.pc.c_box_cull_md5_in++;
  85.906 +			ent->cull = CULL_IN;
  85.907 +			return;
  85.908 +
  85.909 +		case CULL_CLIP:
  85.910 +			tr.pc.c_box_cull_md5_clip++;
  85.911 +			ent->cull = CULL_CLIP;
  85.912 +			return;
  85.913 +
  85.914 +		case CULL_OUT:
  85.915 +		default:
  85.916 +			tr.pc.c_box_cull_md5_out++;
  85.917 +			ent->cull = CULL_OUT;
  85.918 +			return;
  85.919  	}
  85.920  }
  85.921  
  85.922  /*
  85.923  ==============
  85.924 -RB_SurfaceAnim
  85.925 +R_AddMD5Surfaces
  85.926  ==============
  85.927  */
  85.928 -void RB_SurfaceAnim( md4Surface_t *surface ) {
  85.929 -	int				i, j, k;
  85.930 -	float			frontlerp, backlerp;
  85.931 -	int				*triangles;
  85.932 -	int				indexes;
  85.933 -	int				baseIndex, baseVertex;
  85.934 -	int				numVerts;
  85.935 -	md4Vertex_t		*v;
  85.936 -	md4Bone_t		bones[MD4_MAX_BONES];
  85.937 -	md4Bone_t		*bonePtr, *bone;
  85.938 -	md4Header_t		*header;
  85.939 -	md4Frame_t		*frame;
  85.940 -	md4Frame_t		*oldFrame;
  85.941 -	int				frameSize;
  85.942 +void R_AddMD5Surfaces(trRefEntity_t * ent)
  85.943 +{
  85.944 +	md5Model_t     *model;
  85.945 +	md5Surface_t   *surface;
  85.946 +	shader_t       *shader;
  85.947 +	int             i;
  85.948 +	qboolean        personalModel;
  85.949  
  85.950 +	model = tr.currentModel->md5;
  85.951  
  85.952 -	if (  backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) {
  85.953 -		backlerp = 0;
  85.954 -		frontlerp = 1;
  85.955 -	} else  {
  85.956 -		backlerp = backEnd.currentEntity->e.backlerp;
  85.957 -		frontlerp = 1.0f - backlerp;
  85.958 -	}
  85.959 -	header = (md4Header_t *)((byte *)surface + surface->ofsHeader);
  85.960 +	// don't add third_person objects if not in a portal
  85.961 +	personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal;
  85.962  
  85.963 -	frameSize = (size_t)( &((md4Frame_t *)0)->bones[ header->numBones ] );
  85.964 -
  85.965 -	frame = (md4Frame_t *)((byte *)header + header->ofsFrames + 
  85.966 -			backEnd.currentEntity->e.frame * frameSize );
  85.967 -	oldFrame = (md4Frame_t *)((byte *)header + header->ofsFrames + 
  85.968 -			backEnd.currentEntity->e.oldframe * frameSize );
  85.969 -
  85.970 -	RB_CheckOverflow( surface->numVerts, surface->numTriangles * 3 );
  85.971 -
  85.972 -	triangles = (int *) ((byte *)surface + surface->ofsTriangles);
  85.973 -	indexes = surface->numTriangles * 3;
  85.974 -	baseIndex = tess.numIndexes;
  85.975 -	baseVertex = tess.numVertexes;
  85.976 -	for (j = 0 ; j < indexes ; j++) {
  85.977 -		tess.indexes[baseIndex + j] = baseIndex + triangles[j];
  85.978 -	}
  85.979 -	tess.numIndexes += indexes;
  85.980 -
  85.981 -	//
  85.982 -	// lerp all the needed bones
  85.983 -	//
  85.984 -	if ( !backlerp ) {
  85.985 -		// no lerping needed
  85.986 -		bonePtr = frame->bones;
  85.987 -	} else {
  85.988 -		bonePtr = bones;
  85.989 -		for ( i = 0 ; i < header->numBones*12 ; i++ ) {
  85.990 -			((float *)bonePtr)[i] = frontlerp * ((float *)frame->bones)[i]
  85.991 -					+ backlerp * ((float *)oldFrame->bones)[i];
  85.992 -		}
  85.993 +	// cull the entire model if merged bounding box of both frames
  85.994 +	// is outside the view frustum
  85.995 +	R_CullMD5(ent);
  85.996 +	if(ent->cull == CULL_OUT)
  85.997 +	{
  85.998 +		return;
  85.999  	}
 85.1000  
 85.1001 -	//
 85.1002 -	// deform the vertexes by the lerped bones
 85.1003 -	//
 85.1004 -	numVerts = surface->numVerts;
 85.1005 -	// FIXME
 85.1006 -	// This makes TFC's skeletons work.  Shouldn't be necessary anymore, but left
 85.1007 -	// in for reference.
 85.1008 -	//v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts + 12);
 85.1009 -	v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts);
 85.1010 -	for ( j = 0; j < numVerts; j++ ) {
 85.1011 -		vec3_t	tempVert, tempNormal;
 85.1012 -		md4Weight_t	*w;
 85.1013 +	// set up world bounds for light intersection tests
 85.1014 +	R_SetupEntityWorldBounds(ent);
 85.1015  
 85.1016 -		VectorClear( tempVert );
 85.1017 -		VectorClear( tempNormal );
 85.1018 -		w = v->weights;
 85.1019 -		for ( k = 0 ; k < v->numWeights ; k++, w++ ) {
 85.1020 -			bone = bonePtr + w->boneIndex;
 85.1021 -
 85.1022 -			tempVert[0] += w->boneWeight * ( DotProduct( bone->matrix[0], w->offset ) + bone->matrix[0][3] );
 85.1023 -			tempVert[1] += w->boneWeight * ( DotProduct( bone->matrix[1], w->offset ) + bone->matrix[1][3] );
 85.1024 -			tempVert[2] += w->boneWeight * ( DotProduct( bone->matrix[2], w->offset ) + bone->matrix[2][3] );
 85.1025 -
 85.1026 -			tempNormal[0] += w->boneWeight * DotProduct( bone->matrix[0], v->normal );
 85.1027 -			tempNormal[1] += w->boneWeight * DotProduct( bone->matrix[1], v->normal );
 85.1028 -			tempNormal[2] += w->boneWeight * DotProduct( bone->matrix[2], v->normal );
 85.1029 -		}
 85.1030 -
 85.1031 -		tess.xyz[baseVertex + j][0] = tempVert[0];
 85.1032 -		tess.xyz[baseVertex + j][1] = tempVert[1];
 85.1033 -		tess.xyz[baseVertex + j][2] = tempVert[2];
 85.1034 -
 85.1035 -		tess.normal[baseVertex + j][0] = tempNormal[0];
 85.1036 -		tess.normal[baseVertex + j][1] = tempNormal[1];
 85.1037 -		tess.normal[baseVertex + j][2] = tempNormal[2];
 85.1038 -
 85.1039 -		tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
 85.1040 -		tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];
 85.1041 -
 85.1042 -		// FIXME
 85.1043 -		// This makes TFC's skeletons work.  Shouldn't be necessary anymore, but left
 85.1044 -		// in for reference.
 85.1045 -		//v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 );
 85.1046 -		v = (md4Vertex_t *)&v->weights[v->numWeights];
 85.1047 +	// set up lighting now that we know we aren't culled
 85.1048 +	if(!personalModel || r_shadows->integer > 1)
 85.1049 +	{
 85.1050 +		R_SetupEntityLighting(&tr.refdef, ent);
 85.1051  	}
 85.1052  
 85.1053 -	tess.numVertexes += surface->numVerts;
 85.1054 -}
 85.1055 +	if(!r_vboModels->integer || !model->numVBOSurfaces ||
 85.1056 +	   (!glConfig.vboVertexSkinningAvailable && ent->e.skeleton.type == SK_ABSOLUTE))
 85.1057 +	{
 85.1058 +		// finally add surfaces
 85.1059 +		for(i = 0, surface = model->surfaces; i < model->numSurfaces; i++, surface++)
 85.1060 +		{
 85.1061 +			if(ent->e.customShader)
 85.1062 +			{
 85.1063 +				shader = R_GetShaderByHandle(ent->e.customShader);
 85.1064 +			}
 85.1065 +			else if(ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins)
 85.1066 +			{
 85.1067 +				skin_t         *skin;
 85.1068  
 85.1069 +				skin = R_GetSkinByHandle(ent->e.customSkin);
 85.1070  
 85.1071 -#ifdef RAVENMD4
 85.1072 +				// match the surface name to something in the skin file
 85.1073 +				shader = tr.defaultShader;
 85.1074  
 85.1075 -// copied and adapted from tr_mesh.c
 85.1076 -
 85.1077 -/*
 85.1078 -=============
 85.1079 -R_MDRCullModel
 85.1080 -=============
 85.1081 -*/
 85.1082 -
 85.1083 -static int R_MDRCullModel( mdrHeader_t *header, trRefEntity_t *ent ) {
 85.1084 -	vec3_t		bounds[2];
 85.1085 -	mdrFrame_t	*oldFrame, *newFrame;
 85.1086 -	int			i, frameSize;
 85.1087 -
 85.1088 -	frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] );
 85.1089 -	
 85.1090 -	// compute frame pointers
 85.1091 -	newFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame);
 85.1092 -	oldFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.oldframe);
 85.1093 -
 85.1094 -	// cull bounding sphere ONLY if this is not an upscaled entity
 85.1095 -	if ( !ent->e.nonNormalizedAxes )
 85.1096 -	{
 85.1097 -		if ( ent->e.frame == ent->e.oldframe )
 85.1098 -		{
 85.1099 -			switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) )
 85.1100 +				// FIXME: replace MD3_MAX_SURFACES for skin_t::surfaces
 85.1101 +				if(i >= 0 && i < skin->numSurfaces && skin->surfaces[i])
 85.1102 +				{
 85.1103 +					shader = skin->surfaces[i]->shader;
 85.1104 +				}
 85.1105 +				if(shader == tr.defaultShader)
 85.1106 +				{
 85.1107 +					ri.Printf(PRINT_DEVELOPER, "WARNING: no shader for surface %i in skin %s\n", i, skin->name);
 85.1108 +				}
 85.1109 +				else if(shader->defaultShader)
 85.1110 +				{
 85.1111 +					ri.Printf(PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
 85.1112 +				}
 85.1113 +			}
 85.1114 +			else
 85.1115  			{
 85.1116 -				// Ummm... yeah yeah I know we don't really have an md3 here.. but we pretend
 85.1117 -				// we do. After all, the purpose of md4s are not that different, are they?
 85.1118 -				
 85.1119 -				case CULL_OUT:
 85.1120 -					tr.pc.c_sphere_cull_md3_out++;
 85.1121 -					return CULL_OUT;
 85.1122 -
 85.1123 -				case CULL_IN:
 85.1124 -					tr.pc.c_sphere_cull_md3_in++;
 85.1125 -					return CULL_IN;
 85.1126 -
 85.1127 -				case CULL_CLIP:
 85.1128 -					tr.pc.c_sphere_cull_md3_clip++;
 85.1129 -					break;
 85.1130 -			}
 85.1131 -		}
 85.1132 -		else
 85.1133 -		{
 85.1134 -			int sphereCull, sphereCullB;
 85.1135 -
 85.1136 -			sphereCull  = R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius );
 85.1137 -			if ( newFrame == oldFrame ) {
 85.1138 -				sphereCullB = sphereCull;
 85.1139 -			} else {
 85.1140 -				sphereCullB = R_CullLocalPointAndRadius( oldFrame->localOrigin, oldFrame->radius );
 85.1141 +				shader = R_GetShaderByHandle(surface->shaderIndex);
 85.1142  			}
 85.1143  
 85.1144 -			if ( sphereCull == sphereCullB )
 85.1145 +			// we will add shadows even if the main object isn't visible in the view
 85.1146 +
 85.1147 +			// projection shadows work fine with personal models
 85.1148 +			if(r_shadows->integer == 2 && (ent->e.renderfx & RF_SHADOW_PLANE) && shader->sort == SS_OPAQUE)
 85.1149  			{
 85.1150 -				if ( sphereCull == CULL_OUT )
 85.1151 -				{
 85.1152 -					tr.pc.c_sphere_cull_md3_out++;
 85.1153 -					return CULL_OUT;
 85.1154 -				}
 85.1155 -				else if ( sphereCull == CULL_IN )
 85.1156 -				{
 85.1157 -					tr.pc.c_sphere_cull_md3_in++;
 85.1158 -					return CULL_IN;
 85.1159 -				}
 85.1160 -				else
 85.1161 -				{
 85.1162 -					tr.pc.c_sphere_cull_md3_clip++;
 85.1163 -				}
 85.1164 +				R_AddDrawSurf((void *)surface, tr.projectionShadowShader, -1);
 85.1165 +			}
 85.1166 +
 85.1167 +			// don't add third_person objects if not viewing through a portal
 85.1168 +			if(!personalModel)
 85.1169 +			{
 85.1170 +				R_AddDrawSurf((void *)surface, shader, -1);
 85.1171  			}
 85.1172  		}
 85.1173  	}
 85.1174 -	
 85.1175 -	// calculate a bounding box in the current coordinate system
 85.1176 -	for (i = 0 ; i < 3 ; i++) {
 85.1177 -		bounds[0][i] = oldFrame->bounds[0][i] < newFrame->bounds[0][i] ? oldFrame->bounds[0][i] : newFrame->bounds[0][i];
 85.1178 -		bounds[1][i] = oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i];
 85.1179 -	}
 85.1180 +	else
 85.1181 +	{
 85.1182 +		int             i;
 85.1183 +		srfVBOMD5Mesh_t *vboSurface;
 85.1184 +		shader_t       *shader;
 85.1185  
 85.1186 -	switch ( R_CullLocalBox( bounds ) )
 85.1187 -	{
 85.1188 -		case CULL_IN:
 85.1189 -			tr.pc.c_box_cull_md3_in++;
 85.1190 -			return CULL_IN;
 85.1191 -		case CULL_CLIP:
 85.1192 -			tr.pc.c_box_cull_md3_clip++;
 85.1193 -			return CULL_CLIP;
 85.1194 -		case CULL_OUT:
 85.1195 -		default:
 85.1196 -			tr.pc.c_box_cull_md3_out++;
 85.1197 -			return CULL_OUT;
 85.1198 +		for(i = 0; i < model->numVBOSurfaces; i++)
 85.1199 +		{
 85.1200 +			vboSurface = model->vboSurfaces[i];
 85.1201 +
 85.1202 +			if(ent->e.customShader)
 85.1203 +			{
 85.1204 +				shader = R_GetShaderByHandle(ent->e.customShader);
 85.1205 +			}
 85.1206 +			else if(ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins)
 85.1207 +			{
 85.1208 +				skin_t         *skin;
 85.1209 +
 85.1210 +				skin = R_GetSkinByHandle(ent->e.customSkin);
 85.1211 +
 85.1212 +				// match the surface name to something in the skin file
 85.1213 +				shader = tr.defaultShader;
 85.1214 +
 85.1215 +				// FIXME: replace MD3_MAX_SURFACES for skin_t::surfaces
 85.1216 +				//if(i >= 0 && i < skin->numSurfaces && skin->surfaces[i])
 85.1217 +				if(vboSurface->skinIndex >= 0 && vboSurface->skinIndex < skin->numSurfaces && skin->surfaces[vboSurface->skinIndex])
 85.1218 +				{
 85.1219 +					shader = skin->surfaces[vboSurface->skinIndex]->shader;
 85.1220 +				}
 85.1221 +
 85.1222 +				if(shader == tr.defaultShader)
 85.1223 +				{
 85.1224 +					ri.Printf(PRINT_DEVELOPER, "WARNING: no shader for surface %i in skin %s\n", i, skin->name);
 85.1225 +				}
 85.1226 +				else if(shader->defaultShader)
 85.1227 +				{
 85.1228 +					ri.Printf(PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
 85.1229 +				}
 85.1230 +			}
 85.1231 +			else
 85.1232 +			{
 85.1233 +				shader = vboSurface->shader;
 85.1234 +			}
 85.1235 +
 85.1236 +			// don't add third_person objects if not viewing through a portal
 85.1237 +			if(!personalModel)
 85.1238 +			{
 85.1239 +				R_AddDrawSurf((void *)vboSurface, shader, -1);
 85.1240 +			}
 85.1241 +		}
 85.1242  	}
 85.1243  }
 85.1244  
 85.1245  /*
 85.1246  =================
 85.1247 -R_MDRComputeFogNum
 85.1248 -
 85.1249 +R_AddMD5Interactions
 85.1250  =================
 85.1251  */
 85.1252 +void R_AddMD5Interactions(trRefEntity_t * ent, trRefLight_t * light)
 85.1253 +{
 85.1254 +	int             i;
 85.1255 +	md5Model_t     *model;
 85.1256 +	md5Surface_t   *surface;
 85.1257 +	shader_t       *shader = 0;
 85.1258 +	qboolean        personalModel;
 85.1259 +	byte            cubeSideBits = CUBESIDE_CLIPALL;
 85.1260 +	interactionType_t iaType = IA_DEFAULT;
 85.1261  
 85.1262 -int R_MDRComputeFogNum( mdrHeader_t *header, trRefEntity_t *ent ) {
 85.1263 -	int				i, j;
 85.1264 -	fog_t			*fog;
 85.1265 -	mdrFrame_t		*mdrFrame;
 85.1266 -	vec3_t			localOrigin;
 85.1267 -	int frameSize;
 85.1268 +	// cull the entire model if merged bounding box of both frames
 85.1269 +	// is outside the view frustum and we don't care about proper shadowing
 85.1270 +	if(ent->cull == CULL_OUT)
 85.1271 +	{
 85.1272 +		if(r_shadows->integer <= 2 || light->l.noShadows)
 85.1273 +			return;
 85.1274 +		else
 85.1275 +			iaType = IA_SHADOWONLY;
 85.1276 +	}
 85.1277  
 85.1278 -	if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
 85.1279 -		return 0;
 85.1280 +	// avoid drawing of certain objects
 85.1281 +	if(light->l.inverseShadows)
 85.1282 +	{
 85.1283 +		if(iaType != IA_LIGHTONLY && (light->l.noShadowID && (light->l.noShadowID != ent->e.noShadowID)))
 85.1284 +			return;
 85.1285  	}
 85.1286 -	
 85.1287 -	frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] );
 85.1288 +	else
 85.1289 +	{
 85.1290 +		if(iaType != IA_LIGHTONLY && (light->l.noShadowID && (light->l.noShadowID == ent->e.noShadowID)))
 85.1291 +			return;
 85.1292 +	}
 85.1293  
 85.1294 -	// FIXME: non-normalized axis issues
 85.1295 -	mdrFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame);
 85.1296 -	VectorAdd( ent->e.origin, mdrFrame->localOrigin, localOrigin );
 85.1297 -	for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
 85.1298 -		fog = &tr.world->fogs[i];
 85.1299 -		for ( j = 0 ; j < 3 ; j++ ) {
 85.1300 -			if ( localOrigin[j] - mdrFrame->radius >= fog->bounds[1][j] ) {
 85.1301 -				break;
 85.1302 +	// don't add third_person objects if not in a portal
 85.1303 +	personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal;
 85.1304 +
 85.1305 +	model = tr.currentModel->md5;
 85.1306 +
 85.1307 +	// do a quick AABB cull
 85.1308 +	if(!BoundsIntersect(light->worldBounds[0], light->worldBounds[1], ent->worldBounds[0], ent->worldBounds[1]))
 85.1309 +	{
 85.1310 +		tr.pc.c_dlightSurfacesCulled += model->numSurfaces;
 85.1311 +		return;
 85.1312 +	}
 85.1313 +
 85.1314 +	// do a more expensive and precise light frustum cull
 85.1315 +	if(!r_noLightFrustums->integer)
 85.1316 +	{
 85.1317 +		if(R_CullLightWorldBounds(light, ent->worldBounds) == CULL_OUT)
 85.1318 +		{
 85.1319 +			tr.pc.c_dlightSurfacesCulled += model->numSurfaces;
 85.1320 +			return;
 85.1321 +		}
 85.1322 +	}
 85.1323 +
 85.1324 +	cubeSideBits = R_CalcLightCubeSideBits(light, ent->worldBounds);
 85.1325 +
 85.1326 +	if(!r_vboModels->integer || !model->numVBOSurfaces ||
 85.1327 +	   (!glConfig.vboVertexSkinningAvailable && ent->e.skeleton.type == SK_ABSOLUTE))
 85.1328 +	{
 85.1329 +		// generate interactions with all surfaces
 85.1330 +		for(i = 0, surface = model->surfaces; i < model->numSurfaces; i++, surface++)
 85.1331 +		{
 85.1332 +			if(ent->e.customShader)
 85.1333 +			{
 85.1334 +				shader = R_GetShaderByHandle(ent->e.customShader);
 85.1335  			}
 85.1336 -			if ( localOrigin[j] + mdrFrame->radius <= fog->bounds[0][j] ) {
 85.1337 -				break;
 85.1338 +			else if(ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins)
 85.1339 +			{
 85.1340 +				skin_t         *skin;
 85.1341 +
 85.1342 +				skin = R_GetSkinByHandle(ent->e.customSkin);
 85.1343 +
 85.1344 +				// match the surface name to something in the skin file
 85.1345 +				shader = tr.defaultShader;
 85.1346 +
 85.1347 +				// FIXME: replace MD3_MAX_SURFACES for skin_t::surfaces
 85.1348 +				if(i >= 0 && i < skin->numSurfaces && skin->surfaces[i])
 85.1349 +				{
 85.1350 +					shader = skin->surfaces[i]->shader;
 85.1351 +				}
 85.1352 +				if(shader == tr.defaultShader)
 85.1353 +				{
 85.1354 +					ri.Printf(PRINT_DEVELOPER, "WARNING: no shader for surface %i in skin %s\n", i, skin->name);
 85.1355 +				}
 85.1356 +				else if(shader->defaultShader)
 85.1357 +				{
 85.1358 +					ri.Printf(PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
 85.1359 +				}
 85.1360 +			}
 85.1361 +			else
 85.1362 +			{
 85.1363 +				shader = R_GetShaderByHandle(surface->shaderIndex);
 85.1364 +			}
 85.1365 +
 85.1366 +			// skip all surfaces that don't matter for lighting only pass
 85.1367 +			if(shader->isSky || (!shader->interactLight && shader->noShadows))
 85.1368 +				continue;
 85.1369 +
 85.1370 +			// we will add shadows even if the main object isn't visible in the view
 85.1371 +
 85.1372 +			// don't add third_person objects if not viewing through a portal
 85.1373 +			if(!personalModel)
 85.1374 +			{
 85.1375 +				R_AddLightInteraction(light, (void *)surface, shader, cubeSideBits, iaType);
 85.1376 +				tr.pc.c_dlightSurfaces++;
 85.1377  			}
 85.1378  		}
 85.1379 -		if ( j == 3 ) {
 85.1380 -			return i;
 85.1381 +	}
 85.1382 +	else
 85.1383 +	{
 85.1384 +		int             i;
 85.1385 +		srfVBOMD5Mesh_t *vboSurface;
 85.1386 +		shader_t       *shader;
 85.1387 +
 85.1388 +		for(i = 0; i < model->numVBOSurfaces; i++)
 85.1389 +		{
 85.1390 +			vboSurface = model->vboSurfaces[i];
 85.1391 +
 85.1392 +			if(ent->e.customShader)
 85.1393 +			{
 85.1394 +				shader = R_GetShaderByHandle(ent->e.customShader);
 85.1395 +			}
 85.1396 +			else if(ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins)
 85.1397 +			{
 85.1398 +				skin_t         *skin;
 85.1399 +
 85.1400 +				skin = R_GetSkinByHandle(ent->e.customSkin);
 85.1401 +
 85.1402 +				// match the surface name to something in the skin file
 85.1403 +				shader = tr.defaultShader;
 85.1404 +
 85.1405 +				// FIXME: replace MD3_MAX_SURFACES for skin_t::surfaces
 85.1406 +				if(i >= 0 && i < skin->numSurfaces && skin->surfaces[i])
 85.1407 +				{
 85.1408 +					shader = skin->surfaces[i]->shader;
 85.1409 +				}
 85.1410 +				if(shader == tr.defaultShader)
 85.1411 +				{
 85.1412 +					ri.Printf(PRINT_DEVELOPER, "WARNING: no shader for surface %i in skin %s\n", i, skin->name);
 85.1413 +				}
 85.1414 +				else if(shader->defaultShader)
 85.1415 +				{
 85.1416 +					ri.Printf(PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
 85.1417 +				}
 85.1418 +			}
 85.1419 +			else
 85.1420 +			{
 85.1421 +				shader = vboSurface->shader;
 85.1422 +			}
 85.1423 +
 85.1424 +			// skip all surfaces that don't matter for lighting only pass
 85.1425 +			if(shader->isSky || (!shader->interactLight && shader->noShadows))
 85.1426 +				continue;
 85.1427 +
 85.1428 +			// don't add third_person objects if not viewing through a portal
 85.1429 +			if(!personalModel)
 85.1430 +			{
 85.1431 +				R_AddLightInteraction(light, (void *)vboSurface, shader, cubeSideBits, iaType);
 85.1432 +				tr.pc.c_dlightSurfaces++;
 85.1433 +			}
 85.1434  		}
 85.1435  	}
 85.1436 +}
 85.1437 +
 85.1438 +
 85.1439 +/*
 85.1440 +==============
 85.1441 +RE_CheckSkeleton
 85.1442 +
 85.1443 +Tr3B: check if the skeleton bones are the same in the model and animation
 85.1444 +and copy the parentIndex entries into the refSkeleton_t
 85.1445 +==============
 85.1446 +*/
 85.1447 +int RE_CheckSkeleton(refSkeleton_t * skel, qhandle_t hModel, qhandle_t hAnim)
 85.1448 +{
 85.1449 +	int             i;
 85.1450 +	model_t         *model;
 85.1451 +	md5Model_t      *md5Model;
 85.1452 +	skelAnimation_t *skelAnim;
 85.1453 +
 85.1454 +	model = R_GetModelByHandle(hModel);
 85.1455 +	skelAnim = R_GetAnimationByHandle(hAnim);
 85.1456 +
 85.1457 +	if(model->type != MOD_MD5 || !model->md5)
 85.1458 +	{
 85.1459 +		ri.Printf(PRINT_WARNING, "RE_CheckSkeleton: '%s' is not a skeletal model\n", model->name);
 85.1460 +		return qfalse;
 85.1461 +	}
 85.1462 +
 85.1463 +	md5Model = model->md5;
 85.1464 +	if(md5Model->numBones < 1)
 85.1465 +	{
 85.1466 +		ri.Printf(PRINT_WARNING, "RE_CheckSkeleton: '%s' has no bones\n", model->name);
 85.1467 +		return qfalse;
 85.1468 +	}
 85.1469 +	if(md5Model->numBones > MAX_BONES)
 85.1470 +	{
 85.1471 +		ri.Printf(PRINT_WARNING, "RE_CheckSkeleton: '%s' has more than %i bones (%i)\n", model->name, MAX_BONES, md5Model->numBones);
 85.1472 +		return qfalse;
 85.1473 +	}
 85.1474 +
 85.1475 +	if(skelAnim->type == AT_MD5 && skelAnim->md5)
 85.1476 +	{
 85.1477 +		md5Animation_t	*md5Animation;
 85.1478 +		md5Bone_t		*md5Bone;
 85.1479 +		md5Channel_t    *md5Channel;
 85.1480 +
 85.1481 +		md5Animation = skelAnim->md5;
 85.1482 +
 85.1483 +		if(md5Model->numBones != md5Animation->numChannels)
 85.1484 +		{
 85.1485 +			ri.Printf(PRINT_WARNING, "RE_CheckSkeleton: model '%s' has different number of bones than animation '%s': %d != %d\n", model->name, skelAnim->name, md5Model->numBones, md5Animation->numChannels);
 85.1486 +			return qfalse;
 85.1487 +		}
 85.1488 +
 85.1489 +		// check bone names
 85.1490 +		for(i = 0, md5Bone = md5Model->bones, md5Channel = md5Animation->channels; i < md5Model->numBones; i++, md5Bone++, md5Channel++)
 85.1491 +		{
 85.1492 +			if(Q_stricmp(md5Bone->name, md5Channel->name))
 85.1493 +				return qfalse;
 85.1494 +
 85.1495 +			skel->bones[i].parentIndex = md5Bone->parentIndex;
 85.1496 +		}
 85.1497 +
 85.1498 +		return qtrue;
 85.1499 +	}
 85.1500 +	else if(skelAnim->type == AT_PSA && skelAnim->psa)
 85.1501 +	{
 85.1502 +		psaAnimation_t *psaAnimation;
 85.1503 +		axReferenceBone_t *refBone;
 85.1504 +		md5Bone_t		*md5Bone;
 85.1505 +
 85.1506 +		psaAnimation = skelAnim->psa;
 85.1507 +
 85.1508 +		if(md5Model->numBones != psaAnimation->info.numBones)
 85.1509 +		{
 85.1510 +			ri.Printf(PRINT_WARNING, "RE_CheckSkeleton: model '%s' has different number of bones than animation '%s': %d != %d\n", model->name, skelAnim->name, md5Model->numBones, psaAnimation->info.numBones);
 85.1511 +			return qfalse;
 85.1512 +		}
 85.1513 +
 85.1514 +		// check bone names
 85.1515 +		for(i = 0, md5Bone = md5Model->bones, refBone = psaAnimation->bones; i < md5Model->numBones; i++, md5Bone++, refBone++)
 85.1516 +		{
 85.1517 +			if(Q_stricmp(md5Bone->name, refBone->name))
 85.1518 +				return qfalse;
 85.1519 +
 85.1520 +			skel->bones[i].parentIndex = md5Bone->parentIndex;
 85.1521 +		}
 85.1522 +
 85.1523 +		return qtrue;
 85.1524 +	}
 85.1525 +
 85.1526 +	ri.Printf(PRINT_WARNING, "RE_BuildSkeleton: bad animation '%s' with handle %i\n", skelAnim->name, hAnim);
 85.1527 +
 85.1528 +	return qfalse;
 85.1529 +}
 85.1530 +
 85.1531 +/*
 85.1532 +==============
 85.1533 +RE_BuildSkeleton
 85.1534 +==============
 85.1535 +*/
 85.1536 +int RE_BuildSkeleton(refSkeleton_t * skel, qhandle_t hAnim, int startFrame, int endFrame, float frac, qboolean clearOrigin)
 85.1537 +{
 85.1538 +	skelAnimation_t *skelAnim;
 85.1539 +
 85.1540 +	skelAnim = R_GetAnimationByHandle(hAnim);
 85.1541 +
 85.1542 +	if(skelAnim->type == AT_MD5 && skelAnim->md5)
 85.1543 +	{
 85.1544 +		int             i;
 85.1545 +		md5Animation_t *anim;
 85.1546 +		md5Channel_t   *channel;
 85.1547 +		md5Frame_t     *newFrame, *oldFrame;
 85.1548 +		vec3_t          newOrigin, oldOrigin, lerpedOrigin;
 85.1549 +		quat_t          newQuat, oldQuat, lerpedQuat;
 85.1550 +		int             componentsApplied;
 85.1551 +
 85.1552 +		anim = skelAnim->md5;
 85.1553 +
 85.1554 +		// Validate the frames so there is no chance of a crash.
 85.1555 +		// This will write directly into the entity structure, so
 85.1556 +		// when the surfaces are rendered, they don't need to be
 85.1557 +		// range checked again.
 85.1558 +		/*
 85.1559 +		   if((startFrame >= anim->numFrames) || (startFrame < 0) || (endFrame >= anim->numFrames) || (endFrame < 0))
 85.1560 +		   {
 85.1561 +		   ri.Printf(PRINT_DEVELOPER, "RE_BuildSkeleton: no such frame %d to %d for '%s'\n", startFrame, endFrame, anim->name);
 85.1562 +		   //startFrame = 0;
 85.1563 +		   //endFrame = 0;
 85.1564 +		   }
 85.1565 +		 */
 85.1566 +
 85.1567 +		Q_clamp(startFrame, 0, anim->numFrames - 1);
 85.1568 +		Q_clamp(endFrame, 0, anim->numFrames - 1);
 85.1569 +
 85.1570 +		// compute frame pointers
 85.1571 +		oldFrame = &anim->frames[startFrame];
 85.1572 +		newFrame = &anim->frames[endFrame];
 85.1573 +
 85.1574 +		// calculate a bounding box in the current coordinate system
 85.1575 +		for(i = 0; i < 3; i++)
 85.1576 +		{
 85.1577 +			skel->bounds[0][i] =
 85.1578 +				oldFrame->bounds[0][i] < newFrame->bounds[0][i] ? oldFrame->bounds[0][i] : newFrame->bounds[0][i];
 85.1579 +			skel->bounds[1][i] =
 85.1580 +				oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i];
 85.1581 +		}
 85.1582 +
 85.1583 +		for(i = 0, channel = anim->channels; i < anim->numChannels; i++, channel++)
 85.1584 +		{
 85.1585 +			// set baseframe values
 85.1586 +			VectorCopy(channel->baseOrigin, newOrigin);
 85.1587 +			VectorCopy(channel->baseOrigin, oldOrigin);
 85.1588 +
 85.1589 +			QuatCopy(channel->baseQuat, newQuat);
 85.1590 +			QuatCopy(channel->baseQuat, oldQuat);
 85.1591 +
 85.1592 +			componentsApplied = 0;
 85.1593 +
 85.1594 +			// update tranlation bits
 85.1595 +			if(channel->componentsBits & COMPONENT_BIT_TX)
 85.1596 +			{
 85.1597 +				oldOrigin[0] = oldFrame->components[channel->componentsOffset + componentsApplied];
 85.1598 +				newOrigin[0] = newFrame->components[channel->componentsOffset + componentsApplied];
 85.1599 +				componentsApplied++;
 85.1600 +			}
 85.1601 +
 85.1602 +			if(channel->componentsBits & COMPONENT_BIT_TY)
 85.1603 +			{
 85.1604 +				oldOrigin[1] = oldFrame->components[channel->componentsOffset + componentsApplied];
 85.1605 +				newOrigin[1] = newFrame->components[channel->componentsOffset + componentsApplied];
 85.1606 +				componentsApplied++;
 85.1607 +			}
 85.1608 +
 85.1609 +			if(channel->componentsBits & COMPONENT_BIT_TZ)
 85.1610 +			{
 85.1611 +				oldOrigin[2] = oldFrame->components[channel->componentsOffset + componentsApplied];
 85.1612 +				newOrigin[2] = newFrame->components[channel->componentsOffset + componentsApplied];
 85.1613 +				componentsApplied++;
 85.1614 +			}
 85.1615 +
 85.1616 +			// update quaternion rotation bits
 85.1617 +			if(channel->componentsBits & COMPONENT_BIT_QX)
 85.1618 +			{
 85.1619 +				((vec_t *) oldQuat)[0] = oldFrame->components[channel->componentsOffset + componentsApplied];
 85.1620 +				((vec_t *) newQuat)[0] = newFrame->components[channel->componentsOffset + componentsApplied];
 85.1621 +				componentsApplied++;
 85.1622 +			}
 85.1623 +
 85.1624 +			if(channel->componentsBits & COMPONENT_BIT_QY)
 85.1625 +			{
 85.1626 +				((vec_t *) oldQuat)[1] = oldFrame->components[channel->componentsOffset + componentsApplied];
 85.1627 +				((vec_t *) newQuat)[1] = newFrame->components[channel->componentsOffset + componentsApplied];
 85.1628 +				componentsApplied++;
 85.1629 +			}
 85.1630 +
 85.1631 +			if(channel->componentsBits & COMPONENT_BIT_QZ)
 85.1632 +			{
 85.1633 +				((vec_t *) oldQuat)[2] = oldFrame->components[channel->componentsOffset + componentsApplied];
 85.1634 +				((vec_t *) newQuat)[2] = newFrame->components[channel->componentsOffset + componentsApplied];
 85.1635 +			}
 85.1636 +
 85.1637 +			QuatCalcW(oldQuat);
 85.1638 +			QuatNormalize(oldQuat);
 85.1639 +
 85.1640 +			QuatCalcW(newQuat);
 85.1641 +			QuatNormalize(newQuat);
 85.1642 +
 85.1643 +#if 1
 85.1644 +			VectorLerp(oldOrigin, newOrigin, frac, lerpedOrigin);
 85.1645 +			QuatSlerp(oldQuat, newQuat, frac, lerpedQuat);
 85.1646 +#else
 85.1647 +			VectorCopy(newOrigin, lerpedOrigin);
 85.1648 +			QuatCopy(newQuat, lerpedQuat);
 85.1649 +#endif
 85.1650 +
 85.1651 +			// copy lerped information to the bone + extra data
 85.1652 +			skel->bones[i].parentIndex = channel->parentIndex;
 85.1653 +
 85.1654 +			if(channel->parentIndex < 0 && clearOrigin)
 85.1655 +			{
 85.1656 +				VectorClear(skel->bones[i].origin);
 85.1657 +				QuatClear(skel->bones[i].rotation);
 85.1658 +
 85.1659 +				// move bounding box back
 85.1660 +				VectorSubtract(skel->bounds[0], lerpedOrigin, skel->bounds[0]);
 85.1661 +				VectorSubtract(skel->bounds[1], lerpedOrigin, skel->bounds[1]);
 85.1662 +			}
 85.1663 +			else
 85.1664 +			{
 85.1665 +				VectorCopy(lerpedOrigin, skel->bones[i].origin);
 85.1666 +			}
 85.1667 +
 85.1668 +			QuatCopy(lerpedQuat, skel->bones[i].rotation);
 85.1669 +
 85.1670 +			Q_strncpyz(skel->bones[i].name, channel->name, sizeof(skel->bones[i].name));
 85.1671 +		}
 85.1672 +
 85.1673 +		skel->numBones = anim->numChannels;
 85.1674 +		skel->type = SK_RELATIVE;
 85.1675 +		return qtrue;
 85.1676 +	}
 85.1677 +	else if(skelAnim->type == AT_PSA && skelAnim->psa)
 85.1678 +	{
 85.1679 +		int             i;
 85.1680 +		psaAnimation_t *anim;
 85.1681 +		axAnimationKey_t *newKey, *oldKey;
 85.1682 +		axReferenceBone_t *refBone;
 85.1683 +		vec3_t          newOrigin, oldOrigin, lerpedOrigin;
 85.1684 +		quat_t          newQuat, oldQuat, lerpedQuat;
 85.1685 +		refSkeleton_t   skeleton;
 85.1686 +
 85.1687 +		anim = skelAnim->psa;
 85.1688 +
 85.1689 +		Q_clamp(startFrame, 0, anim->info.numRawFrames - 1);
 85.1690 +		Q_clamp(endFrame, 0, anim->info.numRawFrames - 1);
 85.1691 +
 85.1692 +		ClearBounds(skel->bounds[0], skel->bounds[1]);
 85.1693 +
 85.1694 +		skel->numBones = anim->info.numBones;
 85.1695 +		for(i = 0, refBone = anim->bones; i < anim->info.numBones; i++, refBone++)
 85.1696 +		{
 85.1697 +			oldKey = &anim->keys[startFrame * anim->info.numBones + i];
 85.1698 +			newKey = &anim->keys[endFrame * anim->info.numBones + i];
 85.1699 +
 85.1700 +			VectorCopy(newKey->position, newOrigin);
 85.1701 +			VectorCopy(oldKey->position, oldOrigin);
 85.1702 +
 85.1703 +			QuatCopy(newKey->quat, newQuat);
 85.1704 +			QuatCopy(oldKey->quat, oldQuat);
 85.1705 +
 85.1706 +			//QuatCalcW(oldQuat);
 85.1707 +			//QuatNormalize(oldQuat);
 85.1708 +
 85.1709 +			//QuatCalcW(newQuat);
 85.1710 +			//QuatNormalize(newQuat);
 85.1711 +
 85.1712 +			VectorLerp(oldOrigin, newOrigin, frac, lerpedOrigin);
 85.1713 +			QuatSlerp(oldQuat, newQuat, frac, lerpedQuat);
 85.1714 +
 85.1715 +			// copy lerped information to the bone + extra data
 85.1716 +			skel->bones[i].parentIndex = refBone->parentIndex;
 85.1717 +
 85.1718 +			if(refBone->parentIndex < 0 && clearOrigin)
 85.1719 +			{
 85.1720 +				VectorClear(skel->bones[i].origin);
 85.1721 +				QuatClear(skel->bones[i].rotation);
 85.1722 +
 85.1723 +				// move bounding box back
 85.1724 +				VectorSubtract(skel->bounds[0], lerpedOrigin, skel->bounds[0]);
 85.1725 +				VectorSubtract(skel->bounds[1], lerpedOrigin, skel->bounds[1]);
 85.1726 +			}
 85.1727 +			else
 85.1728 +			{
 85.1729 +				VectorCopy(lerpedOrigin, skel->bones[i].origin);
 85.1730 +			}
 85.1731 +
 85.1732 +			QuatCopy(lerpedQuat, skel->bones[i].rotation);
 85.1733 +
 85.1734 +			Q_strncpyz(skel->bones[i].name, refBone->name, sizeof(skel->bones[i].name));
 85.1735 +
 85.1736 +			// calculate absolute values for the bounding box approximation
 85.1737 +			VectorCopy(skel->bones[i].origin, skeleton.bones[i].origin);
 85.1738 +			QuatCopy(skel->bones[i].rotation, skeleton.bones[i].rotation);
 85.1739 +
 85.1740 +			if(refBone->parentIndex >= 0)
 85.1741 +			{
 85.1742 +				vec3_t          rotated;
 85.1743 +				quat_t          quat;
 85.1744 +				refBone_t      *parent;
 85.1745 +				refBone_t      *bone;
 85.1746 +
 85.1747 +				bone = &skeleton.bones[i];
 85.1748 +				parent = &skeleton.bones[refBone->parentIndex];
 85.1749 +
 85.1750 +				QuatTransformVector(parent->rotation, bone->origin, rotated);
 85.1751 +
 85.1752 +				VectorAdd(parent->origin, rotated, bone->origin);
 85.1753 +
 85.1754 +				QuatMultiply1(parent->rotation, bone->rotation, quat);
 85.1755 +				QuatCopy(quat, bone->rotation);
 85.1756 +
 85.1757 +				AddPointToBounds(bone->origin, skel->bounds[0], skel->bounds[1]);
 85.1758 +			}
 85.1759 +		}
 85.1760 +
 85.1761 +		skel->numBones = anim->info.numBones;
 85.1762 +		skel->type = SK_RELATIVE;
 85.1763 +		return qtrue;
 85.1764 +	}
 85.1765 +
 85.1766 +	//ri.Printf(PRINT_WARNING, "RE_BuildSkeleton: bad animation '%s' with handle %i\n", anim->name, hAnim);
 85.1767 +
 85.1768 +	// FIXME: clear existing bones and bounds?
 85.1769 +	return qfalse;
 85.1770 +}
 85.1771 +
 85.1772 +
 85.1773 +/*
 85.1774 +==============
 85.1775 +RE_BlendSkeleton
 85.1776 +==============
 85.1777 +*/
 85.1778 +int RE_BlendSkeleton(refSkeleton_t * skel, const refSkeleton_t * blend, float frac)
 85.1779 +{
 85.1780 +	int             i;
 85.1781 +	vec3_t          lerpedOrigin;
 85.1782 +	quat_t          lerpedQuat;
 85.1783 +	vec3_t          bounds[2];
 85.1784 +
 85.1785 +	if(skel->numBones != blend->numBones)
 85.1786 +	{
 85.1787 +		ri.Printf(PRINT_WARNING, "RE_BlendSkeleton: different number of bones %d != %d\n", skel->numBones, blend->numBones);
 85.1788 +		return qfalse;
 85.1789 +	}
 85.1790 +
 85.1791 +	// lerp between the 2 bone poses
 85.1792 +	for(i = 0; i < skel->numBones; i++)
 85.1793 +	{
 85.1794 +		VectorLerp(skel->bones[i].origin, blend->bones[i].origin, frac, lerpedOrigin);
 85.1795 +		QuatSlerp(skel->bones[i].rotation, blend->bones[i].rotation, frac, lerpedQuat);
 85.1796 +
 85.1797 +		VectorCopy(lerpedOrigin, skel->bones[i].origin);
 85.1798 +		QuatCopy(lerpedQuat, skel->bones[i].rotation);
 85.1799 +	}
 85.1800 +
 85.1801 +	// calculate a bounding box in the current coordinate system
 85.1802 +	for(i = 0; i < 3; i++)
 85.1803 +	{
 85.1804 +		bounds[0][i] = skel->bounds[0][i] < blend->bounds[0][i] ? skel->bounds[0][i] : blend->bounds[0][i];
 85.1805 +		bounds[1][i] = skel->bounds[1][i] > blend->bounds[1][i] ? skel->bounds[1][i] : blend->bounds[1][i];
 85.1806 +	}
 85.1807 +	VectorCopy(bounds[0], skel->bounds[0]);
 85.1808 +	VectorCopy(bounds[1], skel->bounds[1]);
 85.1809 +
 85.1810 +	return qtrue;
 85.1811 +}
 85.1812 +
 85.1813 +
 85.1814 +/*
 85.1815 +==============
 85.1816 +RE_AnimNumFrames
 85.1817 +==============
 85.1818 +*/
 85.1819 +int RE_AnimNumFrames(qhandle_t hAnim)
 85.1820 +{
 85.1821 +	skelAnimation_t *anim;
 85.1822 +
 85.1823 +	anim = R_GetAnimationByHandle(hAnim);
 85.1824 +
 85.1825 +	if(anim->type == AT_MD5 && anim->md5)
 85.1826 +	{
 85.1827 +		return anim->md5->numFrames;
 85.1828 +	}
 85.1829 +
 85.1830 +	if(anim->type == AT_PSA && anim->psa)
 85.1831 +	{
 85.1832 +		return anim->psa->info.numRawFrames;
 85.1833 +	}
 85.1834  
 85.1835  	return 0;
 85.1836  }
 85.1837 @@ -309,351 +1604,24 @@
 85.1838  
 85.1839  /*
 85.1840  ==============
 85.1841 -R_MDRAddAnimSurfaces
 85.1842 +RE_AnimFrameRate
 85.1843  ==============
 85.1844  */
 85.1845 +int RE_AnimFrameRate(qhandle_t hAnim)
 85.1846 +{
 85.1847 +	skelAnimation_t *anim;
 85.1848  
 85.1849 -// much stuff in there is just copied from R_AddMd3Surfaces in tr_mesh.c
 85.1850 +	anim = R_GetAnimationByHandle(hAnim);
 85.1851  
 85.1852 -void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
 85.1853 -	mdrHeader_t		*header;
 85.1854 -	mdrSurface_t	*surface;
 85.1855 -	mdrLOD_t		*lod;
 85.1856 -	shader_t		*shader;
 85.1857 -	skin_t		*skin;
 85.1858 -	int				i, j;
 85.1859 -	int				lodnum = 0;
 85.1860 -	int				fogNum = 0;
 85.1861 -	int				cull;
 85.1862 -	qboolean	personalModel;
 85.1863 -
 85.1864 -	header = (mdrHeader_t *) tr.currentModel->md4;
 85.1865 -	
 85.1866 -	personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal;
 85.1867 -	
 85.1868 -	if ( ent->e.renderfx & RF_WRAP_FRAMES )
 85.1869 +	if(anim->type == AT_MD5 && anim->md5)
 85.1870  	{
 85.1871 -		ent->e.frame %= header->numFrames;
 85.1872 -		ent->e.oldframe %= header->numFrames;
 85.1873 -	}	
 85.1874 -	
 85.1875 -	//
 85.1876 -	// Validate the frames so there is no chance of a crash.
 85.1877 -	// This will write directly into the entity structure, so
 85.1878 -	// when the surfaces are rendered, they don't need to be
 85.1879 -	// range checked again.
 85.1880 -	//
 85.1881 -	if ((ent->e.frame >= header->numFrames) 
 85.1882 -		|| (ent->e.frame < 0)
 85.1883 -		|| (ent->e.oldframe >= header->numFrames)
 85.1884 -		|| (ent->e.oldframe < 0) )
 85.1885 -	{
 85.1886 -		ri.Printf( PRINT_DEVELOPER, "R_MDRAddAnimSurfaces: no such frame %d to %d for '%s'\n",
 85.1887 -			   ent->e.oldframe, ent->e.frame, tr.currentModel->name );
 85.1888 -		ent->e.frame = 0;
 85.1889 -		ent->e.oldframe = 0;
 85.1890 +		return anim->md5->frameRate;
 85.1891  	}
 85.1892  
 85.1893 -	//
 85.1894 -	// cull the entire model if merged bounding box of both frames
 85.1895 -	// is outside the view frustum.
 85.1896 -	//
 85.1897 -	cull = R_MDRCullModel (header, ent);
 85.1898 -	if ( cull == CULL_OUT ) {
 85.1899 -		return;
 85.1900 -	}	
 85.1901 -
 85.1902 -	// figure out the current LOD of the model we're rendering, and set the lod pointer respectively.
 85.1903 -	lodnum = R_ComputeLOD(ent);
 85.1904 -	// check whether this model has as that many LODs at all. If not, try the closest thing we got.
 85.1905 -	if(header->numLODs <= 0)
 85.1906 -		return;
 85.1907 -	if(header->numLODs <= lodnum)
 85.1908 -		lodnum = header->numLODs - 1;
 85.1909 -
 85.1910 -	lod = (mdrLOD_t *)( (byte *)header + header->ofsLODs);
 85.1911 -	for(i = 0; i < lodnum; i++)
 85.1912 +	if(anim->type == AT_PSA && anim->psa)
 85.1913  	{
 85.1914 -		lod = (mdrLOD_t *) ((byte *) lod + lod->ofsEnd);
 85.1915 -	}
 85.1916 -	
 85.1917 -	// set up lighting
 85.1918 -	if ( !personalModel || r_shadows->integer > 1 )
 85.1919 -	{
 85.1920 -		R_SetupEntityLighting( &tr.refdef, ent );
 85.1921 +		return anim->psa->info.frameRate;
 85.1922  	}
 85.1923  
 85.1924 -	// fogNum?
 85.1925 -	fogNum = R_MDRComputeFogNum( header, ent );
 85.1926 -
 85.1927 -	surface = (mdrSurface_t *)( (byte *)lod + lod->ofsSurfaces );
 85.1928 -
 85.1929 -	for ( i = 0 ; i < lod->numSurfaces ; i++ )
 85.1930 -	{
 85.1931 -		
 85.1932 -		if(ent->e.customShader)
 85.1933 -			shader = R_GetShaderByHandle(ent->e.customShader);
 85.1934 -		else if(ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins)
 85.1935 -		{
 85.1936 -			skin = R_GetSkinByHandle(ent->e.customSkin);
 85.1937 -			shader = tr.defaultShader;
 85.1938 -			
 85.1939 -			for(j = 0; j < skin->numSurfaces; j++)
 85.1940 -			{
 85.1941 -				if (!strcmp(skin->surfaces[j]->name, surface->name))
 85.1942 -				{
 85.1943 -					shader = skin->surfaces[j]->shader;
 85.1944 -					break;
 85.1945 -				}
 85.1946 -			}
 85.1947 -		}
 85.1948 -		else if(surface->shaderIndex > 0)
 85.1949 -			shader = R_GetShaderByHandle( surface->shaderIndex );
 85.1950 -		else
 85.1951 -			shader = tr.defaultShader;
 85.1952 -
 85.1953 -		// we will add shadows even if the main object isn't visible in the view
 85.1954 -
 85.1955 -		// stencil shadows can't do personal models unless I polyhedron clip
 85.1956 -		if ( !personalModel
 85.1957 -		        && r_shadows->integer == 2
 85.1958 -			&& fogNum == 0
 85.1959 -			&& !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )
 85.1960 -			&& shader->sort == SS_OPAQUE )
 85.1961 -		{
 85.1962 -			R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse );
 85.1963 -		}
 85.1964 -
 85.1965 -		// projection shadows work fine with personal models
 85.1966 -		if ( r_shadows->integer == 3
 85.1967 -			&& fogNum == 0
 85.1968 -			&& (ent->e.renderfx & RF_SHADOW_PLANE )
 85.1969 -			&& shader->sort == SS_OPAQUE )
 85.1970 -		{
 85.1971 -			R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
 85.1972 -		}
 85.1973 -
 85.1974 -		if (!personalModel)
 85.1975 -			R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse );
 85.1976 -
 85.1977 -		surface = (mdrSurface_t *)( (byte *)surface + surface->ofsEnd );
 85.1978 -	}
 85.1979 +	return 0;
 85.1980  }
 85.1981 -
 85.1982 -/*
 85.1983 -==============
 85.1984 -RB_MDRSurfaceAnim
 85.1985 -==============
 85.1986 -*/
 85.1987 -void RB_MDRSurfaceAnim( md4Surface_t *surface )
 85.1988 -{
 85.1989 -	int				i, j, k;
 85.1990 -	float			frontlerp, backlerp;
 85.1991 -	int				*triangles;
 85.1992 -	int				indexes;
 85.1993 -	int				baseIndex, baseVertex;
 85.1994 -	int				numVerts;
 85.1995 -	mdrVertex_t		*v;
 85.1996 -	mdrHeader_t		*header;
 85.1997 -	mdrFrame_t		*frame;
 85.1998 -	mdrFrame_t		*oldFrame;
 85.1999 -	mdrBone_t		bones[MD4_MAX_BONES], *bonePtr, *bone;
 85.2000 -
 85.2001 -	int			frameSize;
 85.2002 -
 85.2003 -	// don't lerp if lerping off, or this is the only frame, or the last frame...
 85.2004 -	//
 85.2005 -	if (backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame) 
 85.2006 -	{
 85.2007 -		backlerp	= 0;	// if backlerp is 0, lerping is off and frontlerp is never used
 85.2008 -		frontlerp	= 1;
 85.2009 -	} 
 85.2010 -	else  
 85.2011 -	{
 85.2012 -		backlerp	= backEnd.currentEntity->e.backlerp;
 85.2013 -		frontlerp	= 1.0f - backlerp;
 85.2014 -	}
 85.2015 -
 85.2016 -	header = (mdrHeader_t *)((byte *)surface + surface->ofsHeader);
 85.2017 -
 85.2018 -	frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] );
 85.2019 -
 85.2020 -	frame = (mdrFrame_t *)((byte *)header + header->ofsFrames +
 85.2021 -		backEnd.currentEntity->e.frame * frameSize );
 85.2022 -	oldFrame = (mdrFrame_t *)((byte *)header + header->ofsFrames +
 85.2023 -		backEnd.currentEntity->e.oldframe * frameSize );
 85.2024 -
 85.2025 -	RB_CheckOverflow( surface->numVerts, surface->numTriangles );
 85.2026 -
 85.2027 -	triangles	= (int *) ((byte *)surface + surface->ofsTriangles);
 85.2028 -	indexes		= surface->numTriangles * 3;
 85.2029 -	baseIndex	= tess.numIndexes;
 85.2030 -	baseVertex	= tess.numVertexes;
 85.2031 -	
 85.2032 -	// Set up all triangles.
 85.2033 -	for (j = 0 ; j < indexes ; j++) 
 85.2034 -	{
 85.2035 -		tess.indexes[baseIndex + j] = baseVertex + triangles[j];
 85.2036 -	}
 85.2037 -	tess.numIndexes += indexes;
 85.2038 -
 85.2039 -	//
 85.2040 -	// lerp all the needed bones
 85.2041 -	//
 85.2042 -	if ( !backlerp ) 
 85.2043 -	{
 85.2044 -		// no lerping needed
 85.2045 -		bonePtr = frame->bones;
 85.2046 -	} 
 85.2047 -	else 
 85.2048 -	{
 85.2049 -		bonePtr = bones;
 85.2050 -		
 85.2051 -		for ( i = 0 ; i < header->numBones*12 ; i++ ) 
 85.2052 -		{
 85.2053 -			((float *)bonePtr)[i] = frontlerp * ((float *)frame->bones)[i] + backlerp * ((float *)oldFrame->bones)[i];
 85.2054 -		}
 85.2055 -	}
 85.2056 -
 85.2057 -	//
 85.2058 -	// deform the vertexes by the lerped bones
 85.2059 -	//
 85.2060 -	numVerts = surface->numVerts;
 85.2061 -	v = (mdrVertex_t *) ((byte *)surface + surface->ofsVerts);
 85.2062 -	for ( j = 0; j < numVerts; j++ ) 
 85.2063 -	{
 85.2064 -		vec3_t	tempVert, tempNormal;
 85.2065 -		mdrWeight_t	*w;
 85.2066 -
 85.2067 -		VectorClear( tempVert );
 85.2068 -		VectorClear( tempNormal );
 85.2069 -		w = v->weights;
 85.2070 -		for ( k = 0 ; k < v->numWeights ; k++, w++ ) 
 85.2071 -		{
 85.2072 -			bone = bonePtr + w->boneIndex;
 85.2073 -			
 85.2074 -			tempVert[0] += w->boneWeight * ( DotProduct( bone->matrix[0], w->offset ) + bone->matrix[0][3] );
 85.2075 -			tempVert[1] += w->boneWeight * ( DotProduct( bone->matrix[1], w->offset ) + bone->matrix[1][3] );
 85.2076 -			tempVert[2] += w->boneWeight * ( DotProduct( bone->matrix[2], w->offset ) + bone->matrix[2][3] );
 85.2077 -			
 85.2078 -			tempNormal[0] += w->boneWeight * DotProduct( bone->matrix[0], v->normal );
 85.2079 -			tempNormal[1] += w->boneWeight * DotProduct( bone->matrix[1], v->normal );
 85.2080 -			tempNormal[2] += w->boneWeight * DotProduct( bone->matrix[2], v->normal );
 85.2081 -		}
 85.2082 -
 85.2083 -		tess.xyz[baseVertex + j][0] = tempVert[0];
 85.2084 -		tess.xyz[baseVertex + j][1] = tempVert[1];
 85.2085 -		tess.xyz[baseVertex + j][2] = tempVert[2];
 85.2086 -
 85.2087 -		tess.normal[baseVertex + j][0] = tempNormal[0];
 85.2088 -		tess.normal[baseVertex + j][1] = tempNormal[1];
 85.2089 -		tess.normal[baseVertex + j][2] = tempNormal[2];
 85.2090 -
 85.2091 -		tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
 85.2092 -		tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];
 85.2093 -
 85.2094 -		v = (mdrVertex_t *)&v->weights[v->numWeights];
 85.2095 -	}
 85.2096 -
 85.2097 -	tess.numVertexes += surface->numVerts;
 85.2098 -}
 85.2099 -
 85.2100 -
 85.2101 -#define MC_MASK_X ((1<<(MC_BITS_X))-1)
 85.2102 -#define MC_MASK_Y ((1<<(MC_BITS_Y))-1)
 85.2103 -#define MC_MASK_Z ((1<<(MC_BITS_Z))-1)
 85.2104 -#define MC_MASK_VECT ((1<<(MC_BITS_VECT))-1)
 85.2105 -
 85.2106 -#define MC_SCALE_VECT (1.0f/(float)((1<<(MC_BITS_VECT-1))-2))
 85.2107 -
 85.2108 -#define MC_POS_X (0)
 85.2109 -#define MC_SHIFT_X (0)
 85.2110 -
 85.2111 -#define MC_POS_Y ((((MC_BITS_X))/8))
 85.2112 -#define MC_SHIFT_Y ((((MC_BITS_X)%8)))
 85.2113 -
 85.2114 -#define MC_POS_Z ((((MC_BITS_X+MC_BITS_Y))/8))
 85.2115 -#define MC_SHIFT_Z ((((MC_BITS_X+MC_BITS_Y)%8)))
 85.2116 -
 85.2117 -#define MC_POS_V11 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z))/8))
 85.2118 -#define MC_SHIFT_V11 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z)%8)))
 85.2119 -
 85.2120 -#define MC_POS_V12 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT))/8))
 85.2121 -#define MC_SHIFT_V12 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT)%8)))
 85.2122 -
 85.2123 -#define MC_POS_V13 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*2))/8))
 85.2124 -#define MC_SHIFT_V13 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*2)%8)))
 85.2125 -
 85.2126 -#define MC_POS_V21 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*3))/8))
 85.2127 -#define MC_SHIFT_V21 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*3)%8)))
 85.2128 -
 85.2129 -#define MC_POS_V22 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*4))/8))
 85.2130 -#define MC_SHIFT_V22 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*4)%8)))
 85.2131 -
 85.2132 -#define MC_POS_V23 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*5))/8))
 85.2133 -#define MC_SHIFT_V23 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*5)%8)))
 85.2134 -
 85.2135 -#define MC_POS_V31 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*6))/8))
 85.2136 -#define MC_SHIFT_V31 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*6)%8)))
 85.2137 -
 85.2138 -#define MC_POS_V32 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*7))/8))
 85.2139 -#define MC_SHIFT_V32 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*7)%8)))
 85.2140 -
 85.2141 -#define MC_POS_V33 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*8))/8))
 85.2142 -#define MC_SHIFT_V33 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*8)%8)))
 85.2143 -
 85.2144 -void MC_UnCompress(float mat[3][4],const unsigned char * comp)
 85.2145 -{
 85.2146 -	int val;
 85.2147 -
 85.2148 -	val=(int)((unsigned short *)(comp))[0];
 85.2149 -	val-=1<<(MC_BITS_X-1);
 85.2150 -	mat[0][3]=((float)(val))*MC_SCALE_X;
 85.2151 -
 85.2152 -	val=(int)((unsigned short *)(comp))[1];
 85.2153 -	val-=1<<(MC_BITS_Y-1);
 85.2154 -	mat[1][3]=((float)(val))*MC_SCALE_Y;
 85.2155 -
 85.2156 -	val=(int)((unsigned short *)(comp))[2];
 85.2157 -	val-=1<<(MC_BITS_Z-1);
 85.2158 -	mat[2][3]=((float)(val))*MC_SCALE_Z;
 85.2159 -
 85.2160 -	val=(int)((unsigned short *)(comp))[3];
 85.2161 -	val-=1<<(MC_BITS_VECT-1);
 85.2162 -	mat[0][0]=((float)(val))*MC_SCALE_VECT;
 85.2163 -
 85.2164 -	val=(int)((unsigned short *)(comp))[4];
 85.2165 -	val-=1<<(MC_BITS_VECT-1);
 85.2166 -	mat[0][1]=((float)(val))*MC_SCALE_VECT;
 85.2167 -
 85.2168 -	val=(int)((unsigned short *)(comp))[5];
 85.2169 -	val-=1<<(MC_BITS_VECT-1);
 85.2170 -	mat[0][2]=((float)(val))*MC_SCALE_VECT;
 85.2171 -
 85.2172 -
 85.2173 -	val=(int)((unsigned short *)(comp))[6];
 85.2174 -	val-=1<<(MC_BITS_VECT-1);
 85.2175 -	mat[1][0]=((float)(val))*MC_SCALE_VECT;
 85.2176 -
 85.2177 -	val=(int)((unsigned short *)(comp))[7];
 85.2178 -	val-=1<<(MC_BITS_VECT-1);
 85.2179 -	mat[1][1]=((float)(val))*MC_SCALE_VECT;
 85.2180 -
 85.2181 -	val=(int)((unsigned short *)(comp))[8];
 85.2182 -	val-=1<<(MC_BITS_VECT-1);
 85.2183 -	mat[1][2]=((float)(val))*MC_SCALE_VECT;
 85.2184 -
 85.2185 -
 85.2186 -	val=(int)((unsigned short *)(comp))[9];
 85.2187 -	val-=1<<(MC_BITS_VECT-1);
 85.2188 -	mat[2][0]=((float)(val))*MC_SCALE_VECT;
 85.2189 -
 85.2190 -	val=(int)((unsigned short *)(comp))[10];
 85.2191 -	val-=1<<(MC_BITS_VECT-1);
 85.2192 -	mat[2][1]=((float)(val))*MC_SCALE_VECT;
 85.2193 -
 85.2194 -	val=(int)((unsigned short *)(comp))[11];
 85.2195 -	val-=1<<(MC_BITS_VECT-1);
 85.2196 -	mat[2][2]=((float)(val))*MC_SCALE_VECT;
 85.2197 -}
 85.2198 -#endif
    86.1 --- a/src/renderer/tr_backend.c	Sat Jun 06 03:54:16 2009 +0800
    86.2 +++ b/src/renderer/tr_backend.c	Wed Jun 10 09:31:46 2009 +0800
    86.3 @@ -1,385 +1,664 @@
    86.4  /*
    86.5  ===========================================================================
    86.6  Copyright (C) 1999-2005 Id Software, Inc.
    86.7 -Copyright (C) 2000-2006 Tim Angus
    86.8 -
    86.9 -This file is part of Tremfusion.
   86.10 -
   86.11 -Tremfusion is free software; you can redistribute it
   86.12 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
   86.13 +
   86.14 +This file is part of XreaL source code.
   86.15 +
   86.16 +XreaL source code is free software; you can redistribute it
   86.17  and/or modify it under the terms of the GNU General Public License as
   86.18  published by the Free Software Foundation; either version 2 of the License,
   86.19  or (at your option) any later version.
   86.20  
   86.21 -Tremfusion is distributed in the hope that it will be
   86.22 +XreaL source code is distributed in the hope that it will be
   86.23  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   86.24  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   86.25  GNU General Public License for more details.
   86.26  
   86.27  You should have received a copy of the GNU General Public License
   86.28 -along with Tremfusion; if not, write to the Free Software
   86.29 +along with XreaL source code; if not, write to the Free Software
   86.30  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   86.31  ===========================================================================
   86.32  */
   86.33 +// tr_backend.c
   86.34  #include "tr_local.h"
   86.35  
   86.36 -backEndData_t	*backEndData[SMP_FRAMES];
   86.37 -backEndState_t	backEnd;
   86.38 -
   86.39 -
   86.40 -static float	s_flipMatrix[16] = {
   86.41 -	// convert from our coordinate system (looking down X)
   86.42 -	// to OpenGL's coordinate system (looking down -Z)
   86.43 -	0, 0, -1, 0,
   86.44 -	-1, 0, 0, 0,
   86.45 -	0, 1, 0, 0,
   86.46 -	0, 0, 0, 1
   86.47 -};
   86.48 -
   86.49 -
   86.50 -/*
   86.51 -** GL_Bind
   86.52 -*/
   86.53 -void GL_Bind( image_t *image ) {
   86.54 -	int texnum;
   86.55 -
   86.56 -	if ( !image ) {
   86.57 -		ri.Printf( PRINT_WARNING, "GL_Bind: NULL image\n" );
   86.58 +backEndData_t  *backEndData[SMP_FRAMES];
   86.59 +backEndState_t  backEnd;
   86.60 +
   86.61 +void GL_Bind(image_t * image)
   86.62 +{
   86.63 +	int             texnum;
   86.64 +
   86.65 +	if(!image)
   86.66 +	{
   86.67 +		ri.Printf(PRINT_WARNING, "GL_Bind: NULL image\n");
   86.68  		texnum = tr.defaultImage->texnum;
   86.69 -	} else {
   86.70 +	}
   86.71 +	else
   86.72 +	{
   86.73 +		if(r_logFile->integer)
   86.74 +		{
   86.75 +			// don't just call LogComment, or we will get a call to va() every frame!
   86.76 +			GLimp_LogComment(va("--- GL_Bind( %s ) ---\n", image->name));
   86.77 +		}
   86.78 +
   86.79  		texnum = image->texnum;
   86.80  	}
   86.81  
   86.82 -	if ( r_nobind->integer && tr.dlightImage ) {		// performance evaluation option
   86.83 -		texnum = tr.dlightImage->texnum;
   86.84 -	}
   86.85 -
   86.86 -	if ( glState.currenttextures[glState.currenttmu] != texnum ) {
   86.87 +	if(r_nobind->integer && tr.blackImage)
   86.88 +	{
   86.89 +		// performance evaluation option
   86.90 +		texnum = tr.blackImage->texnum;
   86.91 +	}
   86.92 +
   86.93 +	if(glState.currenttextures[glState.currenttmu] != texnum)
   86.94 +	{
   86.95  		image->frameUsed = tr.frameCount;
   86.96  		glState.currenttextures[glState.currenttmu] = texnum;
   86.97 -		qglBindTexture (GL_TEXTURE_2D, texnum);
   86.98 +		qglBindTexture(image->type, texnum);
   86.99  	}
  86.100  }
  86.101  
  86.102 -/*
  86.103 -** GL_SelectTexture
  86.104 -*/
  86.105 -void GL_SelectTexture( int unit )
  86.106 +void GL_Unbind()
  86.107  {
  86.108 -	if ( glState.currenttmu == unit )
  86.109 -	{
  86.110 +	GLimp_LogComment("--- GL_Unbind() ---\n");
  86.111 +
  86.112 +	qglBindTexture(GL_TEXTURE_2D, 0);
  86.113 +}
  86.114 +
  86.115 +void BindAnimatedImage(textureBundle_t * bundle)
  86.116 +{
  86.117 +	int             index;
  86.118 +
  86.119 +	if(bundle->isVideoMap)
  86.120 +	{
  86.121 +		ri.CIN_RunCinematic(bundle->videoMapHandle);
  86.122 +		ri.CIN_UploadCinematic(bundle->videoMapHandle);
  86.123  		return;
  86.124  	}
  86.125  
  86.126 -	if ( unit == 0 )
  86.127 -	{
  86.128 -		qglActiveTextureARB( GL_TEXTURE0_ARB );
  86.129 -		GLimp_LogComment( "glActiveTextureARB( GL_TEXTURE0_ARB )\n" );
  86.130 -		qglClientActiveTextureARB( GL_TEXTURE0_ARB );
  86.131 -		GLimp_LogComment( "glClientActiveTextureARB( GL_TEXTURE0_ARB )\n" );
  86.132 -	}
  86.133 -	else if ( unit == 1 )
  86.134 -	{
  86.135 -		qglActiveTextureARB( GL_TEXTURE1_ARB );
  86.136 -		GLimp_LogComment( "glActiveTextureARB( GL_TEXTURE1_ARB )\n" );
  86.137 -		qglClientActiveTextureARB( GL_TEXTURE1_ARB );
  86.138 -		GLimp_LogComment( "glClientActiveTextureARB( GL_TEXTURE1_ARB )\n" );
  86.139 -	} else {
  86.140 -		ri.Error( ERR_DROP, "GL_SelectTexture: unit = %i", unit );
  86.141 +	if(bundle->numImages <= 1)
  86.142 +	{
  86.143 +		GL_Bind(bundle->image[0]);
  86.144 +		return;
  86.145 +	}
  86.146 +
  86.147 +	// it is necessary to do this messy calc to make sure animations line up
  86.148 +	// exactly with waveforms of the same frequency
  86.149 +	index = Q_ftol(backEnd.refdef.floatTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE);
  86.150 +	index >>= FUNCTABLE_SIZE2;
  86.151 +
  86.152 +	if(index < 0)
  86.153 +	{
  86.154 +		index = 0;				// may happen with shader time offsets
  86.155 +	}
  86.156 +	index %= bundle->numImages;
  86.157 +
  86.158 +	GL_Bind(bundle->image[index]);
  86.159 +}
  86.160 +
  86.161 +void GL_TextureFilter(image_t * image, filterType_t filterType)
  86.162 +{
  86.163 +	if(!image)
  86.164 +	{
  86.165 +		ri.Printf(PRINT_WARNING, "GL_TextureFilter: NULL image\n");
  86.166 +	}
  86.167 +	else
  86.168 +	{
  86.169 +		if(r_logFile->integer)
  86.170 +		{
  86.171 +			// don't just call LogComment, or we will get a call to va() every frame!
  86.172 +			GLimp_LogComment(va("--- GL_TextureFilter( %s ) ---\n", image->name));
  86.173 +		}
  86.174 +	}
  86.175 +
  86.176 +	if(image->filterType == filterType)
  86.177 +		return;
  86.178 +
  86.179 +	// set filter type
  86.180 +	switch (image->filterType)
  86.181 +	{
  86.182 +			/*
  86.183 +			   case FT_DEFAULT:
  86.184 +			   qglTexParameterf(image->type, GL_TEXTURE_MIN_FILTER, gl_filter_min);
  86.185 +			   qglTexParameterf(image->type, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  86.186 +
  86.187 +			   // set texture anisotropy
  86.188 +			   if(glConfig.textureAnisotropyAvailable)
  86.189 +			   qglTexParameterf(image->type, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_ext_texture_filter_anisotropic->value);
  86.190 +			   break;
  86.191 +			 */
  86.192 +
  86.193 +		case FT_LINEAR:
  86.194 +			qglTexParameterf(image->type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  86.195 +			qglTexParameterf(image->type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  86.196 +			break;
  86.197 +
  86.198 +		case FT_NEAREST:
  86.199 +			qglTexParameterf(image->type, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  86.200 +			qglTexParameterf(image->type, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  86.201 +			break;
  86.202 +
  86.203 +		default:
  86.204 +			break;
  86.205 +	}
  86.206 +}
  86.207 +
  86.208 +void GL_BindProgram(shaderProgram_t * program)
  86.209 +{
  86.210 +	if(!program)
  86.211 +	{
  86.212 +		GL_BindNullProgram();
  86.213 +		return;
  86.214 +	}
  86.215 +
  86.216 +	if(r_logFile->integer)
  86.217 +	{
  86.218 +		// don't just call LogComment, or we will get a call to va() every frame!
  86.219 +		GLimp_LogComment(va("--- GL_BindProgram( %s ) ---\n", program->name));
  86.220 +	}
  86.221 +
  86.222 +	if(glState.currentProgram != program)
  86.223 +	{
  86.224 +		qglUseProgramObjectARB(program->program);
  86.225 +		glState.currentProgram = program;
  86.226 +	}
  86.227 +}
  86.228 +
  86.229 +void GL_BindNullProgram(void)
  86.230 +{
  86.231 +	if(r_logFile->integer)
  86.232 +	{
  86.233 +		GLimp_LogComment("--- GL_BindNullProgram ---\n");
  86.234 +	}
  86.235 +
  86.236 +	if(glState.currentProgram)
  86.237 +	{
  86.238 +		qglUseProgramObjectARB(0);
  86.239 +		glState.currentProgram = NULL;
  86.240 +	}
  86.241 +}
  86.242 +
  86.243 +void GL_SelectTexture(int unit)
  86.244 +{
  86.245 +	if(glState.currenttmu == unit)
  86.246 +	{
  86.247 +		return;
  86.248 +	}
  86.249 +
  86.250 +	if(unit >= 0 && unit <= 7)
  86.251 +	{
  86.252 +		qglActiveTextureARB(GL_TEXTURE0_ARB + unit);
  86.253 +
  86.254 +		if(r_logFile->integer)
  86.255 +		{
  86.256 +			GLimp_LogComment(va("glActiveTextureARB( GL_TEXTURE%i_ARB )\n", unit));
  86.257 +		}
  86.258 +	}
  86.259 +	else
  86.260 +	{
  86.261 +		ri.Error(ERR_DROP, "GL_SelectTexture: unit = %i", unit);
  86.262  	}
  86.263  
  86.264  	glState.currenttmu = unit;
  86.265  }
  86.266  
  86.267 +void GL_BlendFunc(GLenum sfactor, GLenum dfactor)
  86.268 +{
  86.269 +	if(glState.blendSrc != sfactor || glState.blendDst != dfactor)
  86.270 +	{
  86.271 +		glState.blendSrc = sfactor;
  86.272 +		glState.blendDst = dfactor;
  86.273 +
  86.274 +		qglBlendFunc(sfactor, dfactor);
  86.275 +	}
  86.276 +}
  86.277 +
  86.278 +void GL_ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
  86.279 +{
  86.280 +	if(glState.clearColorRed != red || glState.clearColorGreen != green || glState.clearColorBlue != blue || glState.clearColorAlpha != alpha)
  86.281 +	{
  86.282 +		glState.clearColorRed = red;
  86.283 +		glState.clearColorGreen = green;
  86.284 +		glState.clearColorBlue = blue;
  86.285 +		glState.clearColorAlpha = alpha;
  86.286 +
  86.287 +		qglClearColor(red, green, blue, alpha);
  86.288 +	}
  86.289 +}
  86.290 +
  86.291 +void GL_ClearDepth(GLclampd depth)
  86.292 +{
  86.293 +	if(glState.clearDepth != depth)
  86.294 +	{
  86.295 +		glState.clearDepth = depth;
  86.296 +
  86.297 +		qglClearDepth(depth);
  86.298 +	}
  86.299 +}
  86.300 +
  86.301 +void GL_ClearStencil(GLint s)
  86.302 +{
  86.303 +	if(glState.clearStencil != s)
  86.304 +	{
  86.305 +		glState.clearStencil = s;
  86.306 +
  86.307 +		qglClearStencil(s);
  86.308 +	}
  86.309 +}
  86.310 +
  86.311 +void GL_ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
  86.312 +{
  86.313 +	if(glState.colorMaskRed != red || glState.colorMaskGreen != green || glState.colorMaskBlue != blue || glState.colorMaskAlpha != alpha)
  86.314 +	{
  86.315 +		glState.colorMaskRed = red;
  86.316 +		glState.colorMaskGreen = green;
  86.317 +		glState.colorMaskBlue = blue;
  86.318 +		glState.colorMaskAlpha = alpha;
  86.319 +
  86.320 +		qglColorMask(red, green, blue, alpha);
  86.321 +	}
  86.322 +}
  86.323 +
  86.324 +void GL_CullFace(GLenum mode)
  86.325 +{
  86.326 +	if(glState.cullFace != mode)
  86.327 +	{
  86.328 +		glState.cullFace = mode;
  86.329 +
  86.330 +		qglCullFace(mode);
  86.331 +	}
  86.332 +}
  86.333 +
  86.334 +void GL_DepthFunc(GLenum func)
  86.335 +{
  86.336 +	if(glState.depthFunc != func)
  86.337 +	{
  86.338 +		glState.depthFunc = func;
  86.339 +
  86.340 +		qglDepthFunc(func);
  86.341 +	}
  86.342 +}
  86.343 +
  86.344 +void GL_DepthMask(GLboolean flag)
  86.345 +{
  86.346 +	if(glState.depthMask != flag)
  86.347 +	{
  86.348 +		glState.depthMask = flag;
  86.349 +
  86.350 +		qglDepthMask(flag);
  86.351 +	}
  86.352 +}
  86.353 +
  86.354 +void GL_DrawBuffer(GLenum mode)
  86.355 +{
  86.356 +	if(glState.drawBuffer != mode)
  86.357 +	{
  86.358 +		glState.drawBuffer = mode;
  86.359 +
  86.360 +		qglDrawBuffer(mode);
  86.361 +	}
  86.362 +}
  86.363 +
  86.364 +void GL_FrontFace(GLenum mode)
  86.365 +{
  86.366 +	if(glState.frontFace != mode)
  86.367 +	{
  86.368 +		glState.frontFace = mode;
  86.369 +
  86.370 +		qglFrontFace(mode);
  86.371 +	}
  86.372 +}
  86.373 +
  86.374 +void GL_LoadModelViewMatrix(const matrix_t m)
  86.375 +{
  86.376 +#if 1
  86.377 +	if(MatrixCompare(glState.modelViewMatrix[glState.stackIndex], m))
  86.378 +	{
  86.379 +		return;
  86.380 +	}
  86.381 +#endif
  86.382 +
  86.383 +
  86.384 +	MatrixCopy(m, glState.modelViewMatrix[glState.stackIndex]);
  86.385 +	MatrixMultiply(glState.projectionMatrix[glState.stackIndex], glState.modelViewMatrix[glState.stackIndex],
  86.386 +				   glState.modelViewProjectionMatrix[glState.stackIndex]);
  86.387 +}
  86.388 +
  86.389 +void GL_LoadProjectionMatrix(const matrix_t m)
  86.390 +{
  86.391 +#if 1
  86.392 +	if(MatrixCompare(glState.projectionMatrix[glState.stackIndex], m))
  86.393 +	{
  86.394 +		return;
  86.395 +	}
  86.396 +#endif
  86.397 +
  86.398 +	MatrixCopy(m, glState.projectionMatrix[glState.stackIndex]);
  86.399 +	MatrixMultiply(glState.projectionMatrix[glState.stackIndex], glState.modelViewMatrix[glState.stackIndex],
  86.400 +				   glState.modelViewProjectionMatrix[glState.stackIndex]);
  86.401 +}
  86.402 +
  86.403 +void GL_PushMatrix()
  86.404 +{
  86.405 +	glState.stackIndex++;
  86.406 +
  86.407 +	if(glState.stackIndex >= MAX_GLSTACK)
  86.408 +	{
  86.409 +		glState.stackIndex = MAX_GLSTACK - 1;
  86.410 +		ri.Error(ERR_DROP, "GL_PushMatrix: stack overflow = %i", glState.stackIndex);
  86.411 +	}
  86.412 +}
  86.413 +
  86.414 +void GL_PopMatrix()
  86.415 +{
  86.416 +	glState.stackIndex--;
  86.417 +
  86.418 +	if(glState.stackIndex < 0)
  86.419 +	{
  86.420 +		glState.stackIndex = 0;
  86.421 +		ri.Error(ERR_DROP, "GL_PushMatrix: stack underflow");
  86.422 +	}
  86.423 +}
  86.424 +
  86.425 +void GL_PolygonMode(GLenum face, GLenum mode)
  86.426 +{
  86.427 +	if(glState.polygonFace != face || glState.polygonMode != mode)
  86.428 +	{
  86.429 +		glState.polygonFace = face;
  86.430 +		glState.polygonMode = mode;
  86.431 +
  86.432 +		qglPolygonMode(face, mode);
  86.433 +	}
  86.434 +}
  86.435 +
  86.436 +static void GL_Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
  86.437 +{
  86.438 +	if(glState.scissorX != x || glState.scissorY != y || glState.scissorWidth != width || glState.scissorHeight != height)
  86.439 +	{
  86.440 +		glState.scissorX = x;
  86.441 +		glState.scissorY = y;
  86.442 +		glState.scissorWidth = width;
  86.443 +		glState.scissorHeight = height;
  86.444 +
  86.445 +		qglScissor(x, y, width, height);
  86.446 +	}
  86.447 +}
  86.448 +
  86.449 +static void GL_Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
  86.450 +{
  86.451 +	if(glState.viewportX != x || glState.viewportY != y || glState.viewportWidth != width || glState.viewportHeight != height)
  86.452 +	{
  86.453 +		glState.viewportX = x;
  86.454 +		glState.viewportY = y;
  86.455 +		glState.viewportWidth = width;
  86.456 +		glState.viewportHeight = height;
  86.457 +
  86.458 +		qglViewport(x, y, width, height);
  86.459 +	}
  86.460 +}
  86.461 +
  86.462 +void GL_Cull(int cullType)
  86.463 +{
  86.464 +	if(glState.faceCulling == cullType)
  86.465 +	{
  86.466 +		return;
  86.467 +	}
  86.468 +
  86.469 +	glState.faceCulling = cullType;
  86.470 +
  86.471 +	if(cullType == CT_TWO_SIDED)
  86.472 +	{
  86.473 +		qglDisable(GL_CULL_FACE);
  86.474 +	}
  86.475 +	else
  86.476 +	{
  86.477 +		qglEnable(GL_CULL_FACE);
  86.478 +
  86.479 +		if(cullType == CT_BACK_SIDED)
  86.480 +		{
  86.481 +			GL_CullFace(GL_BACK);
  86.482 +
  86.483 +			if(backEnd.viewParms.isMirror)
  86.484 +			{
  86.485 +				GL_FrontFace(GL_CW);
  86.486 +			}
  86.487 +			else
  86.488 +			{
  86.489 +				GL_FrontFace(GL_CCW);
  86.490 +			}
  86.491 +		}
  86.492 +		else
  86.493 +		{
  86.494 +			GL_CullFace(GL_FRONT);
  86.495 +
  86.496 +			if(backEnd.viewParms.isMirror)
  86.497 +			{
  86.498 +				GL_FrontFace(GL_CW);
  86.499 +			}
  86.500 +			else
  86.501 +			{
  86.502 +				GL_FrontFace(GL_CCW);
  86.503 +			}
  86.504 +		}
  86.505 +	}
  86.506 +}
  86.507 +
  86.508  
  86.509  /*
  86.510 -** GL_BindMultitexture
  86.511 +GL_State
  86.512 +
  86.513 +This routine is responsible for setting the most commonly changed state
  86.514 +in Q3.
  86.515  */
  86.516 -void GL_BindMultitexture( image_t *image0, GLuint env0, image_t *image1, GLuint env1 ) {
  86.517 -	int		texnum0, texnum1;
  86.518 -
  86.519 -	texnum0 = image0->texnum;
  86.520 -	texnum1 = image1->texnum;
  86.521 -
  86.522 -	if ( r_nobind->integer && tr.dlightImage ) {		// performance evaluation option
  86.523 -		texnum0 = texnum1 = tr.dlightImage->texnum;
  86.524 -	}
  86.525 -
  86.526 -	if ( glState.currenttextures[1] != texnum1 ) {
  86.527 -		GL_SelectTexture( 1 );
  86.528 -		image1->frameUsed = tr.frameCount;
  86.529 -		glState.currenttextures[1] = texnum1;
  86.530 -		qglBindTexture( GL_TEXTURE_2D, texnum1 );
  86.531 -	}
  86.532 -	if ( glState.currenttextures[0] != texnum0 ) {
  86.533 -		GL_SelectTexture( 0 );
  86.534 -		image0->frameUsed = tr.frameCount;
  86.535 -		glState.currenttextures[0] = texnum0;
  86.536 -		qglBindTexture( GL_TEXTURE_2D, texnum0 );
  86.537 -	}
  86.538 -}
  86.539 -
  86.540 -
  86.541 -/*
  86.542 -** GL_Cull
  86.543 -*/
  86.544 -void GL_Cull( int cullType ) {
  86.545 -	if ( glState.faceCulling == cullType ) {
  86.546 +void GL_State(unsigned long stateBits)
  86.547 +{
  86.548 +	unsigned long   diff = stateBits ^ glState.glStateBits;
  86.549 +
  86.550 +	if(!diff)
  86.551 +	{
  86.552  		return;
  86.553  	}
  86.554  
  86.555 -	glState.faceCulling = cullType;
  86.556 -
  86.557 -	if ( cullType == CT_TWO_SIDED ) 
  86.558 -	{
  86.559 -		qglDisable( GL_CULL_FACE );
  86.560 -	} 
  86.561 -	else 
  86.562 -	{
  86.563 -		qglEnable( GL_CULL_FACE );
  86.564 -
  86.565 -		if ( cullType == CT_BACK_SIDED )
  86.566 -		{
  86.567 -			if ( backEnd.viewParms.isMirror )
  86.568 -			{
  86.569 -				qglCullFace( GL_FRONT );
  86.570 -			}
  86.571 -			else
  86.572 -			{
  86.573 -				qglCullFace( GL_BACK );
  86.574 -			}
  86.575 +	// check depthFunc bits
  86.576 +	if(diff & GLS_DEPTHFUNC_BITS)
  86.577 +	{
  86.578 +		switch (stateBits & GLS_DEPTHFUNC_BITS)
  86.579 +		{
  86.580 +			default:
  86.581 +				GL_DepthFunc(GL_LEQUAL);
  86.582 +				break;
  86.583 +			case GLS_DEPTHFUNC_LESS:
  86.584 +				GL_DepthFunc(GL_LESS);
  86.585 +				break;
  86.586 +			case GLS_DEPTHFUNC_EQUAL:
  86.587 +				GL_DepthFunc(GL_EQUAL);
  86.588 +				break;
  86.589 +		}
  86.590 +	}
  86.591 +
  86.592 +	// check blend bits
  86.593 +	if(diff & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS))
  86.594 +	{
  86.595 +		GLenum          srcFactor, dstFactor;
  86.596 +
  86.597 +		if(stateBits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS))
  86.598 +		{
  86.599 +			switch (stateBits & GLS_SRCBLEND_BITS)
  86.600 +			{
  86.601 +				case GLS_SRCBLEND_ZERO:
  86.602 +					srcFactor = GL_ZERO;
  86.603 +					break;
  86.604 +				case GLS_SRCBLEND_ONE:
  86.605 +					srcFactor = GL_ONE;
  86.606 +					break;
  86.607 +				case GLS_SRCBLEND_DST_COLOR:
  86.608 +					srcFactor = GL_DST_COLOR;
  86.609 +					break;
  86.610 +				case GLS_SRCBLEND_ONE_MINUS_DST_COLOR:
  86.611 +					srcFactor = GL_ONE_MINUS_DST_COLOR;
  86.612 +					break;
  86.613 +				case GLS_SRCBLEND_SRC_ALPHA:
  86.614 +					srcFactor = GL_SRC_ALPHA;
  86.615 +					break;
  86.616 +				case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA:
  86.617 +					srcFactor = GL_ONE_MINUS_SRC_ALPHA;
  86.618 +					break;
  86.619 +				case GLS_SRCBLEND_DST_ALPHA:
  86.620 +					srcFactor = GL_DST_ALPHA;
  86.621 +					break;
  86.622 +				case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA:
  86.623 +					srcFactor = GL_ONE_MINUS_DST_ALPHA;
  86.624 +					break;
  86.625 +				case GLS_SRCBLEND_ALPHA_SATURATE:
  86.626 +					srcFactor = GL_SRC_ALPHA_SATURATE;
  86.627 +					break;
  86.628 +				default:
  86.629 +					srcFactor = GL_ONE;	// to get warning to shut up
  86.630 +					ri.Error(ERR_DROP, "GL_State: invalid src blend state bits\n");
  86.631 +					break;
  86.632 +			}
  86.633 +
  86.634 +			switch (stateBits & GLS_DSTBLEND_BITS)
  86.635 +			{
  86.636 +				case GLS_DSTBLEND_ZERO:
  86.637 +					dstFactor = GL_ZERO;
  86.638 +					break;
  86.639 +				case GLS_DSTBLEND_ONE:
  86.640 +					dstFactor = GL_ONE;
  86.641 +					break;
  86.642 +				case GLS_DSTBLEND_SRC_COLOR:
  86.643 +					dstFactor = GL_SRC_COLOR;
  86.644 +					break;
  86.645 +				case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR:
  86.646 +					dstFactor = GL_ONE_MINUS_SRC_COLOR;
  86.647 +					break;
  86.648 +				case GLS_DSTBLEND_SRC_ALPHA:
  86.649 +					dstFactor = GL_SRC_ALPHA;
  86.650 +					break;
  86.651 +				case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA:
  86.652 +					dstFactor = GL_ONE_MINUS_SRC_ALPHA;
  86.653 +					break;
  86.654 +				case GLS_DSTBLEND_DST_ALPHA:
  86.655 +					dstFactor = GL_DST_ALPHA;
  86.656 +					break;
  86.657 +				case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA:
  86.658 +					dstFactor = GL_ONE_MINUS_DST_ALPHA;
  86.659 +					break;
  86.660 +				default:
  86.661 +					dstFactor = GL_ONE;	// to get warning to shut up
  86.662 +					ri.Error(ERR_DROP, "GL_State: invalid dst blend state bits\n");
  86.663 +					break;
  86.664 +			}
  86.665 +
  86.666 +			qglEnable(GL_BLEND);
  86.667 +			GL_BlendFunc(srcFactor, dstFactor);
  86.668  		}
  86.669  		else
  86.670  		{
  86.671 -			if ( backEnd.viewParms.isMirror )
  86.672 -			{
  86.673 -				qglCullFace( GL_BACK );
  86.674 -			}
  86.675 -			else
  86.676 -			{
  86.677 -				qglCullFace( GL_FRONT );
  86.678 -			}
  86.679 -		}
  86.680 -	}
  86.681 -}
  86.682 -
  86.683 -/*
  86.684 -** GL_TexEnv
  86.685 -*/
  86.686 -void GL_TexEnv( int env )
  86.687 -{
  86.688 -	if ( env == glState.texEnv[glState.currenttmu] )
  86.689 -	{
  86.690 -		return;
  86.691 -	}
  86.692 -
  86.693 -	glState.texEnv[glState.currenttmu] = env;
  86.694 -
  86.695 -
  86.696 -	switch ( env )
  86.697 -	{
  86.698 -	case GL_MODULATE:
  86.699 -		qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
  86.700 -		break;
  86.701 -	case GL_REPLACE:
  86.702 -		qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
  86.703 -		break;
  86.704 -	case GL_DECAL:
  86.705 -		qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
  86.706 -		break;
  86.707 -	case GL_ADD:
  86.708 -		qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD );
  86.709 -		break;
  86.710 -	default:
  86.711 -		ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed\n", env );
  86.712 -		break;
  86.713 -	}
  86.714 -}
  86.715 -
  86.716 -/*
  86.717 -** GL_State
  86.718 -**
  86.719 -** This routine is responsible for setting the most commonly changed state
  86.720 -** in Q3.
  86.721 -*/
  86.722 -void GL_State( unsigned long stateBits )
  86.723 -{
  86.724 -	unsigned long diff = stateBits ^ glState.glStateBits;
  86.725 -
  86.726 -	if ( !diff )
  86.727 -	{
  86.728 -		return;
  86.729 -	}
  86.730 -
  86.731 -	//
  86.732 -	// check depthFunc bits
  86.733 -	//
  86.734 -	if ( diff & GLS_DEPTHFUNC_EQUAL )
  86.735 -	{
  86.736 -		if ( stateBits & GLS_DEPTHFUNC_EQUAL )
  86.737 -		{
  86.738 -			qglDepthFunc( GL_EQUAL );
  86.739 +			qglDisable(GL_BLEND);
  86.740 +		}
  86.741 +	}
  86.742 +
  86.743 +	// check colormask
  86.744 +	if(diff & GLS_COLORMASK_BITS)
  86.745 +	{
  86.746 +		if(stateBits & GLS_COLORMASK_BITS)
  86.747 +		{
  86.748 +			GL_ColorMask((stateBits & GLS_REDMASK_FALSE) ? GL_FALSE : GL_TRUE,
  86.749 +						 (stateBits & GLS_GREENMASK_FALSE) ? GL_FALSE : GL_TRUE,
  86.750 +						 (stateBits & GLS_BLUEMASK_FALSE) ? GL_FALSE : GL_TRUE,
  86.751 +						 (stateBits & GLS_ALPHAMASK_FALSE) ? GL_FALSE : GL_TRUE);
  86.752  		}
  86.753  		else
  86.754  		{
  86.755 -			qglDepthFunc( GL_LEQUAL );
  86.756 -		}
  86.757 -	}
  86.758 -
  86.759 -	//
  86.760 -	// check blend bits
  86.761 -	//
  86.762 -	if ( diff & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) )
  86.763 -	{
  86.764 -		GLenum srcFactor, dstFactor;
  86.765 -
  86.766 -		if ( stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) )
  86.767 -		{
  86.768 -			switch ( stateBits & GLS_SRCBLEND_BITS )
  86.769 -			{
  86.770 -			case GLS_SRCBLEND_ZERO:
  86.771 -				srcFactor = GL_ZERO;
  86.772 -				break;
  86.773 -			case GLS_SRCBLEND_ONE:
  86.774 -				srcFactor = GL_ONE;
  86.775 -				break;
  86.776 -			case GLS_SRCBLEND_DST_COLOR:
  86.777 -				srcFactor = GL_DST_COLOR;
  86.778 -				break;
  86.779 -			case GLS_SRCBLEND_ONE_MINUS_DST_COLOR:
  86.780 -				srcFactor = GL_ONE_MINUS_DST_COLOR;
  86.781 -				break;
  86.782 -			case GLS_SRCBLEND_SRC_ALPHA:
  86.783 -				srcFactor = GL_SRC_ALPHA;
  86.784 -				break;
  86.785 -			case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA:
  86.786 -				srcFactor = GL_ONE_MINUS_SRC_ALPHA;
  86.787 -				break;
  86.788 -			case GLS_SRCBLEND_DST_ALPHA:
  86.789 -				srcFactor = GL_DST_ALPHA;
  86.790 -				break;
  86.791 -			case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA:
  86.792 -				srcFactor = GL_ONE_MINUS_DST_ALPHA;
  86.793 -				break;
  86.794 -			case GLS_SRCBLEND_ALPHA_SATURATE:
  86.795 -				srcFactor = GL_SRC_ALPHA_SATURATE;
  86.796 -				break;
  86.797 -			default:
  86.798 -				srcFactor = GL_ONE;		// to get warning to shut up
  86.799 -				ri.Error( ERR_DROP, "GL_State: invalid src blend state bits\n" );
  86.800 -				break;
  86.801 -			}
  86.802 -
  86.803 -			switch ( stateBits & GLS_DSTBLEND_BITS )
  86.804 -			{
  86.805 -			case GLS_DSTBLEND_ZERO:
  86.806 -				dstFactor = GL_ZERO;
  86.807 -				break;
  86.808 -			case GLS_DSTBLEND_ONE:
  86.809 -				dstFactor = GL_ONE;
  86.810 -				break;
  86.811 -			case GLS_DSTBLEND_SRC_COLOR:
  86.812 -				dstFactor = GL_SRC_COLOR;
  86.813 -				break;
  86.814 -			case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR:
  86.815 -				dstFactor = GL_ONE_MINUS_SRC_COLOR;
  86.816 -				break;
  86.817 -			case GLS_DSTBLEND_SRC_ALPHA:
  86.818 -				dstFactor = GL_SRC_ALPHA;
  86.819 -				break;
  86.820 -			case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA:
  86.821 -				dstFactor = GL_ONE_MINUS_SRC_ALPHA;
  86.822 -				break;
  86.823 -			case GLS_DSTBLEND_DST_ALPHA:
  86.824 -				dstFactor = GL_DST_ALPHA;
  86.825 -				break;
  86.826 -			case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA:
  86.827 -				dstFactor = GL_ONE_MINUS_DST_ALPHA;
  86.828 -				break;
  86.829 -			default:
  86.830 -				dstFactor = GL_ONE;		// to get warning to shut up
  86.831 -				ri.Error( ERR_DROP, "GL_State: invalid dst blend state bits\n" );
  86.832 -				break;
  86.833 -			}
  86.834 -
  86.835 -			qglEnable( GL_BLEND );
  86.836 -			qglBlendFunc( srcFactor, dstFactor );
  86.837 +			GL_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  86.838 +		}
  86.839 +	}
  86.840 +
  86.841 +	// check depthmask
  86.842 +	if(diff & GLS_DEPTHMASK_TRUE)
  86.843 +	{
  86.844 +		if(stateBits & GLS_DEPTHMASK_TRUE)
  86.845 +		{
  86.846 +			qglDepthMask(GL_TRUE);
  86.847  		}
  86.848  		else
  86.849  		{
  86.850 -			qglDisable( GL_BLEND );
  86.851 -		}
  86.852 -	}
  86.853 -
  86.854 -	//
  86.855 -	// check depthmask
  86.856 -	//
  86.857 -	if ( diff & GLS_DEPTHMASK_TRUE )
  86.858 -	{
  86.859 -		if ( stateBits & GLS_DEPTHMASK_TRUE )
  86.860 -		{
  86.861 -			qglDepthMask( GL_TRUE );
  86.862 +			qglDepthMask(GL_FALSE);
  86.863 +		}
  86.864 +	}
  86.865 +
  86.866 +	// fill/line mode
  86.867 +	if(diff & GLS_POLYMODE_LINE)
  86.868 +	{
  86.869 +		if(stateBits & GLS_POLYMODE_LINE)
  86.870 +		{
  86.871 +			GL_PolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  86.872  		}
  86.873  		else
  86.874  		{
  86.875 -			qglDepthMask( GL_FALSE );
  86.876 -		}
  86.877 -	}
  86.878 -
  86.879 -	//
  86.880 -	// fill/line mode
  86.881 -	//
  86.882 -	if ( diff & GLS_POLYMODE_LINE )
  86.883 -	{
  86.884 -		if ( stateBits & GLS_POLYMODE_LINE )
  86.885 -		{
  86.886 -			qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
  86.887 +			GL_PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  86.888 +		}
  86.889 +	}
  86.890 +
  86.891 +	// depthtest
  86.892 +	if(diff & GLS_DEPTHTEST_DISABLE)
  86.893 +	{
  86.894 +		if(stateBits & GLS_DEPTHTEST_DISABLE)
  86.895 +		{
  86.896 +			qglDisable(GL_DEPTH_TEST);
  86.897  		}
  86.898  		else
  86.899  		{
  86.900 -			qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  86.901 -		}
  86.902 -	}
  86.903 -
  86.904 -	//
  86.905 -	// depthtest
  86.906 -	//
  86.907 -	if ( diff & GLS_DEPTHTEST_DISABLE )
  86.908 -	{
  86.909 -		if ( stateBits & GLS_DEPTHTEST_DISABLE )
  86.910 -		{
  86.911 -			qglDisable( GL_DEPTH_TEST );
  86.912 +			qglEnable(GL_DEPTH_TEST);
  86.913 +		}
  86.914 +	}
  86.915 +
  86.916 +	// alpha test - deprecated in OpenGL 3.0
  86.917 +	/*
  86.918 +	   if(diff & GLS_ATEST_BITS)
  86.919 +	   {
  86.920 +	   switch (stateBits & GLS_ATEST_BITS)
  86.921 +	   {
  86.922 +	   case 0:
  86.923 +	   qglDisable(GL_ALPHA_TEST);
  86.924 +	   break;
  86.925 +	   case GLS_ATEST_GT_0:
  86.926 +	   qglEnable(GL_ALPHA_TEST);
  86.927 +	   qglAlphaFunc(GL_GREATER, 0.0f);
  86.928 +	   break;
  86.929 +	   case GLS_ATEST_LT_80:
  86.930 +	   qglEnable(GL_ALPHA_TEST);
  86.931 +	   qglAlphaFunc(GL_LESS, 0.5f);
  86.932 +	   break;
  86.933 +	   case GLS_ATEST_GE_80:
  86.934 +	   qglEnable(GL_ALPHA_TEST);
  86.935 +	   qglAlphaFunc(GL_GEQUAL, 0.5f);
  86.936 +	   break;
  86.937 +	   case GLS_ATEST_GT_CUSTOM:
  86.938 +	   // FIXME
  86.939 +	   qglEnable(GL_ALPHA_TEST);
  86.940 +	   qglAlphaFunc(GL_GREATER, 0.5f);
  86.941 +	   break;
  86.942 +	   default:
  86.943 +	   assert(0);
  86.944 +	   break;
  86.945 +	   }
  86.946 +	   }
  86.947 +	 */
  86.948 +
  86.949 +	// stenciltest
  86.950 +	if(diff & GLS_STENCILTEST_ENABLE)
  86.951 +	{
  86.952 +		if(stateBits & GLS_STENCILTEST_ENABLE)
  86.953 +		{
  86.954 +			qglEnable(GL_STENCIL_TEST);
  86.955  		}
  86.956  		else
  86.957  		{
  86.958 -			qglEnable( GL_DEPTH_TEST );
  86.959 -		}
  86.960 -	}
  86.961 -
  86.962 -	//
  86.963 -	// alpha test
  86.964 -	//
  86.965 -	if ( diff & GLS_ATEST_BITS )
  86.966 -	{
  86.967 -		switch ( stateBits & GLS_ATEST_BITS )
  86.968 -		{
  86.969 -		case 0:
  86.970 -			qglDisable( GL_ALPHA_TEST );
  86.971 -			break;
  86.972 -		case GLS_ATEST_GT_0:
  86.973 -			qglEnable( GL_ALPHA_TEST );
  86.974 -			qglAlphaFunc( GL_GREATER, 0.0f );
  86.975 -			break;
  86.976 -		case GLS_ATEST_LT_80:
  86.977 -			qglEnable( GL_ALPHA_TEST );
  86.978 -			qglAlphaFunc( GL_LESS, 0.5f );
  86.979 -			break;
  86.980 -		case GLS_ATEST_GE_80:
  86.981 -			qglEnable( GL_ALPHA_TEST );
  86.982 -			qglAlphaFunc( GL_GEQUAL, 0.5f );
  86.983 -			break;
  86.984 -		default:
  86.985 -			assert( 0 );
  86.986 -			break;
  86.987 +			qglDisable(GL_STENCIL_TEST);
  86.988  		}
  86.989  	}
  86.990  
  86.991 @@ -387,6 +666,385 @@
  86.992  }
  86.993  
  86.994  
  86.995 +void GL_VertexAttribsState(unsigned int stateBits)
  86.996 +{
  86.997 +	unsigned int		diff;
  86.998 +
  86.999 +	if(glConfig.vboVertexSkinningAvailable && tess.vboVertexSkinning)
 86.1000 +		stateBits |= (ATTR_BONE_INDEXES | ATTR_BONE_WEIGHTS);
 86.1001 +
 86.1002 +	GL_VertexAttribPointers(stateBits);
 86.1003 +
 86.1004 +	diff = stateBits ^ glState.vertexAttribsState;
 86.1005 +	if(!diff)
 86.1006 +	{
 86.1007 +		return;
 86.1008 +	}
 86.1009 +
 86.1010 +	if(diff & ATTR_POSITION)
 86.1011 +	{
 86.1012 +		if(stateBits & ATTR_POSITION)
 86.1013 +		{
 86.1014 +			if(r_logFile->integer)
 86.1015 +			{
 86.1016 +				GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_POSITION )\n");
 86.1017 +			}
 86.1018 +			qglEnableVertexAttribArrayARB(ATTR_INDEX_POSITION);
 86.1019 +		}
 86.1020 +		else
 86.1021 +		{
 86.1022 +			if(r_logFile->integer)
 86.1023 +			{
 86.1024 +				GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_POSITION )\n");
 86.1025 +			}
 86.1026 +			qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION);
 86.1027 +		}
 86.1028 +	}
 86.1029 +
 86.1030 +	if(diff & ATTR_TEXCOORD)
 86.1031 +	{
 86.1032 +		if(stateBits & ATTR_TEXCOORD)
 86.1033 +		{
 86.1034 +			if(r_logFile->integer)
 86.1035 +			{
 86.1036 +				GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TEXCOORD )\n");
 86.1037 +			}
 86.1038 +			qglEnableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD0);
 86.1039 +		}
 86.1040 +		else
 86.1041 +		{
 86.1042 +			if(r_logFile->integer)
 86.1043 +			{
 86.1044 +				GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TEXCOORD )\n");
 86.1045 +			}
 86.1046 +			qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD0);
 86.1047 +		}
 86.1048 +	}
 86.1049 +
 86.1050 +	if(diff & ATTR_LIGHTCOORD)
 86.1051 +	{
 86.1052 +		if(stateBits & ATTR_LIGHTCOORD)
 86.1053 +		{
 86.1054 +			if(r_logFile->integer)
 86.1055 +			{
 86.1056 +				GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_LIGHTCOORD )\n");
 86.1057 +			}
 86.1058 +			qglEnableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD1);
 86.1059 +		}
 86.1060 +		else
 86.1061 +		{
 86.1062 +			if(r_logFile->integer)
 86.1063 +			{
 86.1064 +				GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_LIGHTCOORD )\n");
 86.1065 +			}
 86.1066 +			qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD1);
 86.1067 +		}
 86.1068 +	}
 86.1069 +
 86.1070 +	if(diff & ATTR_TANGENT)
 86.1071 +	{
 86.1072 +		if(stateBits & ATTR_TANGENT)
 86.1073 +		{
 86.1074 +			if(r_logFile->integer)
 86.1075 +			{
 86.1076 +				GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TANGENT )\n");
 86.1077 +			}
 86.1078 +			qglEnableVertexAttribArrayARB(ATTR_INDEX_TANGENT);
 86.1079 +		}
 86.1080 +		else
 86.1081 +		{
 86.1082 +			if(r_logFile->integer)
 86.1083 +			{
 86.1084 +				GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TANGENT )\n");
 86.1085 +			}
 86.1086 +			qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT);
 86.1087 +		}
 86.1088 +	}
 86.1089 +
 86.1090 +	if(diff & ATTR_BINORMAL)
 86.1091 +	{
 86.1092 +		if(stateBits & ATTR_BINORMAL)
 86.1093 +		{
 86.1094 +			if(r_logFile->integer)
 86.1095 +			{
 86.1096 +				GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_BINORMAL )\n");
 86.1097 +			}
 86.1098 +			qglEnableVertexAttribArrayARB(ATTR_INDEX_BINORMAL);
 86.1099 +		}
 86.1100 +		else
 86.1101 +		{
 86.1102 +			if(r_logFile->integer)
 86.1103 +			{
 86.1104 +				GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_BINORMAL )\n");
 86.1105 +			}
 86.1106 +			qglDisableVertexAttribArrayARB(ATTR_INDEX_BINORMAL);
 86.1107 +		}
 86.1108 +	}
 86.1109 +
 86.1110 +	if(diff & ATTR_NORMAL)
 86.1111 +	{
 86.1112 +		if(stateBits & ATTR_NORMAL)
 86.1113 +		{
 86.1114 +			if(r_logFile->integer)
 86.1115 +			{
 86.1116 +				GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_NORMAL )\n");
 86.1117 +			}
 86.1118 +			qglEnableVertexAttribArrayARB(ATTR_INDEX_NORMAL);
 86.1119 +		}
 86.1120 +		else
 86.1121 +		{
 86.1122 +			if(r_logFile->integer)
 86.1123 +			{
 86.1124 +				GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_NORMAL )\n");
 86.1125 +			}
 86.1126 +			qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL);
 86.1127 +		}
 86.1128 +	}
 86.1129 +
 86.1130 +	if(diff & ATTR_COLOR)
 86.1131 +	{
 86.1132 +		if(stateBits & ATTR_COLOR)
 86.1133 +		{
 86.1134 +			if(r_logFile->integer)
 86.1135 +			{
 86.1136 +				GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_COLOR )\n");
 86.1137 +			}
 86.1138 +			qglEnableVertexAttribArrayARB(ATTR_INDEX_COLOR);
 86.1139 +		}
 86.1140 +		else
 86.1141 +		{
 86.1142 +			if(r_logFile->integer)
 86.1143 +			{
 86.1144 +				GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_COLOR )\n");
 86.1145 +			}
 86.1146 +			qglDisableVertexAttribArrayARB(ATTR_INDEX_COLOR);
 86.1147 +		}
 86.1148 +	}
 86.1149 +
 86.1150 +	if(diff & ATTR_PAINTCOLOR)
 86.1151 +	{
 86.1152 +		if(stateBits & ATTR_PAINTCOLOR)
 86.1153 +		{
 86.1154 +			if(r_logFile->integer)
 86.1155 +			{
 86.1156 +				GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_PAINTCOLOR )\n");
 86.1157 +			}
 86.1158 +			qglEnableVertexAttribArrayARB(ATTR_INDEX_PAINTCOLOR);
 86.1159 +		}
 86.1160 +		else
 86.1161 +		{
 86.1162 +			if(r_logFile->integer)
 86.1163 +			{
 86.1164 +				GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_PAINTCOLOR )\n");
 86.1165 +			}
 86.1166 +			qglDisableVertexAttribArrayARB(ATTR_INDEX_PAINTCOLOR);
 86.1167 +		}
 86.1168 +	}
 86.1169 +
 86.1170 +	if(diff & ATTR_LIGHTDIRECTION)
 86.1171 +	{
 86.1172 +		if(stateBits & ATTR_LIGHTDIRECTION)
 86.1173 +		{
 86.1174 +			if(r_logFile->integer)
 86.1175 +			{
 86.1176 +				GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_LIGHTDIRECTION )\n");
 86.1177 +			}
 86.1178 +			qglEnableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION);
 86.1179 +		}
 86.1180 +		else
 86.1181 +		{
 86.1182 +			if(r_logFile->integer)
 86.1183 +			{
 86.1184 +				GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_LIGHTDIRECTION )\n");
 86.1185 +			}
 86.1186 +			qglDisableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION);
 86.1187 +		}
 86.1188 +	}
 86.1189 +
 86.1190 +	if(diff & ATTR_BONE_INDEXES)
 86.1191 +	{
 86.1192 +		if(stateBits & ATTR_BONE_INDEXES)
 86.1193 +		{
 86.1194 +			if(r_logFile->integer)
 86.1195 +			{
 86.1196 +				GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_BONE_INDEXES )\n");
 86.1197 +			}
 86.1198 +			qglEnableVertexAttribArrayARB(ATTR_INDEX_BONE_INDEXES);
 86.1199 +		}
 86.1200 +		else
 86.1201 +		{
 86.1202 +			if(r_logFile->integer)
 86.1203 +			{
 86.1204 +				GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_BONE_INDEXES )\n");
 86.1205 +			}
 86.1206 +			qglDisableVertexAttribArrayARB(ATTR_INDEX_BONE_INDEXES);
 86.1207 +		}
 86.1208 +	}
 86.1209 +
 86.1210 +	if(diff & ATTR_BONE_WEIGHTS)
 86.1211 +	{
 86.1212 +		if(stateBits & ATTR_BONE_WEIGHTS)
 86.1213 +		{
 86.1214 +			if(r_logFile->integer)
 86.1215 +			{
 86.1216 +				GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_BONE_WEIGHTS )\n");
 86.1217 +			}
 86.1218 +			qglEnableVertexAttribArrayARB(ATTR_INDEX_BONE_WEIGHTS);
 86.1219 +		}
 86.1220 +		else
 86.1221 +		{
 86.1222 +			if(r_logFile->integer)
 86.1223 +			{
 86.1224 +				GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_BONE_WEIGHTS )\n");
 86.1225 +			}
 86.1226 +			qglDisableVertexAttribArrayARB(ATTR_INDEX_BONE_WEIGHTS);
 86.1227 +		}
 86.1228 +	}
 86.1229 +
 86.1230 +	glState.vertexAttribsState = stateBits;
 86.1231 +}
 86.1232 +
 86.1233 +void GL_VertexAttribPointers(unsigned int attribBits)
 86.1234 +{
 86.1235 +	if(!glState.currentVBO)
 86.1236 +	{
 86.1237 +		ri.Error(ERR_FATAL, "GL_VertexAttribPointers: no VBO bound");
 86.1238 +		return;
 86.1239 +	}
 86.1240 +
 86.1241 +	if(r_logFile->integer)
 86.1242 +	{
 86.1243 +		// don't just call LogComment, or we will get a call to va() every frame!
 86.1244 +		GLimp_LogComment(va("--- GL_VertexAttribPointers( %s ) ---\n", glState.currentVBO->name));
 86.1245 +	}
 86.1246 +
 86.1247 +	if(glConfig.vboVertexSkinningAvailable && tess.vboVertexSkinning)
 86.1248 +		attribBits |= (ATTR_BONE_INDEXES | ATTR_BONE_WEIGHTS);
 86.1249 +
 86.1250 +	if((attribBits & ATTR_POSITION) && !(glState.vertexAttribPointersSet & ATTR_POSITION))
 86.1251 +	{
 86.1252 +		if(r_logFile->integer)
 86.1253 +		{
 86.1254 +			GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_POSITION )\n");
 86.1255 +		}
 86.1256 +
 86.1257 +		qglVertexAttribPointerARB(ATTR_INDEX_POSITION, 4, GL_FLOAT, 0, 0, BUFFER_OFFSET(glState.currentVBO->ofsXYZ));
 86.1258 +		glState.vertexAttribPointersSet |= ATTR_POSITION;
 86.1259 +	}
 86.1260 +
 86.1261 +	if((attribBits & ATTR_TEXCOORD) && !(glState.vertexAttribPointersSet & ATTR_TEXCOORD))
 86.1262 +	{
 86.1263 +		if(r_logFile->integer)
 86.1264 +		{
 86.1265 +			GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TEXCOORD )\n");
 86.1266 +		}
 86.1267 +
 86.1268 +		qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD0, 4, GL_FLOAT, 0, 0, BUFFER_OFFSET(glState.currentVBO->ofsTexCoords));
 86.1269 +		glState.vertexAttribPointersSet |= ATTR_TEXCOORD;
 86.1270 +	}
 86.1271 +
 86.1272 +	if((attribBits & ATTR_LIGHTCOORD) && !(glState.vertexAttribPointersSet & ATTR_LIGHTCOORD))
 86.1273 +	{
 86.1274 +		if(r_logFile->integer)
 86.1275 +		{
 86.1276 +			GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_LIGHTCOORD )\n");
 86.1277 +		}
 86.1278 +
 86.1279 +		qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD1, 4, GL_FLOAT, 0, 0, BUFFER_OFFSET(glState.currentVBO->ofsLightCoords));
 86.1280 +		glState.vertexAttribPointersSet |= ATTR_LIGHTCOORD;
 86.1281 +	}
 86.1282 +
 86.1283 +	if((attribBits & ATTR_TANGENT) && !(glState.vertexAttribPointersSet & ATTR_TANGENT))
 86.1284 +	{
 86.1285 +		if(r_logFile->integer)
 86.1286 +		{
 86.1287 +			GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TANGENT )\n");
 86.1288 +		}
 86.1289 +
 86.1290 +		qglVertexAttribPointerARB(ATTR_INDEX_TANGENT, 3, GL_FLOAT, 0, 16, BUFFER_OFFSET(glState.currentVBO->ofsTangents));
 86.1291 +		glState.vertexAttribPointersSet |= ATTR_TANGENT;
 86.1292 +	}
 86.1293 +
 86.1294 +	if((attribBits & ATTR_BINORMAL) && !(glState.vertexAttribPointersSet & ATTR_BINORMAL))
 86.1295 +	{
 86.1296 +		if(r_logFile->integer)
 86.1297 +		{
 86.1298 +			GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_BINORMAL )\n");
 86.1299 +		}
 86.1300 +
 86.1301 +		qglVertexAttribPointerARB(ATTR_INDEX_BINORMAL, 3, GL_FLOAT, 0, 16, BUFFER_OFFSET(glState.currentVBO->ofsBinormals));
 86.1302 +		glState.vertexAttribPointersSet |= ATTR_BINORMAL;
 86.1303 +	}
 86.1304 +
 86.1305 +	if((attribBits & ATTR_NORMAL) && !(glState.vertexAttribPointersSet & ATTR_NORMAL))
 86.1306 +	{
 86.1307 +		if(r_logFile->integer)
 86.1308 +		{
 86.1309 +			GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_NORMAL )\n");
 86.1310 +		}
 86.1311 +
 86.1312 +		qglVertexAttribPointerARB(ATTR_INDEX_NORMAL, 3, GL_FLOAT, 0, 16, BUFFER_OFFSET(glState.currentVBO->ofsNormals));
 86.1313 +		glState.vertexAttribPointersSet |= ATTR_NORMAL;
 86.1314 +	}
 86.1315 +
 86.1316 +	if((attribBits & ATTR_COLOR) && !(glState.vertexAttribPointersSet & ATTR_COLOR))
 86.1317 +	{
 86.1318 +		if(r_logFile->integer)
 86.1319 +		{
 86.1320 +			GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_COLOR )\n");
 86.1321 +		}
 86.1322 +
 86.1323 +		qglVertexAttribPointerARB(ATTR_INDEX_COLOR, 4, GL_FLOAT, 0, 0, BUFFER_OFFSET(glState.currentVBO->ofsColors));
 86.1324 +		glState.vertexAttribPointersSet |= ATTR_COLOR;
 86.1325 +	}
 86.1326 +
 86.1327 +	if((attribBits & ATTR_PAINTCOLOR) && !(glState.vertexAttribPointersSet & ATTR_PAINTCOLOR))
 86.1328 +	{
 86.1329 +		if(r_logFile->integer)
 86.1330 +		{
 86.1331 +			GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_PAINTCOLOR )\n");
 86.1332 +		}
 86.1333 +
 86.1334 +		qglVertexAttribPointerARB(ATTR_INDEX_PAINTCOLOR, 4, GL_FLOAT, 0, 0, BUFFER_OFFSET(glState.currentVBO->ofsPaintColors));
 86.1335 +		glState.vertexAttribPointersSet |= ATTR_PAINTCOLOR;
 86.1336 +	}
 86.1337 +
 86.1338 +	if((attribBits & ATTR_LIGHTDIRECTION) && !(glState.vertexAttribPointersSet & ATTR_LIGHTDIRECTION))
 86.1339 +	{
 86.1340 +		if(r_logFile->integer)
 86.1341 +		{
 86.1342 +			GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_LIGHTDIRECTION )\n");
 86.1343 +		}
 86.1344 +
 86.1345 +		qglVertexAttribPointerARB(ATTR_INDEX_LIGHTDIRECTION, 3, GL_FLOAT, 0, 16, BUFFER_OFFSET(glState.currentVBO->ofsLightDirections));
 86.1346 +		glState.vertexAttribPointersSet |= ATTR_LIGHTDIRECTION;
 86.1347 +	}
 86.1348 +
 86.1349 +	if((attribBits & ATTR_BONE_INDEXES) && !(glState.vertexAttribPointersSet & ATTR_BONE_INDEXES))
 86.1350 +	{
 86.1351 +		if(r_logFile->integer)
 86.1352 +		{
 86.1353 +			GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_BONE_INDEXES )\n");
 86.1354 +		}
 86.1355 +
 86.1356 +		qglVertexAttribPointerARB(ATTR_INDEX_BONE_INDEXES, 4, GL_INT, 0, 0, BUFFER_OFFSET(glState.currentVBO->ofsBoneIndexes));
 86.1357 +		glState.vertexAttribPointersSet |= ATTR_BONE_INDEXES;
 86.1358 +	}
 86.1359 +
 86.1360 +	if((attribBits & ATTR_BONE_WEIGHTS) && !(glState.vertexAttribPointersSet & ATTR_BONE_WEIGHTS))
 86.1361 +	{
 86.1362 +		if(r_logFile->integer)
 86.1363 +		{
 86.1364 +			GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_BONE_WEIGHTS )\n");
 86.1365 +		}
 86.1366 +
 86.1367 +		qglVertexAttribPointerARB(ATTR_INDEX_BONE_WEIGHTS, 4, GL_FLOAT, 0, 0, BUFFER_OFFSET(glState.currentVBO->ofsBoneWeights));
 86.1368 +		glState.vertexAttribPointersSet |= ATTR_BONE_WEIGHTS;
 86.1369 +	}
 86.1370 +}
 86.1371 +
 86.1372 +
 86.1373 +
 86.1374  
 86.1375  /*
 86.1376  ================
 86.1377 @@ -395,302 +1053,6609 @@
 86.1378  A player has predicted a teleport, but hasn't arrived yet
 86.1379  ================
 86.1380  */
 86.1381 -static void RB_Hyperspace( void ) {
 86.1382 -	float		c;
 86.1383 -
 86.1384 -	if ( !backEnd.isHyperspace ) {
 86.1385 +static void RB_Hyperspace(void)
 86.1386 +{
 86.1387 +	float           c;
 86.1388 +
 86.1389 +	if(!backEnd.isHyperspace)
 86.1390 +	{
 86.1391  		// do initialization shit
 86.1392  	}
 86.1393  
 86.1394 -	c = ( backEnd.refdef.time & 255 ) / 255.0f;
 86.1395 -	qglClearColor( c, c, c, 1 );
 86.1396 -	qglClear( GL_COLOR_BUFFER_BIT );
 86.1397 +	c = (backEnd.refdef.time & 255) / 255.0f;
 86.1398 +	GL_ClearColor(c, c, c, 1);
 86.1399 +	qglClear(GL_COLOR_BUFFER_BIT);
 86.1400  
 86.1401  	backEnd.isHyperspace = qtrue;
 86.1402  }
 86.1403  
 86.1404  
 86.1405 -static void SetViewportAndScissor( void ) {
 86.1406 -	qglMatrixMode(GL_PROJECTION);
 86.1407 -	qglLoadMatrixf( backEnd.viewParms.projectionMatrix );
 86.1408 -	qglMatrixMode(GL_MODELVIEW);
 86.1409 +static void SetViewportAndScissor(void)
 86.1410 +{
 86.1411 +	GL_LoadProjectionMatrix(backEnd.viewParms.projectionMatrix);
 86.1412  
 86.1413  	// set the window clipping
 86.1414 -	qglViewport( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY, 
 86.1415 -		backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight );
 86.1416 -	qglScissor( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY, 
 86.1417 -		backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight );
 86.1418 +	GL_Viewport(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
 86.1419 +				backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
 86.1420 +
 86.1421 +	GL_Scissor(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
 86.1422 +			   backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
 86.1423  }
 86.1424  
 86.1425 +
 86.1426 +
 86.1427 +
 86.1428  /*
 86.1429 -=================
 86.1430 -RB_BeginDrawingView
 86.1431 -
 86.1432 -Any mirrored or portaled views have already been drawn, so prepare
 86.1433 -to actually render the visible surfaces for this view
 86.1434 -=================
 86.1435 +================
 86.1436 +RB_SetGL2D
 86.1437 +================
 86.1438  */
 86.1439 -void RB_BeginDrawingView (void) {
 86.1440 -	int clearBits = 0;
 86.1441 -
 86.1442 -	// sync with gl if needed
 86.1443 -	if ( r_finish->integer == 1 && !glState.finishCalled ) {
 86.1444 -		qglFinish ();
 86.1445 -		glState.finishCalled = qtrue;
 86.1446 -	}
 86.1447 -	if ( r_finish->integer == 0 ) {
 86.1448 -		glState.finishCalled = qtrue;
 86.1449 -	}
 86.1450 -
 86.1451 -	// we will need to change the projection matrix before drawing
 86.1452 -	// 2D images again
 86.1453 -	backEnd.projection2D = qfalse;
 86.1454 -
 86.1455 -	//
 86.1456 -	// set the modelview matrix for the viewer
 86.1457 -	//
 86.1458 -	SetViewportAndScissor();
 86.1459 -
 86.1460 -	// ensures that depth writes are enabled for the depth clear
 86.1461 -	GL_State( GLS_DEFAULT );
 86.1462 -	// clear relevant buffers
 86.1463 -	clearBits = GL_DEPTH_BUFFER_BIT;
 86.1464 -
 86.1465 -	if ( r_measureOverdraw->integer || r_shadows->integer == 2 )
 86.1466 -	{
 86.1467 -		clearBits |= GL_STENCIL_BUFFER_BIT;
 86.1468 -	}
 86.1469 -	if ( r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) )
 86.1470 -	{
 86.1471 -		clearBits |= GL_COLOR_BUFFER_BIT;	// FIXME: only if sky shaders have been used
 86.1472 -#ifdef _DEBUG
 86.1473 -		qglClearColor( 0.8f, 0.7f, 0.4f, 1.0f );	// FIXME: get color of sky
 86.1474 -#else
 86.1475 -		qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f );	// FIXME: get color of sky
 86.1476 -#endif
 86.1477 -	}
 86.1478 -	qglClear( clearBits );
 86.1479 -
 86.1480 -	if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) )
 86.1481 -	{
 86.1482 -		RB_Hyperspace();
 86.1483 -		return;
 86.1484 -	}
 86.1485 -	else
 86.1486 -	{
 86.1487 -		backEnd.isHyperspace = qfalse;
 86.1488 -	}
 86.1489 -
 86.1490 -	glState.faceCulling = -1;		// force face culling to set next time
 86.1491 -
 86.1492 -	// we will only draw a sun if there was sky rendered in this view
 86.1493 -	backEnd.skyRenderedThisView = qfalse;
 86.1494 -
 86.1495 -	// clip to the plane of the portal
 86.1496 -	if ( backEnd.viewParms.isPortal ) {
 86.1497 -		float	plane[4];
 86.1498 -		double	plane2[4];
 86.1499 -
 86.1500 -		plane[0] = backEnd.viewParms.portalPlane.normal[0];
 86.1501 -		plane[1] = backEnd.viewParms.portalPlane.normal[1];
 86.1502 -		plane[2] = backEnd.viewParms.portalPlane.normal[2];
 86.1503 -		plane[3] = backEnd.viewParms.portalPlane.dist;
 86.1504 -
 86.1505 -		plane2[0] = DotProduct (backEnd.viewParms.or.axis[0], plane);
 86.1506 -		plane2[1] = DotProduct (backEnd.viewParms.or.axis[1], plane);
 86.1507 -		plane2[2] = DotProduct (backEnd.viewParms.or.axis[2], plane);
 86.1508 -		plane2[3] = DotProduct (plane, backEnd.viewParms.or.origin) - plane[3];
 86.1509 -
 86.1510 -		qglLoadMatrixf( s_flipMatrix );
 86.1511 -		qglClipPlane (GL_CLIP_PLANE0, plane2);
 86.1512 -		qglEnable (GL_CLIP_PLANE0);
 86.1513 -	} else {
 86.1514 -		qglDisable (GL_CLIP_PLANE0);
 86.1515 -	}
 86.1516 +static void RB_SetGL2D(void)
 86.1517 +{
 86.1518 +	matrix_t        proj;
 86.1519 +
 86.1520 +	GLimp_LogComment("--- RB_SetGL2D ---\n");
 86.1521 +
 86.1522 +	// disable offscreen rendering
 86.1523 +	if(glConfig.framebufferObjectAvailable)
 86.1524 +	{
 86.1525 +		R_BindNullFBO();
 86.1526 +	}
 86.1527 +
 86.1528 +	backEnd.projection2D = qtrue;
 86.1529 +
 86.1530 +	// set 2D virtual screen size
 86.1531 +	GL_Viewport(0, 0, glConfig.vidWidth, glConfig.vidHeight);
 86.1532 +	GL_Scissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);
 86.1533 +
 86.1534 +	MatrixSetupOrthogonalProjection(proj, 0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1);
 86.1535 +	GL_LoadProjectionMatrix(proj);
 86.1536 +	GL_LoadModelViewMatrix(matrixIdentity);
 86.1537 +
 86.1538 +	GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
 86.1539 +
 86.1540 +	qglDisable(GL_CULL_FACE);
 86.1541 +	qglDisable(GL_CLIP_PLANE0);
 86.1542 +
 86.1543 +	// set time for 2D shaders
 86.1544 +	backEnd.refdef.time = ri.Milliseconds();
 86.1545 +	backEnd.refdef.floatTime = backEnd.refdef.time * 0.001f;
 86.1546  }
 86.1547  
 86.1548  
 86.1549 -#define	MAC_EVENT_PUMP_MSEC		5
 86.1550 -
 86.1551 -/*
 86.1552 -==================
 86.1553 -RB_RenderDrawSurfList
 86.1554 -==================
 86.1555 -*/
 86.1556 -void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
 86.1557 -	shader_t		*shader, *oldShader;
 86.1558 -	int				fogNum, oldFogNum;
 86.1559 -	int				entityNum, oldEntityNum;
 86.1560 -	int				dlighted, oldDlighted;
 86.1561 -	qboolean		depthRange, oldDepthRange, isCrosshair, wasCrosshair;
 86.1562 -	int				i;
 86.1563 -	drawSurf_t		*drawSurf;
 86.1564 -	int				oldSort;
 86.1565 -	float			originalTime;
 86.1566 -
 86.1567 -	// save original time for entity shader offsets
 86.1568 -	originalTime = backEnd.refdef.floatTime;
 86.1569 -
 86.1570 -	// clear the z buffer, set the modelview, etc
 86.1571 -	RB_BeginDrawingView ();
 86.1572 +
 86.1573 +static void RB_RenderDrawSurfaces(qboolean opaque, qboolean depthFill)
 86.1574 +{
 86.1575 +	trRefEntity_t  *entity, *oldEntity;
 86.1576 +	shader_t       *shader, *oldShader;
 86.1577 +	int             lightmapNum, oldLightmapNum;
 86.1578 +	qboolean        depthRange, oldDepthRange;
 86.1579 +	int             i;
 86.1580 +	drawSurf_t     *drawSurf;
 86.1581 +
 86.1582 +	GLimp_LogComment("--- RB_RenderDrawSurfaces ---\n");
 86.1583  
 86.1584  	// draw everything
 86.1585 -	oldEntityNum = -1;
 86.1586 -	backEnd.currentEntity = &tr.worldEntity;
 86.1587 +	oldEntity = NULL;
 86.1588  	oldShader = NULL;
 86.1589 -	oldFogNum = -1;
 86.1590 +	oldLightmapNum = -1;
 86.1591  	oldDepthRange = qfalse;
 86.1592 -	wasCrosshair = qfalse;
 86.1593 -	oldDlighted = qfalse;
 86.1594 -	oldSort = -1;
 86.1595  	depthRange = qfalse;
 86.1596 -
 86.1597 -	backEnd.pc.c_surfaces += numDrawSurfs;
 86.1598 -
 86.1599 -	for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) {
 86.1600 -		if ( drawSurf->sort == oldSort ) {
 86.1601 +	backEnd.currentLight = NULL;
 86.1602 +
 86.1603 +	for(i = 0, drawSurf = backEnd.viewParms.drawSurfs; i < backEnd.viewParms.numDrawSurfs; i++, drawSurf++)
 86.1604 +	{
 86.1605 +		// update locals
 86.1606 +		entity = drawSurf->entity;
 86.1607 +		shader = tr.sortedShaders[drawSurf->shaderNum];
 86.1608 +		lightmapNum = drawSurf->lightmapNum;
 86.1609 +
 86.1610 +		if(opaque)
 86.1611 +		{
 86.1612 +			// skip all translucent surfaces that don't matter for this pass
 86.1613 +			if(shader->sort > SS_OPAQUE)
 86.1614 +			{
 86.1615 +				break;
 86.1616 +			}
 86.1617 +		}
 86.1618 +		else
 86.1619 +		{
 86.1620 +			// skip all opaque surfaces that don't matter for this pass
 86.1621 +			if(shader->sort <= SS_OPAQUE)
 86.1622 +			{
 86.1623 +				continue;
 86.1624 +			}
 86.1625 +		}
 86.1626 +
 86.1627 +		if(entity == oldEntity && shader == oldShader && lightmapNum == oldLightmapNum)
 86.1628 +		{
 86.1629  			// fast path, same as previous sort
 86.1630 -			rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
 86.1631 +			rb_surfaceTable[*drawSurf->surface] (drawSurf->surface);
 86.1632  			continue;
 86.1633  		}
 86.1634 -		oldSort = drawSurf->sort;
 86.1635 -		R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted );
 86.1636 -
 86.1637 -		//
 86.1638 +
 86.1639  		// change the tess parameters if needed
 86.1640  		// a "entityMergable" shader is a shader that can have surfaces from seperate
 86.1641  		// entities merged into a single batch, like smoke and blood puff sprites
 86.1642 -		if (shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted 
 86.1643 -			|| ( entityNum != oldEntityNum && !shader->entityMergable ) ) {
 86.1644 -			if (oldShader != NULL) {
 86.1645 -				RB_EndSurface();
 86.1646 -			}
 86.1647 -			RB_BeginSurface( shader, fogNum );
 86.1648 +		if(shader != oldShader || lightmapNum != oldLightmapNum || (entity != oldEntity && !shader->entityMergable))
 86.1649 +		{
 86.1650 +			if(oldShader != NULL)
 86.1651 +			{
 86.1652 +				Tess_End();
 86.1653 +			}
 86.1654 +
 86.1655 +			if(depthFill)
 86.1656 +				Tess_Begin(Tess_StageIteratorDepthFill, shader, NULL, qtrue, qfalse, lightmapNum);
 86.1657 +			else
 86.1658 +				Tess_Begin(Tess_StageIteratorGeneric, shader, NULL, qfalse, qfalse, lightmapNum);
 86.1659 +
 86.1660  			oldShader = shader;
 86.1661 -			oldFogNum = fogNum;
 86.1662 -			oldDlighted = dlighted;
 86.1663 -		}
 86.1664 -
 86.1665 -		//
 86.1666 +			oldLightmapNum = lightmapNum;
 86.1667 +		}
 86.1668 +
 86.1669  		// change the modelview matrix if needed
 86.1670 -		//
 86.1671 -		if ( entityNum != oldEntityNum ) {
 86.1672 -			depthRange = isCrosshair = qfalse;
 86.1673 -
 86.1674 -			if ( entityNum != ENTITYNUM_WORLD ) {
 86.1675 -				backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
 86.1676 -				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
 86.1677 -				// we have to reset the shaderTime as well otherwise image animations start
 86.1678 -				// from the wrong frame
 86.1679 -				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
 86.1680 +		if(entity != oldEntity)
 86.1681 +		{
 86.1682 +			depthRange = qfalse;
 86.1683 +
 86.1684 +			if(entity != &tr.worldEntity)
 86.1685 +			{
 86.1686 +				backEnd.currentEntity = entity;
 86.1687  
 86.1688  				// set up the transformation matrix
 86.1689 -				R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.or );
 86.1690 -
 86.1691 -				// set up the dynamic lighting if needed
 86.1692 -				if ( backEnd.currentEntity->needDlights ) {
 86.1693 -					R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
 86.1694 -				}
 86.1695 +				R_RotateEntityForViewParms(backEnd.currentEntity, &backEnd.viewParms, &backEnd.orientation);
 86.1696  
 86.1697  				if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK)
 86.1698  				{
 86.1699  					// hack the depth range to prevent view model from poking into walls
 86.1700  					depthRange = qtrue;
 86.1701 -					
 86.1702 -					if(backEnd.currentEntity->e.renderfx & RF_CROSSHAIR)
 86.1703 -						isCrosshair = qtrue;
 86.1704 -				}
 86.1705 -			} else {
 86.1706 +				}
 86.1707 +			}
 86.1708 +			else
 86.1709 +			{
 86.1710  				backEnd.currentEntity = &tr.worldEntity;
 86.1711 -				backEnd.refdef.floatTime = originalTime;
 86.1712 -				backEnd.or = backEnd.viewParms.world;
 86.1713 -				// we have to reset the shaderTime as well otherwise image animations on
 86.1714 -				// the world (like water) continue with the wrong frame
 86.1715 -				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
 86.1716 -				R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
 86.1717 -			}
 86.1718 -
 86.1719 -			qglLoadMatrixf( backEnd.or.modelMatrix );
 86.1720 -
 86.1721 -			//
 86.1722 -			// change depthrange. Also change projection matrix so first person weapon does not look like coming
 86.1723 -			// out of the screen.
 86.1724 -			//
 86.1725 -			if (oldDepthRange != depthRange || wasCrosshair != isCrosshair)
 86.1726 -			{
 86.1727 -				if (depthRange)
 86.1728 -				{
 86.1729 -					if(backEnd.viewParms.stereoFrame != STEREO_CENTER)
 86.1730 +				backEnd.orientation = backEnd.viewParms.world;
 86.1731 +			}
 86.1732 +
 86.1733 +			GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.1734 +
 86.1735 +			// change depthrange if needed
 86.1736 +			if(oldDepthRange != depthRange)
 86.1737 +			{
 86.1738 +				if(depthRange)
 86.1739 +				{
 86.1740 +					qglDepthRange(0, 0.3);
 86.1741 +				}
 86.1742 +				else
 86.1743 +				{
 86.1744 +					qglDepthRange(0, 1);
 86.1745 +				}
 86.1746 +				oldDepthRange = depthRange;
 86.1747 +			}
 86.1748 +
 86.1749 +			oldEntity = entity;
 86.1750 +		}
 86.1751 +
 86.1752 +		// add the triangles for this surface
 86.1753 +		rb_surfaceTable[*drawSurf->surface] (drawSurf->surface);
 86.1754 +	}
 86.1755 +
 86.1756 +	// draw the contents of the last shader batch
 86.1757 +	if(oldShader != NULL)
 86.1758 +	{
 86.1759 +		Tess_End();
 86.1760 +	}
 86.1761 +
 86.1762 +	// go back to the world modelview matrix
 86.1763 +	GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.1764 +	if(depthRange)
 86.1765 +	{
 86.1766 +		qglDepthRange(0, 1);
 86.1767 +	}
 86.1768 +
 86.1769 +	GL_CheckErrors();
 86.1770 +}
 86.1771 +
 86.1772 +// *INDENT-OFF*
 86.1773 +#ifdef VOLUMETRIC_LIGHTING
 86.1774 +static void Render_lightVolume(trRefLight_t * light)
 86.1775 +{
 86.1776 +	int             j;
 86.1777 +	shader_t       *lightShader;
 86.1778 +	shaderStage_t  *attenuationXYStage;
 86.1779 +	shaderStage_t  *attenuationZStage;
 86.1780 +
 86.1781 +	// rotate into light space
 86.1782 +	R_RotateLightForViewParms(light, &backEnd.viewParms, &backEnd.orientation);
 86.1783 +	GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.1784 +
 86.1785 +	switch (light->l.rlType)
 86.1786 +	{
 86.1787 +		case RL_PROJ:
 86.1788 +		{
 86.1789 +			MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.0);	// bias
 86.1790 +			MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 1.0 / light->l.distance);	// scale
 86.1791 +			break;
 86.1792 +		}
 86.1793 +
 86.1794 +		case RL_OMNI:
 86.1795 +		default:
 86.1796 +		{
 86.1797 +			MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.5);	// bias
 86.1798 +			MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 0.5);	// scale
 86.1799 +			break;
 86.1800 +		}
 86.1801 +	}
 86.1802 +	MatrixMultiply2(light->attenuationMatrix, light->projectionMatrix);	// light projection (frustum)
 86.1803 +	MatrixMultiply2(light->attenuationMatrix, light->viewMatrix);
 86.1804 +
 86.1805 +	lightShader = light->shader;
 86.1806 +	attenuationZStage = lightShader->stages[0];
 86.1807 +
 86.1808 +	for(j = 1; j < MAX_SHADER_STAGES; j++)
 86.1809 +	{
 86.1810 +		attenuationXYStage = lightShader->stages[j];
 86.1811 +
 86.1812 +		if(!attenuationXYStage)
 86.1813 +		{
 86.1814 +			break;
 86.1815 +		}
 86.1816 +
 86.1817 +		if(attenuationXYStage->type != ST_ATTENUATIONMAP_XY)
 86.1818 +		{
 86.1819 +			continue;
 86.1820 +		}
 86.1821 +
 86.1822 +		if(!RB_EvalExpression(&attenuationXYStage->ifExp, 1.0))
 86.1823 +		{
 86.1824 +			continue;
 86.1825 +		}
 86.1826 +
 86.1827 +		Tess_ComputeColor(attenuationXYStage);
 86.1828 +		R_ComputeFinalAttenuation(attenuationXYStage, light);
 86.1829 +
 86.1830 +		if(light->l.rlType == RL_OMNI)
 86.1831 +		{
 86.1832 +			vec3_t          viewOrigin;
 86.1833 +			vec3_t          lightOrigin;
 86.1834 +			vec4_t          lightColor;
 86.1835 +
 86.1836 +			GLimp_LogComment("--- Render_lightVolume_omni ---\n");
 86.1837 +
 86.1838 +			// enable shader, set arrays
 86.1839 +			GL_BindProgram(tr.lightVolumeShader_omni.program);
 86.1840 +			//GL_VertexAttribsState(tr.lightVolumeShader_omni.attribs);
 86.1841 +			GL_Cull(CT_BACK_SIDED);
 86.1842 +			GL_SelectTexture(0);
 86.1843 +			GL_Bind(tr.whiteImage);
 86.1844 +
 86.1845 +			// don't write to the depth buffer
 86.1846 +			GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
 86.1847 +			//GL_State(GLS_DEPTHFUNC_LESS | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
 86.1848 +			//GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
 86.1849 +			//GL_State(attenuationXYStage->stateBits & ~(GLS_DEPTHMASK_TRUE | GLS_DEPTHTEST_DISABLE));
 86.1850 +
 86.1851 +			// set uniforms
 86.1852 +			VectorCopy(backEnd.viewParms.orientation.origin, viewOrigin);	// in world space
 86.1853 +			VectorCopy(light->origin, lightOrigin);
 86.1854 +			VectorCopy(tess.svars.color, lightColor);
 86.1855 +
 86.1856 +			GLSL_SetUniform_ViewOrigin(&tr.lightVolumeShader, viewOrigin);
 86.1857 +			qglUniform3fARB(tr.lightVolumeShader_omni.u_LightOrigin, lightOrigin[0], lightOrigin[1], lightOrigin[2]);
 86.1858 +			qglUniform3fARB(tr.lightVolumeShader_omni.u_LightColor, lightColor[0], lightColor[1], lightColor[2]);
 86.1859 +			qglUniform1fARB(tr.lightVolumeShader_omni.u_LightRadius, light->sphereRadius);
 86.1860 +			qglUniform1fARB(tr.lightVolumeShader_omni.u_LightScale, r_lightScale->value);
 86.1861 +			qglUniformMatrix4fvARB(tr.lightVolumeShader_omni.u_LightAttenuationMatrix, 1, GL_FALSE, light->attenuationMatrix2);
 86.1862 +			qglUniform1iARB(tr.lightVolumeShader_omni.u_ShadowCompare, !light->l.noShadows);
 86.1863 +			qglUniformMatrix4fvARB(tr.lightVolumeShader_omni.u_ModelMatrix, 1, GL_FALSE, backEnd.orientation.transformMatrix);
 86.1864 +			qglUniformMatrix4fvARB(tr.lightVolumeShader_omni.u_ModelViewProjectionMatrix, 1, GL_FALSE, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.1865 +
 86.1866 +			// bind u_AttenuationMapXY
 86.1867 +			GL_SelectTexture(0);
 86.1868 +			BindAnimatedImage(&attenuationXYStage->bundle[TB_COLORMAP]);
 86.1869 +
 86.1870 +			// bind u_AttenuationMapZ
 86.1871 +			GL_SelectTexture(1);
 86.1872 +			BindAnimatedImage(&attenuationZStage->bundle[TB_COLORMAP]);
 86.1873 +
 86.1874 +			// bind u_ShadowMap
 86.1875 +			if(r_shadows->integer >= 4)
 86.1876 +			{
 86.1877 +				GL_SelectTexture(2);
 86.1878 +				GL_Bind(tr.shadowCubeFBOImage[light->shadowLOD]);
 86.1879 +			}
 86.1880 +
 86.1881 +			// draw the volume
 86.1882 +			qglBegin(GL_QUADS);
 86.1883 +
 86.1884 +			qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorRed);
 86.1885 +			qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2]);
 86.1886 +			qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2]);
 86.1887 +			qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2]);
 86.1888 +			qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2]);
 86.1889 +
 86.1890 +			qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, (colorGreen);
 86.1891 +			qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2]);
 86.1892 +			qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2]);
 86.1893 +			qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2]);
 86.1894 +			qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2]);
 86.1895 +
 86.1896 +			qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorBlue);
 86.1897 +			qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2]);
 86.1898 +			qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2]);
 86.1899 +			qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2]);
 86.1900 +			qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2]);
 86.1901 +
 86.1902 +			qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorYellow);
 86.1903 +			qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2]);
 86.1904 +			qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2]);
 86.1905 +			qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2]);
 86.1906 +			qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2]);
 86.1907 +
 86.1908 +			qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorMagenta);
 86.1909 +			qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2]);
 86.1910 +			qglVertex3f(light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2]);
 86.1911 +			qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2]);
 86.1912 +			qglVertex3f(light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2]);
 86.1913 +
 86.1914 +			qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorCyan);
 86.1915 +			qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2]);
 86.1916 +			qglVertex3f(light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2]);
 86.1917 +			qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2]);
 86.1918 +			qglVertex3f(light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2]);
 86.1919 +
 86.1920 +			qglEnd();
 86.1921 +
 86.1922 +			GL_CheckErrors();
 86.1923 +		}
 86.1924 +	}
 86.1925 +}
 86.1926 +#endif
 86.1927 +// *INDENT-ON*
 86.1928 +
 86.1929 +/*
 86.1930 +=================
 86.1931 +RB_RenderInteractions
 86.1932 +=================
 86.1933 +*/
 86.1934 +static void RB_RenderInteractions()
 86.1935 +{
 86.1936 +	shader_t       *shader, *oldShader;
 86.1937 +	trRefEntity_t  *entity, *oldEntity;
 86.1938 +	trRefLight_t   *light, *oldLight;
 86.1939 +	interaction_t  *ia;
 86.1940 +	qboolean        depthRange, oldDepthRange;
 86.1941 +	int             iaCount;
 86.1942 +	surfaceType_t  *surface;
 86.1943 +	vec3_t          tmp;
 86.1944 +	matrix_t        modelToLight;
 86.1945 +	int             startTime = 0, endTime = 0;
 86.1946 +
 86.1947 +	GLimp_LogComment("--- RB_RenderInteractions ---\n");
 86.1948 +
 86.1949 +	if(r_speeds->integer == 9)
 86.1950 +	{
 86.1951 +		startTime = ri.Milliseconds();
 86.1952 +	}
 86.1953 +
 86.1954 +	// draw everything
 86.1955 +	oldLight = NULL;
 86.1956 +	oldEntity = NULL;
 86.1957 +	oldShader = NULL;
 86.1958 +	oldDepthRange = qfalse;
 86.1959 +	depthRange = qfalse;
 86.1960 +
 86.1961 +	// render interactions
 86.1962 +	for(iaCount = 0, ia = &backEnd.viewParms.interactions[0]; iaCount < backEnd.viewParms.numInteractions;)
 86.1963 +	{
 86.1964 +		backEnd.currentLight = light = ia->light;
 86.1965 +		backEnd.currentEntity = entity = ia->entity;
 86.1966 +		surface = ia->surface;
 86.1967 +		shader = ia->surfaceShader;
 86.1968 +
 86.1969 +		if(glConfig.occlusionQueryBits && glConfig.driverType != GLDRV_MESA && !ia->occlusionQuerySamples)
 86.1970 +		{
 86.1971 +			// skip all interactions of this light because it failed the occlusion query
 86.1972 +			goto skipInteraction;
 86.1973 +		}
 86.1974 +
 86.1975 +		if(!shader->interactLight)
 86.1976 +		{
 86.1977 +			// skip this interaction because the surface shader has no ability to interact with light
 86.1978 +			// this will save texcoords and matrix calculations
 86.1979 +			goto skipInteraction;
 86.1980 +		}
 86.1981 +
 86.1982 +		if(ia->type == IA_SHADOWONLY)
 86.1983 +		{
 86.1984 +			// skip this interaction because the interaction is meant for shadowing only
 86.1985 +			goto skipInteraction;
 86.1986 +		}
 86.1987 +
 86.1988 +		if(light != oldLight)
 86.1989 +		{
 86.1990 +			GLimp_LogComment("----- Rendering new light -----\n");
 86.1991 +
 86.1992 +			// set light scissor to reduce fillrate
 86.1993 +			GL_Scissor(ia->scissorX, ia->scissorY, ia->scissorWidth, ia->scissorHeight);
 86.1994 +		}
 86.1995 +
 86.1996 +		// Tr3B: this should never happen in the first iteration
 86.1997 +		if(light == oldLight && entity == oldEntity && shader == oldShader)
 86.1998 +		{
 86.1999 +			// fast path, same as previous
 86.2000 +			rb_surfaceTable[*surface] (surface);
 86.2001 +			goto nextInteraction;
 86.2002 +		}
 86.2003 +
 86.2004 +		// draw the contents of the last shader batch
 86.2005 +		Tess_End();
 86.2006 +
 86.2007 +		// begin a new batch
 86.2008 +		Tess_Begin(Tess_StageIteratorLighting, shader, light->shader, qfalse, qfalse, -1);
 86.2009 +
 86.2010 +		// change the modelview matrix if needed
 86.2011 +		if(entity != oldEntity)
 86.2012 +		{
 86.2013 +			depthRange = qfalse;
 86.2014 +
 86.2015 +			if(entity != &tr.worldEntity)
 86.2016 +			{
 86.2017 +				// set up the transformation matrix
 86.2018 +				R_RotateEntityForViewParms(backEnd.currentEntity, &backEnd.viewParms, &backEnd.orientation);
 86.2019 +
 86.2020 +				if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK)
 86.2021 +				{
 86.2022 +					// hack the depth range to prevent view model from poking into walls
 86.2023 +					depthRange = qtrue;
 86.2024 +				}
 86.2025 +			}
 86.2026 +			else
 86.2027 +			{
 86.2028 +				backEnd.orientation = backEnd.viewParms.world;
 86.2029 +			}
 86.2030 +
 86.2031 +			GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.2032 +
 86.2033 +			// change depthrange if needed
 86.2034 +			if(oldDepthRange != depthRange)
 86.2035 +			{
 86.2036 +				if(depthRange)
 86.2037 +				{
 86.2038 +					qglDepthRange(0, 0.3);
 86.2039 +				}
 86.2040 +				else
 86.2041 +				{
 86.2042 +					qglDepthRange(0, 1);
 86.2043 +				}
 86.2044 +				oldDepthRange = depthRange;
 86.2045 +			}
 86.2046 +		}
 86.2047 +
 86.2048 +		// change the attenuation matrix if needed
 86.2049 +		if(light != oldLight || entity != oldEntity)
 86.2050 +		{
 86.2051 +			// transform light origin into model space for u_LightOrigin parameter
 86.2052 +			if(entity != &tr.worldEntity)
 86.2053 +			{
 86.2054 +				VectorSubtract(light->origin, backEnd.orientation.origin, tmp);
 86.2055 +				light->transformed[0] = DotProduct(tmp, backEnd.orientation.axis[0]);
 86.2056 +				light->transformed[1] = DotProduct(tmp, backEnd.orientation.axis[1]);
 86.2057 +				light->transformed[2] = DotProduct(tmp, backEnd.orientation.axis[2]);
 86.2058 +			}
 86.2059 +			else
 86.2060 +			{
 86.2061 +				VectorCopy(light->origin, light->transformed);
 86.2062 +			}
 86.2063 +
 86.2064 +			// build the attenuation matrix using the entity transform
 86.2065 +			MatrixMultiply(light->viewMatrix, backEnd.orientation.transformMatrix, modelToLight);
 86.2066 +
 86.2067 +			switch (light->l.rlType)
 86.2068 +			{
 86.2069 +				case RL_PROJ:
 86.2070 +				{
 86.2071 +					MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.0);	// bias
 86.2072 +					MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 1.0 / Q_min(light->l.distFar - light->l.distNear, 1.0));	// scale
 86.2073 +					break;
 86.2074 +				}
 86.2075 +
 86.2076 +				case RL_OMNI:
 86.2077 +				default:
 86.2078 +				{
 86.2079 +					MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.5);	// bias
 86.2080 +					MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 0.5);	// scale
 86.2081 +					break;
 86.2082 +				}
 86.2083 +			}
 86.2084 +			MatrixMultiply2(light->attenuationMatrix, light->projectionMatrix);	// light projection (frustum)
 86.2085 +			MatrixMultiply2(light->attenuationMatrix, modelToLight);
 86.2086 +		}
 86.2087 +
 86.2088 +		// add the triangles for this surface
 86.2089 +		rb_surfaceTable[*surface] (surface);
 86.2090 +
 86.2091 +	  nextInteraction:
 86.2092 +
 86.2093 +		// remember values
 86.2094 +		oldLight = light;
 86.2095 +		oldEntity = entity;
 86.2096 +		oldShader = shader;
 86.2097 +
 86.2098 +	  skipInteraction:
 86.2099 +		if(!ia->next)
 86.2100 +		{
 86.2101 +			// draw the contents of the last shader batch
 86.2102 +			Tess_End();
 86.2103 +
 86.2104 +#ifdef VOLUMETRIC_LIGHTING
 86.2105 +			// draw the light volume if needed
 86.2106 +			if(light->shader->volumetricLight)
 86.2107 +			{
 86.2108 +				Render_lightVolume(light);
 86.2109 +			}
 86.2110 +#endif
 86.2111 +
 86.2112 +			if(iaCount < (backEnd.viewParms.numInteractions - 1))
 86.2113 +			{
 86.2114 +				// jump to next interaction and continue
 86.2115 +				ia++;
 86.2116 +				iaCount++;
 86.2117 +			}
 86.2118 +			else
 86.2119 +			{
 86.2120 +				// increase last time to leave for loop
 86.2121 +				iaCount++;
 86.2122 +			}
 86.2123 +
 86.2124 +			// force updates
 86.2125 +			oldLight = NULL;
 86.2126 +			oldEntity = NULL;
 86.2127 +			oldShader = NULL;
 86.2128 +		}
 86.2129 +		else
 86.2130 +		{
 86.2131 +			// just continue
 86.2132 +			ia = ia->next;
 86.2133 +			iaCount++;
 86.2134 +		}
 86.2135 +	}
 86.2136 +
 86.2137 +	// go back to the world modelview matrix
 86.2138 +	GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.2139 +	if(depthRange)
 86.2140 +	{
 86.2141 +		qglDepthRange(0, 1);
 86.2142 +	}
 86.2143 +
 86.2144 +	// reset scissor
 86.2145 +	GL_Scissor(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
 86.2146 +			   backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
 86.2147 +
 86.2148 +	GL_CheckErrors();
 86.2149 +
 86.2150 +	if(r_speeds->integer == 9)
 86.2151 +	{
 86.2152 +		qglFinish();
 86.2153 +		endTime = ri.Milliseconds();
 86.2154 +		backEnd.pc.c_forwardLightingTime = endTime - startTime;
 86.2155 +	}
 86.2156 +}
 86.2157 +
 86.2158 +
 86.2159 +/*
 86.2160 +=================
 86.2161 +RB_RenderInteractionsStencilShadowed
 86.2162 +=================
 86.2163 +*/
 86.2164 +static void RB_RenderInteractionsStencilShadowed()
 86.2165 +{
 86.2166 +	shader_t       *shader, *oldShader;
 86.2167 +	trRefEntity_t  *entity, *oldEntity;
 86.2168 +	trRefLight_t   *light, *oldLight;
 86.2169 +	interaction_t  *ia;
 86.2170 +	int             iaCount;
 86.2171 +	int             iaFirst;
 86.2172 +	surfaceType_t  *surface;
 86.2173 +	qboolean        depthRange, oldDepthRange;
 86.2174 +	vec3_t          tmp;
 86.2175 +	matrix_t        modelToLight;
 86.2176 +	qboolean        drawShadows;
 86.2177 +	int             startTime = 0, endTime = 0;
 86.2178 +
 86.2179 +	if(glConfig.stencilBits < 4)
 86.2180 +	{
 86.2181 +		RB_RenderInteractions();
 86.2182 +		return;
 86.2183 +	}
 86.2184 +
 86.2185 +	GLimp_LogComment("--- RB_RenderInteractionsStencilShadowed ---\n");
 86.2186 +
 86.2187 +	if(r_speeds->integer == 9)
 86.2188 +	{
 86.2189 +		startTime = ri.Milliseconds();
 86.2190 +	}
 86.2191 +
 86.2192 +	// draw everything
 86.2193 +	oldLight = NULL;
 86.2194 +	oldEntity = NULL;
 86.2195 +	oldShader = NULL;
 86.2196 +	oldDepthRange = qfalse;
 86.2197 +	depthRange = qfalse;
 86.2198 +	drawShadows = qtrue;
 86.2199 +
 86.2200 +	/*
 86.2201 +	   if(qglActiveStencilFaceEXT)
 86.2202 +	   {
 86.2203 +	   qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
 86.2204 +	   }
 86.2205 +	 */
 86.2206 +
 86.2207 +	// render interactions
 86.2208 +	for(iaCount = 0, iaFirst = 0, ia = &backEnd.viewParms.interactions[0]; iaCount < backEnd.viewParms.numInteractions;)
 86.2209 +	{
 86.2210 +		backEnd.currentLight = light = ia->light;
 86.2211 +		backEnd.currentEntity = entity = ia->entity;
 86.2212 +		surface = ia->surface;
 86.2213 +		shader = ia->surfaceShader;
 86.2214 +
 86.2215 +		if(glConfig.occlusionQueryBits && glConfig.driverType != GLDRV_MESA && !ia->occlusionQuerySamples)
 86.2216 +		{
 86.2217 +			// skip all interactions of this light because it failed the occlusion query
 86.2218 +			goto skipInteraction;
 86.2219 +		}
 86.2220 +
 86.2221 +		// only iaCount == iaFirst if first iteration or counters were reset
 86.2222 +		if(iaCount == iaFirst)
 86.2223 +		{
 86.2224 +			if(r_logFile->integer)
 86.2225 +			{
 86.2226 +				// don't just call LogComment, or we will get
 86.2227 +				// a call to va() every frame!
 86.2228 +				GLimp_LogComment(va("----- First Interaction: %i -----\n", iaCount));
 86.2229 +			}
 86.2230 +
 86.2231 +			if(drawShadows)
 86.2232 +			{
 86.2233 +				// set light scissor to reduce fillrate
 86.2234 +				GL_Scissor(ia->scissorX, ia->scissorY, ia->scissorWidth, ia->scissorHeight);
 86.2235 +
 86.2236 +				// set depth test to reduce fillrate
 86.2237 +				if(qglDepthBoundsEXT)
 86.2238 +				{
 86.2239 +					if(!ia->noDepthBoundsTest)
 86.2240  					{
 86.2241 -						if(isCrosshair)
 86.2242 +						qglEnable(GL_DEPTH_BOUNDS_TEST_EXT);
 86.2243 +						qglDepthBoundsEXT(ia->depthNear, ia->depthFar);
 86.2244 +					}
 86.2245 +					else
 86.2246 +					{
 86.2247 +						qglDisable(GL_DEPTH_BOUNDS_TEST_EXT);
 86.2248 +					}
 86.2249 +				}
 86.2250 +
 86.2251 +				if(!light->l.noShadows)
 86.2252 +				{
 86.2253 +					GLimp_LogComment("--- Rendering shadow volumes ---\n");
 86.2254 +
 86.2255 +					// set the reference stencil value
 86.2256 +					GL_ClearStencil(128);
 86.2257 +
 86.2258 +					// reset stencil buffer
 86.2259 +					qglClear(GL_STENCIL_BUFFER_BIT);
 86.2260 +
 86.2261 +					// use less compare as depthfunc
 86.2262 +					// don't write to the color buffer or depth buffer
 86.2263 +					// enable stencil testing for this light
 86.2264 +					GL_State(GLS_DEPTHFUNC_LESS | GLS_COLORMASK_BITS | GLS_STENCILTEST_ENABLE);
 86.2265 +
 86.2266 +					qglStencilFunc(GL_ALWAYS, 128, 255);
 86.2267 +					qglStencilMask(255);
 86.2268 +
 86.2269 +					qglEnable(GL_POLYGON_OFFSET_FILL);
 86.2270 +					qglPolygonOffset(r_shadowOffsetFactor->value, r_shadowOffsetUnits->value);
 86.2271 +
 86.2272 +					// enable shadow volume extrusion shader
 86.2273 +					GL_BindProgram(&tr.shadowExtrudeShader);
 86.2274 +				}
 86.2275 +			}
 86.2276 +			else
 86.2277 +			{
 86.2278 +				GLimp_LogComment("--- Rendering lighting ---\n");
 86.2279 +
 86.2280 +				if(!light->l.noShadows)
 86.2281 +				{
 86.2282 +					qglStencilFunc(GL_EQUAL, 128, 255);
 86.2283 +				}
 86.2284 +				else
 86.2285 +				{
 86.2286 +					// don't consider shadow volumes
 86.2287 +					qglStencilFunc(GL_ALWAYS, 128, 255);
 86.2288 +				}
 86.2289 +
 86.2290 +				/*
 86.2291 +				   if(qglActiveStencilFaceEXT)
 86.2292 +				   {
 86.2293 +				   qglActiveStencilFaceEXT(GL_BACK);
 86.2294 +				   qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
 86.2295 +
 86.2296 +				   qglActiveStencilFaceEXT(GL_FRONT);
 86.2297 +				   qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
 86.2298 +				   }
 86.2299 +				   else
 86.2300 +				 */
 86.2301 +				{
 86.2302 +					qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
 86.2303 +				}
 86.2304 +
 86.2305 +				//qglDisable(GL_POLYGON_OFFSET_FILL);
 86.2306 +
 86.2307 +				// disable shadow volume extrusion shader
 86.2308 +				GL_BindProgram(NULL);
 86.2309 +			}
 86.2310 +		}
 86.2311 +
 86.2312 +		if(drawShadows)
 86.2313 +		{
 86.2314 +			if(entity->e.renderfx & (RF_NOSHADOW | RF_DEPTHHACK))
 86.2315 +			{
 86.2316 +				goto skipInteraction;
 86.2317 +			}
 86.2318 +
 86.2319 +			if(shader->sort > SS_OPAQUE)
 86.2320 +			{
 86.2321 +				goto skipInteraction;
 86.2322 +			}
 86.2323 +
 86.2324 +			if(shader->noShadows || light->l.noShadows)
 86.2325 +			{
 86.2326 +				goto skipInteraction;
 86.2327 +			}
 86.2328 +
 86.2329 +			if(ia->type == IA_LIGHTONLY)
 86.2330 +			{
 86.2331 +				goto skipInteraction;
 86.2332 +			}
 86.2333 +
 86.2334 +			if(light == oldLight && entity == oldEntity)
 86.2335 +			{
 86.2336 +				if(r_logFile->integer)
 86.2337 +				{
 86.2338 +					// don't just call LogComment, or we will get
 86.2339 +					// a call to va() every frame!
 86.2340 +					GLimp_LogComment(va("----- Batching Shadow Interaction: %i -----\n", iaCount));
 86.2341 +				}
 86.2342 +
 86.2343 +				// fast path, same as previous
 86.2344 +				rb_surfaceTable[*surface] (surface);
 86.2345 +				goto nextInteraction;
 86.2346 +			}
 86.2347 +			else
 86.2348 +			{
 86.2349 +				if(oldLight)
 86.2350 +				{
 86.2351 +					// draw the contents of the last shader batch
 86.2352 +					Tess_End();
 86.2353 +				}
 86.2354 +
 86.2355 +				if(r_logFile->integer)
 86.2356 +				{
 86.2357 +					// don't just call LogComment, or we will get
 86.2358 +					// a call to va() every frame!
 86.2359 +					GLimp_LogComment(va("----- Beginning Shadow Interaction: %i -----\n", iaCount));
 86.2360 +				}
 86.2361 +
 86.2362 +				// we don't need tangent space calculations here
 86.2363 +				Tess_Begin(Tess_StageIteratorStencilShadowVolume, shader, light->shader, qtrue, qtrue, -1);
 86.2364 +			}
 86.2365 +		}
 86.2366 +		else
 86.2367 +		{
 86.2368 +			if(!shader->interactLight)
 86.2369 +			{
 86.2370 +				goto skipInteraction;
 86.2371 +			}
 86.2372 +
 86.2373 +			if(ia->type == IA_SHADOWONLY)
 86.2374 +			{
 86.2375 +				goto skipInteraction;
 86.2376 +			}
 86.2377 +
 86.2378 +			if(light == oldLight && entity == oldEntity && shader == oldShader)
 86.2379 +			{
 86.2380 +				if(r_logFile->integer)
 86.2381 +				{
 86.2382 +					// don't just call LogComment, or we will get
 86.2383 +					// a call to va() every frame!
 86.2384 +					GLimp_LogComment(va("----- Batching Light Interaction: %i -----\n", iaCount));
 86.2385 +				}
 86.2386 +
 86.2387 +				// fast path, same as previous
 86.2388 +				rb_surfaceTable[*surface] (surface);
 86.2389 +				goto nextInteraction;
 86.2390 +			}
 86.2391 +			else
 86.2392 +			{
 86.2393 +				if(oldLight)
 86.2394 +				{
 86.2395 +					// draw the contents of the last shader batch
 86.2396 +					Tess_End();
 86.2397 +				}
 86.2398 +
 86.2399 +				if(r_logFile->integer)
 86.2400 +				{
 86.2401 +					// don't just call LogComment, or we will get
 86.2402 +					// a call to va() every frame!
 86.2403 +					GLimp_LogComment(va("----- Beginning Light Interaction: %i -----\n", iaCount));
 86.2404 +				}
 86.2405 +
 86.2406 +				// begin a new batch
 86.2407 +				Tess_Begin(Tess_StageIteratorStencilLighting, shader, light->shader, qfalse, qfalse, -1);
 86.2408 +			}
 86.2409 +		}
 86.2410 +
 86.2411 +		// change the modelview matrix if needed
 86.2412 +		if(entity != oldEntity)
 86.2413 +		{
 86.2414 +			depthRange = qfalse;
 86.2415 +
 86.2416 +			if(entity != &tr.worldEntity)
 86.2417 +			{
 86.2418 +				// set up the transformation matrix
 86.2419 +				R_RotateEntityForViewParms(backEnd.currentEntity, &backEnd.viewParms, &backEnd.orientation);
 86.2420 +
 86.2421 +				if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK)
 86.2422 +				{
 86.2423 +					// hack the depth range to prevent view model from poking into walls
 86.2424 +					depthRange = qtrue;
 86.2425 +				}
 86.2426 +			}
 86.2427 +			else
 86.2428 +			{
 86.2429 +				backEnd.orientation = backEnd.viewParms.world;
 86.2430 +			}
 86.2431 +
 86.2432 +			GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.2433 +
 86.2434 +			if(drawShadows && !light->l.noShadows)
 86.2435 +			{
 86.2436 +				GLSL_SetUniform_ModelViewProjectionMatrix(&tr.shadowExtrudeShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.2437 +			}
 86.2438 +
 86.2439 +			// change depthrange if needed
 86.2440 +			if(oldDepthRange != depthRange)
 86.2441 +			{
 86.2442 +				if(depthRange)
 86.2443 +				{
 86.2444 +					qglDepthRange(0, 0.3);
 86.2445 +				}
 86.2446 +				else
 86.2447 +				{
 86.2448 +					qglDepthRange(0, 1);
 86.2449 +				}
 86.2450 +				oldDepthRange = depthRange;
 86.2451 +			}
 86.2452 +		}
 86.2453 +
 86.2454 +		// change the attenuation matrix if needed
 86.2455 +		if(light != oldLight || entity != oldEntity)
 86.2456 +		{
 86.2457 +			// transform light origin into model space for u_LightOrigin parameter
 86.2458 +			if(entity != &tr.worldEntity)
 86.2459 +			{
 86.2460 +				VectorSubtract(light->origin, backEnd.orientation.origin, tmp);
 86.2461 +				light->transformed[0] = DotProduct(tmp, backEnd.orientation.axis[0]);
 86.2462 +				light->transformed[1] = DotProduct(tmp, backEnd.orientation.axis[1]);
 86.2463 +				light->transformed[2] = DotProduct(tmp, backEnd.orientation.axis[2]);
 86.2464 +			}
 86.2465 +			else
 86.2466 +			{
 86.2467 +				VectorCopy(light->origin, light->transformed);
 86.2468 +			}
 86.2469 +
 86.2470 +			if(drawShadows && !light->l.noShadows)
 86.2471 +			{
 86.2472 +				// set uniform parameter u_LightOrigin for GLSL shader
 86.2473 +				GLSL_SetUniform_LightOrigin(&tr.shadowExtrudeShader, light->transformed);
 86.2474 +			}
 86.2475 +
 86.2476 +			// build the attenuation matrix using the entity transform
 86.2477 +			MatrixMultiply(light->viewMatrix, backEnd.orientation.transformMatrix, modelToLight);
 86.2478 +
 86.2479 +			switch (light->l.rlType)
 86.2480 +			{
 86.2481 +				case RL_PROJ:
 86.2482 +				{
 86.2483 +					MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.0);	// bias
 86.2484 +					MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 1.0 / Q_min(light->l.distFar - light->l.distNear, 1.0));	// scale
 86.2485 +					break;
 86.2486 +				}
 86.2487 +
 86.2488 +				case RL_OMNI:
 86.2489 +				default:
 86.2490 +				{
 86.2491 +					MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.5);	// bias
 86.2492 +					MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 0.5);	// scale
 86.2493 +					break;
 86.2494 +				}
 86.2495 +			}
 86.2496 +			MatrixMultiply2(light->attenuationMatrix, light->projectionMatrix);	// light projection (frustum)
 86.2497 +			MatrixMultiply2(light->attenuationMatrix, modelToLight);
 86.2498 +		}
 86.2499 +
 86.2500 +		if(drawShadows)
 86.2501 +		{
 86.2502 +			// add the triangles for this surface
 86.2503 +			rb_surfaceTable[*surface] (surface);
 86.2504 +		}
 86.2505 +		else
 86.2506 +		{
 86.2507 +			// add the triangles for this surface
 86.2508 +			rb_surfaceTable[*surface] (surface);
 86.2509 +		}
 86.2510 +
 86.2511 +	  nextInteraction:
 86.2512 +
 86.2513 +		// remember values
 86.2514 +		oldLight = light;
 86.2515 +		oldEntity = entity;
 86.2516 +		oldShader = shader;
 86.2517 +
 86.2518 +	  skipInteraction:
 86.2519 +		if(!ia->next)
 86.2520 +		{
 86.2521 +			// if ia->next does not point to any other interaction then
 86.2522 +			// this is the last interaction of the current light
 86.2523 +
 86.2524 +			if(r_logFile->integer)
 86.2525 +			{
 86.2526 +				// don't just call LogComment, or we will get
 86.2527 +				// a call to va() every frame!
 86.2528 +				GLimp_LogComment(va("----- Last Interaction: %i -----\n", iaCount));
 86.2529 +			}
 86.2530 +
 86.2531 +			// draw the contents of the last shader batch
 86.2532 +			Tess_End();
 86.2533 +
 86.2534 +			if(drawShadows)
 86.2535 +			{
 86.2536 +				// jump back to first interaction of this light and start lighting
 86.2537 +				ia = &backEnd.viewParms.interactions[iaFirst];
 86.2538 +				iaCount = iaFirst;
 86.2539 +				drawShadows = qfalse;
 86.2540 +			}
 86.2541 +			else
 86.2542 +			{
 86.2543 +				if(iaCount < (backEnd.viewParms.numInteractions - 1))
 86.2544 +				{
 86.2545 +					// jump to next interaction and start shadowing
 86.2546 +					ia++;
 86.2547 +					iaCount++;
 86.2548 +					iaFirst = iaCount;
 86.2549 +					drawShadows = qtrue;
 86.2550 +				}
 86.2551 +				else
 86.2552 +				{
 86.2553 +					// increase last time to leave for loop
 86.2554 +					iaCount++;
 86.2555 +				}
 86.2556 +			}
 86.2557 +
 86.2558 +			// force updates
 86.2559 +			oldLight = NULL;
 86.2560 +			oldEntity = NULL;
 86.2561 +			oldShader = NULL;
 86.2562 +		}
 86.2563 +		else
 86.2564 +		{
 86.2565 +			// just continue
 86.2566 +			ia = ia->next;
 86.2567 +			iaCount++;
 86.2568 +		}
 86.2569 +	}
 86.2570 +
 86.2571 +	// go back to the world modelview matrix
 86.2572 +	GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.2573 +	if(depthRange)
 86.2574 +	{
 86.2575 +		qglDepthRange(0, 1);
 86.2576 +	}
 86.2577 +
 86.2578 +	// reset scissor clamping
 86.2579 +	GL_Scissor(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
 86.2580 +			   backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
 86.2581 +
 86.2582 +	// reset depth clamping
 86.2583 +	if(qglDepthBoundsEXT)
 86.2584 +	{
 86.2585 +		qglDisable(GL_DEPTH_BOUNDS_TEST_EXT);
 86.2586 +	}
 86.2587 +
 86.2588 +	/*
 86.2589 +	   if(qglActiveStencilFaceEXT)
 86.2590 +	   {
 86.2591 +	   qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
 86.2592 +	   }
 86.2593 +	 */
 86.2594 +
 86.2595 +	GL_CheckErrors();
 86.2596 +
 86.2597 +	if(r_speeds->integer == 9)
 86.2598 +	{
 86.2599 +		qglFinish();
 86.2600 +		endTime = ri.Milliseconds();
 86.2601 +		backEnd.pc.c_forwardLightingTime = endTime - startTime;
 86.2602 +	}
 86.2603 +}
 86.2604 +
 86.2605 +/*
 86.2606 +=================
 86.2607 +RB_RenderInteractionsShadowMapped
 86.2608 +=================
 86.2609 +*/
 86.2610 +static void RB_RenderInteractionsShadowMapped()
 86.2611 +{
 86.2612 +	shader_t       *shader, *oldShader;
 86.2613 +	trRefEntity_t  *entity, *oldEntity;
 86.2614 +	trRefLight_t   *light, *oldLight;
 86.2615 +	interaction_t  *ia;
 86.2616 +	int             iaCount;
 86.2617 +	int             iaFirst;
 86.2618 +	surfaceType_t  *surface;
 86.2619 +	qboolean        depthRange, oldDepthRange;
 86.2620 +	qboolean        alphaTest, oldAlphaTest;
 86.2621 +	vec3_t          tmp;
 86.2622 +	matrix_t        modelToLight;
 86.2623 +	qboolean        drawShadows;
 86.2624 +	int             cubeSide;
 86.2625 +	int             startTime = 0, endTime = 0;
 86.2626 +
 86.2627 +	if(!glConfig.framebufferObjectAvailable || !glConfig.textureFloatAvailable)
 86.2628 +	{
 86.2629 +		RB_RenderInteractions();
 86.2630 +		return;
 86.2631 +	}
 86.2632 +
 86.2633 +	GLimp_LogComment("--- RB_RenderInteractionsShadowMapped ---\n");
 86.2634 +
 86.2635 +	if(r_speeds->integer == 9)
 86.2636 +	{
 86.2637 +		startTime = ri.Milliseconds();
 86.2638 +	}
 86.2639 +
 86.2640 +	// draw everything
 86.2641 +	oldLight = NULL;
 86.2642 +	oldEntity = NULL;
 86.2643 +	oldShader = NULL;
 86.2644 +	oldDepthRange = depthRange = qfalse;
 86.2645 +	oldAlphaTest = alphaTest = qfalse;
 86.2646 +	drawShadows = qtrue;
 86.2647 +	cubeSide = 0;
 86.2648 +
 86.2649 +	// if we need to clear the FBO color buffers then it should be white
 86.2650 +	GL_ClearColor(1.0f, 1.0f, 1.0f, 1.0f);
 86.2651 +
 86.2652 +	// render interactions
 86.2653 +	for(iaCount = 0, iaFirst = 0, ia = &backEnd.viewParms.interactions[0]; iaCount < backEnd.viewParms.numInteractions;)
 86.2654 +	{
 86.2655 +		backEnd.currentLight = light = ia->light;
 86.2656 +		backEnd.currentEntity = entity = ia->entity;
 86.2657 +		surface = ia->surface;
 86.2658 +		shader = ia->surfaceShader;
 86.2659 +		alphaTest = shader->alphaTest;
 86.2660 +
 86.2661 +		if(glConfig.occlusionQueryBits && glConfig.driverType != GLDRV_MESA && !ia->occlusionQuerySamples)
 86.2662 +		{
 86.2663 +			// skip all interactions of this light because it failed the occlusion query
 86.2664 +			goto skipInteraction;
 86.2665 +		}
 86.2666 +
 86.2667 +		if(light->l.inverseShadows)
 86.2668 +		{
 86.2669 +			// handle those lights in RB_RenderInteractionsDeferredInverseShadows
 86.2670 +			goto skipInteraction;
 86.2671 +		}
 86.2672 +
 86.2673 +		// only iaCount == iaFirst if first iteration or counters were reset
 86.2674 +		if(iaCount == iaFirst)
 86.2675 +		{
 86.2676 +			if(drawShadows)
 86.2677 +			{
 86.2678 +				// HACK: bring OpenGL into a safe state or strange FBO update problems will occur
 86.2679 +				GL_BindProgram(NULL);
 86.2680 +				GL_State(GLS_DEFAULT);
 86.2681 +				//GL_VertexAttribsState(ATTR_POSITION);
 86.2682 +
 86.2683 +				GL_SelectTexture(0);
 86.2684 +				GL_Bind(tr.whiteImage);
 86.2685 +
 86.2686 +				if(light->l.noShadows || light->shadowLOD < 0)
 86.2687 +				{
 86.2688 +					if(r_logFile->integer)
 86.2689 +					{
 86.2690 +						// don't just call LogComment, or we will get
 86.2691 +						// a call to va() every frame!
 86.2692 +						GLimp_LogComment(va("----- Skipping shadowCube side: %i -----\n", cubeSide));
 86.2693 +					}
 86.2694 +
 86.2695 +					goto skipInteraction;
 86.2696 +				}
 86.2697 +				else
 86.2698 +				{
 86.2699 +					R_BindFBO(tr.shadowMapFBO[light->shadowLOD]);
 86.2700 +
 86.2701 +					switch (light->l.rlType)
 86.2702 +					{
 86.2703 +						case RL_OMNI:
 86.2704  						{
 86.2705 -							if(oldDepthRange)
 86.2706 +							float           xMin, xMax, yMin, yMax;
 86.2707 +							float           width, height, depth;
 86.2708 +							float           zNear, zFar;
 86.2709 +							float           fovX, fovY;
 86.2710 +							qboolean        flipX, flipY;
 86.2711 +							float          *proj;
 86.2712 +							vec3_t          angles;
 86.2713 +							matrix_t        rotationMatrix, transformMatrix, viewMatrix;
 86.2714 +
 86.2715 +							if(r_logFile->integer)
 86.2716  							{
 86.2717 -								// was not a crosshair but now is, change back proj matrix
 86.2718 -								qglMatrixMode(GL_PROJECTION);
 86.2719 -								qglLoadMatrixf(backEnd.viewParms.projectionMatrix);
 86.2720 -								qglMatrixMode(GL_MODELVIEW);
 86.2721 +								// don't just call LogComment, or we will get
 86.2722 +								// a call to va() every frame!
 86.2723 +								GLimp_LogComment(va("----- Rendering shadowCube side: %i -----\n", cubeSide));
 86.2724 +							}
 86.2725 +							/*
 86.2726 +							   if(r_shadows->integer == 6)
 86.2727 +							   {
 86.2728 +							   R_AttachFBOTextureDepth(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + cubeSide,
 86.2729 +							   tr.shadowCubeFBOImage[light->shadowLOD]->texnum);
 86.2730 +							   }
 86.2731 +							   else
 86.2732 +							 */
 86.2733 +							{
 86.2734 +								R_AttachFBOTexture2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + cubeSide,
 86.2735 +													 tr.shadowCubeFBOImage[light->shadowLOD]->texnum, 0);
 86.2736 +							}
 86.2737 +							if(!r_ignoreGLErrors->integer)
 86.2738 +							{
 86.2739 +								R_CheckFBO(tr.shadowMapFBO[light->shadowLOD]);
 86.2740 +							}
 86.2741 +
 86.2742 +							// set the window clipping
 86.2743 +							GL_Viewport(0, 0, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.2744 +							GL_Scissor(0, 0, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.2745 +
 86.2746 +							qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 86.2747 +
 86.2748 +							switch (cubeSide)
 86.2749 +							{
 86.2750 +								case 0:
 86.2751 +								{
 86.2752 +									// view parameters
 86.2753 +									VectorSet(angles, 0, 0, 90);
 86.2754 +
 86.2755 +									// projection parameters
 86.2756 +									flipX = qfalse;
 86.2757 +									flipY = qfalse;
 86.2758 +									break;
 86.2759 +								}
 86.2760 +
 86.2761 +								case 1:
 86.2762 +								{
 86.2763 +									VectorSet(angles, 0, 180, 90);
 86.2764 +									flipX = qtrue;
 86.2765 +									flipY = qtrue;
 86.2766 +									break;
 86.2767 +								}
 86.2768 +
 86.2769 +								case 2:
 86.2770 +								{
 86.2771 +									VectorSet(angles, 0, 90, 0);
 86.2772 +									flipX = qfalse;
 86.2773 +									flipY = qfalse;
 86.2774 +									break;
 86.2775 +								}
 86.2776 +
 86.2777 +								case 3:
 86.2778 +								{
 86.2779 +									VectorSet(angles, 0, -90, 0);
 86.2780 +									flipX = qtrue;
 86.2781 +									flipY = qtrue;
 86.2782 +									break;
 86.2783 +								}
 86.2784 +
 86.2785 +								case 4:
 86.2786 +								{
 86.2787 +									VectorSet(angles, -90, 90, 0);
 86.2788 +									flipX = qfalse;
 86.2789 +									flipY = qfalse;
 86.2790 +									break;
 86.2791 +								}
 86.2792 +
 86.2793 +								case 5:
 86.2794 +								{
 86.2795 +									VectorSet(angles, 90, 90, 0);
 86.2796 +									flipX = qtrue;
 86.2797 +									flipY = qtrue;
 86.2798 +									break;
 86.2799 +								}
 86.2800 +
 86.2801 +								default:
 86.2802 +								{
 86.2803 +									// shut up compiler
 86.2804 +									VectorSet(angles, 0, 0, 0);
 86.2805 +									flipX = qfalse;
 86.2806 +									flipY = qfalse;
 86.2807 +									break;
 86.2808 +								}
 86.2809 +							}
 86.2810 +
 86.2811 +							// Quake -> OpenGL view matrix from light perspective
 86.2812 +							MatrixFromAngles(rotationMatrix, angles[PITCH], angles[YAW], angles[ROLL]);
 86.2813 +							MatrixSetupTransformFromRotation(transformMatrix, rotationMatrix, light->origin);
 86.2814 +							MatrixAffineInverse(transformMatrix, viewMatrix);
 86.2815 +
 86.2816 +							// convert from our coordinate system (looking down X)
 86.2817 +							// to OpenGL's coordinate system (looking down -Z)
 86.2818 +							MatrixMultiply(quakeToOpenGLMatrix, viewMatrix, light->viewMatrix);
 86.2819 +
 86.2820 +							// OpenGL projection matrix
 86.2821 +							fovX = 90;
 86.2822 +							fovY = 90;	//R_CalcFov(fovX, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.2823 +
 86.2824 +							zNear = 1.0;
 86.2825 +							zFar = light->sphereRadius;
 86.2826 +
 86.2827 +							if(!flipX)
 86.2828 +							{
 86.2829 +								xMax = zNear * tan(fovX * M_PI / 360.0f);
 86.2830 +								xMin = -xMax;
 86.2831 +							}
 86.2832 +							else
 86.2833 +							{
 86.2834 +								xMin = zNear * tan(fovX * M_PI / 360.0f);
 86.2835 +								xMax = -xMin;
 86.2836 +							}
 86.2837 +
 86.2838 +							if(!flipY)
 86.2839 +							{
 86.2840 +								yMax = zNear * tan(fovY * M_PI / 360.0f);
 86.2841 +								yMin = -yMax;
 86.2842 +							}
 86.2843 +							else
 86.2844 +							{
 86.2845 +								yMin = zNear * tan(fovY * M_PI / 360.0f);
 86.2846 +								yMax = -yMin;
 86.2847 +							}
 86.2848 +
 86.2849 +							width = xMax - xMin;
 86.2850 +							height = yMax - yMin;
 86.2851 +							depth = zFar - zNear;
 86.2852 +
 86.2853 +							proj = light->projectionMatrix;
 86.2854 +							proj[0] = (2 * zNear) / width;
 86.2855 +							proj[4] = 0;
 86.2856 +							proj[8] = (xMax + xMin) / width;
 86.2857 +							proj[12] = 0;
 86.2858 +							proj[1] = 0;
 86.2859 +							proj[5] = (2 * zNear) / height;
 86.2860 +							proj[9] = (yMax + yMin) / height;
 86.2861 +							proj[13] = 0;
 86.2862 +							proj[2] = 0;
 86.2863 +							proj[6] = 0;
 86.2864 +							proj[10] = -(zFar + zNear) / depth;
 86.2865 +							proj[14] = -(2 * zFar * zNear) / depth;
 86.2866 +							proj[3] = 0;
 86.2867 +							proj[7] = 0;
 86.2868 +							proj[11] = -1;
 86.2869 +							proj[15] = 0;
 86.2870 +
 86.2871 +							GL_LoadProjectionMatrix(light->projectionMatrix);
 86.2872 +							break;
 86.2873 +						}
 86.2874 +
 86.2875 +						case RL_PROJ:
 86.2876 +						{
 86.2877 +							float           xMin, xMax, yMin, yMax;
 86.2878 +							float           width, height, depth;
 86.2879 +							float           zNear, zFar;
 86.2880 +							float          *proj;
 86.2881 +
 86.2882 +							// TODO LiSPSM
 86.2883 +
 86.2884 +							zNear = light->l.distNear;
 86.2885 +							zFar = light->l.distFar;
 86.2886 +
 86.2887 +							xMax = zNear * tan(light->l.fovX * M_PI / 360.0f);
 86.2888 +							xMin = -xMax;
 86.2889 +
 86.2890 +
 86.2891 +							yMax = zNear * tan(light->l.fovY * M_PI / 360.0f);
 86.2892 +							yMin = -yMax;
 86.2893 +
 86.2894 +							width = xMax - xMin;
 86.2895 +							height = yMax - yMin;
 86.2896 +							depth = zFar - zNear;
 86.2897 +
 86.2898 +							// OpenGL projection matrix
 86.2899 +							proj = light->projectionMatrix;
 86.2900 +							proj[0] = (2 * zNear) / width;
 86.2901 +							proj[4] = 0;
 86.2902 +							proj[8] = (xMax + xMin) / width;
 86.2903 +							proj[12] = 0;
 86.2904 +							proj[1] = 0;
 86.2905 +							proj[5] = (2 * zNear) / height;
 86.2906 +							proj[9] = (yMax + yMin) / height;
 86.2907 +							proj[13] = 0;
 86.2908 +							proj[2] = 0;
 86.2909 +							proj[6] = 0;
 86.2910 +							proj[10] = -(zFar + zNear) / depth;
 86.2911 +							proj[14] = -(2 * zFar * zNear) / depth;
 86.2912 +							proj[3] = 0;
 86.2913 +							proj[7] = 0;
 86.2914 +							proj[11] = -1;
 86.2915 +							proj[15] = 0;
 86.2916 +
 86.2917 +							GLimp_LogComment("--- Rendering projective shadowMap ---\n");
 86.2918 +
 86.2919 +							/*
 86.2920 +							   if(r_shadows->integer == 6)
 86.2921 +							   {
 86.2922 +							   R_AttachFBOTextureDepth(tr.shadowMapFBOImage[light->shadowLOD]->texnum);
 86.2923 +							   }
 86.2924 +							   else
 86.2925 +							 */
 86.2926 +							{
 86.2927 +								R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.shadowMapFBOImage[light->shadowLOD]->texnum, 0);
 86.2928 +							}
 86.2929 +							if(!r_ignoreGLErrors->integer)
 86.2930 +							{
 86.2931 +								R_CheckFBO(tr.shadowMapFBO[light->shadowLOD]);
 86.2932 +							}
 86.2933 +
 86.2934 +							// set the window clipping
 86.2935 +							GL_Viewport(0, 0, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.2936 +							GL_Scissor(0, 0, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.2937 +
 86.2938 +							qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 86.2939 +
 86.2940 +							GL_LoadProjectionMatrix(light->projectionMatrix);
 86.2941 +							break;
 86.2942 +						}
 86.2943 +
 86.2944 +						default:
 86.2945 +							break;
 86.2946 +					}
 86.2947 +				}
 86.2948 +
 86.2949 +				if(r_logFile->integer)
 86.2950 +				{
 86.2951 +					// don't just call LogComment, or we will get
 86.2952 +					// a call to va() every frame!
 86.2953 +					GLimp_LogComment(va("----- First Shadow Interaction: %i -----\n", iaCount));
 86.2954 +				}
 86.2955 +			}
 86.2956 +			else
 86.2957 +			{
 86.2958 +				GLimp_LogComment("--- Rendering lighting ---\n");
 86.2959 +
 86.2960 +				if(r_logFile->integer)
 86.2961 +				{
 86.2962 +					// don't just call LogComment, or we will get
 86.2963 +					// a call to va() every frame!
 86.2964 +					GLimp_LogComment(va("----- First Light Interaction: %i -----\n", iaCount));
 86.2965 +				}
 86.2966 +
 86.2967 +				if(r_hdrRendering->integer)
 86.2968 +					R_BindFBO(tr.deferredRenderFBO);
 86.2969 +				else
 86.2970 +					R_BindNullFBO();
 86.2971 +
 86.2972 +				// set the window clipping
 86.2973 +				GL_Viewport(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
 86.2974 +							backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
 86.2975 +
 86.2976 +				GL_Scissor(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
 86.2977 +						   backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
 86.2978 +
 86.2979 +				// restore camera matrices
 86.2980 +				GL_LoadProjectionMatrix(backEnd.viewParms.projectionMatrix);
 86.2981 +				GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.2982 +
 86.2983 +				// reset light view and projection matrices
 86.2984 +				switch (light->l.rlType)
 86.2985 +				{
 86.2986 +					case RL_OMNI:
 86.2987 +					{
 86.2988 +						MatrixAffineInverse(light->transformMatrix, light->viewMatrix);
 86.2989 +						MatrixSetupScale(light->projectionMatrix, 1.0 / light->l.radius[0], 1.0 / light->l.radius[1],
 86.2990 +										 1.0 / light->l.radius[2]);
 86.2991 +						break;
 86.2992 +					}
 86.2993 +
 86.2994 +					default:
 86.2995 +						break;
 86.2996 +				}
 86.2997 +			}
 86.2998 +		}						// end if(iaCount == iaFirst)
 86.2999 +
 86.3000 +		if(drawShadows)
 86.3001 +		{
 86.3002 +			if(entity->e.renderfx & (RF_NOSHADOW | RF_DEPTHHACK))
 86.3003 +			{
 86.3004 +				goto skipInteraction;
 86.3005 +			}
 86.3006 +
 86.3007 +			if(shader->isSky)
 86.3008 +			{
 86.3009 +				goto skipInteraction;
 86.3010 +			}
 86.3011 +
 86.3012 +			if(shader->sort > SS_OPAQUE)
 86.3013 +			{
 86.3014 +				goto skipInteraction;
 86.3015 +			}
 86.3016 +
 86.3017 +			if(shader->noShadows || light->l.noShadows || light->shadowLOD < 0)
 86.3018 +			{
 86.3019 +				goto skipInteraction;
 86.3020 +			}
 86.3021 +
 86.3022 +			/*
 86.3023 +			   if(light->l.inverseShadows && (entity == &tr.worldEntity))
 86.3024 +			   {
 86.3025 +			   // this light only casts shadows by its player and their items
 86.3026 +			   goto skipInteraction;
 86.3027 +			   }
 86.3028 +			 */
 86.3029 +
 86.3030 +			if(ia->type == IA_LIGHTONLY)
 86.3031 +			{
 86.3032 +				goto skipInteraction;
 86.3033 +			}
 86.3034 +
 86.3035 +			if(light->l.rlType == RL_OMNI && !(ia->cubeSideBits & (1 << cubeSide)))
 86.3036 +			{
 86.3037 +				goto skipInteraction;
 86.3038 +			}
 86.3039 +
 86.3040 +			switch (light->l.rlType)
 86.3041 +			{
 86.3042 +				case RL_OMNI:
 86.3043 +				case RL_PROJ:
 86.3044 +				{
 86.3045 +					if(light == oldLight && entity == oldEntity && (alphaTest ? shader == oldShader : alphaTest == oldAlphaTest))
 86.3046 +					{
 86.3047 +						if(r_logFile->integer)
 86.3048 +						{
 86.3049 +							// don't just call LogComment, or we will get
 86.3050 +							// a call to va() every frame!
 86.3051 +							GLimp_LogComment(va("----- Batching Shadow Interaction: %i -----\n", iaCount));
 86.3052 +						}
 86.3053 +
 86.3054 +						// fast path, same as previous
 86.3055 +						rb_surfaceTable[*surface] (surface);
 86.3056 +						goto nextInteraction;
 86.3057 +					}
 86.3058 +					else
 86.3059 +					{
 86.3060 +						if(oldLight)
 86.3061 +						{
 86.3062 +							// draw the contents of the last shader batch
 86.3063 +							Tess_End();
 86.3064 +						}
 86.3065 +
 86.3066 +						if(r_logFile->integer)
 86.3067 +						{
 86.3068 +							// don't just call LogComment, or we will get
 86.3069 +							// a call to va() every frame!
 86.3070 +							GLimp_LogComment(va("----- Beginning Shadow Interaction: %i -----\n", iaCount));
 86.3071 +						}
 86.3072 +
 86.3073 +						// we don't need tangent space calculations here
 86.3074 +						Tess_Begin(Tess_StageIteratorShadowFill, shader, light->shader, qtrue, qfalse, -1);
 86.3075 +					}
 86.3076 +					break;
 86.3077 +				}
 86.3078 +
 86.3079 +				default:
 86.3080 +					break;
 86.3081 +			}
 86.3082 +		}
 86.3083 +		else
 86.3084 +		{
 86.3085 +			if(!shader->interactLight)
 86.3086 +			{
 86.3087 +				goto skipInteraction;
 86.3088 +			}
 86.3089 +
 86.3090 +			if(ia->type == IA_SHADOWONLY)
 86.3091 +			{
 86.3092 +				goto skipInteraction;
 86.3093 +			}
 86.3094 +
 86.3095 +			if(light == oldLight && entity == oldEntity && shader == oldShader)
 86.3096 +			{
 86.3097 +				if(r_logFile->integer)
 86.3098 +				{
 86.3099 +					// don't just call LogComment, or we will get
 86.3100 +					// a call to va() every frame!
 86.3101 +					GLimp_LogComment(va("----- Batching Light Interaction: %i -----\n", iaCount));
 86.3102 +				}
 86.3103 +
 86.3104 +				// fast path, same as previous
 86.3105 +				rb_surfaceTable[*surface] (surface);
 86.3106 +				goto nextInteraction;
 86.3107 +			}
 86.3108 +			else
 86.3109 +			{
 86.3110 +				if(oldLight)
 86.3111 +				{
 86.3112 +					// draw the contents of the last shader batch
 86.3113 +					Tess_End();
 86.3114 +				}
 86.3115 +
 86.3116 +				if(r_logFile->integer)
 86.3117 +				{
 86.3118 +					// don't just call LogComment, or we will get
 86.3119 +					// a call to va() every frame!
 86.3120 +					GLimp_LogComment(va("----- Beginning Light Interaction: %i -----\n", iaCount));
 86.3121 +				}
 86.3122 +
 86.3123 +				// begin a new batch
 86.3124 +				Tess_Begin(Tess_StageIteratorLighting, shader, light->shader, light->l.inverseShadows, qfalse, -1);
 86.3125 +			}
 86.3126 +		}
 86.3127 +
 86.3128 +		// change the modelview matrix if needed
 86.3129 +		if(entity != oldEntity)
 86.3130 +		{
 86.3131 +			depthRange = qfalse;
 86.3132 +
 86.3133 +			if(entity != &tr.worldEntity)
 86.3134 +			{
 86.3135 +				// set up the transformation matrix
 86.3136 +				if(drawShadows)
 86.3137 +				{
 86.3138 +					R_RotateEntityForLight(entity, light, &backEnd.orientation);
 86.3139 +				}
 86.3140 +				else
 86.3141 +				{
 86.3142 +					R_RotateEntityForViewParms(entity, &backEnd.viewParms, &backEnd.orientation);
 86.3143 +				}
 86.3144 +
 86.3145 +				if(entity->e.renderfx & RF_DEPTHHACK)
 86.3146 +				{
 86.3147 +					// hack the depth range to prevent view model from poking into walls
 86.3148 +					depthRange = qtrue;
 86.3149 +				}
 86.3150 +			}
 86.3151 +			else
 86.3152 +			{
 86.3153 +				// set up the transformation matrix
 86.3154 +				if(drawShadows)
 86.3155 +				{
 86.3156 +					Com_Memset(&backEnd.orientation, 0, sizeof(backEnd.orientation));
 86.3157 +
 86.3158 +					backEnd.orientation.axis[0][0] = 1;
 86.3159 +					backEnd.orientation.axis[1][1] = 1;
 86.3160 +					backEnd.orientation.axis[2][2] = 1;
 86.3161 +					VectorCopy(light->l.origin, backEnd.orientation.viewOrigin);
 86.3162 +
 86.3163 +					MatrixIdentity(backEnd.orientation.transformMatrix);
 86.3164 +					//MatrixAffineInverse(backEnd.orientation.transformMatrix, backEnd.orientation.viewMatrix);
 86.3165 +					MatrixMultiply(light->viewMatrix, backEnd.orientation.transformMatrix, backEnd.orientation.viewMatrix);
 86.3166 +					MatrixCopy(backEnd.orientation.viewMatrix, backEnd.orientation.modelViewMatrix);
 86.3167 +				}
 86.3168 +				else
 86.3169 +				{
 86.3170 +					// transform by the camera placement
 86.3171 +					backEnd.orientation = backEnd.viewParms.world;
 86.3172 +				}
 86.3173 +			}
 86.3174 +
 86.3175 +			GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.3176 +
 86.3177 +			// change depthrange if needed
 86.3178 +			if(oldDepthRange != depthRange)
 86.3179 +			{
 86.3180 +				if(depthRange)
 86.3181 +				{
 86.3182 +					qglDepthRange(0, 0.3);
 86.3183 +				}
 86.3184 +				else
 86.3185 +				{
 86.3186 +					qglDepthRange(0, 1);
 86.3187 +				}
 86.3188 +				oldDepthRange = depthRange;
 86.3189 +			}
 86.3190 +		}
 86.3191 +
 86.3192 +		// change the attenuation matrix if needed
 86.3193 +		if(light != oldLight || entity != oldEntity)
 86.3194 +		{
 86.3195 +			// transform light origin into model space for u_LightOrigin parameter
 86.3196 +			if(entity != &tr.worldEntity)
 86.3197 +			{
 86.3198 +				VectorSubtract(light->origin, backEnd.orientation.origin, tmp);
 86.3199 +				light->transformed[0] = DotProduct(tmp, backEnd.orientation.axis[0]);
 86.3200 +				light->transformed[1] = DotProduct(tmp, backEnd.orientation.axis[1]);
 86.3201 +				light->transformed[2] = DotProduct(tmp, backEnd.orientation.axis[2]);
 86.3202 +			}
 86.3203 +			else
 86.3204 +			{
 86.3205 +				VectorCopy(light->origin, light->transformed);
 86.3206 +			}
 86.3207 +
 86.3208 +			MatrixMultiply(light->viewMatrix, backEnd.orientation.transformMatrix, modelToLight);
 86.3209 +
 86.3210 +			// build the attenuation matrix using the entity transform
 86.3211 +			switch (light->l.rlType)
 86.3212 +			{
 86.3213 +				case RL_PROJ:
 86.3214 +				{
 86.3215 +					MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.0);	// bias
 86.3216 +					MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 1.0 / Q_min(light->l.distFar - light->l.distNear, 1.0));	// scale
 86.3217 +					break;
 86.3218 +				}
 86.3219 +
 86.3220 +				case RL_OMNI:
 86.3221 +				default:
 86.3222 +				{
 86.3223 +					MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.5);	// bias
 86.3224 +					MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 0.5);	// scale
 86.3225 +					break;
 86.3226 +				}
 86.3227 +			}
 86.3228 +			MatrixMultiply2(light->attenuationMatrix, light->projectionMatrix);
 86.3229 +			MatrixMultiply2(light->attenuationMatrix, modelToLight);
 86.3230 +		}
 86.3231 +
 86.3232 +		if(drawShadows)
 86.3233 +		{
 86.3234 +			switch (light->l.rlType)
 86.3235 +			{
 86.3236 +				case RL_OMNI:
 86.3237 +				case RL_PROJ:
 86.3238 +				{
 86.3239 +					// add the triangles for this surface
 86.3240 +					rb_surfaceTable[*surface] (surface);
 86.3241 +					break;
 86.3242 +				}
 86.3243 +
 86.3244 +				default:
 86.3245 +					break;
 86.3246 +			}
 86.3247 +		}
 86.3248 +		else
 86.3249 +		{
 86.3250 +			// add the triangles for this surface
 86.3251 +			rb_surfaceTable[*surface] (surface);
 86.3252 +		}
 86.3253 +
 86.3254 +	  nextInteraction:
 86.3255 +
 86.3256 +		// remember values
 86.3257 +		oldLight = light;
 86.3258 +		oldEntity = entity;
 86.3259 +		oldShader = shader;
 86.3260 +		oldAlphaTest = alphaTest;
 86.3261 +
 86.3262 +	  skipInteraction:
 86.3263 +		if(!ia->next)
 86.3264 +		{
 86.3265 +			// if ia->next does not point to any other interaction then
 86.3266 +			// this is the last interaction of the current light
 86.3267 +
 86.3268 +			if(r_logFile->integer)
 86.3269 +			{
 86.3270 +				// don't just call LogComment, or we will get
 86.3271 +				// a call to va() every frame!
 86.3272 +				GLimp_LogComment(va("----- Last Interaction: %i -----\n", iaCount));
 86.3273 +			}
 86.3274 +
 86.3275 +			// draw the contents of the last shader batch
 86.3276 +			Tess_End();
 86.3277 +
 86.3278 +			if(drawShadows)
 86.3279 +			{
 86.3280 +				switch (light->l.rlType)
 86.3281 +				{
 86.3282 +					case RL_OMNI:
 86.3283 +					{
 86.3284 +						if(cubeSide == 5)
 86.3285 +						{
 86.3286 +							cubeSide = 0;
 86.3287 +							drawShadows = qfalse;
 86.3288 +						}
 86.3289 +						else
 86.3290 +						{
 86.3291 +							cubeSide++;
 86.3292 +						}
 86.3293 +
 86.3294 +						// jump back to first interaction of this light
 86.3295 +						ia = &backEnd.viewParms.interactions[iaFirst];
 86.3296 +						iaCount = iaFirst;
 86.3297 +						break;
 86.3298 +					}
 86.3299 +
 86.3300 +					case RL_PROJ:
 86.3301 +					{
 86.3302 +						// jump back to first interaction of this light and start lighting
 86.3303 +						ia = &backEnd.viewParms.interactions[iaFirst];
 86.3304 +						iaCount = iaFirst;
 86.3305 +						drawShadows = qfalse;
 86.3306 +						break;
 86.3307 +					}
 86.3308 +
 86.3309 +					default:
 86.3310 +						break;
 86.3311 +				}
 86.3312 +			}
 86.3313 +			else
 86.3314 +			{
 86.3315 +#ifdef VOLUMETRIC_LIGHTING
 86.3316 +				// draw the light volume if needed
 86.3317 +				if(light->shader->volumetricLight)
 86.3318 +				{
 86.3319 +					Render_lightVolume(light);
 86.3320 +				}
 86.3321 +#endif
 86.3322 +
 86.3323 +				if(iaCount < (backEnd.viewParms.numInteractions - 1))
 86.3324 +				{
 86.3325 +					// jump to next interaction and start shadowing
 86.3326 +					ia++;
 86.3327 +					iaCount++;
 86.3328 +					iaFirst = iaCount;
 86.3329 +					drawShadows = qtrue;
 86.3330 +				}
 86.3331 +				else
 86.3332 +				{
 86.3333 +					// increase last time to leave for loop
 86.3334 +					iaCount++;
 86.3335 +				}
 86.3336 +			}
 86.3337 +
 86.3338 +			// force updates
 86.3339 +			oldLight = NULL;
 86.3340 +			oldEntity = NULL;
 86.3341 +			oldShader = NULL;
 86.3342 +		}
 86.3343 +		else
 86.3344 +		{
 86.3345 +			// just continue
 86.3346 +			ia = ia->next;
 86.3347 +			iaCount++;
 86.3348 +		}
 86.3349 +	}
 86.3350 +
 86.3351 +	// go back to the world modelview matrix
 86.3352 +	GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.3353 +	if(depthRange)
 86.3354 +	{
 86.3355 +		qglDepthRange(0, 1);
 86.3356 +	}
 86.3357 +
 86.3358 +	// reset scissor clamping
 86.3359 +	GL_Scissor(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
 86.3360 +			   backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
 86.3361 +
 86.3362 +	// reset clear color
 86.3363 +	GL_ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 86.3364 +
 86.3365 +	GL_CheckErrors();
 86.3366 +
 86.3367 +	if(r_speeds->integer == 9)
 86.3368 +	{
 86.3369 +		qglFinish();
 86.3370 +		endTime = ri.Milliseconds();
 86.3371 +		backEnd.pc.c_forwardLightingTime = endTime - startTime;
 86.3372 +	}
 86.3373 +}
 86.3374 +
 86.3375 +static void RB_RenderDrawSurfacesIntoGeometricBuffer()
 86.3376 +{
 86.3377 +	trRefEntity_t  *entity, *oldEntity;
 86.3378 +	shader_t       *shader, *oldShader;
 86.3379 +	int             lightmapNum, oldLightmapNum;
 86.3380 +	qboolean        depthRange, oldDepthRange;
 86.3381 +	int             i;
 86.3382 +	drawSurf_t     *drawSurf;
 86.3383 +	int             startTime = 0, endTime = 0;
 86.3384 +
 86.3385 +	GLimp_LogComment("--- RB_RenderDrawSurfacesIntoGeometricBuffer ---\n");
 86.3386 +
 86.3387 +	if(r_speeds->integer == 9)
 86.3388 +	{
 86.3389 +		startTime = ri.Milliseconds();
 86.3390 +	}
 86.3391 +
 86.3392 +	// draw everything
 86.3393 +	oldEntity = NULL;
 86.3394 +	oldShader = NULL;
 86.3395 +	oldLightmapNum = -1;
 86.3396 +	oldDepthRange = qfalse;
 86.3397 +	depthRange = qfalse;
 86.3398 +	backEnd.currentLight = NULL;
 86.3399 +
 86.3400 +	GL_CheckErrors();
 86.3401 +
 86.3402 +	for(i = 0, drawSurf = backEnd.viewParms.drawSurfs; i < backEnd.viewParms.numDrawSurfs; i++, drawSurf++)
 86.3403 +	{
 86.3404 +		// update locals
 86.3405 +		entity = drawSurf->entity;
 86.3406 +		shader = tr.sortedShaders[drawSurf->shaderNum];
 86.3407 +		lightmapNum = drawSurf->lightmapNum;
 86.3408 +
 86.3409 +		// skip all translucent surfaces that don't matter for this pass
 86.3410 +		if(shader->sort > SS_OPAQUE)
 86.3411 +		{
 86.3412 +			break;
 86.3413 +		}
 86.3414 +
 86.3415 +		if(entity == oldEntity && shader == oldShader && lightmapNum == oldLightmapNum)
 86.3416 +		{
 86.3417 +			// fast path, same as previous sort
 86.3418 +			rb_surfaceTable[*drawSurf->surface] (drawSurf->surface);
 86.3419 +			continue;
 86.3420 +		}
 86.3421 +
 86.3422 +		// change the tess parameters if needed
 86.3423 +		// a "entityMergable" shader is a shader that can have surfaces from seperate
 86.3424 +		// entities merged into a single batch, like smoke and blood puff sprites
 86.3425 +		if(shader != oldShader || (entity != oldEntity && !shader->entityMergable))
 86.3426 +		{
 86.3427 +			if(oldShader != NULL)
 86.3428 +			{
 86.3429 +				Tess_End();
 86.3430 +			}
 86.3431 +
 86.3432 +			Tess_Begin(Tess_StageIteratorGBuffer, shader, NULL, qfalse, qfalse, lightmapNum);
 86.3433 +			oldShader = shader;
 86.3434 +			oldLightmapNum = lightmapNum;
 86.3435 +		}
 86.3436 +
 86.3437 +		// change the modelview matrix if needed
 86.3438 +		if(entity != oldEntity)
 86.3439 +		{
 86.3440 +			depthRange = qfalse;
 86.3441 +
 86.3442 +			if(entity != &tr.worldEntity)
 86.3443 +			{
 86.3444 +				backEnd.currentEntity = entity;
 86.3445 +
 86.3446 +				// set up the transformation matrix
 86.3447 +				R_RotateEntityForViewParms(backEnd.currentEntity, &backEnd.viewParms, &backEnd.orientation);
 86.3448 +
 86.3449 +				if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK)
 86.3450 +				{
 86.3451 +					// hack the depth range to prevent view model from poking into walls
 86.3452 +					depthRange = qtrue;
 86.3453 +				}
 86.3454 +			}
 86.3455 +			else
 86.3456 +			{
 86.3457 +				backEnd.currentEntity = &tr.worldEntity;
 86.3458 +				backEnd.orientation = backEnd.viewParms.world;
 86.3459 +			}
 86.3460 +
 86.3461 +			GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.3462 +
 86.3463 +			// change depthrange if needed
 86.3464 +			if(oldDepthRange != depthRange)
 86.3465 +			{
 86.3466 +				if(depthRange)
 86.3467 +				{
 86.3468 +					qglDepthRange(0, 0.3);
 86.3469 +				}
 86.3470 +				else
 86.3471 +				{
 86.3472 +					qglDepthRange(0, 1);
 86.3473 +				}
 86.3474 +				oldDepthRange = depthRange;
 86.3475 +			}
 86.3476 +
 86.3477 +			oldEntity = entity;
 86.3478 +		}
 86.3479 +
 86.3480 +		// add the triangles for this surface
 86.3481 +		rb_surfaceTable[*drawSurf->surface] (drawSurf->surface);
 86.3482 +	}
 86.3483 +
 86.3484 +	// draw the contents of the last shader batch
 86.3485 +	if(oldShader != NULL)
 86.3486 +	{
 86.3487 +		Tess_End();
 86.3488 +	}
 86.3489 +
 86.3490 +	// go back to the world modelview matrix
 86.3491 +	GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.3492 +	if(depthRange)
 86.3493 +	{
 86.3494 +		qglDepthRange(0, 1);
 86.3495 +	}
 86.3496 +
 86.3497 +	// disable offscreen rendering
 86.3498 +	R_BindNullFBO();
 86.3499 +
 86.3500 +	GL_CheckErrors();
 86.3501 +
 86.3502 +	if(r_speeds->integer == 9)
 86.3503 +	{
 86.3504 +		qglFinish();
 86.3505 +		endTime = ri.Milliseconds();
 86.3506 +		backEnd.pc.c_deferredGBufferTime = endTime - startTime;
 86.3507 +	}
 86.3508 +}
 86.3509 +
 86.3510 +void RB_RenderInteractionsDeferred()
 86.3511 +{
 86.3512 +	interaction_t  *ia;
 86.3513 +	int             iaCount;
 86.3514 +	trRefLight_t   *light, *oldLight = NULL;
 86.3515 +	shader_t       *lightShader;
 86.3516 +	shaderStage_t  *attenuationXYStage;
 86.3517 +	shaderStage_t  *attenuationZStage;
 86.3518 +	int             i, j;
 86.3519 +	vec3_t          viewOrigin;
 86.3520 +	vec3_t          lightOrigin;
 86.3521 +	vec4_t          lightColor;
 86.3522 +	vec4_t          lightFrustum[6];
 86.3523 +	cplane_t       *frust;
 86.3524 +	matrix_t        ortho;
 86.3525 +	vec4_t          quadVerts[4];
 86.3526 +	int             startTime = 0, endTime = 0;
 86.3527 +
 86.3528 +	GLimp_LogComment("--- RB_RenderInteractionsDeferred ---\n");
 86.3529 +
 86.3530 +	if(r_speeds->integer == 9)
 86.3531 +	{
 86.3532 +		startTime = ri.Milliseconds();
 86.3533 +	}
 86.3534 +
 86.3535 +	R_BindFBO(tr.deferredRenderFBO);
 86.3536 +
 86.3537 +	// update uniforms
 86.3538 +	VectorCopy(backEnd.viewParms.orientation.origin, viewOrigin);
 86.3539 +
 86.3540 +	// set 2D virtual screen size
 86.3541 +	GL_PushMatrix();
 86.3542 +	MatrixSetupOrthogonalProjection(ortho, backEnd.viewParms.viewportX,
 86.3543 +									backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
 86.3544 +									backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
 86.3545 +									-99999, 99999);
 86.3546 +	GL_LoadProjectionMatrix(ortho);
 86.3547 +	GL_LoadModelViewMatrix(matrixIdentity);
 86.3548 +
 86.3549 +	// update depth render image
 86.3550 +	GL_SelectTexture(1);
 86.3551 +	GL_Bind(tr.depthRenderImage);
 86.3552 +	//qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.depthRenderImage->uploadWidth, tr.depthRenderImage->uploadHeight);
 86.3553 +
 86.3554 +	// loop trough all light interactions and render the light quad for each last interaction
 86.3555 +	for(iaCount = 0, ia = &backEnd.viewParms.interactions[0]; iaCount < backEnd.viewParms.numInteractions;)
 86.3556 +	{
 86.3557 +		backEnd.currentLight = light = ia->light;
 86.3558 +
 86.3559 +		if(glConfig.occlusionQueryBits && glConfig.driverType != GLDRV_MESA && !ia->occlusionQuerySamples)
 86.3560 +		{
 86.3561 +			// skip all interactions of this light because it failed the occlusion query
 86.3562 +			goto skipInteraction;
 86.3563 +		}
 86.3564 +
 86.3565 +		if(light != oldLight)
 86.3566 +		{
 86.3567 +			// set light scissor to reduce fillrate
 86.3568 +			GL_Scissor(ia->scissorX, ia->scissorY, ia->scissorWidth, ia->scissorHeight);
 86.3569 +
 86.3570 +			// build world to light space matrix
 86.3571 +			switch (light->l.rlType)
 86.3572 +			{
 86.3573 +				case RL_OMNI:
 86.3574 +				{
 86.3575 +					// build the attenuation matrix
 86.3576 +					MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.5);	// bias
 86.3577 +					MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 0.5);	// scale
 86.3578 +					MatrixMultiply2(light->attenuationMatrix, light->projectionMatrix);	// light projection (frustum)
 86.3579 +					MatrixMultiply2(light->attenuationMatrix, light->viewMatrix);
 86.3580 +					break;
 86.3581 +				}
 86.3582 +
 86.3583 +				case RL_PROJ:
 86.3584 +				{
 86.3585 +					// build the attenuation matrix
 86.3586 +					MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.0);	// bias
 86.3587 +					MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, Q_min(light->l.distFar - light->l.distNear, 1.0));	// scale
 86.3588 +					MatrixMultiply2(light->attenuationMatrix, light->projectionMatrix);
 86.3589 +					MatrixMultiply2(light->attenuationMatrix, light->viewMatrix);
 86.3590 +					break;
 86.3591 +				}
 86.3592 +
 86.3593 +				default:
 86.3594 +					break;
 86.3595 +			}
 86.3596 +
 86.3597 +			// copy frustum planes for pixel shader
 86.3598 +			for(i = 0; i < 6; i++)
 86.3599 +			{
 86.3600 +				frust = &light->frustum[i];
 86.3601 +
 86.3602 +				VectorCopy(frust->normal, lightFrustum[i]);
 86.3603 +				lightFrustum[i][3] = frust->dist;
 86.3604 +			}
 86.3605 +		}
 86.3606 +
 86.3607 +	  skipInteraction:
 86.3608 +		if(!ia->next)
 86.3609 +		{
 86.3610 +			if(glConfig.occlusionQueryBits && glConfig.driverType != GLDRV_MESA && ia->occlusionQuerySamples)
 86.3611 +			{
 86.3612 +				// last interaction of current light
 86.3613 +				lightShader = light->shader;
 86.3614 +				attenuationZStage = lightShader->stages[0];
 86.3615 +
 86.3616 +				for(j = 1; j < MAX_SHADER_STAGES; j++)
 86.3617 +				{
 86.3618 +					attenuationXYStage = lightShader->stages[j];
 86.3619 +
 86.3620 +					if(!attenuationXYStage)
 86.3621 +					{
 86.3622 +						break;
 86.3623 +					}
 86.3624 +
 86.3625 +					if(attenuationXYStage->type != ST_ATTENUATIONMAP_XY)
 86.3626 +					{
 86.3627 +						continue;
 86.3628 +					}
 86.3629 +
 86.3630 +					if(!RB_EvalExpression(&attenuationXYStage->ifExp, 1.0))
 86.3631 +					{
 86.3632 +						continue;
 86.3633 +					}
 86.3634 +
 86.3635 +					Tess_ComputeColor(attenuationXYStage);
 86.3636 +					R_ComputeFinalAttenuation(attenuationXYStage, light);
 86.3637 +
 86.3638 +					if(light->l.rlType == RL_OMNI)
 86.3639 +					{
 86.3640 +						// enable shader, set arrays
 86.3641 +						GL_BindProgram(&tr.deferredLightingShader_DBS_omni);
 86.3642 +
 86.3643 +						// set OpenGL state for additive lighting
 86.3644 +						GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHTEST_DISABLE);
 86.3645 +
 86.3646 +						GL_Cull(CT_TWO_SIDED);
 86.3647 +
 86.3648 +						// set uniforms
 86.3649 +						VectorCopy(light->origin, lightOrigin);
 86.3650 +						VectorCopy(tess.svars.color, lightColor);
 86.3651 +
 86.3652 +
 86.3653 +						GLSL_SetUniform_ViewOrigin(&tr.deferredLightingShader_DBS_omni, viewOrigin);
 86.3654 +						GLSL_SetUniform_LightOrigin(&tr.deferredLightingShader_DBS_omni, lightOrigin);
 86.3655 +						GLSL_SetUniform_LightColor(&tr.deferredLightingShader_DBS_omni, lightColor);
 86.3656 +						GLSL_SetUniform_LightRadius(&tr.deferredLightingShader_DBS_omni, light->sphereRadius);
 86.3657 +						GLSL_SetUniform_LightScale(&tr.deferredLightingShader_DBS_omni, light->l.scale);
 86.3658 +						GLSL_SetUniform_LightAttenuationMatrix(&tr.deferredLightingShader_DBS_omni, light->attenuationMatrix2);
 86.3659 +						qglUniform4fvARB(tr.deferredLightingShader_DBS_omni.u_LightFrustum, 6, &lightFrustum[0][0]);
 86.3660 +
 86.3661 +						GLSL_SetUniform_ModelViewProjectionMatrix(&tr.deferredLightingShader_DBS_omni, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.3662 +						GLSL_SetUniform_UnprojectMatrix(&tr.deferredLightingShader_DBS_omni, backEnd.viewParms.unprojectionMatrix);
 86.3663 +
 86.3664 +						GLSL_SetUniform_PortalClipping(&tr.deferredLightingShader_DBS_omni, backEnd.viewParms.isPortal);
 86.3665 +						if(backEnd.viewParms.isPortal)
 86.3666 +						{
 86.3667 +							float           plane[4];
 86.3668 +
 86.3669 +							// clipping plane in world space
 86.3670 +							plane[0] = backEnd.viewParms.portalPlane.normal[0];
 86.3671 +							plane[1] = backEnd.viewParms.portalPlane.normal[1];
 86.3672 +							plane[2] = backEnd.viewParms.portalPlane.normal[2];
 86.3673 +							plane[3] = backEnd.viewParms.portalPlane.dist;
 86.3674 +
 86.3675 +							GLSL_SetUniform_PortalPlane(&tr.deferredLightingShader_DBS_omni, plane);
 86.3676 +						}
 86.3677 +
 86.3678 +						// bind u_DiffuseMap
 86.3679 +						GL_SelectTexture(0);
 86.3680 +						GL_Bind(tr.deferredDiffuseFBOImage);
 86.3681 +
 86.3682 +						// bind u_NormalMap
 86.3683 +						GL_SelectTexture(1);
 86.3684 +						GL_Bind(tr.deferredNormalFBOImage);
 86.3685 +
 86.3686 +						if(r_normalMapping->integer)
 86.3687 +						{
 86.3688 +							// bind u_SpecularMap
 86.3689 +							GL_SelectTexture(2);
 86.3690 +							GL_Bind(tr.deferredSpecularFBOImage);
 86.3691 +						}
 86.3692 +
 86.3693 +						// bind u_DepthMap
 86.3694 +						GL_SelectTexture(3);
 86.3695 +						GL_Bind(tr.depthRenderImage);
 86.3696 +
 86.3697 +						// bind u_AttenuationMapXY
 86.3698 +						GL_SelectTexture(4);
 86.3699 +						BindAnimatedImage(&attenuationXYStage->bundle[TB_COLORMAP]);
 86.3700 +
 86.3701 +						// bind u_AttenuationMapZ
 86.3702 +						GL_SelectTexture(5);
 86.3703 +						BindAnimatedImage(&attenuationZStage->bundle[TB_COLORMAP]);
 86.3704 +
 86.3705 +						// draw lighting
 86.3706 +						VectorSet4(quadVerts[0], ia->scissorX, ia->scissorY, 0, 1);
 86.3707 +						VectorSet4(quadVerts[1], ia->scissorX + ia->scissorWidth - 1, ia->scissorY, 0, 1);
 86.3708 +						VectorSet4(quadVerts[2], ia->scissorX + ia->scissorWidth - 1, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.3709 +						VectorSet4(quadVerts[3], ia->scissorX, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.3710 +						Tess_InstantQuad(quadVerts);
 86.3711 +					}
 86.3712 +					else if(light->l.rlType == RL_PROJ)
 86.3713 +					{
 86.3714 +						// enable shader, set arrays
 86.3715 +						GL_BindProgram(&tr.deferredLightingShader_DBS_proj);
 86.3716 +
 86.3717 +						// set OpenGL state for additive lighting
 86.3718 +						GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHTEST_DISABLE);
 86.3719 +
 86.3720 +						GL_Cull(CT_TWO_SIDED);
 86.3721 +
 86.3722 +						// set uniforms
 86.3723 +						VectorCopy(light->origin, lightOrigin);
 86.3724 +						VectorCopy(tess.svars.color, lightColor);
 86.3725 +
 86.3726 +						GLSL_SetUniform_ViewOrigin(&tr.deferredLightingShader_DBS_proj, viewOrigin);
 86.3727 +						GLSL_SetUniform_LightOrigin(&tr.deferredLightingShader_DBS_proj, lightOrigin);
 86.3728 +						GLSL_SetUniform_LightColor(&tr.deferredLightingShader_DBS_proj, lightColor);
 86.3729 +						GLSL_SetUniform_LightRadius(&tr.deferredLightingShader_DBS_proj, light->sphereRadius);
 86.3730 +						GLSL_SetUniform_LightScale(&tr.deferredLightingShader_DBS_proj, light->l.scale);
 86.3731 +						GLSL_SetUniform_LightAttenuationMatrix(&tr.deferredLightingShader_DBS_proj, light->attenuationMatrix2);
 86.3732 +						qglUniform4fvARB(tr.deferredLightingShader_DBS_proj.u_LightFrustum, 6, &lightFrustum[0][0]);
 86.3733 +
 86.3734 +						GLSL_SetUniform_ModelViewProjectionMatrix(&tr.deferredLightingShader_DBS_proj, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.3735 +						GLSL_SetUniform_UnprojectMatrix(&tr.deferredLightingShader_DBS_proj, backEnd.viewParms.unprojectionMatrix);
 86.3736 +
 86.3737 +						GLSL_SetUniform_PortalClipping(&tr.deferredLightingShader_DBS_proj, backEnd.viewParms.isPortal);
 86.3738 +						if(backEnd.viewParms.isPortal)
 86.3739 +						{
 86.3740 +							float           plane[4];
 86.3741 +
 86.3742 +							// clipping plane in world space
 86.3743 +							plane[0] = backEnd.viewParms.portalPlane.normal[0];
 86.3744 +							plane[1] = backEnd.viewParms.portalPlane.normal[1];
 86.3745 +							plane[2] = backEnd.viewParms.portalPlane.normal[2];
 86.3746 +							plane[3] = backEnd.viewParms.portalPlane.dist;
 86.3747 +
 86.3748 +							GLSL_SetUniform_PortalPlane(&tr.deferredLightingShader_DBS_proj, plane);
 86.3749 +						}
 86.3750 +
 86.3751 +						// bind u_DiffuseMap
 86.3752 +						GL_SelectTexture(0);
 86.3753 +						GL_Bind(tr.deferredDiffuseFBOImage);
 86.3754 +
 86.3755 +						// bind u_NormalMap
 86.3756 +						GL_SelectTexture(1);
 86.3757 +						GL_Bind(tr.deferredNormalFBOImage);
 86.3758 +
 86.3759 +						if(r_normalMapping->integer)
 86.3760 +						{
 86.3761 +							// bind u_SpecularMap
 86.3762 +							GL_SelectTexture(2);
 86.3763 +							GL_Bind(tr.deferredSpecularFBOImage);
 86.3764 +						}
 86.3765 +
 86.3766 +						// bind u_DepthMap
 86.3767 +						GL_SelectTexture(3);
 86.3768 +						GL_Bind(tr.depthRenderImage);
 86.3769 +
 86.3770 +						// bind u_AttenuationMapXY
 86.3771 +						GL_SelectTexture(4);
 86.3772 +						BindAnimatedImage(&attenuationXYStage->bundle[TB_COLORMAP]);
 86.3773 +
 86.3774 +						// bind u_AttenuationMapZ
 86.3775 +						GL_SelectTexture(5);
 86.3776 +						BindAnimatedImage(&attenuationZStage->bundle[TB_COLORMAP]);
 86.3777 +
 86.3778 +						// draw lighting
 86.3779 +						VectorSet4(quadVerts[0], ia->scissorX, ia->scissorY, 0, 1);
 86.3780 +						VectorSet4(quadVerts[1], ia->scissorX + ia->scissorWidth - 1, ia->scissorY, 0, 1);
 86.3781 +						VectorSet4(quadVerts[2], ia->scissorX + ia->scissorWidth - 1, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.3782 +						VectorSet4(quadVerts[3], ia->scissorX, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.3783 +						Tess_InstantQuad(quadVerts);
 86.3784 +					}
 86.3785 +					else
 86.3786 +					{
 86.3787 +						// TODO
 86.3788 +					}
 86.3789 +				}
 86.3790 +			}
 86.3791 +
 86.3792 +			if(iaCount < (backEnd.viewParms.numInteractions - 1))
 86.3793 +			{
 86.3794 +				// jump to next interaction and continue
 86.3795 +				ia++;
 86.3796 +				iaCount++;
 86.3797 +			}
 86.3798 +			else
 86.3799 +			{
 86.3800 +				// increase last time to leave for loop
 86.3801 +				iaCount++;
 86.3802 +			}
 86.3803 +		}
 86.3804 +		else
 86.3805 +		{
 86.3806 +			// just continue
 86.3807 +			ia = ia->next;
 86.3808 +			iaCount++;
 86.3809 +		}
 86.3810 +
 86.3811 +		oldLight = light;
 86.3812 +	}
 86.3813 +
 86.3814 +	GL_PopMatrix();
 86.3815 +
 86.3816 +	// go back to the world modelview matrix
 86.3817 +	backEnd.orientation = backEnd.viewParms.world;
 86.3818 +	GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.3819 +
 86.3820 +	// reset scissor
 86.3821 +	GL_Scissor(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
 86.3822 +			   backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
 86.3823 +
 86.3824 +	GL_CheckErrors();
 86.3825 +
 86.3826 +	if(r_speeds->integer == 9)
 86.3827 +	{
 86.3828 +		qglFinish();
 86.3829 +		endTime = ri.Milliseconds();
 86.3830 +		backEnd.pc.c_deferredLightingTime = endTime - startTime;
 86.3831 +	}
 86.3832 +}
 86.3833 +
 86.3834 +static void RB_RenderInteractionsDeferredShadowMapped()
 86.3835 +{
 86.3836 +	interaction_t  *ia;
 86.3837 +	int             iaCount;
 86.3838 +	int             iaFirst;
 86.3839 +	shader_t       *shader, *oldShader;
 86.3840 +	trRefEntity_t  *entity, *oldEntity;
 86.3841 +	trRefLight_t   *light, *oldLight;
 86.3842 +	surfaceType_t  *surface;
 86.3843 +	qboolean        depthRange, oldDepthRange;
 86.3844 +	qboolean        alphaTest, oldAlphaTest;
 86.3845 +	qboolean        drawShadows;
 86.3846 +	int             cubeSide;
 86.3847 +
 86.3848 +	shader_t       *lightShader;
 86.3849 +	shaderStage_t  *attenuationXYStage;
 86.3850 +	shaderStage_t  *attenuationZStage;
 86.3851 +	int             i, j;
 86.3852 +	vec3_t          viewOrigin;
 86.3853 +	vec3_t          lightOrigin;
 86.3854 +	vec4_t          lightColor;
 86.3855 +	vec4_t          lightFrustum[6];
 86.3856 +	cplane_t       *frust;
 86.3857 +	qboolean        shadowCompare;
 86.3858 +	matrix_t        ortho;
 86.3859 +	vec4_t          quadVerts[4];
 86.3860 +	int             startTime = 0, endTime = 0;
 86.3861 +
 86.3862 +	GLimp_LogComment("--- RB_RenderInteractionsDeferredShadowMapped ---\n");
 86.3863 +
 86.3864 +	if(r_speeds->integer == 9)
 86.3865 +	{
 86.3866 +		startTime = ri.Milliseconds();
 86.3867 +	}
 86.3868 +
 86.3869 +	oldLight = NULL;
 86.3870 +	oldEntity = NULL;
 86.3871 +	oldShader = NULL;
 86.3872 +	oldDepthRange = depthRange = qfalse;
 86.3873 +	oldAlphaTest = alphaTest = qfalse;
 86.3874 +	drawShadows = qtrue;
 86.3875 +	cubeSide = 0;
 86.3876 +
 86.3877 +	// if we need to clear the FBO color buffers then it should be white
 86.3878 +	GL_ClearColor(1.0f, 1.0f, 1.0f, 1.0f);
 86.3879 +
 86.3880 +	// update depth render image
 86.3881 +	R_BindFBO(tr.deferredRenderFBO);
 86.3882 +	GL_SelectTexture(1);
 86.3883 +	GL_Bind(tr.depthRenderImage);
 86.3884 +	//qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.depthRenderImage->uploadWidth, tr.depthRenderImage->uploadHeight);
 86.3885 +
 86.3886 +	// render interactions
 86.3887 +	for(iaCount = 0, iaFirst = 0, ia = &backEnd.viewParms.interactions[0]; iaCount < backEnd.viewParms.numInteractions;)
 86.3888 +	{
 86.3889 +		backEnd.currentLight = light = ia->light;
 86.3890 +		backEnd.currentEntity = entity = ia->entity;
 86.3891 +		surface = ia->surface;
 86.3892 +		shader = ia->surfaceShader;
 86.3893 +		alphaTest = shader->alphaTest;
 86.3894 +
 86.3895 +		if(glConfig.occlusionQueryBits && glConfig.driverType != GLDRV_MESA && !ia->occlusionQuerySamples)
 86.3896 +		{
 86.3897 +			// skip all interactions of this light because it failed the occlusion query
 86.3898 +			goto skipInteraction;
 86.3899 +		}
 86.3900 +
 86.3901 +		// only iaCount == iaFirst if first iteration or counters were reset
 86.3902 +		if(iaCount == iaFirst)
 86.3903 +		{
 86.3904 +			if(drawShadows)
 86.3905 +			{
 86.3906 +				// HACK: bring OpenGL into a safe state or strange FBO update problems will occur
 86.3907 +				GL_BindProgram(NULL);
 86.3908 +				GL_State(GLS_DEFAULT);
 86.3909 +				//GL_VertexAttribsState(ATTR_POSITION);
 86.3910 +
 86.3911 +				GL_SelectTexture(0);
 86.3912 +				GL_Bind(tr.whiteImage);
 86.3913 +
 86.3914 +				if(light->l.noShadows || light->shadowLOD < 0)
 86.3915 +				{
 86.3916 +					if(r_logFile->integer)
 86.3917 +					{
 86.3918 +						// don't just call LogComment, or we will get
 86.3919 +						// a call to va() every frame!
 86.3920 +						GLimp_LogComment(va("----- Skipping shadowCube side: %i -----\n", cubeSide));
 86.3921 +					}
 86.3922 +
 86.3923 +					goto skipInteraction;
 86.3924 +				}
 86.3925 +				else
 86.3926 +				{
 86.3927 +					R_BindFBO(tr.shadowMapFBO[light->shadowLOD]);
 86.3928 +
 86.3929 +					switch (light->l.rlType)
 86.3930 +					{
 86.3931 +						case RL_OMNI:
 86.3932 +						{
 86.3933 +							float           xMin, xMax, yMin, yMax;
 86.3934 +							float           width, height, depth;
 86.3935 +							float           zNear, zFar;
 86.3936 +							float           fovX, fovY;
 86.3937 +							qboolean        flipX, flipY;
 86.3938 +							float          *proj;
 86.3939 +							vec3_t          angles;
 86.3940 +							matrix_t        rotationMatrix, transformMatrix, viewMatrix;
 86.3941 +
 86.3942 +							if(r_logFile->integer)
 86.3943 +							{
 86.3944 +								// don't just call LogComment, or we will get
 86.3945 +								// a call to va() every frame!
 86.3946 +								GLimp_LogComment(va("----- Rendering shadowCube side: %i -----\n", cubeSide));
 86.3947 +							}
 86.3948 +
 86.3949 +							R_AttachFBOTexture2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + cubeSide,
 86.3950 +												 tr.shadowCubeFBOImage[light->shadowLOD]->texnum, 0);
 86.3951 +							if(!r_ignoreGLErrors->integer)
 86.3952 +							{
 86.3953 +								R_CheckFBO(tr.shadowMapFBO[light->shadowLOD]);
 86.3954 +							}
 86.3955 +
 86.3956 +							// set the window clipping
 86.3957 +							GL_Viewport(0, 0, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.3958 +							GL_Scissor(0, 0, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.3959 +
 86.3960 +							qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 86.3961 +
 86.3962 +							switch (cubeSide)
 86.3963 +							{
 86.3964 +								case 0:
 86.3965 +								{
 86.3966 +									// view parameters
 86.3967 +									VectorSet(angles, 0, 0, 90);
 86.3968 +
 86.3969 +									// projection parameters
 86.3970 +									flipX = qfalse;
 86.3971 +									flipY = qfalse;
 86.3972 +									break;
 86.3973 +								}
 86.3974 +
 86.3975 +								case 1:
 86.3976 +								{
 86.3977 +									VectorSet(angles, 0, 180, 90);
 86.3978 +									flipX = qtrue;
 86.3979 +									flipY = qtrue;
 86.3980 +									break;
 86.3981 +								}
 86.3982 +
 86.3983 +								case 2:
 86.3984 +								{
 86.3985 +									VectorSet(angles, 0, 90, 0);
 86.3986 +									flipX = qfalse;
 86.3987 +									flipY = qfalse;
 86.3988 +									break;
 86.3989 +								}
 86.3990 +
 86.3991 +								case 3:
 86.3992 +								{
 86.3993 +									VectorSet(angles, 0, -90, 0);
 86.3994 +									flipX = qtrue;
 86.3995 +									flipY = qtrue;
 86.3996 +									break;
 86.3997 +								}
 86.3998 +
 86.3999 +								case 4:
 86.4000 +								{
 86.4001 +									VectorSet(angles, -90, 90, 0);
 86.4002 +									flipX = qfalse;
 86.4003 +									flipY = qfalse;
 86.4004 +									break;
 86.4005 +								}
 86.4006 +
 86.4007 +								case 5:
 86.4008 +								{
 86.4009 +									VectorSet(angles, 90, 90, 0);
 86.4010 +									flipX = qtrue;
 86.4011 +									flipY = qtrue;
 86.4012 +									break;
 86.4013 +								}
 86.4014 +
 86.4015 +								default:
 86.4016 +								{
 86.4017 +									// shut up compiler
 86.4018 +									VectorSet(angles, 0, 0, 0);
 86.4019 +									flipX = qfalse;
 86.4020 +									flipY = qfalse;
 86.4021 +									break;
 86.4022 +								}
 86.4023 +							}
 86.4024 +
 86.4025 +							// Quake -> OpenGL view matrix from light perspective
 86.4026 +							MatrixFromAngles(rotationMatrix, angles[PITCH], angles[YAW], angles[ROLL]);
 86.4027 +							MatrixSetupTransformFromRotation(transformMatrix, rotationMatrix, light->origin);
 86.4028 +							MatrixAffineInverse(transformMatrix, viewMatrix);
 86.4029 +
 86.4030 +							// convert from our coordinate system (looking down X)
 86.4031 +							// to OpenGL's coordinate system (looking down -Z)
 86.4032 +							MatrixMultiply(quakeToOpenGLMatrix, viewMatrix, light->viewMatrix);
 86.4033 +
 86.4034 +							// OpenGL projection matrix
 86.4035 +							fovX = 90;
 86.4036 +							fovY = 90;	//R_CalcFov(fovX, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.4037 +
 86.4038 +							zNear = 1.0;
 86.4039 +							zFar = light->sphereRadius;
 86.4040 +
 86.4041 +							if(!flipX)
 86.4042 +							{
 86.4043 +								xMax = zNear * tan(fovX * M_PI / 360.0f);
 86.4044 +								xMin = -xMax;
 86.4045 +							}
 86.4046 +							else
 86.4047 +							{
 86.4048 +								xMin = zNear * tan(fovX * M_PI / 360.0f);
 86.4049 +								xMax = -xMin;
 86.4050 +							}
 86.4051 +
 86.4052 +							if(!flipY)
 86.4053 +							{
 86.4054 +								yMax = zNear * tan(fovY * M_PI / 360.0f);
 86.4055 +								yMin = -yMax;
 86.4056 +							}
 86.4057 +							else
 86.4058 +							{
 86.4059 +								yMin = zNear * tan(fovY * M_PI / 360.0f);
 86.4060 +								yMax = -yMin;
 86.4061 +							}
 86.4062 +
 86.4063 +							width = xMax - xMin;
 86.4064 +							height = yMax - yMin;
 86.4065 +							depth = zFar - zNear;
 86.4066 +
 86.4067 +							proj = light->projectionMatrix;
 86.4068 +							proj[0] = (2 * zNear) / width;
 86.4069 +							proj[4] = 0;
 86.4070 +							proj[8] = (xMax + xMin) / width;
 86.4071 +							proj[12] = 0;
 86.4072 +							proj[1] = 0;
 86.4073 +							proj[5] = (2 * zNear) / height;
 86.4074 +							proj[9] = (yMax + yMin) / height;
 86.4075 +							proj[13] = 0;
 86.4076 +							proj[2] = 0;
 86.4077 +							proj[6] = 0;
 86.4078 +							proj[10] = -(zFar + zNear) / depth;
 86.4079 +							proj[14] = -(2 * zFar * zNear) / depth;
 86.4080 +							proj[3] = 0;
 86.4081 +							proj[7] = 0;
 86.4082 +							proj[11] = -1;
 86.4083 +							proj[15] = 0;
 86.4084 +
 86.4085 +							GL_LoadProjectionMatrix(light->projectionMatrix);
 86.4086 +							break;
 86.4087 +						}
 86.4088 +
 86.4089 +						case RL_PROJ:
 86.4090 +						{
 86.4091 +							GLimp_LogComment("--- Rendering projective shadowMap ---\n");
 86.4092 +
 86.4093 +							R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.shadowMapFBOImage[light->shadowLOD]->texnum, 0);
 86.4094 +							if(!r_ignoreGLErrors->integer)
 86.4095 +							{
 86.4096 +								R_CheckFBO(tr.shadowMapFBO[light->shadowLOD]);
 86.4097 +							}
 86.4098 +
 86.4099 +							// set the window clipping
 86.4100 +							GL_Viewport(0, 0, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.4101 +							GL_Scissor(0, 0, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.4102 +
 86.4103 +							qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 86.4104 +
 86.4105 +							GL_LoadProjectionMatrix(light->projectionMatrix);
 86.4106 +							break;
 86.4107 +						}
 86.4108 +
 86.4109 +						default:
 86.4110 +							break;
 86.4111 +					}
 86.4112 +				}
 86.4113 +
 86.4114 +				if(r_logFile->integer)
 86.4115 +				{
 86.4116 +					// don't just call LogComment, or we will get
 86.4117 +					// a call to va() every frame!
 86.4118 +					GLimp_LogComment(va("----- First Shadow Interaction: %i -----\n", iaCount));
 86.4119 +				}
 86.4120 +			}
 86.4121 +			else
 86.4122 +			{
 86.4123 +				GLimp_LogComment("--- Rendering lighting ---\n");
 86.4124 +
 86.4125 +				if(r_logFile->integer)
 86.4126 +				{
 86.4127 +					// don't just call LogComment, or we will get
 86.4128 +					// a call to va() every frame!
 86.4129 +					GLimp_LogComment(va("----- First Light Interaction: %i -----\n", iaCount));
 86.4130 +				}
 86.4131 +
 86.4132 +				// finally draw light
 86.4133 +				R_BindFBO(tr.deferredRenderFBO);
 86.4134 +
 86.4135 +				// set the window clipping
 86.4136 +				GL_Viewport(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
 86.4137 +							backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
 86.4138 +
 86.4139 +				//GL_Scissor(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
 86.4140 +				//        backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
 86.4141 +
 86.4142 +				// set light scissor to reduce fillrate
 86.4143 +				GL_Scissor(ia->scissorX, ia->scissorY, ia->scissorWidth, ia->scissorHeight);
 86.4144 +
 86.4145 +				// restore camera matrices
 86.4146 +				GL_LoadProjectionMatrix(backEnd.viewParms.projectionMatrix);
 86.4147 +				GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.4148 +
 86.4149 +				switch (light->l.rlType)
 86.4150 +				{
 86.4151 +					case RL_OMNI:
 86.4152 +					{
 86.4153 +						// reset light view and projection matrices
 86.4154 +						MatrixAffineInverse(light->transformMatrix, light->viewMatrix);
 86.4155 +						MatrixSetupScale(light->projectionMatrix, 1.0 / light->l.radius[0], 1.0 / light->l.radius[1],
 86.4156 +										 1.0 / light->l.radius[2]);
 86.4157 +
 86.4158 +						// build the attenuation matrix
 86.4159 +						MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.5);	// bias
 86.4160 +						MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 0.5);	// scale
 86.4161 +						MatrixMultiply2(light->attenuationMatrix, light->projectionMatrix);	// light projection (frustum)
 86.4162 +						MatrixMultiply2(light->attenuationMatrix, light->viewMatrix);
 86.4163 +						break;
 86.4164 +					}
 86.4165 +
 86.4166 +					case RL_PROJ:
 86.4167 +					{
 86.4168 +						// build the attenuation matrix
 86.4169 +						MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.0);	// bias
 86.4170 +						MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 1.0 / Q_min(light->l.distFar - light->l.distNear, 1.0));	// scale
 86.4171 +						MatrixMultiply2(light->attenuationMatrix, light->projectionMatrix);
 86.4172 +						MatrixMultiply2(light->attenuationMatrix, light->viewMatrix);
 86.4173 +						break;
 86.4174 +					}
 86.4175 +
 86.4176 +					default:
 86.4177 +						break;
 86.4178 +				}
 86.4179 +
 86.4180 +				// update uniforms
 86.4181 +				VectorCopy(backEnd.viewParms.orientation.origin, viewOrigin);
 86.4182 +
 86.4183 +				// copy frustum planes for pixel shader
 86.4184 +				for(i = 0; i < 6; i++)
 86.4185 +				{
 86.4186 +					frust = &light->frustum[i];
 86.4187 +
 86.4188 +					VectorCopy(frust->normal, lightFrustum[i]);
 86.4189 +					lightFrustum[i][3] = frust->dist;
 86.4190 +				}
 86.4191 +
 86.4192 +				// set 2D virtual screen size
 86.4193 +				GL_PushMatrix();
 86.4194 +				MatrixSetupOrthogonalProjection(ortho, backEnd.viewParms.viewportX,
 86.4195 +												backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
 86.4196 +												backEnd.viewParms.viewportY,
 86.4197 +												backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight, -99999, 99999);
 86.4198 +				GL_LoadProjectionMatrix(ortho);
 86.4199 +				GL_LoadModelViewMatrix(matrixIdentity);
 86.4200 +
 86.4201 +				// last interaction of current light
 86.4202 +				lightShader = light->shader;
 86.4203 +				attenuationZStage = lightShader->stages[0];
 86.4204 +
 86.4205 +				for(j = 1; j < MAX_SHADER_STAGES; j++)
 86.4206 +				{
 86.4207 +					attenuationXYStage = lightShader->stages[j];
 86.4208 +
 86.4209 +					if(!attenuationXYStage)
 86.4210 +					{
 86.4211 +						break;
 86.4212 +					}
 86.4213 +
 86.4214 +					if(attenuationXYStage->type != ST_ATTENUATIONMAP_XY)
 86.4215 +					{
 86.4216 +						continue;
 86.4217 +					}
 86.4218 +
 86.4219 +					if(!RB_EvalExpression(&attenuationXYStage->ifExp, 1.0))
 86.4220 +					{
 86.4221 +						continue;
 86.4222 +					}
 86.4223 +
 86.4224 +					Tess_ComputeColor(attenuationXYStage);
 86.4225 +					R_ComputeFinalAttenuation(attenuationXYStage, light);
 86.4226 +
 86.4227 +					if(light->l.rlType == RL_OMNI)
 86.4228 +					{
 86.4229 +						// enable shader, set arrays
 86.4230 +						GL_BindProgram(&tr.deferredLightingShader_DBS_omni);
 86.4231 +
 86.4232 +						// set OpenGL state for additive lighting
 86.4233 +						GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHTEST_DISABLE);
 86.4234 +
 86.4235 +						GL_Cull(CT_TWO_SIDED);
 86.4236 +
 86.4237 +						// set uniforms
 86.4238 +						VectorCopy(light->origin, lightOrigin);
 86.4239 +						VectorCopy(tess.svars.color, lightColor);
 86.4240 +						shadowCompare = !light->l.noShadows && light->shadowLOD >= 0;
 86.4241 +
 86.4242 +						GLSL_SetUniform_ViewOrigin(&tr.deferredLightingShader_DBS_omni, viewOrigin);
 86.4243 +						GLSL_SetUniform_LightOrigin(&tr.deferredLightingShader_DBS_omni, lightOrigin);
 86.4244 +						GLSL_SetUniform_LightColor(&tr.deferredLightingShader_DBS_omni, lightColor);
 86.4245 +						GLSL_SetUniform_LightRadius(&tr.deferredLightingShader_DBS_omni, light->sphereRadius);
 86.4246 +						GLSL_SetUniform_LightScale(&tr.deferredLightingShader_DBS_omni, light->l.scale);
 86.4247 +						GLSL_SetUniform_LightAttenuationMatrix(&tr.deferredLightingShader_DBS_omni, light->attenuationMatrix2);
 86.4248 +						qglUniform4fvARB(tr.deferredLightingShader_DBS_omni.u_LightFrustum, 6, &lightFrustum[0][0]);
 86.4249 +						GLSL_SetUniform_ShadowCompare(&tr.deferredLightingShader_DBS_omni, shadowCompare);
 86.4250 +
 86.4251 +						GLSL_SetUniform_ModelViewProjectionMatrix(&tr.deferredLightingShader_DBS_omni, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.4252 +						GLSL_SetUniform_UnprojectMatrix(&tr.deferredLightingShader_DBS_omni, backEnd.viewParms.unprojectionMatrix);
 86.4253 +
 86.4254 +						GLSL_SetUniform_PortalClipping(&tr.deferredLightingShader_DBS_omni, backEnd.viewParms.isPortal);
 86.4255 +						if(backEnd.viewParms.isPortal)
 86.4256 +						{
 86.4257 +							float           plane[4];
 86.4258 +
 86.4259 +							// clipping plane in world space
 86.4260 +							plane[0] = backEnd.viewParms.portalPlane.normal[0];
 86.4261 +							plane[1] = backEnd.viewParms.portalPlane.normal[1];
 86.4262 +							plane[2] = backEnd.viewParms.portalPlane.normal[2];
 86.4263 +							plane[3] = backEnd.viewParms.portalPlane.dist;
 86.4264 +
 86.4265 +							GLSL_SetUniform_PortalPlane(&tr.deferredLightingShader_DBS_omni, plane);
 86.4266 +						}
 86.4267 +
 86.4268 +						// bind u_DiffuseMap
 86.4269 +						GL_SelectTexture(0);
 86.4270 +						GL_Bind(tr.deferredDiffuseFBOImage);
 86.4271 +
 86.4272 +						// bind u_NormalMap
 86.4273 +						GL_SelectTexture(1);
 86.4274 +						GL_Bind(tr.deferredNormalFBOImage);
 86.4275 +
 86.4276 +						if(r_normalMapping->integer)
 86.4277 +						{
 86.4278 +							// bind u_SpecularMap
 86.4279 +							GL_SelectTexture(2);
 86.4280 +							GL_Bind(tr.deferredSpecularFBOImage);
 86.4281 +						}
 86.4282 +
 86.4283 +						// bind u_DepthMap
 86.4284 +						GL_SelectTexture(3);
 86.4285 +						GL_Bind(tr.depthRenderImage);
 86.4286 +
 86.4287 +						// bind u_AttenuationMapXY
 86.4288 +						GL_SelectTexture(4);
 86.4289 +						BindAnimatedImage(&attenuationXYStage->bundle[TB_COLORMAP]);
 86.4290 +
 86.4291 +						// bind u_AttenuationMapZ
 86.4292 +						GL_SelectTexture(5);
 86.4293 +						BindAnimatedImage(&attenuationZStage->bundle[TB_COLORMAP]);
 86.4294 +
 86.4295 +						// bind u_ShadowMap
 86.4296 +						if(shadowCompare)
 86.4297 +						{
 86.4298 +							GL_SelectTexture(6);
 86.4299 +							GL_Bind(tr.shadowCubeFBOImage[light->shadowLOD]);
 86.4300 +						}
 86.4301 +
 86.4302 +						// draw lighting
 86.4303 +						VectorSet4(quadVerts[0], ia->scissorX, ia->scissorY, 0, 1);
 86.4304 +						VectorSet4(quadVerts[1], ia->scissorX + ia->scissorWidth - 1, ia->scissorY, 0, 1);
 86.4305 +						VectorSet4(quadVerts[2], ia->scissorX + ia->scissorWidth - 1, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.4306 +						VectorSet4(quadVerts[3], ia->scissorX, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.4307 +						Tess_InstantQuad(quadVerts);
 86.4308 +					}
 86.4309 +					else if(light->l.rlType == RL_PROJ)
 86.4310 +					{
 86.4311 +						if(light->l.inverseShadows)
 86.4312 +						{
 86.4313 +							GL_BindProgram(&tr.deferredShadowingShader_proj);
 86.4314 +
 86.4315 +							GL_State(GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE_MINUS_SRC_COLOR);
 86.4316 +							//GL_State(GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA | GLS_DSTBLEND_SRC_ALPHA);
 86.4317 +							GL_Cull(CT_TWO_SIDED);
 86.4318 +
 86.4319 +							// set uniforms
 86.4320 +							VectorCopy(light->origin, lightOrigin);
 86.4321 +							VectorCopy(tess.svars.color, lightColor);
 86.4322 +							shadowCompare = !light->l.noShadows && light->shadowLOD >= 0;
 86.4323 +
 86.4324 +							GLSL_SetUniform_LightOrigin(&tr.deferredShadowingShader_proj, lightOrigin);
 86.4325 +							GLSL_SetUniform_LightColor(&tr.deferredShadowingShader_proj, lightColor);
 86.4326 +							GLSL_SetUniform_LightRadius(&tr.deferredShadowingShader_proj, light->sphereRadius);
 86.4327 +							GLSL_SetUniform_LightAttenuationMatrix(&tr.deferredShadowingShader_proj, light->attenuationMatrix2);
 86.4328 +							qglUniform4fvARB(tr.deferredShadowingShader_proj.u_LightFrustum, 6, &lightFrustum[0][0]);
 86.4329 +
 86.4330 +							GLSL_SetUniform_ShadowMatrix(&tr.deferredShadowingShader_proj, light->attenuationMatrix);
 86.4331 +							GLSL_SetUniform_ShadowCompare(&tr.deferredShadowingShader_proj, shadowCompare);
 86.4332 +
 86.4333 +							GLSL_SetUniform_ModelViewProjectionMatrix(&tr.deferredShadowingShader_proj, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.4334 +							GLSL_SetUniform_UnprojectMatrix(&tr.deferredShadowingShader_proj, backEnd.viewParms.unprojectionMatrix);
 86.4335 +
 86.4336 +							GLSL_SetUniform_PortalClipping(&tr.deferredShadowingShader_proj, backEnd.viewParms.isPortal);
 86.4337 +							if(backEnd.viewParms.isPortal)
 86.4338 +							{
 86.4339 +								float           plane[4];
 86.4340 +
 86.4341 +								// clipping plane in world space
 86.4342 +								plane[0] = backEnd.viewParms.portalPlane.normal[0];
 86.4343 +								plane[1] = backEnd.viewParms.portalPlane.normal[1];
 86.4344 +								plane[2] = backEnd.viewParms.portalPlane.normal[2];
 86.4345 +								plane[3] = backEnd.viewParms.portalPlane.dist;
 86.4346 +
 86.4347 +								GLSL_SetUniform_PortalPlane(&tr.deferredShadowingShader_proj, plane);
 86.4348 +							}
 86.4349 +
 86.4350 +							// bind u_DepthMap
 86.4351 +							GL_SelectTexture(0);
 86.4352 +							GL_Bind(tr.depthRenderImage);
 86.4353 +
 86.4354 +							// bind u_AttenuationMapXY
 86.4355 +							GL_SelectTexture(1);
 86.4356 +							BindAnimatedImage(&attenuationXYStage->bundle[TB_COLORMAP]);
 86.4357 +
 86.4358 +							// bind u_AttenuationMapZ
 86.4359 +							GL_SelectTexture(2);
 86.4360 +							BindAnimatedImage(&attenuationZStage->bundle[TB_COLORMAP]);
 86.4361 +
 86.4362 +							// bind u_ShadowMap
 86.4363 +							if(shadowCompare)
 86.4364 +							{
 86.4365 +								GL_SelectTexture(3);
 86.4366 +								GL_Bind(tr.shadowMapFBOImage[light->shadowLOD]);
 86.4367 +							}
 86.4368 +
 86.4369 +							// draw lighting
 86.4370 +							VectorSet4(quadVerts[0], ia->scissorX, ia->scissorY, 0, 1);
 86.4371 +							VectorSet4(quadVerts[1], ia->scissorX + ia->scissorWidth - 1, ia->scissorY, 0, 1);
 86.4372 +							VectorSet4(quadVerts[2], ia->scissorX + ia->scissorWidth - 1, ia->scissorY + ia->scissorHeight - 1, 0,
 86.4373 +									   1);
 86.4374 +							VectorSet4(quadVerts[3], ia->scissorX, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.4375 +							Tess_InstantQuad(quadVerts);
 86.4376 +						}
 86.4377 +						else
 86.4378 +						{
 86.4379 +							GL_BindProgram(&tr.deferredLightingShader_DBS_proj);
 86.4380 +
 86.4381 +							// set OpenGL state for additive lighting
 86.4382 +							GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHTEST_DISABLE);
 86.4383 +							GL_Cull(CT_TWO_SIDED);
 86.4384 +
 86.4385 +							// set uniforms
 86.4386 +							VectorCopy(light->origin, lightOrigin);
 86.4387 +							VectorCopy(tess.svars.color, lightColor);
 86.4388 +							shadowCompare = !light->l.noShadows && light->shadowLOD >= 0;
 86.4389 +
 86.4390 +							GLSL_SetUniform_ViewOrigin(&tr.deferredLightingShader_DBS_proj, viewOrigin);
 86.4391 +							GLSL_SetUniform_LightOrigin(&tr.deferredLightingShader_DBS_proj, lightOrigin);
 86.4392 +							GLSL_SetUniform_LightColor(&tr.deferredLightingShader_DBS_proj, lightColor);
 86.4393 +							GLSL_SetUniform_LightRadius(&tr.deferredLightingShader_DBS_proj, light->sphereRadius);
 86.4394 +							GLSL_SetUniform_LightScale(&tr.deferredLightingShader_DBS_proj, light->l.scale);
 86.4395 +							GLSL_SetUniform_LightAttenuationMatrix(&tr.deferredLightingShader_DBS_proj, light->attenuationMatrix2);
 86.4396 +							qglUniform4fvARB(tr.deferredLightingShader_DBS_proj.u_LightFrustum, 6, &lightFrustum[0][0]);
 86.4397 +
 86.4398 +							GLSL_SetUniform_ShadowMatrix(&tr.deferredLightingShader_DBS_proj, light->attenuationMatrix);
 86.4399 +							GLSL_SetUniform_ShadowCompare(&tr.deferredLightingShader_DBS_proj, shadowCompare);
 86.4400 +
 86.4401 +							GLSL_SetUniform_ModelViewProjectionMatrix(&tr.deferredLightingShader_DBS_proj, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.4402 +							GLSL_SetUniform_UnprojectMatrix(&tr.deferredLightingShader_DBS_proj, backEnd.viewParms.unprojectionMatrix);
 86.4403 +
 86.4404 +							GLSL_SetUniform_PortalClipping(&tr.deferredLightingShader_DBS_proj, backEnd.viewParms.isPortal);
 86.4405 +							if(backEnd.viewParms.isPortal)
 86.4406 +							{
 86.4407 +								float           plane[4];
 86.4408 +
 86.4409 +								// clipping plane in world space
 86.4410 +								plane[0] = backEnd.viewParms.portalPlane.normal[0];
 86.4411 +								plane[1] = backEnd.viewParms.portalPlane.normal[1];
 86.4412 +								plane[2] = backEnd.viewParms.portalPlane.normal[2];
 86.4413 +								plane[3] = backEnd.viewParms.portalPlane.dist;
 86.4414 +
 86.4415 +								GLSL_SetUniform_PortalPlane(&tr.deferredLightingShader_DBS_proj, plane);
 86.4416 +							}
 86.4417 +
 86.4418 +							// bind u_DiffuseMap
 86.4419 +							GL_SelectTexture(0);
 86.4420 +							GL_Bind(tr.deferredDiffuseFBOImage);
 86.4421 +
 86.4422 +							// bind u_NormalMap
 86.4423 +							GL_SelectTexture(1);
 86.4424 +							GL_Bind(tr.deferredNormalFBOImage);
 86.4425 +
 86.4426 +							if(r_normalMapping->integer)
 86.4427 +							{
 86.4428 +								// bind u_SpecularMap
 86.4429 +								GL_SelectTexture(2);
 86.4430 +								GL_Bind(tr.deferredSpecularFBOImage);
 86.4431 +							}
 86.4432 +
 86.4433 +							// bind u_DepthMap
 86.4434 +							GL_SelectTexture(3);
 86.4435 +							GL_Bind(tr.depthRenderImage);
 86.4436 +
 86.4437 +							// bind u_AttenuationMapXY
 86.4438 +							GL_SelectTexture(4);
 86.4439 +							BindAnimatedImage(&attenuationXYStage->bundle[TB_COLORMAP]);
 86.4440 +
 86.4441 +							// bind u_AttenuationMapZ
 86.4442 +							GL_SelectTexture(5);
 86.4443 +							BindAnimatedImage(&attenuationZStage->bundle[TB_COLORMAP]);
 86.4444 +
 86.4445 +							// bind u_ShadowMap
 86.4446 +							if(shadowCompare)
 86.4447 +							{
 86.4448 +								GL_SelectTexture(6);
 86.4449 +								GL_Bind(tr.shadowMapFBOImage[light->shadowLOD]);
 86.4450 +							}
 86.4451 +
 86.4452 +							// draw lighting
 86.4453 +							VectorSet4(quadVerts[0], ia->scissorX, ia->scissorY, 0, 1);
 86.4454 +							VectorSet4(quadVerts[1], ia->scissorX + ia->scissorWidth - 1, ia->scissorY, 0, 1);
 86.4455 +							VectorSet4(quadVerts[2], ia->scissorX + ia->scissorWidth - 1, ia->scissorY + ia->scissorHeight - 1, 0,
 86.4456 +									   1);
 86.4457 +							VectorSet4(quadVerts[3], ia->scissorX, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.4458 +							Tess_InstantQuad(quadVerts);
 86.4459 +						}
 86.4460 +					}
 86.4461 +					else
 86.4462 +					{
 86.4463 +						// TODO
 86.4464 +					}
 86.4465 +
 86.4466 +					// end of lighting
 86.4467 +					GL_PopMatrix();
 86.4468 +
 86.4469 +					R_BindNullFBO();
 86.4470 +				}
 86.4471 +			}
 86.4472 +		}						// end if(iaCount == iaFirst)
 86.4473 +
 86.4474 +		if(drawShadows)
 86.4475 +		{
 86.4476 +			if(entity->e.renderfx & (RF_NOSHADOW | RF_DEPTHHACK))
 86.4477 +			{
 86.4478 +				goto skipInteraction;
 86.4479 +			}
 86.4480 +
 86.4481 +			if(shader->isSky)
 86.4482 +			{
 86.4483 +				goto skipInteraction;
 86.4484 +			}
 86.4485 +
 86.4486 +			if(shader->sort > SS_OPAQUE)
 86.4487 +			{
 86.4488 +				goto skipInteraction;
 86.4489 +			}
 86.4490 +
 86.4491 +			if(shader->noShadows || light->l.noShadows || light->shadowLOD < 0)
 86.4492 +			{
 86.4493 +				goto skipInteraction;
 86.4494 +			}
 86.4495 +
 86.4496 +			if(light->l.inverseShadows && (entity == &tr.worldEntity))
 86.4497 +			{
 86.4498 +				// this light only casts shadows by its player and their items
 86.4499 +				goto skipInteraction;
 86.4500 +			}
 86.4501 +
 86.4502 +			if(ia->type == IA_LIGHTONLY)
 86.4503 +			{
 86.4504 +				goto skipInteraction;
 86.4505 +			}
 86.4506 +
 86.4507 +			if(light->l.rlType == RL_OMNI && !(ia->cubeSideBits & (1 << cubeSide)))
 86.4508 +			{
 86.4509 +				goto skipInteraction;
 86.4510 +			}
 86.4511 +
 86.4512 +			switch (light->l.rlType)
 86.4513 +			{
 86.4514 +				case RL_OMNI:
 86.4515 +				case RL_PROJ:
 86.4516 +				{
 86.4517 +					if(light == oldLight && entity == oldEntity && (alphaTest ? shader == oldShader : alphaTest == oldAlphaTest))
 86.4518 +					{
 86.4519 +						if(r_logFile->integer)
 86.4520 +						{
 86.4521 +							// don't just call LogComment, or we will get
 86.4522 +							// a call to va() every frame!
 86.4523 +							GLimp_LogComment(va("----- Batching Shadow Interaction: %i -----\n", iaCount));
 86.4524 +						}
 86.4525 +
 86.4526 +						// fast path, same as previous
 86.4527 +						rb_surfaceTable[*surface] (surface);
 86.4528 +						goto nextInteraction;
 86.4529 +					}
 86.4530 +					else
 86.4531 +					{
 86.4532 +						if(oldLight)
 86.4533 +						{
 86.4534 +							// draw the contents of the last shader batch
 86.4535 +							Tess_End();
 86.4536 +						}
 86.4537 +
 86.4538 +						if(r_logFile->integer)
 86.4539 +						{
 86.4540 +							// don't just call LogComment, or we will get
 86.4541 +							// a call to va() every frame!
 86.4542 +							GLimp_LogComment(va("----- Beginning Shadow Interaction: %i -----\n", iaCount));
 86.4543 +						}
 86.4544 +
 86.4545 +						// we don't need tangent space calculations here
 86.4546 +						Tess_Begin(Tess_StageIteratorShadowFill, shader, light->shader, qtrue, qfalse, -1);
 86.4547 +					}
 86.4548 +					break;
 86.4549 +				}
 86.4550 +
 86.4551 +				default:
 86.4552 +					break;
 86.4553 +			}
 86.4554 +		}
 86.4555 +		else
 86.4556 +		{
 86.4557 +			// jump to !ia->next
 86.4558 +			goto nextInteraction;
 86.4559 +		}
 86.4560 +
 86.4561 +		// change the modelview matrix if needed
 86.4562 +		if(entity != oldEntity)
 86.4563 +		{
 86.4564 +			depthRange = qfalse;
 86.4565 +
 86.4566 +			if(entity != &tr.worldEntity)
 86.4567 +			{
 86.4568 +				// set up the transformation matrix
 86.4569 +				if(drawShadows)
 86.4570 +				{
 86.4571 +					R_RotateEntityForLight(entity, light, &backEnd.orientation);
 86.4572 +				}
 86.4573 +				else
 86.4574 +				{
 86.4575 +					R_RotateEntityForViewParms(entity, &backEnd.viewParms, &backEnd.orientation);
 86.4576 +				}
 86.4577 +
 86.4578 +				if(entity->e.renderfx & RF_DEPTHHACK)
 86.4579 +				{
 86.4580 +					// hack the depth range to prevent view model from poking into walls
 86.4581 +					depthRange = qtrue;
 86.4582 +				}
 86.4583 +			}
 86.4584 +			else
 86.4585 +			{
 86.4586 +				// set up the transformation matrix
 86.4587 +				if(drawShadows)
 86.4588 +				{
 86.4589 +					Com_Memset(&backEnd.orientation, 0, sizeof(backEnd.orientation));
 86.4590 +
 86.4591 +					backEnd.orientation.axis[0][0] = 1;
 86.4592 +					backEnd.orientation.axis[1][1] = 1;
 86.4593 +					backEnd.orientation.axis[2][2] = 1;
 86.4594 +					VectorCopy(light->l.origin, backEnd.orientation.viewOrigin);
 86.4595 +
 86.4596 +					MatrixIdentity(backEnd.orientation.transformMatrix);
 86.4597 +					//MatrixAffineInverse(backEnd.orientation.transformMatrix, backEnd.orientation.viewMatrix);
 86.4598 +					MatrixMultiply(light->viewMatrix, backEnd.orientation.transformMatrix, backEnd.orientation.viewMatrix);
 86.4599 +					MatrixCopy(backEnd.orientation.viewMatrix, backEnd.orientation.modelViewMatrix);
 86.4600 +				}
 86.4601 +				else
 86.4602 +				{
 86.4603 +					// transform by the camera placement
 86.4604 +					backEnd.orientation = backEnd.viewParms.world;
 86.4605 +				}
 86.4606 +			}
 86.4607 +
 86.4608 +			GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.4609 +
 86.4610 +			// change depthrange if needed
 86.4611 +			if(oldDepthRange != depthRange)
 86.4612 +			{
 86.4613 +				if(depthRange)
 86.4614 +				{
 86.4615 +					qglDepthRange(0, 0.3);
 86.4616 +				}
 86.4617 +				else
 86.4618 +				{
 86.4619 +					qglDepthRange(0, 1);
 86.4620 +				}
 86.4621 +				oldDepthRange = depthRange;
 86.4622 +			}
 86.4623 +		}
 86.4624 +
 86.4625 +		if(drawShadows)
 86.4626 +		{
 86.4627 +			switch (light->l.rlType)
 86.4628 +			{
 86.4629 +				case RL_OMNI:
 86.4630 +				case RL_PROJ:
 86.4631 +				{
 86.4632 +					// add the triangles for this surface
 86.4633 +					rb_surfaceTable[*surface] (surface);
 86.4634 +					break;
 86.4635 +				}
 86.4636 +
 86.4637 +				default:
 86.4638 +					break;
 86.4639 +			}
 86.4640 +		}
 86.4641 +		else
 86.4642 +		{
 86.4643 +			// DO NOTHING
 86.4644 +			//rb_surfaceTable[*surface] (surface, ia->numLightIndexes, ia->lightIndexes, 0, NULL);
 86.4645 +		}
 86.4646 +
 86.4647 +	  nextInteraction:
 86.4648 +
 86.4649 +		// remember values
 86.4650 +		oldLight = light;
 86.4651 +		oldEntity = entity;
 86.4652 +		oldShader = shader;
 86.4653 +		oldAlphaTest = alphaTest;
 86.4654 +
 86.4655 +	  skipInteraction:
 86.4656 +		if(!ia->next)
 86.4657 +		{
 86.4658 +			// if ia->next does not point to any other interaction then
 86.4659 +			// this is the last interaction of the current light
 86.4660 +
 86.4661 +			if(r_logFile->integer)
 86.4662 +			{
 86.4663 +				// don't just call LogComment, or we will get
 86.4664 +				// a call to va() every frame!
 86.4665 +				GLimp_LogComment(va("----- Last Interaction: %i -----\n", iaCount));
 86.4666 +			}
 86.4667 +
 86.4668 +			if(drawShadows)
 86.4669 +			{
 86.4670 +				// draw the contents of the last shader batch
 86.4671 +				Tess_End();
 86.4672 +
 86.4673 +				switch (light->l.rlType)
 86.4674 +				{
 86.4675 +					case RL_OMNI:
 86.4676 +					{
 86.4677 +						if(cubeSide == 5)
 86.4678 +						{
 86.4679 +							cubeSide = 0;
 86.4680 +							drawShadows = qfalse;
 86.4681 +						}
 86.4682 +						else
 86.4683 +						{
 86.4684 +							cubeSide++;
 86.4685 +						}
 86.4686 +
 86.4687 +						// jump back to first interaction of this light
 86.4688 +						ia = &backEnd.viewParms.interactions[iaFirst];
 86.4689 +						iaCount = iaFirst;
 86.4690 +						break;
 86.4691 +					}
 86.4692 +
 86.4693 +					case RL_PROJ:
 86.4694 +					{
 86.4695 +						// jump back to first interaction of this light and start lighting
 86.4696 +						ia = &backEnd.viewParms.interactions[iaFirst];
 86.4697 +						iaCount = iaFirst;
 86.4698 +						drawShadows = qfalse;
 86.4699 +						break;
 86.4700 +					}
 86.4701 +
 86.4702 +					default:
 86.4703 +						break;
 86.4704 +				}
 86.4705 +			}
 86.4706 +			else
 86.4707 +			{
 86.4708 +#ifdef VOLUMETRIC_LIGHTING
 86.4709 +				// draw the light volume if needed
 86.4710 +				if(light->shader->volumetricLight)
 86.4711 +				{
 86.4712 +					Render_lightVolume(light);
 86.4713 +				}
 86.4714 +#endif
 86.4715 +
 86.4716 +				if(iaCount < (backEnd.viewParms.numInteractions - 1))
 86.4717 +				{
 86.4718 +					// jump to next interaction and start shadowing
 86.4719 +					ia++;
 86.4720 +					iaCount++;
 86.4721 +					iaFirst = iaCount;
 86.4722 +					drawShadows = qtrue;
 86.4723 +				}
 86.4724 +				else
 86.4725 +				{
 86.4726 +					// increase last time to leave for loop
 86.4727 +					iaCount++;
 86.4728 +				}
 86.4729 +			}
 86.4730 +
 86.4731 +			// force updates
 86.4732 +			oldLight = NULL;
 86.4733 +			oldEntity = NULL;
 86.4734 +			oldShader = NULL;
 86.4735 +		}
 86.4736 +		else
 86.4737 +		{
 86.4738 +			// just continue
 86.4739 +			ia = ia->next;
 86.4740 +			iaCount++;
 86.4741 +		}
 86.4742 +	}
 86.4743 +
 86.4744 +	// go back to the world modelview matrix
 86.4745 +	GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.4746 +	if(depthRange)
 86.4747 +	{
 86.4748 +		qglDepthRange(0, 1);
 86.4749 +	}
 86.4750 +
 86.4751 +	// reset scissor clamping
 86.4752 +	GL_Scissor(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
 86.4753 +			   backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
 86.4754 +
 86.4755 +	// reset clear color
 86.4756 +	GL_ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 86.4757 +
 86.4758 +	GL_CheckErrors();
 86.4759 +
 86.4760 +	if(r_speeds->integer == 9)
 86.4761 +	{
 86.4762 +		qglFinish();
 86.4763 +		endTime = ri.Milliseconds();
 86.4764 +		backEnd.pc.c_deferredLightingTime = endTime - startTime;
 86.4765 +	}
 86.4766 +}
 86.4767 +
 86.4768 +static void RB_RenderInteractionsDeferredInverseShadows()
 86.4769 +{
 86.4770 +	interaction_t  *ia;
 86.4771 +	int             iaCount;
 86.4772 +	int             iaFirst;
 86.4773 +	shader_t       *shader, *oldShader;
 86.4774 +	trRefEntity_t  *entity, *oldEntity;
 86.4775 +	trRefLight_t   *light, *oldLight;
 86.4776 +	surfaceType_t  *surface;
 86.4777 +	qboolean        depthRange, oldDepthRange;
 86.4778 +	qboolean        alphaTest, oldAlphaTest;
 86.4779 +	qboolean        drawShadows;
 86.4780 +	int             cubeSide;
 86.4781 +
 86.4782 +	shader_t       *lightShader;
 86.4783 +	shaderStage_t  *attenuationXYStage;
 86.4784 +	shaderStage_t  *attenuationZStage;
 86.4785 +	int             i, j;
 86.4786 +	vec3_t          viewOrigin;
 86.4787 +	vec3_t          lightOrigin;
 86.4788 +	vec4_t          lightColor;
 86.4789 +	vec4_t          lightFrustum[6];
 86.4790 +	cplane_t       *frust;
 86.4791 +	qboolean        shadowCompare;
 86.4792 +	matrix_t        ortho;
 86.4793 +	vec4_t          quadVerts[4];
 86.4794 +	int             startTime = 0, endTime = 0;
 86.4795 +
 86.4796 +	GLimp_LogComment("--- RB_RenderInteractionsDeferredInverseShadows ---\n");
 86.4797 +
 86.4798 +	if(!glConfig.framebufferObjectAvailable)
 86.4799 +		return;
 86.4800 +
 86.4801 +	if(r_hdrRendering->integer && !glConfig.textureFloatAvailable)
 86.4802 +		return;
 86.4803 +
 86.4804 +	if(r_speeds->integer == 9)
 86.4805 +	{
 86.4806 +		startTime = ri.Milliseconds();
 86.4807 +	}
 86.4808 +
 86.4809 +	oldLight = NULL;
 86.4810 +	oldEntity = NULL;
 86.4811 +	oldShader = NULL;
 86.4812 +	oldDepthRange = depthRange = qfalse;
 86.4813 +	oldAlphaTest = alphaTest = qfalse;
 86.4814 +	drawShadows = qtrue;
 86.4815 +	cubeSide = 0;
 86.4816 +
 86.4817 +	// if we need to clear the FBO color buffers then it should be white
 86.4818 +	GL_ClearColor(1.0f, 1.0f, 1.0f, 1.0f);
 86.4819 +
 86.4820 +	// update depth render image
 86.4821 +	if(r_deferredShading->integer && glConfig.framebufferObjectAvailable && glConfig.textureFloatAvailable &&
 86.4822 +					   glConfig.drawBuffersAvailable && glConfig.maxDrawBuffers >= 4)
 86.4823 +	{
 86.4824 +		// no update needed FBO handles it
 86.4825 +		R_BindFBO(tr.deferredRenderFBO);
 86.4826 +	}
 86.4827 +	else if(r_hdrRendering->integer && glConfig.framebufferObjectAvailable && glConfig.textureFloatAvailable)
 86.4828 +	{
 86.4829 +		// no update needed FBO handles it
 86.4830 +		R_BindFBO(tr.deferredRenderFBO);
 86.4831 +	}
 86.4832 +	else
 86.4833 +	{
 86.4834 +		R_BindNullFBO();
 86.4835 +		GL_SelectTexture(0);
 86.4836 +		GL_Bind(tr.depthRenderImage);
 86.4837 +		qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.depthRenderImage->uploadWidth, tr.depthRenderImage->uploadHeight);
 86.4838 +	}
 86.4839 +
 86.4840 +
 86.4841 +	// render interactions
 86.4842 +	for(iaCount = 0, iaFirst = 0, ia = &backEnd.viewParms.interactions[0]; iaCount < backEnd.viewParms.numInteractions;)
 86.4843 +	{
 86.4844 +		backEnd.currentLight = light = ia->light;
 86.4845 +		backEnd.currentEntity = entity = ia->entity;
 86.4846 +		surface = ia->surface;
 86.4847 +		shader = ia->surfaceShader;
 86.4848 +		alphaTest = shader->alphaTest;
 86.4849 +
 86.4850 +		if(glConfig.occlusionQueryBits && glConfig.driverType != GLDRV_MESA && !ia->occlusionQuerySamples)
 86.4851 +		{
 86.4852 +			// skip all interactions of this light because it failed the occlusion query
 86.4853 +			goto skipInteraction;
 86.4854 +		}
 86.4855 +
 86.4856 +		if(!light->l.inverseShadows)
 86.4857 +		{
 86.4858 +			// we only care about inverse shadows as this is a post process effect
 86.4859 +			goto skipInteraction;
 86.4860 +		}
 86.4861 +
 86.4862 +		// only iaCount == iaFirst if first iteration or counters were reset
 86.4863 +		if(iaCount == iaFirst)
 86.4864 +		{
 86.4865 +			if(drawShadows)
 86.4866 +			{
 86.4867 +				// HACK: bring OpenGL into a safe state or strange FBO update problems will occur
 86.4868 +				GL_BindProgram(NULL);
 86.4869 +				GL_State(GLS_DEFAULT);
 86.4870 +				//GL_VertexAttribsState(ATTR_POSITION);
 86.4871 +
 86.4872 +				GL_SelectTexture(0);
 86.4873 +				GL_Bind(tr.whiteImage);
 86.4874 +
 86.4875 +				if(light->l.noShadows || light->shadowLOD < 0)
 86.4876 +				{
 86.4877 +					if(r_logFile->integer)
 86.4878 +					{
 86.4879 +						// don't just call LogComment, or we will get
 86.4880 +						// a call to va() every frame!
 86.4881 +						GLimp_LogComment(va("----- Skipping shadowCube side: %i -----\n", cubeSide));
 86.4882 +					}
 86.4883 +
 86.4884 +					goto skipInteraction;
 86.4885 +				}
 86.4886 +				else
 86.4887 +				{
 86.4888 +					R_BindFBO(tr.shadowMapFBO[light->shadowLOD]);
 86.4889 +
 86.4890 +					switch (light->l.rlType)
 86.4891 +					{
 86.4892 +						case RL_OMNI:
 86.4893 +						{
 86.4894 +							float           xMin, xMax, yMin, yMax;
 86.4895 +							float           width, height, depth;
 86.4896 +							float           zNear, zFar;
 86.4897 +							float           fovX, fovY;
 86.4898 +							qboolean        flipX, flipY;
 86.4899 +							float          *proj;
 86.4900 +							vec3_t          angles;
 86.4901 +							matrix_t        rotationMatrix, transformMatrix, viewMatrix;
 86.4902 +
 86.4903 +							if(r_logFile->integer)
 86.4904 +							{
 86.4905 +								// don't just call LogComment, or we will get
 86.4906 +								// a call to va() every frame!
 86.4907 +								GLimp_LogComment(va("----- Rendering shadowCube side: %i -----\n", cubeSide));
 86.4908 +							}
 86.4909 +
 86.4910 +							R_AttachFBOTexture2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + cubeSide,
 86.4911 +												 tr.shadowCubeFBOImage[light->shadowLOD]->texnum, 0);
 86.4912 +							if(!r_ignoreGLErrors->integer)
 86.4913 +							{
 86.4914 +								R_CheckFBO(tr.shadowMapFBO[light->shadowLOD]);
 86.4915 +							}
 86.4916 +
 86.4917 +							// set the window clipping
 86.4918 +							GL_Viewport(0, 0, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.4919 +							GL_Scissor(0, 0, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.4920 +
 86.4921 +							qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 86.4922 +
 86.4923 +							switch (cubeSide)
 86.4924 +							{
 86.4925 +								case 0:
 86.4926 +								{
 86.4927 +									// view parameters
 86.4928 +									VectorSet(angles, 0, 0, 90);
 86.4929 +
 86.4930 +									// projection parameters
 86.4931 +									flipX = qfalse;
 86.4932 +									flipY = qfalse;
 86.4933 +									break;
 86.4934 +								}
 86.4935 +
 86.4936 +								case 1:
 86.4937 +								{
 86.4938 +									VectorSet(angles, 0, 180, 90);
 86.4939 +									flipX = qtrue;
 86.4940 +									flipY = qtrue;
 86.4941 +									break;
 86.4942 +								}
 86.4943 +
 86.4944 +								case 2:
 86.4945 +								{
 86.4946 +									VectorSet(angles, 0, 90, 0);
 86.4947 +									flipX = qfalse;
 86.4948 +									flipY = qfalse;
 86.4949 +									break;
 86.4950 +								}
 86.4951 +
 86.4952 +								case 3:
 86.4953 +								{
 86.4954 +									VectorSet(angles, 0, -90, 0);
 86.4955 +									flipX = qtrue;
 86.4956 +									flipY = qtrue;
 86.4957 +									break;
 86.4958 +								}
 86.4959 +
 86.4960 +								case 4:
 86.4961 +								{
 86.4962 +									VectorSet(angles, -90, 90, 0);
 86.4963 +									flipX = qfalse;
 86.4964 +									flipY = qfalse;
 86.4965 +									break;
 86.4966 +								}
 86.4967 +
 86.4968 +								case 5:
 86.4969 +								{
 86.4970 +									VectorSet(angles, 90, 90, 0);
 86.4971 +									flipX = qtrue;
 86.4972 +									flipY = qtrue;
 86.4973 +									break;
 86.4974 +								}
 86.4975 +
 86.4976 +								default:
 86.4977 +								{
 86.4978 +									// shut up compiler
 86.4979 +									VectorSet(angles, 0, 0, 0);
 86.4980 +									flipX = qfalse;
 86.4981 +									flipY = qfalse;
 86.4982 +									break;
 86.4983 +								}
 86.4984 +							}
 86.4985 +
 86.4986 +							// Quake -> OpenGL view matrix from light perspective
 86.4987 +							MatrixFromAngles(rotationMatrix, angles[PITCH], angles[YAW], angles[ROLL]);
 86.4988 +							MatrixSetupTransformFromRotation(transformMatrix, rotationMatrix, light->origin);
 86.4989 +							MatrixAffineInverse(transformMatrix, viewMatrix);
 86.4990 +
 86.4991 +							// convert from our coordinate system (looking down X)
 86.4992 +							// to OpenGL's coordinate system (looking down -Z)
 86.4993 +							MatrixMultiply(quakeToOpenGLMatrix, viewMatrix, light->viewMatrix);
 86.4994 +
 86.4995 +							// OpenGL projection matrix
 86.4996 +							fovX = 90;
 86.4997 +							fovY = 90;	//R_CalcFov(fovX, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.4998 +
 86.4999 +							zNear = 1.0;
 86.5000 +							zFar = light->sphereRadius;
 86.5001 +
 86.5002 +							if(!flipX)
 86.5003 +							{
 86.5004 +								xMax = zNear * tan(fovX * M_PI / 360.0f);
 86.5005 +								xMin = -xMax;
 86.5006 +							}
 86.5007 +							else
 86.5008 +							{
 86.5009 +								xMin = zNear * tan(fovX * M_PI / 360.0f);
 86.5010 +								xMax = -xMin;
 86.5011 +							}
 86.5012 +
 86.5013 +							if(!flipY)
 86.5014 +							{
 86.5015 +								yMax = zNear * tan(fovY * M_PI / 360.0f);
 86.5016 +								yMin = -yMax;
 86.5017 +							}
 86.5018 +							else
 86.5019 +							{
 86.5020 +								yMin = zNear * tan(fovY * M_PI / 360.0f);
 86.5021 +								yMax = -yMin;
 86.5022 +							}
 86.5023 +
 86.5024 +							width = xMax - xMin;
 86.5025 +							height = yMax - yMin;
 86.5026 +							depth = zFar - zNear;
 86.5027 +
 86.5028 +							proj = light->projectionMatrix;
 86.5029 +							proj[0] = (2 * zNear) / width;
 86.5030 +							proj[4] = 0;
 86.5031 +							proj[8] = (xMax + xMin) / width;
 86.5032 +							proj[12] = 0;
 86.5033 +							proj[1] = 0;
 86.5034 +							proj[5] = (2 * zNear) / height;
 86.5035 +							proj[9] = (yMax + yMin) / height;
 86.5036 +							proj[13] = 0;
 86.5037 +							proj[2] = 0;
 86.5038 +							proj[6] = 0;
 86.5039 +							proj[10] = -(zFar + zNear) / depth;
 86.5040 +							proj[14] = -(2 * zFar * zNear) / depth;
 86.5041 +							proj[3] = 0;
 86.5042 +							proj[7] = 0;
 86.5043 +							proj[11] = -1;
 86.5044 +							proj[15] = 0;
 86.5045 +
 86.5046 +							GL_LoadProjectionMatrix(light->projectionMatrix);
 86.5047 +							break;
 86.5048 +						}
 86.5049 +
 86.5050 +						case RL_PROJ:
 86.5051 +						{
 86.5052 +							GLimp_LogComment("--- Rendering projective shadowMap ---\n");
 86.5053 +
 86.5054 +							R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.shadowMapFBOImage[light->shadowLOD]->texnum, 0);
 86.5055 +							if(!r_ignoreGLErrors->integer)
 86.5056 +							{
 86.5057 +								R_CheckFBO(tr.shadowMapFBO[light->shadowLOD]);
 86.5058 +							}
 86.5059 +
 86.5060 +							// set the window clipping
 86.5061 +							GL_Viewport(0, 0, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.5062 +							GL_Scissor(0, 0, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 86.5063 +
 86.5064 +							qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 86.5065 +
 86.5066 +							GL_LoadProjectionMatrix(light->projectionMatrix);
 86.5067 +							break;
 86.5068 +						}
 86.5069 +
 86.5070 +						default:
 86.5071 +							break;
 86.5072 +					}
 86.5073 +				}
 86.5074 +
 86.5075 +				if(r_logFile->integer)
 86.5076 +				{
 86.5077 +					// don't just call LogComment, or we will get
 86.5078 +					// a call to va() every frame!
 86.5079 +					GLimp_LogComment(va("----- First Shadow Interaction: %i -----\n", iaCount));
 86.5080 +				}
 86.5081 +			}
 86.5082 +			else
 86.5083 +			{
 86.5084 +				GLimp_LogComment("--- Rendering lighting ---\n");
 86.5085 +
 86.5086 +				if(r_logFile->integer)
 86.5087 +				{
 86.5088 +					// don't just call LogComment, or we will get
 86.5089 +					// a call to va() every frame!
 86.5090 +					GLimp_LogComment(va("----- First Light Interaction: %i -----\n", iaCount));
 86.5091 +				}
 86.5092 +
 86.5093 +				// finally draw light
 86.5094 +				R_BindFBO(tr.deferredRenderFBO);
 86.5095 +
 86.5096 +				// set the window clipping
 86.5097 +				GL_Viewport(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
 86.5098 +							backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
 86.5099 +
 86.5100 +				//GL_Scissor(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
 86.5101 +				//        backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
 86.5102 +
 86.5103 +				// set light scissor to reduce fillrate
 86.5104 +				GL_Scissor(ia->scissorX, ia->scissorY, ia->scissorWidth, ia->scissorHeight);
 86.5105 +
 86.5106 +				// restore camera matrices
 86.5107 +				GL_LoadProjectionMatrix(backEnd.viewParms.projectionMatrix);
 86.5108 +				GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.5109 +
 86.5110 +				switch (light->l.rlType)
 86.5111 +				{
 86.5112 +					case RL_OMNI:
 86.5113 +					{
 86.5114 +						// reset light view and projection matrices
 86.5115 +						MatrixAffineInverse(light->transformMatrix, light->viewMatrix);
 86.5116 +						MatrixSetupScale(light->projectionMatrix, 1.0 / light->l.radius[0], 1.0 / light->l.radius[1],
 86.5117 +										 1.0 / light->l.radius[2]);
 86.5118 +
 86.5119 +						// build the attenuation matrix
 86.5120 +						MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.5);	// bias
 86.5121 +						MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 0.5);	// scale
 86.5122 +						MatrixMultiply2(light->attenuationMatrix, light->projectionMatrix);	// light projection (frustum)
 86.5123 +						MatrixMultiply2(light->attenuationMatrix, light->viewMatrix);
 86.5124 +						break;
 86.5125 +					}
 86.5126 +
 86.5127 +					case RL_PROJ:
 86.5128 +					{
 86.5129 +						// build the attenuation matrix
 86.5130 +						MatrixSetupTranslation(light->attenuationMatrix, 0.5, 0.5, 0.0);	// bias
 86.5131 +						MatrixMultiplyScale(light->attenuationMatrix, 0.5, 0.5, 1.0 / Q_min(light->l.distFar - light->l.distNear, 1.0));	// scale
 86.5132 +						MatrixMultiply2(light->attenuationMatrix, light->projectionMatrix);
 86.5133 +						MatrixMultiply2(light->attenuationMatrix, light->viewMatrix);
 86.5134 +						break;
 86.5135 +					}
 86.5136 +
 86.5137 +					default:
 86.5138 +						break;
 86.5139 +				}
 86.5140 +
 86.5141 +				// update uniforms
 86.5142 +				VectorCopy(backEnd.viewParms.orientation.origin, viewOrigin);
 86.5143 +
 86.5144 +				// copy frustum planes for pixel shader
 86.5145 +				for(i = 0; i < 6; i++)
 86.5146 +				{
 86.5147 +					frust = &light->frustum[i];
 86.5148 +
 86.5149 +					VectorCopy(frust->normal, lightFrustum[i]);
 86.5150 +					lightFrustum[i][3] = frust->dist;
 86.5151 +				}
 86.5152 +
 86.5153 +				// set 2D virtual screen size
 86.5154 +				GL_PushMatrix();
 86.5155 +				MatrixSetupOrthogonalProjection(ortho, backEnd.viewParms.viewportX,
 86.5156 +												backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
 86.5157 +												backEnd.viewParms.viewportY,
 86.5158 +												backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight, -99999, 99999);
 86.5159 +				GL_LoadProjectionMatrix(ortho);
 86.5160 +				GL_LoadModelViewMatrix(matrixIdentity);
 86.5161 +
 86.5162 +				// last interaction of current light
 86.5163 +				lightShader = light->shader;
 86.5164 +				attenuationZStage = lightShader->stages[0];
 86.5165 +
 86.5166 +				for(j = 1; j < MAX_SHADER_STAGES; j++)
 86.5167 +				{
 86.5168 +					attenuationXYStage = lightShader->stages[j];
 86.5169 +
 86.5170 +					if(!attenuationXYStage)
 86.5171 +					{
 86.5172 +						break;
 86.5173 +					}
 86.5174 +
 86.5175 +					if(attenuationXYStage->type != ST_ATTENUATIONMAP_XY)
 86.5176 +					{
 86.5177 +						continue;
 86.5178 +					}
 86.5179 +
 86.5180 +					if(!RB_EvalExpression(&attenuationXYStage->ifExp, 1.0))
 86.5181 +					{
 86.5182 +						continue;
 86.5183 +					}
 86.5184 +
 86.5185 +					Tess_ComputeColor(attenuationXYStage);
 86.5186 +					R_ComputeFinalAttenuation(attenuationXYStage, light);
 86.5187 +
 86.5188 +					if(light->l.rlType == RL_OMNI)
 86.5189 +					{
 86.5190 +						// TODO
 86.5191 +					}
 86.5192 +					else if(light->l.rlType == RL_PROJ)
 86.5193 +					{
 86.5194 +
 86.5195 +						GL_BindProgram(&tr.deferredShadowingShader_proj);
 86.5196 +
 86.5197 +						GL_State(GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE_MINUS_SRC_COLOR);
 86.5198 +						GL_Cull(CT_TWO_SIDED);
 86.5199 +
 86.5200 +						// set uniforms
 86.5201 +						VectorCopy(light->origin, lightOrigin);
 86.5202 +						VectorCopy(tess.svars.color, lightColor);
 86.5203 +						shadowCompare = !light->l.noShadows && light->shadowLOD >= 0;
 86.5204 +
 86.5205 +						GLSL_SetUniform_LightOrigin(&tr.deferredShadowingShader_proj, lightOrigin);
 86.5206 +						GLSL_SetUniform_LightColor(&tr.deferredShadowingShader_proj, lightColor);
 86.5207 +						GLSL_SetUniform_LightRadius(&tr.deferredShadowingShader_proj, light->sphereRadius);
 86.5208 +						GLSL_SetUniform_LightAttenuationMatrix(&tr.deferredShadowingShader_proj, light->attenuationMatrix2);
 86.5209 +						qglUniform4fvARB(tr.deferredShadowingShader_proj.u_LightFrustum, 6, &lightFrustum[0][0]);
 86.5210 +
 86.5211 +						GLSL_SetUniform_ShadowMatrix(&tr.deferredShadowingShader_proj, light->attenuationMatrix);
 86.5212 +						GLSL_SetUniform_ShadowCompare(&tr.deferredShadowingShader_proj, shadowCompare);
 86.5213 +
 86.5214 +						GLSL_SetUniform_ModelViewProjectionMatrix(&tr.deferredShadowingShader_proj, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.5215 +						GLSL_SetUniform_UnprojectMatrix(&tr.deferredShadowingShader_proj, backEnd.viewParms.unprojectionMatrix);
 86.5216 +
 86.5217 +						GLSL_SetUniform_PortalClipping(&tr.deferredShadowingShader_proj, backEnd.viewParms.isPortal);
 86.5218 +						if(backEnd.viewParms.isPortal)
 86.5219 +						{
 86.5220 +							float           plane[4];
 86.5221 +
 86.5222 +							// clipping plane in world space
 86.5223 +							plane[0] = backEnd.viewParms.portalPlane.normal[0];
 86.5224 +							plane[1] = backEnd.viewParms.portalPlane.normal[1];
 86.5225 +							plane[2] = backEnd.viewParms.portalPlane.normal[2];
 86.5226 +							plane[3] = backEnd.viewParms.portalPlane.dist;
 86.5227 +
 86.5228 +							GLSL_SetUniform_PortalPlane(&tr.deferredShadowingShader_proj, plane);
 86.5229 +						}
 86.5230 +
 86.5231 +						// bind u_DepthMap
 86.5232 +						GL_SelectTexture(0);
 86.5233 +						GL_Bind(tr.depthRenderImage);
 86.5234 +
 86.5235 +						// bind u_AttenuationMapXY
 86.5236 +						GL_SelectTexture(1);
 86.5237 +						BindAnimatedImage(&attenuationXYStage->bundle[TB_COLORMAP]);
 86.5238 +
 86.5239 +						// bind u_AttenuationMapZ
 86.5240 +						GL_SelectTexture(2);
 86.5241 +						BindAnimatedImage(&attenuationZStage->bundle[TB_COLORMAP]);
 86.5242 +
 86.5243 +						// bind u_ShadowMap
 86.5244 +						if(shadowCompare)
 86.5245 +						{
 86.5246 +							GL_SelectTexture(3);
 86.5247 +							GL_Bind(tr.shadowMapFBOImage[light->shadowLOD]);
 86.5248 +						}
 86.5249 +
 86.5250 +						// draw lighting
 86.5251 +						VectorSet4(quadVerts[0], ia->scissorX, ia->scissorY, 0, 1);
 86.5252 +						VectorSet4(quadVerts[1], ia->scissorX + ia->scissorWidth - 1, ia->scissorY, 0, 1);
 86.5253 +						VectorSet4(quadVerts[2], ia->scissorX + ia->scissorWidth - 1, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.5254 +						VectorSet4(quadVerts[3], ia->scissorX, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.5255 +						Tess_InstantQuad(quadVerts);
 86.5256 +					}
 86.5257 +					else
 86.5258 +					{
 86.5259 +						// TODO
 86.5260 +					}
 86.5261 +
 86.5262 +					// end of lighting
 86.5263 +					GL_PopMatrix();
 86.5264 +
 86.5265 +					R_BindNullFBO();
 86.5266 +				}
 86.5267 +			}
 86.5268 +		}						// end if(iaCount == iaFirst)
 86.5269 +
 86.5270 +		if(drawShadows)
 86.5271 +		{
 86.5272 +			if(entity->e.renderfx & (RF_NOSHADOW | RF_DEPTHHACK))
 86.5273 +			{
 86.5274 +				goto skipInteraction;
 86.5275 +			}
 86.5276 +
 86.5277 +			if(shader->isSky)
 86.5278 +			{
 86.5279 +				goto skipInteraction;
 86.5280 +			}
 86.5281 +
 86.5282 +			if(shader->sort > SS_OPAQUE)
 86.5283 +			{
 86.5284 +				goto skipInteraction;
 86.5285 +			}
 86.5286 +
 86.5287 +			if(shader->noShadows || light->l.noShadows || light->shadowLOD < 0)
 86.5288 +			{
 86.5289 +				goto skipInteraction;
 86.5290 +			}
 86.5291 +
 86.5292 +			if(light->l.inverseShadows && (entity == &tr.worldEntity))
 86.5293 +			{
 86.5294 +				// this light only casts shadows by its player and their items
 86.5295 +				goto skipInteraction;
 86.5296 +			}
 86.5297 +
 86.5298 +			if(ia->type == IA_LIGHTONLY)
 86.5299 +			{
 86.5300 +				goto skipInteraction;
 86.5301 +			}
 86.5302 +
 86.5303 +			if(light->l.rlType == RL_OMNI && !(ia->cubeSideBits & (1 << cubeSide)))
 86.5304 +			{
 86.5305 +				goto skipInteraction;
 86.5306 +			}
 86.5307 +
 86.5308 +			switch (light->l.rlType)
 86.5309 +			{
 86.5310 +				case RL_OMNI:
 86.5311 +				case RL_PROJ:
 86.5312 +				{
 86.5313 +					if(light == oldLight && entity == oldEntity && (alphaTest ? shader == oldShader : alphaTest == oldAlphaTest))
 86.5314 +					{
 86.5315 +						if(r_logFile->integer)
 86.5316 +						{
 86.5317 +							// don't just call LogComment, or we will get
 86.5318 +							// a call to va() every frame!
 86.5319 +							GLimp_LogComment(va("----- Batching Shadow Interaction: %i -----\n", iaCount));
 86.5320 +						}
 86.5321 +
 86.5322 +						// fast path, same as previous
 86.5323 +						rb_surfaceTable[*surface] (surface);
 86.5324 +						goto nextInteraction;
 86.5325 +					}
 86.5326 +					else
 86.5327 +					{
 86.5328 +						if(oldLight)
 86.5329 +						{
 86.5330 +							// draw the contents of the last shader batch
 86.5331 +							Tess_End();
 86.5332 +						}
 86.5333 +
 86.5334 +						if(r_logFile->integer)
 86.5335 +						{
 86.5336 +							// don't just call LogComment, or we will get
 86.5337 +							// a call to va() every frame!
 86.5338 +							GLimp_LogComment(va("----- Beginning Shadow Interaction: %i -----\n", iaCount));
 86.5339 +						}
 86.5340 +
 86.5341 +						// we don't need tangent space calculations here
 86.5342 +						Tess_Begin(Tess_StageIteratorShadowFill, shader, light->shader, qtrue, qfalse, -1);
 86.5343 +					}
 86.5344 +					break;
 86.5345 +				}
 86.5346 +
 86.5347 +				default:
 86.5348 +					break;
 86.5349 +			}
 86.5350 +		}
 86.5351 +		else
 86.5352 +		{
 86.5353 +			// jump to !ia->next
 86.5354 +			goto nextInteraction;
 86.5355 +		}
 86.5356 +
 86.5357 +		// change the modelview matrix if needed
 86.5358 +		if(entity != oldEntity)
 86.5359 +		{
 86.5360 +			depthRange = qfalse;
 86.5361 +
 86.5362 +			if(entity != &tr.worldEntity)
 86.5363 +			{
 86.5364 +				// set up the transformation matrix
 86.5365 +				if(drawShadows)
 86.5366 +				{
 86.5367 +					R_RotateEntityForLight(entity, light, &backEnd.orientation);
 86.5368 +				}
 86.5369 +				else
 86.5370 +				{
 86.5371 +					R_RotateEntityForViewParms(entity, &backEnd.viewParms, &backEnd.orientation);
 86.5372 +				}
 86.5373 +
 86.5374 +				if(entity->e.renderfx & RF_DEPTHHACK)
 86.5375 +				{
 86.5376 +					// hack the depth range to prevent view model from poking into walls
 86.5377 +					depthRange = qtrue;
 86.5378 +				}
 86.5379 +			}
 86.5380 +			else
 86.5381 +			{
 86.5382 +				// set up the transformation matrix
 86.5383 +				if(drawShadows)
 86.5384 +				{
 86.5385 +					Com_Memset(&backEnd.orientation, 0, sizeof(backEnd.orientation));
 86.5386 +
 86.5387 +					backEnd.orientation.axis[0][0] = 1;
 86.5388 +					backEnd.orientation.axis[1][1] = 1;
 86.5389 +					backEnd.orientation.axis[2][2] = 1;
 86.5390 +					VectorCopy(light->l.origin, backEnd.orientation.viewOrigin);
 86.5391 +
 86.5392 +					MatrixIdentity(backEnd.orientation.transformMatrix);
 86.5393 +					//MatrixAffineInverse(backEnd.orientation.transformMatrix, backEnd.orientation.viewMatrix);
 86.5394 +					MatrixMultiply(light->viewMatrix, backEnd.orientation.transformMatrix, backEnd.orientation.viewMatrix);
 86.5395 +					MatrixCopy(backEnd.orientation.viewMatrix, backEnd.orientation.modelViewMatrix);
 86.5396 +				}
 86.5397 +				else
 86.5398 +				{
 86.5399 +					// transform by the camera placement
 86.5400 +					backEnd.orientation = backEnd.viewParms.world;
 86.5401 +				}
 86.5402 +			}
 86.5403 +
 86.5404 +			GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.5405 +
 86.5406 +			// change depthrange if needed
 86.5407 +			if(oldDepthRange != depthRange)
 86.5408 +			{
 86.5409 +				if(depthRange)
 86.5410 +				{
 86.5411 +					qglDepthRange(0, 0.3);
 86.5412 +				}
 86.5413 +				else
 86.5414 +				{
 86.5415 +					qglDepthRange(0, 1);
 86.5416 +				}
 86.5417 +				oldDepthRange = depthRange;
 86.5418 +			}
 86.5419 +		}
 86.5420 +
 86.5421 +		if(drawShadows)
 86.5422 +		{
 86.5423 +			switch (light->l.rlType)
 86.5424 +			{
 86.5425 +				case RL_OMNI:
 86.5426 +				case RL_PROJ:
 86.5427 +				{
 86.5428 +					// add the triangles for this surface
 86.5429 +					rb_surfaceTable[*surface] (surface);
 86.5430 +					break;
 86.5431 +				}
 86.5432 +
 86.5433 +				default:
 86.5434 +					break;
 86.5435 +			}
 86.5436 +		}
 86.5437 +		else
 86.5438 +		{
 86.5439 +			// DO NOTHING
 86.5440 +			//rb_surfaceTable[*surface] (surface, ia->numLightIndexes, ia->lightIndexes, 0, NULL);
 86.5441 +		}
 86.5442 +
 86.5443 +	  nextInteraction:
 86.5444 +
 86.5445 +		// remember values
 86.5446 +		oldLight = light;
 86.5447 +		oldEntity = entity;
 86.5448 +		oldShader = shader;
 86.5449 +		oldAlphaTest = alphaTest;
 86.5450 +
 86.5451 +	  skipInteraction:
 86.5452 +		if(!ia->next)
 86.5453 +		{
 86.5454 +			// if ia->next does not point to any other interaction then
 86.5455 +			// this is the last interaction of the current light
 86.5456 +
 86.5457 +			if(r_logFile->integer)
 86.5458 +			{
 86.5459 +				// don't just call LogComment, or we will get
 86.5460 +				// a call to va() every frame!
 86.5461 +				GLimp_LogComment(va("----- Last Interaction: %i -----\n", iaCount));
 86.5462 +			}
 86.5463 +
 86.5464 +			if(drawShadows)
 86.5465 +			{
 86.5466 +				// draw the contents of the last shader batch
 86.5467 +				Tess_End();
 86.5468 +
 86.5469 +				switch (light->l.rlType)
 86.5470 +				{
 86.5471 +					case RL_OMNI:
 86.5472 +					{
 86.5473 +						if(cubeSide == 5)
 86.5474 +						{
 86.5475 +							cubeSide = 0;
 86.5476 +							drawShadows = qfalse;
 86.5477 +						}
 86.5478 +						else
 86.5479 +						{
 86.5480 +							cubeSide++;
 86.5481 +						}
 86.5482 +
 86.5483 +						// jump back to first interaction of this light
 86.5484 +						ia = &backEnd.viewParms.interactions[iaFirst];
 86.5485 +						iaCount = iaFirst;
 86.5486 +						break;
 86.5487 +					}
 86.5488 +
 86.5489 +					case RL_PROJ:
 86.5490 +					{
 86.5491 +						// jump back to first interaction of this light and start lighting
 86.5492 +						ia = &backEnd.viewParms.interactions[iaFirst];
 86.5493 +						iaCount = iaFirst;
 86.5494 +						drawShadows = qfalse;
 86.5495 +						break;
 86.5496 +					}
 86.5497 +
 86.5498 +					default:
 86.5499 +						break;
 86.5500 +				}
 86.5501 +			}
 86.5502 +			else
 86.5503 +			{
 86.5504 +#ifdef VOLUMETRIC_LIGHTING
 86.5505 +				// draw the light volume if needed
 86.5506 +				if(light->shader->volumetricLight)
 86.5507 +				{
 86.5508 +					Render_lightVolume(light);
 86.5509 +				}
 86.5510 +#endif
 86.5511 +
 86.5512 +				if(iaCount < (backEnd.viewParms.numInteractions - 1))
 86.5513 +				{
 86.5514 +					// jump to next interaction and start shadowing
 86.5515 +					ia++;
 86.5516 +					iaCount++;
 86.5517 +					iaFirst = iaCount;
 86.5518 +					drawShadows = qtrue;
 86.5519 +				}
 86.5520 +				else
 86.5521 +				{
 86.5522 +					// increase last time to leave for loop
 86.5523 +					iaCount++;
 86.5524 +				}
 86.5525 +			}
 86.5526 +
 86.5527 +			// force updates
 86.5528 +			oldLight = NULL;
 86.5529 +			oldEntity = NULL;
 86.5530 +			oldShader = NULL;
 86.5531 +		}
 86.5532 +		else
 86.5533 +		{
 86.5534 +			// just continue
 86.5535 +			ia = ia->next;
 86.5536 +			iaCount++;
 86.5537 +		}
 86.5538 +	}
 86.5539 +
 86.5540 +	// go back to the world modelview matrix
 86.5541 +	GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.5542 +	if(depthRange)
 86.5543 +	{
 86.5544 +		qglDepthRange(0, 1);
 86.5545 +	}
 86.5546 +
 86.5547 +	// reset scissor clamping
 86.5548 +	GL_Scissor(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
 86.5549 +			   backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight);
 86.5550 +
 86.5551 +	// reset clear color
 86.5552 +	GL_ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 86.5553 +
 86.5554 +	GL_CheckErrors();
 86.5555 +
 86.5556 +	if(r_speeds->integer == 9)
 86.5557 +	{
 86.5558 +		qglFinish();
 86.5559 +		endTime = ri.Milliseconds();
 86.5560 +		backEnd.pc.c_deferredLightingTime = endTime - startTime;
 86.5561 +	}
 86.5562 +}
 86.5563 +
 86.5564 +void RB_RenderScreenSpaceAmbientOcclusion(qboolean deferred)
 86.5565 +{
 86.5566 +#if 0
 86.5567 +//  int             i;
 86.5568 +//  vec3_t          viewOrigin;
 86.5569 +//  static vec3_t   jitter[32];
 86.5570 +//  static qboolean jitterInit = qfalse;
 86.5571 +//  matrix_t        projectMatrix;
 86.5572 +	matrix_t        ortho;
 86.5573 +
 86.5574 +	GLimp_LogComment("--- RB_RenderScreenSpaceAmbientOcclusion ---\n");
 86.5575 +
 86.5576 +	if(backEnd.refdef.rdflags & RDF_NOWORLDMODEL)
 86.5577 +		return;
 86.5578 +
 86.5579 +	if(!r_screenSpaceAmbientOcclusion->integer)
 86.5580 +		return;
 86.5581 +
 86.5582 +	// enable shader, set arrays
 86.5583 +	GL_BindProgram(&tr.screenSpaceAmbientOcclusionShader);
 86.5584 +
 86.5585 +	GL_State(GLS_DEPTHTEST_DISABLE);	// | GLS_DEPTHMASK_TRUE);
 86.5586 +	GL_Cull(CT_TWO_SIDED);
 86.5587 +
 86.5588 +	qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorWhite);
 86.5589 +
 86.5590 +	// set uniforms
 86.5591 +	/*
 86.5592 +	   VectorCopy(backEnd.viewParms.orientation.origin, viewOrigin); // in world space
 86.5593 +
 86.5594 +	   if(!jitterInit)
 86.5595 +	   {
 86.5596 +	   for(i = 0; i < 32; i++)
 86.5597 +	   {
 86.5598 +	   float *jit = &jitter[i][0];
 86.5599 +
 86.5600 +	   float rad = crandom() * 1024.0f; // FIXME radius;
 86.5601 +	   float a = crandom() * M_PI * 2;
 86.5602 +	   float b = crandom() * M_PI * 2;
 86.5603 +
 86.5604 +	   jit[0] = rad * sin(a) * cos(b);
 86.5605 +	   jit[1] = rad * sin(a) * sin(b);
 86.5606 +	   jit[2] = rad * cos(a);
 86.5607 +	   }
 86.5608 +
 86.5609 +	   jitterInit = qtrue;
 86.5610 +	   }
 86.5611 +
 86.5612 +
 86.5613 +	   MatrixCopy(backEnd.viewParms.projectionMatrix, projectMatrix);
 86.5614 +	   MatrixInverse(projectMatrix);
 86.5615 +
 86.5616 +	   qglUniform3fARB(tr.screenSpaceAmbientOcclusionShader.u_ViewOrigin, viewOrigin[0], viewOrigin[1], viewOrigin[2]);
 86.5617 +	   qglUniform3fvARB(tr.screenSpaceAmbientOcclusionShader.u_SSAOJitter, 32, &jitter[0][0]);
 86.5618 +	   qglUniform1fARB(tr.screenSpaceAmbientOcclusionShader.u_SSAORadius, r_screenSpaceAmbientOcclusionRadius->value);
 86.5619 +
 86.5620 +	   qglUniformMatrix4fvARB(tr.screenSpaceAmbientOcclusionShader.u_UnprojectMatrix, 1, GL_FALSE, backEnd.viewParms.unprojectionMatrix);
 86.5621 +	   qglUniformMatrix4fvARB(tr.screenSpaceAmbientOcclusionShader.u_ProjectMatrix, 1, GL_FALSE, projectMatrix);
 86.5622 +	 */
 86.5623 +
 86.5624 +	// capture current color buffer for u_CurrentMap
 86.5625 +	GL_SelectTexture(0);
 86.5626 +	GL_Bind(tr.currentRenderImage);
 86.5627 +	qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.currentRenderImage->uploadWidth, tr.currentRenderImage->uploadHeight);
 86.5628 +
 86.5629 +	// bind u_DepthMap
 86.5630 +	GL_SelectTexture(1);
 86.5631 +	if(deferred)
 86.5632 +	{
 86.5633 +		GL_Bind(tr.deferredPositionFBOImage);
 86.5634 +	}
 86.5635 +	else
 86.5636 +	{
 86.5637 +		GL_Bind(tr.depthRenderImage);
 86.5638 +		qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.depthRenderImage->uploadWidth, tr.depthRenderImage->uploadHeight);
 86.5639 +	}
 86.5640 +
 86.5641 +	// set 2D virtual screen size
 86.5642 +	GL_PushMatrix();
 86.5643 +	MatrixSetupOrthogonalProjection(ortho, backEnd.viewParms.viewportX,
 86.5644 +									backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
 86.5645 +									backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
 86.5646 +									-99999, 99999);
 86.5647 +	GL_LoadProjectionMatrix(ortho);
 86.5648 +	GL_LoadModelViewMatrix(matrixIdentity);
 86.5649 +
 86.5650 +	GLSL_SetUniform_ModelViewProjectionMatrix(&tr.screenSpaceAmbientOcclusionShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.5651 +
 86.5652 +	// draw viewport
 86.5653 +	Tess_InstantQuad(backEnd.viewParms.viewportVerts);
 86.5654 +
 86.5655 +	// go back to 3D
 86.5656 +	GL_PopMatrix();
 86.5657 +
 86.5658 +	GL_CheckErrors();
 86.5659 +#endif
 86.5660 +}
 86.5661 +
 86.5662 +void RB_RenderDepthOfField()
 86.5663 +{
 86.5664 +	matrix_t        ortho;
 86.5665 +
 86.5666 +	GLimp_LogComment("--- RB_RenderDepthOfField ---\n");
 86.5667 +
 86.5668 +	if(backEnd.refdef.rdflags & RDF_NOWORLDMODEL)
 86.5669 +		return;
 86.5670 +
 86.5671 +	if(!r_depthOfField->integer)
 86.5672 +		return;
 86.5673 +
 86.5674 +	// enable shader, set arrays
 86.5675 +	GL_BindProgram(&tr.depthOfFieldShader);
 86.5676 +
 86.5677 +	GL_State(GLS_DEPTHTEST_DISABLE);	// | GLS_DEPTHMASK_TRUE);
 86.5678 +	GL_Cull(CT_TWO_SIDED);
 86.5679 +
 86.5680 +	qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorWhite);
 86.5681 +
 86.5682 +	// set uniforms
 86.5683 +
 86.5684 +	// capture current color buffer for u_CurrentMap
 86.5685 +	GL_SelectTexture(0);
 86.5686 +	if(r_deferredShading->integer && glConfig.framebufferObjectAvailable && glConfig.textureFloatAvailable &&
 86.5687 +				   glConfig.drawBuffersAvailable && glConfig.maxDrawBuffers >= 4)
 86.5688 +	{
 86.5689 +		GL_Bind(tr.deferredRenderFBOImage);
 86.5690 +	}
 86.5691 +	else if(r_hdrRendering->integer && glConfig.framebufferObjectAvailable && glConfig.textureFloatAvailable)
 86.5692 +	{
 86.5693 +		GL_Bind(tr.deferredRenderFBOImage);
 86.5694 +	}
 86.5695 +	else
 86.5696 +	{
 86.5697 +		GL_Bind(tr.currentRenderImage);
 86.5698 +		qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.currentRenderImage->uploadWidth, tr.currentRenderImage->uploadHeight);
 86.5699 +	}
 86.5700 +
 86.5701 +	// bind u_DepthMap
 86.5702 +	GL_SelectTexture(1);
 86.5703 +	if(r_deferredShading->integer && glConfig.framebufferObjectAvailable && glConfig.textureFloatAvailable &&
 86.5704 +			   glConfig.drawBuffersAvailable && glConfig.maxDrawBuffers >= 4)
 86.5705 +	{
 86.5706 +		GL_Bind(tr.depthRenderImage);
 86.5707 +	}
 86.5708 +	else if(r_hdrRendering->integer && glConfig.framebufferObjectAvailable && glConfig.textureFloatAvailable)
 86.5709 +	{
 86.5710 +		GL_Bind(tr.depthRenderImage);
 86.5711 +	}
 86.5712 +	else
 86.5713 +	{
 86.5714 +		// depth texture is not bound to a FBO
 86.5715 +		GL_Bind(tr.depthRenderImage);
 86.5716 +		qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.depthRenderImage->uploadWidth, tr.depthRenderImage->uploadHeight);
 86.5717 +	}
 86.5718 +
 86.5719 +	// set 2D virtual screen size
 86.5720 +	GL_PushMatrix();
 86.5721 +	MatrixSetupOrthogonalProjection(ortho, backEnd.viewParms.viewportX,
 86.5722 +									backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
 86.5723 +									backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
 86.5724 +									-99999, 99999);
 86.5725 +	GL_LoadProjectionMatrix(ortho);
 86.5726 +	GL_LoadModelViewMatrix(matrixIdentity);
 86.5727 +
 86.5728 +	GLSL_SetUniform_ModelViewProjectionMatrix(&tr.depthOfFieldShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.5729 +
 86.5730 +	// draw viewport
 86.5731 +	Tess_InstantQuad(backEnd.viewParms.viewportVerts);
 86.5732 +
 86.5733 +	// go back to 3D
 86.5734 +	GL_PopMatrix();
 86.5735 +
 86.5736 +	GL_CheckErrors();
 86.5737 +}
 86.5738 +
 86.5739 +void RB_RenderUniformFog()
 86.5740 +{
 86.5741 +	vec3_t          viewOrigin;
 86.5742 +	float           fogDensity;
 86.5743 +	vec3_t          fogColor;
 86.5744 +	matrix_t        ortho;
 86.5745 +
 86.5746 +	GLimp_LogComment("--- RB_RenderUniformFog ---\n");
 86.5747 +
 86.5748 +	if(backEnd.refdef.rdflags & RDF_NOWORLDMODEL)
 86.5749 +		return;
 86.5750 +
 86.5751 +	if(r_noFog->integer)
 86.5752 +		return;
 86.5753 +
 86.5754 +	if(r_forceFog->value <= 0 && tr.fogDensity <= 0)
 86.5755 +		return;
 86.5756 +
 86.5757 +	if(r_forceFog->value <= 0 && VectorLength(tr.fogColor) <= 0)
 86.5758 +		return;
 86.5759 +
 86.5760 +	// enable shader, set arrays
 86.5761 +	GL_BindProgram(&tr.uniformFogShader);
 86.5762 +
 86.5763 +	GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA | GLS_DSTBLEND_SRC_ALPHA);
 86.5764 +	GL_Cull(CT_TWO_SIDED);
 86.5765 +
 86.5766 +	qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorWhite);
 86.5767 +
 86.5768 +	// set uniforms
 86.5769 +	VectorCopy(backEnd.viewParms.orientation.origin, viewOrigin);	// in world space
 86.5770 +
 86.5771 +	if(r_forceFog->value)
 86.5772 +	{
 86.5773 +		fogDensity = r_forceFog->value;
 86.5774 +		VectorCopy(colorMdGrey, fogColor);
 86.5775 +	}
 86.5776 +	else
 86.5777 +	{
 86.5778 +		fogDensity = tr.fogDensity;
 86.5779 +		VectorCopy(tr.fogColor, fogColor);
 86.5780 +	}
 86.5781 +
 86.5782 +	GLSL_SetUniform_ViewOrigin(&tr.uniformFogShader, viewOrigin);
 86.5783 +	qglUniform1fARB(tr.uniformFogShader.u_FogDensity, fogDensity);
 86.5784 +	qglUniform3fARB(tr.uniformFogShader.u_FogColor, fogColor[0], fogColor[1], fogColor[2]);
 86.5785 +	GLSL_SetUniform_UnprojectMatrix(&tr.uniformFogShader, backEnd.viewParms.unprojectionMatrix);
 86.5786 +
 86.5787 +	// bind u_DepthMap
 86.5788 +	GL_SelectTexture(0);
 86.5789 +	if(r_deferredShading->integer && glConfig.framebufferObjectAvailable && glConfig.textureFloatAvailable &&
 86.5790 +			   glConfig.drawBuffersAvailable && glConfig.maxDrawBuffers >= 4)
 86.5791 +	{
 86.5792 +		GL_Bind(tr.depthRenderImage);
 86.5793 +	}
 86.5794 +	else if(r_hdrRendering->integer && glConfig.framebufferObjectAvailable && glConfig.textureFloatAvailable)
 86.5795 +	{
 86.5796 +		GL_Bind(tr.depthRenderImage);
 86.5797 +	}
 86.5798 +	else
 86.5799 +	{
 86.5800 +		// depth texture is not bound to a FBO
 86.5801 +		GL_Bind(tr.depthRenderImage);
 86.5802 +		qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.depthRenderImage->uploadWidth, tr.depthRenderImage->uploadHeight);
 86.5803 +	}
 86.5804 +
 86.5805 +	// set 2D virtual screen size
 86.5806 +	GL_PushMatrix();
 86.5807 +	MatrixSetupOrthogonalProjection(ortho, backEnd.viewParms.viewportX,
 86.5808 +									backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
 86.5809 +									backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
 86.5810 +									-99999, 99999);
 86.5811 +	GL_LoadProjectionMatrix(ortho);
 86.5812 +	GL_LoadModelViewMatrix(matrixIdentity);
 86.5813 +
 86.5814 +	GLSL_SetUniform_ModelViewProjectionMatrix(&tr.uniformFogShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.5815 +
 86.5816 +	// draw viewport
 86.5817 +	Tess_InstantQuad(backEnd.viewParms.viewportVerts);
 86.5818 +
 86.5819 +	// go back to 3D
 86.5820 +	GL_PopMatrix();
 86.5821 +
 86.5822 +	GL_CheckErrors();
 86.5823 +}
 86.5824 +
 86.5825 +void RB_RenderBloom()
 86.5826 +{
 86.5827 +	int				i, j;
 86.5828 +	matrix_t        ortho;
 86.5829 +	matrix_t		modelView;
 86.5830 +
 86.5831 +	GLimp_LogComment("--- RB_RenderBloom ---\n");
 86.5832 +
 86.5833 +	if((backEnd.refdef.rdflags & (RDF_NOWORLDMODEL | RDF_NOBLOOM)) || !r_bloom->integer || backEnd.viewParms.isPortal || !glConfig.framebufferObjectAvailable)
 86.5834 +		return;
 86.5835 +
 86.5836 +	// set 2D virtual screen size
 86.5837 +	GL_PushMatrix();
 86.5838 +	MatrixSetupOrthogonalProjection(ortho, backEnd.viewParms.viewportX,
 86.5839 +									backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
 86.5840 +									backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
 86.5841 +									-99999, 99999);
 86.5842 +	GL_LoadProjectionMatrix(ortho);
 86.5843 +	MatrixIdentity(modelView);
 86.5844 +	GL_LoadModelViewMatrix(modelView);
 86.5845 +
 86.5846 +	// FIXME
 86.5847 +	//if(glConfig.hardwareType != GLHW_ATI && glConfig.hardwareType != GLHW_ATI_DX10)
 86.5848 +	{
 86.5849 +		GL_State(GLS_DEPTHTEST_DISABLE);
 86.5850 +		GL_Cull(CT_TWO_SIDED);
 86.5851 +
 86.5852 +		// render contrast downscaled to 1/4th of the screen
 86.5853 +		GL_BindProgram(&tr.contrastShader);
 86.5854 +
 86.5855 +		GL_PushMatrix();
 86.5856 +		GL_LoadModelViewMatrix(modelView);
 86.5857 +
 86.5858 +#if 1
 86.5859 +		MatrixSetupOrthogonalProjection(ortho, 0, tr.contrastRenderFBO->width, 0, tr.contrastRenderFBO->height, -99999, 99999);
 86.5860 +		GL_LoadProjectionMatrix(ortho);
 86.5861 +#endif
 86.5862 +		GLSL_SetUniform_ModelViewProjectionMatrix(&tr.contrastShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.5863 +		GL_PopMatrix();
 86.5864 +
 86.5865 +		if(r_deferredShading->integer && glConfig.framebufferObjectAvailable && glConfig.textureFloatAvailable &&
 86.5866 +						   glConfig.drawBuffersAvailable && glConfig.maxDrawBuffers >= 4)
 86.5867 +		{
 86.5868 +			if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
 86.5869 +			{
 86.5870 +				if(r_hdrKey->value <= 0)
 86.5871 +				{
 86.5872 +					float			key;
 86.5873 +
 86.5874 +					// calculation from: Perceptual Effects in Real-time Tone Mapping - Krawczyk et al.
 86.5875 +					key = 1.03 - 2.0 / (2.0 + log10f(backEnd.hdrAverageLuminance + 1.0f));
 86.5876 +					qglUniform1fARB(tr.contrastShader.u_HDRKey, key);
 86.5877 +				}
 86.5878 +				else
 86.5879 +				{
 86.5880 +					qglUniform1fARB(tr.contrastShader.u_HDRKey, r_hdrKey->value);
 86.5881 +				}
 86.5882 +
 86.5883 +				qglUniform1fARB(tr.contrastShader.u_HDRAverageLuminance, backEnd.hdrAverageLuminance);
 86.5884 +				qglUniform1fARB(tr.contrastShader.u_HDRMaxLuminance, backEnd.hdrMaxLuminance);
 86.5885 +			}
 86.5886 +
 86.5887 +			GL_SelectTexture(0);
 86.5888 +			GL_Bind(tr.downScaleFBOImage_quarter);
 86.5889 +		}
 86.5890 +		else if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
 86.5891 +		{
 86.5892 +			if(r_hdrKey->value <= 0)
 86.5893 +			{
 86.5894 +				float			key;
 86.5895 +
 86.5896 +				// calculation from: Perceptual Effects in Real-time Tone Mapping - Krawczyk et al.
 86.5897 +				key = 1.03 - 2.0 / (2.0 + log10f(backEnd.hdrAverageLuminance + 1.0f));
 86.5898 +				qglUniform1fARB(tr.contrastShader.u_HDRKey, key);
 86.5899 +			}
 86.5900 +			else
 86.5901 +			{
 86.5902 +				qglUniform1fARB(tr.contrastShader.u_HDRKey, r_hdrKey->value);
 86.5903 +			}
 86.5904 +
 86.5905 +			qglUniform1fARB(tr.contrastShader.u_HDRAverageLuminance, backEnd.hdrAverageLuminance);
 86.5906 +			qglUniform1fARB(tr.contrastShader.u_HDRMaxLuminance, backEnd.hdrMaxLuminance);
 86.5907 +
 86.5908 +			GL_SelectTexture(0);
 86.5909 +			GL_Bind(tr.downScaleFBOImage_quarter);
 86.5910 +		}
 86.5911 +		else
 86.5912 +		{
 86.5913 +			GL_SelectTexture(0);
 86.5914 +			//GL_Bind(tr.downScaleFBOImage_quarter);
 86.5915 +			GL_Bind(tr.currentRenderImage);
 86.5916 +			qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.currentRenderImage->uploadWidth,
 86.5917 +												 tr.currentRenderImage->uploadHeight);
 86.5918 +		}
 86.5919 +
 86.5920 +		R_BindFBO(tr.contrastRenderFBO);
 86.5921 +		GL_ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 86.5922 +		qglClear(GL_COLOR_BUFFER_BIT);
 86.5923 +
 86.5924 +		// draw viewport
 86.5925 +		Tess_InstantQuad(backEnd.viewParms.viewportVerts);
 86.5926 +
 86.5927 +
 86.5928 +		// render bloom in multiple passes
 86.5929 +#if 0
 86.5930 +		GL_BindProgram(&tr.bloomShader);
 86.5931 +
 86.5932 +		GLSL_SetUniform_ModelViewProjectionMatrix(&tr.bloomShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.5933 +		qglUniform1fARB(tr.bloomShader.u_BlurMagnitude, r_bloomBlur->value);
 86.5934 +#endif
 86.5935 +		for(i = 0; i < 2; i++)
 86.5936 +		{
 86.5937 +			for(j = 0; j < r_bloomPasses->integer; j++)
 86.5938 +			{
 86.5939 +				R_BindFBO(tr.bloomRenderFBO[(j + 1) % 2]);
 86.5940 +
 86.5941 +				GL_ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 86.5942 +				qglClear(GL_COLOR_BUFFER_BIT);
 86.5943 +
 86.5944 +				GL_State(GLS_DEPTHTEST_DISABLE);
 86.5945 +
 86.5946 +				GL_SelectTexture(0);
 86.5947 +				if(j == 0)
 86.5948 +					GL_Bind(tr.contrastRenderFBOImage);
 86.5949 +				else
 86.5950 +					GL_Bind(tr.bloomRenderFBOImage[j % 2]);
 86.5951 +
 86.5952 +				GL_PushMatrix();
 86.5953 +				GL_LoadModelViewMatrix(modelView);
 86.5954 +
 86.5955 +				MatrixSetupOrthogonalProjection(ortho, 0, tr.bloomRenderFBO[0]->width, 0, tr.bloomRenderFBO[0]->height, -99999, 99999);
 86.5956 +				GL_LoadProjectionMatrix(ortho);
 86.5957 +
 86.5958 +				if(i == 0)
 86.5959 +				{
 86.5960 +					GL_BindProgram(&tr.blurXShader);
 86.5961 +
 86.5962 +					qglUniform1fARB(tr.blurXShader.u_BlurMagnitude, r_bloomBlur->value);
 86.5963 +					GLSL_SetUniform_ModelViewProjectionMatrix(&tr.blurXShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.5964 +				}
 86.5965 +				else
 86.5966 +				{
 86.5967 +					GL_BindProgram(&tr.blurYShader);
 86.5968 +
 86.5969 +					qglUniform1fARB(tr.blurYShader.u_BlurMagnitude, r_bloomBlur->value);
 86.5970 +					GLSL_SetUniform_ModelViewProjectionMatrix(&tr.blurYShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.5971 +				}
 86.5972 +
 86.5973 +				GL_PopMatrix();
 86.5974 +
 86.5975 +				Tess_InstantQuad(backEnd.viewParms.viewportVerts);
 86.5976 +			}
 86.5977 +
 86.5978 +			// add offscreen processed bloom to screen
 86.5979 +			if(r_deferredShading->integer && glConfig.framebufferObjectAvailable && glConfig.textureFloatAvailable &&
 86.5980 +				   glConfig.drawBuffersAvailable && glConfig.maxDrawBuffers >= 4)
 86.5981 +			{
 86.5982 +				R_BindFBO(tr.deferredRenderFBO);
 86.5983 +
 86.5984 +				GL_BindProgram(&tr.screenShader);
 86.5985 +				GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
 86.5986 +				qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorWhite);
 86.5987 +
 86.5988 +				GLSL_SetUniform_ModelViewProjectionMatrix(&tr.screenShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.5989 +
 86.5990 +				GL_SelectTexture(0);
 86.5991 +				GL_Bind(tr.bloomRenderFBOImage[j % 2]);
 86.5992 +			}
 86.5993 +			else if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
 86.5994 +			{
 86.5995 +				R_BindFBO(tr.deferredRenderFBO);
 86.5996 +
 86.5997 +				GL_BindProgram(&tr.screenShader);
 86.5998 +				GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
 86.5999 +				qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorWhite);
 86.6000 +
 86.6001 +				GLSL_SetUniform_ModelViewProjectionMatrix(&tr.screenShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.6002 +
 86.6003 +				GL_SelectTexture(0);
 86.6004 +				GL_Bind(tr.bloomRenderFBOImage[j % 2]);
 86.6005 +				//GL_Bind(tr.contrastRenderFBOImage);
 86.6006 +			}
 86.6007 +			else
 86.6008 +			{
 86.6009 +				R_BindNullFBO();
 86.6010 +
 86.6011 +				GL_BindProgram(&tr.screenShader);
 86.6012 +				GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
 86.6013 +				qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorWhite);
 86.6014 +
 86.6015 +				GLSL_SetUniform_ModelViewProjectionMatrix(&tr.screenShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.6016 +
 86.6017 +				GL_SelectTexture(0);
 86.6018 +				GL_Bind(tr.bloomRenderFBOImage[j % 2]);
 86.6019 +				//GL_Bind(tr.contrastRenderFBOImage);
 86.6020 +			}
 86.6021 +
 86.6022 +			Tess_InstantQuad(backEnd.viewParms.viewportVerts);
 86.6023 +		}
 86.6024 +	}
 86.6025 +
 86.6026 +	// go back to 3D
 86.6027 +	GL_PopMatrix();
 86.6028 +
 86.6029 +	GL_CheckErrors();
 86.6030 +}
 86.6031 +
 86.6032 +void RB_RenderRotoscope(void)
 86.6033 +{
 86.6034 +	matrix_t        ortho;
 86.6035 +
 86.6036 +	GLimp_LogComment("--- RB_RenderRotoscope ---\n");
 86.6037 +
 86.6038 +	if((backEnd.refdef.rdflags & RDF_NOWORLDMODEL) || !r_rotoscope->integer || backEnd.viewParms.isPortal)
 86.6039 +		return;
 86.6040 +
 86.6041 +	// set 2D virtual screen size
 86.6042 +	GL_PushMatrix();
 86.6043 +	MatrixSetupOrthogonalProjection(ortho, backEnd.viewParms.viewportX,
 86.6044 +									backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
 86.6045 +									backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
 86.6046 +									-99999, 99999);
 86.6047 +	GL_LoadProjectionMatrix(ortho);
 86.6048 +	GL_LoadModelViewMatrix(matrixIdentity);
 86.6049 +
 86.6050 +	GL_State(GLS_DEPTHTEST_DISABLE);
 86.6051 +	GL_Cull(CT_TWO_SIDED);
 86.6052 +
 86.6053 +	// enable shader, set arrays
 86.6054 +	GL_BindProgram(&tr.rotoscopeShader);
 86.6055 +
 86.6056 +	GLSL_SetUniform_ModelViewProjectionMatrix(&tr.rotoscopeShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.6057 +	qglUniform1fARB(tr.rotoscopeShader.u_BlurMagnitude, r_bloomBlur->value);
 86.6058 +
 86.6059 +	GL_SelectTexture(0);
 86.6060 +	GL_Bind(tr.currentRenderImage);
 86.6061 +	qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.currentRenderImage->uploadWidth, tr.currentRenderImage->uploadHeight);
 86.6062 +
 86.6063 +	// draw viewport
 86.6064 +	Tess_InstantQuad(backEnd.viewParms.viewportVerts);
 86.6065 +
 86.6066 +	// go back to 3D
 86.6067 +	GL_PopMatrix();
 86.6068 +
 86.6069 +	GL_CheckErrors();
 86.6070 +}
 86.6071 +
 86.6072 +static void RB_CalculateAdaptation()
 86.6073 +{
 86.6074 +	int				i;
 86.6075 +	static float	image[64 * 64 * 4];
 86.6076 +	float           curTime;
 86.6077 +	float			deltaTime;
 86.6078 +	float           luminance;
 86.6079 +	float			avgLuminance;
 86.6080 +	float			maxLuminance;
 86.6081 +	double			sum;
 86.6082 +	const vec3_t    LUMINANCE_VECTOR = {0.2125f, 0.7154f, 0.0721f};
 86.6083 +	vec4_t			color;
 86.6084 +	float			newAdaptation;
 86.6085 +	float			newMaximum;
 86.6086 +
 86.6087 +	curTime = ri.Milliseconds() / 1000.0f;
 86.6088 +
 86.6089 +	// calculate the average scene luminance
 86.6090 +	R_BindFBO(tr.downScaleFBO_64x64);
 86.6091 +
 86.6092 +	// read back the contents
 86.6093 +//	qglFinish();
 86.6094 +	qglReadPixels(0, 0, 64, 64, GL_RGBA, GL_FLOAT, image);
 86.6095 +
 86.6096 +	sum = 0.0f;
 86.6097 +	maxLuminance = 0.0f;
 86.6098 +	for(i = 0; i < (64 * 64 * 4); i += 4)
 86.6099 +	{
 86.6100 +		color[0] = image[i + 0];
 86.6101 +		color[1] = image[i + 1];
 86.6102 +		color[2] = image[i + 2];
 86.6103 +		color[3] = image[i + 3];
 86.6104 +
 86.6105 +		luminance = DotProduct(color, LUMINANCE_VECTOR) + 0.0001f;
 86.6106 +		if(luminance > maxLuminance)
 86.6107 +			maxLuminance = luminance;
 86.6108 +
 86.6109 +		sum += log(luminance);
 86.6110 +	}
 86.6111 +	sum /= (64.0f * 64.0f);
 86.6112 +	avgLuminance = exp(sum);
 86.6113 +
 86.6114 +	// the user's adapted luminance level is simulated by closing the gap between
 86.6115 +	// adapted luminance and current luminance by 2% every frame, based on a
 86.6116 +	// 30 fps rate. This is not an accurate model of human adaptation, which can
 86.6117 +	// take longer than half an hour.
 86.6118 +	if(backEnd.hdrTime > curTime)
 86.6119 +		backEnd.hdrTime = curTime;
 86.6120 +
 86.6121 +	deltaTime = curTime - backEnd.hdrTime;
 86.6122 +
 86.6123 +	//if(r_hdrMaxLuminance->value)
 86.6124 +	{
 86.6125 +		Q_clamp(backEnd.hdrAverageLuminance, r_hdrMinLuminance->value, r_hdrMaxLuminance->value);
 86.6126 +		Q_clamp(avgLuminance, r_hdrMinLuminance->value, r_hdrMaxLuminance->value);
 86.6127 +
 86.6128 +		Q_clamp(backEnd.hdrMaxLuminance, r_hdrMinLuminance->value, r_hdrMaxLuminance->value);
 86.6129 +		Q_clamp(maxLuminance, r_hdrMinLuminance->value, r_hdrMaxLuminance->value);
 86.6130 +	}
 86.6131 +
 86.6132 +	newAdaptation = backEnd.hdrAverageLuminance + (avgLuminance - backEnd.hdrAverageLuminance) * (1.0f - powf(0.98f, 30.0f * deltaTime));
 86.6133 +	newMaximum = backEnd.hdrMaxLuminance + (maxLuminance - backEnd.hdrMaxLuminance) * (1.0f - powf(0.98f, 30.0f * deltaTime));
 86.6134 +
 86.6135 +	if(!Q_isnan(newAdaptation) && !Q_isnan(newMaximum))
 86.6136 +	{
 86.6137 +		#if 1
 86.6138 +		backEnd.hdrAverageLuminance = newAdaptation;
 86.6139 +		backEnd.hdrMaxLuminance = newMaximum;
 86.6140 +		#else
 86.6141 +		backEnd.hdrAverageLuminance = avgLuminance;
 86.6142 +		backEnd.hdrMaxLuminance = maxLuminance;
 86.6143 +		#endif
 86.6144 +	}
 86.6145 +
 86.6146 +	backEnd.hdrTime = curTime;
 86.6147 +
 86.6148 +	//ri.Printf(PRINT_ALL, "RB_CalculateAdaptation: avg = %f  max = %f\n", backEnd.hdrAverageLuminance, backEnd.hdrMaxLuminance);
 86.6149 +
 86.6150 +	GL_CheckErrors();
 86.6151 +}
 86.6152 +
 86.6153 +void RB_RenderDeferredShadingResultToFrameBuffer()
 86.6154 +{
 86.6155 +	matrix_t        ortho;
 86.6156 +
 86.6157 +	GLimp_LogComment("--- RB_RenderDeferredShadingResultToFrameBuffer ---\n");
 86.6158 +
 86.6159 +	R_BindNullFBO();
 86.6160 +
 86.6161 +	/*
 86.6162 +	   if(backEnd.refdef.rdflags & RDF_NOWORLDMODEL)
 86.6163 +	   {
 86.6164 +	   GL_State(GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
 86.6165 +	   }
 86.6166 +	   else
 86.6167 +	 */
 86.6168 +	{
 86.6169 +		GL_State(GLS_DEPTHTEST_DISABLE);	// | GLS_DEPTHMASK_TRUE);
 86.6170 +	}
 86.6171 +
 86.6172 +	GL_Cull(CT_TWO_SIDED);
 86.6173 +
 86.6174 +	// set uniforms
 86.6175 +
 86.6176 +	// set 2D virtual screen size
 86.6177 +	GL_PushMatrix();
 86.6178 +	MatrixSetupOrthogonalProjection(ortho, backEnd.viewParms.viewportX,
 86.6179 +									backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
 86.6180 +									backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
 86.6181 +									-99999, 99999);
 86.6182 +	GL_LoadProjectionMatrix(ortho);
 86.6183 +	GL_LoadModelViewMatrix(matrixIdentity);
 86.6184 +
 86.6185 +	if(!(backEnd.refdef.rdflags & RDF_NOWORLDMODEL) && r_hdrRendering->integer)
 86.6186 +	{
 86.6187 +		R_BindNullFBO();
 86.6188 +
 86.6189 +		GL_BindProgram(&tr.toneMappingShader);
 86.6190 +
 86.6191 +		// bind u_ColorMap
 86.6192 +		GL_SelectTexture(0);
 86.6193 +		GL_Bind(tr.deferredRenderFBOImage);
 86.6194 +
 86.6195 +		if(r_hdrKey->value <= 0)
 86.6196 +		{
 86.6197 +			float			key;
 86.6198 +
 86.6199 +			// calculation from: Perceptual Effects in Real-time Tone Mapping - Krawczyk et al.
 86.6200 +			key = 1.03 - 2.0 / (2.0 + log10f(backEnd.hdrAverageLuminance + 1.0f));
 86.6201 +			qglUniform1fARB(tr.toneMappingShader.u_HDRKey, key);
 86.6202 +		}
 86.6203 +		else
 86.6204 +		{
 86.6205 +			qglUniform1fARB(tr.toneMappingShader.u_HDRKey, r_hdrKey->value);
 86.6206 +		}
 86.6207 +
 86.6208 +		qglUniform1fARB(tr.toneMappingShader.u_HDRAverageLuminance, backEnd.hdrAverageLuminance);
 86.6209 +		qglUniform1fARB(tr.toneMappingShader.u_HDRMaxLuminance, backEnd.hdrMaxLuminance);
 86.6210 +
 86.6211 +		GLSL_SetUniform_ModelViewProjectionMatrix(&tr.toneMappingShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.6212 +	}
 86.6213 +	else
 86.6214 +	{
 86.6215 +		GL_BindProgram(&tr.screenShader);
 86.6216 +		qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorWhite);
 86.6217 +
 86.6218 +		// bind u_ColorMap
 86.6219 +		GL_SelectTexture(0);
 86.6220 +
 86.6221 +		if(r_showDeferredDiffuse->integer)
 86.6222 +		{
 86.6223 +			GL_Bind(tr.deferredDiffuseFBOImage);
 86.6224 +		}
 86.6225 +		else if(r_showDeferredNormal->integer)
 86.6226 +		{
 86.6227 +			GL_Bind(tr.deferredNormalFBOImage);
 86.6228 +		}
 86.6229 +		else if(r_showDeferredSpecular->integer)
 86.6230 +		{
 86.6231 +			GL_Bind(tr.deferredSpecularFBOImage);
 86.6232 +		}
 86.6233 +		else if(r_showDeferredPosition->integer)
 86.6234 +		{
 86.6235 +			GL_Bind(tr.depthRenderImage);
 86.6236 +		}
 86.6237 +		else
 86.6238 +		{
 86.6239 +			GL_Bind(tr.deferredRenderFBOImage);
 86.6240 +		}
 86.6241 +
 86.6242 +		GLSL_SetUniform_ModelViewProjectionMatrix(&tr.screenShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.6243 +	}
 86.6244 +
 86.6245 +	GL_CheckErrors();
 86.6246 +
 86.6247 +	Tess_InstantQuad(backEnd.viewParms.viewportVerts);
 86.6248 +
 86.6249 +	GL_PopMatrix();
 86.6250 +}
 86.6251 +
 86.6252 +void RB_RenderDeferredHDRResultToFrameBuffer()
 86.6253 +{
 86.6254 +	matrix_t        ortho;
 86.6255 +
 86.6256 +	GLimp_LogComment("--- RB_RenderDeferredHDRResultToFrameBuffer ---\n");
 86.6257 +
 86.6258 +	if(!r_hdrRendering->integer || !glConfig.framebufferObjectAvailable || !glConfig.textureFloatAvailable)
 86.6259 +		return;
 86.6260 +
 86.6261 +	GL_CheckErrors();
 86.6262 +
 86.6263 +	R_BindNullFBO();
 86.6264 +
 86.6265 +	// bind u_ColorMap
 86.6266 +	GL_SelectTexture(0);
 86.6267 +	GL_Bind(tr.deferredRenderFBOImage);
 86.6268 +
 86.6269 +	GL_State(GLS_DEPTHTEST_DISABLE);
 86.6270 +	GL_Cull(CT_TWO_SIDED);
 86.6271 +
 86.6272 +	GL_CheckErrors();
 86.6273 +
 86.6274 +	// set uniforms
 86.6275 +
 86.6276 +	// set 2D virtual screen size
 86.6277 +	GL_PushMatrix();
 86.6278 +	MatrixSetupOrthogonalProjection(ortho, backEnd.viewParms.viewportX,
 86.6279 +									backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
 86.6280 +									backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
 86.6281 +									-99999, 99999);
 86.6282 +	GL_LoadProjectionMatrix(ortho);
 86.6283 +	GL_LoadModelViewMatrix(matrixIdentity);
 86.6284 +
 86.6285 +
 86.6286 +	if(backEnd.refdef.rdflags & RDF_NOWORLDMODEL)
 86.6287 +	{
 86.6288 +		GL_BindProgram(&tr.screenShader);
 86.6289 +
 86.6290 +		qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorWhite);
 86.6291 +
 86.6292 +		GLSL_SetUniform_ModelViewProjectionMatrix(&tr.screenShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.6293 +	}
 86.6294 +	else
 86.6295 +	{
 86.6296 +		GL_BindProgram(&tr.toneMappingShader);
 86.6297 +
 86.6298 +		if(r_hdrKey->value <= 0)
 86.6299 +		{
 86.6300 +			float			key;
 86.6301 +
 86.6302 +			// calculation from: Perceptual Effects in Real-time Tone Mapping - Krawczyk et al.
 86.6303 +			key = 1.03 - 2.0 / (2.0 + log10f(backEnd.hdrAverageLuminance + 1.0f));
 86.6304 +			qglUniform1fARB(tr.toneMappingShader.u_HDRKey, key);
 86.6305 +		}
 86.6306 +		else
 86.6307 +		{
 86.6308 +			qglUniform1fARB(tr.toneMappingShader.u_HDRKey, r_hdrKey->value);
 86.6309 +		}
 86.6310 +
 86.6311 +		qglUniform1fARB(tr.toneMappingShader.u_HDRAverageLuminance, backEnd.hdrAverageLuminance);
 86.6312 +		qglUniform1fARB(tr.toneMappingShader.u_HDRMaxLuminance, backEnd.hdrMaxLuminance);
 86.6313 +
 86.6314 +		GLSL_SetUniform_ModelViewProjectionMatrix(&tr.toneMappingShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.6315 +	}
 86.6316 +
 86.6317 +	GL_CheckErrors();
 86.6318 +
 86.6319 +	Tess_InstantQuad(backEnd.viewParms.viewportVerts);
 86.6320 +
 86.6321 +	GL_PopMatrix();
 86.6322 +}
 86.6323 +
 86.6324 +void RB_RenderLightOcclusionQueries()
 86.6325 +{
 86.6326 +	GLimp_LogComment("--- RB_RenderLightOcclusionQueries ---\n");
 86.6327 +
 86.6328 +	if(glConfig.occlusionQueryBits && glConfig.driverType != GLDRV_MESA)
 86.6329 +	{
 86.6330 +		int             j;
 86.6331 +		interaction_t  *ia;
 86.6332 +		int             iaCount;
 86.6333 +		int             iaFirst;
 86.6334 +		trRefLight_t   *light, *oldLight;
 86.6335 +		int             ocCount;
 86.6336 +		GLint           ocSamples = 0;
 86.6337 +		qboolean        queryObjects;
 86.6338 +		GLint           available;
 86.6339 +		vec4_t          quadVerts[4];
 86.6340 +
 86.6341 +		qglVertexAttrib4fARB(ATTR_INDEX_COLOR, 1.0f, 0.0f, 0.0f, 0.05f);
 86.6342 +
 86.6343 +		GL_BindProgram(&tr.genericSingleShader);
 86.6344 +		GL_Cull(CT_TWO_SIDED);
 86.6345 +
 86.6346 +		GL_LoadProjectionMatrix(backEnd.viewParms.projectionMatrix);
 86.6347 +
 86.6348 +		// set uniforms
 86.6349 +		GLSL_SetUniform_TCGen_Environment(&tr.genericSingleShader,  qfalse);
 86.6350 +		GLSL_SetUniform_ColorGen(&tr.genericSingleShader, CGEN_VERTEX);
 86.6351 +		GLSL_SetUniform_AlphaGen(&tr.genericSingleShader, AGEN_VERTEX);
 86.6352 +		if(glConfig.vboVertexSkinningAvailable)
 86.6353 +		{
 86.6354 +			GLSL_SetUniform_VertexSkinning(&tr.genericSingleShader, qfalse);
 86.6355 +		}
 86.6356 +		GLSL_SetUniform_AlphaTest(&tr.genericSingleShader, 0);
 86.6357 +
 86.6358 +		// bind u_ColorMap
 86.6359 +		GL_SelectTexture(0);
 86.6360 +		GL_Bind(tr.whiteImage);
 86.6361 +		GLSL_SetUniform_ColorTextureMatrix(&tr.genericSingleShader, matrixIdentity);
 86.6362 +
 86.6363 +		// don't write to the color buffer or depth buffer
 86.6364 +		if(r_showOcclusionQueries->integer)
 86.6365 +		{
 86.6366 +			GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
 86.6367 +		}
 86.6368 +		else
 86.6369 +		{
 86.6370 +			GL_State(GLS_COLORMASK_BITS);
 86.6371 +		}
 86.6372 +
 86.6373 +		// loop trough all light interactions and render the light OBB for each last interaction
 86.6374 +		ocCount = -1;
 86.6375 +		for(iaCount = 0, ia = &backEnd.viewParms.interactions[0]; iaCount < backEnd.viewParms.numInteractions;)
 86.6376 +		{
 86.6377 +			backEnd.currentLight = light = ia->light;
 86.6378 +			ia->occlusionQuerySamples = 1;
 86.6379 +
 86.6380 +			if(!ia->next)
 86.6381 +			{
 86.6382 +				// last interaction of current light
 86.6383 +				if(!ia->noOcclusionQueries &&
 86.6384 +				   ocCount <
 86.6385 +				   (MAX_OCCLUSION_QUERIES - 1) /*&& R_CullLightPoint(light, backEnd.viewParms.orientation.origin) == CULL_OUT */ )
 86.6386 +				{
 86.6387 +					ocCount++;
 86.6388 +
 86.6389 +					R_RotateLightForViewParms(light, &backEnd.viewParms, &backEnd.orientation);
 86.6390 +					GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.6391 +					GLSL_SetUniform_ModelViewProjectionMatrix(&tr.genericSingleShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.6392 +
 86.6393 +					// begin the occlusion query
 86.6394 +					qglBeginQueryARB(GL_SAMPLES_PASSED, tr.occlusionQueryObjects[ocCount]);
 86.6395 +
 86.6396 +					switch (light->l.rlType)
 86.6397 +					{
 86.6398 +						case RL_OMNI:
 86.6399 +						{
 86.6400 +							tess.numIndexes = 0;
 86.6401 +							tess.numVertexes = 0;
 86.6402 +
 86.6403 +							VectorSet4(quadVerts[0], light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2],
 86.6404 +									   1);
 86.6405 +							VectorSet4(quadVerts[1], light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2],
 86.6406 +									   1);
 86.6407 +							VectorSet4(quadVerts[2], light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2],
 86.6408 +									   1);
 86.6409 +							VectorSet4(quadVerts[3], light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2],
 86.6410 +									   1);
 86.6411 +							Tess_AddQuadStamp2(quadVerts, colorRed);
 86.6412 +
 86.6413 +							VectorSet4(quadVerts[0], light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2],
 86.6414 +									   1);
 86.6415 +							VectorSet4(quadVerts[1], light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2],
 86.6416 +									   1);
 86.6417 +							VectorSet4(quadVerts[2], light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2],
 86.6418 +									   1);
 86.6419 +							VectorSet4(quadVerts[3], light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2],
 86.6420 +									   1);
 86.6421 +							Tess_AddQuadStamp2(quadVerts, colorGreen);
 86.6422 +
 86.6423 +							VectorSet4(quadVerts[0], light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2],
 86.6424 +									   1);
 86.6425 +							VectorSet4(quadVerts[1], light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2],
 86.6426 +									   1);
 86.6427 +							VectorSet4(quadVerts[2], light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2],
 86.6428 +									   1);
 86.6429 +							VectorSet4(quadVerts[3], light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2],
 86.6430 +									   1);
 86.6431 +							Tess_AddQuadStamp2(quadVerts, colorBlue);
 86.6432 +
 86.6433 +							VectorSet4(quadVerts[0], light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2],
 86.6434 +									   1);
 86.6435 +							VectorSet4(quadVerts[1], light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2],
 86.6436 +									   1);
 86.6437 +							VectorSet4(quadVerts[2], light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2],
 86.6438 +									   1);
 86.6439 +							VectorSet4(quadVerts[3], light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2],
 86.6440 +									   1);
 86.6441 +							Tess_AddQuadStamp2(quadVerts, colorYellow);
 86.6442 +
 86.6443 +							VectorSet4(quadVerts[0], light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2],
 86.6444 +									   1);
 86.6445 +							VectorSet4(quadVerts[1], light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2],
 86.6446 +									   1);
 86.6447 +							VectorSet4(quadVerts[2], light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2],
 86.6448 +									   1);
 86.6449 +							VectorSet4(quadVerts[3], light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2],
 86.6450 +									   1);
 86.6451 +							Tess_AddQuadStamp2(quadVerts, colorMagenta);
 86.6452 +
 86.6453 +							VectorSet4(quadVerts[0], light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2],
 86.6454 +									   1);
 86.6455 +							VectorSet4(quadVerts[1], light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2],
 86.6456 +									   1);
 86.6457 +							VectorSet4(quadVerts[2], light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2],
 86.6458 +									   1);
 86.6459 +							VectorSet4(quadVerts[3], light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2],
 86.6460 +									   1);
 86.6461 +							Tess_AddQuadStamp2(quadVerts, colorCyan);
 86.6462 +
 86.6463 +							Tess_UpdateVBOs(ATTR_POSITION | ATTR_COLOR);
 86.6464 +							Tess_DrawElements();
 86.6465 +
 86.6466 +							tess.numIndexes = 0;
 86.6467 +							tess.numVertexes = 0;
 86.6468 +							break;
 86.6469 +						}
 86.6470 +
 86.6471 +						case RL_PROJ:
 86.6472 +						{
 86.6473 +							float           xMin, xMax, yMin, yMax;
 86.6474 +							float           zNear, zFar;
 86.6475 +							vec4_t          corners[4];
 86.6476 +
 86.6477 +							zNear = light->l.distNear;
 86.6478 +							zFar = light->l.distFar;
 86.6479 +
 86.6480 +							xMax = zNear * tan(light->l.fovX * M_PI / 360.0f);
 86.6481 +							xMin = -xMax;
 86.6482 +
 86.6483 +							yMax = zNear * tan(light->l.fovY * M_PI / 360.0f);
 86.6484 +							yMin = -yMax;
 86.6485 +
 86.6486 +							corners[0][0] = zFar;
 86.6487 +							corners[0][1] = xMin * zFar;
 86.6488 +							corners[0][2] = yMin * zFar;
 86.6489 +							corners[0][3] = 1;
 86.6490 +
 86.6491 +							corners[1][0] = zFar;
 86.6492 +							corners[1][1] = xMax * zFar;
 86.6493 +							corners[1][2] = yMin * zFar;
 86.6494 +							corners[1][3] = 1;
 86.6495 +
 86.6496 +							corners[2][0] = zFar;
 86.6497 +							corners[2][1] = xMax * zFar;
 86.6498 +							corners[2][2] = yMax * zFar;
 86.6499 +							corners[2][3] = 1;
 86.6500 +
 86.6501 +							corners[3][0] = zFar;
 86.6502 +							corners[3][1] = xMin * zFar;
 86.6503 +							corners[3][2] = yMax * zFar;
 86.6504 +							corners[3][3] = 1;
 86.6505 +
 86.6506 +							tess.numIndexes = 0;
 86.6507 +							tess.numVertexes = 0;
 86.6508 +
 86.6509 +							// draw side planes
 86.6510 +							for(j = 0; j < 4; j++)
 86.6511 +							{
 86.6512 +								VectorSet4(tess.xyz[tess.numVertexes], 0, 0, 0, 1);
 86.6513 +								VectorCopy4(g_color_table[j + 1], tess.colors[tess.numVertexes]);
 86.6514 +								tess.indexes[tess.numIndexes++] = tess.numVertexes;
 86.6515 +								tess.numVertexes++;
 86.6516 +
 86.6517 +								VectorCopy(corners[j], tess.xyz[tess.numVertexes]);
 86.6518 +								tess.xyz[tess.numVertexes][3] = 1;
 86.6519 +								VectorCopy4(g_color_table[j + 1], tess.colors[tess.numVertexes]);
 86.6520 +								tess.indexes[tess.numIndexes++] = tess.numVertexes;
 86.6521 +								tess.numVertexes++;
 86.6522 +
 86.6523 +								VectorCopy(corners[(j + 1) % 4], tess.xyz[tess.numVertexes]);
 86.6524 +								tess.xyz[tess.numVertexes][3] = 1;
 86.6525 +								VectorCopy4(g_color_table[j + 1], tess.colors[tess.numVertexes]);
 86.6526 +								tess.indexes[tess.numIndexes++] = tess.numVertexes;
 86.6527 +								tess.numVertexes++;
 86.6528 +							}
 86.6529 +
 86.6530 +							// draw far plane
 86.6531 +							Tess_AddQuadStamp2(corners, g_color_table[j + 1]);
 86.6532 +
 86.6533 +							Tess_UpdateVBOs(ATTR_POSITION | ATTR_COLOR);
 86.6534 +							Tess_DrawElements();
 86.6535 +
 86.6536 +							tess.numIndexes = 0;
 86.6537 +							tess.numVertexes = 0;
 86.6538 +							break;
 86.6539 +						}
 86.6540 +
 86.6541 +						default:
 86.6542 +							break;
 86.6543 +					}
 86.6544 +
 86.6545 +
 86.6546 +					// end the query
 86.6547 +					// don't read back immediately so that we give the query time to be ready
 86.6548 +					qglEndQueryARB(GL_SAMPLES_PASSED);
 86.6549 +
 86.6550 +					backEnd.pc.c_occlusionQueries++;
 86.6551 +				}
 86.6552 +
 86.6553 +				if(iaCount < (backEnd.viewParms.numInteractions - 1))
 86.6554 +				{
 86.6555 +					// jump to next interaction and continue
 86.6556 +					ia++;
 86.6557 +					iaCount++;
 86.6558 +				}
 86.6559 +				else
 86.6560 +				{
 86.6561 +					// increase last time to leave for loop
 86.6562 +					iaCount++;
 86.6563 +				}
 86.6564 +			}
 86.6565 +			else
 86.6566 +			{
 86.6567 +				// just continue
 86.6568 +				ia = ia->next;
 86.6569 +				iaCount++;
 86.6570 +			}
 86.6571 +		}
 86.6572 +
 86.6573 +		// go back to the world modelview matrix
 86.6574 +		backEnd.orientation = backEnd.viewParms.world;
 86.6575 +		GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.6576 +
 86.6577 +		if(backEnd.refdef.rdflags & RDF_NOWORLDMODEL)
 86.6578 +		{
 86.6579 +			// FIXME it ain't work in subviews
 86.6580 +			return;
 86.6581 +		}
 86.6582 +
 86.6583 +		if(ocCount == -1)
 86.6584 +		{
 86.6585 +			// Tr3B: avoid the following qglFinish if there are no lights
 86.6586 +			return;
 86.6587 +		}
 86.6588 +
 86.6589 +		/*
 86.6590 +		   if(!ocCount)
 86.6591 +		   {
 86.6592 +		   qglEnable(GL_TEXTURE_2D);
 86.6593 +		   return;
 86.6594 +		   }
 86.6595 +		 */
 86.6596 +
 86.6597 +		qglFinish();
 86.6598 +
 86.6599 +		// do other work until "most" of the queries are back, to avoid
 86.6600 +		// wasting time spinning
 86.6601 +		if(ocCount >= 0)
 86.6602 +		{
 86.6603 +			int             i;
 86.6604 +			int             avCount;
 86.6605 +			int             limit;
 86.6606 +			int             startTime = 0, endTime = 0;
 86.6607 +
 86.6608 +			if(r_speeds->integer == 7)
 86.6609 +			{
 86.6610 +				startTime = ri.Milliseconds();
 86.6611 +			}
 86.6612 +
 86.6613 +			limit = (int)(ocCount * 5 / 6);	// instead of N-1, to prevent the GPU from going idle
 86.6614 +			//limit = ocCount;
 86.6615 +
 86.6616 +
 86.6617 +			if(limit >= (MAX_OCCLUSION_QUERIES - 1))
 86.6618 +				limit = (MAX_OCCLUSION_QUERIES - 1);
 86.6619 +
 86.6620 +			i = 0;
 86.6621 +			avCount = -1;
 86.6622 +			do
 86.6623 +			{
 86.6624 +				if(i >= ocCount)
 86.6625 +				{
 86.6626 +					i = 0;
 86.6627 +				}
 86.6628 +
 86.6629 +				qglGetQueryObjectivARB(tr.occlusionQueryObjects[i], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
 86.6630 +
 86.6631 +				if(available)
 86.6632 +					avCount++;
 86.6633 +
 86.6634 +				i++;
 86.6635 +
 86.6636 +			} while(avCount < limit);
 86.6637 +
 86.6638 +			if(r_speeds->integer == 7)
 86.6639 +			{
 86.6640 +				endTime = ri.Milliseconds();
 86.6641 +				backEnd.pc.c_occlusionQueriesResponseTime = endTime - startTime;
 86.6642 +			}
 86.6643 +		}
 86.6644 +
 86.6645 +		// reenable writes to depth and color buffers
 86.6646 +		GL_State(GLS_DEPTHMASK_TRUE);
 86.6647 +
 86.6648 +		// loop trough all light interactions and fetch results for each last interaction
 86.6649 +		// then copy result to all other interactions that belong to the same light
 86.6650 +		ocCount = -1;
 86.6651 +		iaFirst = 0;
 86.6652 +		queryObjects = qtrue;
 86.6653 +		oldLight = NULL;
 86.6654 +		for(iaCount = 0, ia = &backEnd.viewParms.interactions[0]; iaCount < backEnd.viewParms.numInteractions;)
 86.6655 +		{
 86.6656 +			backEnd.currentLight = light = ia->light;
 86.6657 +
 86.6658 +			if(light != oldLight)
 86.6659 +			{
 86.6660 +				iaFirst = iaCount;
 86.6661 +			}
 86.6662 +
 86.6663 +			if(!queryObjects)
 86.6664 +			{
 86.6665 +				ia->occlusionQuerySamples = ocSamples;
 86.6666 +
 86.6667 +				if(ocSamples <= 0)
 86.6668 +				{
 86.6669 +					backEnd.pc.c_occlusionQueriesInteractionsCulled++;
 86.6670 +				}
 86.6671 +			}
 86.6672 +
 86.6673 +			if(!ia->next)
 86.6674 +			{
 86.6675 +				if(queryObjects)
 86.6676 +				{
 86.6677 +					if(!ia->noOcclusionQueries &&
 86.6678 +					   ocCount <
 86.6679 +					   (MAX_OCCLUSION_QUERIES - 1) /*&& R_CullLightPoint(light, backEnd.viewParms.orientation.origin) == CULL_OUT */ )
 86.6680 +					{
 86.6681 +						ocCount++;
 86.6682 +
 86.6683 +						qglGetQueryObjectivARB(tr.occlusionQueryObjects[ocCount], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
 86.6684 +						if(available)
 86.6685 +						{
 86.6686 +							backEnd.pc.c_occlusionQueriesAvailable++;
 86.6687 +
 86.6688 +							// get the object and store it in the occlusion bits for the light
 86.6689 +							qglGetQueryObjectivARB(tr.occlusionQueryObjects[ocCount], GL_QUERY_RESULT, &ocSamples);
 86.6690 +
 86.6691 +							if(ocSamples <= 0)
 86.6692 +							{
 86.6693 +								backEnd.pc.c_occlusionQueriesLightsCulled++;
 86.6694  							}
 86.6695  						}
 86.6696  						else
 86.6697  						{
 86.6698 -							viewParms_t temp = backEnd.viewParms;
 86.6699 -
 86.6700 -							R_SetupProjection(&temp, r_znear->value, qfalse);
 86.6701 -
 86.6702 -							qglMatrixMode(GL_PROJECTION);
 86.6703 -							qglLoadMatrixf(temp.projectionMatrix);
 86.6704 -							qglMatrixMode(GL_MODELVIEW);
 86.6705 +							ocSamples = 1;
 86.6706  						}
 86.6707  					}
 86.6708 -
 86.6709 -					if(!oldDepthRange)
 86.6710 -						qglDepthRange (0, 0.3);
 86.6711 +					else
 86.6712 +					{
 86.6713 +						ocSamples = 1;
 86.6714 +					}
 86.6715 +
 86.6716 +					// jump back to first interaction of this light copy query result
 86.6717 +					ia = &backEnd.viewParms.interactions[iaFirst];
 86.6718 +					iaCount = iaFirst;
 86.6719 +					queryObjects = qfalse;
 86.6720  				}
 86.6721  				else
 86.6722  				{
 86.6723 -					if(!wasCrosshair && backEnd.viewParms.stereoFrame != STEREO_CENTER)
 86.6724 +					if(iaCount < (backEnd.viewParms.numInteractions - 1))
 86.6725  					{
 86.6726 -						qglMatrixMode(GL_PROJECTION);
 86.6727 -						qglLoadMatrixf(backEnd.viewParms.projectionMatrix);
 86.6728 -						qglMatrixMode(GL_MODELVIEW);
 86.6729 +						// jump to next interaction and start querying
 86.6730 +						ia++;
 86.6731 +						iaCount++;
 86.6732 +						queryObjects = qtrue;
 86.6733  					}
 86.6734 -
 86.6735 -					qglDepthRange (0, 1);
 86.6736 -				}
 86.6737 -
 86.6738 -				oldDepthRange = depthRange;
 86.6739 -				wasCrosshair = isCrosshair;
 86.6740 -			}
 86.6741 -
 86.6742 -			oldEntityNum = entityNum;
 86.6743 -		}
 86.6744 -
 86.6745 -		// add the triangles for this surface
 86.6746 -		rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
 86.6747 -	}
 86.6748 -
 86.6749 -	backEnd.refdef.floatTime = originalTime;
 86.6750 -
 86.6751 -	// draw the contents of the last shader batch
 86.6752 -	if (oldShader != NULL) {
 86.6753 -		RB_EndSurface();
 86.6754 -	}
 86.6755 -
 86.6756 -	// go back to the world modelview matrix
 86.6757 -	qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
 86.6758 -	if ( depthRange ) {
 86.6759 -		qglDepthRange (0, 1);
 86.6760 -	}
 86.6761 +					else
 86.6762 +					{
 86.6763 +						// increase last time to leave for loop
 86.6764 +						iaCount++;
 86.6765 +					}
 86.6766 +				}
 86.6767 +			}
 86.6768 +			else
 86.6769 +			{
 86.6770 +				// just continue
 86.6771 +				ia = ia->next;
 86.6772 +				iaCount++;
 86.6773 +			}
 86.6774 +
 86.6775 +			oldLight = light;
 86.6776 +		}
 86.6777 +	}
 86.6778 +
 86.6779 +	GL_CheckErrors();
 86.6780 +}
 86.6781 +
 86.6782 +/*
 86.6783 +some debug utilities for displaying entity AABBs and so on
 86.6784 +FIXME rewrite this to use the genericSingle GLSL shader
 86.6785 +this fixed function pipeline stuff is broken
 86.6786 +*/
 86.6787 +static void RB_RenderDebugUtils()
 86.6788 +{
 86.6789 +	GLimp_LogComment("--- RB_RenderDebugUtils ---\n");
 86.6790 +
 86.6791 +#if 1
 86.6792 +	if(r_showLightTransforms->integer || r_showShadowLod->integer)
 86.6793 +	{
 86.6794 +		interaction_t  *ia;
 86.6795 +		int             iaCount, j;
 86.6796 +		trRefLight_t   *light;
 86.6797 +		vec3_t          forward, left, up;
 86.6798 +		vec4_t          tmp;
 86.6799 +		vec4_t          lightColor;
 86.6800 +		vec4_t          quadVerts[4];
 86.6801 +
 86.6802 +		GL_BindProgram(&tr.genericSingleShader);
 86.6803 +		GL_State(GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE);
 86.6804 +		GL_Cull(CT_TWO_SIDED);
 86.6805 +
 86.6806 +		// set uniforms
 86.6807 +		GLSL_SetUniform_TCGen_Environment(&tr.genericSingleShader,  qfalse);
 86.6808 +		GLSL_SetUniform_ColorGen(&tr.genericSingleShader, CGEN_VERTEX);
 86.6809 +		GLSL_SetUniform_AlphaGen(&tr.genericSingleShader, AGEN_VERTEX);
 86.6810 +		if(glConfig.vboVertexSkinningAvailable)
 86.6811 +		{
 86.6812 +			GLSL_SetUniform_VertexSkinning(&tr.genericSingleShader, qfalse);
 86.6813 +		}
 86.6814 +		GLSL_SetUniform_AlphaTest(&tr.genericSingleShader, 0);
 86.6815 +
 86.6816 +		// bind u_ColorMap
 86.6817 +		GL_SelectTexture(0);
 86.6818 +		GL_Bind(tr.whiteImage);
 86.6819 +		GLSL_SetUniform_ColorTextureMatrix(&tr.genericSingleShader, matrixIdentity);
 86.6820 +
 86.6821 +		for(iaCount = 0, ia = &backEnd.viewParms.interactions[0]; iaCount < backEnd.viewParms.numInteractions;)
 86.6822 +		{
 86.6823 +			light = ia->light;
 86.6824 +
 86.6825 +			if(!ia->next)
 86.6826 +			{
 86.6827 +				if(r_showShadowLod->integer)
 86.6828 +				{
 86.6829 +					if(light->shadowLOD == 0)
 86.6830 +					{
 86.6831 +						VectorCopy4(colorRed, lightColor);
 86.6832 +					}
 86.6833 +					else if(light->shadowLOD == 1)
 86.6834 +					{
 86.6835 +						VectorCopy4(colorGreen, lightColor);
 86.6836 +					}
 86.6837 +					else if(light->shadowLOD == 2)
 86.6838 +					{
 86.6839 +						VectorCopy4(colorBlue, lightColor);
 86.6840 +					}
 86.6841 +					else if(light->shadowLOD == 3)
 86.6842 +					{
 86.6843 +						VectorCopy4(colorYellow, lightColor);
 86.6844 +					}
 86.6845 +					else if(light->shadowLOD == 4)
 86.6846 +					{
 86.6847 +						VectorCopy4(colorMagenta, lightColor);
 86.6848 +					}
 86.6849 +					else if(light->shadowLOD == 5)
 86.6850 +					{
 86.6851 +						VectorCopy4(colorCyan, lightColor);
 86.6852 +					}
 86.6853 +					else
 86.6854 +					{
 86.6855 +						VectorCopy4(colorMdGrey, lightColor);
 86.6856 +					}
 86.6857 +				}
 86.6858 +				else
 86.6859 +				{
 86.6860 +					VectorCopy4(g_color_table[iaCount % 8], lightColor);
 86.6861 +				}
 86.6862 +
 86.6863 +				// set up the transformation matrix
 86.6864 +				R_RotateLightForViewParms(light, &backEnd.viewParms, &backEnd.orientation);
 86.6865 +				GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.6866 +				GLSL_SetUniform_ModelViewProjectionMatrix(&tr.genericSingleShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.6867 +
 86.6868 +				MatrixToVectorsFLU(matrixIdentity, forward, left, up);
 86.6869 +				VectorMA(vec3_origin, 16, forward, forward);
 86.6870 +				VectorMA(vec3_origin, 16, left, left);
 86.6871 +				VectorMA(vec3_origin, 16, up, up);
 86.6872 +
 86.6873 +				/*
 86.6874 +				// draw axis
 86.6875 +				qglBegin(GL_LINES);
 86.6876 +
 86.6877 +				// draw orientation
 86.6878 +				qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorRed);
 86.6879 +				qglVertex3fv(vec3_origin);
 86.6880 +				qglVertex3fv(forward);
 86.6881 +
 86.6882 +				qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorGreen);
 86.6883 +				qglVertex3fv(vec3_origin);
 86.6884 +				qglVertex3fv(left);
 86.6885 +
 86.6886 +				qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorBlue);
 86.6887 +				qglVertex3fv(vec3_origin);
 86.6888 +				qglVertex3fv(up);
 86.6889 +
 86.6890 +				// draw special vectors
 86.6891 +				qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorYellow);
 86.6892 +				qglVertex3fv(vec3_origin);
 86.6893 +				VectorSubtract(light->origin, backEnd.orientation.origin, tmp);
 86.6894 +				light->transformed[0] = DotProduct(tmp, backEnd.orientation.axis[0]);
 86.6895 +				light->transformed[1] = DotProduct(tmp, backEnd.orientation.axis[1]);
 86.6896 +				light->transformed[2] = DotProduct(tmp, backEnd.orientation.axis[2]);
 86.6897 +				qglVertex3fv(light->transformed);
 86.6898 +
 86.6899 +				qglEnd();
 86.6900 +				*/
 86.6901 +
 86.6902 +				switch (light->l.rlType)
 86.6903 +				{
 86.6904 +					case RL_OMNI:
 86.6905 +					{
 86.6906 +						tess.numIndexes = 0;
 86.6907 +						tess.numVertexes = 0;
 86.6908 +
 86.6909 +						VectorSet4(quadVerts[0], light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2], 1);
 86.6910 +						VectorSet4(quadVerts[1], light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2], 1);
 86.6911 +						VectorSet4(quadVerts[2], light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2], 1);
 86.6912 +						VectorSet4(quadVerts[3], light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2], 1);
 86.6913 +						Tess_AddQuadStamp2(quadVerts, lightColor);
 86.6914 +
 86.6915 +						VectorSet4(quadVerts[0], light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2], 1);
 86.6916 +						VectorSet4(quadVerts[1], light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2], 1);
 86.6917 +						VectorSet4(quadVerts[2], light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2], 1);
 86.6918 +						VectorSet4(quadVerts[3], light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2], 1);
 86.6919 +						Tess_AddQuadStamp2(quadVerts, lightColor);
 86.6920 +
 86.6921 +						VectorSet4(quadVerts[0], light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2], 1);
 86.6922 +						VectorSet4(quadVerts[1], light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2], 1);
 86.6923 +						VectorSet4(quadVerts[2], light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2], 1);
 86.6924 +						VectorSet4(quadVerts[3], light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2], 1);
 86.6925 +						Tess_AddQuadStamp2(quadVerts, lightColor);
 86.6926 +
 86.6927 +						VectorSet4(quadVerts[0], light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2], 1);
 86.6928 +						VectorSet4(quadVerts[1], light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2], 1);
 86.6929 +						VectorSet4(quadVerts[2], light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2], 1);
 86.6930 +						VectorSet4(quadVerts[3], light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2], 1);
 86.6931 +						Tess_AddQuadStamp2(quadVerts, lightColor);
 86.6932 +
 86.6933 +						VectorSet4(quadVerts[0], light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2], 1);
 86.6934 +						VectorSet4(quadVerts[1], light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2], 1);
 86.6935 +						VectorSet4(quadVerts[2], light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2], 1);
 86.6936 +						VectorSet4(quadVerts[3], light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2], 1);
 86.6937 +						Tess_AddQuadStamp2(quadVerts, lightColor);
 86.6938 +
 86.6939 +						VectorSet4(quadVerts[0], light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2], 1);
 86.6940 +						VectorSet4(quadVerts[1], light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2], 1);
 86.6941 +						VectorSet4(quadVerts[2], light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2], 1);
 86.6942 +						VectorSet4(quadVerts[3], light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2], 1);
 86.6943 +						Tess_AddQuadStamp2(quadVerts, lightColor);
 86.6944 +
 86.6945 +						Tess_UpdateVBOs(ATTR_POSITION | ATTR_COLOR);
 86.6946 +						Tess_DrawElements();
 86.6947 +
 86.6948 +						tess.numIndexes = 0;
 86.6949 +						tess.numVertexes = 0;
 86.6950 +						break;
 86.6951 +					}
 86.6952 +
 86.6953 +					case RL_PROJ:
 86.6954 +					{
 86.6955 +						float           xMin, xMax, yMin, yMax;
 86.6956 +						float           zNear, zFar;
 86.6957 +						vec3_t          corners[4];
 86.6958 +
 86.6959 +						zNear = light->l.distNear;
 86.6960 +						zFar = light->l.distFar;
 86.6961 +
 86.6962 +						xMax = zNear * tan(light->l.fovX * M_PI / 360.0f);
 86.6963 +						xMin = -xMax;
 86.6964 +
 86.6965 +						yMax = zNear * tan(light->l.fovY * M_PI / 360.0f);
 86.6966 +						yMin = -yMax;
 86.6967 +
 86.6968 +
 86.6969 +						corners[0][0] = zFar;
 86.6970 +						corners[0][1] = xMin * zFar;
 86.6971 +						corners[0][2] = yMin * zFar;
 86.6972 +
 86.6973 +						corners[1][0] = zFar;
 86.6974 +						corners[1][1] = xMax * zFar;
 86.6975 +						corners[1][2] = yMin * zFar;
 86.6976 +
 86.6977 +						corners[2][0] = zFar;
 86.6978 +						corners[2][1] = xMax * zFar;
 86.6979 +						corners[2][2] = yMax * zFar;
 86.6980 +
 86.6981 +						corners[3][0] = zFar;
 86.6982 +						corners[3][1] = xMin * zFar;
 86.6983 +						corners[3][2] = yMax * zFar;
 86.6984 +
 86.6985 +						/*
 86.6986 +						// draw pyramid
 86.6987 +						qglBegin(GL_LINES);
 86.6988 +
 86.6989 +						qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, lightColor);
 86.6990 +						for(j = 0; j < 4; j++)
 86.6991 +						{
 86.6992 +							qglVertex3fv(corners[j]);
 86.6993 +							qglVertex3fv(corners[(j + 1) % 4]);
 86.6994 +
 86.6995 +							qglVertex3fv(vec3_origin);
 86.6996 +							qglVertex3fv(corners[j]);
 86.6997 +						}
 86.6998 +						qglEnd();
 86.6999 +						*/
 86.7000 +
 86.7001 +						tess.numVertexes = 0;
 86.7002 +						tess.numIndexes = 0;
 86.7003 +
 86.7004 +						for(j = 0; j < 4; j++)
 86.7005 +						{
 86.7006 +							VectorCopy(corners[j], tess.xyz[tess.numVertexes]);
 86.7007 +							VectorCopy4(lightColor, tess.colors[tess.numVertexes]);
 86.7008 +							tess.indexes[tess.numIndexes++] = tess.numVertexes;
 86.7009 +							tess.numVertexes++;
 86.7010 +
 86.7011 +							VectorCopy(corners[(j + 1) % 4], tess.xyz[tess.numVertexes]);
 86.7012 +							VectorCopy4(lightColor, tess.colors[tess.numVertexes]);
 86.7013 +							tess.indexes[tess.numIndexes++] = tess.numVertexes;
 86.7014 +							tess.numVertexes++;
 86.7015 +
 86.7016 +							VectorCopy(vec3_origin, tess.xyz[tess.numVertexes]);
 86.7017 +							VectorCopy4(lightColor, tess.colors[tess.numVertexes]);
 86.7018 +							tess.indexes[tess.numIndexes++] = tess.numVertexes;
 86.7019 +							tess.numVertexes++;
 86.7020 +						}
 86.7021 +
 86.7022 +						VectorSet4(quadVerts[0], corners[0][0], corners[0][1], corners[0][2], 1);
 86.7023 +						VectorSet4(quadVerts[1], corners[1][0], corners[1][1], corners[1][2], 1);
 86.7024 +						VectorSet4(quadVerts[2], corners[2][0], corners[2][1], corners[2][2], 1);
 86.7025 +						VectorSet4(quadVerts[3], corners[3][0], corners[3][1], corners[3][2], 1);
 86.7026 +						Tess_AddQuadStamp2(quadVerts, lightColor);
 86.7027 +
 86.7028 +						Tess_UpdateVBOs(ATTR_POSITION | ATTR_COLOR);
 86.7029 +						Tess_DrawElements();
 86.7030 +
 86.7031 +						tess.numIndexes = 0;
 86.7032 +						tess.numVertexes = 0;
 86.7033 +
 86.7034 +						break;
 86.7035 +					}
 86.7036 +
 86.7037 +					default:
 86.7038 +						break;
 86.7039 +				}
 86.7040 +
 86.7041 +
 86.7042 +				if(iaCount < (backEnd.viewParms.numInteractions - 1))
 86.7043 +				{
 86.7044 +					// jump to next interaction and continue
 86.7045 +					ia++;
 86.7046 +					iaCount++;
 86.7047 +				}
 86.7048 +				else
 86.7049 +				{
 86.7050 +					// increase last time to leave for loop
 86.7051 +					iaCount++;
 86.7052 +				}
 86.7053 +			}
 86.7054 +			else
 86.7055 +			{
 86.7056 +				// just continue
 86.7057 +				ia = ia->next;
 86.7058 +				iaCount++;
 86.7059 +			}
 86.7060 +		}
 86.7061 +
 86.7062 +		// go back to the world modelview matrix
 86.7063 +		backEnd.orientation = backEnd.viewParms.world;
 86.7064 +		GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.7065 +	}
 86.7066 +#endif
 86.7067  
 86.7068  #if 0
 86.7069 -	RB_DrawSun();
 86.7070 +	if(r_showLightInteractions->integer)
 86.7071 +	{
 86.7072 +		int             i;
 86.7073 +		int             cubeSides;
 86.7074 +		interaction_t  *ia;
 86.7075 +		int             iaCount;
 86.7076 +		trRefLight_t   *light;
 86.7077 +		trRefEntity_t  *entity;
 86.7078 +		surfaceType_t  *surface;
 86.7079 +		vec4_t          lightColor;
 86.7080 +
 86.7081 +		GL_BindProgram(NULL);
 86.7082 +		GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
 86.7083 +		GL_SelectTexture(0);
 86.7084 +		GL_Bind(tr.whiteImage);
 86.7085 +
 86.7086 +		for(iaCount = 0, ia = &backEnd.viewParms.interactions[0]; iaCount < backEnd.viewParms.numInteractions;)
 86.7087 +		{
 86.7088 +			backEnd.currentEntity = entity = ia->entity;
 86.7089 +			light = ia->light;
 86.7090 +			surface = ia->surface;
 86.7091 +
 86.7092 +			if(entity != &tr.worldEntity)
 86.7093 +			{
 86.7094 +				// set up the transformation matrix
 86.7095 +				R_RotateEntityForViewParms(backEnd.currentEntity, &backEnd.viewParms, &backEnd.orientation);
 86.7096 +			}
 86.7097 +			else
 86.7098 +			{
 86.7099 +				backEnd.orientation = backEnd.viewParms.world;
 86.7100 +			}
 86.7101 +
 86.7102 +			GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.7103 +
 86.7104 +			if(r_shadows->integer >= 4 && light->l.rlType == RL_OMNI)
 86.7105 +			{
 86.7106 +#if 0
 86.7107 +				VectorCopy4(colorMdGrey, lightColor);
 86.7108 +
 86.7109 +				if(ia->cubeSideBits & CUBESIDE_PX)
 86.7110 +				{
 86.7111 +					VectorCopy4(colorBlack, lightColor);
 86.7112 +				}
 86.7113 +				if(ia->cubeSideBits & CUBESIDE_PY)
 86.7114 +				{
 86.7115 +					VectorCopy4(colorRed, lightColor);
 86.7116 +				}
 86.7117 +				if(ia->cubeSideBits & CUBESIDE_PZ)
 86.7118 +				{
 86.7119 +					VectorCopy4(colorGreen, lightColor);
 86.7120 +				}
 86.7121 +				if(ia->cubeSideBits & CUBESIDE_NX)
 86.7122 +				{
 86.7123 +					VectorCopy4(colorYellow, lightColor);
 86.7124 +				}
 86.7125 +				if(ia->cubeSideBits & CUBESIDE_NY)
 86.7126 +				{
 86.7127 +					VectorCopy4(colorBlue, lightColor);
 86.7128 +				}
 86.7129 +				if(ia->cubeSideBits & CUBESIDE_NZ)
 86.7130 +				{
 86.7131 +					VectorCopy4(colorCyan, lightColor);
 86.7132 +				}
 86.7133 +				if(ia->cubeSideBits == CUBESIDE_CLIPALL)
 86.7134 +				{
 86.7135 +					VectorCopy4(colorMagenta, lightColor);
 86.7136 +				}
 86.7137 +#else
 86.7138 +				// count how many cube sides are in use for this interaction
 86.7139 +				cubeSides = 0;
 86.7140 +				for(i = 0; i < 6; i++)
 86.7141 +				{
 86.7142 +					if(ia->cubeSideBits & (1 << i))
 86.7143 +					{
 86.7144 +						cubeSides++;
 86.7145 +					}
 86.7146 +				}
 86.7147 +
 86.7148 +				VectorCopy4(g_color_table[cubeSides], lightColor);
 86.7149  #endif
 86.7150 -	// darken down any stencil shadows
 86.7151 -	RB_ShadowFinish();		
 86.7152 -
 86.7153 -	// add light flares on lights that aren't obscured
 86.7154 -	RB_RenderFlares();
 86.7155 +			}
 86.7156 +			else
 86.7157 +			{
 86.7158 +				VectorCopy4(colorMdGrey, lightColor);
 86.7159 +			}
 86.7160 +
 86.7161 +			lightColor[0] *= 0.5f;
 86.7162 +			lightColor[1] *= 0.5f;
 86.7163 +			lightColor[2] *= 0.5f;
 86.7164 +			//lightColor[3] *= 0.2f;
 86.7165 +
 86.7166 +			if(*surface == SF_FACE)
 86.7167 +			{
 86.7168 +				srfSurfaceFace_t *face;
 86.7169 +
 86.7170 +				face = (srfSurfaceFace_t *) surface;
 86.7171 +				R_DebugBoundingBox(vec3_origin, face->bounds[0], face->bounds[1], lightColor);
 86.7172 +			}
 86.7173 +			else if(*surface == SF_GRID)
 86.7174 +			{
 86.7175 +				srfGridMesh_t  *grid;
 86.7176 +
 86.7177 +				grid = (srfGridMesh_t *) surface;
 86.7178 +				R_DebugBoundingBox(vec3_origin, grid->meshBounds[0], grid->meshBounds[1], lightColor);
 86.7179 +			}
 86.7180 +			else if(*surface == SF_TRIANGLES)
 86.7181 +			{
 86.7182 +				srfTriangles_t *tri;
 86.7183 +
 86.7184 +				tri = (srfTriangles_t *) surface;
 86.7185 +				R_DebugBoundingBox(vec3_origin, tri->bounds[0], tri->bounds[1], lightColor);
 86.7186 +			}
 86.7187 +			else if(*surface == SF_VBO_MESH)
 86.7188 +			{
 86.7189 +				srfVBOMesh_t   *srf = (srfVBOMesh_t *) surface;
 86.7190 +
 86.7191 +				R_DebugBoundingBox(vec3_origin, srf->bounds[0], srf->bounds[1], lightColor);
 86.7192 +			}
 86.7193 +			else if(*surface == SF_MDX)
 86.7194 +			{
 86.7195 +				R_DebugBoundingBox(vec3_origin, entity->localBounds[0], entity->localBounds[1], lightColor);
 86.7196 +			}
 86.7197 +
 86.7198 +			if(!ia->next)
 86.7199 +			{
 86.7200 +				if(iaCount < (backEnd.viewParms.numInteractions - 1))
 86.7201 +				{
 86.7202 +					// jump to next interaction and continue
 86.7203 +					ia++;
 86.7204 +					iaCount++;
 86.7205 +				}
 86.7206 +				else
 86.7207 +				{
 86.7208 +					// increase last time to leave for loop
 86.7209 +					iaCount++;
 86.7210 +				}
 86.7211 +			}
 86.7212 +			else
 86.7213 +			{
 86.7214 +				// just continue
 86.7215 +				ia = ia->next;
 86.7216 +				iaCount++;
 86.7217 +			}
 86.7218 +		}
 86.7219 +
 86.7220 +		// go back to the world modelview matrix
 86.7221 +		backEnd.orientation = backEnd.viewParms.world;
 86.7222 +		GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.7223 +	}
 86.7224 +#endif
 86.7225 +
 86.7226 +#if 1
 86.7227 +	if(r_showEntityTransforms->integer)
 86.7228 +	{
 86.7229 +		trRefEntity_t  *ent;
 86.7230 +		int             i;
 86.7231 +		vec4_t          quadVerts[4];
 86.7232 +
 86.7233 +		GL_BindProgram(&tr.genericSingleShader);
 86.7234 +		GL_State(GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE);
 86.7235 +		GL_Cull(CT_TWO_SIDED);
 86.7236 +
 86.7237 +		// set uniforms
 86.7238 +		GLSL_SetUniform_TCGen_Environment(&tr.genericSingleShader,  qfalse);
 86.7239 +		GLSL_SetUniform_ColorGen(&tr.genericSingleShader, CGEN_VERTEX);
 86.7240 +		GLSL_SetUniform_AlphaGen(&tr.genericSingleShader, AGEN_VERTEX);
 86.7241 +		if(glConfig.vboVertexSkinningAvailable)
 86.7242 +		{
 86.7243 +			GLSL_SetUniform_VertexSkinning(&tr.genericSingleShader, qfalse);
 86.7244 +		}
 86.7245 +		GLSL_SetUniform_AlphaTest(&tr.genericSingleShader, 0);
 86.7246 +
 86.7247 +		// bind u_ColorMap
 86.7248 +		GL_SelectTexture(0);
 86.7249 +		GL_Bind(tr.whiteImage);
 86.7250 +		GLSL_SetUniform_ColorTextureMatrix(&tr.genericSingleShader, matrixIdentity);
 86.7251 +
 86.7252 +		ent = backEnd.refdef.entities;
 86.7253 +		for(i = 0; i < backEnd.refdef.numEntities; i++, ent++)
 86.7254 +		{
 86.7255 +			if((ent->e.renderfx & RF_THIRD_PERSON) && !backEnd.viewParms.isPortal)
 86.7256 +				continue;
 86.7257 +
 86.7258 +			// set up the transformation matrix
 86.7259 +			R_RotateEntityForViewParms(ent, &backEnd.viewParms, &backEnd.orientation);
 86.7260 +			GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.7261 +			GLSL_SetUniform_ModelViewProjectionMatrix(&tr.genericSingleShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.7262 +
 86.7263 +			R_DebugAxis(vec3_origin, matrixIdentity);
 86.7264 +			//R_DebugBoundingBox(vec3_origin, ent->localBounds[0], ent->localBounds[1], colorMagenta);
 86.7265 +			tess.numIndexes = 0;
 86.7266 +			tess.numVertexes = 0;
 86.7267 +
 86.7268 +			VectorSet4(quadVerts[0], ent->localBounds[0][0], ent->localBounds[0][1], ent->localBounds[0][2], 1);
 86.7269 +			VectorSet4(quadVerts[1], ent->localBounds[0][0], ent->localBounds[1][1], ent->localBounds[0][2], 1);
 86.7270 +			VectorSet4(quadVerts[2], ent->localBounds[0][0], ent->localBounds[1][1], ent->localBounds[1][2], 1);
 86.7271 +			VectorSet4(quadVerts[3], ent->localBounds[0][0], ent->localBounds[0][1], ent->localBounds[1][2], 1);
 86.7272 +			Tess_AddQuadStamp2(quadVerts, colorRed);
 86.7273 +
 86.7274 +			VectorSet4(quadVerts[0], ent->localBounds[1][0], ent->localBounds[0][1], ent->localBounds[1][2], 1);
 86.7275 +			VectorSet4(quadVerts[1], ent->localBounds[1][0], ent->localBounds[1][1], ent->localBounds[1][2], 1);
 86.7276 +			VectorSet4(quadVerts[2], ent->localBounds[1][0], ent->localBounds[1][1], ent->localBounds[0][2], 1);
 86.7277 +			VectorSet4(quadVerts[3], ent->localBounds[1][0], ent->localBounds[0][1], ent->localBounds[0][2], 1);
 86.7278 +			Tess_AddQuadStamp2(quadVerts, colorGreen);
 86.7279 +
 86.7280 +			VectorSet4(quadVerts[0], ent->localBounds[0][0], ent->localBounds[0][1], ent->localBounds[1][2], 1);
 86.7281 +			VectorSet4(quadVerts[1], ent->localBounds[0][0], ent->localBounds[1][1], ent->localBounds[1][2], 1);
 86.7282 +			VectorSet4(quadVerts[2], ent->localBounds[1][0], ent->localBounds[1][1], ent->localBounds[1][2], 1);
 86.7283 +			VectorSet4(quadVerts[3], ent->localBounds[1][0], ent->localBounds[0][1], ent->localBounds[1][2], 1);
 86.7284 +			Tess_AddQuadStamp2(quadVerts, colorBlue);
 86.7285 +
 86.7286 +			VectorSet4(quadVerts[0], ent->localBounds[1][0], ent->localBounds[0][1], ent->localBounds[0][2], 1);
 86.7287 +			VectorSet4(quadVerts[1], ent->localBounds[1][0], ent->localBounds[1][1], ent->localBounds[0][2], 1);
 86.7288 +			VectorSet4(quadVerts[2], ent->localBounds[0][0], ent->localBounds[1][1], ent->localBounds[0][2], 1);
 86.7289 +			VectorSet4(quadVerts[3], ent->localBounds[0][0], ent->localBounds[0][1], ent->localBounds[0][2], 1);
 86.7290 +			Tess_AddQuadStamp2(quadVerts, colorYellow);
 86.7291 +
 86.7292 +			VectorSet4(quadVerts[0], ent->localBounds[0][0], ent->localBounds[0][1], ent->localBounds[0][2], 1);
 86.7293 +			VectorSet4(quadVerts[1], ent->localBounds[0][0], ent->localBounds[0][1], ent->localBounds[1][2], 1);
 86.7294 +			VectorSet4(quadVerts[2], ent->localBounds[1][0], ent->localBounds[0][1], ent->localBounds[1][2], 1);
 86.7295 +			VectorSet4(quadVerts[3], ent->localBounds[1][0], ent->localBounds[0][1], ent->localBounds[0][2], 1);
 86.7296 +			Tess_AddQuadStamp2(quadVerts, colorMagenta);
 86.7297 +
 86.7298 +			VectorSet4(quadVerts[0], ent->localBounds[1][0], ent->localBounds[1][1], ent->localBounds[0][2], 1);
 86.7299 +			VectorSet4(quadVerts[1], ent->localBounds[1][0], ent->localBounds[1][1], ent->localBounds[1][2], 1);
 86.7300 +			VectorSet4(quadVerts[2], ent->localBounds[0][0], ent->localBounds[1][1], ent->localBounds[1][2], 1);
 86.7301 +			VectorSet4(quadVerts[3], ent->localBounds[0][0], ent->localBounds[1][1], ent->localBounds[0][2], 1);
 86.7302 +			Tess_AddQuadStamp2(quadVerts, colorCyan);
 86.7303 +
 86.7304 +			Tess_UpdateVBOs(ATTR_POSITION | ATTR_COLOR);
 86.7305 +			Tess_DrawElements();
 86.7306 +
 86.7307 +			tess.numIndexes = 0;
 86.7308 +			tess.numVertexes = 0;
 86.7309 +
 86.7310 +
 86.7311 +			// go back to the world modelview matrix
 86.7312 +			//backEnd.orientation = backEnd.viewParms.world;
 86.7313 +			//GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.7314 +
 86.7315 +			//R_DebugBoundingBox(vec3_origin, ent->worldBounds[0], ent->worldBounds[1], colorCyan);
 86.7316 +		}
 86.7317 +
 86.7318 +		// go back to the world modelview matrix
 86.7319 +		backEnd.orientation = backEnd.viewParms.world;
 86.7320 +		GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.7321 +	}
 86.7322 +#endif
 86.7323 +
 86.7324 +#if 1
 86.7325 +	if(r_showSkeleton->integer)
 86.7326 +	{
 86.7327 +		int             i, j, k, parentIndex;
 86.7328 +		trRefEntity_t  *ent;
 86.7329 +		vec3_t          origin, offset;
 86.7330 +		vec3_t          forward, right, up;
 86.7331 +		vec3_t          diff, tmp, tmp2, tmp3;
 86.7332 +		vec_t           length;
 86.7333 +		vec4_t          tetraVerts[4];
 86.7334 +		static refSkeleton_t skeleton;
 86.7335 +		refSkeleton_t  *skel;
 86.7336 +
 86.7337 +		GL_BindProgram(&tr.genericSingleShader);
 86.7338 +		GL_Cull(CT_TWO_SIDED);
 86.7339 +
 86.7340 +		// set uniforms
 86.7341 +		GLSL_SetUniform_TCGen_Environment(&tr.genericSingleShader,  qfalse);
 86.7342 +		GLSL_SetUniform_ColorGen(&tr.genericSingleShader, CGEN_VERTEX);
 86.7343 +		GLSL_SetUniform_AlphaGen(&tr.genericSingleShader, AGEN_VERTEX);
 86.7344 +		if(glConfig.vboVertexSkinningAvailable)
 86.7345 +		{
 86.7346 +			GLSL_SetUniform_VertexSkinning(&tr.genericSingleShader, qfalse);
 86.7347 +		}
 86.7348 +		GLSL_SetUniform_AlphaTest(&tr.genericSingleShader, 0);
 86.7349 +
 86.7350 +		// bind u_ColorMap
 86.7351 +		GL_SelectTexture(0);
 86.7352 +		GL_Bind(tr.charsetImage);
 86.7353 +		GLSL_SetUniform_ColorTextureMatrix(&tr.genericSingleShader, matrixIdentity);
 86.7354 +
 86.7355 +		ent = backEnd.refdef.entities;
 86.7356 +		for(i = 0; i < backEnd.refdef.numEntities; i++, ent++)
 86.7357 +		{
 86.7358 +			if((ent->e.renderfx & RF_THIRD_PERSON) && !backEnd.viewParms.isPortal)
 86.7359 +				continue;
 86.7360 +
 86.7361 +			// set up the transformation matrix
 86.7362 +			R_RotateEntityForViewParms(ent, &backEnd.viewParms, &backEnd.orientation);
 86.7363 +			GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.7364 +			GLSL_SetUniform_ModelViewProjectionMatrix(&tr.genericSingleShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.7365 +
 86.7366 +
 86.7367 +			tess.numVertexes = 0;
 86.7368 +			tess.numIndexes = 0;
 86.7369 +
 86.7370 +			skel = NULL;
 86.7371 +			if(ent->e.skeleton.type == SK_ABSOLUTE)
 86.7372 +			{
 86.7373 +				skel = &ent->e.skeleton;
 86.7374 +			}
 86.7375 +			else
 86.7376 +			{
 86.7377 +				model_t        *model;
 86.7378 +				refBone_t      *bone;
 86.7379 +
 86.7380 +				model = R_GetModelByHandle(ent->e.hModel);
 86.7381 +
 86.7382 +				if(model)
 86.7383 +				{
 86.7384 +					switch (model->type)
 86.7385 +					{
 86.7386 +						case MOD_MD5:
 86.7387 +						{
 86.7388 +							// copy absolute bones
 86.7389 +							skeleton.numBones = model->md5->numBones;
 86.7390 +							for(j = 0, bone = &skeleton.bones[0]; j < skeleton.numBones; j++, bone++)
 86.7391 +							{
 86.7392 +								Q_strncpyz(bone->name, model->md5->bones[j].name, sizeof(bone->name));
 86.7393 +
 86.7394 +								bone->parentIndex = model->md5->bones[j].parentIndex;
 86.7395 +								VectorCopy(model->md5->bones[j].origin, bone->origin);
 86.7396 +								VectorCopy(model->md5->bones[j].rotation, bone->rotation);
 86.7397 +							}
 86.7398 +
 86.7399 +							skel = &skeleton;
 86.7400 +							break;
 86.7401 +						}
 86.7402 +
 86.7403 +						default:
 86.7404 +							break;
 86.7405 +					}
 86.7406 +				}
 86.7407 +			}
 86.7408 +
 86.7409 +			if(skel)
 86.7410 +			{
 86.7411 +				static vec3_t	worldOrigins[MAX_BONES];
 86.7412 +
 86.7413 +				GL_State(GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE);
 86.7414 +
 86.7415 +				for(j = 0; j < skel->numBones; j++)
 86.7416 +				{
 86.7417 +					parentIndex = skel->bones[j].parentIndex;
 86.7418 +
 86.7419 +					if(parentIndex < 0)
 86.7420 +					{
 86.7421 +						VectorClear(origin);
 86.7422 +					}
 86.7423 +					else
 86.7424 +					{
 86.7425 +						VectorCopy(skel->bones[parentIndex].origin, origin);
 86.7426 +					}
 86.7427 +					VectorCopy(skel->bones[j].origin, offset);
 86.7428 +					QuatToVectorsFRU(skel->bones[j].rotation, forward, right, up);
 86.7429 +
 86.7430 +					VectorSubtract(offset, origin, diff);
 86.7431 +					if((length = VectorNormalize(diff)))
 86.7432 +					{
 86.7433 +						PerpendicularVector(tmp, diff);
 86.7434 +						//VectorCopy(up, tmp);
 86.7435 +
 86.7436 +						VectorScale(tmp, length * 0.1, tmp2);
 86.7437 +						VectorMA(tmp2, length * 0.2, diff, tmp2);
 86.7438 +
 86.7439 +						for(k = 0; k < 3; k++)
 86.7440 +						{
 86.7441 +							RotatePointAroundVector(tmp3, diff, tmp2, k * 120);
 86.7442 +							VectorAdd(tmp3, origin, tmp3);
 86.7443 +							VectorCopy(tmp3, tetraVerts[k]);
 86.7444 +							tetraVerts[k][3] = 1;
 86.7445 +						}
 86.7446 +
 86.7447 +						VectorCopy(origin, tetraVerts[3]);
 86.7448 +						tetraVerts[3][3] = 1;
 86.7449 +						Tess_AddTetrahedron(tetraVerts, g_color_table[j % MAX_CCODES]);
 86.7450 +
 86.7451 +						VectorCopy(offset, tetraVerts[3]);
 86.7452 +						tetraVerts[3][3] = 1;
 86.7453 +						Tess_AddTetrahedron(tetraVerts, g_color_table[j % MAX_CCODES]);
 86.7454 +					}
 86.7455 +
 86.7456 +					MatrixTransformPoint(backEnd.orientation.transformMatrix, skel->bones[j].origin, worldOrigins[j]);
 86.7457 +				}
 86.7458 +
 86.7459 +				Tess_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD | ATTR_COLOR);
 86.7460 +
 86.7461 +				Tess_DrawElements();
 86.7462 +
 86.7463 +				tess.numVertexes = 0;
 86.7464 +				tess.numIndexes = 0;
 86.7465 +
 86.7466 +				//if(r_showSkeleton->integer == 2)
 86.7467 +				{
 86.7468 +					GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
 86.7469 +
 86.7470 +					// go back to the world modelview matrix
 86.7471 +					backEnd.orientation = backEnd.viewParms.world;
 86.7472 +					GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.7473 +					GLSL_SetUniform_ModelViewProjectionMatrix(&tr.genericSingleShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.7474 +
 86.7475 +					// draw names
 86.7476 +					for(j = 0; j < skel->numBones; j++)
 86.7477 +					{
 86.7478 +						vec3_t          left, up;
 86.7479 +						float           radius;
 86.7480 +						vec3_t			origin;
 86.7481 +
 86.7482 +						// calculate the xyz locations for the four corners
 86.7483 +						radius = 0.4;
 86.7484 +						VectorScale(backEnd.viewParms.orientation.axis[1], radius, left);
 86.7485 +						VectorScale(backEnd.viewParms.orientation.axis[2], radius, up);
 86.7486 +
 86.7487 +						if(backEnd.viewParms.isMirror)
 86.7488 +						{
 86.7489 +							VectorSubtract(vec3_origin, left, left);
 86.7490 +						}
 86.7491 +
 86.7492 +						for(k = 0; k < strlen(skel->bones[j].name); k++)
 86.7493 +						{
 86.7494 +							int				ch;
 86.7495 +							int             row, col;
 86.7496 +							float           frow, fcol;
 86.7497 +							float           size;
 86.7498 +
 86.7499 +							ch = skel->bones[j].name[k];
 86.7500 +							ch &= 255;
 86.7501 +
 86.7502 +							if(ch == ' ')
 86.7503 +							{
 86.7504 +								break;
 86.7505 +							}
 86.7506 +
 86.7507 +							row = ch >> 4;
 86.7508 +							col = ch & 15;
 86.7509 +
 86.7510 +							frow = row * 0.0625;
 86.7511 +							fcol = col * 0.0625;
 86.7512 +							size = 0.0625;
 86.7513 +
 86.7514 +							VectorMA(worldOrigins[j], -(k + 2.0f), left, origin);
 86.7515 +							Tess_AddQuadStampExt(origin, left, up, colorWhite, fcol, frow, fcol + size, frow + size);
 86.7516 +						}
 86.7517 +
 86.7518 +						Tess_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD | ATTR_COLOR);
 86.7519 +
 86.7520 +						Tess_DrawElements();
 86.7521 +
 86.7522 +						tess.numVertexes = 0;
 86.7523 +						tess.numIndexes = 0;
 86.7524 +					}
 86.7525 +				}
 86.7526 +			}
 86.7527 +
 86.7528 +			tess.numVertexes = 0;
 86.7529 +			tess.numIndexes = 0;
 86.7530 +		}
 86.7531 +	}
 86.7532 +#endif
 86.7533 +
 86.7534 +	if(r_showLightScissors->integer)
 86.7535 +	{
 86.7536 +		interaction_t  *ia;
 86.7537 +		int             iaCount;
 86.7538 +		matrix_t        ortho;
 86.7539 +		vec4_t          quadVerts[4];
 86.7540 +
 86.7541 +		GL_BindProgram(&tr.genericSingleShader);
 86.7542 +		GL_State(GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE);
 86.7543 +		GL_Cull(CT_TWO_SIDED);
 86.7544 +
 86.7545 +		// set uniforms
 86.7546 +		GLSL_SetUniform_TCGen_Environment(&tr.genericSingleShader,  qfalse);
 86.7547 +		GLSL_SetUniform_ColorGen(&tr.genericSingleShader, CGEN_VERTEX);
 86.7548 +		GLSL_SetUniform_AlphaGen(&tr.genericSingleShader, AGEN_VERTEX);
 86.7549 +		if(glConfig.vboVertexSkinningAvailable)
 86.7550 +		{
 86.7551 +			GLSL_SetUniform_VertexSkinning(&tr.genericSingleShader, qfalse);
 86.7552 +		}
 86.7553 +		GLSL_SetUniform_AlphaTest(&tr.genericSingleShader, 0);
 86.7554 +
 86.7555 +		// bind u_ColorMap
 86.7556 +		GL_SelectTexture(0);
 86.7557 +		GL_Bind(tr.whiteImage);
 86.7558 +		GLSL_SetUniform_ColorTextureMatrix(&tr.genericSingleShader, matrixIdentity);
 86.7559 +
 86.7560 +		// set 2D virtual screen size
 86.7561 +		GL_PushMatrix();
 86.7562 +		MatrixSetupOrthogonalProjection(ortho, backEnd.viewParms.viewportX,
 86.7563 +										backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
 86.7564 +										backEnd.viewParms.viewportY,
 86.7565 +										backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight, -99999, 99999);
 86.7566 +		GL_LoadProjectionMatrix(ortho);
 86.7567 +		GL_LoadModelViewMatrix(matrixIdentity);
 86.7568 +
 86.7569 +		GLSL_SetUniform_ModelViewProjectionMatrix(&tr.genericSingleShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.7570 +
 86.7571 +		for(iaCount = 0, ia = &backEnd.viewParms.interactions[0]; iaCount < backEnd.viewParms.numInteractions;)
 86.7572 +		{
 86.7573 +			if(glConfig.occlusionQueryBits && glConfig.driverType != GLDRV_MESA)
 86.7574 +			{
 86.7575 +				if(!ia->occlusionQuerySamples)
 86.7576 +				{
 86.7577 +					qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorRed);
 86.7578 +				}
 86.7579 +				else
 86.7580 +				{
 86.7581 +					qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorGreen);
 86.7582 +				}
 86.7583 +
 86.7584 +				VectorSet4(quadVerts[0], ia->scissorX, ia->scissorY, 0, 1);
 86.7585 +				VectorSet4(quadVerts[1], ia->scissorX + ia->scissorWidth - 1, ia->scissorY, 0, 1);
 86.7586 +				VectorSet4(quadVerts[2], ia->scissorX + ia->scissorWidth - 1, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.7587 +				VectorSet4(quadVerts[3], ia->scissorX, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.7588 +				Tess_InstantQuad(quadVerts);
 86.7589 +			}
 86.7590 +			else if(r_shadows->integer == 3 && qglDepthBoundsEXT)
 86.7591 +			{
 86.7592 +				if(ia->noDepthBoundsTest)
 86.7593 +				{
 86.7594 +					qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorBlue);
 86.7595 +				}
 86.7596 +				else
 86.7597 +				{
 86.7598 +					qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorGreen);
 86.7599 +				}
 86.7600 +
 86.7601 +				VectorSet4(quadVerts[0], ia->scissorX, ia->scissorY, 0, 1);
 86.7602 +				VectorSet4(quadVerts[1], ia->scissorX + ia->scissorWidth - 1, ia->scissorY, 0, 1);
 86.7603 +				VectorSet4(quadVerts[2], ia->scissorX + ia->scissorWidth - 1, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.7604 +				VectorSet4(quadVerts[3], ia->scissorX, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.7605 +				Tess_InstantQuad(quadVerts);
 86.7606 +			}
 86.7607 +			else
 86.7608 +			{
 86.7609 +				qglVertexAttrib4fvARB(ATTR_INDEX_COLOR, colorWhite);
 86.7610 +
 86.7611 +				VectorSet4(quadVerts[0], ia->scissorX, ia->scissorY, 0, 1);
 86.7612 +				VectorSet4(quadVerts[1], ia->scissorX + ia->scissorWidth - 1, ia->scissorY, 0, 1);
 86.7613 +				VectorSet4(quadVerts[2], ia->scissorX + ia->scissorWidth - 1, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.7614 +				VectorSet4(quadVerts[3], ia->scissorX, ia->scissorY + ia->scissorHeight - 1, 0, 1);
 86.7615 +				Tess_InstantQuad(quadVerts);
 86.7616 +			}
 86.7617 +
 86.7618 +			if(!ia->next)
 86.7619 +			{
 86.7620 +				if(iaCount < (backEnd.viewParms.numInteractions - 1))
 86.7621 +				{
 86.7622 +					// jump to next interaction and continue
 86.7623 +					ia++;
 86.7624 +					iaCount++;
 86.7625 +				}
 86.7626 +				else
 86.7627 +				{
 86.7628 +					// increase last time to leave for loop
 86.7629 +					iaCount++;
 86.7630 +				}
 86.7631 +			}
 86.7632 +			else
 86.7633 +			{
 86.7634 +				// just continue
 86.7635 +				ia = ia->next;
 86.7636 +				iaCount++;
 86.7637 +			}
 86.7638 +		}
 86.7639 +
 86.7640 +		GL_PopMatrix();
 86.7641 +	}
 86.7642 +
 86.7643 +#if 1
 86.7644 +	if(r_showCubeProbes->integer)
 86.7645 +	{
 86.7646 +		cubemapProbe_t *cubeProbe;
 86.7647 +		int             j;
 86.7648 +		vec4_t          quadVerts[4];
 86.7649 +		vec4_t			plane;
 86.7650 +		vec3_t			mins = {-8, -8, -8};
 86.7651 +		vec3_t			maxs = { 8,  8,  8};
 86.7652 +		vec3_t			viewOrigin;
 86.7653 +
 86.7654 +		if(tr.refdef.rdflags & (RDF_NOWORLDMODEL | RDF_NOCUBEMAP))
 86.7655 +		{
 86.7656 +			return;
 86.7657 +		}
 86.7658 +
 86.7659 +		// enable shader, set arrays
 86.7660 +		GL_BindProgram(&tr.reflectionShader_C);
 86.7661 +		GL_Cull(CT_FRONT_SIDED);
 86.7662 +
 86.7663 +		// set uniforms
 86.7664 +		VectorCopy(backEnd.viewParms.orientation.origin, viewOrigin);	// in world space
 86.7665 +		GLSL_SetUniform_ViewOrigin(&tr.reflectionShader_C, viewOrigin);
 86.7666 +		if(glConfig.vboVertexSkinningAvailable)
 86.7667 +		{
 86.7668 +			GLSL_SetUniform_VertexSkinning(&tr.genericSingleShader, qfalse);
 86.7669 +		}
 86.7670 +
 86.7671 +		for(j = 0; j < tr.cubeProbes.currentElements; j++)
 86.7672 +		{
 86.7673 +			cubeProbe = Com_GrowListElement(&tr.cubeProbes, j);
 86.7674 +
 86.7675 +			// bind u_ColorMap
 86.7676 +			GL_SelectTexture(0);
 86.7677 +			GL_Bind(cubeProbe->cubemap);
 86.7678 +
 86.7679 +			// set up the transformation matrix
 86.7680 +			MatrixSetupTranslation(backEnd.orientation.transformMatrix, cubeProbe->origin[0], cubeProbe->origin[1], cubeProbe->origin[2]);
 86.7681 +			MatrixMultiply(backEnd.viewParms.world.viewMatrix, backEnd.orientation.transformMatrix, backEnd.orientation.modelViewMatrix);
 86.7682 +
 86.7683 +			GL_LoadModelViewMatrix(backEnd.orientation.modelViewMatrix);
 86.7684 +			GLSL_SetUniform_ModelMatrix(&tr.reflectionShader_C, backEnd.orientation.transformMatrix);
 86.7685 +			GLSL_SetUniform_ModelViewProjectionMatrix(&tr.reflectionShader_C, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.7686 +
 86.7687 +			tess.numIndexes = 0;
 86.7688 +			tess.numVertexes = 0;
 86.7689 +
 86.7690 +			VectorSet4(quadVerts[0], mins[0], mins[1], mins[2], 1);
 86.7691 +			VectorSet4(quadVerts[1], mins[0], maxs[1], mins[2], 1);
 86.7692 +			VectorSet4(quadVerts[2], mins[0], maxs[1], maxs[2], 1);
 86.7693 +			VectorSet4(quadVerts[3], mins[0], mins[1], maxs[2], 1);
 86.7694 +			Tess_AddQuadStamp2WithNormals(quadVerts, colorWhite);
 86.7695 +
 86.7696 +			VectorSet4(quadVerts[0], maxs[0], mins[1], maxs[2], 1);
 86.7697 +			VectorSet4(quadVerts[1], maxs[0], maxs[1], maxs[2], 1);
 86.7698 +			VectorSet4(quadVerts[2], maxs[0], maxs[1], mins[2], 1);
 86.7699 +			VectorSet4(quadVerts[3], maxs[0], mins[1], mins[2], 1);
 86.7700 +			Tess_AddQuadStamp2WithNormals(quadVerts, colorWhite);
 86.7701 +
 86.7702 +			VectorSet4(quadVerts[0], mins[0], mins[1], maxs[2], 1);
 86.7703 +			VectorSet4(quadVerts[1], mins[0], maxs[1], maxs[2], 1);
 86.7704 +			VectorSet4(quadVerts[2], maxs[0], maxs[1], maxs[2], 1);
 86.7705 +			VectorSet4(quadVerts[3], maxs[0], mins[1], maxs[2], 1);
 86.7706 +			Tess_AddQuadStamp2WithNormals(quadVerts, colorWhite);
 86.7707 +
 86.7708 +			VectorSet4(quadVerts[0], maxs[0], mins[1], mins[2], 1);
 86.7709 +			VectorSet4(quadVerts[1], maxs[0], maxs[1], mins[2], 1);
 86.7710 +			VectorSet4(quadVerts[2], mins[0], maxs[1], mins[2], 1);
 86.7711 +			VectorSet4(quadVerts[3], mins[0], mins[1], mins[2], 1);
 86.7712 +			Tess_AddQuadStamp2WithNormals(quadVerts, colorWhite);
 86.7713 +
 86.7714 +			VectorSet4(quadVerts[0], mins[0], mins[1], mins[2], 1);
 86.7715 +			VectorSet4(quadVerts[1], mins[0], mins[1], maxs[2], 1);
 86.7716 +			VectorSet4(quadVerts[2], maxs[0], mins[1], maxs[2], 1);
 86.7717 +			VectorSet4(quadVerts[3], maxs[0], mins[1], mins[2], 1);
 86.7718 +			Tess_AddQuadStamp2WithNormals(quadVerts, colorWhite);
 86.7719 +
 86.7720 +			VectorSet4(quadVerts[0], maxs[0], maxs[1], mins[2], 1);
 86.7721 +			VectorSet4(quadVerts[1], maxs[0], maxs[1], maxs[2], 1);
 86.7722 +			VectorSet4(quadVerts[2], mins[0], maxs[1], maxs[2], 1);
 86.7723 +			VectorSet4(quadVerts[3], mins[0], maxs[1], mins[2], 1);
 86.7724 +			Tess_AddQuadStamp2WithNormals(quadVerts, colorWhite);
 86.7725 +
 86.7726 +			Tess_UpdateVBOs(ATTR_POSITION | ATTR_NORMAL);
 86.7727 +			Tess_DrawElements();
 86.7728 +
 86.7729 +			tess.numIndexes = 0;
 86.7730 +			tess.numVertexes = 0;
 86.7731 +		}
 86.7732 +
 86.7733 +		// go back to the world modelview matrix
 86.7734 +		backEnd.orientation = backEnd.viewParms.world;
 86.7735 +		GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
 86.7736 +	}
 86.7737 +#endif
 86.7738 +
 86.7739 +	GL_CheckErrors();
 86.7740 +}
 86.7741 +
 86.7742 +/*
 86.7743 +==================
 86.7744 +RB_RenderView
 86.7745 +==================
 86.7746 +*/
 86.7747 +static void RB_RenderView(void)
 86.7748 +{
 86.7749 +	if(r_logFile->integer)
 86.7750 +	{
 86.7751 +		// don't just call LogComment, or we will get a call to va() every frame!
 86.7752 +		GLimp_LogComment(va
 86.7753 +						 ("--- RB_RenderView( %i surfaces, %i interactions ) ---\n", backEnd.viewParms.numDrawSurfs,
 86.7754 +						  backEnd.viewParms.numInteractions));
 86.7755 +	}
 86.7756 +
 86.7757 +	GL_CheckErrors();
 86.7758 +
 86.7759 +	backEnd.pc.c_surfaces += backEnd.viewParms.numDrawSurfs;
 86.7760 +
 86.7761 +	if(r_deferredShading->integer && glConfig.framebufferObjectAvailable && glConfig.textureFloatAvailable &&
 86.7762 +	   glConfig.drawBuffersAvailable && glConfig.maxDrawBuffers >= 4)
 86.7763 +	{
 86.7764 +		int             clearBits = 0;
 86.7765 +
 86.7766 +		// sync with gl if needed
 86.7767 +		if(r_finish->integer == 1 && !glState.finishCalled)
 86.7768 +		{
 86.7769 +			qglFinish();
 86.7770 +			glState.finishCalled = qtrue;
 86.7771 +		}
 86.7772 +		if(r_finish->integer == 0)
 86.7773 +		{
 86.7774 +			glState.finishCalled = qtrue;
 86.7775 +		}
 86.7776 +
 86.7777 +		// we will need to change the projection matrix before drawing
 86.7778 +		// 2D images again
 86.7779 +		backEnd.projection2D = qfalse;
 86.7780 +
 86.7781 +		// set the modelview matrix for the viewer
 86.7782 +		SetViewportAndScissor();
 86.7783 +
 86.7784 +		// ensures that depth writes are enabled for the depth clear
 86.7785 +		GL_State(GLS_DEFAULT);
 86.7786 +
 86.7787 +		// clear frame buffer objects
 86.7788 +		R_BindFBO(tr.deferredRenderFBO);
 86.7789 +		//qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 86.7790 +
 86.7791 +		clearBits = GL_DEPTH_BUFFER_BIT;
 86.7792 +
 86.7793 +		/*
 86.7794 +		   if(r_measureOverdraw->integer || r_shadows->integer == 3)
 86.7795 +		   {
 86.7796 +		   clearBits |= GL_STENCIL_BUFFER_BIT;
 86.7797 +		   }
 86.7798 +		 */
 86.7799 +		if(!(backEnd.refdef.rdflags & RDF_NOWORLDMODEL))
 86.7800 +		{
 86.7801 +			clearBits |= GL_COLOR_BUFFER_BIT;
 86.7802 +			GL_ClearColor(0.0f, 0.0f, 0.0f, 1.0f);	// FIXME: get color of sky
 86.7803 +		}
 86.7804 +		qglClear(clearBits);
 86.7805 +
 86.7806 +		R_BindFBO(tr.geometricRenderFBO);
 86.7807 +		if(!(backEnd.refdef.rdflags & RDF_NOWORLDMODEL))
 86.7808 +		{
 86.7809 +			clearBits = GL_COLOR_BUFFER_BIT;
 86.7810 +			GL_ClearColor(0.0f, 0.0f, 0.0f, 1.0f);	// FIXME: get color of sky
 86.7811 +		}
 86.7812 +		else
 86.7813 +		{
 86.7814 +			if(glConfig.framebufferBlitAvailable)
 86.7815 +			{
 86.7816 +				// copy color of the main context to deferredRenderFBO
 86.7817 +				qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
 86.7818 +				qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, tr.deferredRenderFBO->frameBuffer);
 86.7819 +				qglBlitFramebufferEXT(0, 0, glConfig.vidWidth, glConfig.vidHeight,
 86.7820 +									   0, 0, glConfig.vidWidth, glConfig.vidHeight,
 86.7821 +									   GL_COLOR_BUFFER_BIT,
 86.7822 +									   GL_NEAREST);
 86.7823 +			}
 86.7824 +		}
 86.7825 +		qglClear(clearBits);
 86.7826 +
 86.7827 +
 86.7828 +		if((backEnd.refdef.rdflags & RDF_HYPERSPACE))
 86.7829 +		{
 86.7830 +			RB_Hyperspace();
 86.7831 +			return;
 86.7832 +		}
 86.7833 +		else
 86.7834 +		{
 86.7835 +			backEnd.isHyperspace = qfalse;
 86.7836 +		}
 86.7837 +
 86.7838 +		glState.faceCulling = -1;	// force face culling to set next time
 86.7839 +
 86.7840 +		// we will only draw a sun if there was sky rendered in this view
 86.7841 +		backEnd.skyRenderedThisView = qfalse;
 86.7842 +
 86.7843 +		GL_CheckErrors();
 86.7844 +
 86.7845 +#if 1
 86.7846 +		// draw everything that is opaque
 86.7847 +		R_BindFBO(tr.deferredRenderFBO);
 86.7848 +		RB_RenderDrawSurfaces(qtrue, qfalse);
 86.7849 +#endif
 86.7850 +
 86.7851 +		RB_RenderDrawSurfacesIntoGeometricBuffer();
 86.7852 +
 86.7853 +		// try to cull lights using hardware occlusion queries
 86.7854 +		R_BindFBO(tr.deferredRenderFBO);
 86.7855 +		RB_RenderLightOcclusionQueries();
 86.7856 +
 86.7857 +		if(!r_showDeferredRender->integer)
 86.7858 +		{
 86.7859 +			if(r_shadows->integer >= 4)
 86.7860 +			{
 86.7861 +				// render dynamic shadowing and lighting using shadow mapping
 86.7862 +				RB_RenderInteractionsDeferredShadowMapped();
 86.7863 +			}
 86.7864 +			else
 86.7865 +			{
 86.7866 +				// render dynamic lighting
 86.7867 +				RB_RenderInteractionsDeferred();
 86.7868 +			}
 86.7869 +		}
 86.7870 +
 86.7871 +		// draw everything that is translucent
 86.7872 +		R_BindFBO(tr.deferredRenderFBO);
 86.7873 +		RB_RenderDrawSurfaces(qfalse, qfalse);
 86.7874 +
 86.7875 +		// render global fog
 86.7876 +		R_BindFBO(tr.deferredRenderFBO);
 86.7877 +		RB_RenderUniformFog();
 86.7878 +
 86.7879 +		// render debug information
 86.7880 +		R_BindFBO(tr.deferredRenderFBO);
 86.7881 +		RB_RenderDebugUtils();
 86.7882 +
 86.7883 +		// scale down rendered HDR scene to 1 / 4th
 86.7884 +		if(r_hdrRendering->integer)
 86.7885 +		{
 86.7886 +			if(glConfig.framebufferBlitAvailable)
 86.7887 +			{
 86.7888 +				qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, tr.deferredRenderFBO->frameBuffer);
 86.7889 +				qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, tr.downScaleFBO_quarter->frameBuffer);
 86.7890 +				qglBlitFramebufferEXT(0, 0, glConfig.vidWidth, glConfig.vidHeight,
 86.7891 +										0, 0, glConfig.vidWidth * 0.25f, glConfig.vidHeight * 0.25f,
 86.7892 +										GL_COLOR_BUFFER_BIT,
 86.7893 +										GL_LINEAR);
 86.7894 +
 86.7895 +				qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, tr.deferredRenderFBO->frameBuffer);
 86.7896 +				qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, tr.downScaleFBO_64x64->frameBuffer);
 86.7897 +				qglBlitFramebufferEXT(0, 0, glConfig.vidWidth, glConfig.vidHeight,
 86.7898 +									   0, 0, 64, 64,
 86.7899 +									   GL_COLOR_BUFFER_BIT,
 86.7900 +									   GL_LINEAR);
 86.7901 +			}
 86.7902 +			else
 86.7903 +			{
 86.7904 +				// FIXME add non EXT_framebuffer_blit code
 86.7905 +			}
 86.7906 +
 86.7907 +			RB_CalculateAdaptation();
 86.7908 +		}
 86.7909 +		else
 86.7910 +		{
 86.7911 +			if(glConfig.framebufferBlitAvailable)
 86.7912 +			{
 86.7913 +				// copy deferredRenderFBO to downScaleFBO_quarter
 86.7914 +				qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, tr.deferredRenderFBO->frameBuffer);
 86.7915 +				qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, tr.downScaleFBO_quarter->frameBuffer);
 86.7916 +				qglBlitFramebufferEXT(0, 0, glConfig.vidWidth, glConfig.vidHeight,
 86.7917 +										0, 0, glConfig.vidWidth * 0.25f, glConfig.vidHeight * 0.25f,
 86.7918 +										GL_COLOR_BUFFER_BIT,
 86.7919 +										GL_LINEAR);
 86.7920 +			}
 86.7921 +			else
 86.7922 +			{
 86.7923 +				// FIXME add non EXT_framebuffer_blit code
 86.7924 +			}
 86.7925 +		}
 86.7926 +
 86.7927 +		GL_CheckErrors();
 86.7928 +
 86.7929 +		// render bloom post process effect
 86.7930 +		RB_RenderBloom();
 86.7931 +
 86.7932 +		// copy offscreen rendered scene to the current OpenGL context
 86.7933 +		RB_RenderDeferredShadingResultToFrameBuffer();
 86.7934 +
 86.7935 +		if(backEnd.viewParms.isPortal)
 86.7936 +		{
 86.7937 +			if(glConfig.framebufferBlitAvailable)
 86.7938 +			{
 86.7939 +				// copy deferredRenderFBO to portalRenderFBO
 86.7940 +				qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, tr.deferredRenderFBO->frameBuffer);
 86.7941 +				qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, tr.portalRenderFBO->frameBuffer);
 86.7942 +				qglBlitFramebufferEXT(0, 0, tr.deferredRenderFBO->width, tr.deferredRenderFBO->height,
 86.7943 +									   0, 0, tr.portalRenderFBO->width, tr.portalRenderFBO->height,
 86.7944 +									   GL_COLOR_BUFFER_BIT,
 86.7945 +									   GL_NEAREST);
 86.7946 +			}
 86.7947 +			else
 86.7948 +			{
 86.7949 +				// capture current color buffer
 86.7950 +				GL_SelectTexture(0);
 86.7951 +				GL_Bind(tr.portalRenderImage);
 86.7952 +				qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.portalRenderImage->uploadWidth, tr.portalRenderImage->uploadHeight);
 86.7953 +			}
 86.7954 +			backEnd.pc.c_portals++;
 86.7955 +		}
 86.7956 +	}
 86.7957 +	else
 86.7958 +	{
 86.7959 +		int             clearBits = 0;
 86.7960 +		int             startTime = 0, endTime = 0;
 86.7961 +
 86.7962 +		// sync with gl if needed
 86.7963 +		if(r_finish->integer == 1 && !glState.finishCalled)
 86.7964 +		{
 86.7965 +			qglFinish();
 86.7966 +			glState.finishCalled = qtrue;
 86.7967 +		}
 86.7968 +		if(r_finish->integer == 0)
 86.7969 +		{
 86.7970 +			glState.finishCalled = qtrue;
 86.7971 +		}
 86.7972 +
 86.7973 +		// disable offscreen rendering
 86.7974 +		if(glConfig.framebufferObjectAvailable)
 86.7975 +		{
 86.7976 +			if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
 86.7977 +				R_BindFBO(tr.deferredRenderFBO);
 86.7978 +			else
 86.7979 +				R_BindNullFBO();
 86.7980 +		}
 86.7981 +
 86.7982 +		// we will need to change the projection matrix before drawing
 86.7983 +		// 2D images again
 86.7984 +		backEnd.projection2D = qfalse;
 86.7985 +
 86.7986 +		// set the modelview matrix for the viewer
 86.7987 +		SetViewportAndScissor();
 86.7988 +
 86.7989 +		// ensures that depth writes are enabled for the depth clear
 86.7990 +		GL_State(GLS_DEFAULT);
 86.7991 +
 86.7992 +		// clear relevant buffers
 86.7993 +		clearBits = GL_DEPTH_BUFFER_BIT;
 86.7994 +
 86.7995 +		if(r_measureOverdraw->integer || r_shadows->integer == 3)
 86.7996 +		{
 86.7997 +			clearBits |= GL_STENCIL_BUFFER_BIT;
 86.7998 +		}
 86.7999 +
 86.8000 +		if(!(backEnd.refdef.rdflags & RDF_NOWORLDMODEL))
 86.8001 +		{
 86.8002 +			clearBits |= GL_COLOR_BUFFER_BIT;	// FIXME: only if sky shaders have been used
 86.8003 +			GL_ClearColor(0.0f, 0.0f, 0.0f, 1.0f);	// FIXME: get color of sky
 86.8004 +		}
 86.8005 +		else
 86.8006 +		{
 86.8007 +			if(r_hdrRendering->integer && glConfig.textureFloatAvailable && glConfig.framebufferObjectAvailable && glConfig.framebufferBlitAvailable)
 86.8008 +			{
 86.8009 +				// copy color of the main context to deferredRenderFBO
 86.8010 +				qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
 86.8011 +				qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, tr.deferredRenderFBO->frameBuffer);
 86.8012 +				qglBlitFramebufferEXT(0, 0, glConfig.vidWidth, glConfig.vidHeight,
 86.8013 +									   0, 0, glConfig.vidWidth, glConfig.vidHeight,
 86.8014 +									   GL_COLOR_BUFFER_BIT,
 86.8015 +									   GL_NEAREST);
 86.8016 +			}
 86.8017 +		}
 86.8018 +		qglClear(clearBits);
 86.8019 +
 86.8020 +		if((backEnd.refdef.rdflags & RDF_HYPERSPACE))
 86.8021 +		{
 86.8022 +			RB_Hyperspace();
 86.8023 +			return;
 86.8024 +		}
 86.8025 +		else
 86.8026 +		{
 86.8027 +			backEnd.isHyperspace = qfalse;
 86.8028 +		}
 86.8029 +
 86.8030 +		glState.faceCulling = -1;	// force face culling to set next time
 86.8031 +
 86.8032 +		// we will only draw a sun if there was sky rendered in this view
 86.8033 +		backEnd.skyRenderedThisView = qfalse;
 86.8034 +
 86.8035 +		GL_CheckErrors();
 86.8036 +
 86.8037 +		if(r_speeds->integer == 9)
 86.8038 +		{
 86.8039 +			startTime = ri.Milliseconds();
 86.8040 +		}
 86.8041 +
 86.8042 +		// draw everything that is opaque into black so we can benefit from early-z rejections later
 86.8043 +		//RB_RenderDrawSurfaces(qtrue, qtrue);
 86.8044 +
 86.8045 +		// draw everything that is opaque
 86.8046 +		RB_RenderDrawSurfaces(qtrue, qfalse);
 86.8047 +
 86.8048 +		// render ambient occlusion process effect
 86.8049 +		// Tr3B: needs way more work RB_RenderScreenSpaceAmbientOcclusion(qfalse);
 86.8050 +
 86.8051 +		if(r_speeds->integer == 9)
 86.8052 +		{
 86.8053 +			qglFinish();
 86.8054 +			endTime = ri.Milliseconds();
 86.8055 +			backEnd.pc.c_forwardAmbientTime = endTime - startTime;
 86.8056 +		}
 86.8057 +
 86.8058 +		// try to cull lights using hardware occlusion queries
 86.8059 +		RB_RenderLightOcclusionQueries();
 86.8060 +
 86.8061 +		if(r_shadows->integer >= 4)
 86.8062 +		{
 86.8063 +			// render dynamic shadowing and lighting using shadow mapping
 86.8064 +			RB_RenderInteractionsShadowMapped();
 86.8065 +
 86.8066 +			// render player shadows if any
 86.8067 +			RB_RenderInteractionsDeferredInverseShadows();
 86.8068 +		}
 86.8069 +		else if(r_shadows->integer == 3)
 86.8070 +		{
 86.8071 +			// render dynamic shadowing and lighting using stencil shadow volumes
 86.8072 +			RB_RenderInteractionsStencilShadowed();
 86.8073 +		}
 86.8074 +		else
 86.8075 +		{
 86.8076 +			// render dynamic lighting
 86.8077 +			RB_RenderInteractions();
 86.8078 +		}
 86.8079 +
 86.8080 +		if(r_hdrRendering->integer && glConfig.framebufferObjectAvailable && glConfig.textureFloatAvailable)
 86.8081 +			R_BindFBO(tr.deferredRenderFBO);
 86.8082 +
 86.8083 +		// draw everything that is translucent
 86.8084 +		RB_RenderDrawSurfaces(qfalse, qfalse);
 86.8085 +
 86.8086 +		// render global fog post process effect
 86.8087 +		RB_RenderUniformFog(qfalse);
 86.8088 +
 86.8089 +		// scale down rendered HDR scene to 1 / 4th
 86.8090 +		if(r_hdrRendering->integer && glConfig.textureFloatAvailable && glConfig.framebufferObjectAvailable)
 86.8091 +		{
 86.8092 +			if(glConfig.framebufferBlitAvailable)
 86.8093 +			{
 86.8094 +				qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, tr.deferredRenderFBO->frameBuffer);
 86.8095 +				qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, tr.downScaleFBO_quarter->frameBuffer);
 86.8096 +				qglBlitFramebufferEXT(0, 0, glConfig.vidWidth, glConfig.vidHeight,
 86.8097 +										0, 0, glConfig.vidWidth * 0.25f, glConfig.vidHeight * 0.25f,
 86.8098 +										GL_COLOR_BUFFER_BIT,
 86.8099 +										GL_LINEAR);
 86.8100 +
 86.8101 +				qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, tr.deferredRenderFBO->frameBuffer);
 86.8102 +				qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, tr.downScaleFBO_64x64->frameBuffer);
 86.8103 +				qglBlitFramebufferEXT(0, 0, glConfig.vidWidth, glConfig.vidHeight,
 86.8104 +									   0, 0, 64, 64,
 86.8105 +									   GL_COLOR_BUFFER_BIT,
 86.8106 +									   GL_LINEAR);
 86.8107 +			}
 86.8108 +			else
 86.8109 +			{
 86.8110 +				// FIXME add non EXT_framebuffer_blit code
 86.8111 +			}
 86.8112 +
 86.8113 +			RB_CalculateAdaptation();
 86.8114 +		}
 86.8115 +		else
 86.8116 +		{
 86.8117 +			/*
 86.8118 +			Tr3B: FIXME this causes: caught OpenGL error:
 86.8119 +			GL_INVALID_OPERATION in file code/renderer/tr_backend.c line 6479
 86.8120 +
 86.8121 +			if(glConfig.framebufferBlitAvailable)
 86.8122 +			{
 86.8123 +				// copy deferredRenderFBO to downScaleFBO_quarter
 86.8124 +				qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
 86.8125 +				qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, tr.downScaleFBO_quarter->frameBuffer);
 86.8126 +				qglBlitFramebufferEXT(0, 0, glConfig.vidWidth, glConfig.vidHeight,
 86.8127 +										0, 0, glConfig.vidWidth * 0.25f, glConfig.vidHeight * 0.25f,
 86.8128 +										GL_COLOR_BUFFER_BIT,
 86.8129 +										GL_NEAREST);
 86.8130 +			}
 86.8131 +			else
 86.8132 +			{
 86.8133 +				// FIXME add non EXT_framebuffer_blit code
 86.8134 +			}
 86.8135 +			*/
 86.8136 +		}
 86.8137 +
 86.8138 +		GL_CheckErrors();
 86.8139 +
 86.8140 +		// render depth of field post process effect
 86.8141 +		RB_RenderDepthOfField(qfalse);
 86.8142 +
 86.8143 +		// render bloom post process effect
 86.8144 +		RB_RenderBloom();
 86.8145 +
 86.8146 +		// copy offscreen rendered HDR scene to the current OpenGL context
 86.8147 +		RB_RenderDeferredHDRResultToFrameBuffer();
 86.8148 +
 86.8149 +		// render rotoscope post process effect
 86.8150 +		RB_RenderRotoscope();
 86.8151 +
 86.8152 +#if 0
 86.8153 +		// add the sun flare
 86.8154 +		RB_DrawSun();
 86.8155 +#endif
 86.8156 +
 86.8157 +#if 0
 86.8158 +		// add light flares on lights that aren't obscured
 86.8159 +		RB_RenderFlares();
 86.8160 +#endif
 86.8161 +
 86.8162 +		// render debug information
 86.8163 +		RB_RenderDebugUtils();
 86.8164 +
 86.8165 +		if(backEnd.viewParms.isPortal)
 86.8166 +		{
 86.8167 +			if(r_hdrRendering->integer && glConfig.textureFloatAvailable && glConfig.framebufferObjectAvailable && glConfig.framebufferBlitAvailable)
 86.8168 +			{
 86.8169 +				// copy deferredRenderFBO to portalRenderFBO
 86.8170 +				qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, tr.deferredRenderFBO->frameBuffer);
 86.8171 +				qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, tr.portalRenderFBO->frameBuffer);
 86.8172 +				qglBlitFramebufferEXT(0, 0, tr.deferredRenderFBO->width, tr.deferredRenderFBO->height,
 86.8173 +				                       0, 0, tr.portalRenderFBO->width, tr.portalRenderFBO->height,
 86.8174 +				                       GL_COLOR_BUFFER_BIT,
 86.8175 +				                       GL_NEAREST);
 86.8176 +			}
 86.8177 +#if 0
 86.8178 +			// FIXME: this trashes the OpenGL context for an unknown reason
 86.8179 +			else if(glConfig.framebufferObjectAvailable && glConfig.framebufferBlitAvailable)
 86.8180 +			{
 86.8181 +				// copy main context to portalRenderFBO
 86.8182 +				qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
 86.8183 +				qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, tr.portalRenderFBO->frameBuffer);
 86.8184 +				qglBlitFramebufferEXT(0, 0, glConfig.vidWidth, glConfig.vidHeight,
 86.8185 +									   0, 0, glConfig.vidWidth, glConfig.vidHeight,
 86.8186 +									   GL_COLOR_BUFFER_BIT,
 86.8187 +									   GL_NEAREST);
 86.8188 +			}
 86.8189 +#endif
 86.8190 +			else
 86.8191 +			{
 86.8192 +				// capture current color buffer
 86.8193 +				GL_SelectTexture(0);
 86.8194 +				GL_Bind(tr.portalRenderImage);
 86.8195 +				qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, tr.portalRenderImage->uploadWidth, tr.portalRenderImage->uploadHeight);
 86.8196 +			}
 86.8197 +			backEnd.pc.c_portals++;
 86.8198 +		}
 86.8199 +	}
 86.8200 +
 86.8201 +	// copy to given byte buffer that is NOT a FBO
 86.8202 +	if(tr.refdef.pixelTarget != NULL)
 86.8203 +	{
 86.8204 +		int             i;
 86.8205 +
 86.8206 +		// need to convert Y axis
 86.8207 +#if 0
 86.8208 +		qglReadPixels(0, 0, tr.refdef.pixelTargetWidth, tr.refdef.pixelTargetHeight, GL_RGBA, GL_UNSIGNED_BYTE, tr.refdef.pixelTarget);
 86.8209 +#else
 86.8210 +		// Bugfix: drivers absolutely hate running in high res and using qglReadPixels near the top or bottom edge.
 86.8211 +		// Soo.. lets do it in the middle.
 86.8212 +		qglReadPixels(glConfig.vidWidth / 2, glConfig.vidHeight / 2, tr.refdef.pixelTargetWidth, tr.refdef.pixelTargetHeight, GL_RGBA,
 86.8213 +					  GL_UNSIGNED_BYTE, tr.refdef.pixelTarget);
 86.8214 +#endif
 86.8215 +
 86.8216 +		for(i = 0; i < tr.refdef.pixelTargetWidth * tr.refdef.pixelTargetHeight; i++)
 86.8217 +		{
 86.8218 +			tr.refdef.pixelTarget[(i * 4) + 3] = 255;	//set the alpha pure white
 86.8219 +		}
 86.8220 +	}
 86.8221 +
 86.8222 +	GL_CheckErrors();
 86.8223 +
 86.8224 +	backEnd.pc.c_views++;
 86.8225  }
 86.8226  
 86.8227  
 86.8228 @@ -702,36 +7667,6 @@
 86.8229  ============================================================================
 86.8230  */
 86.8231  
 86.8232 -/*
 86.8233 -================
 86.8234 -RB_SetGL2D
 86.8235 -
 86.8236 -================
 86.8237 -*/
 86.8238 -void	RB_SetGL2D (void) {
 86.8239 -	backEnd.projection2D = qtrue;
 86.8240 -
 86.8241 -	// set 2D virtual screen size
 86.8242 -	qglViewport( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
 86.8243 -	qglScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
 86.8244 -	qglMatrixMode(GL_PROJECTION);
 86.8245 -    qglLoadIdentity ();
 86.8246 -	qglOrtho (0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1);
 86.8247 -	qglMatrixMode(GL_MODELVIEW);
 86.8248 -    qglLoadIdentity ();
 86.8249 -
 86.8250 -	GL_State( GLS_DEPTHTEST_DISABLE |
 86.8251 -			  GLS_SRCBLEND_SRC_ALPHA |
 86.8252 -			  GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
 86.8253 -
 86.8254 -	qglDisable( GL_CULL_FACE );
 86.8255 -	qglDisable( GL_CLIP_PLANE0 );
 86.8256 -
 86.8257 -	// set time for 2D shaders
 86.8258 -	backEnd.refdef.time = ri.Milliseconds();
 86.8259 -	backEnd.refdef.floatTime = backEnd.refdef.time * 0.001f;
 86.8260 -}
 86.8261 -
 86.8262  
 86.8263  /*
 86.8264  =============
 86.8265 @@ -742,11 +7677,13 @@
 86.8266  Used for cinematics.
 86.8267  =============
 86.8268  */
 86.8269 -void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
 86.8270 -	int			i, j;
 86.8271 -	int			start, end;
 86.8272 -
 86.8273 -	if ( !tr.registered ) {
 86.8274 +void RE_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte * data, int client, qboolean dirty)
 86.8275 +{
 86.8276 +	int             i, j;
 86.8277 +	int             start, end;
 86.8278 +
 86.8279 +	if(!tr.registered)
 86.8280 +	{
 86.8281  		return;
 86.8282  	}
 86.8283  	R_SyncRenderThread();
 86.8284 @@ -755,97 +7692,201 @@
 86.8285  	qglFinish();
 86.8286  
 86.8287  	start = end = 0;
 86.8288 -	if ( r_speeds->integer ) {
 86.8289 +	if(r_speeds->integer)
 86.8290 +	{
 86.8291  		start = ri.Milliseconds();
 86.8292  	}
 86.8293  
 86.8294  	// make sure rows and cols are powers of 2
 86.8295 -	for ( i = 0 ; ( 1 << i ) < cols ; i++ ) {
 86.8296 -	}
 86.8297 -	for ( j = 0 ; ( 1 << j ) < rows ; j++ ) {
 86.8298 -	}
 86.8299 -	if ( ( 1 << i ) != cols || ( 1 << j ) != rows) {
 86.8300 -		ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
 86.8301 -	}
 86.8302 -
 86.8303 -	GL_Bind( tr.scratchImage[client] );
 86.8304 +	for(i = 0; (1 << i) < cols; i++)
 86.8305 +	{
 86.8306 +	}
 86.8307 +	for(j = 0; (1 << j) < rows; j++)
 86.8308 +	{
 86.8309 +	}
 86.8310 +	if((1 << i) != cols || (1 << j) != rows)
 86.8311 +	{
 86.8312 +		ri.Error(ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
 86.8313 +	}
 86.8314 +
 86.8315 +
 86.8316 +	RB_SetGL2D();
 86.8317 +
 86.8318 +	qglVertexAttrib4fARB(ATTR_INDEX_NORMAL, 0, 0, 1, 1);
 86.8319 +	qglVertexAttrib4fARB(ATTR_INDEX_COLOR, tr.identityLight, tr.identityLight, tr.identityLight, 1);
 86.8320 +
 86.8321 +	GL_BindProgram(&tr.genericSingleShader);
 86.8322 +
 86.8323 +	// set uniforms
 86.8324 +	GLSL_SetUniform_TCGen_Environment(&tr.genericSingleShader,  qfalse);
 86.8325 +	GLSL_SetUniform_ColorGen(&tr.genericSingleShader, CGEN_VERTEX);
 86.8326 +	GLSL_SetUniform_AlphaGen(&tr.genericSingleShader, AGEN_VERTEX);
 86.8327 +	//GLSL_SetUniform_Color(&tr.genericSingleShader, colorWhite);
 86.8328 +	if(glConfig.vboVertexSkinningAvailable)
 86.8329 +	{
 86.8330 +		GLSL_SetUniform_VertexSkinning(&tr.genericSingleShader, qfalse);
 86.8331 +	}
 86.8332 +	GLSL_SetUniform_AlphaTest(&tr.genericSingleShader, 0);
 86.8333 +	GLSL_SetUniform_ModelViewProjectionMatrix(&tr.genericSingleShader, glState.modelViewProjectionMatrix[glState.stackIndex]);
 86.8334 +
 86.8335 +	// bind u_ColorMap
 86.8336 +	GL_SelectTexture(0);
 86.8337 +	GL_Bind(tr.scratchImage[client]);
 86.8338 +	GLSL_SetUniform_ColorTextureMatrix(&tr.genericSingleShader, matrixIdentity);
 86.8339  
 86.8340  	// if the scratchImage isn't in the format we want, specify it as a new texture
 86.8341 -	if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
 86.8342 +	if(cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height)
 86.8343 +	{
 86.8344  		tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
 86.8345  		tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
 86.8346 -		qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
 86.8347 -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
 86.8348 -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
 86.8349 -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
 86.8350 -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );	
 86.8351 -	} else {
 86.8352 -		if (dirty) {
 86.8353 +
 86.8354 +		qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
 86.8355 +
 86.8356 +		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 86.8357 +		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 86.8358 +
 86.8359 +		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
 86.8360 +		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 86.8361 +	}
 86.8362 +	else
 86.8363 +	{
 86.8364 +		if(dirty)
 86.8365 +		{
 86.8366  			// otherwise, just subimage upload it so that drivers can tell we are going to be changing
 86.8367  			// it and don't try and do a texture compression
 86.8368 -			qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
 86.8369 -		}
 86.8370 -	}
 86.8371 -
 86.8372 -	if ( r_speeds->integer ) {
 86.8373 +			qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data);
 86.8374 +		}
 86.8375 +	}
 86.8376 +
 86.8377 +	if(r_speeds->integer)
 86.8378 +	{
 86.8379  		end = ri.Milliseconds();
 86.8380 -		ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start );
 86.8381 -	}
 86.8382 -
 86.8383 -	RB_SetGL2D();
 86.8384 -
 86.8385 -	qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );
 86.8386 -
 86.8387 -	qglBegin (GL_QUADS);
 86.8388 -	qglTexCoord2f ( 0.5f / cols,  0.5f / rows );
 86.8389 -	qglVertex2f (x, y);
 86.8390 -	qglTexCoord2f ( ( cols - 0.5f ) / cols ,  0.5f / rows );
 86.8391 -	qglVertex2f (x+w, y);
 86.8392 -	qglTexCoord2f ( ( cols - 0.5f ) / cols, ( rows - 0.5f ) / rows );
 86.8393 -	qglVertex2f (x+w, y+h);
 86.8394 -	qglTexCoord2f ( 0.5f / cols, ( rows - 0.5f ) / rows );
 86.8395 -	qglVertex2f (x, y+h);
 86.8396 -	qglEnd ();
 86.8397 +		ri.Printf(PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start);
 86.8398 +	}
 86.8399 +
 86.8400 +	/*
 86.8401 +	   qglBegin(GL_QUADS);
 86.8402 +	   qglVertexAttrib4fARB(ATTR_INDEX_TEXCOORD0, 0.5f / cols, 0.5f / rows, 0, 1);
 86.8403 +	   qglVertexAttrib4fARB(ATTR_INDEX_POSITION, x, y, 0, 1);
 86.8404 +	   qglVertexAttrib4fARB(ATTR_INDEX_TEXCOORD0, (cols - 0.5f) / cols, 0.5f / rows, 0, 1);
 86.8405 +	   qglVertexAttrib4fARB(ATTR_INDEX_POSITION, x + w, y, 0, 1);
 86.8406 +	   qglVertexAttrib4fARB(ATTR_INDEX_TEXCOORD0, (cols - 0.5f) / cols, (rows - 0.5f) / rows, 0, 1);
 86.8407 +	   qglVertexAttrib4fARB(ATTR_INDEX_POSITION, x + w, y + h, 0, 1);
 86.8408 +	   qglVertexAttrib4fARB(ATTR_INDEX_TEXCOORD0, 0.5f / cols, (rows - 0.5f) / rows, 0, 1);
 86.8409 +	   qglVertexAttrib4fARB(ATTR_INDEX_POSITION, x, y + h, 0, 1);
 86.8410 +	   qglEnd();
 86.8411 +	 */
 86.8412 +
 86.8413 +	tess.numVertexes = 0;
 86.8414 +	tess.numIndexes = 0;
 86.8415 +
 86.8416 +	tess.xyz[tess.numVertexes][0] = x;
 86.8417 +	tess.xyz[tess.numVertexes][1] = y;
 86.8418 +	tess.xyz[tess.numVertexes][2] = 0;
 86.8419 +	tess.xyz[tess.numVertexes][3] = 1;
 86.8420 +	tess.texCoords[tess.numVertexes][0] = 0.5f / cols;
 86.8421 +	tess.texCoords[tess.numVertexes][1] = 0.5f / rows;
 86.8422 +	tess.texCoords[tess.numVertexes][2] = 0;
 86.8423 +	tess.texCoords[tess.numVertexes][3] = 1;
 86.8424 +	tess.numVertexes++;
 86.8425 +
 86.8426 +	tess.xyz[tess.numVertexes][0] = x + w;
 86.8427 +	tess.xyz[tess.numVertexes][1] = y;
 86.8428 +	tess.xyz[tess.numVertexes][2] = 0;
 86.8429 +	tess.xyz[tess.numVertexes][3] = 1;
 86.8430 +	tess.texCoords[tess.numVertexes][0] = (cols - 0.5f) / cols;
 86.8431 +	tess.texCoords[tess.numVertexes][1] = 0.5f / rows;
 86.8432 +	tess.texCoords[tess.numVertexes][2] = 0;
 86.8433 +	tess.texCoords[tess.numVertexes][3] = 1;
 86.8434 +	tess.numVertexes++;
 86.8435 +
 86.8436 +	tess.xyz[tess.numVertexes][0] = x + w;
 86.8437 +	tess.xyz[tess.numVertexes][1] = y + h;
 86.8438 +	tess.xyz[tess.numVertexes][2] = 0;
 86.8439 +	tess.xyz[tess.numVertexes][3] = 1;
 86.8440 +	tess.texCoords[tess.numVertexes][0] = (cols - 0.5f) / cols;
 86.8441 +	tess.texCoords[tess.numVertexes][1] = (rows - 0.5f) / rows;
 86.8442 +	tess.texCoords[tess.numVertexes][2] = 0;
 86.8443 +	tess.texCoords[tess.numVertexes][3] = 1;
 86.8444 +	tess.numVertexes++;
 86.8445 +
 86.8446 +	tess.xyz[tess.numVertexes][0] = x;
 86.8447 +	tess.xyz[tess.numVertexes][1] = y + h;
 86.8448 +	tess.xyz[tess.numVertexes][2] = 0;
 86.8449 +	tess.xyz[tess.numVertexes][3] = 1;
 86.8450 +	tess.texCoords[tess.numVertexes][0] = 0.5f / cols;
 86.8451 +	tess.texCoords[tess.numVertexes][1] = (rows - 0.5f) / rows;
 86.8452 +	tess.texCoords[tess.numVertexes][2] = 0;
 86.8453 +	tess.texCoords[tess.numVertexes][3] = 1;
 86.8454 +	tess.numVertexes++;
 86.8455 +
 86.8456 +	tess.indexes[tess.numIndexes++] = 0;
 86.8457 +	tess.indexes[tess.numIndexes++] = 1;
 86.8458 +	tess.indexes[tess.numIndexes++] = 2;
 86.8459 +	tess.indexes[tess.numIndexes++] = 0;
 86.8460 +	tess.indexes[tess.numIndexes++] = 2;
 86.8461 +	tess.indexes[tess.numIndexes++] = 3;
 86.8462 +
 86.8463 +	Tess_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD);
 86.8464 +
 86.8465 +	Tess_DrawElements();
 86.8466 +
 86.8467 +	tess.numVertexes = 0;
 86.8468 +	tess.numIndexes = 0;
 86.8469 +
 86.8470 +	GL_CheckErrors();
 86.8471  }
 86.8472  
 86.8473 -void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
 86.8474 -
 86.8475 -	GL_Bind( tr.scratchImage[client] );
 86.8476 +void RE_UploadCinematic(int w, int h, int cols, int rows, const byte * data, int client, qboolean dirty)
 86.8477 +{
 86.8478 +	GL_Bind(tr.scratchImage[client]);
 86.8479  
 86.8480  	// if the scratchImage isn't in the format we want, specify it as a new texture
 86.8481 -	if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
 86.8482 +	if(cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height)
 86.8483 +	{
 86.8484  		tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
 86.8485  		tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
 86.8486 -		qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
 86.8487 -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
 86.8488 -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
 86.8489 -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
 86.8490 -		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );	
 86.8491 -	} else {
 86.8492 -		if (dirty) {
 86.8493 +
 86.8494 +		qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
 86.8495 +
 86.8496 +		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 86.8497 +		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 86.8498 +
 86.8499 +		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
 86.8500 +		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
 86.8501 +		qglTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, colorBlack);
 86.8502 +	}
 86.8503 +	else
 86.8504 +	{
 86.8505 +		if(dirty)
 86.8506 +		{
 86.8507  			// otherwise, just subimage upload it so that drivers can tell we are going to be changing
 86.8508  			// it and don't try and do a texture compression
 86.8509 -			qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
 86.8510 -		}
 86.8511 -	}
 86.8512 +			qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data);
 86.8513 +		}
 86.8514 +	}
 86.8515 +
 86.8516 +	GL_CheckErrors();
 86.8517  }
 86.8518  
 86.8519  
 86.8520  /*
 86.8521  =============
 86.8522  RB_SetColor
 86.8523 -
 86.8524  =============
 86.8525  */
 86.8526 -const void	*RB_SetColor( const void *data ) {
 86.8527 -	const setColorCommand_t	*cmd;
 86.8528 +const void     *RB_SetColor(const void *data)
 86.8529 +{
 86.8530 +	const setColorCommand_t *cmd;
 86.8531 +
 86.8532 +	GLimp_LogComment("--- RB_SetColor ---\n");
 86.8533  
 86.8534  	cmd = (const setColorCommand_t *)data;
 86.8535  
 86.8536 -	backEnd.color2D[0] = cmd->color[0] * 255;
 86.8537 -	backEnd.color2D[1] = cmd->color[1] * 255;
 86.8538 -	backEnd.color2D[2] = cmd->color[2] * 255;
 86.8539 -	backEnd.color2D[3] = cmd->color[3] * 255;
 86.8540 +	backEnd.color2D[0] = cmd->color[0];
 86.8541 +	backEnd.color2D[1] = cmd->color[1];
 86.8542 +	backEnd.color2D[2] = cmd->color[2];
 86.8543 +	backEnd.color2D[3] = cmd->color[3];
 86.8544  
 86.8545  	return (const void *)(cmd + 1);
 86.8546  }
 86.8547 @@ -855,72 +7896,95 @@
 86.8548  RB_StretchPic
 86.8549  =============
 86.8550  */
 86.8551 -const void *RB_StretchPic ( const void *data ) {
 86.8552 -	const stretchPicCommand_t	*cmd;
 86.8553 -	shader_t *shader;
 86.8554 -	int		numVerts, numIndexes;
 86.8555 +const void     *RB_StretchPic(const void *data)
 86.8556 +{
 86.8557 +	int             i;
 86.8558 +	const stretchPicCommand_t *cmd;
 86.8559 +	shader_t       *shader;
 86.8560 +	int             numVerts, numIndexes;
 86.8561 +
 86.8562 +	GLimp_LogComment("--- RB_StretchPic ---\n");
 86.8563  
 86.8564  	cmd = (const stretchPicCommand_t *)data;
 86.8565  
 86.8566 -	if ( !backEnd.projection2D ) {
 86.8567 +	if(!backEnd.projection2D)
 86.8568 +	{
 86.8569  		RB_SetGL2D();
 86.8570  	}
 86.8571  
 86.8572  	shader = cmd->shader;
 86.8573 -	if ( shader != tess.shader ) {
 86.8574 -		if ( tess.numIndexes ) {
 86.8575 -			RB_EndSurface();
 86.8576 +	if(shader != tess.surfaceShader)
 86.8577 +	{
 86.8578 +		if(tess.numIndexes)
 86.8579 +		{
 86.8580 +			Tess_End();
 86.8581  		}
 86.8582  		backEnd.currentEntity = &backEnd.entity2D;
 86.8583 -		RB_BeginSurface( shader, 0 );
 86.8584 -	}
 86.8585 -
 86.8586 -	RB_CHECKOVERFLOW( 4, 6 );
 86.8587 +		Tess_Begin(Tess_StageIteratorGeneric, shader, NULL, qfalse, qfalse, -1);
 86.8588 +	}
 86.8589 +
 86.8590 +	Tess_CheckOverflow(4, 6);
 86.8591  	numVerts = tess.numVertexes;
 86.8592  	numIndexes = tess.numIndexes;
 86.8593  
 86.8594  	tess.numVertexes += 4;
 86.8595  	tess.numIndexes += 6;
 86.8596  
 86.8597 -	tess.indexes[ numIndexes ] = numVerts + 3;
 86.8598 -	tess.indexes[ numIndexes + 1 ] = numVerts + 0;
 86.8599 -	tess.indexes[ numIndexes + 2 ] = numVerts + 2;
 86.8600 -	tess.indexes[ numIndexes + 3 ] = numVerts + 2;
 86.8601 -	tess.indexes[ numIndexes + 4 ] = numVerts + 0;
 86.8602 -	tess.indexes[ numIndexes + 5 ] = numVerts + 1;
 86.8603 -
 86.8604 -	*(int *)tess.vertexColors[ numVerts ] =
 86.8605 -		*(int *)tess.vertexColors[ numVerts + 1 ] =
 86.8606 -		*(int *)tess.vertexColors[ numVerts + 2 ] =
 86.8607 -		*(int *)tess.vertexColors[ numVerts + 3 ] = *(int *)backEnd.color2D;
 86.8608 -
 86.8609 -	tess.xyz[ numVerts ][0] = cmd->x;
 86.8610 -	tess.xyz[ numVerts ][1] = cmd->y;
 86.8611 -	tess.xyz[ numVerts ][2] = 0;
 86.8612 -
 86.8613 -	tess.texCoords[ numVerts ][0][0] = cmd->s1;
 86.8614 -	tess.texCoords[ numVerts ][0][1] = cmd->t1;
 86.8615 -
 86.8616 -	tess.xyz[ numVerts + 1 ][0] = cmd->x + cmd->w;
 86.8617 -	tess.xyz[ numVerts + 1 ][1] = cmd->y;
 86.8618 -	tess.xyz[ numVerts + 1 ][2] = 0;
 86.8619 -
 86.8620 -	tess.texCoords[ numVerts + 1 ][0][0] = cmd->s2;
 86.8621 -	tess.texCoords[ numVerts + 1 ][0][1] = cmd->t1;
 86.8622 -
 86.8623 -	tess.xyz[ numVerts + 2 ][0] = cmd->x + cmd->w;
 86.8624 -	tess.xyz[ numVerts + 2 ][1] = cmd->y + cmd->h;
 86.8625 -	tess.xyz[ numVerts + 2 ][2] = 0;
 86.8626 -
 86.8627 -	tess.texCoords[ numVerts + 2 ][0][0] = cmd->s2;
 86.8628 -	tess.texCoords[ numVerts + 2 ][0][1] = cmd->t2;
 86.8629 -
 86.8630 -	tess.xyz[ numVerts + 3 ][0] = cmd->x;
 86.8631 -	tess.xyz[ numVerts + 3 ][1] = cmd->y + cmd->h;
 86.8632 -	tess.xyz[ numVerts + 3 ][2] = 0;
 86.8633 -
 86.8634 -	tess.texCoords[ numVerts + 3 ][0][0] = cmd->s1;
 86.8635 -	tess.texCoords[ numVerts + 3 ][0][1] = cmd->t2;
 86.8636 +	tess.indexes[numIndexes] = numVerts + 3;
 86.8637 +	tess.indexes[numIndexes + 1] = numVerts + 0;
 86.8638 +	tess.indexes[numIndexes + 2] = numVerts + 2;
 86.8639 +	tess.indexes[numIndexes + 3] = numVerts + 2;
 86.8640 +	tess.indexes[numIndexes + 4] = numVerts + 0;
 86.8641 +	tess.indexes[numIndexes + 5] = numVerts + 1;
 86.8642 +
 86.8643 +
 86.8644 +	for(i = 0; i < 4; i++)
 86.8645 +	{
 86.8646 +		tess.colors[numVerts + i][0] = backEnd.color2D[0];
 86.8647 +		tess.colors[numVerts + i][1] = backEnd.color2D[1];
 86.8648 +		tess.colors[numVerts + i][2] = backEnd.color2D[2];
 86.8649 +		tess.colors[numVerts + i][3] = backEnd.color2D[3];
 86.8650 +	}
 86.8651 +
 86.8652 +	tess.xyz[numVerts][0] = cmd->x;
 86.8653 +	tess.xyz[numVerts][1] = cmd->y;
 86.8654 +	tess.xyz[numVerts][2] = 0;
 86.8655 +	tess.xyz[numVerts][3] = 1;
 86.8656 +
 86.8657 +	tess.texCoords[numVerts][0] = cmd->s1;
 86.8658 +	tess.texCoords[numVerts][1] = cmd->t1;
 86.8659 +	tess.texCoords[numVerts][2] = 0;
 86.8660 +	tess.texCoords[numVerts][3] = 1;
 86.8661 +
 86.8662 +	tess.xyz[numVerts + 1][0] = cmd->x + cmd->w;
 86.8663 +	tess.xyz[numVerts + 1][1] = cmd->y;
 86.8664 +	tess.xyz[numVerts + 1][2] = 0;
 86.8665 +	tess.xyz[numVerts + 1][3] = 1;
 86.8666 +
 86.8667 +	tess.texCoords[numVerts + 1][0] = cmd->s2;
 86.8668 +	tess.texCoords[numVerts + 1][1] = cmd->t1;
 86.8669 +	tess.texCoords[numVerts + 1][2] = 0;
 86.8670 +	tess.texCoords[numVerts + 1][3] = 1;
 86.8671 +
 86.8672 +	tess.xyz[numVerts + 2][0] = cmd->x + cmd->w;
 86.8673 +	tess.xyz[numVerts + 2][1] = cmd->y + cmd->h;
 86.8674 +	tess.xyz[numVerts + 2][2] = 0;
 86.8675 +	tess.xyz[numVerts + 2][3] = 1;
 86.8676 +
 86.8677 +	tess.texCoords[numVerts + 2][0] = cmd->s2;
 86.8678 +	tess.texCoords[numVerts + 2][1] = cmd->t2;
 86.8679 +	tess.texCoords[numVerts + 2][2] = 0;
 86.8680 +	tess.texCoords[numVerts + 2][3] = 1;
 86.8681 +
 86.8682 +	tess.xyz[numVerts + 3][0] = cmd->x;
 86.8683 +	tess.xyz[numVerts + 3][1] = cmd->y + cmd->h;
 86.8684 +	tess.xyz[numVerts + 3][2] = 0;
 86.8685 +	tess.xyz[numVerts + 3][3] = 1;
 86.8686 +
 86.8687 +	tess.texCoords[numVerts + 3][0] = cmd->s1;
 86.8688 +	tess.texCoords[numVerts + 3][1] = cmd->t2;
 86.8689 +	tess.texCoords[numVerts + 3][2] = 0;
 86.8690 +	tess.texCoords[numVerts + 3][3] = 1;
 86.8691  
 86.8692  	return (const void *)(cmd + 1);
 86.8693  }
 86.8694 @@ -928,26 +7992,27 @@
 86.8695  
 86.8696  /*
 86.8697  =============
 86.8698 -RB_DrawSurfs
 86.8699 -
 86.8700 +RB_DrawView
 86.8701  =============
 86.8702  */
 86.8703 -const void	*RB_DrawSurfs( const void *data ) {
 86.8704 -	const drawSurfsCommand_t	*cmd;
 86.8705 +const void     *RB_DrawView(const void *data)
 86.8706 +{
 86.8707 +	const drawViewCommand_t *cmd;
 86.8708 +
 86.8709 +	GLimp_LogComment("--- RB_DrawView ---\n");
 86.8710  
 86.8711  	// finish any 2D drawing if needed
 86.8712 -	if ( tess.numIndexes ) {
 86.8713 -		RB_EndSurface();
 86.8714 -	}
 86.8715 -
 86.8716 -	cmd = (const drawSurfsCommand_t *)data;
 86.8717 +	if(tess.numIndexes)
 86.8718 +	{
 86.8719 +		Tess_End();
 86.8720 +	}
 86.8721 +
 86.8722 +	cmd = (const drawViewCommand_t *)data;
 86.8723  
 86.8724  	backEnd.refdef = cmd->refdef;
 86.8725  	backEnd.viewParms = cmd->viewParms;
 86.8726 -	
 86.8727 -	//TODO Maybe check for rdf_noworld stuff but q3mme has full 3d ui
 86.8728 -	backEnd.doneSurfaces = qtrue;
 86.8729 -	RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs );
 86.8730 +
 86.8731 +	RB_RenderView();
 86.8732  
 86.8733  	return (const void *)(cmd + 1);
 86.8734  }
 86.8735 @@ -956,20 +8021,24 @@
 86.8736  /*
 86.8737  =============
 86.8738  RB_DrawBuffer
 86.8739 -
 86.8740  =============
 86.8741  */
 86.8742 -const void	*RB_DrawBuffer( const void *data ) {
 86.8743 -	const drawBufferCommand_t	*cmd;
 86.8744 +const void     *RB_DrawBuffer(const void *data)
 86.8745 +{
 86.8746 +	const drawBufferCommand_t *cmd;
 86.8747 +
 86.8748 +	GLimp_LogComment("--- RB_DrawBuffer ---\n");
 86.8749  
 86.8750  	cmd = (const drawBufferCommand_t *)data;
 86.8751  
 86.8752 -	qglDrawBuffer( cmd->buffer );
 86.8753 +	GL_DrawBuffer(cmd->buffer);
 86.8754  
 86.8755  	// clear screen for debugging
 86.8756 -	if ( r_clear->integer ) {
 86.8757 -		qglClearColor( 1, 0, 0.5, 1 );
 86.8758 -		qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 86.8759 +	if(r_clear->integer)
 86.8760 +	{
 86.8761 +//      GL_ClearColor(1, 0, 0.5, 1);
 86.8762 +		GL_ClearColor(0, 0, 0, 1);
 86.8763 +		qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 86.8764  	}
 86.8765  
 86.8766  	return (const void *)(cmd + 1);
 86.8767 @@ -985,24 +8054,54 @@
 86.8768  Also called by RE_EndRegistration
 86.8769  ===============
 86.8770  */
 86.8771 -void RB_ShowImages( void ) {
 86.8772 -	int		i;
 86.8773 -	image_t	*image;
 86.8774 -	float	x, y, w, h;
 86.8775 -	int		start, end;
 86.8776 -
 86.8777 -	if ( !backEnd.projection2D ) {
 86.8778 +void RB_ShowImages(void)
 86.8779 +{
 86.8780 +	int             i;
 86.8781 +	image_t        *image;
 86.8782 +	float           x, y, w, h;
 86.8783 +	vec4_t          quadVerts[4];
 86.8784 +	int             start, end;
 86.8785 +
 86.8786 +	GLimp_LogComment("--- RB_ShowImages ---\n");
 86.8787 +
 86.8788 +	if(!backEnd.projection2D)
 86.8789 +	{
 86.8790  		RB_SetGL2D();
 86.8791  	}
 86.8792  
 86.8793 -	qglClear( GL_COLOR_BUFFER_BIT );
 86.8794 +	qglClear(GL_COLOR_BUFFER_BIT);
 86.8795  
 86.8796  	qglFinish();
 86.8797  
 86.8798 +	GL_BindProgram(&tr.genericSingleShader);
 86.8799 +	GL_Cull(CT_TWO_SIDED);
 86.8800 +
 86.8801 +	// set uniforms
 86.8802 +	GLSL_SetUniform_TCGen_Environment(&tr.genericSingleShader,  qfalse);
 86.8803 +	GLSL_SetUniform_ColorGen(&tr.genericSingleShader, CGEN_VERTEX);
 86.8804 +	GLSL_SetUniform_AlphaGen(&tr.genericSingleShader, AGEN_VERTEX);
 86.8805 +	if(glConfig.vboVertexSkinningAvailable)
 86.8806 +	{
 86.8807 +		GLSL_SetUniform_VertexSkinning(&tr.genericSingleShader, qfalse);
 86.8808 +	}
 86.8809 +	GLSL_SetUniform_AlphaTest(&tr.genericSingleShader, 0);
 86.8810 +	GLSL_SetUniform_ColorTextureMatrix(&tr.genericSingleShader, matrixIdentity);
 86.8811 +
 86.8812 +	GL_SelectTexture(0);
 86.8813 +
 86.8814  	start = ri.Milliseconds();
 86.8815  
 86.8816 -	for ( i=0 ; i<tr.numImages ; i++ ) {
 86.8817 -		image = tr.images[i];
 86.8818 +	for(i = 0; i < tr.images.currentElements; i++)
 86.8819 +	{
 86.8820 +		image = Com_GrowListElement(&tr.images, i);
 86.8821 +
 86.8822 +		/*
 86.8823 +		   if(image->bits & (IF_RGBA16F | IF_RGBA32F | IF_LA16F | IF_LA32F))
 86.8824 +		   {
 86.8825 +		   // don't render float textures using FFP
 86.8826 +		   continue;
 86.8827 +		   }
 86.8828 +		 */
 86.8829  
 86.8830  		w = glConfig.vidWidth / 20;
 86.8831  		h = glConfig.vidHeight / 15;
 86.8832 @@ -1010,84 +8109,62 @@
 86.8833  		y = i / 20 * h;
 86.8834  
 86.8835  		// show in proportional size in mode 2
 86.8836 -		if ( r_showImages->integer == 2 ) {
 86.8837 +		if(r_showImages->integer == 2)
 86.8838 +		{
 86.8839  			w *= image->uploadWidth / 512.0f;
 86.8840  			h *= image->uploadHeight / 512.0f;
 86.8841  		}
 86.8842  
 86.8843 -		GL_Bind( image );
 86.8844 -		qglBegin (GL_QUADS);
 86.8845 -		qglTexCoord2f( 0, 0 );
 86.8846 -		qglVertex2f( x, y );
 86.8847 -		qglTexCoord2f( 1, 0 );
 86.8848 -		qglVertex2f( x + w, y );
 86.8849 -		qglTexCoord2f( 1, 1 );
 86.8850 -		qglVertex2f( x + w, y + h );
 86.8851 -		qglTexCoord2f( 0, 1 );
 86.8852 -		qglVertex2f( x, y + h );
 86.8853 -		qglEnd();
 86.8854 +		// bind u_ColorMap
 86.8855 +		GL_Bind(image);
 86.8856 +
 86.8857 +		VectorSet4(quadVerts[0], x, y, 0, 1);
 86.8858 +		VectorSet4(quadVerts[1], x + w, y, 0, 1);
 86.8859 +		VectorSet4(quadVerts[2], x + w, y + h, 0, 1);
 86.8860 +		VectorSet4(quadVerts[3], x, y + h, 0, 1);
 86.8861 +
 86.8862 +		Tess_InstantQuad(quadVerts);
 86.8863 +
 86.8864 +		/*
 86.8865 +		   qglBegin(GL_QUADS);
 86.8866 +		   qglVertexAttrib4fARB(ATTR_INDEX_TEXCOORD0, 0, 0, 0, 1);
 86.8867 +		   qglVertexAttrib4fARB(ATTR_INDEX_POSITION, x, y, 0, 1);
 86.8868 +		   qglVertexAttrib4fARB(ATTR_INDEX_TEXCOORD0, 1, 0, 0, 1);
 86.8869 +		   qglVertexAttrib4fARB(ATTR_INDEX_POSITION, x + w, y, 0, 1);
 86.8870 +		   qglVertexAttrib4fARB(ATTR_INDEX_TEXCOORD0, 1, 1, 0, 1);
 86.8871 +		   qglVertexAttrib4fARB(ATTR_INDEX_POSITION, x + w, y + h, 0, 1);
 86.8872 +		   qglVertexAttrib4fARB(ATTR_INDEX_TEXCOORD0, 0, 1, 0, 1);
 86.8873 +		   qglVertexAttrib4fARB(ATTR_INDEX_POSITION, x, y + h, 0, 1);
 86.8874 +		   qglEnd();
 86.8875 +		 */
 86.8876  	}
 86.8877  
 86.8878  	qglFinish();
 86.8879  
 86.8880  	end = ri.Milliseconds();
 86.8881 -	ri.Printf( PRINT_DEVELOPER, "%i msec to draw all images\n", end - start );
 86.8882 -
 86.8883 -}
 86.8884 -
 86.8885 -/*
 86.8886 -=============
 86.8887 -RB_ColorMask
 86.8888 -
 86.8889 -=============
 86.8890 -*/
 86.8891 -const void *RB_ColorMask(const void *data)
 86.8892 -{
 86.8893 -	const colorMaskCommand_t *cmd = data;
 86.8894 -	
 86.8895 -	qglColorMask(cmd->rgba[0], cmd->rgba[1], cmd->rgba[2], cmd->rgba[3]);
 86.8896 -	
 86.8897 -	return (const void *)(cmd + 1);
 86.8898 -}
 86.8899 -
 86.8900 -/*
 86.8901 -=============
 86.8902 -RB_ClearDepth
 86.8903 -
 86.8904 -=============
 86.8905 -*/
 86.8906 -const void *RB_ClearDepth(const void *data)
 86.8907 -{
 86.8908 -	const clearDepthCommand_t *cmd = data;
 86.8909 -	
 86.8910 -	if(tess.numIndexes)
 86.8911 -		RB_EndSurface();
 86.8912 -
 86.8913 -	// texture swapping test
 86.8914 -	if (r_showImages->integer)
 86.8915 -		RB_ShowImages();
 86.8916 -
 86.8917 -	qglClear(GL_DEPTH_BUFFER_BIT);
 86.8918 -	
 86.8919 -	return (const void *)(cmd + 1);
 86.8920 +	ri.Printf(PRINT_ALL, "%i msec to draw all images\n", end - start);
 86.8921 +
 86.8922 +	GL_CheckErrors();
 86.8923  }
 86.8924  
 86.8925  /*
 86.8926  =============
 86.8927  RB_SwapBuffers
 86.8928 -
 86.8929  =============
 86.8930  */
 86.8931 -const void	*RB_SwapBuffers( const void *data ) {
 86.8932 -	const swapBuffersCommand_t	*cmd;
 86.8933 +const void     *RB_SwapBuffers(const void *data)
 86.8934 +{
 86.8935 +	const swapBuffersCommand_t *cmd;
 86.8936  
 86.8937  	// finish any 2D drawing if needed
 86.8938 -	if ( tess.numIndexes ) {
 86.8939 -		RB_EndSurface();
 86.8940 +	if(tess.numIndexes)
 86.8941 +	{
 86.8942 +		Tess_End();
 86.8943  	}
 86.8944  
 86.8945  	// texture swapping test
 86.8946 -	if ( r_showImages->integer ) {
 86.8947 +	if(r_showImages->integer)
 86.8948 +	{
 86.8949  		RB_ShowImages();
 86.8950  	}
 86.8951  
 86.8952 @@ -1095,36 +8172,36 @@
 86.8953  
 86.8954  	// we measure overdraw by reading back the stencil buffer and
 86.8955  	// counting up the number of increments that have happened
 86.8956 -	if ( r_measureOverdraw->integer ) {
 86.8957 -		int i;
 86.8958 -		long sum = 0;
 86.8959 -		unsigned char *stencilReadback;
 86.8960 -
 86.8961 -		stencilReadback = ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight );
 86.8962 -		qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback );
 86.8963 -
 86.8964 -		for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ ) {
 86.8965 +	if(r_measureOverdraw->integer)
 86.8966 +	{
 86.8967 +		int             i;
 86.8968 +		long            sum = 0;
 86.8969 +		unsigned char  *stencilReadback;
 86.8970 +
 86.8971 +		stencilReadback = ri.Hunk_AllocateTempMemory(glConfig.vidWidth * glConfig.vidHeight);
 86.8972 +		qglReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback);
 86.8973 +
 86.8974 +		for(i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++)
 86.8975 +		{
 86.8976  			sum += stencilReadback[i];
 86.8977  		}
 86.8978  
 86.8979  		backEnd.pc.c_overDraw += sum;
 86.8980 -		ri.Hunk_FreeTempMemory( stencilReadback );
 86.8981 -	}
 86.8982 -
 86.8983 -
 86.8984 -	if ( !glState.finishCalled ) {
 86.8985 +		ri.Hunk_FreeTempMemory(stencilReadback);
 86.8986 +	}
 86.8987 +
 86.8988 +
 86.8989 +	if(!glState.finishCalled)
 86.8990 +	{
 86.8991  		qglFinish();
 86.8992  	}
 86.8993  
 86.8994 -	GLimp_LogComment( "***************** RB_SwapBuffers *****************\n\n\n" );
 86.8995 +	GLimp_LogComment("***************** RB_SwapBuffers *****************\n\n\n");
 86.8996  
 86.8997  	GLimp_EndFrame();
 86.8998  
 86.8999  	backEnd.projection2D = qfalse;
 86.9000 -	
 86.9001 -	backEnd.doneBloom = qfalse;
 86.9002 -	backEnd.doneSurfaces = qfalse;
 86.9003 -	
 86.9004 +
 86.9005  	return (const void *)(cmd + 1);
 86.9006  }
 86.9007  
 86.9008 @@ -1136,59 +8213,57 @@
 86.9009  smp extensions, or asynchronously by another thread.
 86.9010  ====================
 86.9011  */
 86.9012 -void RB_ExecuteRenderCommands( const void *data ) {
 86.9013 -	int		t1, t2;
 86.9014 -
 86.9015 -	t1 = ri.Milliseconds ();
 86.9016 -
 86.9017 -	if ( !r_smp->integer || data == backEndData[0]->commands.cmds ) {
 86.9018 +void RB_ExecuteRenderCommands(const void *data)
 86.9019 +{
 86.9020 +	int             t1, t2;
 86.9021 +
 86.9022 +	GLimp_LogComment("--- RB_ExecuteRenderCommands ---\n");
 86.9023 +
 86.9024 +	t1 = ri.Milliseconds();
 86.9025 +
 86.9026 +	if(!r_smp->integer || data == backEndData[0]->commands.cmds)
 86.9027 +	{
 86.9028  		backEnd.smpFrame = 0;
 86.9029 -	} else {
 86.9030 +	}
 86.9031 +	else
 86.9032 +	{
 86.9033  		backEnd.smpFrame = 1;
 86.9034  	}
 86.9035  
 86.9036 -	while ( 1 ) {
 86.9037 -		switch ( *(const int *)data ) {
 86.9038 -		case RC_SET_COLOR:
 86.9039 -			data = RB_SetColor( data );
 86.9040 -			break;
 86.9041 -		case RC_STRETCH_PIC:
 86.9042 -			//Check if it's time for BLOOM!
 86.9043 -			R_BloomScreen();
 86.9044 -			data = RB_StretchPic( data );
 86.9045 -			break;
 86.9046 -		case RC_DRAW_SURFS:
 86.9047 -			data = RB_DrawSurfs( data );
 86.9048 -			break;
 86.9049 -		case RC_DRAW_BUFFER:
 86.9050 -			data = RB_DrawBuffer( data );
 86.9051 -			break;
 86.9052 -		case RC_SWAP_BUFFERS:
 86.9053 -			//Check if it's time for BLOOM!
 86.9054 -			R_BloomScreen();
 86.9055 -			data = RB_SwapBuffers( data );
 86.9056 -			break;
 86.9057 -		case RC_SCREENSHOT:
 86.9058 -			data = RB_TakeScreenshotCmd( data );
 86.9059 -			break;
 86.9060 -		case RC_VIDEOFRAME:
 86.9061 -			data = RB_TakeVideoFrameCmd( data );
 86.9062 -			break;
 86.9063 -		case RC_COLORMASK:
 86.9064 -			data = RB_ColorMask(data);
 86.9065 -			break;
 86.9066 -		case RC_CLEARDEPTH:
 86.9067 -			data = RB_ClearDepth(data);
 86.9068 -			break;
 86.9069 -		case RC_END_OF_LIST:
 86.9070 -		default:
 86.9071 -			// stop rendering on this thread
 86.9072 -			t2 = ri.Milliseconds ();
 86.9073 -			backEnd.pc.msec = t2 - t1;
 86.9074 -			return;
 86.9075 -		}
 86.9076 -	}
 86.9077 -
 86.9078 +	while(1)
 86.9079 +	{
 86.9080 +		switch (*(const int *)data)
 86.9081 +		{
 86.9082 +			case RC_SET_COLOR:
 86.9083 +				data = RB_SetColor(data);
 86.9084 +				break;
 86.9085 +			case RC_STRETCH_PIC:
 86.9086 +				data = RB_StretchPic(data);
 86.9087 +				break;
 86.9088 +			case RC_DRAW_VIEW:
 86.9089 +				data = RB_DrawView(data);
 86.9090 +				break;
 86.9091 +			case RC_DRAW_BUFFER:
 86.9092 +				data = RB_DrawBuffer(data);
 86.9093 +				break;
 86.9094 +			case RC_SWAP_BUFFERS:
 86.9095 +				data = RB_SwapBuffers(data);
 86.9096 +				break;
 86.9097 +			case RC_SCREENSHOT:
 86.9098 +				data = RB_TakeScreenshotCmd(data);
 86.9099 +				break;
 86.9100 +			case RC_VIDEOFRAME:
 86.9101 +				data = RB_TakeVideoFrameCmd(data);
 86.9102 +				break;
 86.9103 +
 86.9104 +			case RC_END_OF_LIST:
 86.9105 +			default:
 86.9106 +				// stop rendering on this thread
 86.9107 +				t2 = ri.Milliseconds();
 86.9108 +				backEnd.pc.msec = t2 - t1;
 86.9109 +				return;
 86.9110 +		}
 86.9111 +	}
 86.9112  }
 86.9113  
 86.9114  
 86.9115 @@ -1197,23 +8272,25 @@
 86.9116  RB_RenderThread
 86.9117  ================
 86.9118  */
 86.9119 -void RB_RenderThread( void ) {
 86.9120 -	const void	*data;
 86.9121 +void RB_RenderThread(void)
 86.9122 +{
 86.9123 +	const void     *data;
 86.9124  
 86.9125  	// wait for either a rendering command or a quit command
 86.9126 -	while ( 1 ) {
 86.9127 +	while(1)
 86.9128 +	{
 86.9129  		// sleep until we have work to do
 86.9130  		data = GLimp_RendererSleep();
 86.9131  
 86.9132 -		if ( !data ) {
 86.9133 -			return;	// all done, renderer is shutting down
 86.9134 +		if(!data)
 86.9135 +		{
 86.9136 +			return;				// all done, renderer is shutting down
 86.9137  		}
 86.9138  
 86.9139  		renderThreadActive = qtrue;
 86.9140  
 86.9141 -		RB_ExecuteRenderCommands( data );
 86.9142 +		RB_ExecuteRenderCommands(data);
 86.9143  
 86.9144  		renderThreadActive = qfalse;
 86.9145  	}
 86.9146  }
 86.9147 -
    87.1 --- a/src/renderer/tr_bsp.c	Sat Jun 06 03:54:16 2009 +0800
    87.2 +++ b/src/renderer/tr_bsp.c	Wed Jun 10 09:31:46 2009 +0800
    87.3 @@ -1,105 +1,109 @@
    87.4  /*
    87.5  ===========================================================================
    87.6  Copyright (C) 1999-2005 Id Software, Inc.
    87.7 -Copyright (C) 2000-2006 Tim Angus
    87.8 -
    87.9 -This file is part of Tremfusion.
   87.10 -
   87.11 -Tremfusion is free software; you can redistribute it
   87.12 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
   87.13 +Copyright (C) 2009 Peter McNeill <n27@bigpond.net.au>
   87.14 +
   87.15 +This file is part of XreaL source code.
   87.16 +
   87.17 +XreaL source code is free software; you can redistribute it
   87.18  and/or modify it under the terms of the GNU General Public License as
   87.19  published by the Free Software Foundation; either version 2 of the License,
   87.20  or (at your option) any later version.
   87.21  
   87.22 -Tremfusion is distributed in the hope that it will be
   87.23 +XreaL source code is distributed in the hope that it will be
   87.24  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   87.25  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   87.26  GNU General Public License for more details.
   87.27  
   87.28  You should have received a copy of the GNU General Public License
   87.29 -along with Tremfusion; if not, write to the Free Software
   87.30 +along with XreaL source code; if not, write to the Free Software
   87.31  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   87.32  ===========================================================================
   87.33  */
   87.34 -// tr_map.c
   87.35 -
   87.36 +// tr_bsp.c
   87.37  #include "tr_local.h"
   87.38  
   87.39  /*
   87.40 -
   87.41 +========================================================
   87.42  Loads and prepares a map file for scene rendering.
   87.43  
   87.44  A single entry point:
   87.45 -
   87.46 -void RE_LoadWorldMap( const char *name );
   87.47 -
   87.48 +RE_LoadWorldMap(const char *name);
   87.49 +========================================================
   87.50  */
   87.51  
   87.52 -static	world_t		s_worldData;
   87.53 -static	byte		*fileBase;
   87.54 -
   87.55 -int			c_subdivisions;
   87.56 -int			c_gridVerts;
   87.57 +static world_t  s_worldData;
   87.58 +static int      s_lightCount;
   87.59 +static growList_t s_interactions;
   87.60 +static byte    *fileBase;
   87.61 +
   87.62 +static int      c_redundantInteractions;
   87.63 +static int      c_redundantVertexes;
   87.64 +static int      c_vboWorldSurfaces;
   87.65 +static int      c_vboLightSurfaces;
   87.66 +static int      c_vboShadowSurfaces;
   87.67  
   87.68  //===============================================================================
   87.69  
   87.70 -static void HSVtoRGB( float h, float s, float v, float rgb[3] )
   87.71 +void HSVtoRGB(float h, float s, float v, float rgb[3])
   87.72  {
   87.73 -	int i;
   87.74 -	float f;
   87.75 -	float p, q, t;
   87.76 +	int             i;
   87.77 +	float           f;
   87.78 +	float           p, q, t;
   87.79  
   87.80  	h *= 5;
   87.81  
   87.82 -	i = floor( h );
   87.83 +	i = floor(h);
   87.84  	f = h - i;
   87.85  
   87.86 -	p = v * ( 1 - s );
   87.87 -	q = v * ( 1 - s * f );
   87.88 -	t = v * ( 1 - s * ( 1 - f ) );
   87.89 -
   87.90 -	switch ( i )
   87.91 -	{
   87.92 -	case 0:
   87.93 -		rgb[0] = v;
   87.94 -		rgb[1] = t;
   87.95 -		rgb[2] = p;
   87.96 -		break;
   87.97 -	case 1:
   87.98 -		rgb[0] = q;
   87.99 -		rgb[1] = v;
  87.100 -		rgb[2] = p;
  87.101 -		break;
  87.102 -	case 2:
  87.103 -		rgb[0] = p;
  87.104 -		rgb[1] = v;
  87.105 -		rgb[2] = t;
  87.106 -		break;
  87.107 -	case 3:
  87.108 -		rgb[0] = p;
  87.109 -		rgb[1] = q;
  87.110 -		rgb[2] = v;
  87.111 -		break;
  87.112 -	case 4:
  87.113 -		rgb[0] = t;
  87.114 -		rgb[1] = p;
  87.115 -		rgb[2] = v;
  87.116 -		break;
  87.117 -	case 5:
  87.118 -		rgb[0] = v;
  87.119 -		rgb[1] = p;
  87.120 -		rgb[2] = q;
  87.121 -		break;
  87.122 +	p = v * (1 - s);
  87.123 +	q = v * (1 - s * f);
  87.124 +	t = v * (1 - s * (1 - f));
  87.125 +
  87.126 +	switch (i)
  87.127 +	{
  87.128 +		case 0:
  87.129 +			rgb[0] = v;
  87.130 +			rgb[1] = t;
  87.131 +			rgb[2] = p;
  87.132 +			break;
  87.133 +		case 1:
  87.134 +			rgb[0] = q;
  87.135 +			rgb[1] = v;
  87.136 +			rgb[2] = p;
  87.137 +			break;
  87.138 +		case 2:
  87.139 +			rgb[0] = p;
  87.140 +			rgb[1] = v;
  87.141 +			rgb[2] = t;
  87.142 +			break;
  87.143 +		case 3:
  87.144 +			rgb[0] = p;
  87.145 +			rgb[1] = q;
  87.146 +			rgb[2] = v;
  87.147 +			break;
  87.148 +		case 4:
  87.149 +			rgb[0] = t;
  87.150 +			rgb[1] = p;
  87.151 +			rgb[2] = v;
  87.152 +			break;
  87.153 +		case 5:
  87.154 +			rgb[0] = v;
  87.155 +			rgb[1] = p;
  87.156 +			rgb[2] = q;
  87.157 +			break;
  87.158  	}
  87.159  }
  87.160  
  87.161  /*
  87.162  ===============
  87.163  R_ColorShiftLightingBytes
  87.164 -
  87.165  ===============
  87.166  */
  87.167 -static	void R_ColorShiftLightingBytes( byte in[4], byte out[4] ) {
  87.168 -	int		shift, r, g, b;
  87.169 +static void R_ColorShiftLightingBytes(byte in[4], byte out[4])
  87.170 +{
  87.171 +	int             shift, r, g, b;
  87.172  
  87.173  	// shift the color data based on overbright range
  87.174  	shift = r_mapOverBrightBits->integer - tr.overbrightBits;
  87.175 @@ -108,10 +112,11 @@
  87.176  	r = in[0] << shift;
  87.177  	g = in[1] << shift;
  87.178  	b = in[2] << shift;
  87.179 -	
  87.180 +
  87.181  	// normalize by color instead of saturating to white
  87.182 -	if ( ( r | g | b ) > 255 ) {
  87.183 -		int		max;
  87.184 +	if((r | g | b) > 255)
  87.185 +	{
  87.186 +		int             max;
  87.187  
  87.188  		max = r > g ? r : g;
  87.189  		max = max > b ? max : b;
  87.190 @@ -128,92 +133,945 @@
  87.191  
  87.192  /*
  87.193  ===============
  87.194 +R_ColorShiftLightingFloats
  87.195 +===============
  87.196 +*/
  87.197 +static void R_ColorShiftLightingFloats(const vec4_t in, vec4_t out)
  87.198 +{
  87.199 +	int             shift, r, g, b;
  87.200 +
  87.201 +	// shift the color data based on overbright range
  87.202 +	shift = r_mapOverBrightBits->integer - tr.overbrightBits;
  87.203 +
  87.204 +	// shift the data based on overbright range
  87.205 +	r = ((byte)(in[0] * 255)) << shift;
  87.206 +	g = ((byte)(in[1] * 255)) << shift;
  87.207 +	b = ((byte)(in[2] * 255)) << shift;
  87.208 +
  87.209 +	// normalize by color instead of saturating to white
  87.210 +	if((r | g | b) > 255)
  87.211 +	{
  87.212 +		int             max;
  87.213 +
  87.214 +		max = r > g ? r : g;
  87.215 +		max = max > b ? max : b;
  87.216 +		r = r * 255 / max;
  87.217 +		g = g * 255 / max;
  87.218 +		b = b * 255 / max;
  87.219 +	}
  87.220 +
  87.221 +	out[0] = r * (1.0f / 255.0f);
  87.222 +	out[1] = g * (1.0f / 255.0f);
  87.223 +	out[2] = b * (1.0f / 255.0f);
  87.224 +	out[3] = in[3];
  87.225 +}
  87.226 +
  87.227 +/*
  87.228 +===============
  87.229 +R_HDRTonemapLightingColors
  87.230 +===============
  87.231 +*/
  87.232 +static void R_HDRTonemapLightingColors(const vec4_t in, vec4_t out, qboolean applyGamma)
  87.233 +{
  87.234 +#if 0 //!defined(USE_HDR_LIGHTMAPS)
  87.235 +	R_ColorShiftLightingFloats(in, out);
  87.236 +#else
  87.237 +	int             i;
  87.238 +	float           scaledLuminance;
  87.239 +	float           finalLuminance;
  87.240 +	const vec3_t    LUMINANCE_VECTOR = { 0.2125f, 0.7154f, 0.0721f };
  87.241 +	vec4_t          sample;
  87.242 +
  87.243 +
  87.244 +#if 0
  87.245 +	scaledLuminance = r_hdrLightmapExposure->value * DotProduct(in, LUMINANCE_VECTOR);
  87.246 +
  87.247 +#if 0
  87.248 +	finalLuminance = scaledLuminance / (scaledLuminance + 1.0);
  87.249 +#else
  87.250 +	// exponential tone mapping
  87.251 +	finalLuminance = 1.0 - exp(-scaledLuminance);
  87.252 +#endif
  87.253 +
  87.254 +	VectorScale(sample, finalLuminance, sample);
  87.255 +	sample[3] = Q_min(1.0f, sample[3]);
  87.256 +
  87.257 +	if(!r_hdrRendering->integer || !r_hdrLightmap->integer || !glConfig.framebufferObjectAvailable ||
  87.258 +	   !glConfig.textureFloatAvailable || !glConfig.framebufferBlitAvailable)
  87.259 +	{
  87.260 +		float           max;
  87.261 +
  87.262 +		// clamp with color normalization
  87.263 +		NormalizeColor(sample, out);
  87.264 +		out[3] = Q_min(1.0f, sample[3]);
  87.265 +	}
  87.266 +	else
  87.267 +	{
  87.268 +		VectorCopy4(sample, out);
  87.269 +	}
  87.270 +#else
  87.271 +	if(!r_hdrRendering->integer || !r_hdrLightmap->integer || !glConfig.framebufferObjectAvailable ||
  87.272 +	   !glConfig.textureFloatAvailable || !glConfig.framebufferBlitAvailable)
  87.273 +	{
  87.274 +		float           max;
  87.275 +
  87.276 +		VectorCopy4(in, sample);
  87.277 +
  87.278 +		// clamp with color normalization
  87.279 +		max = sample[0];
  87.280 +		if(sample[1] > max)
  87.281 +			max = sample[1];
  87.282 +		if(sample[2] > max)
  87.283 +			max = sample[2];
  87.284 +		if(max > 255.0f)
  87.285 +			VectorScale(sample, (255.0f / max), out);
  87.286 +
  87.287 +		VectorScale(out, (1.0f / 255.0f), out);
  87.288 +
  87.289 +		out[3] = Q_min(1.0f, sample[3]);
  87.290 +	}
  87.291 +	else
  87.292 +	{
  87.293 +		VectorScale4(in, 1.0f / 255.0f, sample);
  87.294 +
  87.295 +		if(applyGamma)
  87.296 +		{
  87.297 +			for(i = 0; i < 3; i++)
  87.298 +			{
  87.299 +				sample[i] = pow(sample[i], 1.0f / r_hdrLightmapGamma->value);
  87.300 +			}
  87.301 +		}
  87.302 +
  87.303 +#if 0
  87.304 +		scaledLuminance = r_hdrLightmapExposure->value * DotProduct(in, LUMINANCE_VECTOR);
  87.305 +
  87.306 +#if 0
  87.307 +		finalLuminance = scaledLuminance / (scaledLuminance + 1.0);
  87.308 +#else
  87.309 +		// exponential tone mapping
  87.310 +		finalLuminance = 1.0 - exp(-scaledLuminance);
  87.311 +#endif
  87.312 +
  87.313 +		VectorScale(sample, finalLuminance, out);
  87.314 +#else
  87.315 +		VectorCopy(sample, out);
  87.316 +#endif
  87.317 +
  87.318 +		out[3] = Q_min(1.0f, sample[3]);
  87.319 +	}
  87.320 +#endif
  87.321 +#endif
  87.322 +}
  87.323 +
  87.324 +static int QDECL LightmapNameCompare(const void *a, const void *b)
  87.325 +{
  87.326 +	char           *s1, *s2;
  87.327 +	int             c1, c2;
  87.328 +
  87.329 +	s1 = *(char **)a;
  87.330 +	s2 = *(char **)b;
  87.331 +
  87.332 +	do
  87.333 +	{
  87.334 +		c1 = *s1++;
  87.335 +		c2 = *s2++;
  87.336 +
  87.337 +		if(c1 >= 'a' && c1 <= 'z')
  87.338 +		{
  87.339 +			c1 -= ('a' - 'A');
  87.340 +		}
  87.341 +		if(c2 >= 'a' && c2 <= 'z')
  87.342 +		{
  87.343 +			c2 -= ('a' - 'A');
  87.344 +		}
  87.345 +
  87.346 +		if(c1 == '\\' || c1 == ':')
  87.347 +		{
  87.348 +			c1 = '/';
  87.349 +		}
  87.350 +		if(c2 == '\\' || c2 == ':')
  87.351 +		{
  87.352 +			c2 = '/';
  87.353 +		}
  87.354 +
  87.355 +		if(c1 < c2)
  87.356 +		{
  87.357 +			// strings not equal
  87.358 +			return -1;
  87.359 +		}
  87.360 +		if(c1 > c2)
  87.361 +		{
  87.362 +			return 1;
  87.363 +		}
  87.364 +	} while(c1);
  87.365 +
  87.366 +	// strings are equal
  87.367 +	return 0;
  87.368 +}
  87.369 +
  87.370 +/* standard conversion from rgbe to float pixels */
  87.371 +/* note: Ward uses ldexp(col+0.5,exp-(128+8)).  However we wanted pixels */
  87.372 +/*       in the range [0,1] to map back into the range [0,1].            */
  87.373 +static ID_INLINE void rgbe2float(float *red, float *green, float *blue, unsigned char rgbe[4])
  87.374 +{
  87.375 +	float           e;
  87.376 +	float           f;
  87.377 +
  87.378 +	if(rgbe[3])
  87.379 +	{							/*nonzero pixel */
  87.380 +		f = ldexp(1.0, rgbe[3] - (int)(128 + 8));
  87.381 +		//f = ldexp(1.0, rgbe[3] - 128) / 10.0;
  87.382 +		e = (rgbe[3] - 128) / 4.0f;
  87.383 +		f = exp2(e);
  87.384 +		//decoded = rgbe.rgb * exp2(fExp);
  87.385 +		*red = (rgbe[0] / 255.0f) * f;
  87.386 +		*green = (rgbe[1] / 255.0f) * f;
  87.387 +		*blue = (rgbe[2] / 255.0f) * f;
  87.388 +	}
  87.389 +	else
  87.390 +		*red = *green = *blue = 0.0;
  87.391 +}
  87.392 +
  87.393 +void LoadRGBEToFloats(const char *name, float **pic, int *width, int *height, qboolean doGamma, qboolean toneMap,
  87.394 +							 qboolean compensate)
  87.395 +{
  87.396 +	int             i, j;
  87.397 +	byte           *buf_p;
  87.398 +	byte           *buffer;
  87.399 +	float          *floatbuf;
  87.400 +	int             len;
  87.401 +	char           *token;
  87.402 +	int             w, h, c;
  87.403 +	qboolean        formatFound;
  87.404 +	unsigned char   rgbe[4];
  87.405 +	float           red;
  87.406 +	float           green;
  87.407 +	float           blue;
  87.408 +	float           max;
  87.409 +	float           inv, dif;
  87.410 +	float           exposure = 1.6;
  87.411 +	float           exposureGain = 1.0;
  87.412 +	const vec3_t    LUMINANCE_VECTOR = { 0.2125f, 0.7154f, 0.0721f };
  87.413 +	float           luminance;
  87.414 +	float           avgLuminance;
  87.415 +	float           maxLuminance;
  87.416 +	float           scaledLuminance;
  87.417 +	float           finalLuminance;
  87.418 +	double          sum;
  87.419 +	float           gamma;
  87.420 +
  87.421 +	union
  87.422 +	{
  87.423 +		byte            b[4];
  87.424 +		float           f;
  87.425 +	} sample;
  87.426 +	vec4_t          sampleVector;
  87.427 +
  87.428 +	*pic = NULL;
  87.429 +
  87.430 +	// load the file
  87.431 +	len = ri.FS_ReadFile((char *)name, (void **)&buffer);
  87.432 +	if(!buffer)
  87.433 +	{
  87.434 +		ri.Error(ERR_DROP, "LoadRGBE: '%s' not found\n", name);
  87.435 +		return;
  87.436 +	}
  87.437 +
  87.438 +	buf_p = buffer;
  87.439 +
  87.440 +	formatFound = qfalse;
  87.441 +	w = h = 0;
  87.442 +	while(qtrue)
  87.443 +	{
  87.444 +		token = Com_ParseExt((char **)&buf_p, qtrue);
  87.445 +		if(!token[0])
  87.446 +			break;
  87.447 +
  87.448 +		if(!Q_stricmp(token, "FORMAT"))
  87.449 +		{
  87.450 +			//ri.Printf(PRINT_ALL, "LoadRGBE: FORMAT found\n");
  87.451 +
  87.452 +			token = Com_ParseExt((char **)&buf_p, qfalse);
  87.453 +			if(!Q_stricmp(token, "="))
  87.454 +			{
  87.455 +				token = Com_ParseExt((char **)&buf_p, qfalse);
  87.456 +				if(!Q_stricmp(token, "32"))
  87.457 +				{
  87.458 +					token = Com_ParseExt((char **)&buf_p, qfalse);
  87.459 +					if(!Q_stricmp(token, "-"))
  87.460 +					{
  87.461 +						token = Com_ParseExt((char **)&buf_p, qfalse);
  87.462 +						if(!Q_stricmp(token, "bit_rle_rgbe"))
  87.463 +						{
  87.464 +							formatFound = qtrue;
  87.465 +						}
  87.466 +						else
  87.467 +						{
  87.468 +							ri.Printf(PRINT_ALL, "LoadRGBE: Expected 'bit_rle_rgbe' found instead '%s'\n", token);
  87.469 +						}
  87.470 +					}
  87.471 +					else
  87.472 +					{
  87.473 +						ri.Printf(PRINT_ALL, "LoadRGBE: Expected '-' found instead '%s'\n", token);
  87.474 +					}
  87.475 +				}
  87.476 +				else
  87.477 +				{
  87.478 +					ri.Printf(PRINT_ALL, "LoadRGBE: Expected '32' found instead '%s'\n", token);
  87.479 +				}
  87.480 +			}
  87.481 +			else
  87.482 +			{
  87.483 +				ri.Printf(PRINT_ALL, "LoadRGBE: Expected '=' found instead '%s'\n", token);
  87.484 +			}
  87.485 +		}
  87.486 +
  87.487 +		if(!Q_stricmp(token, "-"))
  87.488 +		{
  87.489 +			token = Com_ParseExt((char **)&buf_p, qfalse);
  87.490 +			if(!Q_stricmp(token, "Y"))
  87.491 +			{
  87.492 +				token = Com_ParseExt((char **)&buf_p, qfalse);
  87.493 +				w = atoi(token);
  87.494 +
  87.495 +				token = Com_ParseExt((char **)&buf_p, qfalse);
  87.496 +				if(!Q_stricmp(token, "+"))
  87.497 +				{
  87.498 +					token = Com_ParseExt((char **)&buf_p, qfalse);
  87.499 +					if(!Q_stricmp(token, "X"))
  87.500 +					{
  87.501 +						token = Com_ParseExt((char **)&buf_p, qfalse);
  87.502 +						h = atoi(token);
  87.503 +						break;
  87.504 +					}
  87.505 +					else
  87.506 +					{
  87.507 +						ri.Printf(PRINT_ALL, "LoadRGBE: Expected 'X' found instead '%s'\n", token);
  87.508 +					}
  87.509 +				}
  87.510 +				else
  87.511 +				{
  87.512 +					ri.Printf(PRINT_ALL, "LoadRGBE: Expected '+' found instead '%s'\n", token);
  87.513 +				}
  87.514 +			}
  87.515 +			else
  87.516 +			{
  87.517 +				ri.Printf(PRINT_ALL, "LoadRGBE: Expected 'Y' found instead '%s'\n", token);
  87.518 +			}
  87.519 +		}
  87.520 +	}
  87.521 +
  87.522 +	// go to the first byte
  87.523 +	while((c = *buf_p++) != 0)
  87.524 +	{
  87.525 +		if(c == '\n')
  87.526 +		{
  87.527 +			//buf_p++;
  87.528 +			break;
  87.529 +		}
  87.530 +	}
  87.531 +
  87.532 +	if(width)
  87.533 +		*width = w;
  87.534 +	if(height)
  87.535 +		*height = h;
  87.536 +
  87.537 +	if(!formatFound)
  87.538 +	{
  87.539 +		ri.Error(ERR_DROP, "LoadRGBE: %s has no format\n", name);
  87.540 +	}
  87.541 +
  87.542 +	if(!w || !h)
  87.543 +	{
  87.544 +		ri.Error(ERR_DROP, "LoadRGBE: %s has an invalid image size\n", name);
  87.545 +	}
  87.546 +
  87.547 +	*pic = Com_Allocate(w * h * 3 * sizeof(float));
  87.548 +	floatbuf = *pic;
  87.549 +	for(i = 0; i < (w * h); i++)
  87.550 +	{
  87.551 +#if 0
  87.552 +		rgbe[0] = *buf_p++;
  87.553 +		rgbe[1] = *buf_p++;
  87.554 +		rgbe[2] = *buf_p++;
  87.555 +		rgbe[3] = *buf_p++;
  87.556 +
  87.557 +		rgbe2float(&red, &green, &blue, rgbe);
  87.558 +
  87.559 +		*floatbuf++ = red;
  87.560 +		*floatbuf++ = green;
  87.561 +		*floatbuf++ = blue;
  87.562 +#else
  87.563 +		for(j = 0; j < 3; j++)
  87.564 +		{
  87.565 +			sample.b[0] = *buf_p++;
  87.566 +			sample.b[1] = *buf_p++;
  87.567 +			sample.b[2] = *buf_p++;
  87.568 +			sample.b[3] = *buf_p++;
  87.569 +
  87.570 +			*floatbuf++ = sample.f / 255.0f;	// FIXME XMap2's output is 255 times too high
  87.571 +		}
  87.572 +#endif
  87.573 +	}
  87.574 +
  87.575 +	// LOADING DONE
  87.576 +	if(doGamma)
  87.577 +	{
  87.578 +		floatbuf = *pic;
  87.579 +		gamma = 1.0f / r_hdrLightmapGamma->value;
  87.580 +		for(i = 0; i < (w * h); i++)
  87.581 +		{
  87.582 +			for(j = 0; j < 3; j++)
  87.583 +			{
  87.584 +				//*floatbuf = pow(*floatbuf / 255.0f, gamma) * 255.0f;
  87.585 +				*floatbuf = pow(*floatbuf, gamma);
  87.586 +				floatbuf++;
  87.587 +			}
  87.588 +		}
  87.589 +	}
  87.590 +
  87.591 +	if(toneMap)
  87.592 +	{
  87.593 +		// calculate the average and maximum luminance
  87.594 +		sum = 0.0f;
  87.595 +		maxLuminance = 0.0f;
  87.596 +		floatbuf = *pic;
  87.597 +		for(i = 0; i < (w * h); i++)
  87.598 +		{
  87.599 +			for(j = 0; j < 3; j++)
  87.600 +			{
  87.601 +				sampleVector[j] = *floatbuf++;
  87.602 +			}
  87.603 +
  87.604 +			luminance = DotProduct(sampleVector, LUMINANCE_VECTOR) + 0.0001f;
  87.605 +			if(luminance > maxLuminance)
  87.606 +				maxLuminance = luminance;
  87.607 +
  87.608 +			sum += log(luminance);
  87.609 +		}
  87.610 +		sum /= (float)(w * h);
  87.611 +		avgLuminance = exp(sum);
  87.612 +
  87.613 +		// post process buffer with tone mapping
  87.614 +		floatbuf = *pic;
  87.615 +		for(i = 0; i < (w * h); i++)
  87.616 +		{
  87.617 +			for(j = 0; j < 3; j++)
  87.618 +			{
  87.619 +				sampleVector[j] = *floatbuf++;
  87.620 +			}
  87.621 +
  87.622 +			if(r_hdrLightmapExposure->value <= 0)
  87.623 +			{
  87.624 +				exposure = (r_hdrKey->value / avgLuminance);
  87.625 +			}
  87.626 +			else
  87.627 +			{
  87.628 +				exposure = r_hdrLightmapExposure->value;
  87.629 +			}
  87.630 +			//
  87.631 +
  87.632 +			scaledLuminance = exposure * DotProduct(sampleVector, LUMINANCE_VECTOR);
  87.633 +#if 0
  87.634 +			finalLuminance = scaledLuminance / (scaledLuminance + 1.0);
  87.635 +#elif 0
  87.636 +			finalLuminance = (scaledLuminance * (scaledLuminance / maxLuminance + 1.0)) / (scaledLuminance + 1.0);
  87.637 +#elif 0
  87.638 +			finalLuminance =
  87.639 +				(scaledLuminance * ((scaledLuminance / (maxLuminance * maxLuminance)) + 1.0)) / (scaledLuminance + 1.0);
  87.640 +#else
  87.641 +			// exponential tone mapping
  87.642 +			finalLuminance = 1.0 - exp(-scaledLuminance);
  87.643 +#endif
  87.644 +
  87.645 +			//VectorScale(sampleVector, scaledLuminance * (scaledLuminance / maxLuminance + 1.0) / (scaledLuminance + 1.0), sampleVector);
  87.646 +			//VectorScale(sampleVector, scaledLuminance / (scaledLuminance + 1.0), sampleVector);
  87.647 +
  87.648 +			VectorScale(sampleVector, finalLuminance, sampleVector);
  87.649 +
  87.650 +			floatbuf -= 3;
  87.651 +			for(j = 0; j < 3; j++)
  87.652 +			{
  87.653 +				*floatbuf++ = sampleVector[j];
  87.654 +			}
  87.655 +		}
  87.656 +	}
  87.657 +
  87.658 +	if(compensate)
  87.659 +	{
  87.660 +		floatbuf = *pic;
  87.661 +		for(i = 0; i < (w * h); i++)
  87.662 +		{
  87.663 +			for(j = 0; j < 3; j++)
  87.664 +			{
  87.665 +				*floatbuf = *floatbuf / r_hdrLightmapCompensate->value;
  87.666 +				floatbuf++;
  87.667 +			}
  87.668 +		}
  87.669 +	}
  87.670 +
  87.671 +	ri.FS_FreeFile(buffer);
  87.672 +}
  87.673 +
  87.674 +
  87.675 +static void LoadRGBEToBytes(const char *name, byte ** ldrImage, int *width, int *height)
  87.676 +{
  87.677 +	int             i, j;
  87.678 +	int             w, h;
  87.679 +	float          *hdrImage;
  87.680 +	float          *floatbuf;
  87.681 +	byte           *pixbuf;
  87.682 +	vec3_t          sample;
  87.683 +	float           max;
  87.684 +
  87.685 +#if 0
  87.686 +	w = h = 0;
  87.687 +	LoadRGBEToFloats(name, &hdrImage, &w, &h, qtrue, qtrue, qtrue);
  87.688 +
  87.689 +	*width = w;
  87.690 +	*height = h;
  87.691 +
  87.692 +	*ldrImage = ri.Malloc(w * h * 4);
  87.693 +	pixbuf = *ldrImage;
  87.694 +
  87.695 +	floatbuf = hdrImage;
  87.696 +	for(i = 0; i < (w * h); i++)
  87.697 +	{
  87.698 +		for(j = 0; j < 3; j++)
  87.699 +		{
  87.700 +			sample[j] = *floatbuf++;
  87.701 +		}
  87.702 +
  87.703 +		NormalizeColor(sample, sample);
  87.704 +
  87.705 +		*pixbuf++ = (byte) (sample[0] * 255);
  87.706 +		*pixbuf++ = (byte) (sample[1] * 255);
  87.707 +		*pixbuf++ = (byte) (sample[2] * 255);
  87.708 +		*pixbuf++ = (byte) 255;
  87.709 +	}
  87.710 +#else
  87.711 +	w = h = 0;
  87.712 +	LoadRGBEToFloats(name, &hdrImage, &w, &h, qfalse, qfalse, qfalse);
  87.713 +
  87.714 +	*width = w;
  87.715 +	*height = h;
  87.716 +
  87.717 +	*ldrImage = ri.Malloc(w * h * 4);
  87.718 +	pixbuf = *ldrImage;
  87.719 +
  87.720 +	floatbuf = hdrImage;
  87.721 +	for(i = 0; i < (w * h); i++)
  87.722 +	{
  87.723 +		for(j = 0; j < 3; j++)
  87.724 +		{
  87.725 +			sample[j] = *floatbuf++ * 255.0f;
  87.726 +		}
  87.727 +
  87.728 +		// clamp with color normalization
  87.729 +		max = sample[0];
  87.730 +		if(sample[1] > max)
  87.731 +			max = sample[1];
  87.732 +		if(sample[2] > max)
  87.733 +			max = sample[2];
  87.734 +		if(max > 255.0f)
  87.735 +			VectorScale(sample, (255.0f / max), sample);
  87.736 +
  87.737 +		*pixbuf++ = (byte) sample[0];
  87.738 +		*pixbuf++ = (byte) sample[1];
  87.739 +		*pixbuf++ = (byte) sample[2];
  87.740 +		*pixbuf++ = (byte) 255;
  87.741 +	}
  87.742 +#endif
  87.743 +
  87.744 +	Com_Dealloc(hdrImage);
  87.745 +}
  87.746 +
  87.747 +void LoadRGBEToHalfs(const char *name, unsigned short ** halfImage, int *width, int *height);
  87.748 +
  87.749 +/*
  87.750 +===============
  87.751  R_LoadLightmaps
  87.752 -
  87.753  ===============
  87.754  */
  87.755  #define	LIGHTMAP_SIZE	128
  87.756 -static	void R_LoadLightmaps( lump_t *l ) {
  87.757 -	byte		*buf, *buf_p;
  87.758 -	int			len;
  87.759 -	byte		image[LIGHTMAP_SIZE*LIGHTMAP_SIZE*4];
  87.760 -	int			i, j;
  87.761 -	float maxIntensity = 0;
  87.762 -	double sumIntensity = 0;
  87.763 +static void R_LoadLightmaps(lump_t * l, const char *bspName)
  87.764 +{
  87.765 +	byte           *buf, *buf_p;
  87.766 +	int             len;
  87.767 +	image_t        *image;
  87.768 +	static byte     data[LIGHTMAP_SIZE * LIGHTMAP_SIZE * 4];
  87.769 +	int             i, j;
  87.770 +	int             numLightmaps;
  87.771  
  87.772  	len = l->filelen;
  87.773 -	if ( !len ) {
  87.774 -		return;
  87.775 -	}
  87.776 -	buf = fileBase + l->fileofs;
  87.777 -
  87.778 -	// we are about to upload textures
  87.779 -	R_SyncRenderThread();
  87.780 -
  87.781 -	// create all the lightmaps
  87.782 -	tr.numLightmaps = len / (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3);
  87.783 -	if ( tr.numLightmaps == 1 ) {
  87.784 -		//FIXME: HACK: maps with only one lightmap turn up fullbright for some reason.
  87.785 -		//this avoids this, but isn't the correct solution.
  87.786 -		tr.numLightmaps++;
  87.787 -	} else if ( tr.numLightmaps >= MAX_LIGHTMAPS ) { // 20051020 misantropia
  87.788 -		ri.Printf( PRINT_WARNING, "WARNING: number of lightmaps > MAX_LIGHTMAPS\n" );
  87.789 -		tr.numLightmaps = MAX_LIGHTMAPS;
  87.790 -	}
  87.791 -
  87.792 -	// if we are in r_vertexLight mode, we don't need the lightmaps at all
  87.793 -	if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) {
  87.794 -		return;
  87.795 -	}
  87.796 -
  87.797 -	for ( i = 0 ; i < tr.numLightmaps ; i++ ) {
  87.798 -		// expand the 24 bit on-disk to 32 bit
  87.799 -		buf_p = buf + i * LIGHTMAP_SIZE*LIGHTMAP_SIZE * 3;
  87.800 -
  87.801 -		if ( r_lightmap->integer == 2 )
  87.802 -		{	// color code by intensity as development tool	(FIXME: check range)
  87.803 -			for ( j = 0; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ )
  87.804 -			{
  87.805 -				float r = buf_p[j*3+0];
  87.806 -				float g = buf_p[j*3+1];
  87.807 -				float b = buf_p[j*3+2];
  87.808 -				float intensity;
  87.809 -				float out[3] = {0.0, 0.0, 0.0};
  87.810 -
  87.811 -				intensity = 0.33f * r + 0.685f * g + 0.063f * b;
  87.812 -
  87.813 -				if ( intensity > 255 )
  87.814 -					intensity = 1.0f;
  87.815 +	if(!len)
  87.816 +	{
  87.817 +		char            mapName[MAX_QPATH];
  87.818 +		char          **lightmapFiles;
  87.819 +
  87.820 +		Q_strncpyz(mapName, bspName, sizeof(mapName));
  87.821 +		Com_StripExtension(mapName, mapName, sizeof(mapName));
  87.822 +
  87.823 +#if 1
  87.824 +		if(tr.worldHDR_RGBE)
  87.825 +		{
  87.826 +			// we are about to upload textures
  87.827 +			R_SyncRenderThread();
  87.828 +
  87.829 +			// load HDR lightmaps
  87.830 +			lightmapFiles = ri.FS_ListFiles(mapName, ".hdr", &numLightmaps);
  87.831 +
  87.832 +			qsort(lightmapFiles, numLightmaps, sizeof(char *), LightmapNameCompare);
  87.833 +
  87.834 +			if(!lightmapFiles || !numLightmaps)
  87.835 +			{
  87.836 +				ri.Printf(PRINT_WARNING, "WARNING: no lightmap files found\n");
  87.837 +				return;
  87.838 +			}
  87.839 +
  87.840 +			ri.Printf(PRINT_ALL, "...loading %i HDR lightmaps\n", numLightmaps);
  87.841 +
  87.842 +			if(r_hdrRendering->integer && r_hdrLightmap->integer && glConfig.framebufferObjectAvailable &&
  87.843 +			   glConfig.framebufferBlitAvailable && glConfig.textureFloatAvailable && glConfig.textureHalfFloatAvailable)
  87.844 +			{
  87.845 +				int             width, height;
  87.846 +				unsigned short *hdrImage;
  87.847 +
  87.848 +				for(i = 0; i < numLightmaps; i++)
  87.849 +				{
  87.850 +					ri.Printf(PRINT_ALL, "...loading external lightmap as RGB 16 bit half HDR '%s/%s'\n", mapName, lightmapFiles[i]);
  87.851 +
  87.852 +					width = height = 0;
  87.853 +					//LoadRGBEToFloats(va("%s/%s", mapName, lightmapFiles[i]), &hdrImage, &width, &height, qtrue, qfalse, qtrue);
  87.854 +					//LoadRGBEToHalfs(va("%s/%s", mapName, lightmapFiles[i]), &hdrImage, &width, &height);
  87.855 +
  87.856 +					//ri.Printf(PRINT_ALL, "...converted '%s/%s' to HALF format\n", mapName, lightmapFiles[i]);
  87.857 +
  87.858 +					image = R_AllocImage(va("%s/%s", mapName, lightmapFiles[i]), qtrue);
  87.859 +					if(!image)
  87.860 +						break;
  87.861 +
  87.862 +					//Q_strncpyz(image->name, );
  87.863 +					image->type = GL_TEXTURE_2D;
  87.864 +
  87.865 +					image->width = width;
  87.866 +					image->height = height;
  87.867 +
  87.868 +					image->bits = IF_NOPICMIP | IF_RGBA16F;
  87.869 +					image->filterType = FT_NEAREST;
  87.870 +					image->wrapType = WT_CLAMP;
  87.871 +
  87.872 +					GL_Bind(image);
  87.873 +
  87.874 +					image->internalFormat = GL_RGBA16F_ARB;
  87.875 +					image->uploadWidth = width;
  87.876 +					image->uploadHeight = height;
  87.877 +
  87.878 +					qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F_ARB, width, height, 0, GL_RGB, GL_HALF_FLOAT_ARB, hdrImage);
  87.879 +
  87.880 +					if(glConfig.generateMipmapAvailable)
  87.881 +					{
  87.882 +						//qglHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);    // make sure its nice
  87.883 +						qglTexParameteri(image->type, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
  87.884 +						qglTexParameteri(image->type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);   // default to trilinear
  87.885 +					}
  87.886 +
  87.887 +#if 0
  87.888 +					if(glConfig.hardwareType == GLHW_NV_DX10 || glConfig.hardwareType == GLHW_ATI_DX10)
  87.889 +					{
  87.890 +						qglTexParameterf(image->type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  87.891 +						qglTexParameterf(image->type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  87.892 +					}
  87.893 +					else
  87.894 +#endif
  87.895 +					{
  87.896 +						qglTexParameterf(image->type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  87.897 +						qglTexParameterf(image->type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  87.898 +					}
  87.899 +					qglTexParameterf(image->type, GL_TEXTURE_WRAP_S, GL_CLAMP);
  87.900 +					qglTexParameterf(image->type, GL_TEXTURE_WRAP_T, GL_CLAMP);
  87.901 +
  87.902 +					qglBindTexture(image->type, 0);
  87.903 +
  87.904 +					GL_CheckErrors();
  87.905 +
  87.906 +					Com_Dealloc(hdrImage);
  87.907 +
  87.908 +					Com_AddToGrowList(&tr.lightmaps, image);
  87.909 +				}
  87.910 +			}
  87.911 +			else
  87.912 +			{
  87.913 +				int             width, height;
  87.914 +				byte           *ldrImage;
  87.915 +
  87.916 +				for(i = 0; i < numLightmaps; i++)
  87.917 +				{
  87.918 +					ri.Printf(PRINT_ALL, "...loading external lightmap as RGB8 LDR '%s/%s'\n", mapName, lightmapFiles[i]);
  87.919 +
  87.920 +					width = height = 0;
  87.921 +					LoadRGBEToBytes(va("%s/%s", mapName, lightmapFiles[i]), &ldrImage, &width, &height);
  87.922 +
  87.923 +					image = R_CreateImage(va("%s/%s", mapName, lightmapFiles[i]), (byte *) ldrImage, width, height,
  87.924 +									  IF_NOPICMIP | IF_LIGHTMAP | IF_NOCOMPRESSION, FT_DEFAULT, WT_CLAMP);
  87.925 +
  87.926 +					Com_AddToGrowList(&tr.lightmaps, image);
  87.927 +
  87.928 +					ri.Free(ldrImage);
  87.929 +				}
  87.930 +			}
  87.931 +
  87.932 +			if(tr.worldDeluxeMapping)
  87.933 +			{
  87.934 +				// load deluxemaps
  87.935 +				lightmapFiles = ri.FS_ListFiles(mapName, ".png", &numLightmaps);
  87.936 +
  87.937 +				if(!lightmapFiles || !numLightmaps)
  87.938 +				{
  87.939 +					lightmapFiles = ri.FS_ListFiles(mapName, ".tga", &numLightmaps);
  87.940 +
  87.941 +					if(!lightmapFiles || !numLightmaps)
  87.942 +					{
  87.943 +						ri.Printf(PRINT_WARNING, "WARNING: no lightmap files found\n");
  87.944 +						return;
  87.945 +					}
  87.946 +				}
  87.947 +
  87.948 +				qsort(lightmapFiles, numLightmaps, sizeof(char *), LightmapNameCompare);
  87.949 +
  87.950 +				ri.Printf(PRINT_ALL, "...loading %i deluxemaps\n", numLightmaps);
  87.951 +
  87.952 +				for(i = 0; i < numLightmaps; i++)
  87.953 +				{
  87.954 +					ri.Printf(PRINT_ALL, "...loading external lightmap '%s/%s'\n", mapName, lightmapFiles[i]);
  87.955 +
  87.956 +					image = R_FindImageFile(va("%s/%s", mapName, lightmapFiles[i]), IF_NORMALMAP | IF_NOCOMPRESSION, FT_DEFAULT, WT_CLAMP);
  87.957 +					Com_AddToGrowList(&tr.deluxemaps, image);
  87.958 +				}
  87.959 +			}
  87.960 +		}
  87.961 +		else
  87.962 +#endif
  87.963 +		{
  87.964 +			lightmapFiles = ri.FS_ListFiles(mapName, ".png", &numLightmaps);
  87.965 +
  87.966 +			if(!lightmapFiles || !numLightmaps)
  87.967 +			{
  87.968 +				lightmapFiles = ri.FS_ListFiles(mapName, ".tga", &numLightmaps);
  87.969 +
  87.970 +				if(!lightmapFiles || !numLightmaps)
  87.971 +				{
  87.972 +					ri.Printf(PRINT_WARNING, "WARNING: no lightmap files found\n");
  87.973 +					return;
  87.974 +				}
  87.975 +			}
  87.976 +
  87.977 +			qsort(lightmapFiles, numLightmaps, sizeof(char *), LightmapNameCompare);
  87.978 +
  87.979 +			ri.Printf(PRINT_ALL, "...loading %i lightmaps\n", numLightmaps);
  87.980 +
  87.981 +			// we are about to upload textures
  87.982 +			R_SyncRenderThread();
  87.983 +
  87.984 +			for(i = 0; i < numLightmaps; i++)
  87.985 +			{
  87.986 +				ri.Printf(PRINT_ALL, "...loading external lightmap '%s/%s'\n", mapName, lightmapFiles[i]);
  87.987 +
  87.988 +				if(tr.worldDeluxeMapping)
  87.989 +				{
  87.990 +					if(i % 2 == 0)
  87.991 +					{
  87.992 +						image = R_FindImageFile(va("%s/%s", mapName, lightmapFiles[i]), IF_LIGHTMAP | IF_NOCOMPRESSION, FT_DEFAULT, WT_CLAMP);
  87.993 +						Com_AddToGrowList(&tr.lightmaps, image);
  87.994 +					}
  87.995 +					else
  87.996 +					{
  87.997 +						image = R_FindImageFile(va("%s/%s", mapName, lightmapFiles[i]), IF_NORMALMAP | IF_NOCOMPRESSION, FT_DEFAULT, WT_CLAMP);
  87.998 +						Com_AddToGrowList(&tr.deluxemaps, image);
  87.999 +					}
 87.1000 +				}
 87.1001  				else
 87.1002 -					intensity /= 255.0f;
 87.1003 -
 87.1004 -				if ( intensity > maxIntensity )
 87.1005 -					maxIntensity = intensity;
 87.1006 -
 87.1007 -				HSVtoRGB( intensity, 1.00, 0.50, out );
 87.1008 -
 87.1009 -				image[j*4+0] = out[0] * 255;
 87.1010 -				image[j*4+1] = out[1] * 255;
 87.1011 -				image[j*4+2] = out[2] * 255;
 87.1012 -				image[j*4+3] = 255;
 87.1013 -
 87.1014 -				sumIntensity += intensity;
 87.1015 -			}
 87.1016 -		} else {
 87.1017 -			for ( j = 0 ; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ ) {
 87.1018 -				R_ColorShiftLightingBytes( &buf_p[j*3], &image[j*4] );
 87.1019 -				image[j*4+3] = 255;
 87.1020 -			}
 87.1021 -		}
 87.1022 -		tr.lightmaps[i] = R_CreateImage( va("*lightmap%d",i), image, 
 87.1023 -			LIGHTMAP_SIZE, LIGHTMAP_SIZE, qfalse, qfalse, GL_CLAMP_TO_EDGE );
 87.1024 -	}
 87.1025 -
 87.1026 -	if ( r_lightmap->integer == 2 )	{
 87.1027 -		ri.Printf( PRINT_DEVELOPER, "Brightest lightmap value: %d\n", ( int ) ( maxIntensity * 255 ) );
 87.1028 -	}
 87.1029 +				{
 87.1030 +					image = R_FindImageFile(va("%s/%s", mapName, lightmapFiles[i]), IF_LIGHTMAP | IF_NOCOMPRESSION, FT_DEFAULT, WT_CLAMP);
 87.1031 +					Com_AddToGrowList(&tr.lightmaps, image);
 87.1032 +				}
 87.1033 +			}
 87.1034 +		}
 87.1035 +	}
 87.1036 +#if 0 //defined(COMPAT_Q3A)
 87.1037 +	else
 87.1038 +	{
 87.1039 +		buf = fileBase + l->fileofs;
 87.1040 +
 87.1041 +		// we are about to upload textures
 87.1042 +		R_SyncRenderThread();
 87.1043 +
 87.1044 +		// create all the lightmaps
 87.1045 +		tr.numLightmaps = len / (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3);
 87.1046 +
 87.1047 +		ri.Printf(PRINT_ALL, "...loading %i lightmaps\n", tr.numLightmaps);
 87.1048 +
 87.1049 +		for(i = 0; i < tr.numLightmaps; i++)
 87.1050 +		{
 87.1051 +			// expand the 24 bit on-disk to 32 bit
 87.1052 +			buf_p = buf + i * LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3;
 87.1053 +
 87.1054 +			if(tr.worldDeluxeMapping)
 87.1055 +			{
 87.1056 +				if(i % 2 == 0)
 87.1057 +				{
 87.1058 +					for(j = 0; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++)
 87.1059 +					{
 87.1060 +						R_ColorShiftLightingBytes(&buf_p[j * 3], &data[j * 4]);
 87.1061 +						data[j * 4 + 3] = 255;
 87.1062 +					}
 87.1063 +					image = R_CreateImage(va("_lightmap%d", i), data, LIGHTMAP_SIZE, LIGHTMAP_SIZE, IF_LIGHTMAP | IF_NOCOMPRESSION, FT_DEFAULT, WT_CLAMP);
 87.1064 +					Com_AddToGrowList(&tr.lightmaps, image);
 87.1065 +				}
 87.1066 +				else
 87.1067 +				{
 87.1068 +					for(j = 0; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++)
 87.1069 +					{
 87.1070 +						data[j * 4 + 0] = buf_p[j * 3 + 0];
 87.1071 +						data[j * 4 + 1] = buf_p[j * 3 + 1];
 87.1072 +						data[j * 4 + 2] = buf_p[j * 3 + 2];
 87.1073 +						data[j * 4 + 3] = 255;
 87.1074 +					}
 87.1075 +					image = R_CreateImage(va("_lightmap%d", i), data, LIGHTMAP_SIZE, LIGHTMAP_SIZE, IF_NORMALMAP, FT_DEFAULT, WT_CLAMP);
 87.1076 +					Com_AddToGrowList(&tr.deluxemaps, image);
 87.1077 +				}
 87.1078 +			}
 87.1079 +			else
 87.1080 +			{
 87.1081 +				for(j = 0; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++)
 87.1082 +				{
 87.1083 +					R_ColorShiftLightingBytes(&buf_p[j * 3], &data[j * 4]);
 87.1084 +					data[j * 4 + 3] = 255;
 87.1085 +				}
 87.1086 +				image = R_CreateImage(va("_lightmap%d", i), data, LIGHTMAP_SIZE, LIGHTMAP_SIZE, IF_LIGHTMAP | IF_NOCOMPRESSION, FT_DEFAULT, WT_CLAMP);
 87.1087 +				Com_AddToGrowList(&tr.lightmaps, image);
 87.1088 +			}
 87.1089 +		}
 87.1090 +	}
 87.1091 +#else defined(COMPAT_Q3A)
 87.1092 +	else
 87.1093 +	{
 87.1094 +		int             i;
 87.1095 +		//int       BIGSIZE=2048;
 87.1096 +		//int       BIGNUM=16;
 87.1097 +
 87.1098 +		byte           *fatbuffer;
 87.1099 +		int             xoff, yoff, x, y;
 87.1100 +		float           scale = 0.9f;
 87.1101 +
 87.1102 +		tr.fatLightmapSize = 2048;
 87.1103 +		tr.fatLightmapStep = 16;
 87.1104 +
 87.1105 +		len = l->filelen;
 87.1106 +		if(!len)
 87.1107 +		{
 87.1108 +			return;
 87.1109 +		}
 87.1110 +		buf = fileBase + l->fileofs;
 87.1111 +
 87.1112 +		// we are about to upload textures
 87.1113 +		R_SyncRenderThread();
 87.1114 +
 87.1115 +		// create all the lightmaps
 87.1116 +		numLightmaps = len / (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3);
 87.1117 +		if(numLightmaps == 1)
 87.1118 +		{
 87.1119 +			//FIXME: HACK: maps with only one lightmap turn up fullbright for some reason.
 87.1120 +			//this avoids this, but isn't the correct solution.
 87.1121 +			numLightmaps++;
 87.1122 +		}
 87.1123 +		else if(numLightmaps >= MAX_LIGHTMAPS)
 87.1124 +		{
 87.1125 +			// 20051020 misantropia
 87.1126 +			ri.Printf(PRINT_WARNING, "WARNING: number of lightmaps > MAX_LIGHTMAPS\n");
 87.1127 +			numLightmaps = MAX_LIGHTMAPS;
 87.1128 +		}
 87.1129 +
 87.1130 +		if(numLightmaps < 65)
 87.1131 +		{
 87.1132 +			// optimize: use a 1024 if we can get away with it
 87.1133 +			tr.fatLightmapSize = 1024;
 87.1134 +			tr.fatLightmapStep = 8;
 87.1135 +
 87.1136 +		}
 87.1137 +		fatbuffer = ri.Hunk_AllocateTempMemory(sizeof(byte) * tr.fatLightmapSize * tr.fatLightmapSize * 4);
 87.1138 +
 87.1139 +		Com_Memset(fatbuffer, 128, tr.fatLightmapSize * tr.fatLightmapSize * 4);
 87.1140 +		for(i = 0; i < numLightmaps; i++)
 87.1141 +		{
 87.1142 +			// expand the 24 bit on-disk to 32 bit
 87.1143 +			buf_p = buf + i * LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3;
 87.1144 +
 87.1145 +			xoff = i % tr.fatLightmapStep;
 87.1146 +			yoff = i / tr.fatLightmapStep;
 87.1147 +
 87.1148 +			//if (tr.radbumping==qfalse)
 87.1149 +			if(1)
 87.1150 +			{
 87.1151 +				for(y = 0; y < LIGHTMAP_SIZE; y++)
 87.1152 +				{
 87.1153 +					for(x = 0; x < LIGHTMAP_SIZE; x++)
 87.1154 +					{
 87.1155 +						int             index =
 87.1156 +							(x + (y * tr.fatLightmapSize)) + ((xoff * LIGHTMAP_SIZE) + (yoff * tr.fatLightmapSize * LIGHTMAP_SIZE));
 87.1157 +						fatbuffer[(index * 4) + 0] = buf_p[((x + (y * LIGHTMAP_SIZE)) * 3) + 0];
 87.1158 +						fatbuffer[(index * 4) + 1] = buf_p[((x + (y * LIGHTMAP_SIZE)) * 3) + 1];
 87.1159 +						fatbuffer[(index * 4) + 2] = buf_p[((x + (y * LIGHTMAP_SIZE)) * 3) + 2];
 87.1160 +						fatbuffer[(index * 4) + 3] = 255;
 87.1161 +
 87.1162 +						R_ColorShiftLightingBytes(&fatbuffer[(index * 4) + 0], &fatbuffer[(index * 4) + 0]);
 87.1163 +					}
 87.1164 +				}
 87.1165 +			}
 87.1166 +			/*else
 87.1167 +			   {
 87.1168 +			   //We need to darken the lightmaps a little bit when mixing radbump and fallback path rendering
 87.1169 +			   //because radbump will be darker due to the error introduced by using 3 basis vector probes for lighting instead of surf normal.
 87.1170 +			   for ( y = 0 ; y < LIGHTMAP_SIZE ; y++ )
 87.1171 +			   {
 87.1172 +			   for ( x = 0 ; x < LIGHTMAP_SIZE ; x++ )
 87.1173 +			   {
 87.1174 +			   int index = (x+(y*tr.fatLightmapSize))+((xoff*LIGHTMAP_SIZE)+(yoff*tr.fatLightmapSize*LIGHTMAP_SIZE));
 87.1175 +			   fatbuffer[(index*4)+0 ]=(byte)(((float)buf_p[((x+(y*LIGHTMAP_SIZE))*3)+0])*scale);
 87.1176 +			   fatbuffer[(index*4)+1 ]=(byte)(((float)buf_p[((x+(y*LIGHTMAP_SIZE))*3)+1])*scale);
 87.1177 +			   fatbuffer[(index*4)+2 ]=(byte)(((float)buf_p[((x+(y*LIGHTMAP_SIZE))*3)+2])*scale);
 87.1178 +			   fatbuffer[(index*4)+3 ]=255;
 87.1179 +			   }
 87.1180 +			   }
 87.1181 +
 87.1182 +			   } */
 87.1183 +
 87.1184 +
 87.1185 +		}
 87.1186 +		//memset(fatbuffer,128,tr.fatLightmapSize*tr.fatLightmapSize*4);
 87.1187 +
 87.1188 +		tr.fatLightmap = R_CreateImage(va("_fatlightmap%d", 0), fatbuffer, tr.fatLightmapSize, tr.fatLightmapSize, IF_LIGHTMAP | IF_NOCOMPRESSION, FT_DEFAULT, WT_CLAMP);
 87.1189 +		Com_AddToGrowList(&tr.lightmaps, tr.fatLightmap);
 87.1190 +
 87.1191 +		ri.Hunk_FreeTempMemory(fatbuffer);
 87.1192 +	}
 87.1193 +#endif
 87.1194  }
 87.1195  
 87.1196 +static float FatPackU(float input, int lightmapnum)
 87.1197 +{
 87.1198 +	int             x = lightmapnum % tr.fatLightmapStep;
 87.1199 +
 87.1200 +	return (input / ((float)tr.fatLightmapStep)) + ((1.0 / ((float)tr.fatLightmapStep)) * (float)x);
 87.1201 +
 87.1202 +}
 87.1203 +
 87.1204 +static float FatPackV(float input, int lightmapnum)
 87.1205 +{
 87.1206 +	int             y = lightmapnum / ((float)tr.fatLightmapStep);
 87.1207 +
 87.1208 +	return (input / ((float)tr.fatLightmapStep)) + ((1.0 / ((float)tr.fatLightmapStep)) * (float)y);
 87.1209 +}
 87.1210  
 87.1211  /*
 87.1212  =================
 87.1213 @@ -223,42 +1081,49 @@
 87.1214  space in big maps...
 87.1215  =================
 87.1216  */
 87.1217 -void		RE_SetWorldVisData( const byte *vis ) {
 87.1218 +void RE_SetWorldVisData(const byte * vis)
 87.1219 +{
 87.1220  	tr.externalVisData = vis;
 87.1221  }
 87.1222  
 87.1223 -
 87.1224  /*
 87.1225  =================
 87.1226  R_LoadVisibility
 87.1227  =================
 87.1228  */
 87.1229 -static	void R_LoadVisibility( lump_t *l ) {
 87.1230 -	int		len;
 87.1231 -	byte	*buf;
 87.1232 -
 87.1233 -	len = ( s_worldData.numClusters + 63 ) & ~63;
 87.1234 -	s_worldData.novis = ri.Hunk_Alloc( len, h_low );
 87.1235 -	Com_Memset( s_worldData.novis, 0xff, len );
 87.1236 -
 87.1237 -    len = l->filelen;
 87.1238 -	if ( !len ) {
 87.1239 +static void R_LoadVisibility(lump_t * l)
 87.1240 +{
 87.1241 +	int             len;
 87.1242 +	byte           *buf;
 87.1243 +
 87.1244 +	ri.Printf(PRINT_ALL, "...loading visibility\n");
 87.1245 +
 87.1246 +	len = (s_worldData.numClusters + 63) & ~63;
 87.1247 +	s_worldData.novis = ri.Hunk_Alloc(len, h_low);
 87.1248 +	Com_Memset(s_worldData.novis, 0xff, len);
 87.1249 +
 87.1250 +	len = l->filelen;
 87.1251 +	if(!len)
 87.1252 +	{
 87.1253  		return;
 87.1254  	}
 87.1255  	buf = fileBase + l->fileofs;
 87.1256  
 87.1257 -	s_worldData.numClusters = LittleLong( ((int *)buf)[0] );
 87.1258 -	s_worldData.clusterBytes = LittleLong( ((int *)buf)[1] );
 87.1259 +	s_worldData.numClusters = LittleLong(((int *)buf)[0]);
 87.1260 +	s_worldData.clusterBytes = LittleLong(((int *)buf)[1]);
 87.1261  
 87.1262  	// CM_Load should have given us the vis data to share, so
 87.1263  	// we don't need to allocate another copy
 87.1264 -	if ( tr.externalVisData ) {
 87.1265 +	if(tr.externalVisData)
 87.1266 +	{
 87.1267  		s_worldData.vis = tr.externalVisData;
 87.1268 -	} else {
 87.1269 -		byte	*dest;
 87.1270 -
 87.1271 -		dest = ri.Hunk_Alloc( len - 8, h_low );
 87.1272 -		Com_Memcpy( dest, buf + 8, len - 8 );
 87.1273 +	}
 87.1274 +	else
 87.1275 +	{
 87.1276 +		byte           *dest;
 87.1277 +
 87.1278 +		dest = ri.Hunk_Alloc(len - 8, h_low);
 87.1279 +		Com_Memcpy(dest, buf + 8, len - 8);
 87.1280  		s_worldData.vis = dest;
 87.1281  	}
 87.1282  }
 87.1283 @@ -271,31 +1136,30 @@
 87.1284  ShaderForShaderNum
 87.1285  ===============
 87.1286  */
 87.1287 -static shader_t *ShaderForShaderNum( int shaderNum, int lightmapNum ) {
 87.1288 -	shader_t	*shader;
 87.1289 -	dshader_t	*dsh;
 87.1290 -
 87.1291 -	shaderNum = LittleLong( shaderNum );
 87.1292 -	if ( shaderNum < 0 || shaderNum >= s_worldData.numShaders ) {
 87.1293 -		ri.Error( ERR_DROP, "ShaderForShaderNum: bad num %i", shaderNum );
 87.1294 -	}
 87.1295 -	dsh = &s_worldData.shaders[ shaderNum ];
 87.1296 -
 87.1297 -	if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) {
 87.1298 -		lightmapNum = LIGHTMAP_BY_VERTEX;
 87.1299 -	}
 87.1300 -
 87.1301 -	if ( r_fullbright->integer ) {
 87.1302 -		lightmapNum = LIGHTMAP_WHITEIMAGE;
 87.1303 -	}
 87.1304 -
 87.1305 -	shader = R_FindShader( dsh->shader, lightmapNum, qtrue );
 87.1306 +static shader_t *ShaderForShaderNum(int shaderNum)
 87.1307 +{
 87.1308 +	shader_t       *shader;
 87.1309 +	dshader_t      *dsh;
 87.1310 +
 87.1311 +	shaderNum = LittleLong(shaderNum);
 87.1312 +	if(shaderNum < 0 || shaderNum >= s_worldData.numShaders)
 87.1313 +	{
 87.1314 +		ri.Error(ERR_DROP, "ShaderForShaderNum: bad num %i", shaderNum);
 87.1315 +	}
 87.1316 +	dsh = &s_worldData.shaders[shaderNum];
 87.1317 +
 87.1318 +//  ri.Printf(PRINT_ALL, "ShaderForShaderNum: '%s'\n", dsh->shader);
 87.1319 +
 87.1320 +	shader = R_FindShader(dsh->shader, SHADER_3D_STATIC, qtrue);
 87.1321  
 87.1322  	// if the shader had errors, just use default shader
 87.1323 -	if ( shader->defaultShader ) {
 87.1324 +	if(shader->defaultShader)
 87.1325 +	{
 87.1326 +//      ri.Printf(PRINT_ALL, "failed\n");
 87.1327  		return tr.defaultShader;
 87.1328  	}
 87.1329  
 87.1330 +//  ri.Printf(PRINT_ALL, "success\n");
 87.1331  	return shader;
 87.1332  }
 87.1333  
 87.1334 @@ -304,70 +1168,191 @@
 87.1335  ParseFace
 87.1336  ===============
 87.1337  */
 87.1338 -static void ParseFace( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int *indexes  ) {
 87.1339 -	int			i, j;
 87.1340 -	srfSurfaceFace_t	*cv;
 87.1341 -	int			numPoints, numIndexes;
 87.1342 -	int			lightmapNum;
 87.1343 -	int			sfaceSize, ofsIndexes;
 87.1344 -
 87.1345 -	lightmapNum = LittleLong( ds->lightmapNum );
 87.1346 -
 87.1347 -	// get fog volume
 87.1348 -	surf->fogIndex = LittleLong( ds->fogNum ) + 1;
 87.1349 +static void ParseFace(dsurface_t * ds, drawVert_t * verts, bspSurface_t * surf, int *indexes)
 87.1350 +{
 87.1351 +	int             i, j;
 87.1352 +	srfSurfaceFace_t *cv;
 87.1353 +	srfTriangle_t  *tri;
 87.1354 +	int             numVerts, numTriangles;
 87.1355 +	int             realLightmapNum;
 87.1356 +
 87.1357 +	// get lightmap
 87.1358 +	realLightmapNum = LittleLong(ds->lightmapNum);
 87.1359 +	if(r_vertexLighting->integer)
 87.1360 +	{
 87.1361 +		surf->lightmapNum = -1;
 87.1362 +	}
 87.1363 +	else
 87.1364 +	{
 87.1365 +#if defined(COMPAT_Q3A)
 87.1366 +		surf->lightmapNum = 0;
 87.1367 +#else
 87.1368 +		surf->lightmapNum = realLightmapNum;
 87.1369 +#endif
 87.1370 +	}
 87.1371  
 87.1372  	// get shader value
 87.1373 -	surf->shader = ShaderForShaderNum( ds->shaderNum, lightmapNum );
 87.1374 -	if ( r_singleShader->integer && !surf->shader->isSky ) {
 87.1375 +	surf->shader = ShaderForShaderNum(ds->shaderNum);
 87.1376 +	if(r_singleShader->integer && !surf->shader->isSky)
 87.1377 +	{
 87.1378  		surf->shader = tr.defaultShader;
 87.1379  	}
 87.1380  
 87.1381 -	numPoints = LittleLong( ds->numVerts );
 87.1382 -	if (numPoints > MAX_FACE_POINTS) {
 87.1383 -		ri.Printf( PRINT_WARNING, "WARNING: MAX_FACE_POINTS exceeded: %i\n", numPoints);
 87.1384 -    numPoints = MAX_FACE_POINTS;
 87.1385 -    surf->shader = tr.defaultShader;
 87.1386 -	}
 87.1387 -
 87.1388 -	numIndexes = LittleLong( ds->numIndexes );
 87.1389 -
 87.1390 -	// create the srfSurfaceFace_t
 87.1391 -	sfaceSize = ( size_t ) &((srfSurfaceFace_t *)0)->points[numPoints];
 87.1392 -	ofsIndexes = sfaceSize;
 87.1393 -	sfaceSize += sizeof( int ) * numIndexes;
 87.1394 -
 87.1395 -	cv = ri.Hunk_Alloc( sfaceSize, h_low );
 87.1396 +	numVerts = LittleLong(ds->numVerts);
 87.1397 +	/*
 87.1398 +	   if(numVerts > MAX_FACE_POINTS)
 87.1399 +	   {
 87.1400 +	   ri.Printf(PRINT_WARNING, "WARNING: MAX_FACE_POINTS exceeded: %i\n", numVerts);
 87.1401 +	   numVerts = MAX_FACE_POINTS;
 87.1402 +	   surf->shader = tr.defaultShader;
 87.1403 +	   }
 87.1404 +	 */
 87.1405 +	numTriangles = LittleLong(ds->numIndexes) / 3;
 87.1406 +
 87.1407 +	cv = ri.Hunk_Alloc(sizeof(*cv), h_low);
 87.1408  	cv->surfaceType = SF_FACE;
 87.1409 -	cv->numPoints = numPoints;
 87.1410 -	cv->numIndices = numIndexes;
 87.1411 -	cv->ofsIndices = ofsIndexes;
 87.1412 -
 87.1413 -	verts += LittleLong( ds->firstVert );
 87.1414 -	for ( i = 0 ; i < numPoints ; i++ ) {
 87.1415 -		for ( j = 0 ; j < 3 ; j++ ) {
 87.1416 -			cv->points[i][j] = LittleFloat( verts[i].xyz[j] );
 87.1417 -		}
 87.1418 -		for ( j = 0 ; j < 2 ; j++ ) {
 87.1419 -			cv->points[i][3+j] = LittleFloat( verts[i].st[j] );
 87.1420 -			cv->points[i][5+j] = LittleFloat( verts[i].lightmap[j] );
 87.1421 -		}
 87.1422 -		R_ColorShiftLightingBytes( verts[i].color, (byte *)&cv->points[i][7] );
 87.1423 -	}
 87.1424 -
 87.1425 -	indexes += LittleLong( ds->firstIndex );
 87.1426 -	for ( i = 0 ; i < numIndexes ; i++ ) {
 87.1427 -		((int *)((byte *)cv + cv->ofsIndices ))[i] = LittleLong( indexes[ i ] );
 87.1428 -	}
 87.1429 +
 87.1430 +	cv->numTriangles = numTriangles;
 87.1431 +	cv->triangles = ri.Hunk_Alloc(numTriangles * sizeof(cv->triangles[0]), h_low);
 87.1432 +
 87.1433 +	cv->numVerts = numVerts;
 87.1434 +	cv->verts = ri.Hunk_Alloc(numVerts * sizeof(cv->verts[0]), h_low);
 87.1435 +
 87.1436 +	surf->data = (surfaceType_t *) cv;
 87.1437 +
 87.1438 +	// copy vertexes
 87.1439 +	ClearBounds(cv->bounds[0], cv->bounds[1]);
 87.1440 +	verts += LittleLong(ds->firstVert);
 87.1441 +	for(i = 0; i < numVerts; i++)
 87.1442 +	{
 87.1443 +		for(j = 0; j < 3; j++)
 87.1444 +		{
 87.1445 +			cv->verts[i].xyz[j] = LittleFloat(verts[i].xyz[j]);
 87.1446 +			cv->verts[i].normal[j] = LittleFloat(verts[i].normal[j]);
 87.1447 +		}
 87.1448 +		AddPointToBounds(cv->verts[i].xyz, cv->bounds[0], cv->bounds[1]);
 87.1449 +		for(j = 0; j < 2; j++)
 87.1450 +		{
 87.1451 +			cv->verts[i].st[j] = LittleFloat(verts[i].st[j]);
 87.1452 +			cv->verts[i].lightmap[j] = LittleFloat(verts[i].lightmap[j]);
 87.1453 +		}
 87.1454 +
 87.1455 +#if defined(COMPAT_Q3A)
 87.1456 +		cv->verts[i].lightmap[0] = FatPackU(LittleFloat(verts[i].lightmap[0]), realLightmapNum);
 87.1457 +		cv->verts[i].lightmap[1] = FatPackV(LittleFloat(verts[i].lightmap[1]), realLightmapNum);
 87.1458 +
 87.1459 +		for(j = 0; j < 4; j++)
 87.1460 +		{
 87.1461 +			cv->verts[i].lightColor[j] = verts[i].color[j] * (1.0f / 255.0f);
 87.1462 +		}
 87.1463 +		R_ColorShiftLightingFloats(cv->verts[i].lightColor, cv->verts[i].lightColor);
 87.1464 +#else
 87.1465 +		for(j = 0; j < 4; j++)
 87.1466 +		{
 87.1467 +			cv->verts[i].paintColor[j] = Q_clamp(LittleFloat(verts[i].paintColor[j]), 0.0f, 1.0f);
 87.1468 +			cv->verts[i].lightColor[j] = LittleFloat(verts[i].lightColor[j]);
 87.1469 +		}
 87.1470 +
 87.1471 +		for(j = 0; j < 3; j++)
 87.1472 +		{
 87.1473 +			cv->verts[i].lightDirection[j] = LittleFloat(verts[i].lightDirection[j]);
 87.1474 +		}
 87.1475 +		//VectorNormalize(cv->verts[i].lightDirection);
 87.1476 +
 87.1477 +		R_HDRTonemapLightingColors(cv->verts[i].lightColor, cv->verts[i].lightColor, qtrue);
 87.1478 +#endif
 87.1479 +	}
 87.1480 +
 87.1481 +	// copy triangles
 87.1482 +	indexes += LittleLong(ds->firstIndex);
 87.1483 +	for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
 87.1484 +	{
 87.1485 +		for(j = 0; j < 3; j++)
 87.1486 +		{
 87.1487 +			tri->indexes[j] = LittleLong(indexes[i * 3 + j]);
 87.1488 +
 87.1489 +			if(tri->indexes[j] < 0 || tri->indexes[j] >= numVerts)
 87.1490 +			{
 87.1491 +				ri.Error(ERR_DROP, "Bad index in face surface");
 87.1492 +			}
 87.1493 +		}
 87.1494 +	}
 87.1495 +
 87.1496 +	R_CalcSurfaceTriangleNeighbors(numTriangles, cv->triangles);
 87.1497 +	R_CalcSurfaceTrianglePlanes(numTriangles, cv->triangles, cv->verts);
 87.1498  
 87.1499  	// take the plane information from the lightmap vector
 87.1500 -	for ( i = 0 ; i < 3 ; i++ ) {
 87.1501 -		cv->plane.normal[i] = LittleFloat( ds->lightmapVecs[2][i] );
 87.1502 -	}
 87.1503 -	cv->plane.dist = DotProduct( cv->points[0], cv->plane.normal );
 87.1504 -	SetPlaneSignbits( &cv->plane );
 87.1505 -	cv->plane.type = PlaneTypeForNormal( cv->plane.normal );
 87.1506 -
 87.1507 -	surf->data = (surfaceType_t *)cv;
 87.1508 +	for(i = 0; i < 3; i++)
 87.1509 +	{
 87.1510 +		cv->plane.normal[i] = LittleFloat(ds->lightmapVecs[2][i]);
 87.1511 +	}
 87.1512 +	cv->plane.dist = DotProduct(cv->verts[0].xyz, cv->plane.normal);
 87.1513 +	SetPlaneSignbits(&cv->plane);
 87.1514 +	cv->plane.type = PlaneTypeForNormal(cv->plane.normal);
 87.1515 +
 87.1516 +	surf->data = (surfaceType_t *) cv;
 87.1517 +
 87.1518 +	// Tr3B - calc tangent spaces
 87.1519 +#if 0
 87.1520 +	{
 87.1521 +		float          *v;
 87.1522 +		const float    *v0, *v1, *v2;
 87.1523 +		const float    *t0, *t1, *t2;
 87.1524 +		vec3_t          tangent;
 87.1525 +		vec3_t          binormal;
 87.1526 +		vec3_t          normal;
 87.1527 +
 87.1528 +		for(i = 0; i < numVerts; i++)
 87.1529 +		{
 87.1530 +			VectorClear(cv->verts[i].tangent);
 87.1531 +			VectorClear(cv->verts[i].binormal);
 87.1532 +			VectorClear(cv->verts[i].normal);
 87.1533 +		}
 87.1534 +
 87.1535 +		for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
 87.1536 +		{
 87.1537 +			v0 = cv->verts[tri->indexes[0]].xyz;
 87.1538 +			v1 = cv->verts[tri->indexes[1]].xyz;
 87.1539 +			v2 = cv->verts[tri->indexes[2]].xyz;
 87.1540 +
 87.1541 +			t0 = cv->verts[tri->indexes[0]].st;
 87.1542 +			t1 = cv->verts[tri->indexes[1]].st;
 87.1543 +			t2 = cv->verts[tri->indexes[2]].st;
 87.1544 +
 87.1545 +			R_CalcTangentSpace(tangent, binormal, normal, v0, v1, v2, t0, t1, t2);
 87.1546 +
 87.1547 +			for(j = 0; j < 3; j++)
 87.1548 +			{
 87.1549 +				v = cv->verts[tri->indexes[j]].tangent;
 87.1550 +				VectorAdd(v, tangent, v);
 87.1551 +				v = cv->verts[tri->indexes[j]].binormal;
 87.1552 +				VectorAdd(v, binormal, v);
 87.1553 +				v = cv->verts[tri->indexes[j]].normal;
 87.1554 +				VectorAdd(v, normal, v);
 87.1555 +			}
 87.1556 +		}
 87.1557 +
 87.1558 +		for(i = 0; i < numVerts; i++)
 87.1559 +		{
 87.1560 +			VectorNormalize(cv->verts[i].tangent);
 87.1561 +			VectorNormalize(cv->verts[i].binormal);
 87.1562 +			VectorNormalize(cv->verts[i].normal);
 87.1563 +		}
 87.1564 +	}
 87.1565 +#else
 87.1566 +	{
 87.1567 +		srfVert_t      *dv[3];
 87.1568 +
 87.1569 +		for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
 87.1570 +		{
 87.1571 +			dv[0] = &cv->verts[tri->indexes[0]];
 87.1572 +			dv[1] = &cv->verts[tri->indexes[1]];
 87.1573 +			dv[2] = &cv->verts[tri->indexes[2]];
 87.1574 +
 87.1575 +			R_CalcTangentVectors(dv);
 87.1576 +		}
 87.1577 +	}
 87.1578 +#endif
 87.1579  }
 87.1580  
 87.1581  
 87.1582 @@ -376,125 +1361,304 @@
 87.1583  ParseMesh
 87.1584  ===============
 87.1585  */
 87.1586 -static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, msurface_t *surf ) {
 87.1587 -	srfGridMesh_t	*grid;
 87.1588 -	int				i, j;
 87.1589 -	int				width, height, numPoints;
 87.1590 -	drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE];
 87.1591 -	int				lightmapNum;
 87.1592 -	vec3_t			bounds[2];
 87.1593 -	vec3_t			tmpVec;
 87.1594 -	static surfaceType_t	skipData = SF_SKIP;
 87.1595 -
 87.1596 -	lightmapNum = LittleLong( ds->lightmapNum );
 87.1597 -
 87.1598 -	// get fog volume
 87.1599 -	surf->fogIndex = LittleLong( ds->fogNum ) + 1;
 87.1600 +static void ParseMesh(dsurface_t * ds, drawVert_t * verts, bspSurface_t * surf)
 87.1601 +{
 87.1602 +	srfGridMesh_t  *grid;
 87.1603 +	int             i, j;
 87.1604 +	int             width, height, numPoints;
 87.1605 +	srfVert_t       points[MAX_PATCH_SIZE * MAX_PATCH_SIZE];
 87.1606 +	vec3_t          bounds[2];
 87.1607 +	vec3_t          tmpVec;
 87.1608 +	static surfaceType_t skipData = SF_SKIP;int             realLightmapNum;
 87.1609 +
 87.1610 +	// get lightmap
 87.1611 +	realLightmapNum = LittleLong(ds->lightmapNum);
 87.1612 +	if(r_vertexLighting->integer)
 87.1613 +	{
 87.1614 +		surf->lightmapNum = -1;
 87.1615 +	}
 87.1616 +	else
 87.1617 +	{
 87.1618 +#if defined(COMPAT_Q3A)
 87.1619 +		surf->lightmapNum = 0;
 87.1620 +#else
 87.1621 +		surf->lightmapNum = realLightmapNum;
 87.1622 +#endif
 87.1623 +	}
 87.1624  
 87.1625  	// get shader value
 87.1626 -	surf->shader = ShaderForShaderNum( ds->shaderNum, lightmapNum );
 87.1627 -	if ( r_singleShader->integer && !surf->shader->isSky ) {
 87.1628 +	surf->shader = ShaderForShaderNum(ds->shaderNum);
 87.1629 +	if(r_singleShader->integer && !surf->shader->isSky)
 87.1630 +	{
 87.1631  		surf->shader = tr.defaultShader;
 87.1632  	}
 87.1633  
 87.1634  	// we may have a nodraw surface, because they might still need to
 87.1635  	// be around for movement clipping
 87.1636 -	if ( s_worldData.shaders[ LittleLong( ds->shaderNum ) ].surfaceFlags & SURF_NODRAW ) {
 87.1637 +	if(s_worldData.shaders[LittleLong(ds->shaderNum)].surfaceFlags & (SURF_NODRAW | SURF_COLLISION))
 87.1638 +	{
 87.1639  		surf->data = &skipData;
 87.1640  		return;
 87.1641  	}
 87.1642  
 87.1643 -	width = LittleLong( ds->patchWidth );
 87.1644 -	height = LittleLong( ds->patchHeight );
 87.1645 -
 87.1646 -	verts += LittleLong( ds->firstVert );
 87.1647 +	width = LittleLong(ds->patchWidth);
 87.1648 +	height = LittleLong(ds->patchHeight);
 87.1649 +
 87.1650 +	if(width < 0 || width > MAX_PATCH_SIZE || height < 0 || height > MAX_PATCH_SIZE)
 87.1651 +		ri.Error(ERR_DROP, "ParseMesh: bad size");
 87.1652 +
 87.1653 +	verts += LittleLong(ds->firstVert);
 87.1654  	numPoints = width * height;
 87.1655 -	for ( i = 0 ; i < numPoints ; i++ ) {
 87.1656 -		for ( j = 0 ; j < 3 ; j++ ) {
 87.1657 -			points[i].xyz[j] = LittleFloat( verts[i].xyz[j] );
 87.1658 -			points[i].normal[j] = LittleFloat( verts[i].normal[j] );
 87.1659 -		}
 87.1660 -		for ( j = 0 ; j < 2 ; j++ ) {
 87.1661 -			points[i].st[j] = LittleFloat( verts[i].st[j] );
 87.1662 -			points[i].lightmap[j] = LittleFloat( verts[i].lightmap[j] );
 87.1663 -		}
 87.1664 -		R_ColorShiftLightingBytes( verts[i].color, points[i].color );
 87.1665 +	for(i = 0; i < numPoints; i++)
 87.1666 +	{
 87.1667 +		for(j = 0; j < 3; j++)
 87.1668 +		{
 87.1669 +			points[i].xyz[j] = LittleFloat(verts[i].xyz[j]);
 87.1670 +			points[i].normal[j] = LittleFloat(verts[i].normal[j]);
 87.1671 +		}
 87.1672 +
 87.1673 +		for(j = 0; j < 2; j++)
 87.1674 +		{
 87.1675 +			points[i].st[j] = LittleFloat(verts[i].st[j]);
 87.1676 +			points[i].lightmap[j] = LittleFloat(verts[i].lightmap[j]);
 87.1677 +		}
 87.1678 +
 87.1679 +#if defined(COMPAT_Q3A)
 87.1680 +		points[i].lightmap[0] = FatPackU(LittleFloat(verts[i].lightmap[0]), realLightmapNum);
 87.1681 +		points[i].lightmap[1] = FatPackV(LittleFloat(verts[i].lightmap[1]), realLightmapNum);
 87.1682 +
 87.1683 +		for(j = 0; j < 4; j++)
 87.1684 +		{
 87.1685 +			points[i].lightColor[j] = verts[i].color[j] * (1.0f / 255.0f);
 87.1686 +		}
 87.1687 +		R_ColorShiftLightingFloats(points[i].lightColor, points[i].lightColor);
 87.1688 +#else
 87.1689 +		for(j = 0; j < 4; j++)
 87.1690 +		{
 87.1691 +			points[i].paintColor[j] = Q_clamp(LittleFloat(verts[i].paintColor[j]), 0.0f, 1.0f);
 87.1692 +			points[i].lightColor[j] = LittleFloat(verts[i].lightColor[j]);
 87.1693 +		}
 87.1694 +
 87.1695 +		for(j = 0; j < 3; j++)
 87.1696 +		{
 87.1697 +			points[i].lightDirection[j] = LittleFloat(verts[i].lightDirection[j]);
 87.1698 +		}
 87.1699 +		//VectorNormalize(points[i].lightDirection);
 87.1700 +
 87.1701 +		R_HDRTonemapLightingColors(points[i].lightColor, points[i].lightColor, qtrue);
 87.1702 +#endif
 87.1703  	}
 87.1704  
 87.1705  	// pre-tesseleate
 87.1706 -	grid = R_SubdividePatchToGrid( width, height, points );
 87.1707 -	surf->data = (surfaceType_t *)grid;
 87.1708 +	grid = R_SubdividePatchToGrid(width, height, points);
 87.1709 +	surf->data = (surfaceType_t *) grid;
 87.1710  
 87.1711  	// copy the level of detail origin, which is the center
 87.1712  	// of the group of all curves that must subdivide the same
 87.1713  	// to avoid cracking
 87.1714 -	for ( i = 0 ; i < 3 ; i++ ) {
 87.1715 -		bounds[0][i] = LittleFloat( ds->lightmapVecs[0][i] );
 87.1716 -		bounds[1][i] = LittleFloat( ds->lightmapVecs[1][i] );
 87.1717 -	}
 87.1718 -	VectorAdd( bounds[0], bounds[1], bounds[1] );
 87.1719 -	VectorScale( bounds[1], 0.5f, grid->lodOrigin );
 87.1720 -	VectorSubtract( bounds[0], grid->lodOrigin, tmpVec );
 87.1721 -	grid->lodRadius = VectorLength( tmpVec );
 87.1722 +	for(i = 0; i < 3; i++)
 87.1723 +	{
 87.1724 +		bounds[0][i] = LittleFloat(ds->lightmapVecs[0][i]);
 87.1725 +		bounds[1][i] = LittleFloat(ds->lightmapVecs[1][i]);
 87.1726 +	}
 87.1727 +	VectorAdd(bounds[0], bounds[1], bounds[1]);
 87.1728 +	VectorScale(bounds[1], 0.5f, grid->lodOrigin);
 87.1729 +	VectorSubtract(bounds[0], grid->lodOrigin, tmpVec);
 87.1730 +	grid->lodRadius = VectorLength(tmpVec);
 87.1731  }
 87.1732  
 87.1733 +
 87.1734 +
 87.1735  /*
 87.1736  ===============
 87.1737  ParseTriSurf
 87.1738  ===============
 87.1739  */
 87.1740 -static void ParseTriSurf( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int *indexes ) {
 87.1741 -	srfTriangles_t	*tri;
 87.1742 -	int				i, j;
 87.1743 -	int				numVerts, numIndexes;
 87.1744 -
 87.1745 -	// get fog volume
 87.1746 -	surf->fogIndex = LittleLong( ds->fogNum ) + 1;
 87.1747 +static void ParseTriSurf(dsurface_t * ds, drawVert_t * verts, bspSurface_t * surf, int *indexes)
 87.1748 +{
 87.1749 +	srfTriangles_t *cv;
 87.1750 +	srfTriangle_t  *tri;
 87.1751 +	int             i, j;
 87.1752 +	int             numVerts, numTriangles;
 87.1753 +	static surfaceType_t skipData = SF_SKIP;
 87.1754 +
 87.1755 +	// get lightmap
 87.1756 +	surf->lightmapNum = -1;		// FIXME LittleLong(ds->lightmapNum);
 87.1757  
 87.1758  	// get shader
 87.1759 -	surf->shader = ShaderForShaderNum( ds->shaderNum, LIGHTMAP_BY_VERTEX );
 87.1760 -	if ( r_singleShader->integer && !surf->shader->isSky ) {
 87.1761 +	surf->shader = ShaderForShaderNum(ds->shaderNum);
 87.1762 +	if(r_singleShader->integer && !surf->shader->isSky)
 87.1763 +	{
 87.1764  		surf->shader = tr.defaultShader;
 87.1765  	}
 87.1766  
 87.1767 -	numVerts = LittleLong( ds->numVerts );
 87.1768 -	numIndexes = LittleLong( ds->numIndexes );
 87.1769 -
 87.1770 -	tri = ri.Hunk_Alloc( sizeof( *tri ) + numVerts * sizeof( tri->verts[0] ) 
 87.1771 -		+ numIndexes * sizeof( tri->indexes[0] ), h_low );
 87.1772 -	tri->surfaceType = SF_TRIANGLES;
 87.1773 -	tri->numVerts = numVerts;
 87.1774 -	tri->numIndexes = numIndexes;
 87.1775 -	tri->verts = (drawVert_t *)(tri + 1);
 87.1776 -	tri->indexes = (int *)(tri->verts + tri->numVerts );
 87.1777 -
 87.1778 -	surf->data = (surfaceType_t *)tri;
 87.1779 +	// we may have a nodraw surface, because they might still need to
 87.1780 +	// be around for movement clipping
 87.1781 +	if(s_worldData.shaders[LittleLong(ds->shaderNum)].surfaceFlags & (SURF_NODRAW | SURF_COLLISION))
 87.1782 +	{
 87.1783 +		surf->data = &skipData;
 87.1784 +		return;
 87.1785 +	}
 87.1786 +
 87.1787 +	numVerts = LittleLong(ds->numVerts);
 87.1788 +	numTriangles = LittleLong(ds->numIndexes) / 3;
 87.1789 +
 87.1790 +	cv = ri.Hunk_Alloc(sizeof(*cv), h_low);
 87.1791 +	cv->surfaceType = SF_TRIANGLES;
 87.1792 +
 87.1793 +	cv->numTriangles = numTriangles;
 87.1794 +	cv->triangles = ri.Hunk_Alloc(numTriangles * sizeof(cv->triangles[0]), h_low);
 87.1795 +
 87.1796 +	cv->numVerts = numVerts;
 87.1797 +	cv->verts = ri.Hunk_Alloc(numVerts * sizeof(cv->verts[0]), h_low);
 87.1798 +
 87.1799 +	surf->data = (surfaceType_t *) cv;
 87.1800  
 87.1801  	// copy vertexes
 87.1802 -	ClearBounds( tri->bounds[0], tri->bounds[1] );
 87.1803 -	verts += LittleLong( ds->firstVert );
 87.1804 -	for ( i = 0 ; i < numVerts ; i++ ) {
 87.1805 -		for ( j = 0 ; j < 3 ; j++ ) {
 87.1806 -			tri->verts[i].xyz[j] = LittleFloat( verts[i].xyz[j] );
 87.1807 -			tri->verts[i].normal[j] = LittleFloat( verts[i].normal[j] );
 87.1808 -		}
 87.1809 -		AddPointToBounds( tri->verts[i].xyz, tri->bounds[0], tri->bounds[1] );
 87.1810 -		for ( j = 0 ; j < 2 ; j++ ) {
 87.1811 -			tri->verts[i].st[j] = LittleFloat( verts[i].st[j] );
 87.1812 -			tri->verts[i].lightmap[j] = LittleFloat( verts[i].lightmap[j] );
 87.1813 -		}
 87.1814 -
 87.1815 -		R_ColorShiftLightingBytes( verts[i].color, tri->verts[i].color );
 87.1816 -	}
 87.1817 -
 87.1818 -	// copy indexes
 87.1819 -	indexes += LittleLong( ds->firstIndex );
 87.1820 -	for ( i = 0 ; i < numIndexes ; i++ ) {
 87.1821 -		tri->indexes[i] = LittleLong( indexes[i] );
 87.1822 -		if ( tri->indexes[i] < 0 || tri->indexes[i] >= numVerts ) {
 87.1823 -			ri.Error( ERR_DROP, "Bad index in triangle surface" );
 87.1824 -		}
 87.1825 -	}
 87.1826 +	verts += LittleLong(ds->firstVert);
 87.1827 +	for(i = 0; i < numVerts; i++)
 87.1828 +	{
 87.1829 +		for(j = 0; j < 3; j++)
 87.1830 +		{
 87.1831 +			cv->verts[i].xyz[j] = LittleFloat(verts[i].xyz[j]);
 87.1832 +			cv->verts[i].normal[j] = LittleFloat(verts[i].normal[j]);
 87.1833 +		}
 87.1834 +
 87.1835 +		for(j = 0; j < 2; j++)
 87.1836 +		{
 87.1837 +			cv->verts[i].st[j] = LittleFloat(verts[i].st[j]);
 87.1838 +			cv->verts[i].lightmap[j] = LittleFloat(verts[i].lightmap[j]);
 87.1839 +		}
 87.1840 +
 87.1841 +#if defined(COMPAT_Q3A)
 87.1842 +		for(j = 0; j < 4; j++)
 87.1843 +		{
 87.1844 +			cv->verts[i].lightColor[j] = verts[i].color[j] * (1.0f / 255.0f);
 87.1845 +		}
 87.1846 +		R_ColorShiftLightingFloats(cv->verts[i].lightColor, cv->verts[i].lightColor);
 87.1847 +#else
 87.1848 +		for(j = 0; j < 4; j++)
 87.1849 +		{
 87.1850 +			cv->verts[i].paintColor[j] = Q_clamp(LittleFloat(verts[i].paintColor[j]), 0.0f, 1.0f);
 87.1851 +			cv->verts[i].lightColor[j] = LittleFloat(verts[i].lightColor[j]);
 87.1852 +		}
 87.1853 +
 87.1854 +		for(j = 0; j < 3; j++)
 87.1855 +		{
 87.1856 +			cv->verts[i].lightDirection[j] = LittleFloat(verts[i].lightDirection[j]);
 87.1857 +		}
 87.1858 +		//VectorNormalize(cv->verts[i].lightDirection);
 87.1859 +
 87.1860 +		R_HDRTonemapLightingColors(cv->verts[i].lightColor, cv->verts[i].lightColor, qtrue);
 87.1861 +#endif
 87.1862 +	}
 87.1863 +
 87.1864 +	// copy triangles
 87.1865 +	indexes += LittleLong(ds->firstIndex);
 87.1866 +	for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
 87.1867 +	{
 87.1868 +		for(j = 0; j < 3; j++)
 87.1869 +		{
 87.1870 +			tri->indexes[j] = LittleLong(indexes[i * 3 + j]);
 87.1871 +
 87.1872 +			if(tri->indexes[j] < 0 || tri->indexes[j] >= numVerts)
 87.1873 +			{
 87.1874 +				ri.Error(ERR_DROP, "Bad index in face surface");
 87.1875 +			}
 87.1876 +		}
 87.1877 +	}
 87.1878 +
 87.1879 +	// calc bounding box
 87.1880 +	// HACK: don't loop only through the vertices because they can contain bad data with .lwo models ...
 87.1881 +	ClearBounds(cv->bounds[0], cv->bounds[1]);
 87.1882 +	for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
 87.1883 +	{
 87.1884 +		AddPointToBounds(cv->verts[tri->indexes[0]].xyz, cv->bounds[0], cv->bounds[1]);
 87.1885 +		AddPointToBounds(cv->verts[tri->indexes[1]].xyz, cv->bounds[0], cv->bounds[1]);
 87.1886 +		AddPointToBounds(cv->verts[tri->indexes[2]].xyz, cv->bounds[0], cv->bounds[1]);
 87.1887 +	}
 87.1888 +
 87.1889 +	R_CalcSurfaceTriangleNeighbors(numTriangles, cv->triangles);
 87.1890 +	R_CalcSurfaceTrianglePlanes(numTriangles, cv->triangles, cv->verts);
 87.1891 +
 87.1892 +	// Tr3B - calc tangent spaces
 87.1893 +#if 0
 87.1894 +	{
 87.1895 +		float          *v;
 87.1896 +		const float    *v0, *v1, *v2;
 87.1897 +		const float    *t0, *t1, *t2;
 87.1898 +		vec3_t          tangent;
 87.1899 +		vec3_t          binormal;
 87.1900 +		vec3_t          normal;
 87.1901 +
 87.1902 +		for(i = 0; i < numVerts; i++)
 87.1903 +		{
 87.1904 +			VectorClear(cv->verts[i].tangent);
 87.1905 +			VectorClear(cv->verts[i].binormal);
 87.1906 +			VectorClear(cv->verts[i].normal);
 87.1907 +		}
 87.1908 +
 87.1909 +		for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
 87.1910 +		{
 87.1911 +			v0 = cv->verts[tri->indexes[0]].xyz;
 87.1912 +			v1 = cv->verts[tri->indexes[1]].xyz;
 87.1913 +			v2 = cv->verts[tri->indexes[2]].xyz;
 87.1914 +
 87.1915 +			t0 = cv->verts[tri->indexes[0]].st;
 87.1916 +			t1 = cv->verts[tri->indexes[1]].st;
 87.1917 +			t2 = cv->verts[tri->indexes[2]].st;
 87.1918 +
 87.1919 +			R_CalcTangentSpace(tangent, binormal, normal, v0, v1, v2, t0, t1, t2);
 87.1920 +
 87.1921 +			for(j = 0; j < 3; j++)
 87.1922 +			{
 87.1923 +				v = cv->verts[tri->indexes[j]].tangent;
 87.1924 +				VectorAdd(v, tangent, v);
 87.1925 +				v = cv->verts[tri->indexes[j]].binormal;
 87.1926 +				VectorAdd(v, binormal, v);
 87.1927 +				v = cv->verts[tri->indexes[j]].normal;
 87.1928 +				VectorAdd(v, normal, v);
 87.1929 +			}
 87.1930 +		}
 87.1931 +
 87.1932 +		for(i = 0; i < numVerts; i++)
 87.1933 +		{
 87.1934 +			VectorNormalize(cv->verts[i].tangent);
 87.1935 +			VectorNormalize(cv->verts[i].binormal);
 87.1936 +			VectorNormalize(cv->verts[i].normal);
 87.1937 +		}
 87.1938 +
 87.1939 +		// do another extra smoothing for normals to avoid flat shading
 87.1940 +		for(i = 0; i < numVerts; i++)
 87.1941 +		{
 87.1942 +			for(j = 0; j < numVerts; j++)
 87.1943 +			{
 87.1944 +				if(i == j)
 87.1945 +					continue;
 87.1946 +
 87.1947 +				if(R_CompareVert(&cv->verts[i], &cv->verts[j], qfalse))
 87.1948 +				{
 87.1949 +					VectorAdd(cv->verts[i].normal, cv->verts[j].normal, cv->verts[i].normal);
 87.1950 +				}
 87.1951 +			}
 87.1952 +
 87.1953 +			VectorNormalize(cv->verts[i].normal);
 87.1954 +		}
 87.1955 +	}
 87.1956 +#else
 87.1957 +	{
 87.1958 +		srfVert_t      *dv[3];
 87.1959 +
 87.1960 +		for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
 87.1961 +		{
 87.1962 +			dv[0] = &cv->verts[tri->indexes[0]];
 87.1963 +			dv[1] = &cv->verts[tri->indexes[1]];
 87.1964 +			dv[2] = &cv->verts[tri->indexes[2]];
 87.1965 +
 87.1966 +			R_CalcTangentVectors(dv);
 87.1967 +		}
 87.1968 +	}
 87.1969 +#endif
 87.1970  }
 87.1971  
 87.1972  /*
 87.1973 @@ -502,28 +1666,31 @@
 87.1974  ParseFlare
 87.1975  ===============
 87.1976  */
 87.1977 -static void ParseFlare( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int *indexes ) {
 87.1978 -	srfFlare_t		*flare;
 87.1979 -	int				i;
 87.1980 -
 87.1981 -	// get fog volume
 87.1982 -	surf->fogIndex = LittleLong( ds->fogNum ) + 1;
 87.1983 +static void ParseFlare(dsurface_t * ds, drawVert_t * verts, bspSurface_t * surf, int *indexes)
 87.1984 +{
 87.1985 +	srfFlare_t     *flare;
 87.1986 +	int             i;
 87.1987 +
 87.1988 +	// set lightmap
 87.1989 +	surf->lightmapNum = -1;
 87.1990  
 87.1991  	// get shader
 87.1992 -	surf->shader = ShaderForShaderNum( ds->shaderNum, LIGHTMAP_BY_VERTEX );
 87.1993 -	if ( r_singleShader->integer && !surf->shader->isSky ) {
 87.1994 +	surf->shader = ShaderForShaderNum(ds->shaderNum);
 87.1995 +	if(r_singleShader->integer && !surf->shader->isSky)
 87.1996 +	{
 87.1997  		surf->shader = tr.defaultShader;
 87.1998  	}
 87.1999  
 87.2000 -	flare = ri.Hunk_Alloc( sizeof( *flare ), h_low );
 87.2001 +	flare = ri.Hunk_Alloc(sizeof(*flare), h_low);
 87.2002  	flare->surfaceType = SF_FLARE;
 87.2003  
 87.2004 -	surf->data = (surfaceType_t *)flare;
 87.2005 -
 87.2006 -	for ( i = 0 ; i < 3 ; i++ ) {
 87.2007 -		flare->origin[i] = LittleFloat( ds->lightmapOrigin[i] );
 87.2008 -		flare->color[i] = LittleFloat( ds->lightmapVecs[0][i] );
 87.2009 -		flare->normal[i] = LittleFloat( ds->lightmapVecs[2][i] );
 87.2010 +	surf->data = (surfaceType_t *) flare;
 87.2011 +
 87.2012 +	for(i = 0; i < 3; i++)
 87.2013 +	{
 87.2014 +		flare->origin[i] = LittleFloat(ds->lightmapOrigin[i]);
 87.2015 +		flare->color[i] = LittleFloat(ds->lightmapVecs[0][i]);
 87.2016 +		flare->normal[i] = LittleFloat(ds->lightmapVecs[2][i]);
 87.2017  	}
 87.2018  }
 87.2019  
 87.2020 @@ -535,14 +1702,20 @@
 87.2021  returns true if there are grid points merged on a width edge
 87.2022  =================
 87.2023  */
 87.2024 -int R_MergedWidthPoints(srfGridMesh_t *grid, int offset) {
 87.2025 -	int i, j;
 87.2026 -
 87.2027 -	for (i = 1; i < grid->width-1; i++) {
 87.2028 -		for (j = i + 1; j < grid->width-1; j++) {
 87.2029 -			if ( fabs(grid->verts[i + offset].xyz[0] - grid->verts[j + offset].xyz[0]) > .1) continue;
 87.2030 -			if ( fabs(grid->verts[i + offset].xyz[1] - grid->verts[j + offset].xyz[1]) > .1) continue;
 87.2031 -			if ( fabs(grid->verts[i + offset].xyz[2] - grid->verts[j + offset].xyz[2]) > .1) continue;
 87.2032 +int R_MergedWidthPoints(srfGridMesh_t * grid, int offset)
 87.2033 +{
 87.2034 +	int             i, j;
 87.2035 +
 87.2036 +	for(i = 1; i < grid->width - 1; i++)
 87.2037 +	{
 87.2038 +		for(j = i + 1; j < grid->width - 1; j++)
 87.2039 +		{
 87.2040 +			if(fabs(grid->verts[i + offset].xyz[0] - grid->verts[j + offset].xyz[0]) > .1)
 87.2041 +				continue;
 87.2042 +			if(fabs(grid->verts[i + offset].xyz[1] - grid->verts[j + offset].xyz[1]) > .1)
 87.2043 +				continue;
 87.2044 +			if(fabs(grid->verts[i + offset].xyz[2] - grid->verts[j + offset].xyz[2]) > .1)
 87.2045 +				continue;
 87.2046  			return qtrue;
 87.2047  		}
 87.2048  	}
 87.2049 @@ -556,14 +1729,20 @@
 87.2050  returns true if there are grid points merged on a height edge
 87.2051  =================
 87.2052  */
 87.2053 -int R_MergedHeightPoints(srfGridMesh_t *grid, int offset) {
 87.2054 -	int i, j;
 87.2055 -
 87.2056 -	for (i = 1; i < grid->height-1; i++) {
 87.2057 -		for (j = i + 1; j < grid->height-1; j++) {
 87.2058 -			if ( fabs(grid->verts[grid->width * i + offset].xyz[0] - grid->verts[grid->width * j + offset].xyz[0]) > .1) continue;
 87.2059 -			if ( fabs(grid->verts[grid->width * i + offset].xyz[1] - grid->verts[grid->width * j + offset].xyz[1]) > .1) continue;
 87.2060 -			if ( fabs(grid->verts[grid->width * i + offset].xyz[2] - grid->verts[grid->width * j + offset].xyz[2]) > .1) continue;
 87.2061 +int R_MergedHeightPoints(srfGridMesh_t * grid, int offset)
 87.2062 +{
 87.2063 +	int             i, j;
 87.2064 +
 87.2065 +	for(i = 1; i < grid->height - 1; i++)
 87.2066 +	{
 87.2067 +		for(j = i + 1; j < grid->height - 1; j++)
 87.2068 +		{
 87.2069 +			if(fabs(grid->verts[grid->width * i + offset].xyz[0] - grid->verts[grid->width * j + offset].xyz[0]) > .1)
 87.2070 +				continue;
 87.2071 +			if(fabs(grid->verts[grid->width * i + offset].xyz[1] - grid->verts[grid->width * j + offset].xyz[1]) > .1)
 87.2072 +				continue;
 87.2073 +			if(fabs(grid->verts[grid->width * i + offset].xyz[2] - grid->verts[grid->width * j + offset].xyz[2]) > .1)
 87.2074 +				continue;
 87.2075  			return qtrue;
 87.2076  		}
 87.2077  	}
 87.2078 @@ -579,56 +1758,85 @@
 87.2079  FIXME: write generalized version that also avoids cracks between a patch and one that meets half way?
 87.2080  =================
 87.2081  */
 87.2082 -void R_FixSharedVertexLodError_r( int start, srfGridMesh_t *grid1 ) {
 87.2083 -	int j, k, l, m, n, offset1, offset2, touch;
 87.2084 -	srfGridMesh_t *grid2;
 87.2085 -
 87.2086 -	for ( j = start; j < s_worldData.numsurfaces; j++ ) {
 87.2087 +void R_FixSharedVertexLodError_r(int start, srfGridMesh_t * grid1)
 87.2088 +{
 87.2089 +	int             j, k, l, m, n, offset1, offset2, touch;
 87.2090 +	srfGridMesh_t  *grid2;
 87.2091 +
 87.2092 +	for(j = start; j < s_worldData.numSurfaces; j++)
 87.2093 +	{
 87.2094  		//
 87.2095  		grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data;
 87.2096  		// if this surface is not a grid
 87.2097 -		if ( grid2->surfaceType != SF_GRID ) continue;
 87.2098 +		if(grid2->surfaceType != SF_GRID)
 87.2099 +			continue;
 87.2100  		// if the LOD errors are already fixed for this patch
 87.2101 -		if ( grid2->lodFixed == 2 ) continue;
 87.2102 +		if(grid2->lodFixed == 2)
 87.2103 +			continue;
 87.2104  		// grids in the same LOD group should have the exact same lod radius
 87.2105 -		if ( grid1->lodRadius != grid2->lodRadius ) continue;
 87.2106 +		if(grid1->lodRadius != grid2->lodRadius)
 87.2107 +			continue;
 87.2108  		// grids in the same LOD group should have the exact same lod origin
 87.2109 -		if ( grid1->lodOrigin[0] != grid2->lodOrigin[0] ) continue;
 87.2110 -		if ( grid1->lodOrigin[1] != grid2->lodOrigin[1] ) continue;
 87.2111 -		if ( grid1->lodOrigin[2] != grid2->lodOrigin[2] ) continue;
 87.2112 +		if(grid1->lodOrigin[0] != grid2->lodOrigin[0])
 87.2113 +			continue;
 87.2114 +		if(grid1->lodOrigin[1] != grid2->lodOrigin[1])
 87.2115 +			continue;
 87.2116 +		if(grid1->lodOrigin[2] != grid2->lodOrigin[2])
 87.2117 +			continue;
 87.2118  		//
 87.2119  		touch = qfalse;
 87.2120 -		for (n = 0; n < 2; n++) {
 87.2121 +		for(n = 0; n < 2; n++)
 87.2122 +		{
 87.2123  			//
 87.2124 -			if (n) offset1 = (grid1->height-1) * grid1->width;
 87.2125 -			else offset1 = 0;
 87.2126 -			if (R_MergedWidthPoints(grid1, offset1)) continue;
 87.2127 -			for (k = 1; k < grid1->width-1; k++) {
 87.2128 -				for (m = 0; m < 2; m++) {
 87.2129 -
 87.2130 -					if (m) offset2 = (grid2->height-1) * grid2->width;
 87.2131 -					else offset2 = 0;
 87.2132 -					if (R_MergedWidthPoints(grid2, offset2)) continue;
 87.2133 -					for ( l = 1; l < grid2->width-1; l++) {
 87.2134 -					//
 87.2135 -						if ( fabs(grid1->verts[k + offset1].xyz[0] - grid2->verts[l + offset2].xyz[0]) > .1) continue;
 87.2136 -						if ( fabs(grid1->verts[k + offset1].xyz[1] - grid2->verts[l + offset2].xyz[1]) > .1) continue;
 87.2137 -						if ( fabs(grid1->verts[k + offset1].xyz[2] - grid2->verts[l + offset2].xyz[2]) > .1) continue;
 87.2138 +			if(n)
 87.2139 +				offset1 = (grid1->height - 1) * grid1->width;
 87.2140 +			else
 87.2141 +				offset1 = 0;
 87.2142 +			if(R_MergedWidthPoints(grid1, offset1))
 87.2143 +				continue;
 87.2144 +			for(k = 1; k < grid1->width - 1; k++)
 87.2145 +			{
 87.2146 +				for(m = 0; m < 2; m++)
 87.2147 +				{
 87.2148 +
 87.2149 +					if(m)
 87.2150 +						offset2 = (grid2->height - 1) * grid2->width;
 87.2151 +					else
 87.2152 +						offset2 = 0;
 87.2153 +					if(R_MergedWidthPoints(grid2, offset2))
 87.2154 +						continue;
 87.2155 +					for(l = 1; l < grid2->width - 1; l++)
 87.2156 +					{
 87.2157 +						//
 87.2158 +						if(fabs(grid1->verts[k + offset1].xyz[0] - grid2->verts[l + offset2].xyz[0]) > .1)
 87.2159 +							continue;
 87.2160 +						if(fabs(grid1->verts[k + offset1].xyz[1] - grid2->verts[l + offset2].xyz[1]) > .1)
 87.2161 +							continue;
 87.2162 +						if(fabs(grid1->verts[k + offset1].xyz[2] - grid2->verts[l + offset2].xyz[2]) > .1)
 87.2163 +							continue;
 87.2164  						// ok the points are equal and should have the same lod error
 87.2165  						grid2->widthLodError[l] = grid1->widthLodError[k];
 87.2166  						touch = qtrue;
 87.2167  					}
 87.2168  				}
 87.2169 -				for (m = 0; m < 2; m++) {
 87.2170 -
 87.2171 -					if (m) offset2 = grid2->width-1;
 87.2172 -					else offset2 = 0;
 87.2173 -					if (R_MergedHeightPoints(grid2, offset2)) continue;
 87.2174 -					for ( l = 1; l < grid2->height-1; l++) {
 87.2175 -					//
 87.2176 -						if ( fabs(grid1->verts[k + offset1].xyz[0] - grid2->verts[grid2->width * l + offset2].xyz[0]) > .1) continue;
 87.2177 -						if ( fabs(grid1->verts[k + offset1].xyz[1] - grid2->verts[grid2->width * l + offset2].xyz[1]) > .1) continue;
 87.2178 -						if ( fabs(grid1->verts[k + offset1].xyz[2] - grid2->verts[grid2->width * l + offset2].xyz[2]) > .1) continue;
 87.2179 +				for(m = 0; m < 2; m++)
 87.2180 +				{
 87.2181 +
 87.2182 +					if(m)
 87.2183 +						offset2 = grid2->width - 1;
 87.2184 +					else
 87.2185 +						offset2 = 0;
 87.2186 +					if(R_MergedHeightPoints(grid2, offset2))
 87.2187 +						continue;
 87.2188 +					for(l = 1; l < grid2->height - 1; l++)
 87.2189 +					{
 87.2190 +						//
 87.2191 +						if(fabs(grid1->verts[k + offset1].xyz[0] - grid2->verts[grid2->width * l + offset2].xyz[0]) > .1)
 87.2192 +							continue;
 87.2193 +						if(fabs(grid1->verts[k + offset1].xyz[1] - grid2->verts[grid2->width * l + offset2].xyz[1]) > .1)
 87.2194 +							continue;
 87.2195 +						if(fabs(grid1->verts[k + offset1].xyz[2] - grid2->verts[grid2->width * l + offset2].xyz[2]) > .1)
 87.2196 +							continue;
 87.2197  						// ok the points are equal and should have the same lod error
 87.2198  						grid2->heightLodError[l] = grid1->widthLodError[k];
 87.2199  						touch = qtrue;
 87.2200 @@ -636,37 +1844,64 @@
 87.2201  				}
 87.2202  			}
 87.2203  		}
 87.2204 -		for (n = 0; n < 2; n++) {
 87.2205 +		for(n = 0; n < 2; n++)
 87.2206 +		{
 87.2207  			//
 87.2208 -			if (n) offset1 = grid1->width-1;
 87.2209 -			else offset1 = 0;
 87.2210 -			if (R_MergedHeightPoints(grid1, offset1)) continue;
 87.2211 -			for (k = 1; k < grid1->height-1; k++) {
 87.2212 -				for (m = 0; m < 2; m++) {
 87.2213 -
 87.2214 -					if (m) offset2 = (grid2->height-1) * grid2->width;
 87.2215 -					else offset2 = 0;
 87.2216 -					if (R_MergedWidthPoints(grid2, offset2)) continue;
 87.2217 -					for ( l = 1; l < grid2->width-1; l++) {
 87.2218 -					//
 87.2219 -						if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[0] - grid2->verts[l + offset2].xyz[0]) > .1) continue;
 87.2220 -						if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[1] - grid2->verts[l + offset2].xyz[1]) > .1) continue;
 87.2221 -						if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[2] - grid2->verts[l + offset2].xyz[2]) > .1) continue;
 87.2222 +			if(n)
 87.2223 +				offset1 = grid1->width - 1;
 87.2224 +			else
 87.2225 +				offset1 = 0;
 87.2226 +			if(R_MergedHeightPoints(grid1, offset1))
 87.2227 +				continue;
 87.2228 +			for(k = 1; k < grid1->height - 1; k++)
 87.2229 +			{
 87.2230 +				for(m = 0; m < 2; m++)
 87.2231 +				{
 87.2232 +
 87.2233 +					if(m)
 87.2234 +						offset2 = (grid2->height - 1) * grid2->width;
 87.2235 +					else
 87.2236 +						offset2 = 0;
 87.2237 +					if(R_MergedWidthPoints(grid2, offset2))
 87.2238 +						continue;
 87.2239 +					for(l = 1; l < grid2->width - 1; l++)
 87.2240 +					{
 87.2241 +						//
 87.2242 +						if(fabs(grid1->verts[grid1->width * k + offset1].xyz[0] - grid2->verts[l + offset2].xyz[0]) > .1)
 87.2243 +							continue;
 87.2244 +						if(fabs(grid1->verts[grid1->width * k + offset1].xyz[1] - grid2->verts[l + offset2].xyz[1]) > .1)
 87.2245 +							continue;
 87.2246 +						if(fabs(grid1->verts[grid1->width * k + offset1].xyz[2] - grid2->verts[l + offset2].xyz[2]) > .1)
 87.2247 +							continue;
 87.2248  						// ok the points are equal and should have the same lod error
 87.2249  						grid2->widthLodError[l] = grid1->heightLodError[k];
 87.2250  						touch = qtrue;
 87.2251  					}
 87.2252  				}
 87.2253 -				for (m = 0; m < 2; m++) {
 87.2254 -
 87.2255 -					if (m) offset2 = grid2->width-1;
 87.2256 -					else offset2 = 0;
 87.2257 -					if (R_MergedHeightPoints(grid2, offset2)) continue;
 87.2258 -					for ( l = 1; l < grid2->height-1; l++) {
 87.2259 -					//
 87.2260 -						if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[0] - grid2->verts[grid2->width * l + offset2].xyz[0]) > .1) continue;
 87.2261 -						if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[1] - grid2->verts[grid2->width * l + offset2].xyz[1]) > .1) continue;
 87.2262 -						if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[2] - grid2->verts[grid2->width * l + offset2].xyz[2]) > .1) continue;
 87.2263 +				for(m = 0; m < 2; m++)
 87.2264 +				{
 87.2265 +
 87.2266 +					if(m)
 87.2267 +						offset2 = grid2->width - 1;
 87.2268 +					else
 87.2269 +						offset2 = 0;
 87.2270 +					if(R_MergedHeightPoints(grid2, offset2))
 87.2271 +						continue;
 87.2272 +					for(l = 1; l < grid2->height - 1; l++)
 87.2273 +					{
 87.2274 +						//
 87.2275 +						if(fabs
 87.2276 +						   (grid1->verts[grid1->width * k + offset1].xyz[0] -
 87.2277 +							grid2->verts[grid2->width * l + offset2].xyz[0]) > .1)
 87.2278 +							continue;
 87.2279 +						if(fabs
 87.2280 +						   (grid1->verts[grid1->width * k + offset1].xyz[1] -
 87.2281 +							grid2->verts[grid2->width * l + offset2].xyz[1]) > .1)
 87.2282 +							continue;
 87.2283 +						if(fabs
 87.2284 +						   (grid1->verts[grid1->width * k + offset1].xyz[2] -
 87.2285 +							grid2->verts[grid2->width * l + offset2].xyz[2]) > .1)
 87.2286 +							continue;
 87.2287  						// ok the points are equal and should have the same lod error
 87.2288  						grid2->heightLodError[l] = grid1->heightLodError[k];
 87.2289  						touch = qtrue;
 87.2290 @@ -674,9 +1909,10 @@
 87.2291  				}
 87.2292  			}
 87.2293  		}
 87.2294 -		if (touch) {
 87.2295 +		if(touch)
 87.2296 +		{
 87.2297  			grid2->lodFixed = 2;
 87.2298 -			R_FixSharedVertexLodError_r ( start, grid2 );
 87.2299 +			R_FixSharedVertexLodError_r(start, grid2);
 87.2300  			//NOTE: this would be correct but makes things really slow
 87.2301  			//grid2->lodFixed = 1;
 87.2302  		}
 87.2303 @@ -691,23 +1927,25 @@
 87.2304  If this is not the case this function will still do its job but won't fix the highest LoD cracks.
 87.2305  =================
 87.2306  */
 87.2307 -void R_FixSharedVertexLodError( void ) {
 87.2308 -	int i;
 87.2309 -	srfGridMesh_t *grid1;
 87.2310 -
 87.2311 -	for ( i = 0; i < s_worldData.numsurfaces; i++ ) {
 87.2312 +void R_FixSharedVertexLodError(void)
 87.2313 +{
 87.2314 +	int             i;
 87.2315 +	srfGridMesh_t  *grid1;
 87.2316 +
 87.2317 +	for(i = 0; i < s_worldData.numSurfaces; i++)
 87.2318 +	{
 87.2319  		//
 87.2320  		grid1 = (srfGridMesh_t *) s_worldData.surfaces[i].data;
 87.2321  		// if this surface is not a grid
 87.2322 -		if ( grid1->surfaceType != SF_GRID )
 87.2323 +		if(grid1->surfaceType != SF_GRID)
 87.2324  			continue;
 87.2325  		//
 87.2326 -		if ( grid1->lodFixed )
 87.2327 +		if(grid1->lodFixed)
 87.2328  			continue;
 87.2329  		//
 87.2330  		grid1->lodFixed = 2;
 87.2331  		// recursively fix other patches in the same LOD group
 87.2332 -		R_FixSharedVertexLodError_r( i + 1, grid1);
 87.2333 +		R_FixSharedVertexLodError_r(i + 1, grid1);
 87.2334  	}
 87.2335  }
 87.2336  
 87.2337 @@ -717,400 +1955,445 @@
 87.2338  R_StitchPatches
 87.2339  ===============
 87.2340  */
 87.2341 -int R_StitchPatches( int grid1num, int grid2num ) {
 87.2342 -	float *v1, *v2;
 87.2343 -	srfGridMesh_t *grid1, *grid2;
 87.2344 -	int k, l, m, n, offset1, offset2, row, column;
 87.2345 +int R_StitchPatches(int grid1num, int grid2num)
 87.2346 +{
 87.2347 +	float          *v1, *v2;
 87.2348 +	srfGridMesh_t  *grid1, *grid2;
 87.2349 +	int             k, l, m, n, offset1, offset2, row, column;
 87.2350  
 87.2351  	grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data;
 87.2352  	grid2 = (srfGridMesh_t *) s_worldData.surfaces[grid2num].data;
 87.2353 -	for (n = 0; n < 2; n++) {
 87.2354 +	for(n = 0; n < 2; n++)
 87.2355 +	{
 87.2356  		//
 87.2357 -		if (n) offset1 = (grid1->height-1) * grid1->width;
 87.2358 -		else offset1 = 0;
 87.2359 -		if (R_MergedWidthPoints(grid1, offset1))
 87.2360 +		if(n)
 87.2361 +			offset1 = (grid1->height - 1) * grid1->width;
 87.2362 +		else
 87.2363 +			offset1 = 0;
 87.2364 +		if(R_MergedWidthPoints(grid1, offset1))
 87.2365  			continue;
 87.2366 -		for (k = 0; k < grid1->width-2; k += 2) {
 87.2367 -
 87.2368 -			for (m = 0; m < 2; m++) {
 87.2369 -
 87.2370 -				if ( grid2->width >= MAX_GRID_SIZE )
 87.2371 +		for(k = 0; k < grid1->width - 2; k += 2)
 87.2372 +		{
 87.2373 +
 87.2374 +			for(m = 0; m < 2; m++)
 87.2375 +			{
 87.2376 +
 87.2377 +				if(grid2->width >= MAX_GRID_SIZE)
 87.2378  					break;
 87.2379 -				if (m) offset2 = (grid2->height-1) * grid2->width;
 87.2380 -				else offset2 = 0;
 87.2381 -				for ( l = 0; l < grid2->width-1; l++) {
 87.2382 -				//
 87.2383 +				if(m)
 87.2384 +					offset2 = (grid2->height - 1) * grid2->width;
 87.2385 +				else
 87.2386 +					offset2 = 0;
 87.2387 +				for(l = 0; l < grid2->width - 1; l++)
 87.2388 +				{
 87.2389 +					//
 87.2390  					v1 = grid1->verts[k + offset1].xyz;
 87.2391  					v2 = grid2->verts[l + offset2].xyz;
 87.2392 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2393 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2394  						continue;
 87.2395 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2396 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2397  						continue;
 87.2398 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2399 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2400  						continue;
 87.2401  
 87.2402  					v1 = grid1->verts[k + 2 + offset1].xyz;
 87.2403  					v2 = grid2->verts[l + 1 + offset2].xyz;
 87.2404 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2405 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2406  						continue;
 87.2407 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2408 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2409  						continue;
 87.2410 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2411 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2412  						continue;
 87.2413  					//
 87.2414  					v1 = grid2->verts[l + offset2].xyz;
 87.2415  					v2 = grid2->verts[l + 1 + offset2].xyz;
 87.2416 -					if ( fabs(v1[0] - v2[0]) < .01 &&
 87.2417 -							fabs(v1[1] - v2[1]) < .01 &&
 87.2418 -							fabs(v1[2] - v2[2]) < .01)
 87.2419 +					if(fabs(v1[0] - v2[0]) < .01 && fabs(v1[1] - v2[1]) < .01 && fabs(v1[2] - v2[2]) < .01)
 87.2420  						continue;
 87.2421  					//
 87.2422  					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
 87.2423  					// insert column into grid2 right after after column l
 87.2424 -					if (m) row = grid2->height-1;
 87.2425 -					else row = 0;
 87.2426 -					grid2 = R_GridInsertColumn( grid2, l+1, row,
 87.2427 -									grid1->verts[k + 1 + offset1].xyz, grid1->widthLodError[k+1]);
 87.2428 +					if(m)
 87.2429 +						row = grid2->height - 1;
 87.2430 +					else
 87.2431 +						row = 0;
 87.2432 +					grid2 = R_GridInsertColumn(grid2, l + 1, row, grid1->verts[k + 1 + offset1].xyz, grid1->widthLodError[k + 1]);
 87.2433  					grid2->lodStitched = qfalse;
 87.2434 -					s_worldData.surfaces[grid2num].data = (void *) grid2;
 87.2435 +					s_worldData.surfaces[grid2num].data = (void *)grid2;
 87.2436  					return qtrue;
 87.2437  				}
 87.2438  			}
 87.2439 -			for (m = 0; m < 2; m++) {
 87.2440 -
 87.2441 -				if (grid2->height >= MAX_GRID_SIZE)
 87.2442 +			for(m = 0; m < 2; m++)
 87.2443 +			{
 87.2444 +
 87.2445 +				if(grid2->height >= MAX_GRID_SIZE)
 87.2446  					break;
 87.2447 -				if (m) offset2 = grid2->width-1;
 87.2448 -				else offset2 = 0;
 87.2449 -				for ( l = 0; l < grid2->height-1; l++) {
 87.2450 +				if(m)
 87.2451 +					offset2 = grid2->width - 1;
 87.2452 +				else
 87.2453 +					offset2 = 0;
 87.2454 +				for(l = 0; l < grid2->height - 1; l++)
 87.2455 +				{
 87.2456  					//
 87.2457  					v1 = grid1->verts[k + offset1].xyz;
 87.2458  					v2 = grid2->verts[grid2->width * l + offset2].xyz;
 87.2459 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2460 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2461  						continue;
 87.2462 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2463 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2464  						continue;
 87.2465 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2466 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2467  						continue;
 87.2468  
 87.2469  					v1 = grid1->verts[k + 2 + offset1].xyz;
 87.2470  					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
 87.2471 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2472 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2473  						continue;
 87.2474 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2475 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2476  						continue;
 87.2477 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2478 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2479  						continue;
 87.2480  					//
 87.2481  					v1 = grid2->verts[grid2->width * l + offset2].xyz;
 87.2482  					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
 87.2483 -					if ( fabs(v1[0] - v2[0]) < .01 &&
 87.2484 -							fabs(v1[1] - v2[1]) < .01 &&
 87.2485 -							fabs(v1[2] - v2[2]) < .01)
 87.2486 +					if(fabs(v1[0] - v2[0]) < .01 && fabs(v1[1] - v2[1]) < .01 && fabs(v1[2] - v2[2]) < .01)
 87.2487  						continue;
 87.2488  					//
 87.2489  					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
 87.2490  					// insert row into grid2 right after after row l
 87.2491 -					if (m) column = grid2->width-1;
 87.2492 -					else column = 0;
 87.2493 -					grid2 = R_GridInsertRow( grid2, l+1, column,
 87.2494 -										grid1->verts[k + 1 + offset1].xyz, grid1->widthLodError[k+1]);
 87.2495 +					if(m)
 87.2496 +						column = grid2->width - 1;
 87.2497 +					else
 87.2498 +						column = 0;
 87.2499 +					grid2 = R_GridInsertRow(grid2, l + 1, column, grid1->verts[k + 1 + offset1].xyz, grid1->widthLodError[k + 1]);
 87.2500  					grid2->lodStitched = qfalse;
 87.2501 -					s_worldData.surfaces[grid2num].data = (void *) grid2;
 87.2502 +					s_worldData.surfaces[grid2num].data = (void *)grid2;
 87.2503  					return qtrue;
 87.2504  				}
 87.2505  			}
 87.2506  		}
 87.2507  	}
 87.2508 -	for (n = 0; n < 2; n++) {
 87.2509 +	for(n = 0; n < 2; n++)
 87.2510 +	{
 87.2511  		//
 87.2512 -		if (n) offset1 = grid1->width-1;
 87.2513 -		else offset1 = 0;
 87.2514 -		if (R_MergedHeightPoints(grid1, offset1))
 87.2515 +		if(n)
 87.2516 +			offset1 = grid1->width - 1;
 87.2517 +		else
 87.2518 +			offset1 = 0;
 87.2519 +		if(R_MergedHeightPoints(grid1, offset1))
 87.2520  			continue;
 87.2521 -		for (k = 0; k < grid1->height-2; k += 2) {
 87.2522 -			for (m = 0; m < 2; m++) {
 87.2523 -
 87.2524 -				if ( grid2->width >= MAX_GRID_SIZE )
 87.2525 +		for(k = 0; k < grid1->height - 2; k += 2)
 87.2526 +		{
 87.2527 +			for(m = 0; m < 2; m++)
 87.2528 +			{
 87.2529 +
 87.2530 +				if(grid2->width >= MAX_GRID_SIZE)
 87.2531  					break;
 87.2532 -				if (m) offset2 = (grid2->height-1) * grid2->width;
 87.2533 -				else offset2 = 0;
 87.2534 -				for ( l = 0; l < grid2->width-1; l++) {
 87.2535 -				//
 87.2536 +				if(m)
 87.2537 +					offset2 = (grid2->height - 1) * grid2->width;
 87.2538 +				else
 87.2539 +					offset2 = 0;
 87.2540 +				for(l = 0; l < grid2->width - 1; l++)
 87.2541 +				{
 87.2542 +					//
 87.2543  					v1 = grid1->verts[grid1->width * k + offset1].xyz;
 87.2544  					v2 = grid2->verts[l + offset2].xyz;
 87.2545 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2546 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2547  						continue;
 87.2548 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2549 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2550  						continue;
 87.2551 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2552 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2553  						continue;
 87.2554  
 87.2555  					v1 = grid1->verts[grid1->width * (k + 2) + offset1].xyz;
 87.2556  					v2 = grid2->verts[l + 1 + offset2].xyz;
 87.2557 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2558 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2559  						continue;
 87.2560 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2561 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2562  						continue;
 87.2563 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2564 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2565  						continue;
 87.2566  					//
 87.2567  					v1 = grid2->verts[l + offset2].xyz;
 87.2568  					v2 = grid2->verts[(l + 1) + offset2].xyz;
 87.2569 -					if ( fabs(v1[0] - v2[0]) < .01 &&
 87.2570 -							fabs(v1[1] - v2[1]) < .01 &&
 87.2571 -							fabs(v1[2] - v2[2]) < .01)
 87.2572 +					if(fabs(v1[0] - v2[0]) < .01 && fabs(v1[1] - v2[1]) < .01 && fabs(v1[2] - v2[2]) < .01)
 87.2573  						continue;
 87.2574  					//
 87.2575  					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
 87.2576  					// insert column into grid2 right after after column l
 87.2577 -					if (m) row = grid2->height-1;
 87.2578 -					else row = 0;
 87.2579 -					grid2 = R_GridInsertColumn( grid2, l+1, row,
 87.2580 -									grid1->verts[grid1->width * (k + 1) + offset1].xyz, grid1->heightLodError[k+1]);
 87.2581 +					if(m)
 87.2582 +						row = grid2->height - 1;
 87.2583 +					else
 87.2584 +						row = 0;
 87.2585 +					grid2 = R_GridInsertColumn(grid2, l + 1, row,
 87.2586 +											   grid1->verts[grid1->width * (k + 1) + offset1].xyz, grid1->heightLodError[k + 1]);
 87.2587  					grid2->lodStitched = qfalse;
 87.2588 -					s_worldData.surfaces[grid2num].data = (void *) grid2;
 87.2589 +					s_worldData.surfaces[grid2num].data = (void *)grid2;
 87.2590  					return qtrue;
 87.2591  				}
 87.2592  			}
 87.2593 -			for (m = 0; m < 2; m++) {
 87.2594 -
 87.2595 -				if (grid2->height >= MAX_GRID_SIZE)
 87.2596 +			for(m = 0; m < 2; m++)
 87.2597 +			{
 87.2598 +
 87.2599 +				if(grid2->height >= MAX_GRID_SIZE)
 87.2600  					break;
 87.2601 -				if (m) offset2 = grid2->width-1;
 87.2602 -				else offset2 = 0;
 87.2603 -				for ( l = 0; l < grid2->height-1; l++) {
 87.2604 -				//
 87.2605 +				if(m)
 87.2606 +					offset2 = grid2->width - 1;
 87.2607 +				else
 87.2608 +					offset2 = 0;
 87.2609 +				for(l = 0; l < grid2->height - 1; l++)
 87.2610 +				{
 87.2611 +					//
 87.2612  					v1 = grid1->verts[grid1->width * k + offset1].xyz;
 87.2613  					v2 = grid2->verts[grid2->width * l + offset2].xyz;
 87.2614 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2615 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2616  						continue;
 87.2617 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2618 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2619  						continue;
 87.2620 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2621 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2622  						continue;
 87.2623  
 87.2624  					v1 = grid1->verts[grid1->width * (k + 2) + offset1].xyz;
 87.2625  					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
 87.2626 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2627 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2628  						continue;
 87.2629 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2630 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2631  						continue;
 87.2632 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2633 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2634  						continue;
 87.2635  					//
 87.2636  					v1 = grid2->verts[grid2->width * l + offset2].xyz;
 87.2637  					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
 87.2638 -					if ( fabs(v1[0] - v2[0]) < .01 &&
 87.2639 -							fabs(v1[1] - v2[1]) < .01 &&
 87.2640 -							fabs(v1[2] - v2[2]) < .01)
 87.2641 +					if(fabs(v1[0] - v2[0]) < .01 && fabs(v1[1] - v2[1]) < .01 && fabs(v1[2] - v2[2]) < .01)
 87.2642  						continue;
 87.2643  					//
 87.2644  					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
 87.2645  					// insert row into grid2 right after after row l
 87.2646 -					if (m) column = grid2->width-1;
 87.2647 -					else column = 0;
 87.2648 -					grid2 = R_GridInsertRow( grid2, l+1, column,
 87.2649 -									grid1->verts[grid1->width * (k + 1) + offset1].xyz, grid1->heightLodError[k+1]);
 87.2650 +					if(m)
 87.2651 +						column = grid2->width - 1;
 87.2652 +					else
 87.2653 +						column = 0;
 87.2654 +					grid2 = R_GridInsertRow(grid2, l + 1, column,
 87.2655 +											grid1->verts[grid1->width * (k + 1) + offset1].xyz, grid1->heightLodError[k + 1]);
 87.2656  					grid2->lodStitched = qfalse;
 87.2657 -					s_worldData.surfaces[grid2num].data = (void *) grid2;
 87.2658 +					s_worldData.surfaces[grid2num].data = (void *)grid2;
 87.2659  					return qtrue;
 87.2660  				}
 87.2661  			}
 87.2662  		}
 87.2663  	}
 87.2664 -	for (n = 0; n < 2; n++) {
 87.2665 +	for(n = 0; n < 2; n++)
 87.2666 +	{
 87.2667  		//
 87.2668 -		if (n) offset1 = (grid1->height-1) * grid1->width;
 87.2669 -		else offset1 = 0;
 87.2670 -		if (R_MergedWidthPoints(grid1, offset1))
 87.2671 +		if(n)
 87.2672 +			offset1 = (grid1->height - 1) * grid1->width;
 87.2673 +		else
 87.2674 +			offset1 = 0;
 87.2675 +		if(R_MergedWidthPoints(grid1, offset1))
 87.2676  			continue;
 87.2677 -		for (k = grid1->width-1; k > 1; k -= 2) {
 87.2678 -
 87.2679 -			for (m = 0; m < 2; m++) {
 87.2680 -
 87.2681 -				if ( grid2->width >= MAX_GRID_SIZE )
 87.2682 +		for(k = grid1->width - 1; k > 1; k -= 2)
 87.2683 +		{
 87.2684 +
 87.2685 +			for(m = 0; m < 2; m++)
 87.2686 +			{
 87.2687 +
 87.2688 +				if(grid2->width >= MAX_GRID_SIZE)
 87.2689  					break;
 87.2690 -				if (m) offset2 = (grid2->height-1) * grid2->width;
 87.2691 -				else offset2 = 0;
 87.2692 -				for ( l = 0; l < grid2->width-1; l++) {
 87.2693 -				//
 87.2694 +				if(m)
 87.2695 +					offset2 = (grid2->height - 1) * grid2->width;
 87.2696 +				else
 87.2697 +					offset2 = 0;
 87.2698 +				for(l = 0; l < grid2->width - 1; l++)
 87.2699 +				{
 87.2700 +					//
 87.2701  					v1 = grid1->verts[k + offset1].xyz;
 87.2702  					v2 = grid2->verts[l + offset2].xyz;
 87.2703 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2704 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2705  						continue;
 87.2706 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2707 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2708  						continue;
 87.2709 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2710 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2711  						continue;
 87.2712  
 87.2713  					v1 = grid1->verts[k - 2 + offset1].xyz;
 87.2714  					v2 = grid2->verts[l + 1 + offset2].xyz;
 87.2715 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2716 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2717  						continue;
 87.2718 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2719 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2720  						continue;
 87.2721 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2722 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2723  						continue;
 87.2724  					//
 87.2725  					v1 = grid2->verts[l + offset2].xyz;
 87.2726  					v2 = grid2->verts[(l + 1) + offset2].xyz;
 87.2727 -					if ( fabs(v1[0] - v2[0]) < .01 &&
 87.2728 -							fabs(v1[1] - v2[1]) < .01 &&
 87.2729 -							fabs(v1[2] - v2[2]) < .01)
 87.2730 +					if(fabs(v1[0] - v2[0]) < .01 && fabs(v1[1] - v2[1]) < .01 && fabs(v1[2] - v2[2]) < .01)
 87.2731  						continue;
 87.2732  					//
 87.2733  					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
 87.2734  					// insert column into grid2 right after after column l
 87.2735 -					if (m) row = grid2->height-1;
 87.2736 -					else row = 0;
 87.2737 -					grid2 = R_GridInsertColumn( grid2, l+1, row,
 87.2738 -										grid1->verts[k - 1 + offset1].xyz, grid1->widthLodError[k+1]);
 87.2739 +					if(m)
 87.2740 +						row = grid2->height - 1;
 87.2741 +					else
 87.2742 +						row = 0;
 87.2743 +					grid2 = R_GridInsertColumn(grid2, l + 1, row, grid1->verts[k - 1 + offset1].xyz, grid1->widthLodError[k + 1]);
 87.2744  					grid2->lodStitched = qfalse;
 87.2745 -					s_worldData.surfaces[grid2num].data = (void *) grid2;
 87.2746 +					s_worldData.surfaces[grid2num].data = (void *)grid2;
 87.2747  					return qtrue;
 87.2748  				}
 87.2749  			}
 87.2750 -			for (m = 0; m < 2; m++) {
 87.2751 -
 87.2752 -				if (grid2->height >= MAX_GRID_SIZE)
 87.2753 +			for(m = 0; m < 2; m++)
 87.2754 +			{
 87.2755 +
 87.2756 +				if(grid2->height >= MAX_GRID_SIZE)
 87.2757  					break;
 87.2758 -				if (m) offset2 = grid2->width-1;
 87.2759 -				else offset2 = 0;
 87.2760 -				for ( l = 0; l < grid2->height-1; l++) {
 87.2761 -				//
 87.2762 +				if(m)
 87.2763 +					offset2 = grid2->width - 1;
 87.2764 +				else
 87.2765 +					offset2 = 0;
 87.2766 +				for(l = 0; l < grid2->height - 1; l++)
 87.2767 +				{
 87.2768 +					//
 87.2769  					v1 = grid1->verts[k + offset1].xyz;
 87.2770  					v2 = grid2->verts[grid2->width * l + offset2].xyz;
 87.2771 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2772 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2773  						continue;
 87.2774 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2775 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2776  						continue;
 87.2777 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2778 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2779  						continue;
 87.2780  
 87.2781  					v1 = grid1->verts[k - 2 + offset1].xyz;
 87.2782  					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
 87.2783 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2784 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2785  						continue;
 87.2786 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2787 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2788  						continue;
 87.2789 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2790 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2791  						continue;
 87.2792  					//
 87.2793  					v1 = grid2->verts[grid2->width * l + offset2].xyz;
 87.2794  					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
 87.2795 -					if ( fabs(v1[0] - v2[0]) < .01 &&
 87.2796 -							fabs(v1[1] - v2[1]) < .01 &&
 87.2797 -							fabs(v1[2] - v2[2]) < .01)
 87.2798 +					if(fabs(v1[0] - v2[0]) < .01 && fabs(v1[1] - v2[1]) < .01 && fabs(v1[2] - v2[2]) < .01)
 87.2799  						continue;
 87.2800  					//
 87.2801  					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
 87.2802  					// insert row into grid2 right after after row l
 87.2803 -					if (m) column = grid2->width-1;
 87.2804 -					else column = 0;
 87.2805 -					grid2 = R_GridInsertRow( grid2, l+1, column,
 87.2806 -										grid1->verts[k - 1 + offset1].xyz, grid1->widthLodError[k+1]);
 87.2807 -					if (!grid2)
 87.2808 +					if(m)
 87.2809 +						column = grid2->width - 1;
 87.2810 +					else
 87.2811 +						column = 0;
 87.2812 +					grid2 = R_GridInsertRow(grid2, l + 1, column, grid1->verts[k - 1 + offset1].xyz, grid1->widthLodError[k + 1]);
 87.2813 +					if(!grid2)
 87.2814  						break;
 87.2815  					grid2->lodStitched = qfalse;
 87.2816 -					s_worldData.surfaces[grid2num].data = (void *) grid2;
 87.2817 +					s_worldData.surfaces[grid2num].data = (void *)grid2;
 87.2818  					return qtrue;
 87.2819  				}
 87.2820  			}
 87.2821  		}
 87.2822  	}
 87.2823 -	for (n = 0; n < 2; n++) {
 87.2824 +	for(n = 0; n < 2; n++)
 87.2825 +	{
 87.2826  		//
 87.2827 -		if (n) offset1 = grid1->width-1;
 87.2828 -		else offset1 = 0;
 87.2829 -		if (R_MergedHeightPoints(grid1, offset1))
 87.2830 +		if(n)
 87.2831 +			offset1 = grid1->width - 1;
 87.2832 +		else
 87.2833 +			offset1 = 0;
 87.2834 +		if(R_MergedHeightPoints(grid1, offset1))
 87.2835  			continue;
 87.2836 -		for (k = grid1->height-1; k > 1; k -= 2) {
 87.2837 -			for (m = 0; m < 2; m++) {
 87.2838 -
 87.2839 -				if ( grid2->width >= MAX_GRID_SIZE )
 87.2840 +		for(k = grid1->height - 1; k > 1; k -= 2)
 87.2841 +		{
 87.2842 +			for(m = 0; m < 2; m++)
 87.2843 +			{
 87.2844 +
 87.2845 +				if(grid2->width >= MAX_GRID_SIZE)
 87.2846  					break;
 87.2847 -				if (m) offset2 = (grid2->height-1) * grid2->width;
 87.2848 -				else offset2 = 0;
 87.2849 -				for ( l = 0; l < grid2->width-1; l++) {
 87.2850 -				//
 87.2851 +				if(m)
 87.2852 +					offset2 = (grid2->height - 1) * grid2->width;
 87.2853 +				else
 87.2854 +					offset2 = 0;
 87.2855 +				for(l = 0; l < grid2->width - 1; l++)
 87.2856 +				{
 87.2857 +					//
 87.2858  					v1 = grid1->verts[grid1->width * k + offset1].xyz;
 87.2859  					v2 = grid2->verts[l + offset2].xyz;
 87.2860 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2861 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2862  						continue;
 87.2863 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2864 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2865  						continue;
 87.2866 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2867 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2868  						continue;
 87.2869  
 87.2870  					v1 = grid1->verts[grid1->width * (k - 2) + offset1].xyz;
 87.2871  					v2 = grid2->verts[l + 1 + offset2].xyz;
 87.2872 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2873 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2874  						continue;
 87.2875 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2876 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2877  						continue;
 87.2878 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2879 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2880  						continue;
 87.2881  					//
 87.2882  					v1 = grid2->verts[l + offset2].xyz;
 87.2883  					v2 = grid2->verts[(l + 1) + offset2].xyz;
 87.2884 -					if ( fabs(v1[0] - v2[0]) < .01 &&
 87.2885 -							fabs(v1[1] - v2[1]) < .01 &&
 87.2886 -							fabs(v1[2] - v2[2]) < .01)
 87.2887 +					if(fabs(v1[0] - v2[0]) < .01 && fabs(v1[1] - v2[1]) < .01 && fabs(v1[2] - v2[2]) < .01)
 87.2888  						continue;
 87.2889  					//
 87.2890  					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
 87.2891  					// insert column into grid2 right after after column l
 87.2892 -					if (m) row = grid2->height-1;
 87.2893 -					else row = 0;
 87.2894 -					grid2 = R_GridInsertColumn( grid2, l+1, row,
 87.2895 -										grid1->verts[grid1->width * (k - 1) + offset1].xyz, grid1->heightLodError[k+1]);
 87.2896 +					if(m)
 87.2897 +						row = grid2->height - 1;
 87.2898 +					else
 87.2899 +						row = 0;
 87.2900 +					grid2 = R_GridInsertColumn(grid2, l + 1, row,
 87.2901 +											   grid1->verts[grid1->width * (k - 1) + offset1].xyz, grid1->heightLodError[k + 1]);
 87.2902  					grid2->lodStitched = qfalse;
 87.2903 -					s_worldData.surfaces[grid2num].data = (void *) grid2;
 87.2904 +					s_worldData.surfaces[grid2num].data = (void *)grid2;
 87.2905  					return qtrue;
 87.2906  				}
 87.2907  			}
 87.2908 -			for (m = 0; m < 2; m++) {
 87.2909 -
 87.2910 -				if (grid2->height >= MAX_GRID_SIZE)
 87.2911 +			for(m = 0; m < 2; m++)
 87.2912 +			{
 87.2913 +
 87.2914 +				if(grid2->height >= MAX_GRID_SIZE)
 87.2915  					break;
 87.2916 -				if (m) offset2 = grid2->width-1;
 87.2917 -				else offset2 = 0;
 87.2918 -				for ( l = 0; l < grid2->height-1; l++) {
 87.2919 -				//
 87.2920 +				if(m)
 87.2921 +					offset2 = grid2->width - 1;
 87.2922 +				else
 87.2923 +					offset2 = 0;
 87.2924 +				for(l = 0; l < grid2->height - 1; l++)
 87.2925 +				{
 87.2926 +					//
 87.2927  					v1 = grid1->verts[grid1->width * k + offset1].xyz;
 87.2928  					v2 = grid2->verts[grid2->width * l + offset2].xyz;
 87.2929 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2930 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2931  						continue;
 87.2932 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2933 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2934  						continue;
 87.2935 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2936 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2937  						continue;
 87.2938  
 87.2939  					v1 = grid1->verts[grid1->width * (k - 2) + offset1].xyz;
 87.2940  					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
 87.2941 -					if ( fabs(v1[0] - v2[0]) > .1)
 87.2942 +					if(fabs(v1[0] - v2[0]) > .1)
 87.2943  						continue;
 87.2944 -					if ( fabs(v1[1] - v2[1]) > .1)
 87.2945 +					if(fabs(v1[1] - v2[1]) > .1)
 87.2946  						continue;
 87.2947 -					if ( fabs(v1[2] - v2[2]) > .1)
 87.2948 +					if(fabs(v1[2] - v2[2]) > .1)
 87.2949  						continue;
 87.2950  					//
 87.2951  					v1 = grid2->verts[grid2->width * l + offset2].xyz;
 87.2952  					v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
 87.2953 -					if ( fabs(v1[0] - v2[0]) < .01 &&
 87.2954 -							fabs(v1[1] - v2[1]) < .01 &&
 87.2955 -							fabs(v1[2] - v2[2]) < .01)
 87.2956 +					if(fabs(v1[0] - v2[0]) < .01 && fabs(v1[1] - v2[1]) < .01 && fabs(v1[2] - v2[2]) < .01)
 87.2957  						continue;
 87.2958  					//
 87.2959  					//ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
 87.2960  					// insert row into grid2 right after after row l
 87.2961 -					if (m) column = grid2->width-1;
 87.2962 -					else column = 0;
 87.2963 -					grid2 = R_GridInsertRow( grid2, l+1, column,
 87.2964 -										grid1->verts[grid1->width * (k - 1) + offset1].xyz, grid1->heightLodError[k+1]);
 87.2965 +					if(m)
 87.2966 +						column = grid2->width - 1;
 87.2967 +					else
 87.2968 +						column = 0;
 87.2969 +					grid2 = R_GridInsertRow(grid2, l + 1, column,
 87.2970 +											grid1->verts[grid1->width * (k - 1) + offset1].xyz, grid1->heightLodError[k + 1]);
 87.2971  					grid2->lodStitched = qfalse;
 87.2972 -					s_worldData.surfaces[grid2num].data = (void *) grid2;
 87.2973 +					s_worldData.surfaces[grid2num].data = (void *)grid2;
 87.2974  					return qtrue;
 87.2975  				}
 87.2976  			}
 87.2977 @@ -1132,25 +2415,32 @@
 87.2978  might still appear at that side.
 87.2979  ===============
 87.2980  */
 87.2981 -int R_TryStitchingPatch( int grid1num ) {
 87.2982 -	int j, numstitches;
 87.2983 -	srfGridMesh_t *grid1, *grid2;
 87.2984 +int R_TryStitchingPatch(int grid1num)
 87.2985 +{
 87.2986 +	int             j, numstitches;
 87.2987 +	srfGridMesh_t  *grid1, *grid2;
 87.2988  
 87.2989  	numstitches = 0;
 87.2990  	grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data;
 87.2991 -	for ( j = 0; j < s_worldData.numsurfaces; j++ ) {
 87.2992 +	for(j = 0; j < s_worldData.numSurfaces; j++)
 87.2993 +	{
 87.2994  		//
 87.2995  		grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data;
 87.2996  		// if this surface is not a grid
 87.2997 -		if ( grid2->surfaceType != SF_GRID ) continue;
 87.2998 +		if(grid2->surfaceType != SF_GRID)
 87.2999 +			continue;
 87.3000  		// grids in the same LOD group should have the exact same lod radius
 87.3001 -		if ( grid1->lodRadius != grid2->lodRadius ) continue;
 87.3002 +		if(grid1->lodRadius != grid2->lodRadius)
 87.3003 +			continue;
 87.3004  		// grids in the same LOD group should have the exact same lod origin
 87.3005 -		if ( grid1->lodOrigin[0] != grid2->lodOrigin[0] ) continue;
 87.3006 -		if ( grid1->lodOrigin[1] != grid2->lodOrigin[1] ) continue;
 87.3007 -		if ( grid1->lodOrigin[2] != grid2->lodOrigin[2] ) continue;
 87.3008 +		if(grid1->lodOrigin[0] != grid2->lodOrigin[0])
 87.3009 +			continue;
 87.3010 +		if(grid1->lodOrigin[1] != grid2->lodOrigin[1])
 87.3011 +			continue;
 87.3012 +		if(grid1->lodOrigin[2] != grid2->lodOrigin[2])
 87.3013 +			continue;
 87.3014  		//
 87.3015 -		while (R_StitchPatches(grid1num, j))
 87.3016 +		while(R_StitchPatches(grid1num, j))
 87.3017  		{
 87.3018  			numstitches++;
 87.3019  		}
 87.3020 @@ -1163,32 +2453,35 @@
 87.3021  R_StitchAllPatches
 87.3022  ===============
 87.3023  */
 87.3024 -void R_StitchAllPatches( void ) {
 87.3025 -	int i, stitched, numstitches;
 87.3026 -	srfGridMesh_t *grid1;
 87.3027 +void R_StitchAllPatches(void)
 87.3028 +{
 87.3029 +	int             i, stitched, numstitches;
 87.3030 +	srfGridMesh_t  *grid1;
 87.3031 +
 87.3032 +	ri.Printf(PRINT_ALL, "...stitching LoD cracks\n");
 87.3033  
 87.3034  	numstitches = 0;
 87.3035  	do
 87.3036  	{
 87.3037  		stitched = qfalse;
 87.3038 -		for ( i = 0; i < s_worldData.numsurfaces; i++ ) {
 87.3039 +		for(i = 0; i < s_worldData.numSurfaces; i++)
 87.3040 +		{
 87.3041  			//
 87.3042  			grid1 = (srfGridMesh_t *) s_worldData.surfaces[i].data;
 87.3043  			// if this surface is not a grid
 87.3044 -			if ( grid1->surfaceType != SF_GRID )
 87.3045 +			if(grid1->surfaceType != SF_GRID)
 87.3046  				continue;
 87.3047  			//
 87.3048 -			if ( grid1->lodStitched )
 87.3049 +			if(grid1->lodStitched)
 87.3050  				continue;
 87.3051  			//
 87.3052  			grid1->lodStitched = qtrue;
 87.3053  			stitched = qtrue;
 87.3054  			//
 87.3055 -			numstitches += R_TryStitchingPatch( i );
 87.3056 -		}
 87.3057 -	}
 87.3058 -	while (stitched);
 87.3059 -	ri.Printf( PRINT_DEVELOPER, "stitched %d LoD cracks\n", numstitches );
 87.3060 +			numstitches += R_TryStitchingPatch(i);
 87.3061 +		}
 87.3062 +	} while(stitched);
 87.3063 +	ri.Printf(PRINT_ALL, "stitched %d LoD cracks\n", numstitches);
 87.3064  }
 87.3065  
 87.3066  /*
 87.3067 @@ -1196,30 +2489,2155 @@
 87.3068  R_MovePatchSurfacesToHunk
 87.3069  ===============
 87.3070  */
 87.3071 -void R_MovePatchSurfacesToHunk(void) {
 87.3072 -	int i, size;
 87.3073 -	srfGridMesh_t *grid, *hunkgrid;
 87.3074 -
 87.3075 -	for ( i = 0; i < s_worldData.numsurfaces; i++ ) {
 87.3076 +void R_MovePatchSurfacesToHunk(void)
 87.3077 +{
 87.3078 +	int             i, size;
 87.3079 +	srfGridMesh_t  *grid, *hunkgrid;
 87.3080 +
 87.3081 +	for(i = 0; i < s_worldData.numSurfaces; i++)
 87.3082 +	{
 87.3083  		//
 87.3084  		grid = (srfGridMesh_t *) s_worldData.surfaces[i].data;
 87.3085 +
 87.3086  		// if this surface is not a grid
 87.3087 -		if ( grid->surfaceType != SF_GRID )
 87.3088 +		if(grid->surfaceType != SF_GRID)
 87.3089  			continue;
 87.3090  		//
 87.3091 -		size = (grid->width * grid->height - 1) * sizeof( drawVert_t ) + sizeof( *grid );
 87.3092 -		hunkgrid = ri.Hunk_Alloc( size, h_low );
 87.3093 +		size = sizeof(*grid);
 87.3094 +		hunkgrid = ri.Hunk_Alloc(size, h_low);
 87.3095  		Com_Memcpy(hunkgrid, grid, size);
 87.3096  
 87.3097 -		hunkgrid->widthLodError = ri.Hunk_Alloc( grid->width * 4, h_low );
 87.3098 -		Com_Memcpy( hunkgrid->widthLodError, grid->widthLodError, grid->width * 4 );
 87.3099 -
 87.3100 -		hunkgrid->heightLodError = ri.Hunk_Alloc( grid->height * 4, h_low );
 87.3101 -		Com_Memcpy( hunkgrid->heightLodError, grid->heightLodError, grid->height * 4 );
 87.3102 -
 87.3103 -		R_FreeSurfaceGridMesh( grid );
 87.3104 -
 87.3105 -		s_worldData.surfaces[i].data = (void *) hunkgrid;
 87.3106 +		hunkgrid->widthLodError = ri.Hunk_Alloc(grid->width * 4, h_low);
 87.3107 +		Com_Memcpy(hunkgrid->widthLodError, grid->widthLodError, grid->width * 4);
 87.3108 +
 87.3109 +		hunkgrid->heightLodError = ri.Hunk_Alloc(grid->height * 4, h_low);
 87.3110 +		Com_Memcpy(hunkgrid->heightLodError, grid->heightLodError, grid->height * 4);
 87.3111 +
 87.3112 +		hunkgrid->numTriangles = grid->numTriangles;
 87.3113 +		hunkgrid->triangles = ri.Hunk_Alloc(grid->numTriangles * sizeof(srfTriangle_t), h_low);
 87.3114 +		Com_Memcpy(hunkgrid->triangles, grid->triangles, grid->numTriangles * sizeof(srfTriangle_t));
 87.3115 +
 87.3116 +		hunkgrid->numVerts = grid->numVerts;
 87.3117 +		hunkgrid->verts = ri.Hunk_Alloc(grid->numVerts * sizeof(srfVert_t), h_low);
 87.3118 +		Com_Memcpy(hunkgrid->verts, grid->verts, grid->numVerts * sizeof(srfVert_t));
 87.3119 +
 87.3120 +		R_FreeSurfaceGridMesh(grid);
 87.3121 +
 87.3122 +		s_worldData.surfaces[i].data = (void *)hunkgrid;
 87.3123 +	}
 87.3124 +}
 87.3125 +
 87.3126 +/*
 87.3127 +=================
 87.3128 +BSPSurfaceCompare
 87.3129 +compare function for qsort()
 87.3130 +=================
 87.3131 +*/
 87.3132 +static int BSPSurfaceCompare(const void *a, const void *b)
 87.3133 +{
 87.3134 +	bspSurface_t   *aa, *bb;
 87.3135 +
 87.3136 +	aa = *(bspSurface_t **) a;
 87.3137 +	bb = *(bspSurface_t **) b;
 87.3138 +
 87.3139 +	// shader first
 87.3140 +	if(aa->shader < bb->shader)
 87.3141 +		return -1;
 87.3142 +
 87.3143 +	else if(aa->shader > bb->shader)
 87.3144 +		return 1;
 87.3145 +
 87.3146 +	// by lightmap
 87.3147 +	if(aa->lightmapNum < bb->lightmapNum)
 87.3148 +		return -1;
 87.3149 +
 87.3150 +	else if(aa->lightmapNum > bb->lightmapNum)
 87.3151 +		return 1;
 87.3152 +
 87.3153 +	return 0;
 87.3154 +}
 87.3155 +
 87.3156 +
 87.3157 +static void CopyVert(const srfVert_t * in, srfVert_t * out)
 87.3158 +{
 87.3159 +	int             j;
 87.3160 +
 87.3161 +	for(j = 0; j < 3; j++)
 87.3162 +	{
 87.3163 +		out->xyz[j] = in->xyz[j];
 87.3164 +		out->tangent[j] = in->tangent[j];
 87.3165 +		out->binormal[j] = in->binormal[j];
 87.3166 +		out->normal[j] = in->normal[j];
 87.3167 +		out->lightDirection[j] = in->lightDirection[j];
 87.3168 +	}
 87.3169 +
 87.3170 +	for(j = 0; j < 2; j++)
 87.3171 +	{
 87.3172 +		out->st[j] = in->st[j];
 87.3173 +		out->lightmap[j] = in->lightmap[j];
 87.3174 +	}
 87.3175 +
 87.3176 +	for(j = 0; j < 4; j++)
 87.3177 +	{
 87.3178 +		out->paintColor[j] = in->paintColor[j];
 87.3179 +		out->lightColor[j] = in->lightColor[j];
 87.3180 +	}
 87.3181 +
 87.3182 +#if DEBUG_OPTIMIZEVERTICES
 87.3183 +	out->id = in->id;
 87.3184 +#endif
 87.3185 +}
 87.3186 +
 87.3187 +
 87.3188 +#define	EQUAL_EPSILON	0.001
 87.3189 +static qboolean CompareWorldVert(const srfVert_t * v1, const srfVert_t * v2)
 87.3190 +{
 87.3191 +	int             i;
 87.3192 +
 87.3193 +	for(i = 0; i < 3; i++)
 87.3194 +	{
 87.3195 +		//if(fabs(v1->xyz[i] - v2->xyz[i]) > EQUAL_EPSILON)
 87.3196 +		if(v1->xyz[i] != v2->xyz[i])
 87.3197 +			return qfalse;
 87.3198 +	}
 87.3199 +
 87.3200 +	for(i = 0; i < 2; i++)
 87.3201 +	{
 87.3202 +		if(v1->st[i] != v2->st[i])
 87.3203 +			return qfalse;
 87.3204 +	}
 87.3205 +
 87.3206 +	if(r_precomputedLighting->integer)
 87.3207 +	{
 87.3208 +		for(i = 0; i < 2; i++)
 87.3209 +		{
 87.3210 +			if(v1->lightmap[i] != v2->lightmap[i])
 87.3211 +				return qfalse;
 87.3212 +		}
 87.3213 +	}
 87.3214 +
 87.3215 +	for(i = 0; i < 4; i++)
 87.3216 +	{
 87.3217 +		if(v1->lightColor[i] != v2->lightColor[i])
 87.3218 +			return qfalse;
 87.3219 +	}
 87.3220 +
 87.3221 +	return qtrue;
 87.3222 +}
 87.3223 +
 87.3224 +static qboolean CompareLightVert(const srfVert_t * v1, const srfVert_t * v2)
 87.3225 +{
 87.3226 +	int             i;
 87.3227 +
 87.3228 +	for(i = 0; i < 3; i++)
 87.3229 +	{
 87.3230 +		//if(fabs(v1->xyz[i] - v2->xyz[i]) > EQUAL_EPSILON)
 87.3231 +		if(v1->xyz[i] != v2->xyz[i])
 87.3232 +			return qfalse;
 87.3233 +	}
 87.3234 +
 87.3235 +	for(i = 0; i < 2; i++)
 87.3236 +	{
 87.3237 +		if(v1->st[i] != v2->st[i])
 87.3238 +			return qfalse;
 87.3239 +	}
 87.3240 +
 87.3241 +	for(i = 0; i < 4; i++)
 87.3242 +	{
 87.3243 +		if(v1->paintColor[i] != v2->paintColor[i])
 87.3244 +			return qfalse;
 87.3245 +	}
 87.3246 +
 87.3247 +	return qtrue;
 87.3248 +}
 87.3249 +
 87.3250 +static qboolean CompareShadowVertAlphaTest(const srfVert_t * v1, const srfVert_t * v2)
 87.3251 +{
 87.3252 +	int             i;
 87.3253 +
 87.3254 +	for(i = 0; i < 3; i++)
 87.3255 +	{
 87.3256 +		//if(fabs(v1->xyz[i] - v2->xyz[i]) > EQUAL_EPSILON)
 87.3257 +		if(v1->xyz[i] != v2->xyz[i])
 87.3258 +			return qfalse;
 87.3259 +	}
 87.3260 +
 87.3261 +	for(i = 0; i < 2; i++)
 87.3262 +	{
 87.3263 +		if(v1->st[i] != v2->st[i])
 87.3264 +			return qfalse;
 87.3265 +	}
 87.3266 +
 87.3267 +	return qtrue;
 87.3268 +}
 87.3269 +
 87.3270 +static qboolean CompareShadowVert(const srfVert_t * v1, const srfVert_t * v2)
 87.3271 +{
 87.3272 +	int             i;
 87.3273 +
 87.3274 +	for(i = 0; i < 3; i++)
 87.3275 +	{
 87.3276 +		//if(fabs(v1->xyz[i] - v2->xyz[i]) > EQUAL_EPSILON)
 87.3277 +		if(v1->xyz[i] != v2->xyz[i])
 87.3278 +			return qfalse;
 87.3279 +	}
 87.3280 +
 87.3281 +	return qtrue;
 87.3282 +}
 87.3283 +
 87.3284 +static qboolean CompareShadowVolumeVert(const srfVert_t * v1, const srfVert_t * v2)
 87.3285 +{
 87.3286 +	int             i;
 87.3287 +
 87.3288 +	for(i = 0; i < 3; i++)
 87.3289 +	{
 87.3290 +		// don't consider epsilon to avoid shadow volume z-fighting
 87.3291 +		if(v1->xyz[i] != v2->xyz[i])
 87.3292 +			return qfalse;
 87.3293 +	}
 87.3294 +
 87.3295 +	return qtrue;
 87.3296 +}
 87.3297 +
 87.3298 +static qboolean CompareWorldVertSmoothNormal(const srfVert_t * v1, const srfVert_t * v2)
 87.3299 +{
 87.3300 +	int             i;
 87.3301 +
 87.3302 +	for(i = 0; i < 3; i++)
 87.3303 +	{
 87.3304 +		if(fabs(v1->xyz[i] - v2->xyz[i]) > EQUAL_EPSILON)
 87.3305 +			return qfalse;
 87.3306 +	}
 87.3307 +
 87.3308 +	return qtrue;
 87.3309 +}
 87.3310 +
 87.3311 +/*
 87.3312 +remove duplicated / redundant vertices from a batch of vertices
 87.3313 +return the new number of vertices
 87.3314 +*/
 87.3315 +static int OptimizeVertices(int numVerts, srfVert_t * verts, int numTriangles, srfTriangle_t * triangles, srfVert_t * outVerts,
 87.3316 +							qboolean(*CompareVert) (const srfVert_t * v1, const srfVert_t * v2))
 87.3317 +{
 87.3318 +	srfTriangle_t  *tri;
 87.3319 +	int             i, j, k, l;
 87.3320 +
 87.3321 +	static int      redundantIndex[MAX_MAP_DRAW_VERTS];
 87.3322 +	int             numOutVerts;
 87.3323 +
 87.3324 +	if(r_vboOptimizeVertices->integer)
 87.3325 +	{
 87.3326 +		if(numVerts >= MAX_MAP_DRAW_VERTS)
 87.3327 +		{
 87.3328 +			ri.Printf(PRINT_WARNING, "OptimizeVertices: MAX_MAP_DRAW_VERTS reached\n");
 87.3329 +			for(j = 0; j < numVerts; j++)
 87.3330 +			{
 87.3331 +				CopyVert(&verts[j], &outVerts[j]);
 87.3332 +			}
 87.3333 +			return numVerts;
 87.3334 +		}
 87.3335 +
 87.3336 +		memset(redundantIndex, -1, sizeof(redundantIndex));
 87.3337 +
 87.3338 +		c_redundantVertexes = 0;
 87.3339 +		numOutVerts = 0;
 87.3340 +		for(i = 0; i < numVerts; i++)
 87.3341 +		{
 87.3342 +#if DEBUG_OPTIMIZEVERTICES
 87.3343 +			verts[i].id = i;
 87.3344 +#endif
 87.3345 +			if(redundantIndex[i] == -1)
 87.3346 +			{
 87.3347 +				for(j = i + 1; j < numVerts; j++)
 87.3348 +				{
 87.3349 +					if(redundantIndex[i] != -1)
 87.3350 +						continue;
 87.3351 +
 87.3352 +					if(CompareVert(&verts[i], &verts[j]))
 87.3353 +					{
 87.3354 +						// mark vertex as redundant
 87.3355 +						redundantIndex[j] = i;	//numOutVerts;
 87.3356 +					}
 87.3357 +				}
 87.3358 +			}
 87.3359 +		}
 87.3360 +
 87.3361 +#if DEBUG_OPTIMIZEVERTICES
 87.3362 +		ri.Printf(PRINT_ALL, "input triangles: ");
 87.3363 +		for(k = 0, tri = triangles; k < numTriangles; k++, tri++)
 87.3364 +		{
 87.3365 +			ri.Printf(PRINT_ALL, "(%i,%i,%i),", verts[tri->indexes[0]].id, verts[tri->indexes[1]].id, verts[tri->indexes[2]].id);
 87.3366 +		}
 87.3367 +		ri.Printf(PRINT_ALL, "\n");
 87.3368 +#endif
 87.3369 +
 87.3370 +#if DEBUG_OPTIMIZEVERTICES
 87.3371 +		ri.Printf(PRINT_ALL, "input vertices: ");
 87.3372 +		for(i = 0; i < numVerts; i++)
 87.3373 +		{
 87.3374 +			if(redundantIndex[i] != -1)
 87.3375 +			{
 87.3376 +				ri.Printf(PRINT_ALL, "(%i,%i),", i, redundantIndex[i]);
 87.3377 +			}
 87.3378 +			else
 87.3379 +			{
 87.3380 +				ri.Printf(PRINT_ALL, "(%i,-),", i);
 87.3381 +			}
 87.3382 +		}
 87.3383 +		ri.Printf(PRINT_ALL, "\n");
 87.3384 +#endif
 87.3385 +
 87.3386 +		for(i = 0; i < numVerts; i++)
 87.3387 +		{
 87.3388 +			if(redundantIndex[i] != -1)
 87.3389 +			{
 87.3390 +				c_redundantVertexes++;
 87.3391 +			}
 87.3392 +			else
 87.3393 +			{
 87.3394 +				CopyVert(&verts[i], &outVerts[numOutVerts]);
 87.3395 +				numOutVerts++;
 87.3396 +			}
 87.3397 +		}
 87.3398 +
 87.3399 +#if DEBUG_OPTIMIZEVERTICES
 87.3400 +		ri.Printf(PRINT_ALL, "output vertices: ");
 87.3401 +		for(i = 0; i < numOutVerts; i++)
 87.3402 +		{
 87.3403 +			ri.Printf(PRINT_ALL, "(%i),", outVerts[i].id);
 87.3404 +		}
 87.3405 +		ri.Printf(PRINT_ALL, "\n");
 87.3406 +#endif
 87.3407 +
 87.3408 +		for(i = 0; i < numVerts;)
 87.3409 +		{
 87.3410 +			qboolean        noIncrement = qfalse;
 87.3411 +
 87.3412 +			if(redundantIndex[i] != -1)
 87.3413 +			{
 87.3414 +#if DEBUG_OPTIMIZEVERTICES
 87.3415 +				ri.Printf(PRINT_ALL, "-------------------------------------------------\n");
 87.3416 +				ri.Printf(PRINT_ALL, "changing triangles for redundant vertex (%i->%i):\n", i, redundantIndex[i]);
 87.3417 +#endif
 87.3418 +
 87.3419 +				// kill redundant vert
 87.3420 +				for(k = 0, tri = triangles; k < numTriangles; k++, tri++)
 87.3421 +				{
 87.3422 +					for(l = 0; l < 3; l++)
 87.3423 +					{
 87.3424 +						if(tri->indexes[l] == i)	//redundantIndex[i])
 87.3425 +						{
 87.3426 +							// replace duplicated index j with the original vertex index i
 87.3427 +							tri->indexes[l] = redundantIndex[i];	//numOutVerts;
 87.3428 +
 87.3429 +#if DEBUG_OPTIMIZEVERTICES
 87.3430 +							ri.Printf(PRINT_ALL, "mapTriangleIndex<%i,%i>(%i->%i)\n", k, l, i, redundantIndex[i]);
 87.3431 +#endif
 87.3432 +						}
 87.3433 +#if 1
 87.3434 +						else if(tri->indexes[l] > i)	// && redundantIndex[tri->indexes[l]] == -1)
 87.3435 +						{
 87.3436 +							tri->indexes[l]--;
 87.3437 +#if DEBUG_OPTIMIZEVERTICES
 87.3438 +							ri.Printf(PRINT_ALL, "decTriangleIndex<%i,%i>(%i->%i)\n", k, l, tri->indexes[l] + 1, tri->indexes[l]);
 87.3439 +#endif
 87.3440 +
 87.3441 +							if(tri->indexes[l] < 0)
 87.3442 +							{
 87.3443 +								ri.Printf(PRINT_WARNING, "OptimizeVertices: triangle index < 0\n");
 87.3444 +								for(j = 0; j < numVerts; j++)
 87.3445 +								{
 87.3446 +									CopyVert(&verts[j], &outVerts[j]);
 87.3447 +								}
 87.3448 +								return numVerts;
 87.3449 +							}
 87.3450 +						}
 87.3451 +#endif
 87.3452 +					}
 87.3453 +				}
 87.3454 +
 87.3455 +#if DEBUG_OPTIMIZEVERTICES
 87.3456 +				ri.Printf(PRINT_ALL, "pending redundant vertices: ");
 87.3457 +				for(j = i + 1; j < numVerts; j++)
 87.3458 +				{
 87.3459 +					if(redundantIndex[j] != -1)
 87.3460 +					{
 87.3461 +						ri.Printf(PRINT_ALL, "(%i,%i),", j, redundantIndex[j]);
 87.3462 +					}
 87.3463 +					else
 87.3464 +					{
 87.3465 +						//ri.Printf(PRINT_ALL, "(%i,-),", j);
 87.3466 +					}
 87.3467 +				}
 87.3468 +				ri.Printf(PRINT_ALL, "\n");
 87.3469 +#endif
 87.3470 +
 87.3471 +
 87.3472 +				for(j = i + 1; j < numVerts; j++)
 87.3473 +				{
 87.3474 +					if(redundantIndex[j] != -1)	//> i)//== tri->indexes[l])
 87.3475 +					{
 87.3476 +#if DEBUG_OPTIMIZEVERTICES
 87.3477 +						ri.Printf(PRINT_ALL, "updateRedundantIndex(%i->%i) to (%i->%i)\n", j, redundantIndex[j], j - 1,
 87.3478 +								  redundantIndex[j]);
 87.3479 +#endif
 87.3480 +
 87.3481 +						if(redundantIndex[j] <= i)
 87.3482 +						{
 87.3483 +							redundantIndex[j - 1] = redundantIndex[j];
 87.3484 +							redundantIndex[j] = -1;
 87.3485 +						}
 87.3486 +						else
 87.3487 +						{
 87.3488 +							redundantIndex[j - 1] = redundantIndex[j] - 1;
 87.3489 +							redundantIndex[j] = -1;
 87.3490 +						}
 87.3491 +
 87.3492 +						if((j - 1) == i)
 87.3493 +						{
 87.3494 +							noIncrement = qtrue;
 87.3495 +						}
 87.3496 +					}
 87.3497 +				}
 87.3498 +
 87.3499 +#if DEBUG_OPTIMIZEVERTICES
 87.3500 +				ri.Printf(PRINT_ALL, "current triangles: ");
 87.3501 +				for(k = 0, tri = triangles; k < numTriangles; k++, tri++)
 87.3502 +				{
 87.3503 +					ri.Printf(PRINT_ALL, "(%i,%i,%i),", verts[tri->indexes[0]].id, verts[tri->indexes[1]].id,
 87.3504 +							  verts[tri->indexes[2]].id);
 87.3505 +				}
 87.3506 +				ri.Printf(PRINT_ALL, "\n");
 87.3507 +#endif
 87.3508 +			}
 87.3509 +
 87.3510 +			if(!noIncrement)
 87.3511 +			{
 87.3512 +				i++;
 87.3513 +			}
 87.3514 +		}
 87.3515 +
 87.3516 +#if DEBUG_OPTIMIZEVERTICES
 87.3517 +		ri.Printf(PRINT_ALL, "output triangles: ");
 87.3518 +		for(k = 0, tri = triangles; k < numTriangles; k++, tri++)
 87.3519 +		{
 87.3520 +			ri.Printf(PRINT_ALL, "(%i,%i,%i),", verts[tri->indexes[0]].id, verts[tri->indexes[1]].id, verts[tri->indexes[2]].id);
 87.3521 +		}
 87.3522 +		ri.Printf(PRINT_ALL, "\n");
 87.3523 +#endif
 87.3524 +
 87.3525 +		if(c_redundantVertexes)
 87.3526 +		{
 87.3527 +			//*numVerts -= c_redundantVertexes;
 87.3528 +
 87.3529 +			//ri.Printf(PRINT_ALL, "removed %i redundant vertices\n", c_redundantVertexes);
 87.3530 +		}
 87.3531 +
 87.3532 +		return numOutVerts;
 87.3533 +	}
 87.3534 +	else
 87.3535 +	{
 87.3536 +		for(j = 0; j < numVerts; j++)
 87.3537 +		{
 87.3538 +			CopyVert(&verts[j], &outVerts[j]);
 87.3539 +		}
 87.3540 +		return numVerts;
 87.3541 +	}
 87.3542 +}
 87.3543 +
 87.3544 +static void OptimizeTriangles(int numVerts, srfVert_t * verts, int numTriangles, srfTriangle_t * triangles,
 87.3545 +							  qboolean(*compareVert) (const srfVert_t * v1, const srfVert_t * v2))
 87.3546 +{
 87.3547 +#if 1
 87.3548 +	srfTriangle_t  *tri;
 87.3549 +	int             i, j, k, l;
 87.3550 +	static int      redundantIndex[MAX_MAP_DRAW_VERTS];
 87.3551 +	static          qboolean(*compareFunction) (const srfVert_t * v1, const srfVert_t * v2) = NULL;
 87.3552 +	static int      minVertOld = 9999999, maxVertOld = 0;
 87.3553 +	int             minVert, maxVert;
 87.3554 +
 87.3555 +	if(numVerts >= MAX_MAP_DRAW_VERTS)
 87.3556 +	{
 87.3557 +		ri.Printf(PRINT_WARNING, "OptimizeTriangles: MAX_MAP_DRAW_VERTS reached\n");
 87.3558 +		return;
 87.3559 +	}
 87.3560 +
 87.3561 +	// find vertex bounds
 87.3562 +	maxVert = 0;
 87.3563 +	minVert = numVerts - 1;
 87.3564 +	for(k = 0, tri = triangles; k < numTriangles; k++, tri++)
 87.3565 +	{
 87.3566 +		for(l = 0; l < 3; l++)
 87.3567 +		{
 87.3568 +			if(tri->indexes[l] > maxVert)
 87.3569 +				maxVert = tri->indexes[l];
 87.3570 +
 87.3571 +			if(tri->indexes[l] < minVert)
 87.3572 +				minVert = tri->indexes[l];
 87.3573 +		}
 87.3574 +	}
 87.3575 +
 87.3576 +	ri.Printf(PRINT_ALL, "OptimizeTriangles: minVert %i maxVert %i\n", minVert, maxVert);
 87.3577 +
 87.3578 +//  if(compareFunction != compareVert || minVert != minVertOld || maxVert != maxVertOld)
 87.3579 +	{
 87.3580 +		compareFunction = compareVert;
 87.3581 +
 87.3582 +		memset(redundantIndex, -1, sizeof(redundantIndex));
 87.3583 +
 87.3584 +		for(i = minVert; i <= maxVert; i++)
 87.3585 +		{
 87.3586 +			if(redundantIndex[i] == -1)
 87.3587 +			{
 87.3588 +				for(j = i + 1; j <= maxVert; j++)
 87.3589 +				{
 87.3590 +					if(redundantIndex[i] != -1)
 87.3591 +						continue;
 87.3592 +
 87.3593 +					if(compareVert(&verts[i], &verts[j]))
 87.3594 +					{
 87.3595 +						// mark vertex as redundant
 87.3596 +						redundantIndex[j] = i;
 87.3597 +					}
 87.3598 +				}
 87.3599 +			}
 87.3600 +		}
 87.3601 +	}
 87.3602 +
 87.3603 +	c_redundantVertexes = 0;
 87.3604 +	for(i = minVert; i <= maxVert; i++)
 87.3605 +	{
 87.3606 +		if(redundantIndex[i] != -1)
 87.3607 +		{
 87.3608 +			//ri.Printf(PRINT_ALL, "changing triangles for redundant vertex (%i->%i):\n", i, redundantIndex[i]);
 87.3609 +
 87.3610 +			// kill redundant vert
 87.3611 +			for(k = 0, tri = triangles; k < numTriangles; k++, tri++)
 87.3612 +			{
 87.3613 +				for(l = 0; l < 3; l++)
 87.3614 +				{
 87.3615 +					if(tri->indexes[l] == i)	//redundantIndex[i])
 87.3616 +					{
 87.3617 +						// replace duplicated index j with the original vertex index i
 87.3618 +						tri->indexes[l] = redundantIndex[i];
 87.3619 +
 87.3620 +						//ri.Printf(PRINT_ALL, "mapTriangleIndex<%i,%i>(%i->%i)\n", k, l, i, redundantIndex[i]);
 87.3621 +					}
 87.3622 +				}
 87.3623 +			}
 87.3624 +
 87.3625 +			c_redundantVertexes++;
 87.3626 +		}
 87.3627 +	}
 87.3628 +
 87.3629 +#if 0
 87.3630 +	ri.Printf(PRINT_ALL, "vertices: ");
 87.3631 +	for(i = 0; i < numVerts; i++)
 87.3632 +	{
 87.3633 +		if(redundantIndex[i] != -1)
 87.3634 +		{
 87.3635 +			ri.Printf(PRINT_ALL, "(%i,%i),", i, redundantIndex[i]);
 87.3636 +		}
 87.3637 +		else
 87.3638 +		{
 87.3639 +			ri.Printf(PRINT_ALL, "(%i,-),", i);
 87.3640 +		}
 87.3641 +	}
 87.3642 +	ri.Printf(PRINT_ALL, "\n");
 87.3643 +
 87.3644 +	ri.Printf(PRINT_ALL, "triangles: ");
 87.3645 +	for(k = 0, tri = triangles; k < numTriangles; k++, tri++)
 87.3646 +	{
 87.3647 +		ri.Printf(PRINT_ALL, "(%i,%i,%i),", tri->indexes[0], tri->indexes[1], tri->indexes[2]);
 87.3648 +	}
 87.3649 +	ri.Printf(PRINT_ALL, "\n");
 87.3650 +#endif
 87.3651 +
 87.3652 +	if(c_redundantVertexes)
 87.3653 +	{
 87.3654 +		//*numVerts -= c_redundantVertexes;
 87.3655 +
 87.3656 +		//ri.Printf(PRINT_ALL, "removed %i redundant vertices\n", c_redundantVertexes);
 87.3657 +	}
 87.3658 +#endif
 87.3659 +}
 87.3660 +
 87.3661 +static void OptimizeTrianglesLite(const int *redundantIndex, int numTriangles, srfTriangle_t * triangles)
 87.3662 +{
 87.3663 +	srfTriangle_t  *tri;
 87.3664 +	int             k, l;
 87.3665 +
 87.3666 +	c_redundantVertexes = 0;
 87.3667 +	for(k = 0, tri = triangles; k < numTriangles; k++, tri++)
 87.3668 +	{
 87.3669 +		for(l = 0; l < 3; l++)
 87.3670 +		{
 87.3671 +			if(redundantIndex[tri->indexes[l]] != -1)
 87.3672 +			{
 87.3673 +				// replace duplicated index j with the original vertex index i
 87.3674 +				tri->indexes[l] = redundantIndex[tri->indexes[l]];
 87.3675 +
 87.3676 +				//ri.Printf(PRINT_ALL, "mapTriangleIndex<%i,%i>(%i->%i)\n", k, l, tri->indexes[l], redundantIndex[tri->indexes[l]]);
 87.3677 +
 87.3678 +				c_redundantVertexes++;
 87.3679 +			}
 87.3680 +		}
 87.3681 +	}
 87.3682 +}
 87.3683 +
 87.3684 +static void BuildRedundantIndices(int numVerts, const srfVert_t * verts, int *redundantIndex,
 87.3685 +								  qboolean(*CompareVert) (const srfVert_t * v1, const srfVert_t * v2))
 87.3686 +{
 87.3687 +	int             i, j;
 87.3688 +
 87.3689 +	memset(redundantIndex, -1, numVerts * sizeof(int));
 87.3690 +
 87.3691 +	for(i = 0; i < numVerts; i++)
 87.3692 +	{
 87.3693 +		if(redundantIndex[i] == -1)
 87.3694 +		{
 87.3695 +			for(j = i + 1; j < numVerts; j++)
 87.3696 +			{
 87.3697 +				if(redundantIndex[j] != -1)
 87.3698 +					continue;
 87.3699 +
 87.3700 +				if(CompareVert(&verts[i], &verts[j]))
 87.3701 +				{
 87.3702 +					// mark vertex as redundant
 87.3703 +					redundantIndex[j] = i;
 87.3704 +				}
 87.3705 +			}
 87.3706 +		}
 87.3707 +	}
 87.3708 +}
 87.3709 +
 87.3710 +
 87.3711 +
 87.3712 +/*
 87.3713 +static void R_LoadAreaPortals(const char *bspName)
 87.3714 +{
 87.3715 +	int             i, j, k;
 87.3716 +	char            fileName[MAX_QPATH];
 87.3717 +	char           *token;
 87.3718 +	char           *buf_p;
 87.3719 +	byte           *buffer;
 87.3720 +	int             bufferLen;
 87.3721 +	const char     *version = "AREAPRT1";
 87.3722 +	int             numAreas;
 87.3723 +	int             numAreaPortals;
 87.3724 +	int             numPoints;
 87.3725 +
 87.3726 +	bspAreaPortal_t *ap;
 87.3727 +
 87.3728 +	Q_strncpyz(fileName, bspName, sizeof(fileName));
 87.3729 +	Com_StripExtension(fileName, fileName, sizeof(fileName));
 87.3730 +	Q_strcat(fileName, sizeof(fileName), ".areaprt");
 87.3731 +
 87.3732 +	bufferLen = ri.FS_ReadFile(fileName, (void **)&buffer);
 87.3733 +	if(!buffer)
 87.3734 +	{
 87.3735 +		ri.Printf(PRINT_WARNING, "WARNING: could not load area portals file '%s'\n", fileName);
 87.3736 +		return;
 87.3737 +	}
 87.3738 +
 87.3739 +	buf_p = (char *)buffer;
 87.3740 +
 87.3741 +	// check version
 87.3742 +	token = Com_ParseExt(&buf_p, qfalse);
 87.3743 +	if(strcmp(token, version))
 87.3744 +	{
 87.3745 +		ri.Printf(PRINT_WARNING, "R_LoadAreaPortals: %s has wrong version (%i should be %i)\n", fileName, token, version);
 87.3746 +		return;
 87.3747 +	}
 87.3748 +
 87.3749 +	// load areas num
 87.3750 +	token = Com_ParseExt(&buf_p, qtrue);
 87.3751 +	numAreas = atoi(token);
 87.3752 +	if(numAreas != s_worldData.numAreas)
 87.3753 +	{
 87.3754 +		ri.Printf(PRINT_WARNING, "R_LoadAreaPortals: %s has wrong number of areas (%i should be %i)\n", fileName, numAreas,
 87.3755 +				  s_worldData.numAreas);
 87.3756 +		return;
 87.3757 +	}
 87.3758 +
 87.3759 +	// load areas portals
 87.3760 +	token = Com_ParseExt(&buf_p, qtrue);
 87.3761 +	numAreaPortals = atoi(token);
 87.3762 +
 87.3763 +	ri.Printf(PRINT_ALL, "...loading %i area portals\n", numAreaPortals);
 87.3764 +
 87.3765 +	s_worldData.numAreaPortals = numAreaPortals;
 87.3766 +	s_worldData.areaPortals = ri.Hunk_Alloc(numAreaPortals * sizeof(*s_worldData.areaPortals), h_low);
 87.3767 +
 87.3768 +	for(i = 0, ap = s_worldData.areaPortals; i < numAreaPortals; i++, ap++)
 87.3769 +	{
 87.3770 +		token = Com_ParseExt(&buf_p, qtrue);
 87.3771 +		numPoints = atoi(token);
 87.3772 +
 87.3773 +		if(numPoints != 4)
 87.3774 +		{
 87.3775 +			ri.Printf(PRINT_WARNING, "R_LoadAreaPortals: expected 4 found '%s' in file '%s'\n", token, fileName);
 87.3776 +			return;
 87.3777 +		}
 87.3778 +
 87.3779 +		Com_ParseExt(&buf_p, qfalse);
 87.3780 +		ap->areas[0] = atoi(token);
 87.3781 +
 87.3782 +		Com_ParseExt(&buf_p, qfalse);
 87.3783 +		ap->areas[1] = atoi(token);
 87.3784 +
 87.3785 +		for(j = 0; j < numPoints; j++)
 87.3786 +		{
 87.3787 +			// skip (
 87.3788 +			token = Com_ParseExt(&buf_p, qfalse);
 87.3789 +			if(Q_stricmp(token, "("))
 87.3790 +			{
 87.3791 +				ri.Printf(PRINT_WARNING, "R_LoadAreaPortals: expected '(' found '%s' in file '%s'\n", token, fileName);
 87.3792 +				return;
 87.3793 +			}
 87.3794 +
 87.3795 +			for(k = 0; k < 3; k++)
 87.3796 +			{
 87.3797 +				token = Com_ParseExt(&buf_p, qfalse);
 87.3798 +				ap->points[j][k] = atof(token);
 87.3799 +			}
 87.3800 +
 87.3801 +			// skip )
 87.3802 +			token = Com_ParseExt(&buf_p, qfalse);
 87.3803 +			if(Q_stricmp(token, ")"))
 87.3804 +			{
 87.3805 +				ri.Printf(PRINT_WARNING, "R_LoadAreaPortals: expected ')' found '%s' in file '%s'\n", token, fileName);
 87.3806 +				return;
 87.3807 +			}
 87.3808 +		}
 87.3809 +	}
 87.3810 +}
 87.3811 +*/
 87.3812 +
 87.3813 +/*
 87.3814 +=================
 87.3815 +R_CreateAreas
 87.3816 +=================
 87.3817 +*/
 87.3818 +/*
 87.3819 +static void R_CreateAreas()
 87.3820 +{
 87.3821 +	int             i, j;
 87.3822 +	int             numAreas, maxArea;
 87.3823 +	bspNode_t      *node;
 87.3824 +	bspArea_t      *area;
 87.3825 +	growList_t      areaSurfaces;
 87.3826 +	int             c;
 87.3827 +	bspSurface_t   *surface, **mark;
 87.3828 +	int             surfaceNum;
 87.3829 +
 87.3830 +
 87.3831 +	ri.Printf(PRINT_ALL, "...creating BSP areas\n");
 87.3832 +
 87.3833 +	// go through the leaves and count areas
 87.3834 +	maxArea = 0;
 87.3835 +
 87.3836 +	for(i = 0, node = s_worldData.nodes; i < s_worldData.numnodes; i++, node++)
 87.3837 +	{
 87.3838 +		if(node->contents == CONTENTS_NODE)
 87.3839 +			continue;
 87.3840 +
 87.3841 +		if(node->area == -1)
 87.3842 +			continue;
 87.3843 +
 87.3844 +		if(node->area > maxArea)
 87.3845 +			maxArea = node->area;
 87.3846 +	}
 87.3847 +
 87.3848 +	numAreas = maxArea + 1;
 87.3849 +
 87.3850 +	s_worldData.numAreas = numAreas;
 87.3851 +	s_worldData.areas = ri.Hunk_Alloc(numAreas * sizeof(*s_worldData.areas), h_low);
 87.3852 +
 87.3853 +	// reset surfaces' viewCount
 87.3854 +	for(i = 0, surface = s_worldData.surfaces; i < s_worldData.numSurfaces; i++, surface++)
 87.3855 +	{
 87.3856 +		surface->viewCount = -1;
 87.3857 +	}
 87.3858 +
 87.3859 +	// add area surfaces
 87.3860 +	for(i = 0; i < numAreas; i++)
 87.3861 +	{
 87.3862 +		area = &s_worldData.areas[i];
 87.3863 +
 87.3864 +		Com_InitGrowList(&areaSurfaces, 100);
 87.3865 +
 87.3866 +		for(j = 0, node = s_worldData.nodes; j < s_worldData.numnodes; j++, node++)
 87.3867 +		{
 87.3868 +			if(node->contents == CONTENTS_NODE)
 87.3869 +				continue;
 87.3870 +
 87.3871 +			if(node->area != i)
 87.3872 +				continue;
 87.3873 +
 87.3874 +			if(node->cluster < 0)
 87.3875 +				continue;
 87.3876 +
 87.3877 +			// add the individual surfaces
 87.3878 +			mark = node->markSurfaces;
 87.3879 +			c = node->numMarkSurfaces;
 87.3880 +			while(c--)
 87.3881 +			{
 87.3882 +				// the surface may have already been added if it
 87.3883 +				// spans multiple leafs
 87.3884 +				surface = *mark;
 87.3885 +
 87.3886 +				surfaceNum = surface - s_worldData.surfaces;
 87.3887 +
 87.3888 +				if((surface->viewCount != (i + 1)) && (surfaceNum < s_worldData.numWorldSurfaces))
 87.3889 +				{
 87.3890 +					surface->viewCount = i + 1;
 87.3891 +					Com_AddToGrowList(&areaSurfaces, surface);
 87.3892 +				}
 87.3893 +
 87.3894 +				mark++;
 87.3895 +			}
 87.3896 +		}
 87.3897 +
 87.3898 +		// move area surfaces list to hunk
 87.3899 +		area->numMarkSurfaces = areaSurfaces.currentElements;
 87.3900 +		area->markSurfaces = ri.Hunk_Alloc(area->numMarkSurfaces * sizeof(*area->markSurfaces), h_low);
 87.3901 +
 87.3902 +		for(j = 0; j < area->numMarkSurfaces; j++)
 87.3903 +		{
 87.3904 +			area->markSurfaces[j] = (bspSurface_t *) Com_GrowListElement(&areaSurfaces, j);
 87.3905 +		}
 87.3906 +
 87.3907 +		Com_DestroyGrowList(&areaSurfaces);
 87.3908 +
 87.3909 +		ri.Printf(PRINT_ALL, "area %i contains %i bsp surfaces\n", i, area->numMarkSurfaces);
 87.3910 +	}
 87.3911 +
 87.3912 +	ri.Printf(PRINT_ALL, "%i world areas created\n", numAreas);
 87.3913 +}
 87.3914 +*/
 87.3915 +
 87.3916 +/*
 87.3917 +===============
 87.3918 +R_CreateVBOWorldSurfaces
 87.3919 +===============
 87.3920 +*/
 87.3921 +/*
 87.3922 +static void R_CreateVBOWorldSurfaces()
 87.3923 +{
 87.3924 +	int             i, j, k, l, a;
 87.3925 +
 87.3926 +	int             numVerts;
 87.3927 +	srfVert_t      *verts;
 87.3928 +
 87.3929 +	srfVert_t      *optimizedVerts;
 87.3930 +
 87.3931 +	int             numTriangles;
 87.3932 +	srfTriangle_t  *triangles;
 87.3933 +
 87.3934 +	shader_t       *shader, *oldShader;
 87.3935 +	int             lightmapNum, oldLightmapNum;
 87.3936 +
 87.3937 +	int             numSurfaces;
 87.3938 +	bspSurface_t   *surface, *surface2;
 87.3939 +	bspSurface_t  **surfacesSorted;
 87.3940 +
 87.3941 +	bspArea_t      *area;
 87.3942 +
 87.3943 +	growList_t      vboSurfaces;
 87.3944 +	srfVBOMesh_t   *vboSurf;
 87.3945 +
 87.3946 +	if(!glConfig.vertexBufferObjectAvailable)
 87.3947 +		return;
 87.3948 +
 87.3949 +	for(a = 0, area = s_worldData.areas; a < s_worldData.numAreas; a++, area++)
 87.3950 +	{
 87.3951 +		// count number of static area surfaces
 87.3952 +		numSurfaces = 0;
 87.3953 +		for(k = 0; k < area->numMarkSurfaces; k++)
 87.3954 +		{
 87.3955 +			surface = area->markSurfaces[k];
 87.3956 +			shader = surface->shader;
 87.3957 +
 87.3958 +			if(shader->isSky)
 87.3959 +				continue;
 87.3960 +
 87.3961 +			if(shader->isPortal || shader->isMirror)
 87.3962 +				continue;
 87.3963 +
 87.3964 +			if(shader->numDeforms)
 87.3965 +				continue;
 87.3966 +
 87.3967 +			numSurfaces++;
 87.3968 +		}
 87.3969 +
 87.3970 +		if(!numSurfaces)
 87.3971 +			continue;
 87.3972 +
 87.3973 +		// build interaction caches list
 87.3974 +		surfacesSorted = ri.Hunk_AllocateTempMemory(numSurfaces * sizeof(surfacesSorted[0]));
 87.3975 +
 87.3976 +		numSurfaces = 0;
 87.3977 +		for(k = 0; k < area->numMarkSurfaces; k++)
 87.3978 +		{
 87.3979 +			surface = area->markSurfaces[k];
 87.3980 +			shader = surface->shader;
 87.3981 +
 87.3982 +			if(shader->isSky)
 87.3983 +				continue;
 87.3984 +
 87.3985 +			if(shader->isPortal || shader->isMirror)
 87.3986 +				continue;
 87.3987 +
 87.3988 +			if(shader->numDeforms)
 87.3989 +				continue;
 87.3990 +
 87.3991 +			surfacesSorted[numSurfaces] = surface;
 87.3992 +			numSurfaces++;
 87.3993 +		}
 87.3994 +
 87.3995 +		Com_InitGrowList(&vboSurfaces, 100);
 87.3996 +
 87.3997 +		// sort surfaces by shader
 87.3998 +		qsort(surfacesSorted, numSurfaces, sizeof(surfacesSorted), BSPSurfaceCompare);
 87.3999 +
 87.4000 +		// create a VBO for each shader
 87.4001 +		shader = oldShader = NULL;
 87.4002 +		lightmapNum = oldLightmapNum = -1;
 87.4003 +
 87.4004 +		for(k = 0; k < numSurfaces; k++)
 87.4005 +		{
 87.4006 +			surface = surfacesSorted[k];
 87.4007 +			shader = surface->shader;
 87.4008 +			lightmapNum = surface->lightmapNum;
 87.4009 +
 87.4010 +			if(shader != oldShader || (r_precomputedLighting->integer ? lightmapNum != oldLightmapNum : 0))
 87.4011 +			{
 87.4012 +				oldShader = shader;
 87.4013 +				oldLightmapNum = lightmapNum;
 87.4014 +
 87.4015 +				// count vertices and indices
 87.4016 +				numVerts = 0;
 87.4017 +				numTriangles = 0;
 87.4018 +
 87.4019 +				for(l = k; l < numSurfaces; l++)
 87.4020 +				{
 87.4021 +					surface2 = surfacesSorted[l];
 87.4022 +
 87.4023 +					if(surface2->shader != shader)
 87.4024 +						continue;
 87.4025 +
 87.4026 +					if(*surface2->data == SF_FACE)
 87.4027 +					{
 87.4028 +						srfSurfaceFace_t *face = (srfSurfaceFace_t *) surface2->data;
 87.4029 +
 87.4030 +						if(face->numVerts)
 87.4031 +							numVerts += face->numVerts;
 87.4032 +
 87.4033 +						if(face->numTriangles)
 87.4034 +							numTriangles += face->numTriangles;
 87.4035 +					}
 87.4036 +					else if(*surface2->data == SF_GRID)
 87.4037 +					{
 87.4038 +						srfGridMesh_t  *grid = (srfGridMesh_t *) surface2->data;
 87.4039 +
 87.4040 +						if(grid->numVerts)
 87.4041 +							numVerts += grid->numVerts;
 87.4042 +
 87.4043 +						if(grid->numTriangles)
 87.4044 +							numTriangles += grid->numTriangles;
 87.4045 +					}
 87.4046 +					else if(*surface2->data == SF_TRIANGLES)
 87.4047 +					{
 87.4048 +						srfTriangles_t *tri = (srfTriangles_t *) surface2->data;
 87.4049 +
 87.4050 +						if(tri->numVerts)
 87.4051 +							numVerts += tri->numVerts;
 87.4052 +
 87.4053 +						if(tri->numTriangles)
 87.4054 +							numTriangles += tri->numTriangles;
 87.4055 +					}
 87.4056 +				}
 87.4057 +
 87.4058 +				if(!numVerts || !numTriangles)
 87.4059 +					continue;
 87.4060 +
 87.4061 +				ri.Printf(PRINT_DEVELOPER, "...calculating world mesh VBOs ( %s, %i verts %i tris )\n", shader->name, numVerts,
 87.4062 +						  numTriangles);
 87.4063 +
 87.4064 +				// create surface
 87.4065 +				vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low);
 87.4066 +				Com_AddToGrowList(&vboSurfaces, vboSurf);
 87.4067 +
 87.4068 +				vboSurf->surfaceType = SF_VBO_MESH;
 87.4069 +				vboSurf->numIndexes = numTriangles * 3;
 87.4070 +				vboSurf->numVerts = numVerts;
 87.4071 +
 87.4072 +				vboSurf->shader = shader;
 87.4073 +				vboSurf->lightmapNum = lightmapNum;
 87.4074 +
 87.4075 +				// create arrays
 87.4076 +				verts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t));
 87.4077 +				optimizedVerts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t));
 87.4078 +				numVerts = 0;
 87.4079 +
 87.4080 +				triangles = ri.Hunk_AllocateTempMemory(numTriangles * sizeof(srfTriangle_t));
 87.4081 +				numTriangles = 0;
 87.4082 +
 87.4083 +				ClearBounds(vboSurf->bounds[0], vboSurf->bounds[1]);
 87.4084 +
 87.4085 +				// build triangle indices
 87.4086 +				for(l = k; l < numSurfaces; l++)
 87.4087 +				{
 87.4088 +					surface2 = surfacesSorted[l];
 87.4089 +
 87.4090 +					if(surface2->shader != shader)
 87.4091 +						continue;
 87.4092 +
 87.4093 +					// set up triangle indices
 87.4094 +					if(*surface2->data == SF_FACE)
 87.4095 +					{
 87.4096 +						srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface2->data;
 87.4097 +
 87.4098 +						if(srf->numTriangles)
 87.4099 +						{
 87.4100 +							srfTriangle_t  *tri;
 87.4101 +
 87.4102 +							for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
 87.4103 +							{
 87.4104 +								for(j = 0; j < 3; j++)
 87.4105 +								{
 87.4106 +									triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
 87.4107 +								}
 87.4108 +							}
 87.4109 +
 87.4110 +							numTriangles += srf->numTriangles;
 87.4111 +						}
 87.4112 +
 87.4113 +						if(srf->numVerts)
 87.4114 +							numVerts += srf->numVerts;
 87.4115 +					}
 87.4116 +					else if(*surface2->data == SF_GRID)
 87.4117 +					{
 87.4118 +						srfGridMesh_t  *srf = (srfGridMesh_t *) surface2->data;
 87.4119 +
 87.4120 +						if(srf->numTriangles)
 87.4121 +						{
 87.4122 +							srfTriangle_t  *tri;
 87.4123 +
 87.4124 +							for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
 87.4125 +							{
 87.4126 +								for(j = 0; j < 3; j++)
 87.4127 +								{
 87.4128 +									triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
 87.4129 +								}
 87.4130 +							}
 87.4131 +
 87.4132 +							numTriangles += srf->numTriangles;
 87.4133 +						}
 87.4134 +
 87.4135 +						if(srf->numVerts)
 87.4136 +							numVerts += srf->numVerts;
 87.4137 +					}
 87.4138 +					else if(*surface2->data == SF_TRIANGLES)
 87.4139 +					{
 87.4140 +						srfTriangles_t *srf = (srfTriangles_t *) surface2->data;
 87.4141 +
 87.4142 +						if(srf->numTriangles)
 87.4143 +						{
 87.4144 +							srfTriangle_t  *tri;
 87.4145 +
 87.4146 +							for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
 87.4147 +							{
 87.4148 +								for(j = 0; j < 3; j++)
 87.4149 +								{
 87.4150 +									triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
 87.4151 +								}
 87.4152 +							}
 87.4153 +
 87.4154 +							numTriangles += srf->numTriangles;
 87.4155 +						}
 87.4156 +
 87.4157 +						if(srf->numVerts)
 87.4158 +							numVerts += srf->numVerts;
 87.4159 +					}
 87.4160 +				}
 87.4161 +
 87.4162 +				// build vertices
 87.4163 +				numVerts = 0;
 87.4164 +				for(l = k; l < numSurfaces; l++)
 87.4165 +				{
 87.4166 +					surface2 = surfacesSorted[l];
 87.4167 +
 87.4168 +					if(surface2->shader != shader)
 87.4169 +						continue;
 87.4170 +
 87.4171 +					if(*surface2->data == SF_FACE)
 87.4172 +					{
 87.4173 +						srfSurfaceFace_t *cv = (srfSurfaceFace_t *) surface2->data;
 87.4174 +
 87.4175 +						if(cv->numVerts)
 87.4176 +						{
 87.4177 +							for(i = 0; i < cv->numVerts; i++)
 87.4178 +							{
 87.4179 +								CopyVert(&cv->verts[i], &verts[numVerts + i]);
 87.4180 +
 87.4181 +								AddPointToBounds(cv->verts[i].xyz, vboSurf->bounds[0], vboSurf->bounds[1]);
 87.4182 +							}
 87.4183 +
 87.4184 +							numVerts += cv->numVerts;
 87.4185 +						}
 87.4186 +					}
 87.4187 +					else if(*surface2->data == SF_GRID)
 87.4188 +					{
 87.4189 +						srfGridMesh_t  *cv = (srfGridMesh_t *) surface2->data;
 87.4190 +
 87.4191 +						if(cv->numVerts)
 87.4192 +						{
 87.4193 +							for(i = 0; i < cv->numVerts; i++)
 87.4194 +							{
 87.4195 +								CopyVert(&cv->verts[i], &verts[numVerts + i]);
 87.4196 +
 87.4197 +								AddPointToBounds(cv->verts[i].xyz, vboSurf->bounds[0], vboSurf->bounds[1]);
 87.4198 +							}
 87.4199 +
 87.4200 +							numVerts += cv->numVerts;
 87.4201 +						}
 87.4202 +					}
 87.4203 +					else if(*surface2->data == SF_TRIANGLES)
 87.4204 +					{
 87.4205 +						srfTriangles_t *cv = (srfTriangles_t *) surface2->data;
 87.4206 +
 87.4207 +						if(cv->numVerts)
 87.4208 +						{
 87.4209 +							for(i = 0; i < cv->numVerts; i++)
 87.4210 +							{
 87.4211 +								CopyVert(&cv->verts[i], &verts[numVerts + i]);
 87.4212 +
 87.4213 +								AddPointToBounds(cv->verts[i].xyz, vboSurf->bounds[0], vboSurf->bounds[1]);
 87.4214 +							}
 87.4215 +
 87.4216 +							numVerts += cv->numVerts;
 87.4217 +						}
 87.4218 +					}
 87.4219 +				}
 87.4220 +
 87.4221 +				numVerts = OptimizeVertices(numVerts, verts, numTriangles, triangles, optimizedVerts, CompareWorldVert);
 87.4222 +				if(c_redundantVertexes)
 87.4223 +				{
 87.4224 +					ri.Printf(PRINT_DEVELOPER,
 87.4225 +							  "...removed %i redundant vertices from staticWorldMesh %i ( %s, %i verts %i tris )\n",
 87.4226 +							  c_redundantVertexes, vboSurfaces.currentElements, shader->name, numVerts, numTriangles);
 87.4227 +				}
 87.4228 +
 87.4229 +				vboSurf->vbo = R_CreateVBO2(va("staticWorldMesh_vertices %i", vboSurfaces.currentElements), numVerts, optimizedVerts,
 87.4230 +									   ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BINORMAL | ATTR_NORMAL
 87.4231 +									   | ATTR_COLOR);
 87.4232 +
 87.4233 +				vboSurf->ibo = R_CreateIBO2(va("staticWorldMesh_indices %i", vboSurfaces.currentElements), numTriangles, triangles);
 87.4234 +
 87.4235 +				ri.Hunk_FreeTempMemory(triangles);
 87.4236 +				ri.Hunk_FreeTempMemory(optimizedVerts);
 87.4237 +				ri.Hunk_FreeTempMemory(verts);
 87.4238 +			}
 87.4239 +		}
 87.4240 +
 87.4241 +		ri.Hunk_FreeTempMemory(surfacesSorted);
 87.4242 +
 87.4243 +		// move VBO surfaces list to hunk
 87.4244 +		area->numVBOSurfaces = vboSurfaces.currentElements;
 87.4245 +		area->vboSurfaces = ri.Hunk_Alloc(area->numVBOSurfaces * sizeof(*area->vboSurfaces), h_low);
 87.4246 +
 87.4247 +		for(i = 0; i < area->numVBOSurfaces; i++)
 87.4248 +		{
 87.4249 +			area->vboSurfaces[i] = (srfVBOMesh_t *) Com_GrowListElement(&vboSurfaces, i);
 87.4250 +		}
 87.4251 +
 87.4252 +		Com_DestroyGrowList(&vboSurfaces);
 87.4253 +
 87.4254 +		ri.Printf(PRINT_ALL, "%i VBO surfaces created for area %i\n", area->numVBOSurfaces, a);
 87.4255 +	}
 87.4256 +}
 87.4257 +*/
 87.4258 +
 87.4259 +/*
 87.4260 +=================
 87.4261 +R_CreateClusters
 87.4262 +=================
 87.4263 +*/
 87.4264 +static void R_CreateClusters()
 87.4265 +{
 87.4266 +	int             i, j;
 87.4267 +	int             numClusters;
 87.4268 +	bspNode_t      *node, *parent;
 87.4269 +	bspCluster_t   *cluster;
 87.4270 +	growList_t      clusterSurfaces;
 87.4271 +	const byte     *vis;
 87.4272 +	int             c;
 87.4273 +	bspSurface_t   *surface, **mark;
 87.4274 +	int             surfaceNum;
 87.4275 +	vec3_t          mins, maxs;
 87.4276 +
 87.4277 +	ri.Printf(PRINT_ALL, "...creating BSP clusters\n");
 87.4278 +
 87.4279 +	if(s_worldData.vis)
 87.4280 +	{
 87.4281 +		// go through the leaves and count clusters
 87.4282 +		numClusters = 0;
 87.4283 +		for(i = 0, node = s_worldData.nodes; i < s_worldData.numnodes; i++, node++)
 87.4284 +		{
 87.4285 +			if(node->cluster >= numClusters)
 87.4286 +			{
 87.4287 +				numClusters = node->cluster;
 87.4288 +			}
 87.4289 +		}
 87.4290 +		numClusters++;
 87.4291 +
 87.4292 +		s_worldData.numClusters = numClusters;
 87.4293 +		s_worldData.clusters = ri.Hunk_Alloc((numClusters + 1) * sizeof(*s_worldData.clusters), h_low);	// + supercluster
 87.4294 +
 87.4295 +		// reset surfaces' viewCount
 87.4296 +		for(i = 0, surface = s_worldData.surfaces; i < s_worldData.numSurfaces; i++, surface++)
 87.4297 +		{
 87.4298 +			surface->viewCount = -1;
 87.4299 +		}
 87.4300 +
 87.4301 +		for(j = 0, node = s_worldData.nodes; j < s_worldData.numnodes; j++, node++)
 87.4302 +		{
 87.4303 +			node->visCounts[0] = -1;
 87.4304 +		}
 87.4305 +
 87.4306 +		for(i = 0; i < numClusters; i++)
 87.4307 +		{
 87.4308 +			cluster = &s_worldData.clusters[i];
 87.4309 +
 87.4310 +			// mark leaves in cluster
 87.4311 +			vis = s_worldData.vis + i * s_worldData.clusterBytes;
 87.4312 +
 87.4313 +			for(j = 0, node = s_worldData.nodes; j < s_worldData.numnodes; j++, node++)
 87.4314 +			{
 87.4315 +				if(node->cluster < 0 || node->cluster >= numClusters)
 87.4316 +				{
 87.4317 +					continue;
 87.4318 +				}
 87.4319 +
 87.4320 +				// check general pvs
 87.4321 +				if(!(vis[node->cluster >> 3] & (1 << (node->cluster & 7))))
 87.4322 +				{
 87.4323 +					continue;
 87.4324 +				}
 87.4325 +
 87.4326 +				parent = node;
 87.4327 +				do
 87.4328 +				{
 87.4329 +					if(parent->visCounts[0] == i)
 87.4330 +						break;
 87.4331 +					parent->visCounts[0] = i;
 87.4332 +					parent = parent->parent;
 87.4333 +				} while(parent);
 87.4334 +			}
 87.4335 +
 87.4336 +
 87.4337 +			// add cluster surfaces
 87.4338 +			Com_InitGrowList(&clusterSurfaces, 10000);
 87.4339 +
 87.4340 +			ClearBounds(mins, maxs);
 87.4341 +			for(j = 0, node = s_worldData.nodes; j < s_worldData.numnodes; j++, node++)
 87.4342 +			{
 87.4343 +				if(node->contents == CONTENTS_NODE)
 87.4344 +					continue;
 87.4345 +
 87.4346 +				if(node->visCounts[0] != i)
 87.4347 +					continue;
 87.4348 +
 87.4349 +				BoundsAdd(mins, maxs, node->mins, node->maxs);
 87.4350 +
 87.4351 +				mark = node->markSurfaces;
 87.4352 +				c = node->numMarkSurfaces;
 87.4353 +				while(c--)
 87.4354 +				{
 87.4355 +					// the surface may have already been added if it
 87.4356 +					// spans multiple leafs
 87.4357 +					surface = *mark;
 87.4358 +
 87.4359 +					surfaceNum = surface - s_worldData.surfaces;
 87.4360 +
 87.4361 +					if((surface->viewCount != i) && (surfaceNum < s_worldData.numWorldSurfaces))
 87.4362 +					{
 87.4363 +						surface->viewCount = i;
 87.4364 +						Com_AddToGrowList(&clusterSurfaces, surface);
 87.4365 +					}
 87.4366 +
 87.4367 +					mark++;
 87.4368 +				}
 87.4369 +			}
 87.4370 +
 87.4371 +			cluster->origin[0] = (mins[0] + maxs[0]) / 2;
 87.4372 +			cluster->origin[1] = (mins[1] + maxs[1]) / 2;
 87.4373 +			cluster->origin[2] = (mins[2] + maxs[2]) / 2;
 87.4374 +
 87.4375 +			//ri.Printf(PRINT_ALL, "cluster %i origin at (%i %i %i)\n", i, (int)cluster->origin[0], (int)cluster->origin[1], (int)cluster->origin[2]);
 87.4376 +
 87.4377 +			// move cluster surfaces list to hunk
 87.4378 +			cluster->numMarkSurfaces = clusterSurfaces.currentElements;
 87.4379 +			cluster->markSurfaces = ri.Hunk_Alloc(cluster->numMarkSurfaces * sizeof(*cluster->markSurfaces), h_low);
 87.4380 +
 87.4381 +			for(j = 0; j < cluster->numMarkSurfaces; j++)
 87.4382 +			{
 87.4383 +				cluster->markSurfaces[j] = (bspSurface_t *) Com_GrowListElement(&clusterSurfaces, j);
 87.4384 +			}
 87.4385 +
 87.4386 +			Com_DestroyGrowList(&clusterSurfaces);
 87.4387 +
 87.4388 +			//ri.Printf(PRINT_ALL, "cluster %i contains %i bsp surfaces\n", i, cluster->numMarkSurfaces);
 87.4389 +		}
 87.4390 +	}
 87.4391 +	else
 87.4392 +	{
 87.4393 +		numClusters = 0;
 87.4394 +
 87.4395 +		s_worldData.numClusters = numClusters;
 87.4396 +		s_worldData.clusters = ri.Hunk_Alloc((numClusters + 1) * sizeof(*s_worldData.clusters), h_low);	// + supercluster
 87.4397 +	}
 87.4398 +
 87.4399 +	// create a super cluster that will be always used when no view cluster can be found
 87.4400 +	Com_InitGrowList(&clusterSurfaces, 10000);
 87.4401 +
 87.4402 +	for(i = 0, surface = s_worldData.surfaces; i < s_worldData.numWorldSurfaces; i++, surface++)
 87.4403 +	{
 87.4404 +		Com_AddToGrowList(&clusterSurfaces, surface);
 87.4405 +	}
 87.4406 +
 87.4407 +	cluster = &s_worldData.clusters[numClusters];
 87.4408 +	cluster->numMarkSurfaces = clusterSurfaces.currentElements;
 87.4409 +	cluster->markSurfaces = ri.Hunk_Alloc(cluster->numMarkSurfaces * sizeof(*cluster->markSurfaces), h_low);
 87.4410 +
 87.4411 +	for(j = 0; j < cluster->numMarkSurfaces; j++)
 87.4412 +	{
 87.4413 +		cluster->markSurfaces[j] = (bspSurface_t *) Com_GrowListElement(&clusterSurfaces, j);
 87.4414 +	}
 87.4415 +
 87.4416 +	Com_DestroyGrowList(&clusterSurfaces);
 87.4417 +
 87.4418 +	for(i = 0; i < MAX_VISCOUNTS; i++)
 87.4419 +	{
 87.4420 +		Com_InitGrowList(&s_worldData.clusterVBOSurfaces[i], 100);
 87.4421 +	}
 87.4422 +
 87.4423 +	//ri.Printf(PRINT_ALL, "noVis cluster contains %i bsp surfaces\n", cluster->numMarkSurfaces);
 87.4424 +
 87.4425 +	ri.Printf(PRINT_ALL, "%i world clusters created\n", numClusters + 1);
 87.4426 +
 87.4427 +
 87.4428 +	// reset surfaces' viewCount
 87.4429 +	for(i = 0, surface = s_worldData.surfaces; i < s_worldData.numSurfaces; i++, surface++)
 87.4430 +	{
 87.4431 +		surface->viewCount = -1;
 87.4432 +	}
 87.4433 +
 87.4434 +	for(j = 0, node = s_worldData.nodes; j < s_worldData.numnodes; j++, node++)
 87.4435 +	{
 87.4436 +		node->visCounts[0] = -1;
 87.4437 +	}
 87.4438 +}
 87.4439 +
 87.4440 +/*
 87.4441 +SmoothNormals()
 87.4442 +smooths together coincident vertex normals across the bsp
 87.4443 +*/
 87.4444 +#if 0
 87.4445 +#define MAX_SAMPLES				256
 87.4446 +#define THETA_EPSILON			0.000001
 87.4447 +#define EQUAL_NORMAL_EPSILON	0.01
 87.4448 +
 87.4449 +void SmoothNormals(const char *name, srfVert_t * verts, int numTotalVerts)
 87.4450 +{
 87.4451 +	int             i, j, k, f, cs, numVerts, numVotes, fOld, startTime, endTime;
 87.4452 +	float           shadeAngle, defaultShadeAngle, maxShadeAngle, dot, testAngle;
 87.4453 +
 87.4454 +//  shaderInfo_t   *si;
 87.4455 +	float          *shadeAngles;
 87.4456 +	byte           *smoothed;
 87.4457 +	vec3_t          average, diff;
 87.4458 +	int             indexes[MAX_SAMPLES];
 87.4459 +	vec3_t          votes[MAX_SAMPLES];
 87.4460 +
 87.4461 +	srfVert_t      *yDrawVerts;
 87.4462 +
 87.4463 +	ri.Printf(PRINT_ALL, "smoothing normals for mesh '%s'\n", name);
 87.4464 +
 87.4465 +	yDrawVerts = Com_Allocate(numTotalVerts * sizeof(srfVert_t));
 87.4466 +	memcpy(yDrawVerts, verts, numTotalVerts * sizeof(srfVert_t));
 87.4467 +
 87.4468 +	// allocate shade angle table
 87.4469 +	shadeAngles = Com_Allocate(numTotalVerts * sizeof(float));
 87.4470 +	memset(shadeAngles, 0, numTotalVerts * sizeof(float));
 87.4471 +
 87.4472 +	// allocate smoothed table
 87.4473 +	cs = (numTotalVerts / 8) + 1;
 87.4474 +	smoothed = Com_Allocate(cs);
 87.4475 +	memset(smoothed, 0, cs);
 87.4476 +
 87.4477 +	// set default shade angle
 87.4478 +	defaultShadeAngle = DEG2RAD(179);
 87.4479 +	maxShadeAngle = defaultShadeAngle;
 87.4480 +
 87.4481 +	// run through every surface and flag verts belonging to non-lightmapped surfaces
 87.4482 +	//   and set per-vertex smoothing angle
 87.4483 +	/*
 87.4484 +	   for(i = 0; i < numBSPDrawSurfaces; i++)
 87.4485 +	   {
 87.4486 +	   // get drawsurf
 87.4487 +	   ds = &bspDrawSurfaces[i];
 87.4488 +
 87.4489 +	   // get shader for shade angle
 87.4490 +	   si = surfaceInfos[i].si;
 87.4491 +	   if(si->shadeAngleDegrees)
 87.4492 +	   shadeAngle = DEG2RAD(si->shadeAngleDegrees);
 87.4493 +	   else
 87.4494 +	   shadeAngle = defaultShadeAngle;
 87.4495 +	   if(shadeAngle > maxShadeAngle)
 87.4496 +	   maxShadeAngle = shadeAngle;
 87.4497 +
 87.4498 +	   // flag its verts
 87.4499 +	   for(j = 0; j < ds->numVerts; j++)
 87.4500 +	   {
 87.4501 +	   f = ds->firstVert + j;
 87.4502 +	   shadeAngles[f] = shadeAngle;
 87.4503 +	   if(ds->surfaceType == MST_TRIANGLE_SOUP)
 87.4504 +	   smoothed[f >> 3] |= (1 << (f & 7));
 87.4505 +	   }
 87.4506 +	   }
 87.4507 +
 87.4508 +	   // bail if no surfaces have a shade angle
 87.4509 +	   if(maxShadeAngle == 0)
 87.4510 +	   {
 87.4511 +	   Com_Dealloc(shadeAngles);
 87.4512 +	   Com_Dealloc(smoothed);
 87.4513 +	   return;
 87.4514 +	   }
 87.4515 +	 */
 87.4516 +
 87.4517 +	// init pacifier
 87.4518 +	fOld = -1;
 87.4519 +	startTime = ri.Milliseconds();
 87.4520 +
 87.4521 +	// go through the list of vertexes
 87.4522 +	for(i = 0; i < numTotalVerts; i++)
 87.4523 +	{
 87.4524 +		// print pacifier
 87.4525 +		f = 10 * i / numTotalVerts;
 87.4526 +		if(f != fOld)
 87.4527 +		{
 87.4528 +			fOld = f;
 87.4529 +			ri.Printf(PRINT_ALL, "%i...", f);
 87.4530 +		}
 87.4531 +
 87.4532 +		// already smoothed?
 87.4533 +		if(smoothed[i >> 3] & (1 << (i & 7)))
 87.4534 +			continue;
 87.4535 +
 87.4536 +		// clear
 87.4537 +		VectorClear(average);
 87.4538 +		numVerts = 0;
 87.4539 +		numVotes = 0;
 87.4540 +
 87.4541 +		// build a table of coincident vertexes
 87.4542 +		for(j = i; j < numTotalVerts && numVerts < MAX_SAMPLES; j++)
 87.4543 +		{
 87.4544 +			// already smoothed?
 87.4545 +			if(smoothed[j >> 3] & (1 << (j & 7)))
 87.4546 +				continue;
 87.4547 +
 87.4548 +			// test vertexes
 87.4549 +			if(CompareWorldVertSmoothNormal(&yDrawVerts[i], &yDrawVerts[j]) == qfalse)
 87.4550 +				continue;
 87.4551 +
 87.4552 +			// use smallest shade angle
 87.4553 +			//shadeAngle = (shadeAngles[i] < shadeAngles[j] ? shadeAngles[i] : shadeAngles[j]);
 87.4554 +			shadeAngle = maxShadeAngle;
 87.4555 +
 87.4556 +			// check shade angle
 87.4557 +			dot = DotProduct(verts[i].normal, verts[j].normal);
 87.4558 +			if(dot > 1.0)
 87.4559 +				dot = 1.0;
 87.4560 +			else if(dot < -1.0)
 87.4561 +				dot = -1.0;
 87.4562 +			testAngle = acos(dot) + THETA_EPSILON;
 87.4563 +			if(testAngle >= shadeAngle)
 87.4564 +			{
 87.4565 +				//Sys_Printf( "F(%3.3f >= %3.3f) ", RAD2DEG( testAngle ), RAD2DEG( shadeAngle ) );
 87.4566 +				continue;
 87.4567 +			}
 87.4568 +			//Sys_Printf( "P(%3.3f < %3.3f) ", RAD2DEG( testAngle ), RAD2DEG( shadeAngle ) );
 87.4569 +
 87.4570 +			// add to the list
 87.4571 +			indexes[numVerts++] = j;
 87.4572 +
 87.4573 +			// flag vertex
 87.4574 +			smoothed[j >> 3] |= (1 << (j & 7));
 87.4575 +
 87.4576 +			// see if this normal has already been voted
 87.4577 +			for(k = 0; k < numVotes; k++)
 87.4578 +			{
 87.4579 +				VectorSubtract(verts[j].normal, votes[k], diff);
 87.4580 +				if(fabs(diff[0]) < EQUAL_NORMAL_EPSILON &&
 87.4581 +				   fabs(diff[1]) < EQUAL_NORMAL_EPSILON && fabs(diff[2]) < EQUAL_NORMAL_EPSILON)
 87.4582 +					break;
 87.4583 +			}
 87.4584 +
 87.4585 +			// add a new vote?
 87.4586 +			if(k == numVotes && numVotes < MAX_SAMPLES)
 87.4587 +			{
 87.4588 +				VectorAdd(average, verts[j].normal, average);
 87.4589 +				VectorCopy(verts[j].normal, votes[numVotes]);
 87.4590 +				numVotes++;
 87.4591 +			}
 87.4592 +		}
 87.4593 +
 87.4594 +		// don't average for less than 2 verts
 87.4595 +		if(numVerts < 2)
 87.4596 +			continue;
 87.4597 +
 87.4598 +		// average normal
 87.4599 +		if(VectorNormalize(average) > 0)
 87.4600 +		{
 87.4601 +			// smooth
 87.4602 +			for(j = 0; j < numVerts; j++)
 87.4603 +				VectorCopy(average, yDrawVerts[indexes[j]].normal);
 87.4604 +		}
 87.4605 +	}
 87.4606 +
 87.4607 +	// copy yDrawVerts normals back
 87.4608 +	for(i = 0; i < numTotalVerts; i++)
 87.4609 +	{
 87.4610 +		VectorCopy(yDrawVerts[i].normal, verts[i].normal);
 87.4611 +	}
 87.4612 +
 87.4613 +	// free the tables
 87.4614 +	Com_Dealloc(yDrawVerts);
 87.4615 +	Com_Dealloc(shadeAngles);
 87.4616 +	Com_Dealloc(smoothed);
 87.4617 +
 87.4618 +	endTime = ri.Milliseconds();
 87.4619 +	ri.Printf(PRINT_ALL, " (%5.2f seconds)\n", (endTime - startTime) / 1000.0);
 87.4620 +}
 87.4621 +#endif
 87.4622 +
 87.4623 +/*
 87.4624 +===============
 87.4625 +R_CreateWorldVBO
 87.4626 +===============
 87.4627 +*/
 87.4628 +static void R_CreateWorldVBO()
 87.4629 +{
 87.4630 +	int             i, j, k;
 87.4631 +
 87.4632 +	int             numVerts;
 87.4633 +	srfVert_t      *verts;
 87.4634 +
 87.4635 +//  srfVert_t      *optimizedVerts;
 87.4636 +
 87.4637 +	int             numTriangles;
 87.4638 +	srfTriangle_t  *triangles;
 87.4639 +
 87.4640 +//  int             numSurfaces;
 87.4641 +	bspSurface_t   *surface;
 87.4642 +
 87.4643 +	trRefLight_t   *light;
 87.4644 +
 87.4645 +	int             startTime, endTime;
 87.4646 +
 87.4647 +	startTime = ri.Milliseconds();
 87.4648 +
 87.4649 +	numVerts = 0;
 87.4650 +	numTriangles = 0;
 87.4651 +	for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numWorldSurfaces; k++, surface++)
 87.4652 +	{
 87.4653 +		if(*surface->data == SF_FACE)
 87.4654 +		{
 87.4655 +			srfSurfaceFace_t *face = (srfSurfaceFace_t *) surface->data;
 87.4656 +
 87.4657 +			if(face->numVerts)
 87.4658 +				numVerts += face->numVerts;
 87.4659 +
 87.4660 +			if(face->numTriangles)
 87.4661 +				numTriangles += face->numTriangles;
 87.4662 +		}
 87.4663 +		else if(*surface->data == SF_GRID)
 87.4664 +		{
 87.4665 +			srfGridMesh_t  *grid = (srfGridMesh_t *) surface->data;
 87.4666 +
 87.4667 +			if(grid->numVerts)
 87.4668 +				numVerts += grid->numVerts;
 87.4669 +
 87.4670 +			if(grid->numTriangles)
 87.4671 +				numTriangles += grid->numTriangles;
 87.4672 +		}
 87.4673 +		else if(*surface->data == SF_TRIANGLES)
 87.4674 +		{
 87.4675 +			srfTriangles_t *tri = (srfTriangles_t *) surface->data;
 87.4676 +
 87.4677 +			if(tri->numVerts)
 87.4678 +				numVerts += tri->numVerts;
 87.4679 +
 87.4680 +			if(tri->numTriangles)
 87.4681 +				numTriangles += tri->numTriangles;
 87.4682 +		}
 87.4683 +	}
 87.4684 +
 87.4685 +	if(!numVerts || !numTriangles)
 87.4686 +		return;
 87.4687 +
 87.4688 +	ri.Printf(PRINT_ALL, "...calculating world VBO ( %i verts %i tris )\n", numVerts, numTriangles);
 87.4689 +
 87.4690 +	// create arrays
 87.4691 +
 87.4692 +	s_worldData.numVerts = numVerts;
 87.4693 +	s_worldData.verts = verts = ri.Hunk_Alloc(numVerts * sizeof(srfVert_t), h_low);
 87.4694 +	//optimizedVerts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t));
 87.4695 +
 87.4696 +	s_worldData.numTriangles = numTriangles;
 87.4697 +	s_worldData.triangles = triangles = ri.Hunk_Alloc(numTriangles * sizeof(srfTriangle_t), h_low);
 87.4698 +
 87.4699 +	// set up triangle indices
 87.4700 +	numVerts = 0;
 87.4701 +	numTriangles = 0;
 87.4702 +	for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numWorldSurfaces; k++, surface++)
 87.4703 +	{
 87.4704 +		if(*surface->data == SF_FACE)
 87.4705 +		{
 87.4706 +			srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
 87.4707 +
 87.4708 +			srf->firstTriangle = numTriangles;
 87.4709 +
 87.4710 +			if(srf->numTriangles)
 87.4711 +			{
 87.4712 +				srfTriangle_t  *tri;
 87.4713 +
 87.4714 +				for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
 87.4715 +				{
 87.4716 +					for(j = 0; j < 3; j++)
 87.4717 +					{
 87.4718 +						triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
 87.4719 +					}
 87.4720 +				}
 87.4721 +
 87.4722 +				numTriangles += srf->numTriangles;
 87.4723 +			}
 87.4724 +
 87.4725 +			if(srf->numVerts)
 87.4726 +				numVerts += srf->numVerts;
 87.4727 +		}
 87.4728 +		else if(*surface->data == SF_GRID)
 87.4729 +		{
 87.4730 +			srfGridMesh_t  *srf = (srfGridMesh_t *) surface->data;
 87.4731 +
 87.4732 +			srf->firstTriangle = numTriangles;
 87.4733 +
 87.4734 +			if(srf->numTriangles)
 87.4735 +			{
 87.4736 +				srfTriangle_t  *tri;
 87.4737 +
 87.4738 +				for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
 87.4739 +				{
 87.4740 +					for(j = 0; j < 3; j++)
 87.4741 +					{
 87.4742 +						triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
 87.4743 +					}
 87.4744 +				}
 87.4745 +
 87.4746 +				numTriangles += srf->numTriangles;
 87.4747 +			}
 87.4748 +
 87.4749 +			if(srf->numVerts)
 87.4750 +				numVerts += srf->numVerts;
 87.4751 +		}
 87.4752 +		else if(*surface->data == SF_TRIANGLES)
 87.4753 +		{
 87.4754 +			srfTriangles_t *srf = (srfTriangles_t *) surface->data;
 87.4755 +
 87.4756 +			srf->firstTriangle = numTriangles;
 87.4757 +
 87.4758 +			if(srf->numTriangles)
 87.4759 +			{
 87.4760 +				srfTriangle_t  *tri;
 87.4761 +
 87.4762 +				for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
 87.4763 +				{
 87.4764 +					for(j = 0; j < 3; j++)
 87.4765 +					{
 87.4766 +						triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
 87.4767 +					}
 87.4768 +				}
 87.4769 +
 87.4770 +				numTriangles += srf->numTriangles;
 87.4771 +			}
 87.4772 +
 87.4773 +			if(srf->numVerts)
 87.4774 +				numVerts += srf->numVerts;
 87.4775 +		}
 87.4776 +	}
 87.4777 +
 87.4778 +	// build vertices
 87.4779 +	numVerts = 0;
 87.4780 +	for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numWorldSurfaces; k++, surface++)
 87.4781 +	{
 87.4782 +		if(*surface->data == SF_FACE)
 87.4783 +		{
 87.4784 +			srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
 87.4785 +
 87.4786 +			srf->firstVert = numVerts;
 87.4787 +
 87.4788 +			if(srf->numVerts)
 87.4789 +			{
 87.4790 +				for(i = 0; i < srf->numVerts; i++)
 87.4791 +				{
 87.4792 +					CopyVert(&srf->verts[i], &verts[numVerts + i]);
 87.4793 +				}
 87.4794 +
 87.4795 +				numVerts += srf->numVerts;
 87.4796 +			}
 87.4797 +		}
 87.4798 +		else if(*surface->data == SF_GRID)
 87.4799 +		{
 87.4800 +			srfGridMesh_t  *srf = (srfGridMesh_t *) surface->data;
 87.4801 +
 87.4802 +			srf->firstVert = numVerts;
 87.4803 +
 87.4804 +			if(srf->numVerts)
 87.4805 +			{
 87.4806 +				for(i = 0; i < srf->numVerts; i++)
 87.4807 +				{
 87.4808 +					CopyVert(&srf->verts[i], &verts[numVerts + i]);
 87.4809 +				}
 87.4810 +
 87.4811 +				numVerts += srf->numVerts;
 87.4812 +			}
 87.4813 +		}
 87.4814 +		else if(*surface->data == SF_TRIANGLES)
 87.4815 +		{
 87.4816 +			srfTriangles_t *srf = (srfTriangles_t *) surface->data;
 87.4817 +
 87.4818 +			srf->firstVert = numVerts;
 87.4819 +
 87.4820 +			if(srf->numVerts)
 87.4821 +			{
 87.4822 +				for(i = 0; i < srf->numVerts; i++)
 87.4823 +				{
 87.4824 +					CopyVert(&srf->verts[i], &verts[numVerts + i]);
 87.4825 +				}
 87.4826 +
 87.4827 +				numVerts += srf->numVerts;
 87.4828 +			}
 87.4829 +		}
 87.4830 +	}
 87.4831 +
 87.4832 +#if 0
 87.4833 +	numVerts = OptimizeVertices(numVerts, verts, numTriangles, triangles, optimizedVerts, CompareWorldVert);
 87.4834 +	if(c_redundantVertexes)
 87.4835 +	{
 87.4836 +		ri.Printf(PRINT_DEVELOPER,
 87.4837 +				  "...removed %i redundant vertices from staticWorldMesh %i ( %s, %i verts %i tris )\n",
 87.4838 +				  c_redundantVertexes, vboSurfaces.currentElements, shader->name, numVerts, numTriangles);
 87.4839 +	}
 87.4840 +
 87.4841 +	s_worldData.vbo = R_CreateVBO2(va("bspModelMesh_vertices %i", 0), numVerts, optimizedVerts,
 87.4842 +								   ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BINORMAL |
 87.4843 +								   ATTR_NORMAL | ATTR_COLOR | GLCS_LIGHTCOLOR | ATTR_LIGHTDIRECTION);
 87.4844 +#else
 87.4845 +	s_worldData.vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", 0), numVerts, verts,
 87.4846 +								   ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BINORMAL |
 87.4847 +								   ATTR_NORMAL | ATTR_COLOR | ATTR_PAINTCOLOR | ATTR_LIGHTDIRECTION, GL_STATIC_DRAW_ARB);
 87.4848 +#endif
 87.4849 +
 87.4850 +	endTime = ri.Milliseconds();
 87.4851 +	ri.Printf(PRINT_ALL, "world VBO calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0);
 87.4852 +
 87.4853 +
 87.4854 +	startTime = ri.Milliseconds();
 87.4855 +
 87.4856 +	// Tr3B: FIXME move this to somewhere else?
 87.4857 +#if CALC_REDUNDANT_SHADOWVERTS
 87.4858 +	s_worldData.redundantVertsCalculationNeeded = 0;
 87.4859 +	for(i = 0; i < s_worldData.numLights; i++)
 87.4860 +	{
 87.4861 +		light = &s_worldData.lights[i];
 87.4862 +
 87.4863 +		if((r_precomputedLighting->integer || r_vertexLighting->integer) && !light->noRadiosity)
 87.4864 +			continue;
 87.4865 +
 87.4866 +		s_worldData.redundantVertsCalculationNeeded++;
 87.4867 +	}
 87.4868 +
 87.4869 +	if(s_worldData.redundantVertsCalculationNeeded)
 87.4870 +	{
 87.4871 +		ri.Printf(PRINT_ALL, "...calculating redundant world vertices ( %i verts )\n", numVerts);
 87.4872 +
 87.4873 +		s_worldData.redundantLightVerts = ri.Hunk_Alloc(numVerts * sizeof(int), h_low);
 87.4874 +		BuildRedundantIndices(numVerts, verts, s_worldData.redundantLightVerts, CompareLightVert);
 87.4875 +
 87.4876 +		s_worldData.redundantShadowVerts = ri.Hunk_Alloc(numVerts * sizeof(int), h_low);
 87.4877 +		BuildRedundantIndices(numVerts, verts, s_worldData.redundantShadowVerts, CompareShadowVert);
 87.4878 +
 87.4879 +		s_worldData.redundantShadowAlphaTestVerts = ri.Hunk_Alloc(numVerts * sizeof(int), h_low);
 87.4880 +		BuildRedundantIndices(numVerts, verts, s_worldData.redundantShadowAlphaTestVerts, CompareShadowVertAlphaTest);
 87.4881 +	}
 87.4882 +
 87.4883 +	endTime = ri.Milliseconds();
 87.4884 +	ri.Printf(PRINT_ALL, "redundant world vertices calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0);
 87.4885 +#endif
 87.4886 +
 87.4887 +	//ri.Hunk_FreeTempMemory(triangles);
 87.4888 +	//ri.Hunk_FreeTempMemory(optimizedVerts);
 87.4889 +	//ri.Hunk_FreeTempMemory(verts);
 87.4890 +}
 87.4891 +
 87.4892 +/*
 87.4893 +===============
 87.4894 +R_CreateSubModelVBOs
 87.4895 +===============
 87.4896 +*/
 87.4897 +static void R_CreateSubModelVBOs()
 87.4898 +{
 87.4899 +	int             i, j, k, l, m;
 87.4900 +
 87.4901 +	int             numVerts;
 87.4902 +	srfVert_t      *verts;
 87.4903 +
 87.4904 +	srfVert_t      *optimizedVerts;
 87.4905 +
 87.4906 +	int             numTriangles;
 87.4907 +	srfTriangle_t  *triangles;
 87.4908 +
 87.4909 +	shader_t       *shader, *oldShader;
 87.4910 +	int             lightmapNum, oldLightmapNum;
 87.4911 +
 87.4912 +	int             numSurfaces;
 87.4913 +	bspSurface_t   *surface, *surface2;
 87.4914 +	bspSurface_t  **surfacesSorted;
 87.4915 +
 87.4916 +	bspModel_t     *model;
 87.4917 +
 87.4918 +	growList_t      vboSurfaces;
 87.4919 +	srfVBOMesh_t   *vboSurf;
 87.4920 +
 87.4921 +	for(m = 1, model = s_worldData.models; m < s_worldData.numModels; m++, model++)
 87.4922 +	{
 87.4923 +		// count number of static area surfaces
 87.4924 +		numSurfaces = 0;
 87.4925 +		for(k = 0; k < model->numSurfaces; k++)
 87.4926 +		{
 87.4927 +			surface = model->firstSurface + k;
 87.4928 +			shader = surface->shader;
 87.4929 +
 87.4930 +			if(shader->isSky)
 87.4931 +				continue;
 87.4932 +
 87.4933 +			if(shader->isPortal)
 87.4934 +				continue;
 87.4935 +
 87.4936 +			if(shader->numDeforms)
 87.4937 +				continue;
 87.4938 +
 87.4939 +			numSurfaces++;
 87.4940 +		}
 87.4941 +
 87.4942 +		if(!numSurfaces)
 87.4943 +			continue;
 87.4944 +
 87.4945 +		// build interaction caches list
 87.4946 +		surfacesSorted = ri.Hunk_AllocateTempMemory(numSurfaces * sizeof(surfacesSorted[0]));
 87.4947 +
 87.4948 +		numSurfaces = 0;
 87.4949 +		for(k = 0; k < model->numSurfaces; k++)
 87.4950 +		{
 87.4951 +			surface = model->firstSurface + k;
 87.4952 +			shader = surface->shader;
 87.4953 +
 87.4954 +			if(shader->isSky)
 87.4955 +				continue;
 87.4956 +
 87.4957 +			if(shader->isPortal)
 87.4958 +				continue;
 87.4959 +
 87.4960 +			if(shader->numDeforms)
 87.4961 +				continue;
 87.4962 +
 87.4963 +			surfacesSorted[numSurfaces] = surface;
 87.4964 +			numSurfaces++;
 87.4965 +		}
 87.4966 +
 87.4967 +		Com_InitGrowList(&vboSurfaces, 100);
 87.4968 +
 87.4969 +		// sort surfaces by shader
 87.4970 +		qsort(surfacesSorted, numSurfaces, sizeof(surfacesSorted), BSPSurfaceCompare);
 87.4971 +
 87.4972 +		// create a VBO for each shader
 87.4973 +		shader = oldShader = NULL;
 87.4974 +		lightmapNum = oldLightmapNum = -1;
 87.4975 +
 87.4976 +		for(k = 0; k < numSurfaces; k++)
 87.4977 +		{
 87.4978 +			surface = surfacesSorted[k];
 87.4979 +			shader = surface->shader;
 87.4980 +			lightmapNum = surface->lightmapNum;
 87.4981 +
 87.4982 +			if(shader != oldShader || (r_precomputedLighting->integer ? lightmapNum != oldLightmapNum : 0))
 87.4983 +			{
 87.4984 +				oldShader = shader;
 87.4985 +				oldLightmapNum = lightmapNum;
 87.4986 +
 87.4987 +				// count vertices and indices
 87.4988 +				numVerts = 0;
 87.4989 +				numTriangles = 0;
 87.4990 +
 87.4991 +				for(l = k; l < numSurfaces; l++)
 87.4992 +				{
 87.4993 +					surface2 = surfacesSorted[l];
 87.4994 +
 87.4995 +					if(surface2->shader != shader)
 87.4996 +						continue;
 87.4997 +
 87.4998 +					if(*surface2->data == SF_FACE)
 87.4999 +					{
 87.5000 +						srfSurfaceFace_t *face = (srfSurfaceFace_t *) surface2->data;
 87.5001 +
 87.5002 +						if(face->numVerts)
 87.5003 +							numVerts += face->numVerts;
 87.5004 +
 87.5005 +						if(face->numTriangles)
 87.5006 +							numTriangles += face->numTriangles;
 87.5007 +					}
 87.5008 +					else if(*surface2->data == SF_GRID)
 87.5009 +					{
 87.5010 +						srfGridMesh_t  *grid = (srfGridMesh_t *) surface2->data;
 87.5011 +
 87.5012 +						if(grid->numVerts)
 87.5013 +							numVerts += grid->numVerts;
 87.5014 +
 87.5015 +						if(grid->numTriangles)
 87.5016 +							numTriangles += grid->numTriangles;
 87.5017 +					}
 87.5018 +					else if(*surface2->data == SF_TRIANGLES)
 87.5019 +					{
 87.5020 +						srfTriangles_t *tri = (srfTriangles_t *) surface2->data;
 87.5021 +
 87.5022 +						if(tri->numVerts)
 87.5023 +							numVerts += tri->numVerts;
 87.5024 +
 87.5025 +						if(tri->numTriangles)
 87.5026 +							numTriangles += tri->numTriangles;
 87.5027 +					}
 87.5028 +				}
 87.5029 +
 87.5030 +				if(!numVerts || !numTriangles)
 87.5031 +					continue;
 87.5032 +
 87.5033 +				ri.Printf(PRINT_DEVELOPER, "...calculating entity mesh VBOs ( %s, %i verts %i tris )\n", shader->name, numVerts,
 87.5034 +						  numTriangles);
 87.5035 +
 87.5036 +				// create surface
 87.5037 +				vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low);
 87.5038 +				Com_AddToGrowList(&vboSurfaces, vboSurf);
 87.5039 +
 87.5040 +				vboSurf->surfaceType = SF_VBO_MESH;
 87.5041 +				vboSurf->numIndexes = numTriangles * 3;
 87.5042 +				vboSurf->numVerts = numVerts;
 87.5043 +
 87.5044 +				vboSurf->shader = shader;
 87.5045 +				vboSurf->lightmapNum = lightmapNum;
 87.5046 +
 87.5047 +				// create arrays
 87.5048 +				verts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t));
 87.5049 +				optimizedVerts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t));
 87.5050 +				numVerts = 0;
 87.5051 +
 87.5052 +				triangles = ri.Hunk_AllocateTempMemory(numTriangles * sizeof(srfTriangle_t));
 87.5053 +				numTriangles = 0;
 87.5054 +
 87.5055 +				ClearBounds(vboSurf->bounds[0], vboSurf->bounds[1]);
 87.5056 +
 87.5057 +				// build triangle indices
 87.5058 +				for(l = k; l < numSurfaces; l++)
 87.5059 +				{
 87.5060 +					surface2 = surfacesSorted[l];
 87.5061 +
 87.5062 +					if(surface2->shader != shader)
 87.5063 +						continue;
 87.5064 +
 87.5065 +					// set up triangle indices
 87.5066 +					if(*surface2->data == SF_FACE)
 87.5067 +					{
 87.5068 +						srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface2->data;
 87.5069 +
 87.5070 +						if(srf->numTriangles)
 87.5071 +						{
 87.5072 +							srfTriangle_t  *tri;
 87.5073 +
 87.5074 +							for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
 87.5075 +							{
 87.5076 +								for(j = 0; j < 3; j++)
 87.5077 +								{
 87.5078 +									triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
 87.5079 +								}
 87.5080 +							}
 87.5081 +
 87.5082 +							numTriangles += srf->numTriangles;
 87.5083 +						}
 87.5084 +
 87.5085 +						if(srf->numVerts)
 87.5086 +							numVerts += srf->numVerts;
 87.5087 +					}
 87.5088 +					else if(*surface2->data == SF_GRID)
 87.5089 +					{
 87.5090 +						srfGridMesh_t  *srf = (srfGridMesh_t *) surface2->data;
 87.5091 +
 87.5092 +						if(srf->numTriangles)
 87.5093 +						{
 87.5094 +							srfTriangle_t  *tri;
 87.5095 +
 87.5096 +							for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
 87.5097 +							{
 87.5098 +								for(j = 0; j < 3; j++)
 87.5099 +								{
 87.5100 +									triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
 87.5101 +								}
 87.5102 +							}
 87.5103 +
 87.5104 +							numTriangles += srf->numTriangles;
 87.5105 +						}
 87.5106 +
 87.5107 +						if(srf->numVerts)
 87.5108 +							numVerts += srf->numVerts;
 87.5109 +					}
 87.5110 +					else if(*surface2->data == SF_TRIANGLES)
 87.5111 +					{
 87.5112 +						srfTriangles_t *srf = (srfTriangles_t *) surface2->data;
 87.5113 +
 87.5114 +						if(srf->numTriangles)
 87.5115 +						{
 87.5116 +							srfTriangle_t  *tri;
 87.5117 +
 87.5118 +							for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
 87.5119 +							{
 87.5120 +								for(j = 0; j < 3; j++)
 87.5121 +								{
 87.5122 +									triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
 87.5123 +								}
 87.5124 +							}
 87.5125 +
 87.5126 +							numTriangles += srf->numTriangles;
 87.5127 +						}
 87.5128 +
 87.5129 +						if(srf->numVerts)
 87.5130 +							numVerts += srf->numVerts;
 87.5131 +					}
 87.5132 +				}
 87.5133 +
 87.5134 +				// build vertices
 87.5135 +				numVerts = 0;
 87.5136 +				for(l = k; l < numSurfaces; l++)
 87.5137 +				{
 87.5138 +					surface2 = surfacesSorted[l];
 87.5139 +
 87.5140 +					if(surface2->shader != shader)
 87.5141 +						continue;
 87.5142 +
 87.5143 +					if(*surface2->data == SF_FACE)
 87.5144 +					{
 87.5145 +						srfSurfaceFace_t *cv = (srfSurfaceFace_t *) surface2->data;
 87.5146 +
 87.5147 +						if(cv->numVerts)
 87.5148 +						{
 87.5149 +							for(i = 0; i < cv->numVerts; i++)
 87.5150 +							{
 87.5151 +								CopyVert(&cv->verts[i], &verts[numVerts + i]);
 87.5152 +
 87.5153 +								AddPointToBounds(cv->verts[i].xyz, vboSurf->bounds[0], vboSurf->bounds[1]);
 87.5154 +							}
 87.5155 +
 87.5156 +							numVerts += cv->numVerts;
 87.5157 +						}
 87.5158 +					}
 87.5159 +					else if(*surface2->data == SF_GRID)
 87.5160 +					{
 87.5161 +						srfGridMesh_t  *cv = (srfGridMesh_t *) surface2->data;
 87.5162 +
 87.5163 +						if(cv->numVerts)
 87.5164 +						{
 87.5165 +							for(i = 0; i < cv->numVerts; i++)
 87.5166 +							{
 87.5167 +								CopyVert(&cv->verts[i], &verts[numVerts + i]);
 87.5168 +
 87.5169 +								AddPointToBounds(cv->verts[i].xyz, vboSurf->bounds[0], vboSurf->bounds[1]);
 87.5170 +							}
 87.5171 +
 87.5172 +							numVerts += cv->numVerts;
 87.5173 +						}
 87.5174 +					}
 87.5175 +					else if(*surface2->data == SF_TRIANGLES)
 87.5176 +					{
 87.5177 +						srfTriangles_t *cv = (srfTriangles_t *) surface2->data;
 87.5178 +
 87.5179 +						if(cv->numVerts)
 87.5180 +						{
 87.5181 +							for(i = 0; i < cv->numVerts; i++)
 87.5182 +							{
 87.5183 +								CopyVert(&cv->verts[i], &verts[numVerts + i]);
 87.5184 +
 87.5185 +								AddPointToBounds(cv->verts[i].xyz, vboSurf->bounds[0], vboSurf->bounds[1]);
 87.5186 +							}
 87.5187 +
 87.5188 +							numVerts += cv->numVerts;
 87.5189 +						}
 87.5190 +					}
 87.5191 +				}
 87.5192 +
 87.5193 +#if 0
 87.5194 +				numVerts = OptimizeVertices(numVerts, verts, numTriangles, triangles, optimizedVerts, CompareWorldVert);
 87.5195 +				if(c_redundantVertexes)
 87.5196 +				{
 87.5197 +					ri.Printf(PRINT_DEVELOPER,
 87.5198 +							  "...removed %i redundant vertices from staticEntityMesh %i ( %s, %i verts %i tris )\n",
 87.5199 +							  c_redundantVertexes, vboSurfaces.currentElements, shader->name, numVerts, numTriangles);
 87.5200 +				}
 87.5201 +
 87.5202 +				vboSurf->vbo =
 87.5203 +					R_CreateVBO2(va("staticBspModel%i_VBO %i", m, vboSurfaces.currentElements), numVerts, optimizedVerts,
 87.5204 +								 ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BINORMAL | ATTR_NORMAL
 87.5205 +								 | ATTR_COLOR | GLCS_LIGHTCOLOR | ATTR_LIGHTDIRECTION, GL_STATIC_DRAW_ARB);
 87.5206 +#else
 87.5207 +				vboSurf->vbo =
 87.5208 +					R_CreateVBO2(va("staticBspModel%i_VBO %i", m, vboSurfaces.currentElements), numVerts, verts,
 87.5209 +								 ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BINORMAL | ATTR_NORMAL
 87.5210 +								 | ATTR_COLOR | ATTR_PAINTCOLOR | ATTR_LIGHTDIRECTION, GL_STATIC_DRAW_ARB);
 87.5211 +#endif
 87.5212 +
 87.5213 +				vboSurf->ibo =
 87.5214 +					R_CreateIBO2(va("staticBspModel%i_IBO %i", m, vboSurfaces.currentElements), numTriangles, triangles,
 87.5215 +								 GL_STATIC_DRAW_ARB);
 87.5216 +
 87.5217 +				ri.Hunk_FreeTempMemory(triangles);
 87.5218 +				ri.Hunk_FreeTempMemory(optimizedVerts);
 87.5219 +				ri.Hunk_FreeTempMemory(verts);
 87.5220 +			}
 87.5221 +		}
 87.5222 +
 87.5223 +		ri.Hunk_FreeTempMemory(surfacesSorted);
 87.5224 +
 87.5225 +		// move VBO surfaces list to hunk
 87.5226 +		model->numVBOSurfaces = vboSurfaces.currentElements;
 87.5227 +		model->vboSurfaces = ri.Hunk_Alloc(model->numVBOSurfaces * sizeof(*model->vboSurfaces), h_low);
 87.5228 +
 87.5229 +		for(i = 0; i < model->numVBOSurfaces; i++)
 87.5230 +		{
 87.5231 +			model->vboSurfaces[i] = (srfVBOMesh_t *) Com_GrowListElement(&vboSurfaces, i);
 87.5232 +		}
 87.5233 +
 87.5234 +		Com_DestroyGrowList(&vboSurfaces);
 87.5235 +
 87.5236 +		ri.Printf(PRINT_ALL, "%i VBO surfaces created for BSP submodel %i\n", model->numVBOSurfaces, m);
 87.5237  	}
 87.5238  }
 87.5239  
 87.5240 @@ -1228,73 +4646,86 @@
 87.5241  R_LoadSurfaces
 87.5242  ===============
 87.5243  */
 87.5244 -static	void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) {
 87.5245 -	dsurface_t	*in;
 87.5246 -	msurface_t	*out;
 87.5247 -	drawVert_t	*dv;
 87.5248 -	int			*indexes;
 87.5249 -	int			count;
 87.5250 -	int			numFaces, numMeshes, numTriSurfs, numFlares;
 87.5251 -	int			i;
 87.5252 +static void R_LoadSurfaces(lump_t * surfs, lump_t * verts, lump_t * indexLump)
 87.5253 +{
 87.5254 +	dsurface_t     *in;
 87.5255 +	bspSurface_t   *out;
 87.5256 +	drawVert_t     *dv;
 87.5257 +	int            *indexes;
 87.5258 +	int             count;
 87.5259 +	int             numFaces, numMeshes, numTriSurfs, numFlares, numFoliages;
 87.5260 +	int             i;
 87.5261 +
 87.5262 +	ri.Printf(PRINT_ALL, "...loading surfaces\n");
 87.5263  
 87.5264  	numFaces = 0;
 87.5265  	numMeshes = 0;
 87.5266  	numTriSurfs = 0;
 87.5267  	numFlares = 0;
 87.5268 +	numFoliages = 0;
 87.5269  
 87.5270  	in = (void *)(fileBase + surfs->fileofs);
 87.5271 -	if (surfs->filelen % sizeof(*in))
 87.5272 -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
 87.5273 +	if(surfs->filelen % sizeof(*in))
 87.5274 +		ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
 87.5275  	count = surfs->filelen / sizeof(*in);
 87.5276  
 87.5277  	dv = (void *)(fileBase + verts->fileofs);
 87.5278 -	if (verts->filelen % sizeof(*dv))
 87.5279 -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
 87.5280 +	if(verts->filelen % sizeof(*dv))
 87.5281 +		ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
 87.5282  
 87.5283  	indexes = (void *)(fileBase + indexLump->fileofs);
 87.5284 -	if ( indexLump->filelen % sizeof(*indexes))
 87.5285 -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
 87.5286 -
 87.5287 -	out = ri.Hunk_Alloc ( count * sizeof(*out), h_low );	
 87.5288 +	if(indexLump->filelen % sizeof(*indexes))
 87.5289 +		ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
 87.5290 +
 87.5291 +	out = ri.Hunk_Alloc(count * sizeof(*out), h_low);
 87.5292  
 87.5293  	s_worldData.surfaces = out;
 87.5294 -	s_worldData.numsurfaces = count;
 87.5295 -
 87.5296 -	for ( i = 0 ; i < count ; i++, in++, out++ ) {
 87.5297 -		switch ( LittleLong( in->surfaceType ) ) {
 87.5298 -		case MST_PATCH:
 87.5299 -			ParseMesh ( in, dv, out );
 87.5300 -			numMeshes++;
 87.5301 -			break;
 87.5302 -		case MST_TRIANGLE_SOUP:
 87.5303 -			ParseTriSurf( in, dv, out, indexes );
 87.5304 -			numTriSurfs++;
 87.5305 -			break;
 87.5306 -		case MST_PLANAR:
 87.5307 -			ParseFace( in, dv, out, indexes );
 87.5308 -			numFaces++;
 87.5309 -			break;
 87.5310 -		case MST_FLARE:
 87.5311 -			ParseFlare( in, dv, out, indexes );
 87.5312 -			numFlares++;
 87.5313 -			break;
 87.5314 -		default:
 87.5315 -			ri.Error( ERR_DROP, "Bad surfaceType" );
 87.5316 -		}
 87.5317 -	}
 87.5318 -
 87.5319 -#ifdef PATCH_STITCHING
 87.5320 -	R_StitchAllPatches();
 87.5321 -#endif
 87.5322 +	s_worldData.numSurfaces = count;
 87.5323 +
 87.5324 +	for(i = 0; i < count; i++, in++, out++)
 87.5325 +	{
 87.5326 +		switch (LittleLong(in->surfaceType))
 87.5327 +		{
 87.5328 +			case MST_PATCH:
 87.5329 +				ParseMesh(in, dv, out);
 87.5330 +				numMeshes++;
 87.5331 +				break;
 87.5332 +			case MST_TRIANGLE_SOUP:
 87.5333 +				ParseTriSurf(in, dv, out, indexes);
 87.5334 +				numTriSurfs++;
 87.5335 +				break;
 87.5336 +			case MST_PLANAR:
 87.5337 +				ParseFace(in, dv, out, indexes);
 87.5338 +				numFaces++;
 87.5339 +				break;
 87.5340 +			case MST_FLARE:
 87.5341 +				ParseFlare(in, dv, out, indexes);
 87.5342 +				numFlares++;
 87.5343 +				break;
 87.5344 +			case MST_FOLIAGE:
 87.5345 +				// Tr3B: TODO ParseFoliage
 87.5346 +				ParseTriSurf(in, dv, out, indexes);
 87.5347 +				numFoliages++;
 87.5348 +				break;
 87.5349 +			default:
 87.5350 +				ri.Error(ERR_DROP, "Bad surfaceType");
 87.5351 +		}
 87.5352 +	}
 87.5353 +
 87.5354 +	ri.Printf(PRINT_ALL, "...loaded %d faces, %i meshes, %i trisurfs, %i flares %i foliages\n", numFaces, numMeshes, numTriSurfs,
 87.5355 +			  numFlares, numFoliages);
 87.5356 +
 87.5357 +	if(r_stitchCurves->integer)
 87.5358 +	{
 87.5359 +		R_StitchAllPatches();
 87.5360 +	}
 87.5361  
 87.5362  	R_FixSharedVertexLodError();
 87.5363  
 87.5364 -#ifdef PATCH_STITCHING
 87.5365 -	R_MovePatchSurfacesToHunk();
 87.5366 -#endif
 87.5367 -
 87.5368 -	ri.Printf( PRINT_DEVELOPER, "...loaded %d faces, %i meshes, %i trisurfs, %i flares\n", 
 87.5369 -		numFaces, numMeshes, numTriSurfs, numFlares );
 87.5370 +	if(r_stitchCurves->integer)
 87.5371 +	{
 87.5372 +		R_MovePatchSurfacesToHunk();
 87.5373 +	}
 87.5374  }
 87.5375  
 87.5376  
 87.5377 @@ -1304,39 +4735,50 @@
 87.5378  R_LoadSubmodels
 87.5379  =================
 87.5380  */
 87.5381 -static	void R_LoadSubmodels( lump_t *l ) {
 87.5382 -	dmodel_t	*in;
 87.5383 -	bmodel_t	*out;
 87.5384 -	int			i, j, count;
 87.5385 +static void R_LoadSubmodels(lump_t * l)
 87.5386 +{
 87.5387 +	dmodel_t       *in;
 87.5388 +	bspModel_t     *out;
 87.5389 +	int             i, j, count;
 87.5390 +
 87.5391 +	ri.Printf(PRINT_ALL, "...loading submodels\n");
 87.5392  
 87.5393  	in = (void *)(fileBase + l->fileofs);
 87.5394 -	if (l->filelen % sizeof(*in))
 87.5395 -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
 87.5396 +	if(l->filelen % sizeof(*in))
 87.5397 +		ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
 87.5398  	count = l->filelen / sizeof(*in);
 87.5399  
 87.5400 -	s_worldData.bmodels = out = ri.Hunk_Alloc( count * sizeof(*out), h_low );
 87.5401 -
 87.5402 -	for ( i=0 ; i<count ; i++, in++, out++ ) {
 87.5403 -		model_t *model;
 87.5404 +	s_worldData.numModels = count;
 87.5405 +	s_worldData.models = out = ri.Hunk_Alloc(count * sizeof(*out), h_low);
 87.5406 +
 87.5407 +	for(i = 0; i < count; i++, in++, out++)
 87.5408 +	{
 87.5409 +		model_t        *model;
 87.5410  
 87.5411  		model = R_AllocModel();
 87.5412  
 87.5413 -		assert( model != NULL );			// this should never happen
 87.5414 -		if ( model == NULL ) {
 87.5415 +		assert(model != NULL);	// this should never happen
 87.5416 +		if(model == NULL)
 87.5417  			ri.Error(ERR_DROP, "R_LoadSubmodels: R_AllocModel() failed");
 87.5418 -		}
 87.5419 -
 87.5420 -		model->type = MOD_BRUSH;
 87.5421 -		model->bmodel = out;
 87.5422 -		Com_sprintf( model->name, sizeof( model->name ), "*%d", i );
 87.5423 -
 87.5424 -		for (j=0 ; j<3 ; j++) {
 87.5425 -			out->bounds[0][j] = LittleFloat (in->mins[j]);
 87.5426 -			out->bounds[1][j] = LittleFloat (in->maxs[j]);
 87.5427 -		}
 87.5428 -
 87.5429 -		out->firstSurface = s_worldData.surfaces + LittleLong( in->firstSurface );
 87.5430 -		out->numSurfaces = LittleLong( in->numSurfaces );
 87.5431 +
 87.5432 +		model->type = MOD_BSP;
 87.5433 +		model->bsp = out;
 87.5434 +		Com_sprintf(model->name, sizeof(model->name), "*%d", i);
 87.5435 +
 87.5436 +		for(j = 0; j < 3; j++)
 87.5437 +		{
 87.5438 +			out->bounds[0][j] = LittleFloat(in->mins[j]);
 87.5439 +			out->bounds[1][j] = LittleFloat(in->maxs[j]);
 87.5440 +		}
 87.5441 +
 87.5442 +		out->firstSurface = s_worldData.surfaces + LittleLong(in->firstSurface);
 87.5443 +		out->numSurfaces = LittleLong(in->numSurfaces);
 87.5444 +
 87.5445 +		if(i == 0)
 87.5446 +		{
 87.5447 +			// Tr3B: add this for limiting VBO surface creation
 87.5448 +			s_worldData.numWorldSurfaces = out->numSurfaces;
 87.5449 +		}
 87.5450  	}
 87.5451  }
 87.5452  
 87.5453 @@ -1349,13 +4791,13 @@
 87.5454  R_SetParent
 87.5455  =================
 87.5456  */
 87.5457 -static	void R_SetParent (mnode_t *node, mnode_t *parent)
 87.5458 +static void R_SetParent(bspNode_t * node, bspNode_t * parent)
 87.5459  {
 87.5460  	node->parent = parent;
 87.5461 -	if (node->contents != -1)
 87.5462 +	if(node->contents != -1)
 87.5463  		return;
 87.5464 -	R_SetParent (node->children[0], node);
 87.5465 -	R_SetParent (node->children[1], node);
 87.5466 +	R_SetParent(node->children[0], node);
 87.5467 +	R_SetParent(node->children[1], node);
 87.5468  }
 87.5469  
 87.5470  /*
 87.5471 @@ -1363,75 +4805,78 @@
 87.5472  R_LoadNodesAndLeafs
 87.5473  =================
 87.5474  */
 87.5475 -static	void R_LoadNodesAndLeafs (lump_t *nodeLump, lump_t *leafLump) {
 87.5476 -	int			i, j, p;
 87.5477 -	dnode_t		*in;
 87.5478 -	dleaf_t		*inLeaf;
 87.5479 -	mnode_t 	*out;
 87.5480 -	int			numNodes, numLeafs;
 87.5481 +static void R_LoadNodesAndLeafs(lump_t * nodeLump, lump_t * leafLump)
 87.5482 +{
 87.5483 +	int             i, j, p;
 87.5484 +	dnode_t        *in;
 87.5485 +	dleaf_t        *inLeaf;
 87.5486 +	bspNode_t      *out;
 87.5487 +	int             numNodes, numLeafs;
 87.5488 +
 87.5489 +	ri.Printf(PRINT_ALL, "...loading nodes and leaves\n");
 87.5490  
 87.5491  	in = (void *)(fileBase + nodeLump->fileofs);
 87.5492 -	if (nodeLump->filelen % sizeof(dnode_t) ||
 87.5493 -		leafLump->filelen % sizeof(dleaf_t) ) {
 87.5494 -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
 87.5495 +	if(nodeLump->filelen % sizeof(dnode_t) || leafLump->filelen % sizeof(dleaf_t))
 87.5496 +	{
 87.5497 +		ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
 87.5498  	}
 87.5499  	numNodes = nodeLump->filelen / sizeof(dnode_t);
 87.5500  	numLeafs = leafLump->filelen / sizeof(dleaf_t);
 87.5501  
 87.5502 -	out = ri.Hunk_Alloc ( (numNodes + numLeafs) * sizeof(*out), h_low);	
 87.5503 +	out = ri.Hunk_Alloc((numNodes + numLeafs) * sizeof(*out), h_low);
 87.5504  
 87.5505  	s_worldData.nodes = out;
 87.5506  	s_worldData.numnodes = numNodes + numLeafs;
 87.5507  	s_worldData.numDecisionNodes = numNodes;
 87.5508  
 87.5509  	// load nodes
 87.5510 -	for ( i=0 ; i<numNodes; i++, in++, out++)
 87.5511 -	{
 87.5512 -		for (j=0 ; j<3 ; j++)
 87.5513 -		{
 87.5514 -			out->mins[j] = LittleLong (in->mins[j]);
 87.5515 -			out->maxs[j] = LittleLong (in->maxs[j]);
 87.5516 -		}
 87.5517 -	
 87.5518 +	for(i = 0; i < numNodes; i++, in++, out++)
 87.5519 +	{
 87.5520 +		for(j = 0; j < 3; j++)
 87.5521 +		{
 87.5522 +			out->mins[j] = LittleLong(in->mins[j]);
 87.5523 +			out->maxs[j] = LittleLong(in->maxs[j]);
 87.5524 +		}
 87.5525 +
 87.5526  		p = LittleLong(in->planeNum);
 87.5527  		out->plane = s_worldData.planes + p;
 87.5528  
 87.5529  		out->contents = CONTENTS_NODE;	// differentiate from leafs
 87.5530  
 87.5531 -		for (j=0 ; j<2 ; j++)
 87.5532 -		{
 87.5533 -			p = LittleLong (in->children[j]);
 87.5534 -			if (p >= 0)
 87.5535 +		for(j = 0; j < 2; j++)
 87.5536 +		{
 87.5537 +			p = LittleLong(in->children[j]);
 87.5538 +			if(p >= 0)
 87.5539  				out->children[j] = s_worldData.nodes + p;
 87.5540  			else
 87.5541  				out->children[j] = s_worldData.nodes + numNodes + (-1 - p);
 87.5542  		}
 87.5543  	}
 87.5544 -	
 87.5545 +
 87.5546  	// load leafs
 87.5547  	inLeaf = (void *)(fileBase + leafLump->fileofs);
 87.5548 -	for ( i=0 ; i<numLeafs ; i++, inLeaf++, out++)
 87.5549 -	{
 87.5550 -		for (j=0 ; j<3 ; j++)
 87.5551 -		{
 87.5552 -			out->mins[j] = LittleLong (inLeaf->mins[j]);
 87.5553 -			out->maxs[j] = LittleLong (inLeaf->maxs[j]);
 87.5554 +	for(i = 0; i < numLeafs; i++, inLeaf++, out++)
 87.5555 +	{
 87.5556 +		for(j = 0; j < 3; j++)
 87.5557 +		{
 87.5558 +			out->mins[j] = LittleLong(inLeaf->mins[j]);
 87.5559 +			out->maxs[j] = LittleLong(inLeaf->maxs[j]);
 87.5560  		}
 87.5561  
 87.5562  		out->cluster = LittleLong(inLeaf->cluster);
 87.5563  		out->area = LittleLong(inLeaf->area);
 87.5564  
 87.5565 -		if ( out->cluster >= s_worldData.numClusters ) {
 87.5566 +		if(out->cluster >= s_worldData.numClusters)
 87.5567 +		{
 87.5568  			s_worldData.numClusters = out->cluster + 1;
 87.5569  		}
 87.5570  
 87.5571 -		out->firstmarksurface = s_worldData.marksurfaces +
 87.5572 -			LittleLong(inLeaf->firstLeafSurface);
 87.5573 -		out->nummarksurfaces = LittleLong(inLeaf->numLeafSurfaces);
 87.5574 -	}	
 87.5575 +		out->markSurfaces = s_worldData.markSurfaces + LittleLong(inLeaf->firstLeafSurface);
 87.5576 +		out->numMarkSurfaces = LittleLong(inLeaf->numLeafSurfaces);
 87.5577 +	}
 87.5578  
 87.5579  	// chain decendants
 87.5580 -	R_SetParent (s_worldData.nodes, NULL);
 87.5581 +	R_SetParent(s_worldData.nodes, NULL);
 87.5582  }
 87.5583  
 87.5584  //=============================================================================
 87.5585 @@ -1441,24 +4886,30 @@
 87.5586  R_LoadShaders
 87.5587  =================
 87.5588  */
 87.5589 -static	void R_LoadShaders( lump_t *l ) {	
 87.5590 -	int		i, count;
 87.5591 -	dshader_t	*in, *out;
 87.5592 -	
 87.5593 +static void R_LoadShaders(lump_t * l)
 87.5594 +{
 87.5595 +	int             i, count;
 87.5596 +	dshader_t      *in, *out;
 87.5597 +
 87.5598 +	ri.Printf(PRINT_ALL, "...loading shaders\n");
 87.5599 +
 87.5600  	in = (void *)(fileBase + l->fileofs);
 87.5601 -	if (l->filelen % sizeof(*in))
 87.5602 -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
 87.5603 +	if(l->filelen % sizeof(*in))
 87.5604 +		ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
 87.5605  	count = l->filelen / sizeof(*in);
 87.5606 -	out = ri.Hunk_Alloc ( count*sizeof(*out), h_low );
 87.5607 +	out = ri.Hunk_Alloc(count * sizeof(*out), h_low);
 87.5608  
 87.5609  	s_worldData.shaders = out;
 87.5610  	s_worldData.numShaders = count;
 87.5611  
 87.5612 -	Com_Memcpy( out, in, count*sizeof(*out) );
 87.5613 -
 87.5614 -	for ( i=0 ; i<count ; i++ ) {
 87.5615 -		out[i].surfaceFlags = LittleLong( out[i].surfaceFlags );
 87.5616 -		out[i].contentFlags = LittleLong( out[i].contentFlags );
 87.5617 +	Com_Memcpy(out, in, count * sizeof(*out));
 87.5618 +
 87.5619 +	for(i = 0; i < count; i++)
 87.5620 +	{
 87.5621 +		ri.Printf(PRINT_DEVELOPER, "shader: '%s'\n", out[i].shader);
 87.5622 +
 87.5623 +		out[i].surfaceFlags = LittleLong(out[i].surfaceFlags);
 87.5624 +		out[i].contentFlags = LittleLong(out[i].contentFlags);
 87.5625  	}
 87.5626  }
 87.5627  
 87.5628 @@ -1468,22 +4919,24 @@
 87.5629  R_LoadMarksurfaces
 87.5630  =================
 87.5631  */
 87.5632 -static	void R_LoadMarksurfaces (lump_t *l)
 87.5633 -{	
 87.5634 -	int		i, j, count;
 87.5635 -	int		*in;
 87.5636 -	msurface_t **out;
 87.5637 -	
 87.5638 +static void R_LoadMarksurfaces(lump_t * l)
 87.5639 +{
 87.5640 +	int             i, j, count;
 87.5641 +	int            *in;
 87.5642 +	bspSurface_t  **out;
 87.5643 +
 87.5644 +	ri.Printf(PRINT_ALL, "...loading mark surfaces\n");
 87.5645 +
 87.5646  	in = (void *)(fileBase + l->fileofs);
 87.5647 -	if (l->filelen % sizeof(*in))
 87.5648 -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
 87.5649 +	if(l->filelen % sizeof(*in))
 87.5650 +		ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
 87.5651  	count = l->filelen / sizeof(*in);
 87.5652 -	out = ri.Hunk_Alloc ( count*sizeof(*out), h_low);	
 87.5653 -
 87.5654 -	s_worldData.marksurfaces = out;
 87.5655 -	s_worldData.nummarksurfaces = count;
 87.5656 -
 87.5657 -	for ( i=0 ; i<count ; i++)
 87.5658 +	out = ri.Hunk_Alloc(count * sizeof(*out), h_low);
 87.5659 +
 87.5660 +	s_worldData.markSurfaces = out;
 87.5661 +	s_worldData.numMarkSurfaces = count;
 87.5662 +
 87.5663 +	for(i = 0; i < count; i++)
 87.5664  	{
 87.5665  		j = LittleLong(in[i]);
 87.5666  		out[i] = s_worldData.surfaces + j;
 87.5667 @@ -1496,164 +4949,60 @@
 87.5668  R_LoadPlanes
 87.5669  =================
 87.5670  */
 87.5671 -static	void R_LoadPlanes( lump_t *l ) {
 87.5672 -	int			i, j;
 87.5673 -	cplane_t	*out;
 87.5674 -	dplane_t 	*in;
 87.5675 -	int			count;
 87.5676 -	int			bits;
 87.5677 -	
 87.5678 +static void R_LoadPlanes(lump_t * l)
 87.5679 +{
 87.5680 +	int             i, j;
 87.5681 +	cplane_t       *out;
 87.5682 +	dplane_t       *in;
 87.5683 +	int             count;
 87.5684 +	int             bits;
 87.5685 +
 87.5686 +	ri.Printf(PRINT_ALL, "...loading planes\n");
 87.5687 +
 87.5688  	in = (void *)(fileBase + l->fileofs);
 87.5689 -	if (l->filelen % sizeof(*in))
 87.5690 -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
 87.5691 +	if(l->filelen % sizeof(*in))
 87.5692 +		ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
 87.5693  	count = l->filelen / sizeof(*in);
 87.5694 -	out = ri.Hunk_Alloc ( count*2*sizeof(*out), h_low);	
 87.5695 -	
 87.5696 +	out = ri.Hunk_Alloc(count * 2 * sizeof(*out), h_low);
 87.5697 +
 87.5698  	s_worldData.planes = out;
 87.5699  	s_worldData.numplanes = count;
 87.5700  
 87.5701 -	for ( i=0 ; i<count ; i++, in++, out++) {
 87.5702 +	for(i = 0; i < count; i++, in++, out++)
 87.5703 +	{
 87.5704  		bits = 0;
 87.5705 -		for (j=0 ; j<3 ; j++) {
 87.5706 -			out->normal[j] = LittleFloat (in->normal[j]);
 87.5707 -			if (out->normal[j] < 0) {
 87.5708 -				bits |= 1<<j;
 87.5709 -			}
 87.5710 -		}
 87.5711 -
 87.5712 -		out->dist = LittleFloat (in->dist);
 87.5713 -		out->type = PlaneTypeForNormal( out->normal );
 87.5714 +		for(j = 0; j < 3; j++)
 87.5715 +		{
 87.5716 +			out->normal[j] = LittleFloat(in->normal[j]);
 87.5717 +			if(out->normal[j] < 0)
 87.5718 +			{
 87.5719 +				bits |= 1 << j;
 87.5720 +			}
 87.5721 +		}
 87.5722 +
 87.5723 +		out->dist = LittleFloat(in->dist);
 87.5724 +		out->type = PlaneTypeForNormal(out->normal);
 87.5725  		out->signbits = bits;
 87.5726  	}
 87.5727  }
 87.5728  
 87.5729 -/*
 87.5730 -=================
 87.5731 -R_LoadFogs
 87.5732 -
 87.5733 -=================
 87.5734 -*/
 87.5735 -static	void R_LoadFogs( lump_t *l, lump_t *brushesLump, lump_t *sidesLump ) {
 87.5736 -	int			i;
 87.5737 -	fog_t		*out;
 87.5738 -	dfog_t		*fogs;
 87.5739 -	dbrush_t 	*brushes, *brush;
 87.5740 -	dbrushside_t	*sides;
 87.5741 -	int			count, brushesCount, sidesCount;
 87.5742 -	int			sideNum;
 87.5743 -	int			planeNum;
 87.5744 -	shader_t	*shader;
 87.5745 -	float		d;
 87.5746 -	int			firstSide;
 87.5747 -
 87.5748 -	fogs = (void *)(fileBase + l->fileofs);
 87.5749 -	if (l->filelen % sizeof(*fogs)) {
 87.5750 -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
 87.5751 -	}
 87.5752 -	count = l->filelen / sizeof(*fogs);
 87.5753 -
 87.5754 -	// create fog strucutres for them
 87.5755 -	s_worldData.numfogs = count + 1;
 87.5756 -	s_worldData.fogs = ri.Hunk_Alloc ( s_worldData.numfogs*sizeof(*out), h_low);
 87.5757 -	out = s_worldData.fogs + 1;
 87.5758 -
 87.5759 -	if ( !count ) {
 87.5760 -		return;
 87.5761 -	}
 87.5762 -
 87.5763 -	brushes = (void *)(fileBase + brushesLump->fileofs);
 87.5764 -	if (brushesLump->filelen % sizeof(*brushes)) {
 87.5765 -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
 87.5766 -	}
 87.5767 -	brushesCount = brushesLump->filelen / sizeof(*brushes);
 87.5768 -
 87.5769 -	sides = (void *)(fileBase + sidesLump->fileofs);
 87.5770 -	if (sidesLump->filelen % sizeof(*sides)) {
 87.5771 -		ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
 87.5772 -	}
 87.5773 -	sidesCount = sidesLump->filelen / sizeof(*sides);
 87.5774 -
 87.5775 -	for ( i=0 ; i<count ; i++, fogs++) {
 87.5776 -		out->originalBrushNumber = LittleLong( fogs->brushNum );
 87.5777 -
 87.5778 -		if ( (unsigned)out->originalBrushNumber >= brushesCount ) {
 87.5779 -			ri.Error( ERR_DROP, "fog brushNumber out of range" );
 87.5780 -		}
 87.5781 -		brush = brushes + out->originalBrushNumber;
 87.5782 -
 87.5783 -		firstSide = LittleLong( brush->firstSide );
 87.5784 -
 87.5785 -			if ( (unsigned)firstSide > sidesCount - 6 ) {
 87.5786 -			ri.Error( ERR_DROP, "fog brush sideNumber out of range" );
 87.5787 -		}
 87.5788 -
 87.5789 -		// brushes are always sorted with the axial sides first
 87.5790 -		sideNum = firstSide + 0;
 87.5791 -		planeNum = LittleLong( sides[ sideNum ].planeNum );
 87.5792 -		out->bounds[0][0] = -s_worldData.planes[ planeNum ].dist;
 87.5793 -
 87.5794 -		sideNum = firstSide + 1;
 87.5795 -		planeNum = LittleLong( sides[ sideNum ].planeNum );
 87.5796 -		out->bounds[1][0] = s_worldData.planes[ planeNum ].dist;
 87.5797 -
 87.5798 -		sideNum = firstSide + 2;
 87.5799 -		planeNum = LittleLong( sides[ sideNum ].planeNum );
 87.5800 -		out->bounds[0][1] = -s_worldData.planes[ planeNum ].dist;
 87.5801 -
 87.5802 -		sideNum = firstSide + 3;
 87.5803 -		planeNum = LittleLong( sides[ sideNum ].planeNum );
 87.5804 -		out->bounds[1][1] = s_worldData.planes[ planeNum ].dist;
 87.5805 -
 87.5806 -		sideNum = firstSide + 4;
 87.5807 -		planeNum = LittleLong( sides[ sideNum ].planeNum );
 87.5808 -		out->bounds[0][2] = -s_worldData.planes[ planeNum ].dist;
 87.5809 -
 87.5810 -		sideNum = firstSide + 5;
 87.5811 -		planeNum = LittleLong( sides[ sideNum ].planeNum );
 87.5812 -		out->bounds[1][2] = s_worldData.planes[ planeNum ].dist;
 87.5813 -
 87.5814 -		// get information from the shader for fog parameters
 87.5815 -		shader = R_FindShader( fogs->shader, LIGHTMAP_NONE, qtrue );
 87.5816 -
 87.5817 -		out->parms = shader->fogParms;
 87.5818 -
 87.5819 -		out->colorInt = ColorBytes4 ( shader->fogParms.color[0] * tr.identityLight, 
 87.5820 -			                          shader->fogParms.color[1] * tr.identityLight, 
 87.5821 -			                          shader->fogParms.color[2] * tr.identityLight, 1.0 );
 87.5822 -
 87.5823 -		d = shader->fogParms.depthForOpaque < 1 ? 1 : shader->fogParms.depthForOpaque;
 87.5824 -		out->tcScale = 1.0f / ( d * 8 );
 87.5825 -
 87.5826 -		// set the gradient vector
 87.5827 -		sideNum = LittleLong( fogs->visibleSide );
 87.5828 -
 87.5829 -		if ( sideNum == -1 ) {
 87.5830 -			out->hasSurface = qfalse;
 87.5831 -		} else {
 87.5832 -			out->hasSurface = qtrue;
 87.5833 -			planeNum = LittleLong( sides[ firstSide + sideNum ].planeNum );
 87.5834 -			VectorSubtract( vec3_origin, s_worldData.planes[ planeNum ].normal, out->surface );
 87.5835 -			out->surface[3] = -s_worldData.planes[ planeNum ].dist;
 87.5836 -		}
 87.5837 -
 87.5838 -		out++;
 87.5839 -	}
 87.5840 -
 87.5841 -}
 87.5842 -
 87.5843  
 87.5844  /*
 87.5845  ================
 87.5846  R_LoadLightGrid
 87.5847 -
 87.5848  ================
 87.5849  */
 87.5850 -void R_LoadLightGrid( lump_t *l ) {
 87.5851 -	int		i;
 87.5852 -	vec3_t	maxs;
 87.5853 -	int		numGridPoints;
 87.5854 -	world_t	*w;
 87.5855 -	float	*wMins, *wMaxs;
 87.5856 +void R_LoadLightGrid(lump_t * l)
 87.5857 +{
 87.5858 +	int             i, j;
 87.5859 +	vec3_t          maxs;
 87.5860 +	int             numGridPoints;
 87.5861 +	world_t        *w;
 87.5862 +	float          *wMins, *wMaxs;
 87.5863 +	dgridPoint_t   *in;
 87.5864 +	bspGridPoint_t *out;
 87.5865 +
 87.5866 +	ri.Printf(PRINT_ALL, "...loading light grid\n");
 87.5867  
 87.5868  	w = &s_worldData;
 87.5869  
 87.5870 @@ -1661,31 +5010,88 @@
 87.5871  	w->lightGridInverseSize[1] = 1.0f / w->lightGridSize[1];
 87.5872  	w->lightGridInverseSize[2] = 1.0f / w->lightGridSize[2];
 87.5873  
 87.5874 -	wMins = w->bmodels[0].bounds[0];
 87.5875 -	wMaxs = w->bmodels[0].bounds[1];
 87.5876 -
 87.5877 -	for ( i = 0 ; i < 3 ; i++ ) {
 87.5878 -		w->lightGridOrigin[i] = w->lightGridSize[i] * ceil( wMins[i] / w->lightGridSize[i] );
 87.5879 -		maxs[i] = w->lightGridSize[i] * floor( wMaxs[i] / w->lightGridSize[i] );
 87.5880 -		w->lightGridBounds[i] = (maxs[i] - w->lightGridOrigin[i])/w->lightGridSize[i] + 1;
 87.5881 +	wMins = w->models[0].bounds[0];
 87.5882 +	wMaxs = w->models[0].bounds[1];
 87.5883 +
 87.5884 +	for(i = 0; i < 3; i++)
 87.5885 +	{
 87.5886 +		w->lightGridOrigin[i] = w->lightGridSize[i] * ceil(wMins[i] / w->lightGridSize[i]);
 87.5887 +		maxs[i] = w->lightGridSize[i] * floor(wMaxs[i] / w->lightGridSize[i]);
 87.5888 +		w->lightGridBounds[i] = (maxs[i] - w->lightGridOrigin[i]) / w->lightGridSize[i] + 1;
 87.5889  	}
 87.5890  
 87.5891  	numGridPoints = w->lightGridBounds[0] * w->lightGridBounds[1] * w->lightGridBounds[2];
 87.5892  
 87.5893 -	if ( l->filelen != numGridPoints * 8 ) {
 87.5894 -		ri.Printf( PRINT_WARNING, "WARNING: light grid mismatch\n" );
 87.5895 +	if(l->filelen != numGridPoints * sizeof(dgridPoint_t))
 87.5896 +	{
 87.5897 +		ri.Printf(PRINT_WARNING, "WARNING: light grid mismatch\n");
 87.5898  		w->lightGridData = NULL;
 87.5899  		return;
 87.5900  	}
 87.5901  
 87.5902 -	w->lightGridData = ri.Hunk_Alloc( l->filelen, h_low );
 87.5903 -	Com_Memcpy( w->lightGridData, (void *)(fileBase + l->fileofs), l->filelen );
 87.5904 -
 87.5905 -	// deal with overbright bits
 87.5906 -	for ( i = 0 ; i < numGridPoints ; i++ ) {
 87.5907 -		R_ColorShiftLightingBytes( &w->lightGridData[i*8], &w->lightGridData[i*8] );
 87.5908 -		R_ColorShiftLightingBytes( &w->lightGridData[i*8+3], &w->lightGridData[i*8+3] );
 87.5909 -	}
 87.5910 +	in = (void *)(fileBase + l->fileofs);
 87.5911 +	if(l->filelen % sizeof(*in))
 87.5912 +		ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
 87.5913 +	out = ri.Hunk_Alloc(numGridPoints * sizeof(*out), h_low);
 87.5914 +
 87.5915 +	w->lightGridData = out;
 87.5916 +	//Com_Memcpy(w->lightGridData, (void *)(fileBase + l->fileofs), l->filelen);
 87.5917 +
 87.5918 +	for(i = 0; i < numGridPoints; i++, in++, out++)
 87.5919 +	{
 87.5920 +#if defined(COMPAT_Q3A)
 87.5921 +		byte		tmpAmbient[4];
 87.5922 +		byte		tmpDirected[4];
 87.5923 +
 87.5924 +		tmpAmbient[0] = in->ambient[0];
 87.5925 +		tmpAmbient[1] = in->ambient[1];
 87.5926 +		tmpAmbient[2] = in->ambient[2];
 87.5927 +		tmpAmbient[3] = 255;
 87.5928 +
 87.5929 +		tmpDirected[0] = in->directed[0];
 87.5930 +		tmpDirected[1] = in->directed[1];
 87.5931 +		tmpDirected[2] = in->directed[2];
 87.5932 +		tmpDirected[3] = 255;
 87.5933 +
 87.5934 +		R_ColorShiftLightingBytes(tmpAmbient, tmpAmbient);
 87.5935 +		R_ColorShiftLightingBytes(tmpDirected, tmpDirected);
 87.5936 +
 87.5937 +		for(j = 0; j < 3; j++)
 87.5938 +		{
 87.5939 +			out->ambient[j] = tmpAmbient[j] * (1.0f / 255.0f);
 87.5940 +			out->directed[j] = tmpDirected[j] * (1.0f / 255.0f);
 87.5941 +		}
 87.5942 +#else
 87.5943 +		for(j = 0; j < 3; j++)
 87.5944 +		{
 87.5945 +
 87.5946 +			out->ambient[j] = LittleFloat(in->ambient[j]);
 87.5947 +			out->directed[j] = LittleFloat(in->directed[j]);
 87.5948 +		}
 87.5949 +#endif
 87.5950 +
 87.5951 +		out->ambient[3] = 1.0f;
 87.5952 +		out->directed[3] = 1.0f;
 87.5953 +
 87.5954 +		for(j = 0; j < 2; j++)
 87.5955 +		{
 87.5956 +			out->latLong[j] = in->latLong[j];
 87.5957 +		}
 87.5958 +
 87.5959 +#if 0
 87.5960 +		// debug print to see if the XBSP format is correct
 87.5961 +		ri.Printf(PRINT_ALL, "%9d Amb: (%03.1f %03.1f %03.1f) Dir: (%03.1f %03.1f %03.1f)\n",
 87.5962 +			  i, out->ambient[0], out->ambient[1], out->ambient[2], out->directed[0], out->directed[1], out->directed[2]);
 87.5963 +#endif
 87.5964 +
 87.5965 +#if !defined(COMPAT_Q3A)
 87.5966 +		// deal with overbright bits
 87.5967 +		R_HDRTonemapLightingColors(out->ambient, out->ambient, qtrue);
 87.5968 +		R_HDRTonemapLightingColors(out->directed, out->directed, qtrue);
 87.5969 +#endif
 87.5970 +	}
 87.5971 +
 87.5972 +	ri.Printf(PRINT_ALL, "%i light grid points created\n", numGridPoints);
 87.5973  }
 87.5974  
 87.5975  /*
 87.5976 @@ -1693,99 +5099,3075 @@
 87.5977  R_LoadEntities
 87.5978  ================
 87.5979  */
 87.5980 -void R_LoadEntities( lump_t *l ) {
 87.5981 -	char *p, *token, *s;
 87.5982 -	char keyname[MAX_TOKEN_CHARS];
 87.5983 -	char value[MAX_TOKEN_CHARS];
 87.5984 -	world_t	*w;
 87.5985 +void R_LoadEntities(lump_t * l)
 87.5986 +{
 87.5987 +	int             i;
 87.5988 +	char           *p, *pOld, *token, *s;
 87.5989 +	char            keyname[MAX_TOKEN_CHARS];
 87.5990 +	char            value[MAX_TOKEN_CHARS];
 87.5991 +	world_t        *w;
 87.5992 +	qboolean        isLight = qfalse;
 87.5993 +	int             numEntities = 0;
 87.5994 +	int             numLights = 0;
 87.5995 +	int             numOmniLights = 0;
 87.5996 +	int             numProjLights = 0;
 87.5997 +	trRefLight_t   *light;
 87.5998 +
 87.5999 +	ri.Printf(PRINT_ALL, "...loading entities\n");
 87.6000  
 87.6001  	w = &s_worldData;
 87.6002  	w->lightGridSize[0] = 64;
 87.6003  	w->lightGridSize[1] = 64;
 87.6004  	w->lightGridSize[2] = 128;
 87.6005  
 87.6006 +	// store for reference by the cgame
 87.6007 +	w->entityString = ri.Hunk_Alloc(l->filelen + 1, h_low);
 87.6008 +	//strcpy(w->entityString, (char *)(fileBase + l->fileofs));
 87.6009 +	Q_strncpyz(w->entityString, (char *)(fileBase + l->fileofs), l->filelen + 1);
 87.6010 +	w->entityParsePoint = w->entityString;
 87.6011 +
 87.6012 +#if 1
 87.6013 +	p = w->entityString;
 87.6014 +#else
 87.6015  	p = (char *)(fileBase + l->fileofs);
 87.6016 -
 87.6017 -	// store for reference by the cgame
 87.6018 -	w->entityString = ri.Hunk_Alloc( l->filelen + 1, h_low );
 87.6019 -	strcpy( w->entityString, p );
 87.6020 -	w->entityParsePoint = w->entityString;
 87.6021 -
 87.6022 -	token = COM_ParseExt( &p, qtrue );
 87.6023 -	if (!*token || *token != '{') {
 87.6024 -		return;
 87.6025 -	}
 87.6026 +#endif
 87.6027  
 87.6028  	// only parse the world spawn
 87.6029 -	while ( 1 ) {	
 87.6030 +	while(1)
 87.6031 +	{
 87.6032  		// parse key
 87.6033 -		token = COM_ParseExt( &p, qtrue );
 87.6034 -
 87.6035 -		if ( !*token || *token == '}' ) {
 87.6036 +		token = Com_ParseExt(&p, qtrue);
 87.6037 +
 87.6038 +		if(!*token)
 87.6039 +		{
 87.6040 +			ri.Printf(PRINT_WARNING, "WARNING: unexpected end of entities string while parsing worldspawn\n", token);
 87.6041  			break;
 87.6042  		}
 87.6043 +
 87.6044 +		if(*token == '{')
 87.6045 +		{
 87.6046 +			continue;
 87.6047 +		}
 87.6048 +
 87.6049 +		if(*token == '}')
 87.6050 +		{
 87.6051 +			break;
 87.6052 +		}
 87.6053 +
 87.6054  		Q_strncpyz(keyname, token, sizeof(keyname));
 87.6055  
 87.6056  		// parse value
 87.6057 -		token = COM_ParseExt( &p, qtrue );
 87.6058 -
 87.6059 -		if ( !*token || *token == '}' ) {
 87.6060 -			break;
 87.6061 -		}
 87.6062 +		token = Com_ParseExt(&p, qfalse);
 87.6063 +
 87.6064 +		if(!*token)
 87.6065 +		{
 87.6066 +			continue;
 87.6067 +		}
 87.6068 +
 87.6069  		Q_strncpyz(value, token, sizeof(value));
 87.6070  
 87.6071  		// check for remapping of shaders for vertex lighting
 87.6072  		s = "vertexremapshader";
 87.6073 -		if (!Q_strncmp(keyname, s, strlen(s)) ) {
 87.6074 +		if(!Q_strncmp(keyname, s, strlen(s)))
 87.6075 +		{
 87.6076  			s = strchr(value, ';');
 87.6077 -			if (!s) {
 87.6078 -				ri.Printf( PRINT_WARNING, "WARNING: no semi colon in vertexshaderremap '%s'\n", value );
 87.6079 +			if(!s)
 87.6080 +			{
 87.6081 +				ri.Printf(PRINT_WARNING, "WARNING: no semi colon in vertexshaderremap '%s'\n", value);
 87.6082  				break;
 87.6083  			}
 87.6084  			*s++ = 0;
 87.6085 -			if (r_vertexLight->integer) {
 87.6086 -				R_RemapShader(value, s, "0");
 87.6087 -			}
 87.6088  			continue;
 87.6089  		}
 87.6090 +
 87.6091  		// check for remapping of shaders
 87.6092  		s = "remapshader";
 87.6093 -		if (!Q_strncmp(keyname, s, strlen(s)) ) {
 87.6094 +		if(!Q_strncmp(keyname, s, strlen(s)))
 87.6095 +		{
 87.6096  			s = strchr(value, ';');
 87.6097 -			if (!s) {
 87.6098 -				ri.Printf( PRINT_WARNING, "WARNING: no semi colon in shaderremap '%s'\n", value );
 87.6099 +			if(!s)
 87.6100 +			{
 87.6101 +				ri.Printf(PRINT_WARNING, "WARNING: no semi colon in shaderremap '%s'\n", value);
 87.6102  				break;
 87.6103  			}
 87.6104  			*s++ = 0;
 87.6105  			R_RemapShader(value, s, "0");
 87.6106  			continue;
 87.6107  		}
 87.6108 +
 87.6109  		// check for a different grid size
 87.6110 -		if (!Q_stricmp(keyname, "gridsize")) {
 87.6111 -			sscanf(value, "%f %f %f", &w->lightGridSize[0], &w->lightGridSize[1], &w->lightGridSize[2] );
 87.6112 +		if(!Q_stricmp(keyname, "gridsize"))
 87.6113 +		{
 87.6114 +			sscanf(value, "%f %f %f", &w->lightGridSize[0], &w->lightGridSize[1], &w->lightGridSize[2]);
 87.6115  			continue;
 87.6116  		}
 87.6117 -	}
 87.6118 +
 87.6119 +		// check for ambient color
 87.6120 +		else if(!Q_stricmp(keyname, "_color") || !Q_stricmp(keyname, "ambientColor"))
 87.6121 +		{
 87.6122 +			if(r_forceAmbient->value <= 0)
 87.6123 +			{
 87.6124 +				sscanf(value, "%f %f %f", &tr.worldEntity.ambientLight[0], &tr.worldEntity.ambientLight[1],
 87.6125 +					   &tr.worldEntity.ambientLight[2]);
 87.6126 +
 87.6127 +				VectorCopy(tr.worldEntity.ambientLight, tr.worldEntity.ambientLight);
 87.6128 +				VectorScale(tr.worldEntity.ambientLight, r_ambientScale->value, tr.worldEntity.ambientLight);
 87.6129 +			}
 87.6130 +		}
 87.6131 +
 87.6132 +		// check for fog color
 87.6133 +		else if(!Q_stricmp(keyname, "fogColor"))
 87.6134 +		{
 87.6135 +			sscanf(value, "%f %f %f", &tr.fogColor[0], &tr.fogColor[1], &tr.fogColor[2]);
 87.6136 +		}
 87.6137 +
 87.6138 +		// check for fog density
 87.6139 +		else if(!Q_stricmp(keyname, "fogDensity"))
 87.6140 +		{
 87.6141 +			tr.fogDensity = atof(value);
 87.6142 +		}
 87.6143 +
 87.6144 +		// check for deluxe mapping support
 87.6145 +		if(!Q_stricmp(keyname, "deluxeMapping") && !Q_stricmp(value, "1"))
 87.6146 +		{
 87.6147 +			ri.Printf(PRINT_ALL, "map features directional light mapping\n");
 87.6148 +			tr.worldDeluxeMapping = qtrue;
 87.6149 +			continue;
 87.6150 +		}
 87.6151 +
 87.6152 +		// check for HDR light mapping support
 87.6153 +		if(!Q_stricmp(keyname, "hdrRGBE") && !Q_stricmp(value, "1"))
 87.6154 +		{
 87.6155 +			ri.Printf(PRINT_ALL, "map features HDR light mapping\n");
 87.6156 +			tr.worldHDR_RGBE = qtrue;
 87.6157 +			continue;
 87.6158 +		}
 87.6159 +
 87.6160 +		if(!Q_stricmp(keyname, "classname") && Q_stricmp(value, "worldspawn"))
 87.6161 +		{
 87.6162 +			ri.Printf(PRINT_WARNING, "WARNING: expected worldspawn found '%s'\n", value);
 87.6163 +			continue;
 87.6164 +		}
 87.6165 +	}
 87.6166 +
 87.6167 +//  ri.Printf(PRINT_ALL, "-----------\n%s\n----------\n", p);
 87.6168 +
 87.6169 +	pOld = p;
 87.6170 +	numEntities = 1;			// parsed worldspawn so far
 87.6171 +
 87.6172 +	// count lights
 87.6173 +	while(1)
 87.6174 +	{
 87.6175 +		// parse {
 87.6176 +		token = Com_ParseExt(&p, qtrue);
 87.6177 +
 87.6178 +		if(!*token)
 87.6179 +		{
 87.6180 +			// end of entities string
 87.6181 +			break;
 87.6182 +		}
 87.6183 +
 87.6184 +		if(*token != '{')
 87.6185 +		{
 87.6186 +			ri.Printf(PRINT_WARNING, "WARNING: expected { found '%s'\n", token);
 87.6187 +			break;
 87.6188 +		}
 87.6189 +
 87.6190 +		// new entity
 87.6191 +		isLight = qfalse;
 87.6192 +
 87.6193 +		// parse epairs
 87.6194 +		while(1)
 87.6195 +		{
 87.6196 +			// parse key
 87.6197 +			token = Com_ParseExt(&p, qtrue);
 87.6198 +
 87.6199 +			if(*token == '}')
 87.6200 +			{
 87.6201 +				break;
 87.6202 +			}
 87.6203 +
 87.6204 +			if(!*token)
 87.6205 +			{
 87.6206 +				ri.Printf(PRINT_WARNING, "WARNING: EOF without closing bracket\n");
 87.6207 +				break;
 87.6208 +			}
 87.6209 +
 87.6210 +			Q_strncpyz(keyname, token, sizeof(keyname));
 87.6211 +
 87.6212 +			// parse value
 87.6213 +			token = Com_ParseExt(&p, qfalse);
 87.6214 +
 87.6215 +			if(!*token)
 87.6216 +			{
 87.6217 +				ri.Printf(PRINT_WARNING, "WARNING: missing value for key '%s'\n", keyname);
 87.6218 +				continue;
 87.6219 +			}
 87.6220 +
 87.6221 +			Q_strncpyz(value, token, sizeof(value));
 87.6222 +
 87.6223 +			// check if this entity is a light
 87.6224 +			if(!Q_stricmp(keyname, "classname") && !Q_stricmp(value, "light"))
 87.6225 +			{
 87.6226 +				isLight = qtrue;
 87.6227 +			}
 87.6228 +		}
 87.6229 +
 87.6230 +		if(*token != '}')
 87.6231 +		{
 87.6232 +			ri.Printf(PRINT_WARNING, "WARNING: expected } found '%s'\n", token);
 87.6233 +			break;
 87.6234 +		}
 87.6235 +
 87.6236 +		if(isLight)
 87.6237 +		{
 87.6238 +			numLights++;
 87.6239 +		}
 87.6240 +
 87.6241 +		numEntities++;
 87.6242 +	}
 87.6243 +
 87.6244 +	ri.Printf(PRINT_ALL, "%i total entities counted\n", numEntities);
 87.6245 +	ri.Printf(PRINT_ALL, "%i total lights counted\n", numLights);
 87.6246 +
 87.6247 +	s_worldData.numLights = numLights;
 87.6248 +	s_worldData.lights = ri.Hunk_Alloc(s_worldData.numLights * sizeof(trRefLight_t), h_low);
 87.6249 +
 87.6250 +	// basic light setup
 87.6251 +	for(i = 0, light = s_worldData.lights; i < s_worldData.numLights; i++, light++)
 87.6252 +	{
 87.6253 +		QuatClear(light->l.rotation);
 87.6254 +		VectorClear(light->l.center);
 87.6255 +
 87.6256 +		light->l.color[0] = 1;
 87.6257 +		light->l.color[1] = 1;
 87.6258 +		light->l.color[2] = 1;
 87.6259 +
 87.6260 +		light->l.scale = r_lightScale->value;
 87.6261 +
 87.6262 +		light->l.radius[0] = 300;
 87.6263 +		light->l.radius[1] = 300;
 87.6264 +		light->l.radius[2] = 300;
 87.6265 +
 87.6266 +		light->l.fovX = 90;
 87.6267 +		light->l.fovY = 90;
 87.6268 +		light->l.distNear = 1;
 87.6269 +		light->l.distFar = 300;
 87.6270 +
 87.6271 +		light->l.inverseShadows = qfalse;
 87.6272 +
 87.6273 +		light->isStatic = qtrue;
 87.6274 +		light->noRadiosity = qfalse;
 87.6275 +		light->additive = qtrue;
 87.6276 +
 87.6277 +		light->shadowLOD = 0;
 87.6278 +	}
 87.6279 +
 87.6280 +	// parse lights
 87.6281 +	p = pOld;
 87.6282 +	numEntities = 1;
 87.6283 +	light = &s_worldData.lights[0];
 87.6284 +
 87.6285 +	while(1)
 87.6286 +	{
 87.6287 +		// parse {
 87.6288 +		token = Com_ParseExt(&p, qtrue);
 87.6289 +
 87.6290 +		if(!*token)
 87.6291 +		{
 87.6292 +			// end of entities string
 87.6293 +			break;
 87.6294 +		}
 87.6295 +
 87.6296 +		if(*token != '{')
 87.6297 +		{
 87.6298 +			ri.Printf(PRINT_WARNING, "WARNING: expected { found '%s'\n", token);
 87.6299 +			break;
 87.6300 +		}
 87.6301 +
 87.6302 +		// new entity
 87.6303 +		isLight = qfalse;
 87.6304 +
 87.6305 +		// parse epairs
 87.6306 +		while(1)
 87.6307 +		{
 87.6308 +			// parse key
 87.6309 +			token = Com_ParseExt(&p, qtrue);
 87.6310 +
 87.6311 +			if(*token == '}')
 87.6312 +			{
 87.6313 +				break;
 87.6314 +			}
 87.6315 +
 87.6316 +			if(!*token)
 87.6317 +			{
 87.6318 +				ri.Printf(PRINT_WARNING, "WARNING: EOF without closing bracket\n");
 87.6319 +				break;
 87.6320 +			}
 87.6321 +
 87.6322 +			Q_strncpyz(keyname, token, sizeof(keyname));
 87.6323 +
 87.6324 +			// parse value
 87.6325 +			token = Com_ParseExt(&p, qfalse);
 87.6326 +
 87.6327 +			if(!*token)
 87.6328 +			{
 87.6329 +				ri.Printf(PRINT_WARNING, "WARNING: missing value for key '%s'\n", keyname);
 87.6330 +				continue;
 87.6331 +			}
 87.6332 +
 87.6333 +			Q_strncpyz(value, token, sizeof(value));
 87.6334 +
 87.6335 +			// check if this entity is a light
 87.6336 +			if(!Q_stricmp(keyname, "classname") && !Q_stricmp(value, "light"))
 87.6337 +			{
 87.6338 +				isLight = qtrue;
 87.6339 +			}
 87.6340 +			// check for origin
 87.6341 +			else if(!Q_stricmp(keyname, "origin") || !Q_stricmp(keyname, "light_origin"))
 87.6342 +			{
 87.6343 +				sscanf(value, "%f %f %f", &light->l.origin[0], &light->l.origin[1], &light->l.origin[2]);
 87.6344 +			}
 87.6345 +			// check for center
 87.6346 +			else if(!Q_stricmp(keyname, "light_center"))
 87.6347 +			{
 87.6348 +				sscanf(value, "%f %f %f", &light->l.center[0], &light->l.center[1], &light->l.center[2]);
 87.6349 +			}
 87.6350 +			// check for color
 87.6351 +			else if(!Q_stricmp(keyname, "_color"))
 87.6352 +			{
 87.6353 +				sscanf(value, "%f %f %f", &light->l.color[0], &light->l.color[1], &light->l.color[2]);
 87.6354 +			}
 87.6355 +			// check for radius
 87.6356 +			else if(!Q_stricmp(keyname, "light_radius"))
 87.6357 +			{
 87.6358 +				sscanf(value, "%f %f %f", &light->l.radius[0], &light->l.radius[1], &light->l.radius[2]);
 87.6359 +			}
 87.6360 +			// check for fovX
 87.6361 +			else if(!Q_stricmp(keyname, "light_fovX"))
 87.6362 +			{
 87.6363 +				light->l.fovX = atof(value);
 87.6364 +				light->l.rlType = RL_PROJ;
 87.6365 +			}
 87.6366 +			// check for fovY
 87.6367 +			else if(!Q_stricmp(keyname, "light_fovY"))
 87.6368 +			{
 87.6369 +				light->l.fovY = atof(value);
 87.6370 +				light->l.rlType = RL_PROJ;
 87.6371 +			}
 87.6372 +			// check for near
 87.6373 +			else if(!Q_stricmp(keyname, "light_near"))
 87.6374 +			{
 87.6375 +				light->l.distNear = atof(value);
 87.6376 +				light->l.rlType = RL_PROJ;
 87.6377 +			}
 87.6378 +			// check for far
 87.6379 +			else if(!Q_stricmp(keyname, "light_far"))
 87.6380 +			{
 87.6381 +				light->l.distFar = atof(value);
 87.6382 +				light->l.rlType = RL_PROJ;
 87.6383 +			}
 87.6384 +			// check for radius
 87.6385 +			else if(!Q_stricmp(keyname, "light") || !Q_stricmp(keyname, "_light"))
 87.6386 +			{
 87.6387 +				vec_t           value2;
 87.6388 +
 87.6389 +				value2 = atof(value);
 87.6390 +				light->l.radius[0] = value2;
 87.6391 +				light->l.radius[1] = value2;
 87.6392 +				light->l.radius[2] = value2;
 87.6393 +			}
 87.6394 +			// check for scale
 87.6395 +			else if(!Q_stricmp(keyname, "light_scale"))
 87.6396 +			{
 87.6397 +				light->l.scale = atof(value);
 87.6398 +
 87.6399 +				if(!r_hdrRendering->integer || !glConfig.textureFloatAvailable || !glConfig.framebufferObjectAvailable || !glConfig.framebufferBlitAvailable)
 87.6400 +				{
 87.6401 +					if(light->l.scale >= r_lightScale->value)
 87.6402 +					{
 87.6403 +						light->l.scale = r_lightScale->value;
 87.6404 +					}
 87.6405 +				}
 87.6406 +			}
 87.6407 +			// check for light shader
 87.6408 +			else if(!Q_stricmp(keyname, "texture"))
 87.6409 +			{
 87.6410 +				light->l.attenuationShader = RE_RegisterShaderLightAttenuation(value);
 87.6411 +			}
 87.6412 +			// check for rotation
 87.6413 +			else if(!Q_stricmp(keyname, "rotation") || !Q_stricmp(keyname, "light_rotation"))
 87.6414 +			{
 87.6415 +				matrix_t        rotation;
 87.6416 +
 87.6417 +				sscanf(value, "%f %f %f %f %f %f %f %f %f", &rotation[0], &rotation[1], &rotation[2],
 87.6418 +					   &rotation[4], &rotation[5], &rotation[6], &rotation[8], &rotation[9], &rotation[10]);
 87.6419 +
 87.6420 +				QuatFromMatrix(light->l.rotation, rotation);
 87.6421 +			}
 87.6422 +			// check if this light does not cast any shadows
 87.6423 +			else if(!Q_stricmp(keyname, "noshadows") && !Q_stricmp(value, "1"))
 87.6424 +			{
 87.6425 +				light->l.noShadows = qtrue;
 87.6426 +			}
 87.6427 +			// check if this light does not contribute to the global lightmapping
 87.6428 +			else if(!Q_stricmp(keyname, "noradiosity") && !Q_stricmp(value, "1"))
 87.6429 +			{
 87.6430 +				light->noRadiosity = qtrue;
 87.6431 +			}
 87.6432 +		}
 87.6433 +
 87.6434 +		if(*token != '}')
 87.6435 +		{
 87.6436 +			ri.Printf(PRINT_WARNING, "WARNING: expected } found '%s'\n", token);
 87.6437 +			break;
 87.6438 +		}
 87.6439 +
 87.6440 +		if(!isLight)
 87.6441 +		{
 87.6442 +			// reset rotation because it may be set to the rotation of other entities
 87.6443 +			QuatClear(light->l.rotation);
 87.6444 +		}
 87.6445 +		else
 87.6446 +		{
 87.6447 +			if((numOmniLights + numProjLights) < s_worldData.numLights);
 87.6448 +			{
 87.6449 +				switch (light->l.rlType)
 87.6450 +				{
 87.6451 +					case RL_OMNI:
 87.6452 +						numOmniLights++;
 87.6453 +						break;
 87.6454 +
 87.6455 +					case RL_PROJ:
 87.6456 +						numProjLights++;
 87.6457 +						break;
 87.6458 +
 87.6459 +					default:
 87.6460 +						break;
 87.6461 +				}
 87.6462 +
 87.6463 +				light++;
 87.6464 +			}
 87.6465 +		}
 87.6466 +
 87.6467 +		numEntities++;
 87.6468 +	}
 87.6469 +
 87.6470 +	if((numOmniLights + numProjLights) != s_worldData.numLights)
 87.6471 +	{
 87.6472 +		ri.Error(ERR_DROP, "counted %i lights and parsed %i lights", s_worldData.numLights, (numOmniLights + numProjLights));
 87.6473 +	}
 87.6474 +
 87.6475 +	ri.Printf(PRINT_ALL, "%i total entities parsed\n", numEntities);
 87.6476 +	ri.Printf(PRINT_ALL, "%i total lights parsed\n", numOmniLights + numProjLights);
 87.6477 +	ri.Printf(PRINT_ALL, "%i omni-directional lights parsed\n", numOmniLights);
 87.6478 +	ri.Printf(PRINT_ALL, "%i projective lights parsed\n", numProjLights);
 87.6479  }
 87.6480  
 87.6481 +
 87.6482  /*
 87.6483  =================
 87.6484  R_GetEntityToken
 87.6485  =================
 87.6486  */
 87.6487 -qboolean R_GetEntityToken( char *buffer, int size ) {
 87.6488 -	const char	*s;
 87.6489 -
 87.6490 -	s = COM_Parse( &s_worldData.entityParsePoint );
 87.6491 -	Q_strncpyz( buffer, s, size );
 87.6492 -	if ( !s_worldData.entityParsePoint || !s[0] ) {
 87.6493 +qboolean R_GetEntityToken(char *buffer, int size)
 87.6494 +{
 87.6495 +	const char     *s;
 87.6496 +
 87.6497 +	s = Com_Parse(&s_worldData.entityParsePoint);
 87.6498 +	Q_strncpyz(buffer, s, size);
 87.6499 +	if(!s_worldData.entityParsePoint || !s[0])
 87.6500 +	{
 87.6501  		s_worldData.entityParsePoint = s_worldData.entityString;
 87.6502  		return qfalse;
 87.6503 -	} else {
 87.6504 +	}
 87.6505 +	else
 87.6506 +	{
 87.6507  		return qtrue;
 87.6508  	}
 87.6509  }
 87.6510  
 87.6511 +
 87.6512 +/*
 87.6513 +=================
 87.6514 +R_PrecacheInteraction
 87.6515 +=================
 87.6516 +*/
 87.6517 +static void R_PrecacheInteraction(trRefLight_t * light, bspSurface_t * surface)
 87.6518 +{
 87.6519 +	interactionCache_t *iaCache;
 87.6520 +
 87.6521 +	iaCache = ri.Hunk_Alloc(sizeof(*iaCache), h_low);
 87.6522 +	Com_AddToGrowList(&s_interactions, iaCache);
 87.6523 +
 87.6524 +	// connect to interaction grid
 87.6525 +	if(!light->firstInteractionCache)
 87.6526 +	{
 87.6527 +		light->firstInteractionCache = iaCache;
 87.6528 +	}
 87.6529 +
 87.6530 +	if(light->lastInteractionCache)
 87.6531 +	{
 87.6532 +		light->lastInteractionCache->next = iaCache;
 87.6533 +	}
 87.6534 +
 87.6535 +	light->lastInteractionCache = iaCache;
 87.6536 +
 87.6537 +	iaCache->next = NULL;
 87.6538 +	iaCache->surface = surface;
 87.6539 +
 87.6540 +	iaCache->redundant = qfalse;
 87.6541 +}
 87.6542 +
 87.6543 +/*
 87.6544 +static int R_BuildShadowVolume(int numTriangles, const srfTriangle_t * triangles, int numVerts, int indexes[SHADER_MAX_INDEXES])
 87.6545 +{
 87.6546 +	int             i;
 87.6547 +	int             numIndexes;
 87.6548 +	const srfTriangle_t *tri;
 87.6549 +
 87.6550 +	// calculate zfail shadow volume
 87.6551 +	numIndexes = 0;
 87.6552 +
 87.6553 +	// set up indices for silhouette edges
 87.6554 +	for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
 87.6555 +	{
 87.6556 +		if(!sh.facing[i])
 87.6557 +		{
 87.6558 +			continue;
 87.6559 +		}
 87.6560 +
 87.6561 +		if(tri->neighbors[0] < 0 || !sh.facing[tri->neighbors[0]])
 87.6562 +		{
 87.6563 +			indexes[numIndexes + 0] = tri->indexes[1];
 87.6564 +			indexes[numIndexes + 1] = tri->indexes[0];
 87.6565 +			indexes[numIndexes + 2] = tri->indexes[0] + numVerts;
 87.6566 +
 87.6567 +			indexes[numIndexes + 3] = tri->indexes[1];
 87.6568 +			indexes[numIndexes + 4] = tri->indexes[0] + numVerts;
 87.6569 +			indexes[numIndexes + 5] = tri->indexes[1] + numVerts;
 87.6570 +
 87.6571 +			numIndexes += 6;
 87.6572 +		}
 87.6573 +
 87.6574 +		if(tri->neighbors[1] < 0 || !sh.facing[tri->neighbors[1]])
 87.6575 +		{
 87.6576 +			indexes[numIndexes + 0] = tri->indexes[2];
 87.6577 +			indexes[numIndexes + 1] = tri->indexes[1];
 87.6578 +			indexes[numIndexes + 2] = tri->indexes[1] + numVerts;
 87.6579 +
 87.6580 +			indexes[numIndexes + 3] = tri->indexes[2];
 87.6581 +			indexes[numIndexes + 4] = tri->indexes[1] + numVerts;
 87.6582 +			indexes[numIndexes + 5] = tri->indexes[2] + numVerts;
 87.6583 +
 87.6584 +			numIndexes += 6;
 87.6585 +		}
 87.6586 +
 87.6587 +		if(tri->neighbors[2] < 0 || !sh.facing[tri->neighbors[2]])
 87.6588 +		{
 87.6589 +			indexes[numIndexes + 0] = tri->indexes[0];
 87.6590 +			indexes[numIndexes + 1] = tri->indexes[2];
 87.6591 +			indexes[numIndexes + 2] = tri->indexes[2] + numVerts;
 87.6592 +
 87.6593 +			indexes[numIndexes + 3] = tri->indexes[0];
 87.6594 +			indexes[numIndexes + 4] = tri->indexes[2] + numVerts;
 87.6595 +			indexes[numIndexes + 5] = tri->indexes[0] + numVerts;
 87.6596 +
 87.6597 +			numIndexes += 6;
 87.6598 +		}
 87.6599 +	}
 87.6600 +
 87.6601 +	// set up indices for light and dark caps
 87.6602 +	for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
 87.6603 +	{
 87.6604 +		if(!sh.facing[i])
 87.6605 +		{
 87.6606 +			continue;
 87.6607 +		}
 87.6608 +
 87.6609 +		// light cap
 87.6610 +		indexes[numIndexes + 0] = tri->indexes[0];
 87.6611 +		indexes[numIndexes + 1] = tri->indexes[1];
 87.6612 +		indexes[numIndexes + 2] = tri->indexes[2];
 87.6613 +
 87.6614 +		// dark cap
 87.6615 +		indexes[numIndexes + 3] = tri->indexes[2] + numVerts;
 87.6616 +		indexes[numIndexes + 4] = tri->indexes[1] + numVerts;
 87.6617 +		indexes[numIndexes + 5] = tri->indexes[0] + numVerts;
 87.6618 +
 87.6619 +		numIndexes += 6;
 87.6620 +	}
 87.6621 +
 87.6622 +	return numIndexes;
 87.6623 +}
 87.6624 +*/
 87.6625 +
 87.6626 +/*
 87.6627 +static int R_BuildShadowPlanes(int numTriangles, const srfTriangle_t * triangles, int numVerts, srfVert_t * verts,
 87.6628 +							   cplane_t shadowPlanes[SHADER_MAX_TRIANGLES], trRefLight_t * light)
 87.6629 +{
 87.6630 +	int             i;
 87.6631 +	int             numShadowPlanes;
 87.6632 +	const srfTriangle_t *tri;
 87.6633 +	vec3_t          pos[3];
 87.6634 +
 87.6635 +//  vec3_t          lightDir;
 87.6636 +	vec4_t          plane;
 87.6637 +
 87.6638 +	if(r_noShadowFrustums->integer)
 87.6639 +	{
 87.6640 +		return 0;
 87.6641 +	}
 87.6642 +
 87.6643 +	// calculate shadow frustum
 87.6644 +	numShadowPlanes = 0;
 87.6645 +
 87.6646 +	// set up indices for silhouette edges
 87.6647 +	for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
 87.6648 +	{
 87.6649 +		if(!sh.facing[i])
 87.6650 +		{
 87.6651 +			continue;
 87.6652 +		}
 87.6653 +
 87.6654 +		if(tri->neighbors[0] < 0 || !sh.facing[tri->neighbors[0]])
 87.6655 +		{
 87.6656 +			//indexes[numIndexes + 0] = tri->indexes[1];
 87.6657 +			//indexes[numIndexes + 1] = tri->indexes[0];
 87.6658 +			//indexes[numIndexes + 2] = tri->indexes[0] + numVerts;
 87.6659 +
 87.6660 +			VectorCopy(verts[tri->indexes[1]].xyz, pos[0]);
 87.6661 +			VectorCopy(verts[tri->indexes[0]].xyz, pos[1]);
 87.6662 +			VectorCopy(light->origin, pos[2]);
 87.6663 +
 87.6664 +			// extrude the infinite one
 87.6665 +			//VectorSubtract(verts[tri->indexes[0]].xyz, light->origin, lightDir);
 87.6666 +			//VectorAdd(verts[tri->indexes[0]].xyz, lightDir, pos[2]);
 87.6667 +			//VectorNormalize(lightDir);
 87.6668 +			//VectorMA(verts[tri->indexes[0]].xyz, 9999, lightDir, pos[2]);
 87.6669 +
 87.6670 +			if(PlaneFromPoints(plane, pos[0], pos[1], pos[2], qtrue))
 87.6671 +			{
 87.6672 +				shadowPlanes[numShadowPlanes].normal[0] = plane[0];
 87.6673 +				shadowPlanes[numShadowPlanes].normal[1] = plane[1];
 87.6674 +				shadowPlanes[numShadowPlanes].normal[2] = plane[2];
 87.6675 +				shadowPlanes[numShadowPlanes].dist = plane[3];
 87.6676 +
 87.6677 +				numShadowPlanes++;
 87.6678 +			}
 87.6679 +			else
 87.6680 +			{
 87.6681 +				return 0;
 87.6682 +			}
 87.6683 +		}
 87.6684 +
 87.6685 +		if(tri->neighbors[1] < 0 || !sh.facing[tri->neighbors[1]])
 87.6686 +		{
 87.6687 +			//indexes[numIndexes + 0] = tri->indexes[2];
 87.6688 +			//indexes[numIndexes + 1] = tri->indexes[1];
 87.6689 +			//indexes[numIndexes + 2] = tri->indexes[1] + numVerts;
 87.6690 +
 87.6691 +			VectorCopy(verts[tri->indexes[2]].xyz, pos[0]);
 87.6692 +			VectorCopy(verts[tri->indexes[1]].xyz, pos[1]);
 87.6693 +			VectorCopy(light->origin, pos[2]);
 87.6694 +
 87.6695 +			// extrude the infinite one
 87.6696 +			//VectorSubtract(verts[tri->indexes[1]].xyz, light->origin, lightDir);
 87.6697 +			//VectorNormalize(lightDir);
 87.6698 +			//VectorMA(verts[tri->indexes[1]].xyz, 9999, lightDir, pos[2]);
 87.6699 +
 87.6700 +			if(PlaneFromPoints(plane, pos[0], pos[1], pos[2], qtrue))
 87.6701 +			{
 87.6702 +				shadowPlanes[numShadowPlanes].normal[0] = plane[0];
 87.6703 +				shadowPlanes[numShadowPlanes].normal[1] = plane[1];
 87.6704 +				shadowPlanes[numShadowPlanes].normal[2] = plane[2];
 87.6705 +				shadowPlanes[numShadowPlanes].dist = plane[3];
 87.6706 +
 87.6707 +				numShadowPlanes++;
 87.6708 +			}
 87.6709 +			else
 87.6710 +			{
 87.6711 +				return 0;
 87.6712 +			}
 87.6713 +		}
 87.6714 +
 87.6715 +		if(tri->neighbors[2] < 0 || !sh.facing[tri->neighbors[2]])
 87.6716 +		{
 87.6717 +			//indexes[numIndexes + 0] = tri->indexes[0];
 87.6718 +			//indexes[numIndexes + 1] = tri->indexes[2];
 87.6719 +			//indexes[numIndexes + 2] = tri->indexes[2] + numVerts;
 87.6720 +
 87.6721 +			VectorCopy(verts[tri->indexes[0]].xyz, pos[0]);
 87.6722 +			VectorCopy(verts[tri->indexes[2]].xyz, pos[1]);
 87.6723 +			VectorCopy(light->origin, pos[2]);
 87.6724 +
 87.6725 +			// extrude the infinite one
 87.6726 +			//VectorSubtract(verts[tri->indexes[2]].xyz, light->origin, lightDir);
 87.6727 +			//VectorNormalize(lightDir);
 87.6728 +			//VectorMA(verts[tri->indexes[2]].xyz, 9999, lightDir, pos[2]);
 87.6729 +
 87.6730 +			if(PlaneFromPoints(plane, pos[0], pos[1], pos[2], qtrue))
 87.6731 +			{
 87.6732 +				shadowPlanes[numShadowPlanes].normal[0] = plane[0];
 87.6733 +				shadowPlanes[numShadowPlanes].normal[1] = plane[1];
 87.6734 +				shadowPlanes[numShadowPlanes].normal[2] = plane[2];
 87.6735 +				shadowPlanes[numShadowPlanes].dist = plane[3];
 87.6736 +
 87.6737 +				numShadowPlanes++;
 87.6738 +			}
 87.6739 +			else
 87.6740 +			{
 87.6741 +				return 0;
 87.6742 +			}
 87.6743 +		}
 87.6744 +	}
 87.6745 +
 87.6746 +	// set up indices for light and dark caps
 87.6747 +	for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
 87.6748 +	{
 87.6749 +		if(!sh.facing[i])
 87.6750 +		{
 87.6751 +			continue;
 87.6752 +		}
 87.6753 +
 87.6754 +		// light cap
 87.6755 +		//indexes[numIndexes + 0] = tri->indexes[0];
 87.6756 +		//indexes[numIndexes + 1] = tri->indexes[1];
 87.6757 +		//indexes[numIndexes + 2] = tri->indexes[2];
 87.6758 +
 87.6759 +		VectorCopy(verts[tri->indexes[0]].xyz, pos[0]);
 87.6760 +		VectorCopy(verts[tri->indexes[1]].xyz, pos[1]);
 87.6761 +		VectorCopy(verts[tri->indexes[2]].xyz, pos[2]);
 87.6762 +
 87.6763 +		if(PlaneFromPoints(plane, pos[0], pos[1], pos[2], qfalse))
 87.6764 +		{
 87.6765 +			shadowPlanes[numShadowPlanes].normal[0] = plane[0];
 87.6766 +			shadowPlanes[numShadowPlanes].normal[1] = plane[1];
 87.6767 +			shadowPlanes[numShadowPlanes].normal[2] = plane[2];
 87.6768 +			shadowPlanes[numShadowPlanes].dist = plane[3];
 87.6769 +
 87.6770 +			numShadowPlanes++;
 87.6771 +		}
 87.6772 +		else
 87.6773 +		{
 87.6774 +			return 0;
 87.6775 +		}
 87.6776 +	}
 87.6777 +
 87.6778 +
 87.6779 +	for(i = 0; i < numShadowPlanes; i++)
 87.6780 +	{
 87.6781 +		//vec_t           length, ilength;
 87.6782 +
 87.6783 +		shadowPlanes[i].type = PLANE_NON_AXIAL;
 87.6784 +
 87.6785 +
 87.6786 +		SetPlaneSignbits(&shadowPlanes[i]);
 87.6787 +	}
 87.6788 +
 87.6789 +	return numShadowPlanes;
 87.6790 +}
 87.6791 +*/
 87.6792 +
 87.6793 +static qboolean R_PrecacheFaceInteraction(srfSurfaceFace_t * cv, shader_t * shader, trRefLight_t * light)
 87.6794 +{
 87.6795 +	// check if bounds intersect
 87.6796 +	if(!BoundsIntersect(light->worldBounds[0], light->worldBounds[1], cv->bounds[0], cv->bounds[1]))
 87.6797 +	{
 87.6798 +		return qfalse;
 87.6799 +	}
 87.6800 +
 87.6801 +	return qtrue;
 87.6802 +}
 87.6803 +
 87.6804 +
 87.6805 +static int R_PrecacheGridInteraction(srfGridMesh_t * cv, shader_t * shader, trRefLight_t * light)
 87.6806 +{
 87.6807 +	// check if bounds intersect
 87.6808 +	if(!BoundsIntersect(light->worldBounds[0], light->worldBounds[1], cv->meshBounds[0], cv->meshBounds[1]))
 87.6809 +	{
 87.6810 +		return qfalse;
 87.6811 +	}
 87.6812 +
 87.6813 +	return qtrue;
 87.6814 +}
 87.6815 +
 87.6816 +
 87.6817 +static int R_PrecacheTrisurfInteraction(srfTriangles_t * cv, shader_t * shader, trRefLight_t * light)
 87.6818 +{
 87.6819 +	// check if bounds intersect
 87.6820 +	if(!BoundsIntersect(light->worldBounds[0], light->worldBounds[1], cv->bounds[0], cv->bounds[1]))
 87.6821 +	{
 87.6822 +		return qfalse;
 87.6823 +	}
 87.6824 +
 87.6825 +	return qtrue;
 87.6826 +}
 87.6827 +
 87.6828 +
 87.6829 +/*
 87.6830 +======================
 87.6831 +R_PrecacheInteractionSurface
 87.6832 +======================
 87.6833 +*/
 87.6834 +static void R_PrecacheInteractionSurface(bspSurface_t * surf, trRefLight_t * light)
 87.6835 +{
 87.6836 +	qboolean        intersects;
 87.6837 +
 87.6838 +	if(surf->lightCount == s_lightCount)
 87.6839 +	{
 87.6840 +		return;					// already checked this surface
 87.6841 +	}
 87.6842 +	surf->lightCount = s_lightCount;
 87.6843 +
 87.6844 +	// skip all surfaces that don't matter for lighting only pass
 87.6845 +	if(surf->shader->isSky || (!surf->shader->interactLight && surf->shader->noShadows))
 87.6846 +		return;
 87.6847 +
 87.6848 +	if(*surf->data == SF_FACE)
 87.6849 +	{
 87.6850 +		intersects = R_PrecacheFaceInteraction((srfSurfaceFace_t *) surf->data, surf->shader, light);
 87.6851 +	}
 87.6852 +	else if(*surf->data == SF_GRID)
 87.6853 +	{
 87.6854 +		intersects = R_PrecacheGridInteraction((srfGridMesh_t *) surf->data, surf->shader, light);
 87.6855 +	}
 87.6856 +	else if(*surf->data == SF_TRIANGLES)
 87.6857 +	{
 87.6858 +		intersects = R_PrecacheTrisurfInteraction((srfTriangles_t *) surf->data, surf->shader, light);
 87.6859 +	}
 87.6860 +	else
 87.6861 +	{
 87.6862 +		intersects = qfalse;
 87.6863 +	}
 87.6864 +
 87.6865 +	if(intersects)
 87.6866 +	{
 87.6867 +		R_PrecacheInteraction(light, surf);
 87.6868 +	}
 87.6869 +}
 87.6870 +
 87.6871 +/*
 87.6872 +================
 87.6873 +R_RecursivePrecacheInteractionNode
 87.6874 +================
 87.6875 +*/
 87.6876 +static void R_RecursivePrecacheInteractionNode(bspNode_t * node, trRefLight_t * light)
 87.6877 +{
 87.6878 +	int             r;
 87.6879 +
 87.6880 +	// light already hit node
 87.6881 +	if(node->lightCount == s_lightCount)
 87.6882 +	{
 87.6883 +		return;
 87.6884 +	}
 87.6885 +	node->lightCount = s_lightCount;
 87.6886 +
 87.6887 +	if(node->contents != -1)
 87.6888 +	{
 87.6889 +		// leaf node, so add mark surfaces
 87.6890 +		int             c;
 87.6891 +		bspSurface_t   *surf, **mark;
 87.6892 +
 87.6893 +		// add the individual surfaces
 87.6894 +		mark = node->markSurfaces;
 87.6895 +		c = node->numMarkSurfaces;
 87.6896 +		while(c--)
 87.6897 +		{
 87.6898 +			// the surface may have already been added if it
 87.6899 +			// spans multiple leafs
 87.6900 +			surf = *mark;
 87.6901 +			R_PrecacheInteractionSurface(surf, light);
 87.6902 +			mark++;
 87.6903 +		}
 87.6904 +
 87.6905 +		return;
 87.6906 +	}
 87.6907 +
 87.6908 +	// node is just a decision point, so go down both sides
 87.6909 +	// since we don't care about sort orders, just go positive to negative
 87.6910 +	r = BoxOnPlaneSide(light->worldBounds[0], light->worldBounds[1], node->plane);
 87.6911 +
 87.6912 +	switch (r)
 87.6913 +	{
 87.6914 +		case 1:
 87.6915 +			R_RecursivePrecacheInteractionNode(node->children[0], light);
 87.6916 +			break;
 87.6917 +
 87.6918 +		case 2:
 87.6919 +			R_RecursivePrecacheInteractionNode(node->children[1], light);
 87.6920 +			break;
 87.6921 +
 87.6922 +		case 3:
 87.6923 +		default:
 87.6924 +			// recurse down the children, front side first
 87.6925 +			R_RecursivePrecacheInteractionNode(node->children[0], light);
 87.6926 +			R_RecursivePrecacheInteractionNode(node->children[1], light);
 87.6927 +			break;
 87.6928 +	}
 87.6929 +}
 87.6930 +
 87.6931 +/*
 87.6932 +================
 87.6933 +R_RecursiveAddInteractionNode
 87.6934 +================
 87.6935 +*/
 87.6936 +static void R_RecursiveAddInteractionNode(bspNode_t * node, trRefLight_t * light, int *numLeafs, qboolean onlyCount)
 87.6937 +{
 87.6938 +	int             r;
 87.6939 +
 87.6940 +	// light already hit node
 87.6941 +	if(node->lightCount == s_lightCount)
 87.6942 +	{
 87.6943 +		return;
 87.6944 +	}
 87.6945 +	node->lightCount = s_lightCount;
 87.6946 +
 87.6947 +	if(node->contents != -1)
 87.6948 +	{
 87.6949 +		vec3_t          worldBounds[2];
 87.6950 +
 87.6951 +		VectorCopy(node->mins, worldBounds[0]);
 87.6952 +		VectorCopy(node->maxs, worldBounds[1]);
 87.6953 +
 87.6954 +		if(R_CullLightWorldBounds(light, worldBounds) != CULL_OUT)
 87.6955 +		{
 87.6956 +			if(!onlyCount)
 87.6957 +			{
 87.6958 +				// assign leave and increase leave counter
 87.6959 +				light->leafs[*numLeafs] = node;
 87.6960 +			}
 87.6961 +
 87.6962 +			*numLeafs = *numLeafs + 1;
 87.6963 +		}
 87.6964 +		return;
 87.6965 +	}
 87.6966 +
 87.6967 +	// node is just a decision point, so go down both sides
 87.6968 +	// since we don't care about sort orders, just go positive to negative
 87.6969 +	r = BoxOnPlaneSide(light->worldBounds[0], light->worldBounds[1], node->plane);
 87.6970 +
 87.6971 +	switch (r)
 87.6972 +	{
 87.6973 +		case 1:
 87.6974 +			R_RecursiveAddInteractionNode(node->children[0], light, numLeafs, onlyCount);
 87.6975 +			break;
 87.6976 +
 87.6977 +		case 2:
 87.6978 +			R_RecursiveAddInteractionNode(node->children[1], light, numLeafs, onlyCount);
 87.6979 +			break;
 87.6980 +
 87.6981 +		case 3:
 87.6982 +		default:
 87.6983 +			// recurse down the children, front side first
 87.6984 +			R_RecursiveAddInteractionNode(node->children[0], light, numLeafs, onlyCount);
 87.6985 +			R_RecursiveAddInteractionNode(node->children[1], light, numLeafs, onlyCount);
 87.6986 +			break;
 87.6987 +	}
 87.6988 +}
 87.6989 +
 87.6990 +/*
 87.6991 +=================
 87.6992 +R_ShadowFrustumCullWorldBounds
 87.6993 +
 87.6994 +Returns CULL_IN, CULL_CLIP, or CULL_OUT
 87.6995 +=================
 87.6996 +*/
 87.6997 +int R_ShadowFrustumCullWorldBounds(int numShadowPlanes, cplane_t * shadowPlanes, vec3_t worldBounds[2])
 87.6998 +{
 87.6999 +	int             i;
 87.7000 +	cplane_t       *plane;
 87.7001 +	qboolean        anyClip;
 87.7002 +	int             r;
 87.7003 +
 87.7004 +	if(!numShadowPlanes)
 87.7005 +		return CULL_CLIP;
 87.7006 +
 87.7007 +	// check against frustum planes
 87.7008 +	anyClip = qfalse;
 87.7009 +	for(i = 0; i < numShadowPlanes; i++)
 87.7010 +	{
 87.7011 +		plane = &shadowPlanes[i];
 87.7012 +
 87.7013 +		r = BoxOnPlaneSide(worldBounds[0], worldBounds[1], plane);
 87.7014 +
 87.7015 +		if(r == 2)
 87.7016 +		{
 87.7017 +			// completely outside frustum
 87.7018 +			return CULL_OUT;
 87.7019 +		}
 87.7020 +		if(r == 3)
 87.7021 +		{
 87.7022 +			anyClip = qtrue;
 87.7023 +		}
 87.7024 +	}
 87.7025 +
 87.7026 +	if(!anyClip)
 87.7027 +	{
 87.7028 +		// completely inside frustum
 87.7029 +		return CULL_IN;
 87.7030 +	}
 87.7031 +
 87.7032 +	// partially clipped
 87.7033 +	return CULL_CLIP;
 87.7034 +}
 87.7035 +
 87.7036 +/*
 87.7037 +=============
 87.7038 +R_KillRedundantInteractions
 87.7039 +=============
 87.7040 +*/
 87.7041 +/*
 87.7042 +static void R_KillRedundantInteractions(trRefLight_t * light)
 87.7043 +{
 87.7044 +	interactionCache_t *iaCache, *iaCache2;
 87.7045 +	bspSurface_t   *surface;
 87.7046 +	vec3_t          localBounds[2];
 87.7047 +
 87.7048 +	if(r_shadows->integer <= 2)
 87.7049 +		return;
 87.7050 +
 87.7051 +	if(!light->firstInteractionCache)
 87.7052 +	{
 87.7053 +		// this light has no interactions precached
 87.7054 +		return;
 87.7055 +	}
 87.7056 +
 87.7057 +	if(light->l.noShadows)
 87.7058 +	{
 87.7059 +		// actually noShadows lights are quite bad concerning this optimization
 87.7060 +		return;
 87.7061 +	}
 87.7062 +
 87.7063 +	for(iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next)
 87.7064 +	{
 87.7065 +		surface = iaCache->surface;
 87.7066 +
 87.7067 +		if(surface->shader->sort > SS_OPAQUE)
 87.7068 +			continue;
 87.7069 +
 87.7070 +		if(surface->shader->noShadows)
 87.7071 +			continue;
 87.7072 +
 87.7073 +		// HACK: allow fancy alphatest shadows with shadow mapping
 87.7074 +		if(r_shadows->integer >= 4 && surface->shader->alphaTest)
 87.7075 +			continue;
 87.7076 +
 87.7077 +		for(iaCache2 = light->firstInteractionCache; iaCache2; iaCache2 = iaCache2->next)
 87.7078 +		{
 87.7079 +			if(iaCache == iaCache2)
 87.7080 +			{
 87.7081 +				// don't check the surface of the current interaction with its shadow frustum
 87.7082 +				continue;
 87.7083 +			}
 87.7084 +
 87.7085 +			surface = iaCache2->surface;
 87.7086 +
 87.7087 +			if(*surface->data == SF_FACE)
 87.7088 +			{
 87.7089 +				srfSurfaceFace_t *face;
 87.7090 +
 87.7091 +				face = (srfSurfaceFace_t *) surface->data;
 87.7092 +
 87.7093 +				VectorCopy(face->bounds[0], localBounds[0]);
 87.7094 +				VectorCopy(face->bounds[1], localBounds[1]);
 87.7095 +			}
 87.7096 +			else if(*surface->data == SF_GRID)
 87.7097 +			{
 87.7098 +				srfGridMesh_t  *grid;
 87.7099 +
 87.7100 +				grid = (srfGridMesh_t *) surface->data;
 87.7101 +
 87.7102 +				VectorCopy(grid->meshBounds[0], localBounds[0]);
 87.7103 +				VectorCopy(grid->meshBounds[1], localBounds[1]);
 87.7104 +			}
 87.7105 +			else if(*surface->data == SF_TRIANGLES)
 87.7106 +			{
 87.7107 +				srfTriangles_t *tri;
 87.7108 +
 87.7109 +				tri = (srfTriangles_t *) surface->data;
 87.7110 +
 87.7111 +				VectorCopy(tri->bounds[0], localBounds[0]);
 87.7112 +				VectorCopy(tri->bounds[1], localBounds[1]);
 87.7113 +			}
 87.7114 +			else
 87.7115 +			{
 87.7116 +				iaCache2->redundant = qfalse;
 87.7117 +				continue;
 87.7118 +			}
 87.7119 +
 87.7120 +			if(R_ShadowFrustumCullWorldBounds(iaCache->numShadowPlanes, iaCache->shadowPlanes, localBounds) == CULL_IN)
 87.7121 +			{
 87.7122 +				iaCache2->redundant = qtrue;
 87.7123 +				c_redundantInteractions++;
 87.7124 +			}
 87.7125 +		}
 87.7126 +
 87.7127 +		if(iaCache->redundant)
 87.7128 +		{
 87.7129 +			c_redundantInteractions++;
 87.7130 +		}
 87.7131 +	}
 87.7132 +}
 87.7133 +*/
 87.7134 +
 87.7135 +
 87.7136 +/*
 87.7137 +=================
 87.7138 +R_CreateInteractionVBO
 87.7139 +=================
 87.7140 +*/
 87.7141 +static interactionVBO_t *R_CreateInteractionVBO(trRefLight_t * light)
 87.7142 +{
 87.7143 +	interactionVBO_t *iaVBO;
 87.7144 +
 87.7145 +	iaVBO = ri.Hunk_Alloc(sizeof(*iaVBO), h_low);
 87.7146 +
 87.7147 +	// connect to interaction grid
 87.7148 +	if(!light->firstInteractionVBO)
 87.7149 +	{
 87.7150 +		light->firstInteractionVBO = iaVBO;
 87.7151 +	}
 87.7152 +
 87.7153 +	if(light->lastInteractionVBO)
 87.7154 +	{
 87.7155 +		light->lastInteractionVBO->next = iaVBO;
 87.7156 +	}
 87.7157 +
 87.7158 +	light->lastInteractionVBO = iaVBO;
 87.7159 +	iaVBO->next = NULL;
 87.7160 +
 87.7161 +	return iaVBO;
 87.7162 +}
 87.7163 +
 87.7164 +/*
 87.7165 +=================
 87.7166 +InteractionCacheCompare
 87.7167 +compare function for qsort()
 87.7168 +=================
 87.7169 +*/
 87.7170 +static int InteractionCacheCompare(const void *a, const void *b)
 87.7171 +{
 87.7172 +	interactionCache_t *aa, *bb;
 87.7173 +
 87.7174 +	aa = *(interactionCache_t **) a;
 87.7175 +	bb = *(interactionCache_t **) b;
 87.7176 +
 87.7177 +	// shader first
 87.7178 +	if(aa->surface->shader < bb->surface->shader)
 87.7179 +		return -1;
 87.7180 +
 87.7181 +	else if(aa->surface->shader > bb->surface->shader)
 87.7182 +		return 1;
 87.7183 +
 87.7184 +	// then alphaTest
 87.7185 +	if(aa->surface->shader->alphaTest < bb->surface->shader->alphaTest)
 87.7186 +		return -1;
 87.7187 +
 87.7188 +	else if(aa->surface->shader->alphaTest > bb->surface->shader->alphaTest)
 87.7189 +		return 1;
 87.7190 +
 87.7191 +	return 0;
 87.7192 +}
 87.7193 +
 87.7194 +static int UpdateLightTriangles(const srfVert_t * verts, int numTriangles, srfTriangle_t * triangles, shader_t * surfaceShader,
 87.7195 +								trRefLight_t * light)
 87.7196 +{
 87.7197 +	int             i;
 87.7198 +	srfTriangle_t  *tri;
 87.7199 +	int             numFacing;
 87.7200 +
 87.7201 +	numFacing = 0;
 87.7202 +	for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
 87.7203 +	{
 87.7204 +		vec3_t          pos[3];
 87.7205 +		float           d;
 87.7206 +
 87.7207 +		VectorCopy(verts[tri->indexes[0]].xyz, pos[0]);
 87.7208 +		VectorCopy(verts[tri->indexes[1]].xyz, pos[1]);
 87.7209 +		VectorCopy(verts[tri->indexes[2]].xyz, pos[2]);
 87.7210 +
 87.7211 +		if(PlaneFromPoints(tri->plane, pos[0], pos[1], pos[2], qtrue))
 87.7212 +		{
 87.7213 +			tri->degenerated = qfalse;
 87.7214 +
 87.7215 +			// check if light origin is behind triangle
 87.7216 +			d = DotProduct(tri->plane, light->origin) - tri->plane[3];
 87.7217 +
 87.7218 +			if(surfaceShader->cullType == CT_TWO_SIDED || (d > 0 && surfaceShader->cullType != CT_BACK_SIDED))
 87.7219 +			{
 87.7220 +				tri->facingLight = qtrue;
 87.7221 +			}
 87.7222 +			else
 87.7223 +			{
 87.7224 +				tri->facingLight = qfalse;
 87.7225 +			}
 87.7226 +		}
 87.7227 +		else
 87.7228 +		{
 87.7229 +			tri->degenerated = qtrue;
 87.7230 +			tri->facingLight = qtrue;	// FIXME ?
 87.7231 +		}
 87.7232 +
 87.7233 +		if(R_CullLightTriangle(light, pos) == CULL_OUT)
 87.7234 +		{
 87.7235 +			tri->facingLight = qfalse;
 87.7236 +		}
 87.7237 +
 87.7238 +		if(tri->facingLight)
 87.7239 +			numFacing++;
 87.7240 +	}
 87.7241 +
 87.7242 +	return numFacing;
 87.7243 +}
 87.7244 +
 87.7245 +/*
 87.7246 +===============
 87.7247 +R_CreateVBOLightMeshes
 87.7248 +===============
 87.7249 +*/
 87.7250 +static void R_CreateVBOLightMeshes(trRefLight_t * light)
 87.7251 +{
 87.7252 +#if 1
 87.7253 +	int             i, j, k, l;
 87.7254 +
 87.7255 +	int             numVerts;
 87.7256 +
 87.7257 +	int             numTriangles;
 87.7258 +	srfTriangle_t  *triangles;
 87.7259 +	srfTriangle_t  *tri;
 87.7260 +
 87.7261 +	interactionVBO_t *iaVBO;
 87.7262 +
 87.7263 +	interactionCache_t *iaCache, *iaCache2;
 87.7264 +	interactionCache_t **iaCachesSorted;
 87.7265 +	int             numCaches;
 87.7266 +
 87.7267 +	shader_t       *shader, *oldShader;
 87.7268 +
 87.7269 +	bspSurface_t   *surface;
 87.7270 +
 87.7271 +	srfVBOMesh_t   *vboSurf;
 87.7272 +
 87.7273 +	if(!r_vboLighting->integer)
 87.7274 +		return;
 87.7275 +
 87.7276 +	if(r_deferredShading->integer && r_shadows->integer <= 3)
 87.7277 +		return;
 87.7278 +
 87.7279 +	if(!light->firstInteractionCache)
 87.7280 +	{
 87.7281 +		// this light has no interactions precached
 87.7282 +		return;
 87.7283 +	}
 87.7284 +
 87.7285 +	// count number of interaction caches
 87.7286 +	numCaches = 0;
 87.7287 +	for(iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next)
 87.7288 +	{
 87.7289 +		if(iaCache->redundant)
 87.7290 +			continue;
 87.7291 +
 87.7292 +		surface = iaCache->surface;
 87.7293 +
 87.7294 +		if(!surface->shader->interactLight)
 87.7295 +			continue;
 87.7296 +
 87.7297 +		numCaches++;
 87.7298 +	}
 87.7299 +
 87.7300 +	// build interaction caches list
 87.7301 +	iaCachesSorted = ri.Hunk_AllocateTempMemory(numCaches * sizeof(iaCachesSorted[0]));
 87.7302 +
 87.7303 +	numCaches = 0;
 87.7304 +	for(iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next)
 87.7305 +	{
 87.7306 +		if(iaCache->redundant)
 87.7307 +			continue;
 87.7308 +
 87.7309 +		surface = iaCache->surface;
 87.7310 +
 87.7311 +		if(!surface->shader->interactLight)
 87.7312 +			continue;
 87.7313 +
 87.7314 +		iaCachesSorted[numCaches] = iaCache;
 87.7315 +		numCaches++;
 87.7316 +	}
 87.7317 +
 87.7318 +
 87.7319 +	// sort interaction caches by shader
 87.7320 +	qsort(iaCachesSorted, numCaches, sizeof(iaCachesSorted), InteractionCacheCompare);
 87.7321 +
 87.7322 +	// create a VBO for each shader
 87.7323 +	shader = oldShader = NULL;
 87.7324 +
 87.7325 +	for(k = 0; k < numCaches; k++)
 87.7326 +	{
 87.7327 +		iaCache = iaCachesSorted[k];
 87.7328 +
 87.7329 +		shader = iaCache->surface->shader;
 87.7330 +
 87.7331 +		if(shader != oldShader)
 87.7332 +		{
 87.7333 +			oldShader = shader;
 87.7334 +
 87.7335 +			// count vertices and indices
 87.7336 +			numVerts = 0;
 87.7337 +			numTriangles = 0;
 87.7338 +
 87.7339 +			for(l = k; l < numCaches; l++)
 87.7340 +			{
 87.7341 +				iaCache2 = iaCachesSorted[l];
 87.7342 +
 87.7343 +				surface = iaCache2->surface;
 87.7344 +
 87.7345 +				if(surface->shader != shader)
 87.7346 +					continue;
 87.7347 +
 87.7348 +				if(*surface->data == SF_FACE)
 87.7349 +				{
 87.7350 +					srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
 87.7351 +
 87.7352 +					if(srf->numTriangles)
 87.7353 +						numTriangles +=
 87.7354 +							UpdateLightTriangles(s_worldData.verts, srf->numTriangles, s_worldData.triangles + srf->firstTriangle,
 87.7355 +												 surface->shader, light);
 87.7356 +
 87.7357 +					if(srf->numVerts)
 87.7358 +						numVerts += srf->numVerts;
 87.7359 +				}
 87.7360 +				else if(*surface->data == SF_GRID)
 87.7361 +				{
 87.7362 +					srfGridMesh_t  *srf = (srfGridMesh_t *) surface->data;
 87.7363 +
 87.7364 +					if(srf->numTriangles)
 87.7365 +						numTriangles +=
 87.7366 +							UpdateLightTriangles(s_worldData.verts, srf->numTriangles, s_worldData.triangles + srf->firstTriangle,
 87.7367 +												 surface->shader, light);
 87.7368 +
 87.7369 +					if(srf->numVerts)
 87.7370 +						numVerts += srf->numVerts;
 87.7371 +				}
 87.7372 +				else if(*surface->data == SF_TRIANGLES)
 87.7373 +				{
 87.7374 +					srfTriangles_t *srf = (srfTriangles_t *) surface->data;
 87.7375 +
 87.7376 +					if(srf->numTriangles)
 87.7377 +						numTriangles +=
 87.7378 +							UpdateLightTriangles(s_worldData.verts, srf->numTriangles, s_worldData.triangles + srf->firstTriangle,
 87.7379 +												 surface->shader, light);
 87.7380 +
 87.7381 +					if(srf->numVerts)
 87.7382 +						numVerts += srf->numVerts;
 87.7383 +				}
 87.7384 +			}
 87.7385 +
 87.7386 +			if(!numVerts || !numTriangles)
 87.7387 +				continue;
 87.7388 +
 87.7389 +			//ri.Printf(PRINT_ALL, "...calculating light mesh VBOs ( %s, %i verts %i tris )\n", shader->name, vertexesNum, indexesNum / 3);
 87.7390 +
 87.7391 +			// create surface
 87.7392 +			vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low);
 87.7393 +			vboSurf->surfaceType = SF_VBO_MESH;
 87.7394 +			vboSurf->numIndexes = numTriangles * 3;
 87.7395 +			vboSurf->numVerts = numVerts;
 87.7396 +			vboSurf->lightmapNum = -1;
 87.7397 +			ZeroBounds(vboSurf->bounds[0], vboSurf->bounds[1]);	// FIXME: merge surface bounding boxes
 87.7398 +
 87.7399 +			// create arrays
 87.7400 +			triangles = ri.Hunk_AllocateTempMemory(numTriangles * sizeof(srfTriangle_t));
 87.7401 +			numTriangles = 0;
 87.7402 +
 87.7403 +			// build triangle indices
 87.7404 +			for(l = k; l < numCaches; l++)
 87.7405 +			{
 87.7406 +				iaCache2 = iaCachesSorted[l];
 87.7407 +
 87.7408 +				surface = iaCache2->surface;
 87.7409 +
 87.7410 +				if(surface->shader != shader)
 87.7411 +					continue;
 87.7412 +
 87.7413 +				if(*surface->data == SF_FACE)
 87.7414 +				{
 87.7415 +					srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
 87.7416 +
 87.7417 +					for(i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++)
 87.7418 +					{
 87.7419 +						if(tri->facingLight)
 87.7420 +						{
 87.7421 +							for(j = 0; j < 3; j++)
 87.7422 +							{
 87.7423 +								triangles[numTriangles].indexes[j] = tri->indexes[j];
 87.7424 +							}
 87.7425 +
 87.7426 +							numTriangles++;
 87.7427 +						}
 87.7428 +					}
 87.7429 +				}
 87.7430 +				else if(*surface->data == SF_GRID)
 87.7431 +				{
 87.7432 +					srfGridMesh_t  *srf = (srfGridMesh_t *) surface->data;
 87.7433 +
 87.7434 +					for(i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++)
 87.7435 +					{
 87.7436 +						if(tri->facingLight)
 87.7437 +						{
 87.7438 +							for(j = 0; j < 3; j++)
 87.7439 +							{
 87.7440 +								triangles[numTriangles].indexes[j] = tri->indexes[j];
 87.7441 +							}
 87.7442 +
 87.7443 +							numTriangles++;
 87.7444 +						}
 87.7445 +					}
 87.7446 +				}
 87.7447 +				else if(*surface->data == SF_TRIANGLES)
 87.7448 +				{
 87.7449 +					srfTriangles_t *srf = (srfTriangles_t *) surface->data;
 87.7450 +
 87.7451 +					for(i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++)
 87.7452 +					{
 87.7453 +						if(tri->facingLight)
 87.7454 +						{
 87.7455 +							for(j = 0; j < 3; j++)
 87.7456 +							{
 87.7457 +								triangles[numTriangles].indexes[j] = tri->indexes[j];
 87.7458 +							}
 87.7459 +
 87.7460 +							numTriangles++;
 87.7461 +						}
 87.7462 +					}
 87.7463 +				}
 87.7464 +			}
 87.7465 +
 87.7466 +			/*
 87.7467 +			   numVerts = OptimizeVertices(numVerts, verts, numTriangles, triangles, optimizedVerts, CompareLightVert);
 87.7468 +			   if(c_redundantVertexes)
 87.7469 +			   {
 87.7470 +			   ri.Printf(PRINT_DEVELOPER,
 87.7471 +			   "...removed %i redundant vertices from staticLightMesh %i ( %s, %i verts %i tris )\n",
 87.7472 +			   c_redundantVertexes, c_vboLightSurfaces, shader->name, numVerts, numTriangles);
 87.7473 +			   }
 87.7474 +
 87.7475 +			   vboSurf->vbo = R_CreateVBO2(va("staticLightMesh_vertices %i", c_vboLightSurfaces), numVerts, optimizedVerts,
 87.7476 +			   ATTR_POSITION | ATTR_TEXCOORD | ATTR_TANGENT | ATTR_BINORMAL | ATTR_NORMAL |
 87.7477 +			   ATTR_COLOR, GL_STATIC_DRAW_ARB);
 87.7478 +			 */
 87.7479 +
 87.7480 +#if CALC_REDUNDANT_SHADOWVERTS
 87.7481 +			OptimizeTrianglesLite(s_worldData.redundantLightVerts, numTriangles, triangles);
 87.7482 +			if(c_redundantVertexes)
 87.7483 +			{
 87.7484 +				ri.Printf(PRINT_DEVELOPER, "...removed %i redundant vertices from staticLightMesh %i ( %s, %i verts %i tris )\n",
 87.7485 +						  c_redundantVertexes, c_vboLightSurfaces, shader->name, numVerts, numTriangles);
 87.7486 +			}
 87.7487 +#endif
 87.7488 +			vboSurf->vbo = s_worldData.vbo;
 87.7489 +			vboSurf->ibo =
 87.7490 +				R_CreateIBO2(va("staticLightMesh_IBO %i", c_vboLightSurfaces), numTriangles, triangles, GL_STATIC_DRAW_ARB);
 87.7491 +
 87.7492 +			ri.Hunk_FreeTempMemory(triangles);
 87.7493 +
 87.7494 +			// add everything needed to the light
 87.7495 +			iaVBO = R_CreateInteractionVBO(light);
 87.7496 +			iaVBO->shader = (struct shader_s *)shader;
 87.7497 +			iaVBO->vboLightMesh = (struct srfVBOMesh_s *)vboSurf;
 87.7498 +
 87.7499 +			c_vboLightSurfaces++;
 87.7500 +		}
 87.7501 +	}
 87.7502 +
 87.7503 +	ri.Hunk_FreeTempMemory(iaCachesSorted);
 87.7504 +#endif
 87.7505 +}
 87.7506 +
 87.7507 +/*
 87.7508 +===============
 87.7509 +R_CreateVBOShadowCubeMeshes
 87.7510 +===============
 87.7511 +*/
 87.7512 +static void R_CreateVBOShadowCubeMeshes(trRefLight_t * light)
 87.7513 +{
 87.7514 +	int             i, j, k, l;
 87.7515 +
 87.7516 +	int             numVerts;
 87.7517 +
 87.7518 +	int             numTriangles;
 87.7519 +	srfTriangle_t  *triangles;
 87.7520 +	srfTriangle_t  *tri;
 87.7521 +
 87.7522 +	interactionVBO_t *iaVBO;
 87.7523 +
 87.7524 +	interactionCache_t *iaCache, *iaCache2;
 87.7525 +	interactionCache_t **iaCachesSorted;
 87.7526 +	int             numCaches;
 87.7527 +
 87.7528 +	shader_t       *shader, *oldShader;
 87.7529 +	qboolean        alphaTest, oldAlphaTest;
 87.7530 +	int             cubeSide;
 87.7531 +
 87.7532 +	bspSurface_t   *surface;
 87.7533 +
 87.7534 +	srfVBOMesh_t   *vboSurf;
 87.7535 +
 87.7536 +	if(!r_vboShadows->integer)
 87.7537 +		return;
 87.7538 +
 87.7539 +	if(r_shadows->integer < 4)
 87.7540 +		return;
 87.7541 +
 87.7542 +	if(!light->firstInteractionCache)
 87.7543 +	{
 87.7544 +		// this light has no interactions precached
 87.7545 +		return;
 87.7546 +	}
 87.7547 +
 87.7548 +	if(light->l.noShadows)
 87.7549 +		return;
 87.7550 +
 87.7551 +	if(light->l.rlType != RL_OMNI)
 87.7552 +		return;
 87.7553 +
 87.7554 +	// count number of interaction caches
 87.7555 +	numCaches = 0;
 87.7556 +	for(iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next)
 87.7557 +	{
 87.7558 +		if(iaCache->redundant)
 87.7559 +			continue;
 87.7560 +
 87.7561 +		surface = iaCache->surface;
 87.7562 +
 87.7563 +		if(!surface->shader->interactLight)
 87.7564 +			continue;
 87.7565 +
 87.7566 +		if(surface->shader->isSky)
 87.7567 +			continue;
 87.7568 +
 87.7569 +		if(surface->shader->noShadows)
 87.7570 +			continue;
 87.7571 +
 87.7572 +		if(surface->shader->sort > SS_OPAQUE)
 87.7573 +			continue;
 87.7574 +
 87.7575 +		numCaches++;
 87.7576 +	}
 87.7577 +
 87.7578 +	// build interaction caches list
 87.7579 +	iaCachesSorted = ri.Hunk_AllocateTempMemory(numCaches * sizeof(iaCachesSorted[0]));
 87.7580 +
 87.7581 +	numCaches = 0;
 87.7582 +	for(iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next)
 87.7583 +	{
 87.7584 +		if(iaCache->redundant)
 87.7585 +			continue;
 87.7586 +
 87.7587 +		surface = iaCache->surface;
 87.7588 +
 87.7589 +		if(!surface->shader->interactLight)
 87.7590 +			continue;
 87.7591 +
 87.7592 +		if(surface->shader->isSky)
 87.7593 +			continue;
 87.7594 +
 87.7595 +		if(surface->shader->noShadows)
 87.7596 +			continue;
 87.7597 +
 87.7598 +		if(surface->shader->sort > SS_OPAQUE)
 87.7599 +			continue;
 87.7600 +
 87.7601 +		iaCachesSorted[numCaches] = iaCache;
 87.7602 +		numCaches++;
 87.7603 +	}
 87.7604 +
 87.7605 +	// sort interaction caches by shader
 87.7606 +	qsort(iaCachesSorted, numCaches, sizeof(iaCachesSorted), InteractionCacheCompare);
 87.7607 +
 87.7608 +	// create a VBO for each shader
 87.7609 +	for(cubeSide = 0; cubeSide < 6; cubeSide++)
 87.7610 +	{
 87.7611 +		shader = oldShader = NULL;
 87.7612 +		oldAlphaTest = alphaTest = -1;
 87.7613 +
 87.7614 +		for(k = 0; k < numCaches; k++)
 87.7615 +		{
 87.7616 +			iaCache = iaCachesSorted[k];
 87.7617 +			shader = iaCache->surface->shader;
 87.7618 +			alphaTest = shader->alphaTest;
 87.7619 +
 87.7620 +			//if(!(iaCache->cubeSideBits & (1 << cubeSide)))
 87.7621 +			//  continue;
 87.7622 +
 87.7623 +			//if(shader != oldShader)
 87.7624 +			if(alphaTest ? shader != oldShader : alphaTest != oldAlphaTest)
 87.7625 +			{
 87.7626 +				oldShader = shader;
 87.7627 +				oldAlphaTest = alphaTest;
 87.7628 +
 87.7629 +				// count vertices and indices
 87.7630 +				numVerts = 0;
 87.7631 +				numTriangles = 0;
 87.7632 +
 87.7633 +				for(l = k; l < numCaches; l++)
 87.7634 +				{
 87.7635 +					iaCache2 = iaCachesSorted[l];
 87.7636 +
 87.7637 +					surface = iaCache2->surface;
 87.7638 +
 87.7639 +#if 0
 87.7640 +					if(surface->shader != shader)
 87.7641 +						break;
 87.7642 +#else
 87.7643 +					if(alphaTest)
 87.7644 +					{
 87.7645 +						if(surface->shader != shader)
 87.7646 +							break;
 87.7647 +					}
 87.7648 +					else
 87.7649 +					{
 87.7650 +						if(surface->shader->alphaTest != alphaTest)
 87.7651 +							break;
 87.7652 +					}
 87.7653 +#endif
 87.7654 +
 87.7655 +					if(!(iaCache2->cubeSideBits & (1 << cubeSide)))
 87.7656 +						continue;
 87.7657 +
 87.7658 +					if(*surface->data == SF_FACE)
 87.7659 +					{
 87.7660 +						srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
 87.7661 +
 87.7662 +						if(srf->numTriangles)
 87.7663 +							numTriangles +=
 87.7664 +								UpdateLightTriangles(s_worldData.verts, srf->numTriangles,
 87.7665 +													 s_worldData.triangles + srf->firstTriangle, surface->shader, light);
 87.7666 +
 87.7667 +						if(srf->numVerts)
 87.7668 +							numVerts += srf->numVerts;
 87.7669 +					}
 87.7670 +					else if(*surface->data == SF_GRID)
 87.7671 +					{
 87.7672 +						srfGridMesh_t  *srf = (srfGridMesh_t *) surface->data;
 87.7673 +
 87.7674 +						if(srf->numTriangles)
 87.7675 +							numTriangles +=
 87.7676 +								UpdateLightTriangles(s_worldData.verts, srf->numTriangles,
 87.7677 +													 s_worldData.triangles + srf->firstTriangle, surface->shader, light);
 87.7678 +
 87.7679 +						if(srf->numVerts)
 87.7680 +							numVerts += srf->numVerts;
 87.7681 +					}
 87.7682 +					else if(*surface->data == SF_TRIANGLES)
 87.7683 +					{
 87.7684 +						srfTriangles_t *srf = (srfTriangles_t *) surface->data;
 87.7685 +
 87.7686 +						if(srf->numTriangles)
 87.7687 +							numTriangles +=
 87.7688 +								UpdateLightTriangles(s_worldData.verts, srf->numTriangles,
 87.7689 +													 s_worldData.triangles + srf->firstTriangle, surface->shader, light);
 87.7690 +
 87.7691 +						if(srf->numVerts)
 87.7692 +							numVerts += srf->numVerts;
 87.7693 +					}
 87.7694 +				}
 87.7695 +
 87.7696 +				if(!numVerts || !numTriangles)
 87.7697 +					continue;
 87.7698 +
 87.7699 +				//ri.Printf(PRINT_ALL, "...calculating light mesh VBOs ( %s, %i verts %i tris )\n", shader->name, vertexesNum, indexesNum / 3);
 87.7700 +
 87.7701 +				// create surface
 87.7702 +				vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low);
 87.7703 +				vboSurf->surfaceType = SF_VBO_MESH;
 87.7704 +				vboSurf->numIndexes = numTriangles * 3;
 87.7705 +				vboSurf->numVerts = numVerts;
 87.7706 +				vboSurf->lightmapNum = -1;
 87.7707 +				ZeroBounds(vboSurf->bounds[0], vboSurf->bounds[1]);
 87.7708 +
 87.7709 +				// create arrays
 87.7710 +				triangles = ri.Hunk_AllocateTempMemory(numTriangles * sizeof(srfTriangle_t));
 87.7711 +				numTriangles = 0;
 87.7712 +
 87.7713 +				// build triangle indices
 87.7714 +				for(l = k; l < numCaches; l++)
 87.7715 +				{
 87.7716 +					iaCache2 = iaCachesSorted[l];
 87.7717 +
 87.7718 +					surface = iaCache2->surface;
 87.7719 +
 87.7720 +#if 0
 87.7721 +					if(surface->shader != shader)
 87.7722 +						break;
 87.7723 +#else
 87.7724 +					if(alphaTest)
 87.7725 +					{
 87.7726 +						if(surface->shader != shader)
 87.7727 +							break;
 87.7728 +					}
 87.7729 +					else
 87.7730 +					{
 87.7731 +						if(surface->shader->alphaTest != alphaTest)
 87.7732 +							break;
 87.7733 +					}
 87.7734 +#endif
 87.7735 +
 87.7736 +					if(!(iaCache2->cubeSideBits & (1 << cubeSide)))
 87.7737 +						continue;
 87.7738 +
 87.7739 +					if(*surface->data == SF_FACE)
 87.7740 +					{
 87.7741 +						srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
 87.7742 +
 87.7743 +						for(i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++)
 87.7744 +						{
 87.7745 +							if(tri->facingLight)
 87.7746 +							{
 87.7747 +								for(j = 0; j < 3; j++)
 87.7748 +								{
 87.7749 +									triangles[numTriangles].indexes[j] = tri->indexes[j];
 87.7750 +								}
 87.7751 +
 87.7752 +								numTriangles++;
 87.7753 +							}
 87.7754 +						}
 87.7755 +					}
 87.7756 +					else if(*surface->data == SF_GRID)
 87.7757 +					{
 87.7758 +						srfGridMesh_t  *srf = (srfGridMesh_t *) surface->data;
 87.7759 +
 87.7760 +						for(i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++)
 87.7761 +						{
 87.7762 +							if(tri->facingLight)
 87.7763 +							{
 87.7764 +								for(j = 0; j < 3; j++)
 87.7765 +								{
 87.7766 +									triangles[numTriangles].indexes[j] = tri->indexes[j];
 87.7767 +								}
 87.7768 +
 87.7769 +								numTriangles++;
 87.7770 +							}
 87.7771 +						}
 87.7772 +					}
 87.7773 +					else if(*surface->data == SF_TRIANGLES)
 87.7774 +					{
 87.7775 +						srfTriangles_t *srf = (srfTriangles_t *) surface->data;
 87.7776 +
 87.7777 +						for(i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++)
 87.7778 +						{
 87.7779 +							if(tri->facingLight)
 87.7780 +							{
 87.7781 +								for(j = 0; j < 3; j++)
 87.7782 +								{
 87.7783 +									triangles[numTriangles].indexes[j] = tri->indexes[j];
 87.7784 +								}
 87.7785 +
 87.7786 +								numTriangles++;
 87.7787 +							}
 87.7788 +						}
 87.7789 +					}
 87.7790 +				}
 87.7791 +
 87.7792 +				if(alphaTest)
 87.7793 +				{
 87.7794 +#if CALC_REDUNDANT_SHADOWVERTS
 87.7795 +					//OptimizeTriangles(s_worldData.numVerts, s_worldData.verts, numTriangles, triangles, CompareShadowVertAlphaTest);
 87.7796 +					OptimizeTrianglesLite(s_worldData.redundantShadowAlphaTestVerts, numTriangles, triangles);
 87.7797 +					if(c_redundantVertexes)
 87.7798 +					{
 87.7799 +						ri.Printf(PRINT_DEVELOPER,
 87.7800 +								  "...removed %i redundant vertices from staticShadowPyramidMesh %i ( %s, %i verts %i tris )\n",
 87.7801 +								  c_redundantVertexes, c_vboShadowSurfaces, shader->name, numVerts, numTriangles);
 87.7802 +					}
 87.7803 +#endif
 87.7804 +					vboSurf->vbo = s_worldData.vbo;
 87.7805 +					vboSurf->ibo =
 87.7806 +						R_CreateIBO2(va("staticShadowPyramidMesh_IBO %i", c_vboShadowSurfaces), numTriangles, triangles,
 87.7807 +									 GL_STATIC_DRAW_ARB);
 87.7808 +				}
 87.7809 +				else
 87.7810 +				{
 87.7811 +#if CALC_REDUNDANT_SHADOWVERTS
 87.7812 +					//OptimizeTriangles(s_worldData.numVerts, s_worldData.verts, numTriangles, triangles, CompareShadowVert);
 87.7813 +					OptimizeTrianglesLite(s_worldData.redundantShadowVerts, numTriangles, triangles);
 87.7814 +					if(c_redundantVertexes)
 87.7815 +					{
 87.7816 +						ri.Printf(PRINT_DEVELOPER,
 87.7817 +								  "...removed %i redundant vertices from staticShadowPyramidMesh %i ( %s, %i verts %i tris )\n",
 87.7818 +								  c_redundantVertexes, c_vboShadowSurfaces, shader->name, numVerts, numTriangles);
 87.7819 +					}
 87.7820 +#endif
 87.7821 +					vboSurf->vbo = s_worldData.vbo;
 87.7822 +					vboSurf->ibo =
 87.7823 +						R_CreateIBO2(va("staticShadowPyramidMesh_IBO %i", c_vboShadowSurfaces), numTriangles, triangles,
 87.7824 +									 GL_STATIC_DRAW_ARB);
 87.7825 +				}
 87.7826 +
 87.7827 +				ri.Hunk_FreeTempMemory(triangles);
 87.7828 +
 87.7829 +				// add everything needed to the light
 87.7830 +				iaVBO = R_CreateInteractionVBO(light);
 87.7831 +				iaVBO->cubeSideBits = (1 << cubeSide);
 87.7832 +				iaVBO->shader = (struct shader_s *)shader;
 87.7833 +				iaVBO->vboShadowMesh = (struct srfVBOMesh_s *)vboSurf;
 87.7834 +
 87.7835 +				c_vboShadowSurfaces++;
 87.7836 +			}
 87.7837 +		}
 87.7838 +	}
 87.7839 +
 87.7840 +	ri.Hunk_FreeTempMemory(iaCachesSorted);
 87.7841 +}
 87.7842 +
 87.7843 +/*
 87.7844 +===============
 87.7845 +R_CreateVBOShadowVolume
 87.7846 +Go through all static interactions of this light and create a new VBO shadow volume surface,
 87.7847 +so we can render all static shadows of this light using a single glDrawElements call
 87.7848 +without any renderer backend batching
 87.7849 +===============
 87.7850 +*/
 87.7851 +static void R_CreateVBOShadowVolume(trRefLight_t * light)
 87.7852 +{
 87.7853 +	int             i, j;
 87.7854 +
 87.7855 +	int             numLightVerts;
 87.7856 +	srfVert_t      *lightVerts;
 87.7857 +	srfVert_t      *optimizedLightVerts;
 87.7858 +
 87.7859 +	int             numLightTriangles;
 87.7860 +	srfTriangle_t  *lightTriangles;
 87.7861 +
 87.7862 +	int             numShadowIndexes;
 87.7863 +	int            *shadowIndexes;
 87.7864 +
 87.7865 +	byte           *data;
 87.7866 +	int             dataSize;
 87.7867 +	int             dataOfs;
 87.7868 +
 87.7869 +	byte           *indexes;
 87.7870 +	int             indexesSize;
 87.7871 +	int             indexesOfs;
 87.7872 +
 87.7873 +	interactionVBO_t *iaVBO;
 87.7874 +	interactionCache_t *iaCache;
 87.7875 +
 87.7876 +	bspSurface_t   *surface;
 87.7877 +	srfTriangle_t  *tri;
 87.7878 +	vec4_t          tmp;
 87.7879 +	int             index;
 87.7880 +
 87.7881 +	srfVBOShadowVolume_t *shadowSurf;
 87.7882 +
 87.7883 +	if(r_shadows->integer != 3)
 87.7884 +		return;
 87.7885 +
 87.7886 +	if(!r_vboShadows->integer)
 87.7887 +		return;
 87.7888 +
 87.7889 +	if(r_deferredShading->integer)
 87.7890 +		return;
 87.7891 +
 87.7892 +	if(!light->firstInteractionCache)
 87.7893 +	{
 87.7894 +		// this light has no interactions precached
 87.7895 +		return;
 87.7896 +	}
 87.7897 +
 87.7898 +	if(light->l.noShadows)
 87.7899 +	{
 87.7900 +		// actually noShadows lights are quite bad concerning this optimization
 87.7901 +		return;
 87.7902 +	}
 87.7903 +
 87.7904 +	// count vertices and indices
 87.7905 +	numLightVerts = 0;
 87.7906 +	numLightTriangles = 0;
 87.7907 +
 87.7908 +	for(iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next)
 87.7909 +	{
 87.7910 +		if(iaCache->redundant)
 87.7911 +			continue;
 87.7912 +
 87.7913 +		surface = iaCache->surface;
 87.7914 +
 87.7915 +		if(surface->shader->sort > SS_OPAQUE)
 87.7916 +			continue;
 87.7917 +
 87.7918 +		if(surface->shader->noShadows)
 87.7919 +			continue;
 87.7920 +
 87.7921 +		if(*surface->data == SF_FACE)
 87.7922 +		{
 87.7923 +			srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
 87.7924 +
 87.7925 +			if(srf->numTriangles)
 87.7926 +				numLightTriangles += UpdateLightTriangles(srf->verts, srf->numTriangles, srf->triangles, surface->shader, light);
 87.7927 +
 87.7928 +			if(srf->numVerts)
 87.7929 +				numLightVerts += srf->numVerts;
 87.7930 +		}
 87.7931 +		else if(*surface->data == SF_GRID)
 87.7932 +		{
 87.7933 +			srfGridMesh_t  *srf = (srfGridMesh_t *) surface->data;
 87.7934 +
 87.7935 +			if(srf->numTriangles)
 87.7936 +				numLightTriangles += UpdateLightTriangles(srf->verts, srf->numTriangles, srf->triangles, surface->shader, light);
 87.7937 +
 87.7938 +			if(srf->numVerts)
 87.7939 +				numLightVerts += srf->numVerts;
 87.7940 +		}
 87.7941 +		else if(*surface->data == SF_TRIANGLES)
 87.7942 +		{
 87.7943 +			srfTriangles_t *srf = (srfTriangles_t *) surface->data;
 87.7944 +
 87.7945 +			if(srf->numTriangles)
 87.7946 +				numLightTriangles += UpdateLightTriangles(srf->verts, srf->numTriangles, srf->triangles, surface->shader, light);
 87.7947 +
 87.7948 +			if(srf->numVerts)
 87.7949 +				numLightVerts += srf->numVerts;
 87.7950 +		}
 87.7951 +	}
 87.7952 +
 87.7953 +	if(!numLightVerts || !numLightTriangles)
 87.7954 +		return;
 87.7955 +
 87.7956 +	// create light arrays
 87.7957 +	lightVerts = ri.Hunk_AllocateTempMemory(numLightVerts * sizeof(srfVert_t));
 87.7958 +	optimizedLightVerts = ri.Hunk_AllocateTempMemory(numLightVerts * sizeof(srfVert_t));
 87.7959 +	numLightVerts = 0;
 87.7960 +
 87.7961 +	lightTriangles = ri.Hunk_AllocateTempMemory(numLightTriangles * sizeof(srfTriangle_t));
 87.7962 +	shadowIndexes = ri.Hunk_AllocateTempMemory(numLightTriangles * (6 + 2) * 3 * sizeof(int));
 87.7963 +
 87.7964 +	numLightTriangles = 0;
 87.7965 +	numShadowIndexes = 0;
 87.7966 +
 87.7967 +	for(iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next)
 87.7968 +	{
 87.7969 +		if(iaCache->redundant)
 87.7970 +			continue;
 87.7971 +
 87.7972 +		surface = iaCache->surface;
 87.7973 +
 87.7974 +		if(surface->shader->sort > SS_OPAQUE)
 87.7975 +			continue;
 87.7976 +
 87.7977 +		if(surface->shader->noShadows)
 87.7978 +			continue;
 87.7979 +
 87.7980 +		// set the interaction to lightonly because we will render the shadows
 87.7981 +		// using the new srfVBOShadowVolume
 87.7982 +		iaCache->type = IA_LIGHTONLY;
 87.7983 +
 87.7984 +		// set up triangle indices
 87.7985 +		//if(iaCache->numLightIndexes)
 87.7986 +		/*
 87.7987 +		   {
 87.7988 +		   for(i = 0; i < iaCache->numLightIndexes / 3; i++)
 87.7989 +		   {
 87.7990 +		   for(j = 0; j < 3; j++)
 87.7991 +		   {
 87.7992 +		   lightTriangles[numLightTriangles + i].indexes[j] = numLightVerts + iaCache->lightIndexes[i * 3 + j];
 87.7993 +		   }
 87.7994 +		   }
 87.7995 +
 87.7996 +		   numLightTriangles += iaCache->numLightIndexes / 3;
 87.7997 +		   }
 87.7998 +		 */
 87.7999 +
 87.8000 +		if(*surface->data == SF_FACE)
 87.8001 +		{
 87.8002 +			srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
 87.8003 +
 87.8004 +			for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
 87.8005 +			{
 87.8006 +				if(tri->facingLight)
 87.8007 +				{
 87.8008 +					for(j = 0; j < 3; j++)
 87.8009 +					{
 87.8010 +						lightTriangles[numLightTriangles].indexes[j] = numLightVerts + tri->indexes[j];
 87.8011 +					}
 87.8012 +
 87.8013 +					numLightTriangles++;
 87.8014 +				}
 87.8015 +			}
 87.8016 +
 87.8017 +			if(srf->numVerts)
 87.8018 +			{
 87.8019 +				for(i = 0; i < srf->numVerts; i++)
 87.8020 +				{
 87.8021 +					CopyVert(&srf->verts[i], &lightVerts[numLightVerts + i]);
 87.8022 +				}
 87.8023 +
 87.8024 +				numLightVerts += srf->numVerts;
 87.8025 +			}
 87.8026 +		}
 87.8027 +		else if(*surface->data == SF_GRID)
 87.8028 +		{
 87.8029 +			srfGridMesh_t  *srf = (srfGridMesh_t *) surface->data;
 87.8030 +
 87.8031 +			for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
 87.8032 +			{
 87.8033 +				if(tri->facingLight)
 87.8034 +				{
 87.8035 +					for(j = 0; j < 3; j++)
 87.8036 +					{
 87.8037 +						lightTriangles[numLightTriangles].indexes[j] = numLightVerts + tri->indexes[j];
 87.8038 +					}
 87.8039 +
 87.8040 +					numLightTriangles++;
 87.8041 +				}
 87.8042 +			}
 87.8043 +
 87.8044 +			if(srf->numVerts)
 87.8045 +			{
 87.8046 +				for(i = 0; i < srf->numVerts; i++)
 87.8047 +				{
 87.8048 +					CopyVert(&srf->verts[i], &lightVerts[numLightVerts + i]);
 87.8049 +				}
 87.8050 +
 87.8051 +				numLightVerts += srf->numVerts;
 87.8052 +			}
 87.8053 +		}
 87.8054 +		else if(*surface->data == SF_TRIANGLES)
 87.8055 +		{
 87.8056 +			srfTriangles_t *srf = (srfTriangles_t *) surface->data;
 87.8057 +
 87.8058 +			for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
 87.8059 +			{
 87.8060 +				if(tri->facingLight)
 87.8061 +				{
 87.8062 +					for(j = 0; j < 3; j++)
 87.8063 +					{
 87.8064 +						lightTriangles[numLightTriangles].indexes[j] = numLightVerts + tri->indexes[j];
 87.8065 +					}
 87.8066 +
 87.8067 +					numLightTriangles++;
 87.8068 +				}
 87.8069 +			}
 87.8070 +
 87.8071 +			if(srf->numVerts)
 87.8072 +			{
 87.8073 +				for(i = 0; i < srf->numVerts; i++)
 87.8074 +				{
 87.8075 +					CopyVert(&srf->verts[i], &lightVerts[numLightVerts + i]);
 87.8076 +				}
 87.8077 +
 87.8078 +				numLightVerts += srf->numVerts;
 87.8079 +			}
 87.8080 +		}
 87.8081 +	}
 87.8082 +
 87.8083 +	// remove duplicated vertices that don't matter
 87.8084 +	numLightVerts =
 87.8085 +		OptimizeVertices(numLightVerts, lightVerts, numLightTriangles, lightTriangles, optimizedLightVerts,
 87.8086 +						 CompareShadowVolumeVert);
 87.8087 +	if(c_redundantVertexes)
 87.8088 +	{
 87.8089 +		ri.Printf(PRINT_DEVELOPER, "...removed %i redundant vertices from staticShadowVolume %i ( %i verts %i tris )\n",
 87.8090 +				  c_redundantVertexes, c_vboShadowSurfaces, numLightVerts, numLightTriangles);
 87.8091 +	}
 87.8092 +
 87.8093 +	// use optimized light triangles to create new neighbor information for them
 87.8094 +	R_CalcSurfaceTriangleNeighbors(numLightTriangles, lightTriangles);
 87.8095 +
 87.8096 +
 87.8097 +	// calculate zfail shadow volume using the triangles' neighbor information
 87.8098 +
 87.8099 +	// set up indices for silhouette edges
 87.8100 +	for(i = 0, tri = lightTriangles; i < numLightTriangles; i++, tri++)
 87.8101 +	{
 87.8102 +		if(tri->neighbors[0] < 0)
 87.8103 +		{
 87.8104 +			shadowIndexes[numShadowIndexes + 0] = tri->indexes[1];
 87.8105 +			shadowIndexes[numShadowIndexes + 1] = tri->indexes[0];
 87.8106 +			shadowIndexes[numShadowIndexes + 2] = tri->indexes[0] + numLightVerts;
 87.8107 +
 87.8108 +			shadowIndexes[numShadowIndexes + 3] = tri->indexes[1];
 87.8109 +			shadowIndexes[numShadowIndexes + 4] = tri->indexes[0] + numLightVerts;
 87.8110 +			shadowIndexes[numShadowIndexes + 5] = tri->indexes[1] + numLightVerts;
 87.8111 +
 87.8112 +			numShadowIndexes += 6;
 87.8113 +		}
 87.8114 +
 87.8115 +		if(tri->neighbors[1] < 0)
 87.8116 +		{
 87.8117 +			shadowIndexes[numShadowIndexes + 0] = tri->indexes[2];
 87.8118 +			shadowIndexes[numShadowIndexes + 1] = tri->indexes[1];
 87.8119 +			shadowIndexes[numShadowIndexes + 2] = tri->indexes[1] + numLightVerts;
 87.8120 +
 87.8121 +			shadowIndexes[numShadowIndexes + 3] = tri->indexes[2];
 87.8122 +			shadowIndexes[numShadowIndexes + 4] = tri->indexes[1] + numLightVerts;
 87.8123 +			shadowIndexes[numShadowIndexes + 5] = tri->indexes[2] + numLightVerts;
 87.8124 +
 87.8125 +			numShadowIndexes += 6;
 87.8126 +		}
 87.8127 +
 87.8128 +		if(tri->neighbors[2] < 0)
 87.8129 +		{
 87.8130 +			shadowIndexes[numShadowIndexes + 0] = tri->indexes[0];
 87.8131 +			shadowIndexes[numShadowIndexes + 1] = tri->indexes[2];
 87.8132 +			shadowIndexes[numShadowIndexes + 2] = tri->indexes[2] + numLightVerts;
 87.8133 +
 87.8134 +			shadowIndexes[numShadowIndexes + 3] = tri->indexes[0];
 87.8135 +			shadowIndexes[numShadowIndexes + 4] = tri->indexes[2] + numLightVerts;
 87.8136 +			shadowIndexes[numShadowIndexes + 5] = tri->indexes[0] + numLightVerts;
 87.8137 +
 87.8138 +			numShadowIndexes += 6;
 87.8139 +		}
 87.8140 +	}
 87.8141 +
 87.8142 +	// set up indices for light and dark caps
 87.8143 +	for(i = 0, tri = lightTriangles; i < numLightTriangles; i++, tri++)
 87.8144 +	{
 87.8145 +		// light cap
 87.8146 +		shadowIndexes[numShadowIndexes + 0] = tri->indexes[0];
 87.8147 +		shadowIndexes[numShadowIndexes + 1] = tri->indexes[1];
 87.8148 +		shadowIndexes[numShadowIndexes + 2] = tri->indexes[2];
 87.8149 +
 87.8150 +		// dark cap
 87.8151 +		shadowIndexes[numShadowIndexes + 3] = tri->indexes[2] + numLightVerts;
 87.8152 +		shadowIndexes[numShadowIndexes + 4] = tri->indexes[1] + numLightVerts;
 87.8153 +		shadowIndexes[numShadowIndexes + 5] = tri->indexes[0] + numLightVerts;
 87.8154 +
 87.8155 +		numShadowIndexes += 6;
 87.8156 +	}
 87.8157 +
 87.8158 +	//ri.Printf(PRINT_ALL, "...calculating shadow volume VBOs %i verts %i tris\n", numLightVerts * 2, numShadowIndexes / 3);
 87.8159 +
 87.8160 +	// create surface
 87.8161 +	shadowSurf = ri.Hunk_Alloc(sizeof(*shadowSurf), h_low);
 87.8162 +	shadowSurf->surfaceType = SF_VBO_SHADOW_VOLUME;
 87.8163 +	shadowSurf->numIndexes = numShadowIndexes;
 87.8164 +	shadowSurf->numVerts = numLightVerts * 2;
 87.8165 +
 87.8166 +	// create VBOs
 87.8167 +	dataSize = numLightVerts * (sizeof(vec4_t) * 2);
 87.8168 +	data = ri.Hunk_AllocateTempMemory(dataSize);
 87.8169 +	dataOfs = 0;
 87.8170 +
 87.8171 +	indexesSize = numShadowIndexes * sizeof(int);
 87.8172 +	indexes = ri.Hunk_AllocateTempMemory(indexesSize);
 87.8173 +	indexesOfs = 0;
 87.8174 +
 87.8175 +	// set up triangle indices
 87.8176 +	for(i = 0; i < numShadowIndexes; i++)
 87.8177 +	{
 87.8178 +		index = shadowIndexes[i];
 87.8179 +
 87.8180 +		memcpy(indexes + indexesOfs, &index, sizeof(int));
 87.8181 +		indexesOfs += sizeof(int);
 87.8182 +	}
 87.8183 +
 87.8184 +	// set up xyz array
 87.8185 +	for(i = 0; i < numLightVerts; i++)
 87.8186 +	{
 87.8187 +		for(j = 0; j < 3; j++)
 87.8188 +		{
 87.8189 +			tmp[j] = optimizedLightVerts[i].xyz[j];
 87.8190 +		}
 87.8191 +		tmp[3] = 1;
 87.8192 +
 87.8193 +		memcpy(data + dataOfs, (vec_t *) tmp, sizeof(vec4_t));
 87.8194 +		dataOfs += sizeof(vec4_t);
 87.8195 +	}
 87.8196 +
 87.8197 +	for(i = 0; i < numLightVerts; i++)
 87.8198 +	{
 87.8199 +		for(j = 0; j < 3; j++)
 87.8200 +		{
 87.8201 +			tmp[j] = optimizedLightVerts[i].xyz[j];
 87.8202 +		}
 87.8203 +		tmp[3] = 0;
 87.8204 +
 87.8205 +		memcpy(data + dataOfs, (vec_t *) tmp, sizeof(vec4_t));
 87.8206 +		dataOfs += sizeof(vec4_t);
 87.8207 +	}
 87.8208 +
 87.8209 +	shadowSurf->vbo = R_CreateVBO(va("staticShadowVolume_VBO %i", c_vboShadowSurfaces), data, dataSize, GL_STATIC_DRAW_ARB);
 87.8210 +	shadowSurf->ibo = R_CreateIBO(va("staticShadowVolume_IBO %i", c_vboShadowSurfaces), indexes, indexesSize, GL_STATIC_DRAW_ARB);
 87.8211 +
 87.8212 +	ri.Hunk_FreeTempMemory(indexes);
 87.8213 +	ri.Hunk_FreeTempMemory(data);
 87.8214 +	ri.Hunk_FreeTempMemory(shadowIndexes);
 87.8215 +	ri.Hunk_FreeTempMemory(lightTriangles);
 87.8216 +	ri.Hunk_FreeTempMemory(optimizedLightVerts);
 87.8217 +	ri.Hunk_FreeTempMemory(lightVerts);
 87.8218 +
 87.8219 +	// add everything needed to the light
 87.8220 +	iaVBO = R_CreateInteractionVBO(light);
 87.8221 +	iaVBO->vboShadowVolume = (struct srfVBOShadowVolume_s *)shadowSurf;
 87.8222 +
 87.8223 +	c_vboShadowSurfaces++;
 87.8224 +}
 87.8225 +
 87.8226 +static void R_CalcInteractionCubeSideBits(trRefLight_t * light)
 87.8227 +{
 87.8228 +	interactionCache_t *iaCache;
 87.8229 +	bspSurface_t   *surface;
 87.8230 +	vec3_t          localBounds[2];
 87.8231 +
 87.8232 +	if(r_shadows->integer <= 2)
 87.8233 +		return;
 87.8234 +
 87.8235 +	if(!light->firstInteractionCache)
 87.8236 +	{
 87.8237 +		// this light has no interactions precached
 87.8238 +		return;
 87.8239 +	}
 87.8240 +
 87.8241 +	if(light->l.noShadows)
 87.8242 +	{
 87.8243 +		// actually noShadows lights are quite bad concerning this optimization
 87.8244 +		return;
 87.8245 +	}
 87.8246 +
 87.8247 +	if(light->l.rlType != RL_OMNI)
 87.8248 +		return;
 87.8249 +
 87.8250 +	/*
 87.8251 +	   if(glConfig.vertexBufferObjectAvailable && r_vboLighting->integer)
 87.8252 +	   {
 87.8253 +	   srfVBOLightMesh_t *srf;
 87.8254 +
 87.8255 +	   for(iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next)
 87.8256 +	   {
 87.8257 +	   if(iaCache->redundant)
 87.8258 +	   continue;
 87.8259 +
 87.8260 +	   if(!iaCache->vboLightMesh)
 87.8261 +	   continue;
 87.8262 +
 87.8263 +	   srf = iaCache->vboLightMesh;
 87.8264 +
 87.8265 +	   VectorCopy(srf->bounds[0], localBounds[0]);
 87.8266 +	   VectorCopy(srf->bounds[1], localBounds[1]);
 87.8267 +
 87.8268 +	   light->shadowLOD = 0;    // important for R_CalcLightCubeSideBits
 87.8269 +	   iaCache->cubeSideBits = R_CalcLightCubeSideBits(light, localBounds);
 87.8270 +	   }
 87.8271 +	   }
 87.8272 +	   else
 87.8273 +	 */
 87.8274 +	{
 87.8275 +		for(iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next)
 87.8276 +		{
 87.8277 +			surface = iaCache->surface;
 87.8278 +
 87.8279 +			if(*surface->data == SF_FACE)
 87.8280 +			{
 87.8281 +				srfSurfaceFace_t *face;
 87.8282 +
 87.8283 +				face = (srfSurfaceFace_t *) surface->data;
 87.8284 +
 87.8285 +				VectorCopy(face->bounds[0], localBounds[0]);
 87.8286 +				VectorCopy(face->bounds[1], localBounds[1]);
 87.8287 +			}
 87.8288 +			else if(*surface->data == SF_GRID)
 87.8289 +			{
 87.8290 +				srfGridMesh_t  *grid;
 87.8291 +
 87.8292 +				grid = (srfGridMesh_t *) surface->data;
 87.8293 +
 87.8294 +				VectorCopy(grid->meshBounds[0], localBounds[0]);
 87.8295 +				VectorCopy(grid->meshBounds[1], localBounds[1]);
 87.8296 +			}
 87.8297 +			else if(*surface->data == SF_TRIANGLES)
 87.8298 +			{
 87.8299 +				srfTriangles_t *tri;
 87.8300 +
 87.8301 +				tri = (srfTriangles_t *) surface->data;
 87.8302 +
 87.8303 +				VectorCopy(tri->bounds[0], localBounds[0]);
 87.8304 +				VectorCopy(tri->bounds[1], localBounds[1]);
 87.8305 +			}
 87.8306 +			else
 87.8307 +			{
 87.8308 +				iaCache->cubeSideBits = CUBESIDE_CLIPALL;
 87.8309 +				continue;
 87.8310 +			}
 87.8311 +
 87.8312 +			light->shadowLOD = 0;	// important for R_CalcLightCubeSideBits
 87.8313 +			iaCache->cubeSideBits = R_CalcLightCubeSideBits(light, localBounds);
 87.8314 +		}
 87.8315 +	}
 87.8316 +}
 87.8317 +
 87.8318 +/*
 87.8319 +=============
 87.8320 +R_PrecacheInteractions
 87.8321 +=============
 87.8322 +*/
 87.8323 +void R_PrecacheInteractions()
 87.8324 +{
 87.8325 +	int             i;
 87.8326 +	trRefLight_t   *light;
 87.8327 +	bspSurface_t   *surface;
 87.8328 +	int             numLeafs;
 87.8329 +	int             startTime, endTime;
 87.8330 +
 87.8331 +	//if(r_precomputedLighting->integer)
 87.8332 +	//  return;
 87.8333 +
 87.8334 +	startTime = ri.Milliseconds();
 87.8335 +
 87.8336 +	// reset surfaces' viewCount
 87.8337 +	s_lightCount = 0;
 87.8338 +	for(i = 0, surface = s_worldData.surfaces; i < s_worldData.numSurfaces; i++, surface++)
 87.8339 +	{
 87.8340 +		surface->lightCount = -1;
 87.8341 +	}
 87.8342 +
 87.8343 +	Com_InitGrowList(&s_interactions, 100);
 87.8344 +
 87.8345 +	c_redundantInteractions = 0;
 87.8346 +	c_vboWorldSurfaces = 0;
 87.8347 +	c_vboLightSurfaces = 0;
 87.8348 +	c_vboShadowSurfaces = 0;
 87.8349 +
 87.8350 +	ri.Printf(PRINT_ALL, "...precaching %i lights\n", s_worldData.numLights);
 87.8351 +
 87.8352 +	for(i = 0; i < s_worldData.numLights; i++)
 87.8353 +	{
 87.8354 +		light = &s_worldData.lights[i];
 87.8355 +
 87.8356 +		if((r_precomputedLighting->integer || r_vertexLighting->integer) && !light->noRadiosity)
 87.8357 +			continue;
 87.8358 +
 87.8359 +#if 0
 87.8360 +		ri.Printf(PRINT_ALL, "light %i: origin(%i %i %i) radius(%i %i %i) color(%f %f %f)\n",
 87.8361 +				  i,
 87.8362 +				  (int)light->l.origin[0], (int)light->l.origin[1], (int)light->l.origin[2],
 87.8363 +				  (int)light->l.radius[0], (int)light->l.radius[1], (int)light->l.radius[2],
 87.8364 +				  light->l.color[0], light->l.color[1], light->l.color[2]);
 87.8365 +#endif
 87.8366 +
 87.8367 +		// set up light transform matrix
 87.8368 +		MatrixSetupTransformFromQuat(light->transformMatrix, light->l.rotation, light->l.origin);
 87.8369 +
 87.8370 +		// set up light origin for lighting and shadowing
 87.8371 +		R_SetupLightOrigin(light);
 87.8372 +
 87.8373 +		// set up model to light view matrix
 87.8374 +		R_SetupLightView(light);
 87.8375 +
 87.8376 +		// set up projection
 87.8377 +		R_SetupLightProjection(light);
 87.8378 +
 87.8379 +		// calc local bounds for culling
 87.8380 +		R_SetupLightLocalBounds(light);
 87.8381 +
 87.8382 +		// setup world bounds for intersection tests
 87.8383 +		R_SetupLightWorldBounds(light);
 87.8384 +
 87.8385 +		// setup frustum planes for intersection tests
 87.8386 +		R_SetupLightFrustum(light);
 87.8387 +
 87.8388 +		// setup interactions
 87.8389 +		light->firstInteractionCache = NULL;
 87.8390 +		light->lastInteractionCache = NULL;
 87.8391 +
 87.8392 +		light->firstInteractionVBO = NULL;
 87.8393 +		light->lastInteractionVBO = NULL;
 87.8394 +
 87.8395 +		// perform culling and add all the potentially visible surfaces
 87.8396 +		s_lightCount++;
 87.8397 +		R_RecursivePrecacheInteractionNode(s_worldData.nodes, light);
 87.8398 +
 87.8399 +		// count number of leafs that touch this light
 87.8400 +		s_lightCount++;
 87.8401 +		numLeafs = 0;
 87.8402 +		R_RecursiveAddInteractionNode(s_worldData.nodes, light, &numLeafs, qtrue);
 87.8403 +		//ri.Printf(PRINT_ALL, "light %i touched %i leaves\n", i, numLeafs);
 87.8404 +
 87.8405 +		// create storage room for them
 87.8406 +		light->leafs = (struct bspNode_s **)ri.Hunk_Alloc(numLeafs * sizeof(*light->leafs), h_low);
 87.8407 +		light->numLeafs = numLeafs;
 87.8408 +
 87.8409 +		// fill storage with them
 87.8410 +		s_lightCount++;
 87.8411 +		numLeafs = 0;
 87.8412 +		R_RecursiveAddInteractionNode(s_worldData.nodes, light, &numLeafs, qfalse);
 87.8413 +
 87.8414 +#if 0
 87.8415 +		// Tr3b: this can cause really bad shadow problems :/
 87.8416 +
 87.8417 +		// check if interactions are inside shadows of other interactions
 87.8418 +		R_KillRedundantInteractions(light);
 87.8419 +#endif
 87.8420 +
 87.8421 +		// create a static VBO surface for each light geometry batch
 87.8422 +		R_CreateVBOLightMeshes(light);
 87.8423 +
 87.8424 +		// calculate pyramid bits for each interaction in omni-directional lights
 87.8425 +		R_CalcInteractionCubeSideBits(light);
 87.8426 +
 87.8427 +		// create a static VBO surface for each light geometry batch inside a cubemap pyramid
 87.8428 +		R_CreateVBOShadowCubeMeshes(light);
 87.8429 +
 87.8430 +		// create a static VBO surface of all shadow volumes
 87.8431 +		R_CreateVBOShadowVolume(light);
 87.8432 +	}
 87.8433 +
 87.8434 +	// move interactions grow list to hunk
 87.8435 +	s_worldData.numInteractions = s_interactions.currentElements;
 87.8436 +	s_worldData.interactions = ri.Hunk_Alloc(s_worldData.numInteractions * sizeof(*s_worldData.interactions), h_low);
 87.8437 +
 87.8438 +	for(i = 0; i < s_worldData.numInteractions; i++)
 87.8439 +	{
 87.8440 +		s_worldData.interactions[i] = (interactionCache_t *) Com_GrowListElement(&s_interactions, i);
 87.8441 +	}
 87.8442 +
 87.8443 +	Com_DestroyGrowList(&s_interactions);
 87.8444 +
 87.8445 +
 87.8446 +	ri.Printf(PRINT_ALL, "%i interactions precached\n", s_worldData.numInteractions);
 87.8447 +	ri.Printf(PRINT_ALL, "%i interactions were hidden in shadows\n", c_redundantInteractions);
 87.8448 +
 87.8449 +	if(r_shadows->integer >= 4)
 87.8450 +	{
 87.8451 +		// only interesting for omni-directional shadow mapping
 87.8452 +		ri.Printf(PRINT_ALL, "%i omni pyramid tests\n", tr.pc.c_pyramidTests);
 87.8453 +		ri.Printf(PRINT_ALL, "%i omni pyramid surfaces visible\n", tr.pc.c_pyramid_cull_ent_in);
 87.8454 +		ri.Printf(PRINT_ALL, "%i omni pyramid surfaces clipped\n", tr.pc.c_pyramid_cull_ent_clip);
 87.8455 +		ri.Printf(PRINT_ALL, "%i omni pyramid surfaces culled\n", tr.pc.c_pyramid_cull_ent_out);
 87.8456 +	}
 87.8457 +
 87.8458 +	endTime = ri.Milliseconds();
 87.8459 +
 87.8460 +	ri.Printf(PRINT_ALL, "lights precaching time = %5.2f seconds\n", (endTime - startTime) / 1000.0);
 87.8461 +}
 87.8462 +
 87.8463 +
 87.8464 +#define HASHTABLE_SIZE 7919 // 32749 // 2039 	/* prime, use % */
 87.8465 +#define HASH_USE_EPSILON
 87.8466 +
 87.8467 +#ifdef HASH_USE_EPSILON
 87.8468 +#define HASH_XYZ_EPSILON					0.01f
 87.8469 +#define HASH_XYZ_EPSILONSPACE_MULTIPLIER	1.f / HASH_XYZ_EPSILON
 87.8470 +#endif
 87.8471 +
 87.8472 +unsigned int VertexCoordGenerateHash(const vec3_t xyz)
 87.8473 +{
 87.8474 +	unsigned int    hash = 0;
 87.8475 +
 87.8476 +#ifndef HASH_USE_EPSILON
 87.8477 +	hash += ~(*((unsigned int *)&xyz[0]) << 15);
 87.8478 +	hash ^= (*((unsigned int *)&xyz[0]) >> 10);
 87.8479 +	hash += (*((unsigned int *)&xyz[1]) << 3);
 87.8480 +	hash ^= (*((unsigned int *)&xyz[1]) >> 6);
 87.8481 +	hash += ~(*((unsigned int *)&xyz[2]) << 11);
 87.8482 +	hash ^= (*((unsigned int *)&xyz[2]) >> 16);
 87.8483 +#else
 87.8484 +	vec3_t          xyz_epsilonspace;
 87.8485 +
 87.8486 +	VectorScale(xyz, HASH_XYZ_EPSILONSPACE_MULTIPLIER, xyz_epsilonspace);
 87.8487 +	xyz_epsilonspace[0] = (double)floor(xyz_epsilonspace[0]);
 87.8488 +	xyz_epsilonspace[1] = (double)floor(xyz_epsilonspace[1]);
 87.8489 +	xyz_epsilonspace[2] = (double)floor(xyz_epsilonspace[2]);
 87.8490 +
 87.8491 +	hash += ~(*((unsigned int *)&xyz_epsilonspace[0]) << 15);
 87.8492 +	hash ^= (*((unsigned int *)&xyz_epsilonspace[0]) >> 10);
 87.8493 +	hash += (*((unsigned int *)&xyz_epsilonspace[1]) << 3);
 87.8494 +	hash ^= (*((unsigned int *)&xyz_epsilonspace[1]) >> 6);
 87.8495 +	hash += ~(*((unsigned int *)&xyz_epsilonspace[2]) << 11);
 87.8496 +	hash ^= (*((unsigned int *)&xyz_epsilonspace[2]) >> 16);
 87.8497 +#endif
 87.8498 +
 87.8499 +	hash = (int)fabs(xyz[3]) / 8;
 87.8500 +
 87.8501 +	hash = hash % (HASHTABLE_SIZE);
 87.8502 +	return hash;
 87.8503 +}
 87.8504 +
 87.8505 +vertexHash_t **NewVertexHashTable(void)
 87.8506 +{
 87.8507 +	vertexHash_t **hashTable = Com_Allocate(HASHTABLE_SIZE * sizeof(vertexHash_t *));
 87.8508 +
 87.8509 +	Com_Memset(hashTable, 0, HASHTABLE_SIZE * sizeof(vertexHash_t *));
 87.8510 +
 87.8511 +	return hashTable;
 87.8512 +}
 87.8513 +
 87.8514 +void FreeVertexHashTable(vertexHash_t ** hashTable)
 87.8515 +{
 87.8516 +	int             i;
 87.8517 +	vertexHash_t *vertexHash;
 87.8518 +	vertexHash_t *nextVertexHash;
 87.8519 +
 87.8520 +	if(hashTable == NULL)
 87.8521 +		return;
 87.8522 +
 87.8523 +	for(i = 0; i < HASHTABLE_SIZE; i++)
 87.8524 +	{
 87.8525 +		if(hashTable[i])
 87.8526 +		{
 87.8527 +			nextVertexHash = NULL;
 87.8528 +
 87.8529 +			for(vertexHash = hashTable[i]; vertexHash; vertexHash = nextVertexHash)
 87.8530 +			{
 87.8531 +				nextVertexHash = vertexHash->next;
 87.8532 +				/*
 87.8533 +				if(vertexHash->data != NULL)
 87.8534 +				{
 87.8535 +					Com_Dealloc(vertexHash->data);
 87.8536 +				}
 87.8537 +				*/
 87.8538 +				Com_Dealloc(vertexHash);
 87.8539 +			}
 87.8540 +		}
 87.8541 +	}
 87.8542 +
 87.8543 +	Com_Dealloc(hashTable);
 87.8544 +}
 87.8545 +
 87.8546 +vertexHash_t *FindVertexInHashTable(vertexHash_t ** hashTable, const vec3_t xyz, float distance)
 87.8547 +{
 87.8548 +	unsigned int    hash;
 87.8549 +	vertexHash_t *vertexHash;
 87.8550 +
 87.8551 +	if(hashTable == NULL || xyz == NULL)
 87.8552 +		return NULL;
 87.8553 +
 87.8554 +	hash = VertexCoordGenerateHash(xyz);
 87.8555 +
 87.8556 +	for(vertexHash = hashTable[hash]; vertexHash; vertexHash = vertexHash->next)
 87.8557 +	{
 87.8558 +#ifndef HASH_USE_EPSILON
 87.8559 +		if((vertexHash->vcd.xyz[0] != xyz[0] || vertexHash->vcd.xyz[1] != xyz[1] ||
 87.8560 +			vertexHash->vcd.xyz[2] != xyz[2]))
 87.8561 +			continue;
 87.8562 +
 87.8563 +#elif 1
 87.8564 +		if(Distance(xyz, vertexHash->xyz) > distance)
 87.8565 +			continue;
 87.8566 +
 87.8567 +#else
 87.8568 +		if((fabs(xyz[0] - vertexHash->vcd.xyz[0])) > HASH_XYZ_EPSILON ||
 87.8569 +		   (fabs(xyz[1] - vertexHash->vcd.xyz[1])) > HASH_XYZ_EPSILON ||
 87.8570 +		   (fabs(xyz[2] - vertexHash->vcd.xyz[2])) > HASH_XYZ_EPSILON)
 87.8571 +			continue;
 87.8572 +#endif
 87.8573 +		return vertexHash;
 87.8574 +	}
 87.8575 +
 87.8576 +	return NULL;
 87.8577 +}
 87.8578 +
 87.8579 +vertexHash_t *AddVertexToHashTable(vertexHash_t ** hashTable, vec3_t xyz, void *data)
 87.8580 +{
 87.8581 +	unsigned int    hash;
 87.8582 +	vertexHash_t *vertexHash;
 87.8583 +
 87.8584 +	if(hashTable == NULL || xyz == NULL)
 87.8585 +		return NULL;
 87.8586 +
 87.8587 +	vertexHash = Com_Allocate(sizeof(vertexHash_t));
 87.8588 +
 87.8589 +	if(!vertexHash)
 87.8590 +		return NULL;
 87.8591 +
 87.8592 +	hash = VertexCoordGenerateHash(xyz);
 87.8593 +
 87.8594 +	VectorCopy(xyz, vertexHash->xyz);
 87.8595 +	vertexHash->data = data;
 87.8596 +
 87.8597 +	// link into table
 87.8598 +	vertexHash->next = hashTable[hash];
 87.8599 +	hashTable[hash] = vertexHash;
 87.8600 +
 87.8601 +	return vertexHash;
 87.8602 +}
 87.8603 +
 87.8604 +void GL_BindNearestCubeMap(const vec3_t xyz)
 87.8605 +{
 87.8606 +#if 0
 87.8607 +	int             j;
 87.8608 +	float			distance, maxDistance;
 87.8609 +	cubemapProbe_t *cubeProbe;
 87.8610 +
 87.8611 +	GLimp_LogComment("--- GL_BindNearestCubeMap ---\n");
 87.8612 +
 87.8613 +	maxDistance = 9999999.0f;
 87.8614 +	tr.autoCubeImage = tr.blackCubeImage;
 87.8615 +	for(j = 0; j < tr.cubeProbes.currentElements; j++)
 87.8616 +	{
 87.8617 +		cubeProbe = Com_GrowListElement(&tr.cubeProbes, j);
 87.8618 +
 87.8619 +		distance = Distance(cubeProbe->origin, xyz);
 87.8620 +		if(distance < maxDistance)
 87.8621 +		{
 87.8622 +			tr.autoCubeImage = cubeProbe->cubemap;
 87.8623 +			maxDistance = distance;
 87.8624 +		}
 87.8625 +	}
 87.8626 +#else
 87.8627 +	float			distance, maxDistance;
 87.8628 +	cubemapProbe_t *cubeProbe;
 87.8629 +	unsigned int    hash;
 87.8630 +	vertexHash_t	*vertexHash;
 87.8631 +
 87.8632 +	tr.autoCubeImage = tr.blackCubeImage;
 87.8633 +
 87.8634 +	if(tr.cubeHashTable == NULL || xyz == NULL)
 87.8635 +		return;
 87.8636 +
 87.8637 +	maxDistance = 9999999.0f;
 87.8638 +
 87.8639 +	hash = VertexCoordGenerateHash(xyz);
 87.8640 +
 87.8641 +	for(vertexHash = tr.cubeHashTable[hash]; vertexHash; vertexHash = vertexHash->next)
 87.8642 +	{
 87.8643 +		cubeProbe = vertexHash->data;
 87.8644 +
 87.8645 +		distance = Distance(cubeProbe->origin, xyz);
 87.8646 +		if(distance < maxDistance)
 87.8647 +		{
 87.8648 +			tr.autoCubeImage = cubeProbe->cubemap;
 87.8649 +			maxDistance = distance;
 87.8650 +		}
 87.8651 +	}
 87.8652 +#endif
 87.8653 +
 87.8654 +	GL_Bind(tr.autoCubeImage);
 87.8655 +}
 87.8656 +
 87.8657 +static void R_BuildCubeMaps(void)
 87.8658 +{
 87.8659 +#if 1
 87.8660 +	int             i, j, k;
 87.8661 +	int             ii, jj;
 87.8662 +	int             cl;
 87.8663 +	refdef_t        rf;
 87.8664 +	qboolean        flipx;
 87.8665 +	qboolean        flipy;
 87.8666 +	int             x, y, xy, xy2;
 87.8667 +
 87.8668 +	cubemapProbe_t *cubeProbe;
 87.8669 +	byte            temp[128 * 128 * 4];
 87.8670 +	byte           *dest;
 87.8671 +
 87.8672 +	bspCluster_t   *cluster;
 87.8673 +
 87.8674 +	int             distance = 512;
 87.8675 +	qboolean        bad;
 87.8676 +
 87.8677 +//  srfSurfaceStatic_t *sv;
 87.8678 +	int				progress = 0;
 87.8679 +	int             startTime, endTime;
 87.8680 +
 87.8681 +	startTime = ri.Milliseconds();
 87.8682 +
 87.8683 +	memset(&rf, 0, sizeof(refdef_t));
 87.8684 +
 87.8685 +	for(i = 0; i < 6; i++)
 87.8686 +	{
 87.8687 +		tr.cubeTemp[i] = ri.Malloc(REF_CUBEMAP_SIZE * REF_CUBEMAP_SIZE * 4);
 87.8688 +	}
 87.8689 +
 87.8690 +	// calculate origins for our probes
 87.8691 +	Com_InitGrowList(&tr.cubeProbes, 4000);
 87.8692 +	tr.cubeHashTable = NewVertexHashTable();
 87.8693 +
 87.8694 +#if 0
 87.8695 +	if(tr.world->vis)
 87.8696 +	{
 87.8697 +		for(cl = 0; cl < tr.world->numClusters; cl++)
 87.8698 +		{
 87.8699 +			cluster = &tr.world->clusters[cl];
 87.8700 +
 87.8701 +			// check to see if this is a shit location
 87.8702 +			if(CM_PointContents(cluster->origin, 0) == CONTENTS_SOLID)
 87.8703 +				continue;
 87.8704 +
 87.8705 +			// check to see if we're too close to an existing probe
 87.8706 +			bad = qfalse;
 87.8707 +			for(i = 0; i < tr.cubeProbes.currentElements; i++)
 87.8708 +			{
 87.8709 +				cubeProbe = Com_GrowListElement(&tr.cubeProbes, i);
 87.8710 +
 87.8711 +				if(Distance(cubeProbe->origin, cluster->origin) < distance)
 87.8712 +				{
 87.8713 +					bad = qtrue;
 87.8714 +					break;
 87.8715 +				}
 87.8716 +			}
 87.8717 +
 87.8718 +			if(bad == qfalse)
 87.8719 +			{
 87.8720 +				cubeProbe = ri.Hunk_Alloc(sizeof(*cubeProbe), h_low);
 87.8721 +				Com_AddToGrowList(&tr.cubeProbes, cubeProbe);
 87.8722 +
 87.8723 +				VectorCopy(cluster->origin, cubeProbe->origin);
 87.8724 +
 87.8725 +				// FIXME
 87.8726 +				//if(tr.cubeProbes.currentElements >= 128)
 87.8727 +				//  break;
 87.8728 +			}
 87.8729 +		}
 87.8730 +	}
 87.8731 +#else
 87.8732 +	{
 87.8733 +		int             numGridPoints;
 87.8734 +		bspGridPoint_t *gridPoint;
 87.8735 +		int             gridStep[3];
 87.8736 +		int             pos[3];
 87.8737 +		float           posFloat[3];
 87.8738 +
 87.8739 +		gridStep[0] = 1;
 87.8740 +		gridStep[1] = tr.world->lightGridBounds[0];
 87.8741 +		gridStep[2] = tr.world->lightGridBounds[0] * tr.world->lightGridBounds[1];
 87.8742 +
 87.8743 +		numGridPoints = tr.world->lightGridBounds[0] * tr.world->lightGridBounds[1] * tr.world->lightGridBounds[2];
 87.8744 +
 87.8745 +		ri.Printf(PRINT_ALL, "...trying to allocate %d cubemaps", numGridPoints);
 87.8746 +		ri.Printf(PRINT_ALL, " with gridsize (%i %i %i)", (int)tr.world->lightGridSize[0], (int)tr.world->lightGridSize[1],
 87.8747 +				  (int)tr.world->lightGridSize[2]);
 87.8748 +		ri.Printf(PRINT_ALL, " and gridbounds (%i %i %i)\n", (int)tr.world->lightGridBounds[0], (int)tr.world->lightGridBounds[1],
 87.8749 +				  (int)tr.world->lightGridBounds[2]);
 87.8750 +
 87.8751 +		for(i = 0; i < tr.world->lightGridBounds[0]; i += 1)
 87.8752 +		{
 87.8753 +			for(j = 0; j < tr.world->lightGridBounds[1]; j += 1)
 87.8754 +			{
 87.8755 +				for(k = 0; k < tr.world->lightGridBounds[2]; k += 1)
 87.8756 +				{
 87.8757 +					pos[0] = i;
 87.8758 +					pos[1] = j;
 87.8759 +					pos[2] = k;
 87.8760 +
 87.8761 +					posFloat[0] = i * tr.world->lightGridSize[0];
 87.8762 +					posFloat[1] = j * tr.world->lightGridSize[1];
 87.8763 +					posFloat[2] = k * tr.world->lightGridSize[2];
 87.8764 +
 87.8765 +					VectorAdd(posFloat, tr.world->lightGridOrigin, posFloat);
 87.8766 +
 87.8767 +					// check to see if this is a shit location
 87.8768 +					if(CM_PointContents(posFloat, 0) == CONTENTS_SOLID)
 87.8769 +						continue;
 87.8770 +
 87.8771 +					if(FindVertexInHashTable(tr.cubeHashTable, posFloat, 256) == NULL)
 87.8772 +					{
 87.8773 +						cubeProbe = ri.Hunk_Alloc(sizeof(*cubeProbe), h_high);
 87.8774 +						Com_AddToGrowList(&tr.cubeProbes, cubeProbe);
 87.8775 +
 87.8776 +						VectorCopy(posFloat, cubeProbe->origin);
 87.8777 +
 87.8778 +						AddVertexToHashTable(tr.cubeHashTable, posFloat, cubeProbe);
 87.8779 +
 87.8780 +						gridPoint = tr.world->lightGridData + pos[0] * gridStep[0] + pos[1] * gridStep[1] + pos[2] * gridStep[2];
 87.8781 +
 87.8782 +						// TODO connect cubeProbe with gridPoint
 87.8783 +					}
 87.8784 +				}
 87.8785 +			}
 87.8786 +		}
 87.8787 +	}
 87.8788 +#endif
 87.8789 +
 87.8790 +	// if we can't find one, fake one
 87.8791 +	if(tr.cubeProbes.currentElements == 0)
 87.8792 +	{
 87.8793 +		cubeProbe = ri.Hunk_Alloc(sizeof(*cubeProbe), h_low);
 87.8794 +		Com_AddToGrowList(&tr.cubeProbes, cubeProbe);
 87.8795 +
 87.8796 +		VectorClear(cubeProbe->origin);
 87.8797 +	}
 87.8798 +
 87.8799 +	ri.Printf(PRINT_ALL, "...pre-rendering %d cubemaps\n", tr.cubeProbes.currentElements);
 87.8800 +	for(j = 0; j < tr.cubeProbes.currentElements; j++)
 87.8801 +	{
 87.8802 +		cubeProbe = Com_GrowListElement(&tr.cubeProbes, j);
 87.8803 +
 87.8804 +		//ri.Printf(PRINT_ALL, "rendering cubemap at (%i %i %i)\n", (int)cubeProbe->origin[0], (int)cubeProbe->origin[1],
 87.8805 +		//		  (int)cubeProbe->origin[2]);
 87.8806 +
 87.8807 +		if(tr.cubeProbes.currentElements > 10 &&  ((j % (tr.cubeProbes.currentElements / 10)) == 0))
 87.8808 +		{
 87.8809 +			ri.Printf(PRINT_ALL, "%i...", progress);
 87.8810 +			progress += 10;
 87.8811 +		}
 87.8812 +
 87.8813 +		VectorCopy(cubeProbe->origin, rf.vieworg);
 87.8814 +
 87.8815 +		AxisClear(rf.viewaxis);
 87.8816 +
 87.8817 +		rf.fov_x = 90;
 87.8818 +		rf.fov_y = 90;
 87.8819 +		rf.x = 0;
 87.8820 +		rf.y = 0;
 87.8821 +		rf.width = REF_CUBEMAP_SIZE;
 87.8822 +		rf.height = REF_CUBEMAP_SIZE;
 87.8823 +		rf.time = 0;
 87.8824 +
 87.8825 +		rf.rdflags = RDF_NOCUBEMAP | RDF_NOBLOOM;
 87.8826 +
 87.8827 +		for(i = 0; i < 6; i++)
 87.8828 +		{
 87.8829 +			flipx = qfalse;
 87.8830 +			flipy = qfalse;
 87.8831 +			switch (i)
 87.8832 +			{
 87.8833 +
 87.8834 +				case 0:
 87.8835 +				{
 87.8836 +					//X+
 87.8837 +					rf.viewaxis[0][0] = 1;
 87.8838 +					rf.viewaxis[0][1] = 0;
 87.8839 +					rf.viewaxis[0][2] = 0;
 87.8840 +
 87.8841 +					rf.viewaxis[1][0] = 0;
 87.8842 +					rf.viewaxis[1][1] = 0;
 87.8843 +					rf.viewaxis[1][2] = 1;
 87.8844 +
 87.8845 +					CrossProduct(rf.viewaxis[0], rf.viewaxis[1], rf.viewaxis[2]);
 87.8846 +					//flipx=qtrue;
 87.8847 +					break;
 87.8848 +				}
 87.8849 +				case 1:
 87.8850 +				{
 87.8851 +					//X-
 87.8852 +					rf.viewaxis[0][0] = -1;
 87.8853 +					rf.viewaxis[0][1] = 0;
 87.8854 +					rf.viewaxis[0][2] = 0;
 87.8855 +
 87.8856 +					rf.viewaxis[1][0] = 0;
 87.8857 +					rf.viewaxis[1][1] = 0;
 87.8858 +					rf.viewaxis[1][2] = -1;
 87.8859 +
 87.8860 +					CrossProduct(rf.viewaxis[0], rf.viewaxis[1], rf.viewaxis[2]);
 87.8861 +					//flipx=qtrue;
 87.8862 +					break;
 87.8863 +				}
 87.8864 +				case 2:
 87.8865 +				{
 87.8866 +					//Y+
 87.8867 +					rf.viewaxis[0][0] = 0;
 87.8868 +					rf.viewaxis[0][1] = 1;
 87.8869 +					rf.viewaxis[0][2] = 0;
 87.8870 +
 87.8871 +					rf.viewaxis[1][0] = -1;
 87.8872 +					rf.viewaxis[1][1] = 0;
 87.8873 +					rf.viewaxis[1][2] = 0;
 87.8874 +
 87.8875 +					CrossProduct(rf.viewaxis[0], rf.viewaxis[1], rf.viewaxis[2]);
 87.8876 +					//flipx=qtrue;
 87.8877 +					break;
 87.8878 +				}
 87.8879 +				case 3:
 87.8880 +				{
 87.8881 +					//Y-
 87.8882 +					rf.viewaxis[0][0] = 0;
 87.8883 +					rf.viewaxis[0][1] = -1;
 87.8884 +					rf.viewaxis[0][2] = 0;
 87.8885 +
 87.8886 +					rf.viewaxis[1][0] = -1;	//-1
 87.8887 +					rf.viewaxis[1][1] = 0;
 87.8888 +					rf.viewaxis[1][2] = 0;
 87.8889 +
 87.8890 +					CrossProduct(rf.viewaxis[0], rf.viewaxis[1], rf.viewaxis[2]);
 87.8891 +					//flipx=qtrue;
 87.8892 +					break;
 87.8893 +				}
 87.8894 +				case 4:
 87.8895 +				{
 87.8896 +					//Z+
 87.8897 +					rf.viewaxis[0][0] = 0;
 87.8898 +					rf.viewaxis[0][1] = 0;
 87.8899 +					rf.viewaxis[0][2] = 1;
 87.8900 +
 87.8901 +					rf.viewaxis[1][0] = -1;
 87.8902 +					rf.viewaxis[1][1] = 0;
 87.8903 +					rf.viewaxis[1][2] = 0;
 87.8904 +
 87.8905 +					CrossProduct(rf.viewaxis[0], rf.viewaxis[1], rf.viewaxis[2]);
 87.8906 +					//  flipx=qtrue;
 87.8907 +					break;
 87.8908 +				}
 87.8909 +				case 5:
 87.8910 +				{
 87.8911 +					//Z-
 87.8912 +					rf.viewaxis[0][0] = 0;
 87.8913 +					rf.viewaxis[0][1] = 0;
 87.8914 +					rf.viewaxis[0][2] = -1;
 87.8915 +
 87.8916 +					rf.viewaxis[1][0] = 1;
 87.8917 +					rf.viewaxis[1][1] = 0;
 87.8918 +					rf.viewaxis[1][2] = 0;
 87.8919 +
 87.8920 +					CrossProduct(rf.viewaxis[0], rf.viewaxis[1], rf.viewaxis[2]);
 87.8921 +					//flipx=qtrue;
 87.8922 +					break;
 87.8923 +				}
 87.8924 +
 87.8925 +			}
 87.8926 +
 87.8927 +			tr.refdef.pixelTarget = tr.cubeTemp[i];
 87.8928 +			memset(tr.cubeTemp[i], 255, REF_CUBEMAP_SIZE * REF_CUBEMAP_SIZE * 4);
 87.8929 +			tr.refdef.pixelTargetWidth = REF_CUBEMAP_SIZE;
 87.8930 +			tr.refdef.pixelTargetHeight = REF_CUBEMAP_SIZE;
 87.8931 +
 87.8932 +			RE_BeginFrame(STEREO_CENTER);
 87.8933 +			RE_RenderScene(&rf);
 87.8934 +			RE_EndFrame(&ii, &jj);
 87.8935 +
 87.8936 +			if(flipx)
 87.8937 +			{
 87.8938 +				dest = tr.cubeTemp[i];
 87.8939 +				memcpy(temp, dest, REF_CUBEMAP_SIZE * REF_CUBEMAP_SIZE * 4);
 87.8940 +
 87.8941 +				for(y = 0; y < REF_CUBEMAP_SIZE; y++)
 87.8942 +				{
 87.8943 +					for(x = 0; x < REF_CUBEMAP_SIZE; x++)
 87.8944 +					{
 87.8945 +						xy = ((y * REF_CUBEMAP_SIZE) + x) * 4;
 87.8946 +						xy2 = ((y * REF_CUBEMAP_SIZE) + ((REF_CUBEMAP_SIZE - 1) - x)) * 4;
 87.8947 +						dest[xy2 + 0] = temp[xy + 0];
 87.8948 +						dest[xy2 + 1] = temp[xy + 1];
 87.8949 +						dest[xy2 + 2] = temp[xy + 2];
 87.8950 +						dest[xy2 + 3] = temp[xy + 3];
 87.8951 +
 87.8952 +					}
 87.8953 +				}
 87.8954 +			}
 87.8955 +
 87.8956 +			if(flipy)
 87.8957 +			{
 87.8958 +				dest = tr.cubeTemp[i];
 87.8959 +				memcpy(temp, dest, REF_CUBEMAP_SIZE * REF_CUBEMAP_SIZE * 4);
 87.8960 +
 87.8961 +				for(y = 0; y < REF_CUBEMAP_SIZE; y++)
 87.8962 +				{
 87.8963 +					for(x = 0; x < REF_CUBEMAP_SIZE; x++)
 87.8964 +					{
 87.8965 +						xy = ((y * REF_CUBEMAP_SIZE) + x) * 4;
 87.8966 +						xy2 = ((((REF_CUBEMAP_SIZE - 1) - y) * REF_CUBEMAP_SIZE) + x) * 4;
 87.8967 +						dest[xy2 + 0] = temp[xy + 0];
 87.8968 +						dest[xy2 + 1] = temp[xy + 1];
 87.8969 +						dest[xy2 + 2] = temp[xy + 2];
 87.8970 +						dest[xy2 + 3] = temp[xy + 3];
 87.8971 +
 87.8972 +					}
 87.8973 +				}
 87.8974 +			}
 87.8975 +
 87.8976 +			// encode the pixel intensity into the alpha channel, saves work in the shader
 87.8977 +			if(qtrue)
 87.8978 +			{
 87.8979 +				byte            r, g, b, best;
 87.8980 +
 87.8981 +				dest = tr.cubeTemp[i];
 87.8982 +				for(y = 0; y < REF_CUBEMAP_SIZE; y++)
 87.8983 +				{
 87.8984 +					for(x = 0; x < REF_CUBEMAP_SIZE; x++)
 87.8985 +					{
 87.8986 +						xy = ((y * REF_CUBEMAP_SIZE) + x) * 4;
 87.8987 +
 87.8988 +						r = dest[xy + 0];
 87.8989 +						g = dest[xy + 1];
 87.8990 +						b = dest[xy + 2];
 87.8991 +
 87.8992 +						if((r > g) && (r > b))
 87.8993 +						{
 87.8994 +							best = r;
 87.8995 +						}
 87.8996 +						else if((g > r) && (g > b))
 87.8997 +						{
 87.8998 +							best = g;
 87.8999 +						}
 87.9000 +						else
 87.9001 +						{
 87.9002 +							best = b;
 87.9003 +						}
 87.9004 +
 87.9005 +						dest[xy + 3] = best;
 87.9006 +					}
 87.9007 +				}
 87.9008 +			}
 87.9009 +		}
 87.9010 +
 87.9011 +		// build the cubemap
 87.9012 +		//cubeProbe->cubemap = R_CreateCubeImage(va("_autoCube%d", j), (const byte **)tr.cubeTemp, REF_CUBEMAP_SIZE, REF_CUBEMAP_SIZE, IF_NOPICMIP, FT_LINEAR, WT_EDGE_CLAMP);
 87.9013 +		cubeProbe->cubemap = R_AllocImage(va("_autoCube%d", j), qfalse);
 87.9014 +		if(!cubeProbe->cubemap)
 87.9015 +			return;
 87.9016 +
 87.9017 +		cubeProbe->cubemap->type = GL_TEXTURE_CUBE_MAP_ARB;
 87.9018 +
 87.9019 +		cubeProbe->cubemap->width = REF_CUBEMAP_SIZE;
 87.9020 +		cubeProbe->cubemap->height = REF_CUBEMAP_SIZE;
 87.9021 +
 87.9022 +		cubeProbe->cubemap->bits = IF_NOPICMIP;
 87.9023 +		cubeProbe->cubemap->filterType = FT_LINEAR;
 87.9024 +		cubeProbe->cubemap->wrapType = WT_EDGE_CLAMP;
 87.9025 +
 87.9026 +		GL_Bind(cubeProbe->cubemap);
 87.9027 +
 87.9028 +		R_UploadImage((const byte **)tr.cubeTemp, 6, cubeProbe->cubemap);
 87.9029 +
 87.9030 +		qglBindTexture(cubeProbe->cubemap->type, 0);
 87.9031 +	}
 87.9032 +	ri.Printf(PRINT_ALL, "\n");
 87.9033 +
 87.9034 +	// turn pixel targets off
 87.9035 +	tr.refdef.pixelTarget = NULL;
 87.9036 +
 87.9037 +
 87.9038 +	// assign the surfs a cubemap
 87.9039 +#if 0
 87.9040 +	for(i = 0; i < tr.world->numnodes; i++)
 87.9041 +	{
 87.9042 +		msurface_t    **mark;
 87.9043 +		msurface_t     *surf;
 87.9044 +
 87.9045 +		if(tr.world->nodes[i].contents != CONTENTS_SOLID)
 87.9046 +		{
 87.9047 +			mark = tr.world->nodes[i].firstmarksurface;
 87.9048 +			j = tr.world->nodes[i].nummarksurfaces;
 87.9049 +			while(j--)
 87.9050 +			{
 87.9051 +				int             dist = 9999999;
 87.9052 +				int             best = 0;
 87.9053 +
 87.9054 +				surf = *mark;
 87.9055 +				mark++;
 87.9056 +				sv = (void *)surf->data;
 87.9057 +				if(sv->surfaceType != SF_STATIC)
 87.9058 +					continue;	//
 87.9059 +				if(sv->numIndices == 0 || sv->numVerts == 0)
 87.9060 +					continue;
 87.9061 +				if(sv->cubemap != NULL)
 87.9062 +					continue;
 87.9063 +
 87.9064 +				for(x = 0; x < tr.cubeProbesCount; x++)
 87.9065 +				{
 87.9066 +					vec3_t          pos;
 87.9067 +
 87.9068 +					pos[0] = tr.cubeProbes[x].origin[0] - sv->origin[0];
 87.9069 +					pos[1] = tr.cubeProbes[x].origin[1] - sv->origin[1];
 87.9070 +					pos[2] = tr.cubeProbes[x].origin[2] - sv->origin[2];
 87.9071 +
 87.9072 +					distance = VectorLength(pos);
 87.9073 +					if(distance < dist)
 87.9074 +					{
 87.9075 +						dist = distance;
 87.9076 +						best = x;
 87.9077 +					}
 87.9078 +				}
 87.9079 +				sv->cubemap = tr.cubeProbes[best].cubemap;
 87.9080 +			}
 87.9081 +		}
 87.9082 +	}
 87.9083 +#endif
 87.9084 +
 87.9085 +	endTime = ri.Milliseconds();
 87.9086 +	ri.Printf(PRINT_ALL, "cubemap probes pre-rendering time of %i cubes = %5.2f seconds\n", tr.cubeProbes.currentElements,
 87.9087 +			  (endTime - startTime) / 1000.0);
 87.9088 +
 87.9089 +#endif
 87.9090 +}
 87.9091 +
 87.9092  /*
 87.9093  =================
 87.9094  RE_LoadWorldMap
 87.9095 @@ -1793,18 +8175,19 @@
 87.9096  Called directly from cgame
 87.9097  =================
 87.9098  */
 87.9099 -void RE_LoadWorldMap( const char *name ) {
 87.9100 -	int			i;
 87.9101 -	dheader_t	*header;
 87.9102 -	union {
 87.9103 -		byte *b;
 87.9104 -		void *v;
 87.9105 -	} buffer;
 87.9106 -	byte		*startMarker;
 87.9107 -
 87.9108 -	if ( tr.worldMapLoaded ) {
 87.9109 -		ri.Error( ERR_DROP, "ERROR: attempted to redundantly load world map\n" );
 87.9110 -	}
 87.9111 +void RE_LoadWorldMap(const char *name)
 87.9112 +{
 87.9113 +	int             i;
 87.9114 +	dheader_t      *header;
 87.9115 +	byte           *buffer;
 87.9116 +	byte           *startMarker;
 87.9117 +
 87.9118 +	if(tr.worldMapLoaded)
 87.9119 +	{
 87.9120 +		ri.Error(ERR_DROP, "ERROR: attempted to redundantly load world map\n");
 87.9121 +	}
 87.9122 +
 87.9123 +	ri.Printf(PRINT_ALL, "----- RE_LoadWorldMap( %s ) -----\n", name);
 87.9124  
 87.9125  	// set default sun direction to be used if it isn't
 87.9126  	// overridden by a shader
 87.9127 @@ -1812,61 +8195,86 @@
 87.9128  	tr.sunDirection[1] = 0.3f;
 87.9129  	tr.sunDirection[2] = 0.9f;
 87.9130  
 87.9131 -	VectorNormalize( tr.sunDirection );
 87.9132 +	VectorNormalize(tr.sunDirection);
 87.9133 +
 87.9134 +	VectorCopy(colorMdGrey, tr.fogColor);
 87.9135 +	tr.fogDensity = 0;
 87.9136 +
 87.9137 +	// set default ambient color
 87.9138 +	tr.worldEntity.ambientLight[0] = r_forceAmbient->value;
 87.9139 +	tr.worldEntity.ambientLight[1] = r_forceAmbient->value;
 87.9140 +	tr.worldEntity.ambientLight[2] = r_forceAmbient->value;
 87.9141  
 87.9142  	tr.worldMapLoaded = qtrue;
 87.9143  
 87.9144  	// load it
 87.9145 -    ri.FS_ReadFile( name, &buffer.v );
 87.9146 -	if ( !buffer.b ) {
 87.9147 -		ri.Error (ERR_DROP, "RE_LoadWorldMap: %s not found", name);
 87.9148 +	ri.FS_ReadFile(name, (void **)&buffer);
 87.9149 +	if(!buffer)
 87.9150 +	{
 87.9151 +		ri.Error(ERR_DROP, "RE_LoadWorldMap: %s not found", name);
 87.9152  	}
 87.9153  
 87.9154  	// clear tr.world so if the level fails to load, the next
 87.9155  	// try will not look at the partially loaded version
 87.9156  	tr.world = NULL;
 87.9157  
 87.9158 -	Com_Memset( &s_worldData, 0, sizeof( s_worldData ) );
 87.9159 -	Q_strncpyz( s_worldData.name, name, sizeof( s_worldData.name ) );
 87.9160 -
 87.9161 -	Q_strncpyz( s_worldData.baseName, COM_SkipPath( s_worldData.name ), sizeof( s_worldData.name ) );
 87.9162 -	COM_StripExtension(s_worldData.baseName, s_worldData.baseName, sizeof(s_worldData.baseName));
 87.9163 +	Com_Memset(&s_worldData, 0, sizeof(s_worldData));
 87.9164 +	Q_strncpyz(s_worldData.name, name, sizeof(s_worldData.name));
 87.9165 +
 87.9166 +	Q_strncpyz(s_worldData.baseName, Com_SkipPath(s_worldData.name), sizeof(s_worldData.name));
 87.9167 +	Com_StripExtension(s_worldData.baseName, s_worldData.baseName, sizeof(s_worldData.baseName));
 87.9168  
 87.9169  	startMarker = ri.Hunk_Alloc(0, h_low);
 87.9170 -	c_gridVerts = 0;
 87.9171 -
 87.9172 -	header = (dheader_t *)buffer.b;
 87.9173 -	fileBase = (byte *)header;
 87.9174 -
 87.9175 -	i = LittleLong (header->version);
 87.9176 -	if ( i != BSP_VERSION ) {
 87.9177 -		ri.Error (ERR_DROP, "RE_LoadWorldMap: %s has wrong version number (%i should be %i)", 
 87.9178 -			name, i, BSP_VERSION);
 87.9179 +
 87.9180 +	header = (dheader_t *) buffer;
 87.9181 +	fileBase = (byte *) header;
 87.9182 +
 87.9183 +	i = LittleLong(header->version);
 87.9184 +	if(i != BSP_VERSION)
 87.9185 +	{
 87.9186 +		ri.Error(ERR_DROP, "RE_LoadWorldMap: %s has wrong version number (%i should be %i)", name, i, BSP_VERSION);
 87.9187  	}
 87.9188  
 87.9189  	// swap all the lumps
 87.9190 -	for (i=0 ; i<sizeof(dheader_t)/4 ; i++) {
 87.9191 -		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
 87.9192 +	for(i = 0; i < sizeof(dheader_t) / 4; i++)
 87.9193 +	{
 87.9194 +		((int *)header)[i] = LittleLong(((int *)header)[i]);
 87.9195  	}
 87.9196  
 87.9197  	// load into heap
 87.9198 -	R_LoadShaders( &header->lumps[LUMP_SHADERS] );
 87.9199 -	R_LoadLightmaps( &header->lumps[LUMP_LIGHTMAPS] );
 87.9200 -	R_LoadPlanes (&header->lumps[LUMP_PLANES]);
 87.9201 -	R_LoadFogs( &header->lumps[LUMP_FOGS], &header->lumps[LUMP_BRUSHES], &header->lumps[LUMP_BRUSHSIDES] );
 87.9202 -	R_LoadSurfaces( &header->lumps[LUMP_SURFACES], &header->lumps[LUMP_DRAWVERTS], &header->lumps[LUMP_DRAWINDEXES] );
 87.9203 -	R_LoadMarksurfaces (&header->lumps[LUMP_LEAFSURFACES]);
 87.9204 -	R_LoadNodesAndLeafs (&header->lumps[LUMP_NODES], &header->lumps[LUMP_LEAFS]);
 87.9205 -	R_LoadSubmodels (&header->lumps[LUMP_MODELS]);
 87.9206 -	R_LoadVisibility( &header->lumps[LUMP_VISIBILITY] );
 87.9207 -	R_LoadEntities( &header->lumps[LUMP_ENTITIES] );
 87.9208 -	R_LoadLightGrid( &header->lumps[LUMP_LIGHTGRID] );
 87.9209 -
 87.9210 -	s_worldData.dataSize = (byte *)ri.Hunk_Alloc(0, h_low) - startMarker;
 87.9211 +	R_LoadEntities(&header->lumps[LUMP_ENTITIES]);
 87.9212 +	R_LoadShaders(&header->lumps[LUMP_SHADERS]);
 87.9213 +	R_LoadLightmaps(&header->lumps[LUMP_LIGHTMAPS], name);
 87.9214 +	R_LoadPlanes(&header->lumps[LUMP_PLANES]);
 87.9215 +	R_LoadSurfaces(&header->lumps[LUMP_SURFACES], &header->lumps[LUMP_DRAWVERTS], &header->lumps[LUMP_DRAWINDEXES]);
 87.9216 +	R_LoadMarksurfaces(&header->lumps[LUMP_LEAFSURFACES]);
 87.9217 +	R_LoadNodesAndLeafs(&header->lumps[LUMP_NODES], &header->lumps[LUMP_LEAFS]);
 87.9218 +	R_LoadSubmodels(&header->lumps[LUMP_MODELS]);
 87.9219 +	R_LoadVisibility(&header->lumps[LUMP_VISIBILITY]);
 87.9220 +	R_LoadLightGrid(&header->lumps[LUMP_LIGHTGRID]);
 87.9221 +
 87.9222 +	// create static VBOS from the world
 87.9223 +	R_CreateWorldVBO();
 87.9224 +	R_CreateClusters();
 87.9225 +	R_CreateSubModelVBOs();
 87.9226 +
 87.9227 +	// we precache interactions between lights and surfaces
 87.9228 +	// to reduce the polygon count
 87.9229 +	R_PrecacheInteractions();
 87.9230 +
 87.9231 +	s_worldData.dataSize = (byte *) ri.Hunk_Alloc(0, h_low) - startMarker;
 87.9232 +
 87.9233 +	//ri.Printf(PRINT_ALL, "total world data size: %d.%02d MB\n", s_worldData.dataSize / (1024 * 1024),
 87.9234 +	//        (s_worldData.dataSize % (1024 * 1024)) * 100 / (1024 * 1024));
 87.9235  
 87.9236  	// only set tr.world now that we know the entire level has loaded properly
 87.9237  	tr.world = &s_worldData;
 87.9238  
 87.9239 -    ri.FS_FreeFile( buffer.v );
 87.9240 +	//R_BuildCubeMaps();
 87.9241 +
 87.9242 +	// make sure the VBO glState entries are save
 87.9243 +	R_BindNullVBO();
 87.9244 +	R_BindNullIBO();
 87.9245 +
 87.9246 +	ri.FS_FreeFile(buffer);
 87.9247  }
 87.9248 -
    88.1 --- a/src/renderer/tr_cmds.c	Sat Jun 06 03:54:16 2009 +0800
    88.2 +++ b/src/renderer/tr_cmds.c	Wed Jun 10 09:31:46 2009 +0800
    88.3 @@ -1,78 +1,130 @@
    88.4  /*
    88.5  ===========================================================================
    88.6  Copyright (C) 1999-2005 Id Software, Inc.
    88.7 -Copyright (C) 2000-2006 Tim Angus
    88.8 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    88.9  
   88.10 -This file is part of Tremfusion.
   88.11 +This file is part of XreaL source code.
   88.12  
   88.13 -Tremfusion is free software; you can redistribute it
   88.14 +XreaL source code is free software; you can redistribute it
   88.15  and/or modify it under the terms of the GNU General Public License as
   88.16  published by the Free Software Foundation; either version 2 of the License,
   88.17  or (at your option) any later version.
   88.18  
   88.19 -Tremfusion is distributed in the hope that it will be
   88.20 +XreaL source code is distributed in the hope that it will be
   88.21  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   88.22  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   88.23  GNU General Public License for more details.
   88.24  
   88.25  You should have received a copy of the GNU General Public License
   88.26 -along with Tremfusion; if not, write to the Free Software
   88.27 +along with XreaL source code; if not, write to the Free Software
   88.28  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   88.29  ===========================================================================
   88.30  */
   88.31 +// tr_cmds.c
   88.32  #include "tr_local.h"
   88.33  
   88.34 -volatile renderCommandList_t	*renderCommandList;
   88.35 +volatile renderCommandList_t *renderCommandList;
   88.36  
   88.37 -volatile qboolean	renderThreadActive;
   88.38 -
   88.39 +volatile qboolean renderThreadActive;
   88.40  
   88.41  /*
   88.42  =====================
   88.43  R_PerformanceCounters
   88.44  =====================
   88.45  */
   88.46 -void R_PerformanceCounters( void ) {
   88.47 -	if ( !r_speeds->integer ) {
   88.48 +void R_PerformanceCounters(void)
   88.49 +{
   88.50 +	if(!r_speeds->integer)
   88.51 +	{
   88.52  		// clear the counters even if we aren't printing
   88.53 -		Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );
   88.54 -		Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
   88.55 +		Com_Memset(&tr.pc, 0, sizeof(tr.pc));
   88.56 +		Com_Memset(&backEnd.pc, 0, sizeof(backEnd.pc));
   88.57  		return;
   88.58  	}
   88.59  
   88.60 -	if (r_speeds->integer == 1) {
   88.61 -		ri.Printf (PRINT_ALL, "%i/%i shaders/surfs %i leafs %i verts %i/%i tris %.2f mtex %.2f dc\n",
   88.62 -			backEnd.pc.c_shaders, backEnd.pc.c_surfaces, tr.pc.c_leafs, backEnd.pc.c_vertexes, 
   88.63 -			backEnd.pc.c_indexes/3, backEnd.pc.c_totalIndexes/3, 
   88.64 -			R_SumOfUsedImages()/(1000000.0f), backEnd.pc.c_overDraw / (float)(glConfig.vidWidth * glConfig.vidHeight) ); 
   88.65 -	} else if (r_speeds->integer == 2) {
   88.66 -		ri.Printf (PRINT_ALL, "(patch) %i sin %i sclip  %i sout %i bin %i bclip %i bout\n",
   88.67 -			tr.pc.c_sphere_cull_patch_in, tr.pc.c_sphere_cull_patch_clip, tr.pc.c_sphere_cull_patch_out, 
   88.68 -			tr.pc.c_box_cull_patch_in, tr.pc.c_box_cull_patch_clip, tr.pc.c_box_cull_patch_out );
   88.69 -		ri.Printf (PRINT_ALL, "(md3) %i sin %i sclip  %i sout %i bin %i bclip %i bout\n",
   88.70 -			tr.pc.c_sphere_cull_md3_in, tr.pc.c_sphere_cull_md3_clip, tr.pc.c_sphere_cull_md3_out, 
   88.71 -			tr.pc.c_box_cull_md3_in, tr.pc.c_box_cull_md3_clip, tr.pc.c_box_cull_md3_out );
   88.72 -	} else if (r_speeds->integer == 3) {
   88.73 -		ri.Printf (PRINT_ALL, "viewcluster: %i\n", tr.viewCluster );
   88.74 -	} else if (r_speeds->integer == 4) {
   88.75 -		if ( backEnd.pc.c_dlightVertexes ) {
   88.76 -			ri.Printf (PRINT_ALL, "dlight srf:%i  culled:%i  verts:%i  tris:%i\n", 
   88.77 -				tr.pc.c_dlightSurfaces, tr.pc.c_dlightSurfacesCulled,
   88.78 -				backEnd.pc.c_dlightVertexes, backEnd.pc.c_dlightIndexes / 3 );
   88.79 -		}
   88.80 -	} 
   88.81 -	else if (r_speeds->integer == 5 )
   88.82 +	if(r_speeds->integer == 1)
   88.83  	{
   88.84 -		ri.Printf( PRINT_ALL, "zFar: %.0f\n", tr.viewParms.zFar );
   88.85 +		ri.Printf(PRINT_ALL, "%i views %i portals %i batches %i surfs %i leafs %i verts %i tris\n",
   88.86 +				  backEnd.pc.c_views, backEnd.pc.c_portals, backEnd.pc.c_batches, backEnd.pc.c_surfaces, tr.pc.c_leafs,
   88.87 +				  backEnd.pc.c_vertexes, backEnd.pc.c_indexes / 3);
   88.88 +
   88.89 +		ri.Printf(PRINT_ALL, "%i lights %i bout %i pvsout %i queryout %i interactions\n",
   88.90 +				  tr.pc.c_dlights + tr.pc.c_slights - backEnd.pc.c_occlusionQueriesLightsCulled,
   88.91 +				  tr.pc.c_box_cull_light_out,
   88.92 +				  tr.pc.c_pvs_cull_light_out,
   88.93 +				  backEnd.pc.c_occlusionQueriesLightsCulled,
   88.94 +				  tr.pc.c_dlightInteractions + tr.pc.c_slightInteractions - backEnd.pc.c_occlusionQueriesInteractionsCulled);
   88.95 +
   88.96 +		/*
   88.97 +		   ri.Printf(PRINT_ALL, "%i draws %.2f mtex %.2f dc\n",
   88.98 +		   backEnd.pc.c_drawElements,
   88.99 +		   R_SumOfUsedImages() / (1000000.0f),
  88.100 +		   backEnd.pc.c_overDraw / (float)(glConfig.vidWidth * glConfig.vidHeight));
  88.101 +		 */
  88.102 +
  88.103 +		ri.Printf(PRINT_ALL, "%i draws %i vbos %i ibos %i verts %i tris\n",
  88.104 +				  backEnd.pc.c_drawElements,
  88.105 +				  backEnd.pc.c_vboVertexBuffers, backEnd.pc.c_vboIndexBuffers,
  88.106 +				  backEnd.pc.c_vboVertexes, backEnd.pc.c_vboIndexes / 3);
  88.107  	}
  88.108 -	else if (r_speeds->integer == 6 )
  88.109 +	else if(r_speeds->integer == 2)
  88.110  	{
  88.111 -		ri.Printf( PRINT_ALL, "flare adds:%i tests:%i renders:%i\n", 
  88.112 -			backEnd.pc.c_flareAdds, backEnd.pc.c_flareTests, backEnd.pc.c_flareRenders );
  88.113 +		ri.Printf(PRINT_ALL, "(patch) %i sin %i sclip %i sout %i bin %i bclip %i bout\n",
  88.114 +				  tr.pc.c_sphere_cull_patch_in, tr.pc.c_sphere_cull_patch_clip,
  88.115 +				  tr.pc.c_sphere_cull_patch_out, tr.pc.c_box_cull_patch_in,
  88.116 +				  tr.pc.c_box_cull_patch_clip, tr.pc.c_box_cull_patch_out);
  88.117 +
  88.118 +		ri.Printf(PRINT_ALL, "(mdx) %i sin %i sclip %i sout %i bin %i bclip %i bout\n",
  88.119 +				  tr.pc.c_sphere_cull_mdx_in, tr.pc.c_sphere_cull_mdx_clip,
  88.120 +				  tr.pc.c_sphere_cull_mdx_out, tr.pc.c_box_cull_mdx_in, tr.pc.c_box_cull_mdx_clip, tr.pc.c_box_cull_mdx_out);
  88.121 +
  88.122 +		ri.Printf(PRINT_ALL, "(md5) %i bin %i bclip %i bout\n",
  88.123 +				  tr.pc.c_box_cull_md5_in, tr.pc.c_box_cull_md5_clip, tr.pc.c_box_cull_md5_out);
  88.124 +	}
  88.125 +	else if(r_speeds->integer == 3)
  88.126 +	{
  88.127 +		ri.Printf(PRINT_ALL, "viewcluster: %i\n", tr.visClusters[tr.visIndex]);
  88.128 +	}
  88.129 +	else if(r_speeds->integer == 4)
  88.130 +	{
  88.131 +		ri.Printf(PRINT_ALL, "dlight srf:%i culled:%i\n", tr.pc.c_dlightSurfaces, tr.pc.c_dlightSurfacesCulled);
  88.132 +
  88.133 +		ri.Printf(PRINT_ALL, "dlights:%i interactions:%i\n", tr.pc.c_dlights, tr.pc.c_dlightInteractions);
  88.134 +
  88.135 +		ri.Printf(PRINT_ALL, "slights:%i interactions:%i\n", tr.pc.c_slights, tr.pc.c_slightInteractions);
  88.136 +	}
  88.137 +	else if(r_speeds->integer == 5)
  88.138 +	{
  88.139 +		ri.Printf(PRINT_ALL, "omni pyramid tests:%i bin:%i bclip:%i bout:%i\n",
  88.140 +				  tr.pc.c_pyramidTests, tr.pc.c_pyramid_cull_ent_in, tr.pc.c_pyramid_cull_ent_clip, tr.pc.c_pyramid_cull_ent_out);
  88.141 +	}
  88.142 +	else if(r_speeds->integer == 6)
  88.143 +	{
  88.144 +		ri.Printf(PRINT_ALL, "flare adds:%i tests:%i renders:%i\n",
  88.145 +				  backEnd.pc.c_flareAdds, backEnd.pc.c_flareTests, backEnd.pc.c_flareRenders);
  88.146 +	}
  88.147 +	else if(r_speeds->integer == 7)
  88.148 +	{
  88.149 +		ri.Printf(PRINT_ALL, "occlusion queries:%i avail:%i culled lights:%i time:%i\n",
  88.150 +				  backEnd.pc.c_occlusionQueries, backEnd.pc.c_occlusionQueriesAvailable,
  88.151 +				  backEnd.pc.c_occlusionQueriesLightsCulled, backEnd.pc.c_occlusionQueriesResponseTime);
  88.152 +	}
  88.153 +	else if(r_speeds->integer == 8)
  88.154 +	{
  88.155 +		ri.Printf(PRINT_ALL, "depth bounds tests:%i rejected:%i\n", tr.pc.c_depthBoundsTests, tr.pc.c_depthBoundsTestsRejected);
  88.156 +	}
  88.157 +	else if(r_speeds->integer == 9)
  88.158 +	{
  88.159 +		if(r_deferredShading->integer)
  88.160 +			ri.Printf(PRINT_ALL, "deferred shading times: g-buffer:%i lighting:%i\n", backEnd.pc.c_deferredGBufferTime,
  88.161 +					  backEnd.pc.c_deferredLightingTime);
  88.162 +		else
  88.163 +			ri.Printf(PRINT_ALL, "forward shading times: ambient:%i lighting:%i\n", backEnd.pc.c_forwardAmbientTime,
  88.164 +					  backEnd.pc.c_forwardLightingTime);
  88.165  	}
  88.166  
  88.167 -	Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );
  88.168 -	Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
  88.169 +	Com_Memset(&tr.pc, 0, sizeof(tr.pc));
  88.170 +	Com_Memset(&backEnd.pc, 0, sizeof(backEnd.pc));
  88.171  }
  88.172  
  88.173  
  88.174 @@ -81,15 +133,20 @@
  88.175  R_InitCommandBuffers
  88.176  ====================
  88.177  */
  88.178 -void R_InitCommandBuffers( void ) {
  88.179 +void R_InitCommandBuffers(void)
  88.180 +{
  88.181  	glConfig.smpActive = qfalse;
  88.182 -	if ( r_smp->integer ) {
  88.183 -		ri.Printf( PRINT_ALL, "Trying SMP acceleration...\n" );
  88.184 -		if ( GLimp_SpawnRenderThread( RB_RenderThread ) ) {
  88.185 -			ri.Printf( PRINT_ALL, "...succeeded.\n" );
  88.186 +	if(r_smp->integer)
  88.187 +	{
  88.188 +		ri.Printf(PRINT_ALL, "Trying SMP acceleration...\n");
  88.189 +		if(GLimp_SpawnRenderThread(RB_RenderThread))
  88.190 +		{
  88.191 +			ri.Printf(PRINT_ALL, "...succeeded.\n");
  88.192  			glConfig.smpActive = qtrue;
  88.193 -		} else {
  88.194 -			ri.Printf( PRINT_ALL, "...failed.\n" );
  88.195 +		}
  88.196 +		else
  88.197 +		{
  88.198 +			ri.Printf(PRINT_ALL, "...failed.\n");
  88.199  		}
  88.200  	}
  88.201  }
  88.202 @@ -99,10 +156,12 @@
  88.203  R_ShutdownCommandBuffers
  88.204  ====================
  88.205  */
  88.206 -void R_ShutdownCommandBuffers( void ) {
  88.207 +void R_ShutdownCommandBuffers(void)
  88.208 +{
  88.209  	// kill the rendering thread
  88.210 -	if ( glConfig.smpActive ) {
  88.211 -		GLimp_WakeRenderer( NULL );
  88.212 +	if(glConfig.smpActive)
  88.213 +	{
  88.214 +		GLimp_WakeRenderer(NULL);
  88.215  		glConfig.smpActive = qfalse;
  88.216  	}
  88.217  }
  88.218 @@ -112,31 +171,38 @@
  88.219  R_IssueRenderCommands
  88.220  ====================
  88.221  */
  88.222 -int	c_blockedOnRender;
  88.223 -int	c_blockedOnMain;
  88.224 +int             c_blockedOnRender;
  88.225 +int             c_blockedOnMain;
  88.226  
  88.227 -void R_IssueRenderCommands( qboolean runPerformanceCounters ) {
  88.228 -	renderCommandList_t	*cmdList;
  88.229 +void R_IssueRenderCommands(qboolean runPerformanceCounters)
  88.230 +{
  88.231 +	renderCommandList_t *cmdList;
  88.232  
  88.233  	cmdList = &backEndData[tr.smpFrame]->commands;
  88.234 -	assert(cmdList);
  88.235 +	assert(cmdList);			// bk001205
  88.236  	// add an end-of-list command
  88.237  	*(int *)(cmdList->cmds + cmdList->used) = RC_END_OF_LIST;
  88.238  
  88.239  	// clear it out, in case this is a sync and not a buffer flip
  88.240  	cmdList->used = 0;
  88.241  
  88.242 -	if ( glConfig.smpActive ) {
  88.243 +	if(glConfig.smpActive)
  88.244 +	{
  88.245  		// if the render thread is not idle, wait for it
  88.246 -		if ( renderThreadActive ) {
  88.247 +		if(renderThreadActive)
  88.248 +		{
  88.249  			c_blockedOnRender++;
  88.250 -			if ( r_showSmp->integer ) {
  88.251 -				ri.Printf( PRINT_ALL, "R" );
  88.252 +			if(r_showSmp->integer)
  88.253 +			{
  88.254 +				ri.Printf(PRINT_ALL, "R");
  88.255  			}
  88.256 -		} else {
  88.257 +		}
  88.258 +		else
  88.259 +		{
  88.260  			c_blockedOnMain++;
  88.261 -			if ( r_showSmp->integer ) {
  88.262 -				ri.Printf( PRINT_ALL, "." );
  88.263 +			if(r_showSmp->integer)
  88.264 +			{
  88.265 +				ri.Printf(PRINT_ALL, ".");
  88.266  			}
  88.267  		}
  88.268  
  88.269 @@ -146,17 +212,22 @@
  88.270  
  88.271  	// at this point, the back end thread is idle, so it is ok
  88.272  	// to look at it's performance counters
  88.273 -	if ( runPerformanceCounters ) {
  88.274 +	if(runPerformanceCounters)
  88.275 +	{
  88.276  		R_PerformanceCounters();
  88.277  	}
  88.278  
  88.279  	// actually start the commands going
  88.280 -	if ( !r_skipBackEnd->integer ) {
  88.281 +	if(!r_skipBackEnd->integer)
  88.282 +	{
  88.283  		// let it start on the new batch
  88.284 -		if ( !glConfig.smpActive ) {
  88.285 -			RB_ExecuteRenderCommands( cmdList->cmds );
  88.286 -		} else {
  88.287 -			GLimp_WakeRenderer( cmdList );
  88.288 +		if(!glConfig.smpActive)
  88.289 +		{
  88.290 +			RB_ExecuteRenderCommands(cmdList->cmds);
  88.291 +		}
  88.292 +		else
  88.293 +		{
  88.294 +			GLimp_WakeRenderer(cmdList);
  88.295  		}
  88.296  	}
  88.297  }
  88.298 @@ -172,13 +243,16 @@
  88.299  OpenGL calls until R_IssueRenderCommands is called.
  88.300  ====================
  88.301  */
  88.302 -void R_SyncRenderThread( void ) {
  88.303 -	if ( !tr.registered ) {
  88.304 +void R_SyncRenderThread(void)
  88.305 +{
  88.306 +	if(!tr.registered)
  88.307 +	{
  88.308  		return;
  88.309  	}
  88.310 -	R_IssueRenderCommands( qfalse );
  88.311 +	R_IssueRenderCommands(qfalse);
  88.312  
  88.313 -	if ( !glConfig.smpActive ) {
  88.314 +	if(!glConfig.smpActive)
  88.315 +	{
  88.316  		return;
  88.317  	}
  88.318  	GLimp_FrontEndSleep();
  88.319 @@ -192,15 +266,18 @@
  88.320  render thread if needed.
  88.321  ============
  88.322  */
  88.323 -void *R_GetCommandBuffer( int bytes ) {
  88.324 -	renderCommandList_t	*cmdList;
  88.325 +void           *R_GetCommandBuffer(int bytes)
  88.326 +{
  88.327 +	renderCommandList_t *cmdList;
  88.328  
  88.329  	cmdList = &backEndData[tr.smpFrame]->commands;
  88.330  
  88.331  	// always leave room for the end of list command
  88.332 -	if ( cmdList->used + bytes + 4 > MAX_RENDER_COMMANDS ) {
  88.333 -		if ( bytes > MAX_RENDER_COMMANDS - 4 ) {
  88.334 -			ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes );
  88.335 +	if(cmdList->used + bytes + 4 > MAX_RENDER_COMMANDS)
  88.336 +	{
  88.337 +		if(bytes > MAX_RENDER_COMMANDS - 4)
  88.338 +		{
  88.339 +			ri.Error(ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes);
  88.340  		}
  88.341  		// if we run out of room, just start dropping commands
  88.342  		return NULL;
  88.343 @@ -214,21 +291,19 @@
  88.344  
  88.345  /*
  88.346  =============
  88.347 -R_AddDrawSurfCmd
  88.348 -
  88.349 +R_AddDrawViewCmd
  88.350  =============
  88.351  */
  88.352 -void	R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs ) {
  88.353 -	drawSurfsCommand_t	*cmd;
  88.354 +void R_AddDrawViewCmd()
  88.355 +{
  88.356 +	drawViewCommand_t *cmd;
  88.357  
  88.358 -	cmd = R_GetCommandBuffer( sizeof( *cmd ) );
  88.359 -	if ( !cmd ) {
  88.360 +	cmd = R_GetCommandBuffer(sizeof(*cmd));
  88.361 +	if(!cmd)
  88.362 +	{
  88.363  		return;
  88.364  	}
  88.365 -	cmd->commandId = RC_DRAW_SURFS;
  88.366 -
  88.367 -	cmd->drawSurfs = drawSurfs;
  88.368 -	cmd->numDrawSurfs = numDrawSurfs;
  88.369 +	cmd->commandId = RC_DRAW_VIEW;
  88.370  
  88.371  	cmd->refdef = tr.refdef;
  88.372  	cmd->viewParms = tr.viewParms;
  88.373 @@ -242,19 +317,23 @@
  88.374  Passing NULL will set the color to white
  88.375  =============
  88.376  */
  88.377 -void	RE_SetColor( const float *rgba ) {
  88.378 -	setColorCommand_t	*cmd;
  88.379 +void RE_SetColor(const float *rgba)
  88.380 +{
  88.381 +	setColorCommand_t *cmd;
  88.382  
  88.383 -  if ( !tr.registered ) {
  88.384 -    return;
  88.385 -  }
  88.386 -	cmd = R_GetCommandBuffer( sizeof( *cmd ) );
  88.387 -	if ( !cmd ) {
  88.388 +	if(!tr.registered)
  88.389 +	{
  88.390 +		return;
  88.391 +	}
  88.392 +	cmd = R_GetCommandBuffer(sizeof(*cmd));
  88.393 +	if(!cmd)
  88.394 +	{
  88.395  		return;
  88.396  	}
  88.397  	cmd->commandId = RC_SET_COLOR;
  88.398 -	if ( !rgba ) {
  88.399 -		static float colorWhite[4] = { 1, 1, 1, 1 };
  88.400 +	if(!rgba)
  88.401 +	{
  88.402 +		static float    colorWhite[4] = { 1, 1, 1, 1 };
  88.403  
  88.404  		rgba = colorWhite;
  88.405  	}
  88.406 @@ -271,19 +350,21 @@
  88.407  RE_StretchPic
  88.408  =============
  88.409  */
  88.410 -void RE_StretchPic ( float x, float y, float w, float h, 
  88.411 -					  float s1, float t1, float s2, float t2, qhandle_t hShader ) {
  88.412 -	stretchPicCommand_t	*cmd;
  88.413 +void RE_StretchPic(float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t hShader)
  88.414 +{
  88.415 +	stretchPicCommand_t *cmd;
  88.416  
  88.417 -  if (!tr.registered) {
  88.418 -    return;
  88.419 -  }
  88.420 -	cmd = R_GetCommandBuffer( sizeof( *cmd ) );
  88.421 -	if ( !cmd ) {
  88.422 +	if(!tr.registered)
  88.423 +	{
  88.424 +		return;
  88.425 +	}
  88.426 +	cmd = R_GetCommandBuffer(sizeof(*cmd));
  88.427 +	if(!cmd)
  88.428 +	{
  88.429  		return;
  88.430  	}
  88.431  	cmd->commandId = RC_STRETCH_PIC;
  88.432 -	cmd->shader = R_GetShaderByHandle( hShader );
  88.433 +	cmd->shader = R_GetShaderByHandle(hShader);
  88.434  	cmd->x = x;
  88.435  	cmd->y = y;
  88.436  	cmd->w = w;
  88.437 @@ -294,38 +375,6 @@
  88.438  	cmd->t2 = t2;
  88.439  }
  88.440  
  88.441 -#define MODE_RED_CYAN	1
  88.442 -#define MODE_RED_BLUE	2
  88.443 -#define MODE_RED_GREEN	3
  88.444 -#define MODE_MAX	MODE_RED_GREEN
  88.445 -
  88.446 -void R_SetColorMode(GLboolean *rgba, stereoFrame_t stereoFrame, int colormode)
  88.447 -{
  88.448 -	rgba[0] = rgba[1] = rgba[2] = rgba[3] = GL_TRUE;
  88.449 -	
  88.450 -	if(colormode > MODE_MAX)
  88.451 -	{
  88.452 -		if(stereoFrame == STEREO_LEFT)
  88.453 -			stereoFrame = STEREO_RIGHT;
  88.454 -		else if(stereoFrame == STEREO_RIGHT)
  88.455 -			stereoFrame = STEREO_LEFT;
  88.456 -		
  88.457 -		colormode -= MODE_MAX;
  88.458 -	}
  88.459 -	
  88.460 -	if(stereoFrame == STEREO_LEFT)
  88.461 -		rgba[1] = rgba[2] = GL_FALSE;
  88.462 -	else if(stereoFrame == STEREO_RIGHT)
  88.463 -	{
  88.464 -		rgba[0] = GL_FALSE;
  88.465 -		
  88.466 -		if(colormode == MODE_RED_BLUE)
  88.467 -			rgba[1] = GL_FALSE;
  88.468 -		else if(colormode == MODE_RED_GREEN)
  88.469 -			rgba[2] = GL_FALSE;
  88.470 -	}
  88.471 -}
  88.472 -
  88.473  
  88.474  /*
  88.475  ====================
  88.476 @@ -335,69 +384,70 @@
  88.477  for each RE_EndFrame
  88.478  ====================
  88.479  */
  88.480 -void RE_BeginFrame( stereoFrame_t stereoFrame ) {
  88.481 -	drawBufferCommand_t	*cmd = NULL;
  88.482 -	colorMaskCommand_t *colcmd = NULL;
  88.483 +void RE_BeginFrame(stereoFrame_t stereoFrame)
  88.484 +{
  88.485 +	drawBufferCommand_t *cmd;
  88.486  
  88.487 -	if ( !tr.registered ) {
  88.488 +	if(!tr.registered)
  88.489 +	{
  88.490  		return;
  88.491  	}
  88.492 +
  88.493 +	GLimp_LogComment("--- RE_BeginFrame ---\n");
  88.494 +
  88.495  	glState.finishCalled = qfalse;
  88.496  
  88.497  	tr.frameCount++;
  88.498  	tr.frameSceneNum = 0;
  88.499  
  88.500 -	//
  88.501  	// do overdraw measurement
  88.502 -	//
  88.503 -	if ( r_measureOverdraw->integer )
  88.504 +	if(r_measureOverdraw->integer)
  88.505  	{
  88.506 -		if ( glConfig.stencilBits < 4 )
  88.507 +		if(glConfig.stencilBits < 4)
  88.508  		{
  88.509 -			ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits );
  88.510 -			ri.Cvar_Set( "r_measureOverdraw", "0" );
  88.511 +			ri.Printf(PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits);
  88.512 +			ri.Cvar_Set("r_measureOverdraw", "0");
  88.513  			r_measureOverdraw->modified = qfalse;
  88.514  		}
  88.515 -		else if ( r_shadows->integer == 2 )
  88.516 +		else if(r_shadows->integer == 3)
  88.517  		{
  88.518 -			ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" );
  88.519 -			ri.Cvar_Set( "r_measureOverdraw", "0" );
  88.520 +			ri.Printf(PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n");
  88.521 +			ri.Cvar_Set("r_measureOverdraw", "0");
  88.522  			r_measureOverdraw->modified = qfalse;
  88.523  		}
  88.524  		else
  88.525  		{
  88.526  			R_SyncRenderThread();
  88.527 -			qglEnable( GL_STENCIL_TEST );
  88.528 -			qglStencilMask( ~0U );
  88.529 -			qglClearStencil( 0U );
  88.530 -			qglStencilFunc( GL_ALWAYS, 0U, ~0U );
  88.531 -			qglStencilOp( GL_KEEP, GL_INCR, GL_INCR );
  88.532 +			qglEnable(GL_STENCIL_TEST);
  88.533 +			qglStencilMask(~0U);
  88.534 +			GL_ClearStencil(0U);
  88.535 +			qglStencilFunc(GL_ALWAYS, 0U, ~0U);
  88.536 +			qglStencilOp(GL_KEEP, GL_INCR, GL_INCR);
  88.537  		}
  88.538  		r_measureOverdraw->modified = qfalse;
  88.539  	}
  88.540  	else
  88.541  	{
  88.542  		// this is only reached if it was on and is now off
  88.543 -		if ( r_measureOverdraw->modified ) {
  88.544 +		if(r_measureOverdraw->modified)
  88.545 +		{
  88.546  			R_SyncRenderThread();
  88.547 -			qglDisable( GL_STENCIL_TEST );
  88.548 +			qglDisable(GL_STENCIL_TEST);
  88.549  		}
  88.550  		r_measureOverdraw->modified = qfalse;
  88.551  	}
  88.552  
  88.553 -	//
  88.554  	// texturemode stuff
  88.555 -	//
  88.556 -	if ( r_textureMode->modified ) {
  88.557 +	if(r_textureMode->modified)
  88.558 +	{
  88.559  		R_SyncRenderThread();
  88.560 -		GL_TextureMode( r_textureMode->string );
  88.561 +		GL_TextureMode(r_textureMode->string);
  88.562  		r_textureMode->modified = qfalse;
  88.563  	}
  88.564  
  88.565 -	//
  88.566  	// gamma stuff
  88.567 -	//
  88.568 -	if ( r_gamma->modified ) {
  88.569 +	if(r_gamma->modified)
  88.570 +	{
  88.571  		r_gamma->modified = qfalse;
  88.572  
  88.573  		R_SyncRenderThread();
  88.574 @@ -405,100 +455,89 @@
  88.575  	}
  88.576  
  88.577  	// check for errors
  88.578 -	if ( !r_ignoreGLErrors->integer )
  88.579 +	if(!r_ignoreGLErrors->integer)
  88.580  	{
  88.581 -		int	err;
  88.582 +		int             err;
  88.583 +		char            s[128];
  88.584  
  88.585  		R_SyncRenderThread();
  88.586 -		if ((err = qglGetError()) != GL_NO_ERROR)
  88.587 -			ri.Error(ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!\n", err);
  88.588 +
  88.589 +		if((err = qglGetError()) != GL_NO_ERROR)
  88.590 +		{
  88.591 +			switch (err)
  88.592 +			{
  88.593 +				case GL_INVALID_ENUM:
  88.594 +					strcpy(s, "GL_INVALID_ENUM");
  88.595 +					break;
  88.596 +				case GL_INVALID_VALUE:
  88.597 +					strcpy(s, "GL_INVALID_VALUE");
  88.598 +					break;
  88.599 +				case GL_INVALID_OPERATION:
  88.600 +					strcpy(s, "GL_INVALID_OPERATION");
  88.601 +					break;
  88.602 +				case GL_STACK_OVERFLOW:
  88.603 +					strcpy(s, "GL_STACK_OVERFLOW");
  88.604 +					break;
  88.605 +				case GL_STACK_UNDERFLOW:
  88.606 +					strcpy(s, "GL_STACK_UNDERFLOW");
  88.607 +					break;
  88.608 +				case GL_OUT_OF_MEMORY:
  88.609 +					strcpy(s, "GL_OUT_OF_MEMORY");
  88.610 +					break;
  88.611 +				case GL_TABLE_TOO_LARGE:
  88.612 +					strcpy(s, "GL_TABLE_TOO_LARGE");
  88.613 +					break;
  88.614 +				case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
  88.615 +					strcpy(s, "GL_INVALID_FRAMEBUFFER_OPERATION_EXT");
  88.616 +					break;
  88.617 +				default:
  88.618 +					Com_sprintf(s, sizeof(s), "0x%X", err);
  88.619 +					break;
  88.620 +			}
  88.621 +
  88.622 +			//ri.Error(ERR_FATAL, "caught OpenGL error: %s in file %s line %i", s, filename, line);
  88.623 +			ri.Error(ERR_FATAL, "RE_BeginFrame() - glGetError() failed (%s)!\n", s);
  88.624 +		}
  88.625  	}
  88.626  
  88.627 -	if (glConfig.stereoEnabled) {
  88.628 -		if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) )
  88.629 -			return;
  88.630 -			
  88.631 -		cmd->commandId = RC_DRAW_BUFFER;
  88.632 -		
  88.633 -		if ( stereoFrame == STEREO_LEFT ) {
  88.634 +	// draw buffer stuff
  88.635 +	cmd = R_GetCommandBuffer(sizeof(*cmd));
  88.636 +	if(!cmd)
  88.637 +	{
  88.638 +		return;
  88.639 +	}
  88.640 +	cmd->commandId = RC_DRAW_BUFFER;
  88.641 +
  88.642 +	if(glConfig.stereoEnabled)
  88.643 +	{
  88.644 +		if(stereoFrame == STEREO_LEFT)
  88.645 +		{
  88.646  			cmd->buffer = (int)GL_BACK_LEFT;
  88.647 -		} else if ( stereoFrame == STEREO_RIGHT ) {
  88.648 +		}
  88.649 +		else if(stereoFrame == STEREO_RIGHT)
  88.650 +		{
  88.651  			cmd->buffer = (int)GL_BACK_RIGHT;
  88.652 -		} else {
  88.653 -			ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame );
  88.654 +		}
  88.655 +		else
  88.656 +		{
  88.657 +			ri.Error(ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame);
  88.658  		}
  88.659  	}
  88.660  	else
  88.661  	{
  88.662 -		if(r_anaglyphMode->integer)
  88.663 +		if(stereoFrame != STEREO_CENTER)
  88.664  		{
  88.665 -			if(r_anaglyphMode->modified)
  88.666 -			{
  88.667 -				// clear both, front and backbuffer.
  88.668 -				qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  88.669 -				qglClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  88.670 -				
  88.671 -				qglDrawBuffer(GL_FRONT);
  88.672 -				qglClear(GL_COLOR_BUFFER_BIT);
  88.673 -				qglDrawBuffer(GL_BACK);
  88.674 -				qglClear(GL_COLOR_BUFFER_BIT);
  88.675 -				
  88.676 -				r_anaglyphMode->modified = qfalse;
  88.677 -			}
  88.678 -			
  88.679 -			if(stereoFrame == STEREO_LEFT)
  88.680 -			{
  88.681 -				if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) )
  88.682 -					return;
  88.683 -				
  88.684 -				if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) )
  88.685 -					return;
  88.686 -			}
  88.687 -			else if(stereoFrame == STEREO_RIGHT)
  88.688 -			{
  88.689 -				clearDepthCommand_t *cldcmd;
  88.690 -				
  88.691 -				if( !(cldcmd = R_GetCommandBuffer(sizeof(*cldcmd))) )
  88.692 -					return;
  88.693 -
  88.694 -				cldcmd->commandId = RC_CLEARDEPTH;
  88.695 -
  88.696 -				if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) )
  88.697 -					return;
  88.698 -			}
  88.699 -			else
  88.700 -				ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame );
  88.701 -
  88.702 -			R_SetColorMode(colcmd->rgba, stereoFrame, r_anaglyphMode->integer);
  88.703 -			colcmd->commandId = RC_COLORMASK;
  88.704 +			ri.Error(ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame);
  88.705 +		}
  88.706 +		if(!Q_stricmp(r_drawBuffer->string, "GL_FRONT"))
  88.707 +		{
  88.708 +			cmd->buffer = (int)GL_FRONT;
  88.709  		}
  88.710  		else
  88.711  		{
  88.712 -			if(stereoFrame != STEREO_CENTER)
  88.713 -				ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame );
  88.714 -
  88.715 -			if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) )
  88.716 -				return;
  88.717 -		}
  88.718 -
  88.719 -		if(cmd)
  88.720 -		{
  88.721 -			cmd->commandId = RC_DRAW_BUFFER;
  88.722 -
  88.723 -			if(r_anaglyphMode->modified)
  88.724 -			{
  88.725 -				qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  88.726 -				r_anaglyphMode->modified = qfalse;
  88.727 -			}
  88.728 -
  88.729 -			if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT"))
  88.730 -				cmd->buffer = (int)GL_FRONT;
  88.731 -			else
  88.732 -				cmd->buffer = (int)GL_BACK;
  88.733 +			cmd->buffer = (int)GL_BACK;
  88.734  		}
  88.735  	}
  88.736 -	
  88.737 -	tr.refdef.stereoFrame = stereoFrame;
  88.738  }
  88.739  
  88.740  
  88.741 @@ -509,29 +548,34 @@
  88.742  Returns the number of msec spent in the back end
  88.743  =============
  88.744  */
  88.745 -void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {
  88.746 -	swapBuffersCommand_t	*cmd;
  88.747 +void RE_EndFrame(int *frontEndMsec, int *backEndMsec)
  88.748 +{
  88.749 +	swapBuffersCommand_t *cmd;
  88.750  
  88.751 -	if ( !tr.registered ) {
  88.752 +	if(!tr.registered)
  88.753 +	{
  88.754  		return;
  88.755  	}
  88.756 -	cmd = R_GetCommandBuffer( sizeof( *cmd ) );
  88.757 -	if ( !cmd ) {
  88.758 +	cmd = R_GetCommandBuffer(sizeof(*cmd));
  88.759 +	if(!cmd)
  88.760 +	{
  88.761  		return;
  88.762  	}
  88.763  	cmd->commandId = RC_SWAP_BUFFERS;
  88.764  
  88.765 -	R_IssueRenderCommands( qtrue );
  88.766 +	R_IssueRenderCommands(qtrue);
  88.767  
  88.768  	// use the other buffers next frame, because another CPU
  88.769  	// may still be rendering into the current ones
  88.770  	R_ToggleSmpFrame();
  88.771  
  88.772 -	if ( frontEndMsec ) {
  88.773 +	if(frontEndMsec)
  88.774 +	{
  88.775  		*frontEndMsec = tr.frontEndMsec;
  88.776  	}
  88.777  	tr.frontEndMsec = 0;
  88.778 -	if ( backEndMsec ) {
  88.779 +	if(backEndMsec)
  88.780 +	{
  88.781  		*backEndMsec = backEnd.pc.msec;
  88.782  	}
  88.783  	backEnd.pc.msec = 0;
  88.784 @@ -542,17 +586,18 @@
  88.785  RE_TakeVideoFrame
  88.786  =============
  88.787  */
  88.788 -void RE_TakeVideoFrame( int width, int height,
  88.789 -		byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg )
  88.790 +void RE_TakeVideoFrame(int width, int height, byte * captureBuffer, byte * encodeBuffer, qboolean motionJpeg)
  88.791  {
  88.792 -	videoFrameCommand_t	*cmd;
  88.793 +	videoFrameCommand_t *cmd;
  88.794  
  88.795 -	if( !tr.registered ) {
  88.796 +	if(!tr.registered)
  88.797 +	{
  88.798  		return;
  88.799  	}
  88.800  
  88.801 -	cmd = R_GetCommandBuffer( sizeof( *cmd ) );
  88.802 -	if( !cmd ) {
  88.803 +	cmd = R_GetCommandBuffer(sizeof(*cmd));
  88.804 +	if(!cmd)
  88.805 +	{
  88.806  		return;
  88.807  	}
  88.808  
    89.1 --- a/src/renderer/tr_curve.c	Sat Jun 06 03:54:16 2009 +0800
    89.2 +++ b/src/renderer/tr_curve.c	Wed Jun 10 09:31:46 2009 +0800
    89.3 @@ -1,30 +1,30 @@
    89.4  /*
    89.5  ===========================================================================
    89.6  Copyright (C) 1999-2005 Id Software, Inc.
    89.7 -Copyright (C) 2000-2006 Tim Angus
    89.8 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    89.9  
   89.10 -This file is part of Tremfusion.
   89.11 +This file is part of XreaL source code.
   89.12  
   89.13 -Tremfusion is free software; you can redistribute it
   89.14 +XreaL source code is free software; you can redistribute it
   89.15  and/or modify it under the terms of the GNU General Public License as
   89.16  published by the Free Software Foundation; either version 2 of the License,
   89.17  or (at your option) any later version.
   89.18  
   89.19 -Tremfusion is distributed in the hope that it will be
   89.20 +XreaL source code is distributed in the hope that it will be
   89.21  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   89.22  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   89.23  GNU General Public License for more details.
   89.24  
   89.25  You should have received a copy of the GNU General Public License
   89.26 -along with Tremfusion; if not, write to the Free Software
   89.27 +along with XreaL source code; if not, write to the Free Software
   89.28  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   89.29  ===========================================================================
   89.30  */
   89.31 -
   89.32 +// tr_curve.c
   89.33  #include "tr_local.h"
   89.34  
   89.35  /*
   89.36 -
   89.37 +======================================================================================
   89.38  This file does all of the processing necessary to turn a raw grid of points
   89.39  read from the map file into a srfGridMesh_t ready for rendering.
   89.40  
   89.41 @@ -32,19 +32,17 @@
   89.42  distance from the true curve.
   89.43  
   89.44  Only a single entry point:
   89.45 -
   89.46 -srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
   89.47 -								drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
   89.48 -
   89.49 +R_SubdividePatchToGrid(int width, int height, srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE])
   89.50 +======================================================================================
   89.51  */
   89.52  
   89.53 -
   89.54  /*
   89.55  ============
   89.56  LerpDrawVert
   89.57  ============
   89.58  */
   89.59 -static void LerpDrawVert( drawVert_t *a, drawVert_t *b, drawVert_t *out ) {
   89.60 +static void LerpSurfaceVert(srfVert_t * a, srfVert_t * b, srfVert_t * out)
   89.61 +{
   89.62  	out->xyz[0] = 0.5f * (a->xyz[0] + b->xyz[0]);
   89.63  	out->xyz[1] = 0.5f * (a->xyz[1] + b->xyz[1]);
   89.64  	out->xyz[2] = 0.5f * (a->xyz[2] + b->xyz[2]);
   89.65 @@ -55,10 +53,19 @@
   89.66  	out->lightmap[0] = 0.5f * (a->lightmap[0] + b->lightmap[0]);
   89.67  	out->lightmap[1] = 0.5f * (a->lightmap[1] + b->lightmap[1]);
   89.68  
   89.69 -	out->color[0] = (a->color[0] + b->color[0]) >> 1;
   89.70 -	out->color[1] = (a->color[1] + b->color[1]) >> 1;
   89.71 -	out->color[2] = (a->color[2] + b->color[2]) >> 1;
   89.72 -	out->color[3] = (a->color[3] + b->color[3]) >> 1;
   89.73 +	out->paintColor[0] = (a->paintColor[0] + b->paintColor[0]) * 0.5f;
   89.74 +	out->paintColor[1] = (a->paintColor[1] + b->paintColor[1]) * 0.5f;
   89.75 +	out->paintColor[2] = (a->paintColor[2] + b->paintColor[2]) * 0.5f;
   89.76 +	out->paintColor[3] = (a->paintColor[3] + b->paintColor[3]) * 0.5f;
   89.77 +
   89.78 +	out->lightColor[0] = (a->lightColor[0] + b->lightColor[0]) * 0.5f;
   89.79 +	out->lightColor[1] = (a->lightColor[1] + b->lightColor[1]) * 0.5f;
   89.80 +	out->lightColor[2] = (a->lightColor[2] + b->lightColor[2]) * 0.5f;
   89.81 +	out->lightColor[3] = (a->lightColor[3] + b->lightColor[3]) * 0.5f;
   89.82 +
   89.83 +	out->lightDirection[0] = (a->lightDirection[0] + b->lightDirection[0]) * 0.5f;
   89.84 +	out->lightDirection[1] = (a->lightDirection[1] + b->lightDirection[1]) * 0.5f;
   89.85 +	out->lightDirection[2] = (a->lightDirection[2] + b->lightDirection[2]) * 0.5f;
   89.86  }
   89.87  
   89.88  /*
   89.89 @@ -66,33 +73,47 @@
   89.90  Transpose
   89.91  ============
   89.92  */
   89.93 -static void Transpose( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
   89.94 -	int		i, j;
   89.95 -	drawVert_t	temp;
   89.96 +static void Transpose(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE])
   89.97 +{
   89.98 +	int             i, j;
   89.99 +	srfVert_t       temp;
  89.100  
  89.101 -	if ( width > height ) {
  89.102 -		for ( i = 0 ; i < height ; i++ ) {
  89.103 -			for ( j = i + 1 ; j < width ; j++ ) {
  89.104 -				if ( j < height ) {
  89.105 +	if(width > height)
  89.106 +	{
  89.107 +		for(i = 0; i < height; i++)
  89.108 +		{
  89.109 +			for(j = i + 1; j < width; j++)
  89.110 +			{
  89.111 +				if(j < height)
  89.112 +				{
  89.113  					// swap the value
  89.114  					temp = ctrl[j][i];
  89.115  					ctrl[j][i] = ctrl[i][j];
  89.116  					ctrl[i][j] = temp;
  89.117 -				} else {
  89.118 +				}
  89.119 +				else
  89.120 +				{
  89.121  					// just copy
  89.122  					ctrl[j][i] = ctrl[i][j];
  89.123  				}
  89.124  			}
  89.125  		}
  89.126 -	} else {
  89.127 -		for ( i = 0 ; i < width ; i++ ) {
  89.128 -			for ( j = i + 1 ; j < height ; j++ ) {
  89.129 -				if ( j < width ) {
  89.130 +	}
  89.131 +	else
  89.132 +	{
  89.133 +		for(i = 0; i < width; i++)
  89.134 +		{
  89.135 +			for(j = i + 1; j < height; j++)
  89.136 +			{
  89.137 +				if(j < width)
  89.138 +				{
  89.139  					// swap the value
  89.140  					temp = ctrl[i][j];
  89.141  					ctrl[i][j] = ctrl[j][i];
  89.142  					ctrl[j][i] = temp;
  89.143 -				} else {
  89.144 +				}
  89.145 +				else
  89.146 +				{
  89.147  					// just copy
  89.148  					ctrl[i][j] = ctrl[j][i];
  89.149  				}
  89.150 @@ -110,125 +131,397 @@
  89.151  Handles all the complicated wrapping and degenerate cases
  89.152  =================
  89.153  */
  89.154 -static void MakeMeshNormals( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
  89.155 -	int		i, j, k, dist;
  89.156 -	vec3_t	normal;
  89.157 -	vec3_t	sum;
  89.158 -	int		count = 0;
  89.159 -	vec3_t	base;
  89.160 -	vec3_t	delta;
  89.161 -	int		x, y;
  89.162 -	drawVert_t	*dv;
  89.163 -	vec3_t		around[8], temp;
  89.164 -	qboolean	good[8];
  89.165 -	qboolean	wrapWidth, wrapHeight;
  89.166 -	float		len;
  89.167 -static	int	neighbors[8][2] = {
  89.168 -	{0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}
  89.169 +static void MakeMeshNormals(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE])
  89.170 +{
  89.171 +	int             i, j, k, dist;
  89.172 +	vec3_t          normal;
  89.173 +	vec3_t          sum;
  89.174 +	int             count;
  89.175 +	vec3_t          base;
  89.176 +	vec3_t          delta;
  89.177 +	int             x, y;
  89.178 +	srfVert_t      *dv;
  89.179 +	vec3_t          around[8], temp;
  89.180 +	qboolean        good[8];
  89.181 +	qboolean        wrapWidth, wrapHeight;
  89.182 +	float           len;
  89.183 +	static int      neighbors[8][2] = {
  89.184 +		{0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}
  89.185  	};
  89.186  
  89.187  	wrapWidth = qfalse;
  89.188 -	for ( i = 0 ; i < height ; i++ ) {
  89.189 -		VectorSubtract( ctrl[i][0].xyz, ctrl[i][width-1].xyz, delta );
  89.190 -		len = VectorLengthSquared( delta );
  89.191 -		if ( len > 1.0 ) {
  89.192 +	for(i = 0; i < height; i++)
  89.193 +	{
  89.194 +		VectorSubtract(ctrl[i][0].xyz, ctrl[i][width - 1].xyz, delta);
  89.195 +		len = VectorLengthSquared(delta);
  89.196 +		if(len > 1.0)
  89.197 +		{
  89.198  			break;
  89.199  		}
  89.200  	}
  89.201 -	if ( i == height ) {
  89.202 +	if(i == height)
  89.203 +	{
  89.204  		wrapWidth = qtrue;
  89.205  	}
  89.206  
  89.207  	wrapHeight = qfalse;
  89.208 -	for ( i = 0 ; i < width ; i++ ) {
  89.209 -		VectorSubtract( ctrl[0][i].xyz, ctrl[height-1][i].xyz, delta );
  89.210 -		len = VectorLengthSquared( delta );
  89.211 -		if ( len > 1.0 ) {
  89.212 +	for(i = 0; i < width; i++)
  89.213 +	{
  89.214 +		VectorSubtract(ctrl[0][i].xyz, ctrl[height - 1][i].xyz, delta);
  89.215 +		len = VectorLengthSquared(delta);
  89.216 +		if(len > 1.0)
  89.217 +		{
  89.218  			break;
  89.219  		}
  89.220  	}
  89.221 -	if ( i == width) {
  89.222 +	if(i == width)
  89.223 +	{
  89.224  		wrapHeight = qtrue;
  89.225  	}
  89.226  
  89.227  
  89.228 -	for ( i = 0 ; i < width ; i++ ) {
  89.229 -		for ( j = 0 ; j < height ; j++ ) {
  89.230 +	for(i = 0; i < width; i++)
  89.231 +	{
  89.232 +		for(j = 0; j < height; j++)
  89.233 +		{
  89.234  			count = 0;
  89.235  			dv = &ctrl[j][i];
  89.236 -			VectorCopy( dv->xyz, base );
  89.237 -			for ( k = 0 ; k < 8 ; k++ ) {
  89.238 -				VectorClear( around[k] );
  89.239 +			VectorCopy(dv->xyz, base);
  89.240 +			for(k = 0; k < 8; k++)
  89.241 +			{
  89.242 +				VectorClear(around[k]);
  89.243  				good[k] = qfalse;
  89.244  
  89.245 -				for ( dist = 1 ; dist <= 3 ; dist++ ) {
  89.246 +				for(dist = 1; dist <= 3; dist++)
  89.247 +				{
  89.248  					x = i + neighbors[k][0] * dist;
  89.249  					y = j + neighbors[k][1] * dist;
  89.250 -					if ( wrapWidth ) {
  89.251 -						if ( x < 0 ) {
  89.252 +					if(wrapWidth)
  89.253 +					{
  89.254 +						if(x < 0)
  89.255 +						{
  89.256  							x = width - 1 + x;
  89.257 -						} else if ( x >= width ) {
  89.258 +						}
  89.259 +						else if(x >= width)
  89.260 +						{
  89.261  							x = 1 + x - width;
  89.262  						}
  89.263  					}
  89.264 -					if ( wrapHeight ) {
  89.265 -						if ( y < 0 ) {
  89.266 +					if(wrapHeight)
  89.267 +					{
  89.268 +						if(y < 0)
  89.269 +						{
  89.270  							y = height - 1 + y;
  89.271 -						} else if ( y >= height ) {
  89.272 +						}
  89.273 +						else if(y >= height)
  89.274 +						{
  89.275  							y = 1 + y - height;
  89.276  						}
  89.277  					}
  89.278  
  89.279 -					if ( x < 0 || x >= width || y < 0 || y >= height ) {
  89.280 -						break;					// edge of patch
  89.281 +					if(x < 0 || x >= width || y < 0 || y >= height)
  89.282 +					{
  89.283 +						break;	// edge of patch
  89.284  					}
  89.285 -					VectorSubtract( ctrl[y][x].xyz, base, temp );
  89.286 -					if ( VectorNormalize2( temp, temp ) == 0 ) {
  89.287 -						continue;				// degenerate edge, get more dist
  89.288 -					} else {
  89.289 +					VectorSubtract(ctrl[y][x].xyz, base, temp);
  89.290 +					if(VectorNormalize2(temp, temp) == 0)
  89.291 +					{
  89.292 +						continue;	// degenerate edge, get more dist
  89.293 +					}
  89.294 +					else
  89.295 +					{
  89.296  						good[k] = qtrue;
  89.297 -						VectorCopy( temp, around[k] );
  89.298 -						break;					// good edge
  89.299 +						VectorCopy(temp, around[k]);
  89.300 +						break;	// good edge
  89.301  					}
  89.302  				}
  89.303  			}
  89.304  
  89.305 -			VectorClear( sum );
  89.306 -			for ( k = 0 ; k < 8 ; k++ ) {
  89.307 -				if ( !good[k] || !good[(k+1)&7] ) {
  89.308 +			VectorClear(sum);
  89.309 +			for(k = 0; k < 8; k++)
  89.310 +			{
  89.311 +				if(!good[k] || !good[(k + 1) & 7])
  89.312 +				{
  89.313  					continue;	// didn't get two points
  89.314  				}
  89.315 -				CrossProduct( around[(k+1)&7], around[k], normal );
  89.316 -				if ( VectorNormalize2( normal, normal ) == 0 ) {
  89.317 +				CrossProduct(around[(k + 1) & 7], around[k], normal);
  89.318 +				if(VectorNormalize2(normal, normal) == 0)
  89.319 +				{
  89.320  					continue;
  89.321  				}
  89.322 -				VectorAdd( normal, sum, sum );
  89.323 +				VectorAdd(normal, sum, sum);
  89.324  				count++;
  89.325  			}
  89.326 -			if ( count == 0 ) {
  89.327 -//Com_Printf("bad normal\n");
  89.328 +			if(count == 0)
  89.329 +			{
  89.330 +//printf("bad normal\n");
  89.331  				count = 1;
  89.332  			}
  89.333 -			VectorNormalize2( sum, dv->normal );
  89.334 +			VectorNormalize2(sum, dv->normal);
  89.335  		}
  89.336  	}
  89.337  }
  89.338  
  89.339 +static void MakeMeshTangentVectors(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], int numTriangles,
  89.340 +								   srfTriangle_t triangles[SHADER_MAX_TRIANGLES])
  89.341 +{
  89.342 +	int             i, j;
  89.343 +	srfVert_t      *dv[3];
  89.344 +	srfVert_t       ctrl2[MAX_GRID_SIZE * MAX_GRID_SIZE];
  89.345 +	srfTriangle_t  *tri;
  89.346 +
  89.347 +	// FIXME: use more elegant way
  89.348 +	for(i = 0; i < width; i++)
  89.349 +	{
  89.350 +		for(j = 0; j < height; j++)
  89.351 +		{
  89.352 +			dv[0] = &ctrl2[j * width + i];
  89.353 +			*dv[0] = ctrl[j][i];
  89.354 +		}
  89.355 +	}
  89.356 +
  89.357 +	for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
  89.358 +	{
  89.359 +		dv[0] = &ctrl2[tri->indexes[0]];
  89.360 +		dv[1] = &ctrl2[tri->indexes[1]];
  89.361 +		dv[2] = &ctrl2[tri->indexes[2]];
  89.362 +
  89.363 +		R_CalcTangentVectors(dv);
  89.364 +	}
  89.365 +
  89.366 +#if 0
  89.367 +	for(i = 0; i < (width * height); i++)
  89.368 +	{
  89.369 +		dv0 = &ctrl2[i];
  89.370 +
  89.371 +		VectorNormalize(dv0->normal);
  89.372 +#if 0
  89.373 +		VectorNormalize(dv0->tangent);
  89.374 +		VectorNormalize(dv0->binormal);
  89.375 +#else
  89.376 +		d = DotProduct(dv0->tangent, dv0->normal);
  89.377 +		VectorMA(dv0->tangent, -d, dv0->normal, dv0->tangent);
  89.378 +		VectorNormalize(dv0->tangent);
  89.379 +
  89.380 +		d = DotProduct(dv0->binormal, dv0->normal);
  89.381 +		VectorMA(dv0->binormal, -d, dv0->normal, dv0->binormal);
  89.382 +		VectorNormalize(dv0->binormal);
  89.383 +#endif
  89.384 +	}
  89.385 +#endif
  89.386 +
  89.387 +
  89.388 +#if 0
  89.389 +	// do another extra smoothing for normals to avoid flat shading
  89.390 +	for(i = 0; i < (width * height); i++)
  89.391 +	{
  89.392 +		for(j = 0; j < (width * height); j++)
  89.393 +		{
  89.394 +			if(R_CompareVert(&ctrl2[i], &ctrl2[j], qfalse))
  89.395 +			{
  89.396 +				VectorAdd(ctrl2[i].normal, ctrl2[j].normal, ctrl2[i].normal);
  89.397 +			}
  89.398 +		}
  89.399 +
  89.400 +		VectorNormalize(ctrl2[i].normal);
  89.401 +	}
  89.402 +#endif
  89.403 +
  89.404 +	for(i = 0; i < width; i++)
  89.405 +	{
  89.406 +		for(j = 0; j < height; j++)
  89.407 +		{
  89.408 +			dv[0] = &ctrl2[j * width + i];
  89.409 +			dv[1] = &ctrl[j][i];
  89.410 +
  89.411 +			VectorCopy(dv[0]->tangent, dv[1]->tangent);
  89.412 +			VectorCopy(dv[0]->binormal, dv[1]->binormal);
  89.413 +		}
  89.414 +	}
  89.415 +}
  89.416 +
  89.417 +static int MakeMeshTriangles(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
  89.418 +							 srfTriangle_t triangles[SHADER_MAX_TRIANGLES])
  89.419 +{
  89.420 +	int             i, j;
  89.421 +	int             numTriangles;
  89.422 +	int             w, h;
  89.423 +	srfVert_t      *dv;
  89.424 +	srfVert_t       ctrl2[MAX_GRID_SIZE * MAX_GRID_SIZE];
  89.425 +
  89.426 +	h = height - 1;
  89.427 +	w = width - 1;
  89.428 +	numTriangles = 0;
  89.429 +	for(i = 0; i < h; i++)
  89.430 +	{
  89.431 +		for(j = 0; j < w; j++)
  89.432 +		{
  89.433 +			int             v1, v2, v3, v4;
  89.434 +
  89.435 +			// vertex order to be reckognized as tristrips
  89.436 +			v1 = i * width + j + 1;
  89.437 +			v2 = v1 - 1;
  89.438 +			v3 = v2 + width;
  89.439 +			v4 = v3 + 1;
  89.440 +
  89.441 +			triangles[numTriangles].indexes[0] = v2;
  89.442 +			triangles[numTriangles].indexes[1] = v3;
  89.443 +			triangles[numTriangles].indexes[2] = v1;
  89.444 +			numTriangles++;
  89.445 +
  89.446 +			triangles[numTriangles].indexes[0] = v1;
  89.447 +			triangles[numTriangles].indexes[1] = v3;
  89.448 +			triangles[numTriangles].indexes[2] = v4;
  89.449 +			numTriangles++;
  89.450 +		}
  89.451 +	}
  89.452 +
  89.453 +	R_CalcSurfaceTriangleNeighbors(numTriangles, triangles);
  89.454 +
  89.455 +	// FIXME: use more elegant way
  89.456 +	for(i = 0; i < width; i++)
  89.457 +	{
  89.458 +		for(j = 0; j < height; j++)
  89.459 +		{
  89.460 +			dv = &ctrl2[j * width + i];
  89.461 +			*dv = ctrl[j][i];
  89.462 +		}
  89.463 +	}
  89.464 +
  89.465 +	R_CalcSurfaceTrianglePlanes(numTriangles, triangles, ctrl2);
  89.466 +
  89.467 +	return numTriangles;
  89.468 +}
  89.469 +
  89.470 +static void MakeTangentSpaces(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], int numTriangles,
  89.471 +							  srfTriangle_t triangles[SHADER_MAX_TRIANGLES])
  89.472 +{
  89.473 +	int             i, j;
  89.474 +	float          *v;
  89.475 +	const float    *v0, *v1, *v2;
  89.476 +	const float    *t0, *t1, *t2;
  89.477 +	vec3_t          tangent;
  89.478 +	vec3_t          binormal;
  89.479 +	vec3_t          normal;
  89.480 +	vec_t           d;
  89.481 +	srfVert_t      *dv0, *dv1, *dv2;
  89.482 +	srfVert_t       ctrl2[MAX_GRID_SIZE * MAX_GRID_SIZE];
  89.483 +	srfTriangle_t  *tri;
  89.484 +
  89.485 +	// FIXME: use more elegant way
  89.486 +	for(i = 0; i < width; i++)
  89.487 +	{
  89.488 +		for(j = 0; j < height; j++)
  89.489 +		{
  89.490 +			dv0 = &ctrl2[j * width + i];
  89.491 +			*dv0 = ctrl[j][i];
  89.492 +		}
  89.493 +	}
  89.494 +
  89.495 +	for(i = 0; i < (width * height); i++)
  89.496 +	{
  89.497 +		dv0 = &ctrl2[i];
  89.498 +
  89.499 +		VectorClear(dv0->tangent);
  89.500 +		VectorClear(dv0->binormal);
  89.501 +		VectorClear(dv0->normal);
  89.502 +	}
  89.503 +
  89.504 +	for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
  89.505 +	{
  89.506 +		dv0 = &ctrl2[tri->indexes[0]];
  89.507 +		dv1 = &ctrl2[tri->indexes[1]];
  89.508 +		dv2 = &ctrl2[tri->indexes[2]];
  89.509 +
  89.510 +		v0 = dv0->xyz;
  89.511 +		v1 = dv1->xyz;
  89.512 +		v2 = dv2->xyz;
  89.513 +
  89.514 +		t0 = dv0->st;
  89.515 +		t1 = dv1->st;
  89.516 +		t2 = dv2->st;
  89.517 +
  89.518 +		R_CalcTangentSpace2(tangent, binormal, normal, v0, v1, v2, t0, t1, t2);
  89.519 +
  89.520 +		for(j = 0; j < 3; j++)
  89.521 +		{
  89.522 +			dv0 = &ctrl2[tri->indexes[j]];
  89.523 +
  89.524 +			v = dv0->tangent;
  89.525 +			VectorAdd(v, tangent, v);
  89.526 +
  89.527 +			v = dv0->binormal;
  89.528 +			VectorAdd(v, binormal, v);
  89.529 +
  89.530 +			v = dv0->normal;
  89.531 +			VectorAdd(v, normal, v);
  89.532 +		}
  89.533 +	}
  89.534 +
  89.535 +	for(i = 0; i < (width * height); i++)
  89.536 +	{
  89.537 +		dv0 = &ctrl2[i];
  89.538 +
  89.539 +		VectorNormalize(dv0->normal);
  89.540 +#if 0
  89.541 +		VectorNormalize(dv0->tangent);
  89.542 +		VectorNormalize(dv0->binormal);
  89.543 +#else
  89.544 +		d = DotProduct(dv0->tangent, dv0->normal);
  89.545 +		VectorMA(dv0->tangent, -d, dv0->normal, dv0->tangent);
  89.546 +		VectorNormalize(dv0->tangent);
  89.547 +
  89.548 +		d = DotProduct(dv0->binormal, dv0->normal);
  89.549 +		VectorMA(dv0->binormal, -d, dv0->normal, dv0->binormal);
  89.550 +		VectorNormalize(dv0->binormal);
  89.551 +#endif
  89.552 +	}
  89.553 +
  89.554 +	// do another extra smoothing for normals to avoid flat shading
  89.555 +	for(i = 0; i < (width * height); i++)
  89.556 +	{
  89.557 +		for(j = 0; j < (width * height); j++)
  89.558 +		{
  89.559 +			if(R_CompareVert(&ctrl2[i], &ctrl2[j], qfalse))
  89.560 +			{
  89.561 +				VectorAdd(ctrl2[i].normal, ctrl2[j].normal, ctrl2[i].normal);
  89.562 +			}
  89.563 +		}
  89.564 +
  89.565 +		VectorNormalize(ctrl2[i].normal);
  89.566 +	}
  89.567 +
  89.568 +	for(i = 0; i < width; i++)
  89.569 +	{
  89.570 +		for(j = 0; j < height; j++)
  89.571 +		{
  89.572 +			dv0 = &ctrl2[j * width + i];
  89.573 +			dv1 = &ctrl[j][i];
  89.574 +
  89.575 +			VectorCopy(dv0->tangent, dv1->tangent);
  89.576 +			VectorCopy(dv0->binormal, dv1->binormal);
  89.577 +			VectorCopy(dv0->normal, dv1->normal);
  89.578 +		}
  89.579 +	}
  89.580 +}
  89.581  
  89.582  /*
  89.583  ============
  89.584  InvertCtrl
  89.585  ============
  89.586  */
  89.587 -static void InvertCtrl( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
  89.588 -	int		i, j;
  89.589 -	drawVert_t	temp;
  89.590 +static void InvertCtrl(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE])
  89.591 +{
  89.592 +	int             i, j;
  89.593 +	srfVert_t       temp;
  89.594  
  89.595 -	for ( i = 0 ; i < height ; i++ ) {
  89.596 -		for ( j = 0 ; j < width/2 ; j++ ) {
  89.597 +	for(i = 0; i < height; i++)
  89.598 +	{
  89.599 +		for(j = 0; j < width / 2; j++)
  89.600 +		{
  89.601  			temp = ctrl[i][j];
  89.602 -			ctrl[i][j] = ctrl[i][width-1-j];
  89.603 -			ctrl[i][width-1-j] = temp;
  89.604 +			ctrl[i][j] = ctrl[i][width - 1 - j];
  89.605 +			ctrl[i][width - 1 - j] = temp;
  89.606  		}
  89.607  	}
  89.608  }
  89.609 @@ -239,18 +532,21 @@
  89.610  InvertErrorTable
  89.611  =================
  89.612  */
  89.613 -static void InvertErrorTable( float errorTable[2][MAX_GRID_SIZE], int width, int height ) {
  89.614 -	int		i;
  89.615 -	float	copy[2][MAX_GRID_SIZE];
  89.616 +static void InvertErrorTable(float errorTable[2][MAX_GRID_SIZE], int width, int height)
  89.617 +{
  89.618 +	int             i;
  89.619 +	float           copy[2][MAX_GRID_SIZE];
  89.620  
  89.621 -	Com_Memcpy( copy, errorTable, sizeof( copy ) );
  89.622 +	Com_Memcpy(copy, errorTable, sizeof(copy));
  89.623  
  89.624 -	for ( i = 0 ; i < width ; i++ ) {
  89.625 +	for(i = 0; i < width; i++)
  89.626 +	{
  89.627  		errorTable[1][i] = copy[0][i];	//[width-1-i];
  89.628  	}
  89.629  
  89.630 -	for ( i = 0 ; i < height ; i++ ) {
  89.631 -		errorTable[0][i] = copy[1][height-1-i];
  89.632 +	for(i = 0; i < height; i++)
  89.633 +	{
  89.634 +		errorTable[0][i] = copy[1][height - 1 - i];
  89.635  	}
  89.636  
  89.637  }
  89.638 @@ -260,25 +556,29 @@
  89.639  PutPointsOnCurve
  89.640  ==================
  89.641  */
  89.642 -static void PutPointsOnCurve( drawVert_t	ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], 
  89.643 -							 int width, int height ) {
  89.644 -	int			i, j;
  89.645 -	drawVert_t	prev, next;
  89.646 +static void PutPointsOnCurve(srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], int width, int height)
  89.647 +{
  89.648 +	int             i, j;
  89.649 +	srfVert_t       prev, next;
  89.650  
  89.651 -	for ( i = 0 ; i < width ; i++ ) {
  89.652 -		for ( j = 1 ; j < height ; j += 2 ) {
  89.653 -			LerpDrawVert( &ctrl[j][i], &ctrl[j+1][i], &prev );
  89.654 -			LerpDrawVert( &ctrl[j][i], &ctrl[j-1][i], &next );
  89.655 -			LerpDrawVert( &prev, &next, &ctrl[j][i] );
  89.656 +	for(i = 0; i < width; i++)
  89.657 +	{
  89.658 +		for(j = 1; j < height; j += 2)
  89.659 +		{
  89.660 +			LerpSurfaceVert(&ctrl[j][i], &ctrl[j + 1][i], &prev);
  89.661 +			LerpSurfaceVert(&ctrl[j][i], &ctrl[j - 1][i], &next);
  89.662 +			LerpSurfaceVert(&prev, &next, &ctrl[j][i]);
  89.663  		}
  89.664  	}
  89.665  
  89.666  
  89.667 -	for ( j = 0 ; j < height ; j++ ) {
  89.668 -		for ( i = 1 ; i < width ; i += 2 ) {
  89.669 -			LerpDrawVert( &ctrl[j][i], &ctrl[j][i+1], &prev );
  89.670 -			LerpDrawVert( &ctrl[j][i], &ctrl[j][i-1], &next );
  89.671 -			LerpDrawVert( &prev, &next, &ctrl[j][i] );
  89.672 +	for(j = 0; j < height; j++)
  89.673 +	{
  89.674 +		for(i = 1; i < width; i += 2)
  89.675 +		{
  89.676 +			LerpSurfaceVert(&ctrl[j][i], &ctrl[j][i + 1], &prev);
  89.677 +			LerpSurfaceVert(&ctrl[j][i], &ctrl[j][i - 1], &next);
  89.678 +			LerpSurfaceVert(&prev, &next, &ctrl[j][i]);
  89.679  		}
  89.680  	}
  89.681  }
  89.682 @@ -288,55 +588,77 @@
  89.683  R_CreateSurfaceGridMesh
  89.684  =================
  89.685  */
  89.686 -srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
  89.687 -								drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE] ) {
  89.688 -	int i, j, size;
  89.689 -	drawVert_t	*vert;
  89.690 -	vec3_t		tmpVec;
  89.691 -	srfGridMesh_t *grid;
  89.692 +static srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
  89.693 +											  srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
  89.694 +											  float errorTable[2][MAX_GRID_SIZE],
  89.695 +											  int numTriangles, srfTriangle_t triangles[SHADER_MAX_TRIANGLES])
  89.696 +{
  89.697 +	int             i, j, size;
  89.698 +	srfVert_t      *vert;
  89.699 +	vec3_t          tmpVec;
  89.700 +	srfGridMesh_t  *grid;
  89.701  
  89.702  	// copy the results out to a grid
  89.703 -	size = (width * height - 1) * sizeof( drawVert_t ) + sizeof( *grid );
  89.704 +	size = sizeof(*grid);
  89.705  
  89.706 -#ifdef PATCH_STITCHING
  89.707 -	grid = /*ri.Hunk_Alloc*/ ri.Malloc( size );
  89.708 -	Com_Memset(grid, 0, size);
  89.709 +	if(r_stitchCurves->integer)
  89.710 +	{
  89.711 +		grid = /*ri.Hunk_Alloc */ Com_Allocate(size);
  89.712 +		Com_Memset(grid, 0, size);
  89.713  
  89.714 -	grid->widthLodError = /*ri.Hunk_Alloc*/ ri.Malloc( width * 4 );
  89.715 -	Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 );
  89.716 +		grid->widthLodError = /*ri.Hunk_Alloc */ Com_Allocate(width * 4);
  89.717 +		Com_Memcpy(grid->widthLodError, errorTable[0], width * 4);
  89.718  
  89.719 -	grid->heightLodError = /*ri.Hunk_Alloc*/ ri.Malloc( height * 4 );
  89.720 -	Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 );
  89.721 -#else
  89.722 -	grid = ri.Hunk_Alloc( size );
  89.723 -	Com_Memset(grid, 0, size);
  89.724 +		grid->heightLodError = /*ri.Hunk_Alloc */ Com_Allocate(height * 4);
  89.725 +		Com_Memcpy(grid->heightLodError, errorTable[1], height * 4);
  89.726  
  89.727 -	grid->widthLodError = ri.Hunk_Alloc( width * 4 );
  89.728 -	Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 );
  89.729 +		grid->numTriangles = numTriangles;
  89.730 +		grid->triangles = Com_Allocate(grid->numTriangles * sizeof(srfTriangle_t));
  89.731 +		Com_Memcpy(grid->triangles, triangles, numTriangles * sizeof(srfTriangle_t));
  89.732  
  89.733 -	grid->heightLodError = ri.Hunk_Alloc( height * 4 );
  89.734 -	Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 );
  89.735 -#endif
  89.736 +		grid->numVerts = (width * height);
  89.737 +		grid->verts = Com_Allocate(grid->numVerts * sizeof(srfVert_t));
  89.738 +	}
  89.739 +	else
  89.740 +	{
  89.741 +		grid = ri.Hunk_Alloc(size, h_low);
  89.742 +		Com_Memset(grid, 0, size);
  89.743 +
  89.744 +		grid->widthLodError = ri.Hunk_Alloc(width * 4, h_low);
  89.745 +		Com_Memcpy(grid->widthLodError, errorTable[0], width * 4);
  89.746 +
  89.747 +		grid->heightLodError = ri.Hunk_Alloc(height * 4, h_low);
  89.748 +		Com_Memcpy(grid->heightLodError, errorTable[1], height * 4);
  89.749 +
  89.750 +		grid->numTriangles = numTriangles;
  89.751 +		grid->triangles = ri.Hunk_Alloc(grid->numTriangles * sizeof(srfTriangle_t), h_low);
  89.752 +		Com_Memcpy(grid->triangles, triangles, numTriangles * sizeof(srfTriangle_t));
  89.753 +
  89.754 +		grid->numVerts = (width * height);
  89.755 +		grid->verts = ri.Hunk_Alloc(grid->numVerts * sizeof(srfVert_t), h_low);
  89.756 +	}
  89.757  
  89.758  	grid->width = width;
  89.759  	grid->height = height;
  89.760  	grid->surfaceType = SF_GRID;
  89.761 -	ClearBounds( grid->meshBounds[0], grid->meshBounds[1] );
  89.762 -	for ( i = 0 ; i < width ; i++ ) {
  89.763 -		for ( j = 0 ; j < height ; j++ ) {
  89.764 -			vert = &grid->verts[j*width+i];
  89.765 +	ClearBounds(grid->meshBounds[0], grid->meshBounds[1]);
  89.766 +	for(i = 0; i < width; i++)
  89.767 +	{
  89.768 +		for(j = 0; j < height; j++)
  89.769 +		{
  89.770 +			vert = &grid->verts[j * width + i];
  89.771  			*vert = ctrl[j][i];
  89.772 -			AddPointToBounds( vert->xyz, grid->meshBounds[0], grid->meshBounds[1] );
  89.773 +			AddPointToBounds(vert->xyz, grid->meshBounds[0], grid->meshBounds[1]);
  89.774  		}
  89.775  	}
  89.776  
  89.777  	// compute local origin and bounds
  89.778 -	VectorAdd( grid->meshBounds[0], grid->meshBounds[1], grid->localOrigin );
  89.779 -	VectorScale( grid->localOrigin, 0.5f, grid->localOrigin );
  89.780 -	VectorSubtract( grid->meshBounds[0], grid->localOrigin, tmpVec );
  89.781 -	grid->meshRadius = VectorLength( tmpVec );
  89.782 +	VectorAdd(grid->meshBounds[0], grid->meshBounds[1], grid->localOrigin);
  89.783 +	VectorScale(grid->localOrigin, 0.5f, grid->localOrigin);
  89.784 +	VectorSubtract(grid->meshBounds[0], grid->localOrigin, tmpVec);
  89.785 +	grid->meshRadius = VectorLength(tmpVec);
  89.786  
  89.787 -	VectorCopy( grid->localOrigin, grid->lodOrigin );
  89.788 +	VectorCopy(grid->localOrigin, grid->lodOrigin);
  89.789  	grid->lodRadius = grid->meshRadius;
  89.790  	//
  89.791  	return grid;
  89.792 @@ -347,10 +669,13 @@
  89.793  R_FreeSurfaceGridMesh
  89.794  =================
  89.795  */
  89.796 -void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) {
  89.797 -	ri.Free(grid->widthLodError);
  89.798 -	ri.Free(grid->heightLodError);
  89.799 -	ri.Free(grid);
  89.800 +void R_FreeSurfaceGridMesh(srfGridMesh_t * grid)
  89.801 +{
  89.802 +	Com_Dealloc(grid->widthLodError);
  89.803 +	Com_Dealloc(grid->heightLodError);
  89.804 +	Com_Dealloc(grid->triangles);
  89.805 +	Com_Dealloc(grid->verts);
  89.806 +	Com_Dealloc(grid);
  89.807  }
  89.808  
  89.809  /*
  89.810 @@ -358,64 +683,71 @@
  89.811  R_SubdividePatchToGrid
  89.812  =================
  89.813  */
  89.814 -srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
  89.815 -								drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
  89.816 -	int			i, j, k, l;
  89.817 -	drawVert_t_cleared( prev );
  89.818 -	drawVert_t_cleared( next );
  89.819 -	drawVert_t_cleared( mid );
  89.820 -	float		len, maxLen;
  89.821 -	int			dir;
  89.822 -	int			t;
  89.823 -	drawVert_t	ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
  89.824 -	float		errorTable[2][MAX_GRID_SIZE];
  89.825 +srfGridMesh_t  *R_SubdividePatchToGrid(int width, int height, srfVert_t points[MAX_PATCH_SIZE * MAX_PATCH_SIZE])
  89.826 +{
  89.827 +	int             i, j, k, l;
  89.828 +	srfVert_t       prev, next, mid;
  89.829 +	float           len, maxLen;
  89.830 +	int             dir;
  89.831 +	int             t;
  89.832 +	srfVert_t       ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
  89.833 +	float           errorTable[2][MAX_GRID_SIZE];
  89.834 +	int             numTriangles;
  89.835 +	static srfTriangle_t triangles[SHADER_MAX_TRIANGLES];
  89.836  
  89.837 -	for ( i = 0 ; i < width ; i++ ) {
  89.838 -		for ( j = 0 ; j < height ; j++ ) {
  89.839 -			ctrl[j][i] = points[j*width+i];
  89.840 +	for(i = 0; i < width; i++)
  89.841 +	{
  89.842 +		for(j = 0; j < height; j++)
  89.843 +		{
  89.844 +			ctrl[j][i] = points[j * width + i];
  89.845  		}
  89.846  	}
  89.847  
  89.848 -	for ( dir = 0 ; dir < 2 ; dir++ ) {
  89.849 +	for(dir = 0; dir < 2; dir++)
  89.850 +	{
  89.851  
  89.852 -		for ( j = 0 ; j < MAX_GRID_SIZE ; j++ ) {
  89.853 +		for(j = 0; j < MAX_GRID_SIZE; j++)
  89.854 +		{
  89.855  			errorTable[dir][j] = 0;
  89.856  		}
  89.857  
  89.858  		// horizontal subdivisions
  89.859 -		for ( j = 0 ; j + 2 < width ; j += 2 ) {
  89.860 +		for(j = 0; j + 2 < width; j += 2)
  89.861 +		{
  89.862  			// check subdivided midpoints against control points
  89.863  
  89.864  			// FIXME: also check midpoints of adjacent patches against the control points
  89.865  			// this would basically stitch all patches in the same LOD group together.
  89.866  
  89.867  			maxLen = 0;
  89.868 -			for ( i = 0 ; i < height ; i++ ) {
  89.869 -				vec3_t		midxyz;
  89.870 -				vec3_t		midxyz2;
  89.871 -				vec3_t		dir;
  89.872 -				vec3_t		projected;
  89.873 -				float		d;
  89.874 +			for(i = 0; i < height; i++)
  89.875 +			{
  89.876 +				vec3_t          midxyz;
  89.877 +				vec3_t          midxyz2;
  89.878 +				vec3_t          dir;
  89.879 +				vec3_t          projected;
  89.880 +				float           d;
  89.881  
  89.882  				// calculate the point on the curve
  89.883 -				for ( l = 0 ; l < 3 ; l++ ) {
  89.884 -					midxyz[l] = (ctrl[i][j].xyz[l] + ctrl[i][j+1].xyz[l] * 2
  89.885 -							+ ctrl[i][j+2].xyz[l] ) * 0.25f;
  89.886 +				for(l = 0; l < 3; l++)
  89.887 +				{
  89.888 +					midxyz[l] = (ctrl[i][j].xyz[l] + ctrl[i][j + 1].xyz[l] * 2 + ctrl[i][j + 2].xyz[l]) * 0.25f;
  89.889  				}
  89.890  
  89.891  				// see how far off the line it is
  89.892  				// using dist-from-line will not account for internal
  89.893  				// texture warping, but it gives a lot less polygons than
  89.894  				// dist-from-midpoint
  89.895 -				VectorSubtract( midxyz, ctrl[i][j].xyz, midxyz );
  89.896 -				VectorSubtract( ctrl[i][j+2].xyz, ctrl[i][j].xyz, dir );
  89.897 -				VectorNormalize( dir );
  89.898 +				VectorSubtract(midxyz, ctrl[i][j].xyz, midxyz);
  89.899 +				VectorSubtract(ctrl[i][j + 2].xyz, ctrl[i][j].xyz, dir);
  89.900 +				VectorNormalize(dir);
  89.901  
  89.902 -				d = DotProduct( midxyz, dir );
  89.903 -				VectorScale( dir, d, projected );
  89.904 -				VectorSubtract( midxyz, projected, midxyz2);
  89.905 -				len = VectorLengthSquared( midxyz2 );			// we will do the sqrt later
  89.906 -				if ( len > maxLen ) {
  89.907 +				d = DotProduct(midxyz, dir);
  89.908 +				VectorScale(dir, d, projected);
  89.909 +				VectorSubtract(midxyz, projected, midxyz2);
  89.910 +				len = VectorLengthSquared(midxyz2);	// we will do the sqrt later
  89.911 +				if(len > maxLen)
  89.912 +				{
  89.913  					maxLen = len;
  89.914  				}
  89.915  			}
  89.916 @@ -423,33 +755,38 @@
  89.917  			maxLen = sqrt(maxLen);
  89.918  
  89.919  			// if all the points are on the lines, remove the entire columns
  89.920 -			if ( maxLen < 0.1f ) {
  89.921 -				errorTable[dir][j+1] = 999;
  89.922 +			if(maxLen < 0.1f)
  89.923 +			{
  89.924 +				errorTable[dir][j + 1] = 999;
  89.925  				continue;
  89.926  			}
  89.927  
  89.928  			// see if we want to insert subdivided columns
  89.929 -			if ( width + 2 > MAX_GRID_SIZE ) {
  89.930 -				errorTable[dir][j+1] = 1.0f/maxLen;
  89.931 -				continue;	// can't subdivide any more
  89.932 +			if(width + 2 > MAX_GRID_SIZE)
  89.933 +			{
  89.934 +				errorTable[dir][j + 1] = 1.0f / maxLen;
  89.935 +				continue;		// can't subdivide any more
  89.936  			}
  89.937  
  89.938 -			if ( maxLen <= r_subdivisions->value ) {
  89.939 -				errorTable[dir][j+1] = 1.0f/maxLen;
  89.940 -				continue;	// didn't need subdivision
  89.941 +			if(maxLen <= r_subdivisions->value)
  89.942 +			{
  89.943 +				errorTable[dir][j + 1] = 1.0f / maxLen;
  89.944 +				continue;		// didn't need subdivision
  89.945  			}
  89.946  
  89.947 -			errorTable[dir][j+2] = 1.0f/maxLen;
  89.948 +			errorTable[dir][j + 2] = 1.0f / maxLen;
  89.949  
  89.950  			// insert two columns and replace the peak
  89.951  			width += 2;
  89.952 -			for ( i = 0 ; i < height ; i++ ) {
  89.953 -				LerpDrawVert( &ctrl[i][j], &ctrl[i][j+1], &prev );
  89.954 -				LerpDrawVert( &ctrl[i][j+1], &ctrl[i][j+2], &next );
  89.955 -				LerpDrawVert( &prev, &next, &mid );
  89.956 +			for(i = 0; i < height; i++)
  89.957 +			{
  89.958 +				LerpSurfaceVert(&ctrl[i][j], &ctrl[i][j + 1], &prev);
  89.959 +				LerpSurfaceVert(&ctrl[i][j + 1], &ctrl[i][j + 2], &next);
  89.960 +				LerpSurfaceVert(&prev, &next, &mid);
  89.961  
  89.962 -				for ( k = width - 1 ; k > j + 3 ; k-- ) {
  89.963 -					ctrl[i][k] = ctrl[i][k-2];
  89.964 +				for(k = width - 1; k > j + 3; k--)
  89.965 +				{
  89.966 +					ctrl[i][k] = ctrl[i][k - 2];
  89.967  				}
  89.968  				ctrl[i][j + 1] = prev;
  89.969  				ctrl[i][j + 2] = mid;
  89.970 @@ -461,39 +798,46 @@
  89.971  
  89.972  		}
  89.973  
  89.974 -		Transpose( width, height, ctrl );
  89.975 +		Transpose(width, height, ctrl);
  89.976  		t = width;
  89.977  		width = height;
  89.978  		height = t;
  89.979  	}
  89.980  
  89.981 -
  89.982  	// put all the aproximating points on the curve
  89.983 -	PutPointsOnCurve( ctrl, width, height );
  89.984 +	PutPointsOnCurve(ctrl, width, height);
  89.985  
  89.986  	// cull out any rows or columns that are colinear
  89.987 -	for ( i = 1 ; i < width-1 ; i++ ) {
  89.988 -		if ( errorTable[0][i] != 999 ) {
  89.989 +	for(i = 1; i < width - 1; i++)
  89.990 +	{
  89.991 +		if(errorTable[0][i] != 999)
  89.992 +		{
  89.993  			continue;
  89.994  		}
  89.995 -		for ( j = i+1 ; j < width ; j++ ) {
  89.996 -			for ( k = 0 ; k < height ; k++ ) {
  89.997 -				ctrl[k][j-1] = ctrl[k][j];
  89.998 +		for(j = i + 1; j < width; j++)
  89.999 +		{
 89.1000 +			for(k = 0; k < height; k++)
 89.1001 +			{
 89.1002 +				ctrl[k][j - 1] = ctrl[k][j];
 89.1003  			}
 89.1004 -			errorTable[0][j-1] = errorTable[0][j];
 89.1005 +			errorTable[0][j - 1] = errorTable[0][j];
 89.1006  		}
 89.1007  		width--;
 89.1008  	}
 89.1009  
 89.1010 -	for ( i = 1 ; i < height-1 ; i++ ) {
 89.1011 -		if ( errorTable[1][i] != 999 ) {
 89.1012 +	for(i = 1; i < height - 1; i++)
 89.1013 +	{
 89.1014 +		if(errorTable[1][i] != 999)
 89.1015 +		{
 89.1016  			continue;
 89.1017  		}
 89.1018 -		for ( j = i+1 ; j < height ; j++ ) {
 89.1019 -			for ( k = 0 ; k < width ; k++ ) {
 89.1020 -				ctrl[j-1][k] = ctrl[j][k];
 89.1021 +		for(j = i + 1; j < height; j++)
 89.1022 +		{
 89.1023 +			for(k = 0; k < width; k++)
 89.1024 +			{
 89.1025 +				ctrl[j - 1][k] = ctrl[j][k];
 89.1026  			}
 89.1027 -			errorTable[1][j-1] = errorTable[1][j];
 89.1028 +			errorTable[1][j - 1] = errorTable[1][j];
 89.1029  		}
 89.1030  		height--;
 89.1031  	}
 89.1032 @@ -502,20 +846,28 @@
 89.1033  	// flip for longest tristrips as an optimization
 89.1034  	// the results should be visually identical with or
 89.1035  	// without this step
 89.1036 -	if ( height > width ) {
 89.1037 -		Transpose( width, height, ctrl );
 89.1038 -		InvertErrorTable( errorTable, width, height );
 89.1039 +	if(height > width)
 89.1040 +	{
 89.1041 +		Transpose(width, height, ctrl);
 89.1042 +		InvertErrorTable(errorTable, width, height);
 89.1043  		t = width;
 89.1044  		width = height;
 89.1045  		height = t;
 89.1046 -		InvertCtrl( width, height, ctrl );
 89.1047 +		InvertCtrl(width, height, ctrl);
 89.1048  	}
 89.1049  #endif
 89.1050  
 89.1051 +	// calculate triangles
 89.1052 +	numTriangles = MakeMeshTriangles(width, height, ctrl, triangles);
 89.1053 +
 89.1054  	// calculate normals
 89.1055 -	MakeMeshNormals( width, height, ctrl );
 89.1056 +	MakeMeshNormals(width, height, ctrl);
 89.1057 +	MakeMeshTangentVectors(width, height, ctrl, numTriangles, triangles);
 89.1058  
 89.1059 -	return R_CreateSurfaceGridMesh( width, height, ctrl, errorTable );
 89.1060 +	// calculate tangent spaces
 89.1061 +	//MakeTangentSpaces(width, height, ctrl, numTriangles, triangles);
 89.1062 +
 89.1063 +	return R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
 89.1064  }
 89.1065  
 89.1066  /*
 89.1067 @@ -523,50 +875,67 @@
 89.1068  R_GridInsertColumn
 89.1069  ===============
 89.1070  */
 89.1071 -srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ) {
 89.1072 -	int i, j;
 89.1073 -	int width, height, oldwidth;
 89.1074 -	drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
 89.1075 -	float errorTable[2][MAX_GRID_SIZE];
 89.1076 -	float lodRadius;
 89.1077 -	vec3_t lodOrigin;
 89.1078 +srfGridMesh_t  *R_GridInsertColumn(srfGridMesh_t * grid, int column, int row, vec3_t point, float loderror)
 89.1079 +{
 89.1080 +	int             i, j;
 89.1081 +	int             width, height, oldwidth;
 89.1082 +	srfVert_t       ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
 89.1083 +	float           errorTable[2][MAX_GRID_SIZE];
 89.1084 +	float           lodRadius;
 89.1085 +	vec3_t          lodOrigin;
 89.1086 +	int             numTriangles;
 89.1087 +	static srfTriangle_t triangles[SHADER_MAX_TRIANGLES];
 89.1088  
 89.1089  	oldwidth = 0;
 89.1090  	width = grid->width + 1;
 89.1091 -	if (width > MAX_GRID_SIZE)
 89.1092 +	if(width > MAX_GRID_SIZE)
 89.1093  		return NULL;
 89.1094  	height = grid->height;
 89.1095 -	for (i = 0; i < width; i++) {
 89.1096 -		if (i == column) {
 89.1097 +	for(i = 0; i < width; i++)
 89.1098 +	{
 89.1099 +		if(i == column)
 89.1100 +		{
 89.1101  			//insert new column
 89.1102 -			for (j = 0; j < grid->height; j++) {
 89.1103 -				LerpDrawVert( &grid->verts[j * grid->width + i-1], &grid->verts[j * grid->width + i], &ctrl[j][i] );
 89.1104 -				if (j == row)
 89.1105 +			for(j = 0; j < grid->height; j++)
 89.1106 +			{
 89.1107 +				LerpSurfaceVert(&grid->verts[j * grid->width + i - 1], &grid->verts[j * grid->width + i], &ctrl[j][i]);
 89.1108 +				if(j == row)
 89.1109  					VectorCopy(point, ctrl[j][i].xyz);
 89.1110  			}
 89.1111  			errorTable[0][i] = loderror;
 89.1112  			continue;
 89.1113  		}
 89.1114  		errorTable[0][i] = grid->widthLodError[oldwidth];
 89.1115 -		for (j = 0; j < grid->height; j++) {
 89.1116 +		for(j = 0; j < grid->height; j++)
 89.1117 +		{
 89.1118  			ctrl[j][i] = grid->verts[j * grid->width + oldwidth];
 89.1119  		}
 89.1120  		oldwidth++;
 89.1121  	}
 89.1122 -	for (j = 0; j < grid->height; j++) {
 89.1123 +	for(j = 0; j < grid->height; j++)
 89.1124 +	{
 89.1125  		errorTable[1][j] = grid->heightLodError[j];
 89.1126  	}
 89.1127 +
 89.1128  	// put all the aproximating points on the curve
 89.1129  	//PutPointsOnCurve( ctrl, width, height );
 89.1130 +
 89.1131 +	// calculate triangles
 89.1132 +	numTriangles = MakeMeshTriangles(width, height, ctrl, triangles);
 89.1133 +
 89.1134  	// calculate normals
 89.1135 -	MakeMeshNormals( width, height, ctrl );
 89.1136 +	MakeMeshNormals(width, height, ctrl);
 89.1137 +	MakeMeshTangentVectors(width, height, ctrl, numTriangles, triangles);
 89.1138 +
 89.1139 +	// calculate tangent spaces
 89.1140 +	//MakeTangentSpaces(width, height, ctrl, numTriangles, triangles);
 89.1141  
 89.1142  	VectorCopy(grid->lodOrigin, lodOrigin);
 89.1143  	lodRadius = grid->lodRadius;
 89.1144  	// free the old grid
 89.1145  	R_FreeSurfaceGridMesh(grid);
 89.1146  	// create a new grid
 89.1147 -	grid = R_CreateSurfaceGridMesh( width, height, ctrl, errorTable );
 89.1148 +	grid = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
 89.1149  	grid->lodRadius = lodRadius;
 89.1150  	VectorCopy(lodOrigin, grid->lodOrigin);
 89.1151  	return grid;
 89.1152 @@ -577,50 +946,66 @@
 89.1153  R_GridInsertRow
 89.1154  ===============
 89.1155  */
 89.1156 -srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ) {
 89.1157 -	int i, j;
 89.1158 -	int width, height, oldheight;
 89.1159 -	drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
 89.1160 -	float errorTable[2][MAX_GRID_SIZE];
 89.1161 -	float lodRadius;
 89.1162 -	vec3_t lodOrigin;
 89.1163 +srfGridMesh_t  *R_GridInsertRow(srfGridMesh_t * grid, int row, int column, vec3_t point, float loderror)
 89.1164 +{
 89.1165 +	int             i, j;
 89.1166 +	int             width, height, oldheight;
 89.1167 +	srfVert_t       ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
 89.1168 +	float           errorTable[2][MAX_GRID_SIZE];
 89.1169 +	float           lodRadius;
 89.1170 +	vec3_t          lodOrigin;
 89.1171 +	int             numTriangles;
 89.1172 +	static srfTriangle_t triangles[SHADER_MAX_TRIANGLES];
 89.1173  
 89.1174  	oldheight = 0;
 89.1175  	width = grid->width;
 89.1176  	height = grid->height + 1;
 89.1177 -	if (height > MAX_GRID_SIZE)
 89.1178 +	if(height > MAX_GRID_SIZE)
 89.1179  		return NULL;
 89.1180 -	for (i = 0; i < height; i++) {
 89.1181 -		if (i == row) {
 89.1182 +	for(i = 0; i < height; i++)
 89.1183 +	{
 89.1184 +		if(i == row)
 89.1185 +		{
 89.1186  			//insert new row
 89.1187 -			for (j = 0; j < grid->width; j++) {
 89.1188 -				LerpDrawVert( &grid->verts[(i-1) * grid->width + j], &grid->verts[i * grid->width + j], &ctrl[i][j] );
 89.1189 -				if (j == column)
 89.1190 +			for(j = 0; j < grid->width; j++)
 89.1191 +			{
 89.1192 +				LerpSurfaceVert(&grid->verts[(i - 1) * grid->width + j], &grid->verts[i * grid->width + j], &ctrl[i][j]);
 89.1193 +				if(j == column)
 89.1194  					VectorCopy(point, ctrl[i][j].xyz);
 89.1195  			}
 89.1196  			errorTable[1][i] = loderror;
 89.1197  			continue;
 89.1198  		}
 89.1199  		errorTable[1][i] = grid->heightLodError[oldheight];
 89.1200 -		for (j = 0; j < grid->width; j++) {
 89.1201 +		for(j = 0; j < grid->width; j++)
 89.1202 +		{
 89.1203  			ctrl[i][j] = grid->verts[oldheight * grid->width + j];
 89.1204  		}
 89.1205  		oldheight++;
 89.1206  	}
 89.1207 -	for (j = 0; j < grid->width; j++) {
 89.1208 +	for(j = 0; j < grid->width; j++)
 89.1209 +	{
 89.1210  		errorTable[0][j] = grid->widthLodError[j];
 89.1211  	}
 89.1212  	// put all the aproximating points on the curve
 89.1213  	//PutPointsOnCurve( ctrl, width, height );
 89.1214 +
 89.1215 +	// calculate triangles
 89.1216 +	numTriangles = MakeMeshTriangles(width, height, ctrl, triangles);
 89.1217 +
 89.1218  	// calculate normals
 89.1219 -	MakeMeshNormals( width, height, ctrl );
 89.1220 +	MakeMeshNormals(width, height, ctrl);
 89.1221 +	MakeMeshTangentVectors(width, height, ctrl, numTriangles, triangles);
 89.1222 +
 89.1223 +	// calculate tangent spaces
 89.1224 +	//MakeTangentSpaces(width, height, ctrl, numTriangles, triangles);
 89.1225  
 89.1226  	VectorCopy(grid->lodOrigin, lodOrigin);
 89.1227  	lodRadius = grid->lodRadius;
 89.1228  	// free the old grid
 89.1229  	R_FreeSurfaceGridMesh(grid);
 89.1230  	// create a new grid
 89.1231 -	grid = R_CreateSurfaceGridMesh( width, height, ctrl, errorTable );
 89.1232 +	grid = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
 89.1233  	grid->lodRadius = lodRadius;
 89.1234  	VectorCopy(lodOrigin, grid->lodOrigin);
 89.1235  	return grid;
    90.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.2 +++ b/src/renderer/tr_fbo.c	Wed Jun 10 09:31:46 2009 +0800
    90.3 @@ -0,0 +1,912 @@
    90.4 +/*
    90.5 +===========================================================================
    90.6 +Copyright (C) 2006 Kirk Barnes
    90.7 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    90.8 +
    90.9 +This file is part of XreaL source code.
   90.10 +
   90.11 +XreaL source code is free software; you can redistribute it
   90.12 +and/or modify it under the terms of the GNU General Public License as
   90.13 +published by the Free Software Foundation; either version 2 of the License,
   90.14 +or (at your option) any later version.
   90.15 +
   90.16 +XreaL source code is distributed in the hope that it will be
   90.17 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   90.18 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   90.19 +GNU General Public License for more details.
   90.20 +
   90.21 +You should have received a copy of the GNU General Public License
   90.22 +along with XreaL source code; if not, write to the Free Software
   90.23 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   90.24 +===========================================================================
   90.25 +*/
   90.26 +// tr_fbo.c
   90.27 +#include "tr_local.h"
   90.28 +
   90.29 +/*
   90.30 +=============
   90.31 +R_CheckFBO
   90.32 +=============
   90.33 +*/
   90.34 +qboolean R_CheckFBO(const FBO_t * fbo)
   90.35 +{
   90.36 +	int             code;
   90.37 +	int             id;
   90.38 +
   90.39 +	qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &id);
   90.40 +	qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->frameBuffer);
   90.41 +
   90.42 +	code = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
   90.43 +
   90.44 +	if(code == GL_FRAMEBUFFER_COMPLETE_EXT)
   90.45 +	{
   90.46 +		qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
   90.47 +		return qtrue;
   90.48 +	}
   90.49 +
   90.50 +	// an error occured
   90.51 +	switch (code)
   90.52 +	{
   90.53 +		case GL_FRAMEBUFFER_COMPLETE_EXT:
   90.54 +			break;
   90.55 +
   90.56 +		case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
   90.57 +			ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Unsupported framebuffer format\n", fbo->name);
   90.58 +			break;
   90.59 +
   90.60 +		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
   90.61 +			ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete attachment\n", fbo->name);
   90.62 +			break;
   90.63 +
   90.64 +		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
   90.65 +			ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing attachment\n", fbo->name);
   90.66 +			break;
   90.67 +
   90.68 +			//case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
   90.69 +			//  ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, duplicate attachment\n", fbo->name);
   90.70 +			//  break;
   90.71 +
   90.72 +		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
   90.73 +			ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, attached images must have same dimensions\n",
   90.74 +					  fbo->name);
   90.75 +			break;
   90.76 +
   90.77 +		case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
   90.78 +			ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, attached images must have same format\n",
   90.79 +					  fbo->name);
   90.80 +			break;
   90.81 +
   90.82 +		case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
   90.83 +			ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing draw buffer\n", fbo->name);
   90.84 +			break;
   90.85 +
   90.86 +		case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
   90.87 +			ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing read buffer\n", fbo->name);
   90.88 +			break;
   90.89 +
   90.90 +		default:
   90.91 +			ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) unknown error 0x%X\n", fbo->name, code);
   90.92 +			//ri.Error(ERR_FATAL, "R_CheckFBO: (%s) unknown error 0x%X", fbo->name, code);
   90.93 +			//assert(0);
   90.94 +			break;
   90.95 +	}
   90.96 +
   90.97 +	qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
   90.98 +
   90.99 +	return qfalse;
  90.100 +}
  90.101 +
  90.102 +/*
  90.103 +============
  90.104 +R_CreateFBO
  90.105 +============
  90.106 +*/
  90.107 +FBO_t          *R_CreateFBO(const char *name, int width, int height)
  90.108 +{
  90.109 +	FBO_t          *fbo;
  90.110 +
  90.111 +	if(strlen(name) >= MAX_QPATH)
  90.112 +	{
  90.113 +		ri.Error(ERR_DROP, "R_CreateFBO: \"%s\" is too long\n", name);
  90.114 +	}
  90.115 +
  90.116 +	if(width <= 0 || width > glConfig.maxRenderbufferSize)
  90.117 +	{
  90.118 +		ri.Error(ERR_DROP, "R_CreateFBO: bad width %i", width);
  90.119 +	}
  90.120 +
  90.121 +	if(height <= 0 || height > glConfig.maxRenderbufferSize)
  90.122 +	{
  90.123 +		ri.Error(ERR_DROP, "R_CreateFBO: bad height %i", height);
  90.124 +	}
  90.125 +
  90.126 +	if(tr.numFBOs == MAX_FBOS)
  90.127 +	{
  90.128 +		ri.Error(ERR_DROP, "R_CreateFBO: MAX_FBOS hit");
  90.129 +	}
  90.130 +
  90.131 +	fbo = tr.fbos[tr.numFBOs] = ri.Hunk_Alloc(sizeof(*fbo), h_low);
  90.132 +	Q_strncpyz(fbo->name, name, sizeof(fbo->name));
  90.133 +	fbo->index = tr.numFBOs++;
  90.134 +	fbo->width = width;
  90.135 +	fbo->height = height;
  90.136 +
  90.137 +	qglGenFramebuffersEXT(1, &fbo->frameBuffer);
  90.138 +
  90.139 +	return fbo;
  90.140 +}
  90.141 +
  90.142 +/*
  90.143 +================
  90.144 +R_CreateFBOColorBuffer
  90.145 +
  90.146 +Framebuffer must be bound
  90.147 +================
  90.148 +*/
  90.149 +void R_CreateFBOColorBuffer(FBO_t * fbo, int format, int index)
  90.150 +{
  90.151 +	qboolean        absent;
  90.152 +
  90.153 +	if(index < 0 || index >= glConfig.maxColorAttachments)
  90.154 +	{
  90.155 +		ri.Printf(PRINT_WARNING, "R_CreateFBOColorBuffer: invalid attachment index %i\n", index);
  90.156 +		return;
  90.157 +	}
  90.158 +
  90.159 +#if 0
  90.160 +	if(format != GL_RGB &&
  90.161 +	   format != GL_RGBA &&
  90.162 +	   format != GL_RGB16F_ARB && format != GL_RGBA16F_ARB && format != GL_RGB32F_ARB && format != GL_RGBA32F_ARB)
  90.163 +	{
  90.164 +		ri.Printf(PRINT_WARNING, "R_CreateFBOColorBuffer: format %i is not color-renderable\n", format);
  90.165 +		//return;
  90.166 +	}
  90.167 +#endif
  90.168 +
  90.169 +	fbo->colorFormat = format;
  90.170 +
  90.171 +	absent = fbo->colorBuffers[index] == 0;
  90.172 +	if(absent)
  90.173 +		qglGenRenderbuffersEXT(1, &fbo->colorBuffers[index]);
  90.174 +
  90.175 +	qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->colorBuffers[index]);
  90.176 +	qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, fbo->width, fbo->height);
  90.177 +
  90.178 +	if(absent)
  90.179 +		qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_RENDERBUFFER_EXT,
  90.180 +									  fbo->colorBuffers[index]);
  90.181 +
  90.182 +	GL_CheckErrors();
  90.183 +}
  90.184 +
  90.185 +/*
  90.186 +================
  90.187 +R_CreateFBODepthBuffer
  90.188 +================
  90.189 +*/
  90.190 +void R_CreateFBODepthBuffer(FBO_t * fbo, int format)
  90.191 +{
  90.192 +	qboolean        absent;
  90.193 +
  90.194 +	if(format != GL_DEPTH_COMPONENT &&
  90.195 +	   format != GL_DEPTH_COMPONENT16_ARB && format != GL_DEPTH_COMPONENT24_ARB && format != GL_DEPTH_COMPONENT32_ARB)
  90.196 +	{
  90.197 +		ri.Printf(PRINT_WARNING, "R_CreateFBODepthBuffer: format %i is not depth-renderable\n", format);
  90.198 +		return;
  90.199 +	}
  90.200 +
  90.201 +	fbo->depthFormat = format;
  90.202 +
  90.203 +	absent = fbo->depthBuffer == 0;
  90.204 +	if(absent)
  90.205 +		qglGenRenderbuffersEXT(1, &fbo->depthBuffer);
  90.206 +
  90.207 +	qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->depthBuffer);
  90.208 +	qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, fbo->depthFormat, fbo->width, fbo->height);
  90.209 +
  90.210 +	if(absent)
  90.211 +		qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->depthBuffer);
  90.212 +
  90.213 +	GL_CheckErrors();
  90.214 +}
  90.215 +
  90.216 +/*
  90.217 +================
  90.218 +R_CreateFBOStencilBuffer
  90.219 +================
  90.220 +*/
  90.221 +void R_CreateFBOStencilBuffer(FBO_t * fbo, int format)
  90.222 +{
  90.223 +	qboolean        absent;
  90.224 +
  90.225 +	if(format != GL_STENCIL_INDEX &&
  90.226 +	   //format != GL_STENCIL_INDEX_EXT &&
  90.227 +	   format != GL_STENCIL_INDEX1_EXT &&
  90.228 +	   format != GL_STENCIL_INDEX4_EXT && format != GL_STENCIL_INDEX8_EXT && format != GL_STENCIL_INDEX16_EXT)
  90.229 +	{
  90.230 +		ri.Printf(PRINT_WARNING, "R_CreateFBOStencilBuffer: format %i is not stencil-renderable\n", format);
  90.231 +		return;
  90.232 +	}
  90.233 +
  90.234 +	fbo->stencilFormat = format;
  90.235 +
  90.236 +	absent = fbo->stencilBuffer == 0;
  90.237 +	if(absent)
  90.238 +		qglGenRenderbuffersEXT(1, &fbo->stencilBuffer);
  90.239 +
  90.240 +	qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->stencilBuffer);
  90.241 +	qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, fbo->stencilFormat, fbo->width, fbo->height);
  90.242 +	GL_CheckErrors();
  90.243 +
  90.244 +	if(absent)
  90.245 +		qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->stencilBuffer);
  90.246 +
  90.247 +	GL_CheckErrors();
  90.248 +}
  90.249 +
  90.250 +/*
  90.251 +================
  90.252 +R_CreateFBOPackedDepthStencilBuffer
  90.253 +================
  90.254 +*/
  90.255 +void R_CreateFBOPackedDepthStencilBuffer(FBO_t * fbo, int format)
  90.256 +{
  90.257 +	qboolean        absent;
  90.258 +
  90.259 +	if(format != GL_DEPTH_STENCIL_EXT && format != GL_DEPTH24_STENCIL8_EXT)
  90.260 +	{
  90.261 +		ri.Printf(PRINT_WARNING, "R_CreateFBOPackedDepthStencilBuffer: format %i is not depth-stencil-renderable\n", format);
  90.262 +		return;
  90.263 +	}
  90.264 +
  90.265 +	fbo->packedDepthStencilFormat = format;
  90.266 +
  90.267 +	absent = fbo->packedDepthStencilBuffer == 0;
  90.268 +	if(absent)
  90.269 +		qglGenRenderbuffersEXT(1, &fbo->packedDepthStencilBuffer);
  90.270 +
  90.271 +	qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->packedDepthStencilBuffer);
  90.272 +	qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, fbo->packedDepthStencilFormat, fbo->width, fbo->height);
  90.273 +	GL_CheckErrors();
  90.274 +
  90.275 +	if(absent)
  90.276 +	{
  90.277 +		qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT,
  90.278 +									  fbo->packedDepthStencilBuffer);
  90.279 +		qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT,
  90.280 +									  fbo->packedDepthStencilBuffer);
  90.281 +	}
  90.282 +
  90.283 +	GL_CheckErrors();
  90.284 +}
  90.285 +
  90.286 +
  90.287 +/*
  90.288 +=================
  90.289 +R_AttachFBOTexture1D
  90.290 +=================
  90.291 +*/
  90.292 +void R_AttachFBOTexture1D(int texId, int index)
  90.293 +{
  90.294 +	if(index < 0 || index >= glConfig.maxColorAttachments)
  90.295 +	{
  90.296 +		ri.Printf(PRINT_WARNING, "R_AttachFBOTexture1D: invalid attachment index %i\n", index);
  90.297 +		return;
  90.298 +	}
  90.299 +
  90.300 +	qglFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_1D, texId, 0);
  90.301 +}
  90.302 +
  90.303 +/*
  90.304 +=================
  90.305 +R_AttachFBOTexture2D
  90.306 +=================
  90.307 +*/
  90.308 +void R_AttachFBOTexture2D(int target, int texId, int index)
  90.309 +{
  90.310 +	if(target != GL_TEXTURE_2D && (target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB))
  90.311 +	{
  90.312 +		ri.Printf(PRINT_WARNING, "R_AttachFBOTexture2D: invalid target %i\n", target);
  90.313 +		return;
  90.314 +	}
  90.315 +
  90.316 +	if(index < 0 || index >= glConfig.maxColorAttachments)
  90.317 +	{
  90.318 +		ri.Printf(PRINT_WARNING, "R_AttachFBOTexture2D: invalid attachment index %i\n", index);
  90.319 +		return;
  90.320 +	}
  90.321 +
  90.322 +	qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, target, texId, 0);
  90.323 +}
  90.324 +
  90.325 +/*
  90.326 +=================
  90.327 +R_AttachFBOTexture3D
  90.328 +=================
  90.329 +*/
  90.330 +void R_AttachFBOTexture3D(int texId, int index, int zOffset)
  90.331 +{
  90.332 +	if(index < 0 || index >= glConfig.maxColorAttachments)
  90.333 +	{
  90.334 +		ri.Printf(PRINT_WARNING, "R_AttachFBOTexture3D: invalid attachment index %i\n", index);
  90.335 +		return;
  90.336 +	}
  90.337 +
  90.338 +	qglFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_3D_EXT, texId, 0, zOffset);
  90.339 +}
  90.340 +
  90.341 +/*
  90.342 +=================
  90.343 +R_AttachFBOTextureDepth
  90.344 +=================
  90.345 +*/
  90.346 +void R_AttachFBOTextureDepth(int texId)
  90.347 +{
  90.348 +	qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0);
  90.349 +}
  90.350 +
  90.351 +/*
  90.352 +=================
  90.353 +R_AttachFBOTexturePackedDepthStencil
  90.354 +=================
  90.355 +*/
  90.356 +void R_AttachFBOTexturePackedDepthStencil(int texId)
  90.357 +{
  90.358 +	qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0);
  90.359 +	qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0);
  90.360 +}
  90.361 +
  90.362 +/*
  90.363 +============
  90.364 +R_BindFBO
  90.365 +============
  90.366 +*/
  90.367 +void R_BindFBO(FBO_t * fbo)
  90.368 +{
  90.369 +	if(!fbo)
  90.370 +	{
  90.371 +		R_BindNullFBO();
  90.372 +		return;
  90.373 +	}
  90.374 +
  90.375 +	if(r_logFile->integer)
  90.376 +	{
  90.377 +		// don't just call LogComment, or we will get a call to va() every frame!
  90.378 +		GLimp_LogComment(va("--- R_BindFBO( %s ) ---\n", fbo->name));
  90.379 +	}
  90.380 +
  90.381 +	if(glState.currentFBO != fbo)
  90.382 +	{
  90.383 +		qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->frameBuffer);
  90.384 +
  90.385 +		/*
  90.386 +		   if(fbo->colorBuffers[0])
  90.387 +		   {
  90.388 +		   qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->colorBuffers[0]);
  90.389 +		   }
  90.390 +		 */
  90.391 +
  90.392 +		/*
  90.393 +		   if(fbo->depthBuffer)
  90.394 +		   {
  90.395 +		   qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->depthBuffer);
  90.396 +		   qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->depthBuffer);
  90.397 +		   }
  90.398 +		 */
  90.399 +
  90.400 +		glState.currentFBO = fbo;
  90.401 +	}
  90.402 +}
  90.403 +
  90.404 +/*
  90.405 +============
  90.406 +R_BindNullFBO
  90.407 +============
  90.408 +*/
  90.409 +void R_BindNullFBO(void)
  90.410 +{
  90.411 +	if(r_logFile->integer)
  90.412 +	{
  90.413 +		GLimp_LogComment("--- R_BindNullFBO ---\n");
  90.414 +	}
  90.415 +
  90.416 +	if(glState.currentFBO)
  90.417 +	{
  90.418 +		qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  90.419 +		qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
  90.420 +		glState.currentFBO = NULL;
  90.421 +	}
  90.422 +}
  90.423 +
  90.424 +/*
  90.425 +============
  90.426 +R_InitFBOs
  90.427 +============
  90.428 +*/
  90.429 +void R_InitFBOs(void)
  90.430 +{
  90.431 +	int             i;
  90.432 +	int             width, height;
  90.433 +
  90.434 +	ri.Printf(PRINT_ALL, "------- R_InitFBOs -------\n");
  90.435 +
  90.436 +	if(!glConfig.framebufferObjectAvailable)
  90.437 +		return;
  90.438 +
  90.439 +	tr.numFBOs = 0;
  90.440 +
  90.441 +	GL_CheckErrors();
  90.442 +
  90.443 +	// make sure the render thread is stopped
  90.444 +	R_SyncRenderThread();
  90.445 +
  90.446 +	if(r_deferredShading->integer && glConfig.maxColorAttachments >= 4 && glConfig.textureFloatAvailable &&
  90.447 +	   glConfig.drawBuffersAvailable && glConfig.maxDrawBuffers >= 4)
  90.448 +	{
  90.449 +		// geometricRender FBO as G-Buffer for deferred shading
  90.450 +		GLenum          drawbuffers[] = {
  90.451 +			GL_COLOR_ATTACHMENT0_EXT,
  90.452 +			GL_COLOR_ATTACHMENT1_EXT,
  90.453 +			GL_COLOR_ATTACHMENT2_EXT
  90.454 +			//GL_COLOR_ATTACHMENT3_EXT
  90.455 +			//GL_DEPTH_ATTACHMENT_EXT
  90.456 +		};
  90.457 +
  90.458 +		if(glConfig.textureNPOTAvailable)
  90.459 +		{
  90.460 +			width = glConfig.vidWidth;
  90.461 +			height = glConfig.vidHeight;
  90.462 +		}
  90.463 +		else
  90.464 +		{
  90.465 +			width = NearestPowerOfTwo(glConfig.vidWidth);
  90.466 +			height = NearestPowerOfTwo(glConfig.vidHeight);
  90.467 +		}
  90.468 +
  90.469 +		// deferredRender FBO for the lighting pass
  90.470 +		tr.deferredRenderFBO = R_CreateFBO("_deferredRender", width, height);
  90.471 +		R_BindFBO(tr.deferredRenderFBO);
  90.472 +
  90.473 +		if(r_hdrRendering->integer)
  90.474 +		{
  90.475 +			R_CreateFBOColorBuffer(tr.deferredRenderFBO, GL_RGBA16F_ARB, 0);
  90.476 +		}
  90.477 +		else
  90.478 +		{
  90.479 +			R_CreateFBOColorBuffer(tr.deferredRenderFBO, GL_RGBA, 0);
  90.480 +		}
  90.481 +		R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.deferredRenderFBOImage->texnum, 0);
  90.482 +
  90.483 +		if(glConfig.hardwareType == GLHW_ATI || glConfig.hardwareType == GLHW_ATI_DX10)// || glConfig.hardwareType == GLHW_NV_DX10)
  90.484 +		{
  90.485 +			R_CreateFBODepthBuffer(tr.deferredRenderFBO, GL_DEPTH_COMPONENT16_ARB);
  90.486 +			R_AttachFBOTextureDepth(tr.depthRenderImage->texnum);
  90.487 +		}
  90.488 +		else if(glConfig.framebufferPackedDepthStencilAvailable)
  90.489 +		{
  90.490 +			R_CreateFBOPackedDepthStencilBuffer(tr.deferredRenderFBO, GL_DEPTH24_STENCIL8_EXT);
  90.491 +			R_AttachFBOTexturePackedDepthStencil(tr.depthRenderImage->texnum);
  90.492 +		}
  90.493 +		else
  90.494 +		{
  90.495 +			R_CreateFBODepthBuffer(tr.deferredRenderFBO, GL_DEPTH_COMPONENT24_ARB);
  90.496 +			R_AttachFBOTextureDepth(tr.depthRenderImage->texnum);
  90.497 +		}
  90.498 +
  90.499 +		R_CheckFBO(tr.deferredRenderFBO);
  90.500 +
  90.501 +
  90.502 +
  90.503 +		tr.geometricRenderFBO = R_CreateFBO("_geometricRender", width, height);
  90.504 +		R_BindFBO(tr.geometricRenderFBO);
  90.505 +
  90.506 +		if(r_normalMapping->integer)
  90.507 +		{
  90.508 +			// enable all attachments as draw buffers
  90.509 +			qglDrawBuffersARB(3, drawbuffers);
  90.510 +
  90.511 +			R_CreateFBOColorBuffer(tr.geometricRenderFBO, GL_RGBA, 0);
  90.512 +			R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.deferredDiffuseFBOImage->texnum, 0);
  90.513 +
  90.514 +			R_CreateFBOColorBuffer(tr.geometricRenderFBO, GL_RGBA, 1);
  90.515 +			R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.deferredNormalFBOImage->texnum, 1);
  90.516 +
  90.517 +			R_CreateFBOColorBuffer(tr.geometricRenderFBO, GL_RGBA, 2);
  90.518 +			R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.deferredSpecularFBOImage->texnum, 2);
  90.519 +		}
  90.520 +		else
  90.521 +		{
  90.522 +			// only enable diffuse + normal
  90.523 +			qglDrawBuffersARB(2, drawbuffers);
  90.524 +
  90.525 +			R_CreateFBOColorBuffer(tr.geometricRenderFBO, GL_RGBA, 0);
  90.526 +			R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.deferredDiffuseFBOImage->texnum, 0);
  90.527 +
  90.528 +			R_CreateFBOColorBuffer(tr.geometricRenderFBO, GL_RGBA, 1);
  90.529 +			R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.deferredNormalFBOImage->texnum, 1);
  90.530 +		}
  90.531 +
  90.532 +		// share depth buffer
  90.533 +		tr.geometricRenderFBO->depthFormat = tr.deferredRenderFBO->depthFormat;
  90.534 +		tr.geometricRenderFBO->depthBuffer = tr.deferredRenderFBO->depthBuffer;
  90.535 +
  90.536 +		//qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tr.deferredRenderFBO->depthBuffer);
  90.537 +		//qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, tr.deferredRenderFBO->depthFormat, tr.deferredRenderFBO->width, tr.deferredRenderFBO->height);
  90.538 +
  90.539 +		qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT,
  90.540 +									  tr.geometricRenderFBO->depthBuffer);
  90.541 +
  90.542 +
  90.543 +		if(glConfig.hardwareType == GLHW_ATI || glConfig.hardwareType == GLHW_ATI_DX10)// || glConfig.hardwareType == GLHW_NV_DX10)
  90.544 +		{
  90.545 +			R_AttachFBOTextureDepth(tr.depthRenderImage->texnum);
  90.546 +		}
  90.547 +		else if(glConfig.framebufferPackedDepthStencilAvailable)
  90.548 +		{
  90.549 +			R_AttachFBOTexturePackedDepthStencil(tr.depthRenderImage->texnum);
  90.550 +		}
  90.551 +		else
  90.552 +		{
  90.553 +			R_AttachFBOTextureDepth(tr.depthRenderImage->texnum);
  90.554 +		}
  90.555 +
  90.556 +		R_CheckFBO(tr.geometricRenderFBO);
  90.557 +	}
  90.558 +	else
  90.559 +	{
  90.560 +		// forward shading
  90.561 +
  90.562 +		if(glConfig.textureNPOTAvailable)
  90.563 +		{
  90.564 +			width = glConfig.vidWidth;
  90.565 +			height = glConfig.vidHeight;
  90.566 +		}
  90.567 +		else
  90.568 +		{
  90.569 +			width = NearestPowerOfTwo(glConfig.vidWidth);
  90.570 +			height = NearestPowerOfTwo(glConfig.vidHeight);
  90.571 +		}
  90.572 +
  90.573 +		// deferredRender FBO for the HDR or LDR context
  90.574 +		tr.deferredRenderFBO = R_CreateFBO("_deferredRender", width, height);
  90.575 +		R_BindFBO(tr.deferredRenderFBO);
  90.576 +
  90.577 +		if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
  90.578 +		{
  90.579 +			R_CreateFBOColorBuffer(tr.deferredRenderFBO, GL_RGBA16F_ARB, 0);
  90.580 +		}
  90.581 +		else
  90.582 +		{
  90.583 +			R_CreateFBOColorBuffer(tr.deferredRenderFBO, GL_RGBA, 0);
  90.584 +		}
  90.585 +		R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.deferredRenderFBOImage->texnum, 0);
  90.586 +
  90.587 +		if(glConfig.hardwareType == GLHW_ATI || glConfig.hardwareType == GLHW_ATI_DX10)// || glConfig.hardwareType == GLHW_NV_DX10)
  90.588 +		{
  90.589 +			R_CreateFBODepthBuffer(tr.deferredRenderFBO, GL_DEPTH_COMPONENT16_ARB);
  90.590 +			R_AttachFBOTextureDepth(tr.depthRenderImage->texnum);
  90.591 +		}
  90.592 +		else if(glConfig.framebufferPackedDepthStencilAvailable)
  90.593 +		{
  90.594 +			R_CreateFBOPackedDepthStencilBuffer(tr.deferredRenderFBO, GL_DEPTH24_STENCIL8_EXT);
  90.595 +			R_AttachFBOTexturePackedDepthStencil(tr.depthRenderImage->texnum);
  90.596 +		}
  90.597 +		else
  90.598 +		{
  90.599 +			R_CreateFBODepthBuffer(tr.deferredRenderFBO, GL_DEPTH_COMPONENT24_ARB);
  90.600 +			R_AttachFBOTextureDepth(tr.depthRenderImage->texnum);
  90.601 +		}
  90.602 +		R_CheckFBO(tr.deferredRenderFBO);
  90.603 +	}
  90.604 +
  90.605 +	if(glConfig.framebufferBlitAvailable)
  90.606 +	{
  90.607 +		if(glConfig.textureNPOTAvailable)
  90.608 +		{
  90.609 +			width = glConfig.vidWidth;
  90.610 +			height = glConfig.vidHeight;
  90.611 +		}
  90.612 +		else
  90.613 +		{
  90.614 +			width = NearestPowerOfTwo(glConfig.vidWidth);
  90.615 +			height = NearestPowerOfTwo(glConfig.vidHeight);
  90.616 +		}
  90.617 +
  90.618 +		tr.occlusionRenderFBO = R_CreateFBO("_occlusionRender", width, height);
  90.619 +		R_BindFBO(tr.occlusionRenderFBO);
  90.620 +
  90.621 +		if(glConfig.hardwareType == GLHW_ATI_DX10)
  90.622 +		{
  90.623 +			//R_CreateFBOColorBuffer(tr.occlusionRenderFBO, GL_ALPHA16F_ARB, 0);
  90.624 +			R_CreateFBODepthBuffer(tr.occlusionRenderFBO, GL_DEPTH_COMPONENT16_ARB);
  90.625 +		}
  90.626 +		else if(glConfig.hardwareType == GLHW_NV_DX10)
  90.627 +		{
  90.628 +			//R_CreateFBOColorBuffer(tr.occlusionRenderFBO, GL_ALPHA32F_ARB, 0);
  90.629 +			R_CreateFBODepthBuffer(tr.occlusionRenderFBO, GL_DEPTH_COMPONENT24_ARB);
  90.630 +		}
  90.631 +		else if(glConfig.framebufferPackedDepthStencilAvailable)
  90.632 +		{
  90.633 +			//R_CreateFBOColorBuffer(tr.occlusionRenderFBO, GL_ALPHA32F_ARB, 0);
  90.634 +			R_CreateFBOPackedDepthStencilBuffer(tr.occlusionRenderFBO, GL_DEPTH24_STENCIL8_EXT);
  90.635 +		}
  90.636 +		else
  90.637 +		{
  90.638 +			//R_CreateFBOColorBuffer(tr.occlusionRenderFBO, GL_RGBA, 0);
  90.639 +			R_CreateFBODepthBuffer(tr.occlusionRenderFBO, GL_DEPTH_COMPONENT24_ARB);
  90.640 +		}
  90.641 +
  90.642 +		R_CreateFBOColorBuffer(tr.occlusionRenderFBO, GL_RGBA, 0);
  90.643 +		R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.occlusionRenderFBOImage->texnum, 0);
  90.644 +
  90.645 +		R_CheckFBO(tr.occlusionRenderFBO);
  90.646 +	}
  90.647 +
  90.648 +	if(r_shadows->integer >= 4 && glConfig.textureFloatAvailable)
  90.649 +	{
  90.650 +		// shadowMap FBOs for shadow mapping offscreen rendering
  90.651 +		for(i = 0; i < 5; i++)
  90.652 +		{
  90.653 +			width = height = shadowMapResolutions[i];
  90.654 +
  90.655 +			tr.shadowMapFBO[i] = R_CreateFBO(va("_shadowMap%d", i), width, height);
  90.656 +			R_BindFBO(tr.shadowMapFBO[i]);
  90.657 +
  90.658 +			if(glConfig.hardwareType == GLHW_ATI)
  90.659 +			{
  90.660 +				R_CreateFBOColorBuffer(tr.shadowMapFBO[i], GL_RGBA16, 0);
  90.661 +			}
  90.662 +			else if((glConfig.hardwareType == GLHW_NV_DX10 || glConfig.hardwareType == GLHW_ATI_DX10) && r_shadows->integer == 4)
  90.663 +			{
  90.664 +				R_CreateFBOColorBuffer(tr.shadowMapFBO[i], GL_LUMINANCE_ALPHA16F_ARB, 0);
  90.665 +			}
  90.666 +			else if((glConfig.hardwareType == GLHW_NV_DX10 || glConfig.hardwareType == GLHW_ATI_DX10) && r_shadows->integer == 5)
  90.667 +			{
  90.668 +				R_CreateFBOColorBuffer(tr.shadowMapFBO[i], GL_LUMINANCE_ALPHA32F_ARB, 0);
  90.669 +			}
  90.670 +			else if((glConfig.hardwareType == GLHW_NV_DX10 || glConfig.hardwareType == GLHW_ATI_DX10) && r_shadows->integer == 6)
  90.671 +			{
  90.672 +				R_CreateFBOColorBuffer(tr.shadowMapFBO[i], GL_ALPHA32F_ARB, 0);
  90.673 +			}
  90.674 +			else
  90.675 +			{
  90.676 +				R_CreateFBOColorBuffer(tr.shadowMapFBO[i], GL_RGBA16F_ARB, 0);
  90.677 +			}
  90.678 +
  90.679 +			R_CreateFBODepthBuffer(tr.shadowMapFBO[i], GL_DEPTH_COMPONENT24_ARB);
  90.680 +
  90.681 +			R_CheckFBO(tr.shadowMapFBO[i]);
  90.682 +		}
  90.683 +	}
  90.684 +
  90.685 +	{
  90.686 +		if(glConfig.textureNPOTAvailable)
  90.687 +		{
  90.688 +			width = glConfig.vidWidth;
  90.689 +			height = glConfig.vidHeight;
  90.690 +		}
  90.691 +		else
  90.692 +		{
  90.693 +			width = NearestPowerOfTwo(glConfig.vidWidth);
  90.694 +			height = NearestPowerOfTwo(glConfig.vidHeight);
  90.695 +		}
  90.696 +
  90.697 +		// portalRender FBO for portals, mirrors, water, cameras et cetera
  90.698 +		tr.portalRenderFBO = R_CreateFBO("_portalRender", width, height);
  90.699 +		R_BindFBO(tr.portalRenderFBO);
  90.700 +
  90.701 +		if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
  90.702 +		{
  90.703 +			R_CreateFBOColorBuffer(tr.portalRenderFBO, GL_RGBA16F_ARB, 0);
  90.704 +		}
  90.705 +		else
  90.706 +		{
  90.707 +			R_CreateFBOColorBuffer(tr.portalRenderFBO, GL_RGBA, 0);
  90.708 +		}
  90.709 +		R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.portalRenderImage->texnum, 0);
  90.710 +
  90.711 +		R_CheckFBO(tr.portalRenderFBO);
  90.712 +	}
  90.713 +
  90.714 +
  90.715 +	{
  90.716 +		if(glConfig.textureNPOTAvailable)
  90.717 +		{
  90.718 +			width = glConfig.vidWidth * 0.25f;
  90.719 +			height = glConfig.vidHeight * 0.25f;
  90.720 +		}
  90.721 +		else
  90.722 +		{
  90.723 +			width = NearestPowerOfTwo(glConfig.vidWidth * 0.25f);
  90.724 +			height = NearestPowerOfTwo(glConfig.vidHeight * 0.25f);
  90.725 +		}
  90.726 +
  90.727 +		tr.downScaleFBO_quarter = R_CreateFBO("_downScale_quarter", width, height);
  90.728 +		R_BindFBO(tr.downScaleFBO_quarter);
  90.729 +		if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
  90.730 +		{
  90.731 +			R_CreateFBOColorBuffer(tr.downScaleFBO_quarter, GL_RGBA16F_ARB, 0);
  90.732 +		}
  90.733 +		else
  90.734 +		{
  90.735 +			R_CreateFBOColorBuffer(tr.downScaleFBO_quarter, GL_RGBA, 0);
  90.736 +		}
  90.737 +		R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.downScaleFBOImage_quarter->texnum, 0);
  90.738 +		R_CheckFBO(tr.downScaleFBO_quarter);
  90.739 +
  90.740 +
  90.741 +		tr.downScaleFBO_64x64 = R_CreateFBO("_downScale_64x64", 64, 64);
  90.742 +		R_BindFBO(tr.downScaleFBO_64x64);
  90.743 +		if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
  90.744 +		{
  90.745 +			R_CreateFBOColorBuffer(tr.downScaleFBO_64x64, GL_RGBA16F_ARB, 0);
  90.746 +		}
  90.747 +		else
  90.748 +		{
  90.749 +			R_CreateFBOColorBuffer(tr.downScaleFBO_64x64, GL_RGBA, 0);
  90.750 +		}
  90.751 +		R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.downScaleFBOImage_64x64->texnum, 0);
  90.752 +		R_CheckFBO(tr.downScaleFBO_64x64);
  90.753 +
  90.754 +#if 0
  90.755 +		tr.downScaleFBO_16x16 = R_CreateFBO("_downScale_16x16", 16, 16);
  90.756 +		R_BindFBO(tr.downScaleFBO_16x16);
  90.757 +		if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
  90.758 +		{
  90.759 +			R_CreateFBOColorBuffer(tr.downScaleFBO_16x16, GL_RGBA16F_ARB, 0);
  90.760 +		}
  90.761 +		else
  90.762 +		{
  90.763 +			R_CreateFBOColorBuffer(tr.downScaleFBO_16x16, GL_RGBA, 0);
  90.764 +		}
  90.765 +		R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.downScaleFBOImage_16x16->texnum, 0);
  90.766 +		R_CheckFBO(tr.downScaleFBO_16x16);
  90.767 +
  90.768 +
  90.769 +		tr.downScaleFBO_4x4 = R_CreateFBO("_downScale_4x4", 4, 4);
  90.770 +		R_BindFBO(tr.downScaleFBO_4x4);
  90.771 +		if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
  90.772 +		{
  90.773 +			R_CreateFBOColorBuffer(tr.downScaleFBO_4x4, GL_RGBA16F_ARB, 0);
  90.774 +		}
  90.775 +		else
  90.776 +		{
  90.777 +			R_CreateFBOColorBuffer(tr.downScaleFBO_4x4, GL_RGBA, 0);
  90.778 +		}
  90.779 +		R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.downScaleFBOImage_4x4->texnum, 0);
  90.780 +		R_CheckFBO(tr.downScaleFBO_4x4);
  90.781 +
  90.782 +
  90.783 +		tr.downScaleFBO_1x1 = R_CreateFBO("_downScale_1x1", 1, 1);
  90.784 +		R_BindFBO(tr.downScaleFBO_1x1);
  90.785 +		if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
  90.786 +		{
  90.787 +			R_CreateFBOColorBuffer(tr.downScaleFBO_1x1, GL_RGBA16F_ARB, 0);
  90.788 +		}
  90.789 +		else
  90.790 +		{
  90.791 +			R_CreateFBOColorBuffer(tr.downScaleFBO_1x1, GL_RGBA, 0);
  90.792 +		}
  90.793 +		R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.downScaleFBOImage_1x1->texnum, 0);
  90.794 +		R_CheckFBO(tr.downScaleFBO_1x1);
  90.795 +#endif
  90.796 +
  90.797 +
  90.798 +		if(glConfig.textureNPOTAvailable)
  90.799 +		{
  90.800 +			width = glConfig.vidWidth * 0.25f;
  90.801 +			height = glConfig.vidHeight * 0.25f;
  90.802 +		}
  90.803 +		else
  90.804 +		{
  90.805 +			width = NearestPowerOfTwo(glConfig.vidWidth * 0.25f);
  90.806 +			height = NearestPowerOfTwo(glConfig.vidHeight * 0.25f);
  90.807 +		}
  90.808 +
  90.809 +
  90.810 +		tr.contrastRenderFBO = R_CreateFBO("_contrastRender", width, height);
  90.811 +		R_BindFBO(tr.contrastRenderFBO);
  90.812 +
  90.813 +		if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
  90.814 +		{
  90.815 +			R_CreateFBOColorBuffer(tr.contrastRenderFBO, GL_RGBA16F_ARB, 0);
  90.816 +		}
  90.817 +		else
  90.818 +		{
  90.819 +			R_CreateFBOColorBuffer(tr.contrastRenderFBO, GL_RGBA, 0);
  90.820 +		}
  90.821 +		R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.contrastRenderFBOImage->texnum, 0);
  90.822 +
  90.823 +		R_CheckFBO(tr.contrastRenderFBO);
  90.824 +
  90.825 +
  90.826 +		for(i = 0; i < 2; i++)
  90.827 +		{
  90.828 +			tr.bloomRenderFBO[i] = R_CreateFBO(va("_bloomRender%d", i), width, height);
  90.829 +			R_BindFBO(tr.bloomRenderFBO[i]);
  90.830 +
  90.831 +			if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
  90.832 +			{
  90.833 +				R_CreateFBOColorBuffer(tr.bloomRenderFBO[i], GL_RGBA16F_ARB, 0);
  90.834 +			}
  90.835 +			else
  90.836 +			{
  90.837 +				R_CreateFBOColorBuffer(tr.bloomRenderFBO[i], GL_RGBA, 0);
  90.838 +			}
  90.839 +			R_AttachFBOTexture2D(GL_TEXTURE_2D, tr.bloomRenderFBOImage[i]->texnum, 0);
  90.840 +
  90.841 +			R_CheckFBO(tr.bloomRenderFBO[i]);
  90.842 +		}
  90.843 +	}
  90.844 +
  90.845 +	GL_CheckErrors();
  90.846 +
  90.847 +	R_BindNullFBO();
  90.848 +}
  90.849 +
  90.850 +/*
  90.851 +============
  90.852 +R_ShutdownFBOs
  90.853 +============
  90.854 +*/
  90.855 +void R_ShutdownFBOs(void)
  90.856 +{
  90.857 +	int             i, j;
  90.858 +	FBO_t          *fbo;
  90.859 +
  90.860 +	ri.Printf(PRINT_ALL, "------- R_ShutdownFBOs -------\n");
  90.861 +
  90.862 +	if(!glConfig.framebufferObjectAvailable)
  90.863 +		return;
  90.864 +
  90.865 +	R_BindNullFBO();
  90.866 +
  90.867 +	for(i = 0; i < tr.numFBOs; i++)
  90.868 +	{
  90.869 +		fbo = tr.fbos[i];
  90.870 +
  90.871 +		for(j = 0; j < glConfig.maxColorAttachments; j++)
  90.872 +		{
  90.873 +			if(fbo->colorBuffers[j])
  90.874 +				qglDeleteRenderbuffersEXT(1, &fbo->colorBuffers[j]);
  90.875 +		}
  90.876 +
  90.877 +		if(fbo->depthBuffer)
  90.878 +			qglDeleteRenderbuffersEXT(1, &fbo->depthBuffer);
  90.879 +
  90.880 +		if(fbo->stencilBuffer)
  90.881 +			qglDeleteRenderbuffersEXT(1, &fbo->stencilBuffer);
  90.882 +
  90.883 +		if(fbo->frameBuffer)
  90.884 +			qglDeleteFramebuffersEXT(1, &fbo->frameBuffer);
  90.885 +	}
  90.886 +}
  90.887 +
  90.888 +/*
  90.889 +============
  90.890 +R_FBOList_f
  90.891 +============
  90.892 +*/
  90.893 +void R_FBOList_f(void)
  90.894 +{
  90.895 +	int             i;
  90.896 +	FBO_t          *fbo;
  90.897 +
  90.898 +	if(!glConfig.framebufferObjectAvailable)
  90.899 +	{
  90.900 +		ri.Printf(PRINT_ALL, "GL_EXT_framebuffer_object is not available.\n");
  90.901 +		return;
  90.902 +	}
  90.903 +
  90.904 +	ri.Printf(PRINT_ALL, "             size       name\n");
  90.905 +	ri.Printf(PRINT_ALL, "----------------------------------------------------------\n");
  90.906 +
  90.907 +	for(i = 0; i < tr.numFBOs; i++)
  90.908 +	{
  90.909 +		fbo = tr.fbos[i];
  90.910 +
  90.911 +		ri.Printf(PRINT_ALL, "  %4i: %4i %4i %s\n", i, fbo->width, fbo->height, fbo->name);
  90.912 +	}
  90.913 +
  90.914 +	ri.Printf(PRINT_ALL, " %i FBOs\n", tr.numFBOs);
  90.915 +}
    91.1 --- a/src/renderer/tr_flares.c	Sat Jun 06 03:54:16 2009 +0800
    91.2 +++ b/src/renderer/tr_flares.c	Wed Jun 10 09:31:46 2009 +0800
    91.3 @@ -1,32 +1,30 @@
    91.4  /*
    91.5  ===========================================================================
    91.6  Copyright (C) 1999-2005 Id Software, Inc.
    91.7 -Copyright (C) 2000-2006 Tim Angus
    91.8 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    91.9  
   91.10 -This file is part of Tremfusion.
   91.11 +This file is part of XreaL source code.
   91.12  
   91.13 -Tremfusion is free software; you can redistribute it
   91.14 +XreaL source code is free software; you can redistribute it
   91.15  and/or modify it under the terms of the GNU General Public License as
   91.16  published by the Free Software Foundation; either version 2 of the License,
   91.17  or (at your option) any later version.
   91.18  
   91.19 -Tremfusion is distributed in the hope that it will be
   91.20 +XreaL source code is distributed in the hope that it will be
   91.21  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   91.22  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   91.23  GNU General Public License for more details.
   91.24  
   91.25  You should have received a copy of the GNU General Public License
   91.26 -along with Tremfusion; if not, write to the Free Software
   91.27 +along with XreaL source code; if not, write to the Free Software
   91.28  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   91.29  ===========================================================================
   91.30  */
   91.31  // tr_flares.c
   91.32 -
   91.33  #include "tr_local.h"
   91.34  
   91.35  /*
   91.36  =============================================================================
   91.37 -
   91.38  LIGHT FLARES
   91.39  
   91.40  A light flare is an effect that takes place inside the eye when bright light
   91.41 @@ -51,61 +49,58 @@
   91.42  
   91.43  RB_RenderFlares() will be called once per view (twice in a mirrored scene, potentially
   91.44  up to five or more times in a frame with 3D status bar icons).
   91.45 -
   91.46  =============================================================================
   91.47  */
   91.48  
   91.49 +// flare states maintain visibility over multiple frames for fading layers: view, mirror, menu
   91.50 +typedef struct flare_s
   91.51 +{
   91.52 +	struct flare_s *next;		// for active chain
   91.53  
   91.54 -// flare states maintain visibility over multiple frames for fading
   91.55 -// layers: view, mirror, menu
   91.56 -typedef struct flare_s {
   91.57 -	struct		flare_s	*next;		// for active chain
   91.58 +	int             addedFrame;
   91.59  
   91.60 -	int			addedFrame;
   91.61 +	qboolean        inPortal;	// true if in a portal view of the scene
   91.62 +	int             frameSceneNum;
   91.63 +	void           *surface;
   91.64  
   91.65 -	qboolean	inPortal;				// true if in a portal view of the scene
   91.66 -	int			frameSceneNum;
   91.67 -	void		*surface;
   91.68 -	int			fogNum;
   91.69 +	int             fadeTime;
   91.70  
   91.71 -	int			fadeTime;
   91.72 +	qboolean        visible;	// state of last test
   91.73 +	float           drawIntensity;	// may be non 0 even if !visible due to fading
   91.74  
   91.75 -	qboolean	visible;			// state of last test
   91.76 -	float		drawIntensity;		// may be non 0 even if !visible due to fading
   91.77 +	int             windowX, windowY;
   91.78 +	float           eyeZ;
   91.79  
   91.80 -	int			windowX, windowY;
   91.81 -	float		eyeZ;
   91.82 -
   91.83 -	vec3_t		origin;
   91.84 -	vec3_t		color;
   91.85 +	vec3_t          color;
   91.86  } flare_t;
   91.87  
   91.88 -#define		MAX_FLARES		128
   91.89 +#define			MAX_FLARES 128
   91.90  
   91.91 -flare_t		r_flareStructs[MAX_FLARES];
   91.92 -flare_t		*r_activeFlares, *r_inactiveFlares;
   91.93 +flare_t         r_flareStructs[MAX_FLARES];
   91.94 +flare_t        *r_activeFlares, *r_inactiveFlares;
   91.95  
   91.96 -int flareCoeff;
   91.97 +int             flareCoeff;
   91.98  
   91.99  /*
  91.100  ==================
  91.101  R_ClearFlares
  91.102  ==================
  91.103  */
  91.104 -void R_ClearFlares( void ) {
  91.105 -	int		i;
  91.106 +void R_ClearFlares(void)
  91.107 +{
  91.108 +	int             i;
  91.109  
  91.110 -	Com_Memset( r_flareStructs, 0, sizeof( r_flareStructs ) );
  91.111 +	Com_Memset(r_flareStructs, 0, sizeof(r_flareStructs));
  91.112  	r_activeFlares = NULL;
  91.113  	r_inactiveFlares = NULL;
  91.114  
  91.115 -	for ( i = 0 ; i < MAX_FLARES ; i++ ) {
  91.116 +	for(i = 0; i < MAX_FLARES; i++)
  91.117 +	{
  91.118  		r_flareStructs[i].next = r_inactiveFlares;
  91.119  		r_inactiveFlares = &r_flareStructs[i];
  91.120  	}
  91.121  }
  91.122  
  91.123 -
  91.124  /*
  91.125  ==================
  91.126  RB_AddFlare
  91.127 @@ -113,60 +108,55 @@
  91.128  This is called at surface tesselation time
  91.129  ==================
  91.130  */
  91.131 -void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, vec3_t normal ) {
  91.132 -	int				i;
  91.133 -	flare_t			*f, *oldest;
  91.134 -	vec3_t			local;
  91.135 -	float			d = 1;
  91.136 -	vec4_t			eye, clip, normalized, window;
  91.137 +void RB_AddFlare(void *surface, vec3_t point, vec3_t color, vec3_t normal)
  91.138 +{
  91.139 +	int             i;
  91.140 +	flare_t        *f, *oldest;
  91.141 +	vec3_t          local;
  91.142 +	vec4_t          eye, clip, normalized, window;
  91.143 +	float           distBias = 512.0;
  91.144 +	float           distLerp = 0.5;
  91.145 +	float           d1 = 0.0f, d2 = 0.0f;
  91.146  
  91.147  	backEnd.pc.c_flareAdds++;
  91.148  
  91.149 -	if(normal && (normal[0] || normal[1] || normal[2]))
  91.150 -	{
  91.151 -		VectorSubtract( backEnd.viewParms.or.origin, point, local );
  91.152 -		VectorNormalizeFast(local);
  91.153 -		d = DotProduct(local, normal);
  91.154 -
  91.155 -		// If the viewer is behind the flare don't add it.
  91.156 -		if(d < 0)
  91.157 -			return;
  91.158 -	}
  91.159 -
  91.160  	// if the point is off the screen, don't bother adding it
  91.161  	// calculate screen coordinates and depth
  91.162 -	R_TransformModelToClip( point, backEnd.or.modelMatrix, 
  91.163 -		backEnd.viewParms.projectionMatrix, eye, clip );
  91.164 +	R_TransformModelToClip(point, backEnd.orientation.modelViewMatrix, backEnd.viewParms.projectionMatrix, eye, clip);
  91.165  
  91.166  	// check to see if the point is completely off screen
  91.167 -	for ( i = 0 ; i < 3 ; i++ ) {
  91.168 -		if ( clip[i] >= clip[3] || clip[i] <= -clip[3] ) {
  91.169 +	for(i = 0; i < 3; i++)
  91.170 +	{
  91.171 +		if(clip[i] >= clip[3] || clip[i] <= -clip[3])
  91.172 +		{
  91.173  			return;
  91.174  		}
  91.175  	}
  91.176  
  91.177 -	R_TransformClipToWindow( clip, &backEnd.viewParms, normalized, window );
  91.178 +	R_TransformClipToWindow(clip, &backEnd.viewParms, normalized, window);
  91.179  
  91.180 -	if ( window[0] < 0 || window[0] >= backEnd.viewParms.viewportWidth
  91.181 -		|| window[1] < 0 || window[1] >= backEnd.viewParms.viewportHeight ) {
  91.182 -		return;	// shouldn't happen, since we check the clip[] above, except for FP rounding
  91.183 -	}
  91.184 +	if(window[0] < 0 || window[0] >= backEnd.viewParms.viewportWidth ||
  91.185 +	   window[1] < 0 || window[1] >= backEnd.viewParms.viewportHeight)
  91.186 +		return;					// shouldn't happen, since we check the clip[] above, except for FP rounding
  91.187  
  91.188  	// see if a flare with a matching surface, scene, and view exists
  91.189  	oldest = r_flareStructs;
  91.190 -	for ( f = r_activeFlares ; f ; f = f->next ) {
  91.191 -		if ( f->surface == surface && f->frameSceneNum == backEnd.viewParms.frameSceneNum
  91.192 -			&& f->inPortal == backEnd.viewParms.isPortal ) {
  91.193 +	for(f = r_activeFlares; f; f = f->next)
  91.194 +	{
  91.195 +		if(f->surface == surface && f->frameSceneNum == backEnd.viewParms.frameSceneNum &&
  91.196 +		   f->inPortal == backEnd.viewParms.isPortal)
  91.197  			break;
  91.198 -		}
  91.199  	}
  91.200  
  91.201  	// allocate a new one
  91.202 -	if (!f ) {
  91.203 -		if ( !r_inactiveFlares ) {
  91.204 +	if(!f)
  91.205 +	{
  91.206 +		if(!r_inactiveFlares)
  91.207 +		{
  91.208  			// the list is completely full
  91.209  			return;
  91.210  		}
  91.211 +
  91.212  		f = r_inactiveFlares;
  91.213  		r_inactiveFlares = r_inactiveFlares->next;
  91.214  		f->next = r_activeFlares;
  91.215 @@ -178,20 +168,43 @@
  91.216  		f->addedFrame = -1;
  91.217  	}
  91.218  
  91.219 -	if ( f->addedFrame != backEnd.viewParms.frameCount - 1 ) {
  91.220 +	if(f->addedFrame != backEnd.viewParms.frameCount - 1)
  91.221 +	{
  91.222  		f->visible = qfalse;
  91.223  		f->fadeTime = backEnd.refdef.time - 2000;
  91.224  	}
  91.225  
  91.226  	f->addedFrame = backEnd.viewParms.frameCount;
  91.227 -	f->fogNum = fogNum;
  91.228  
  91.229 -	VectorCopy(point, f->origin);
  91.230 -	VectorCopy( color, f->color );
  91.231 +	VectorCopy(color, f->color);
  91.232 +
  91.233 +	d2 = 0.0;
  91.234 +	d2 = -eye[2];
  91.235 +	if(d2 > distBias)
  91.236 +	{
  91.237 +		if(d2 > (distBias * 2.0))
  91.238 +			d2 = (distBias * 2.0);
  91.239 +		d2 -= distBias;
  91.240 +		d2 = 1.0 - (d2 * (1.0 / distBias));
  91.241 +		d2 *= distLerp;
  91.242 +	}
  91.243 +	else
  91.244 +	{
  91.245 +		d2 = distLerp;
  91.246 +	}
  91.247  
  91.248  	// fade the intensity of the flare down as the
  91.249  	// light surface turns away from the viewer
  91.250 -	VectorScale( f->color, d, f->color ); 
  91.251 +	if(normal)
  91.252 +	{
  91.253 +		VectorSubtract(backEnd.viewParms.orientation.origin, point, local);
  91.254 +		VectorNormalize(local);
  91.255 +		d1 = DotProduct(local, normal);
  91.256 +		d1 *= (1.0 - distLerp);
  91.257 +		d1 += d2;
  91.258 +	}
  91.259 +
  91.260 +	VectorScale(f->color, d1, f->color);
  91.261  
  91.262  	// save info needed to test
  91.263  	f->windowX = backEnd.viewParms.viewportX + window[0];
  91.264 @@ -202,47 +215,24 @@
  91.265  
  91.266  /*
  91.267  ==================
  91.268 -RB_AddDlightFlares
  91.269 +RB_AddLightFlares
  91.270  ==================
  91.271  */
  91.272 -void RB_AddDlightFlares( void ) {
  91.273 -	dlight_t		*l;
  91.274 -	int				i, j, k;
  91.275 -	fog_t			*fog = NULL;
  91.276 +void RB_AddLightFlares(void)
  91.277 +{
  91.278 +	trRefLight_t   *l;
  91.279 +	int             i;
  91.280  
  91.281 -	if ( !r_flares->integer ) {
  91.282 +	if(!r_flares->integer)
  91.283  		return;
  91.284 -	}
  91.285  
  91.286 -	l = backEnd.refdef.dlights;
  91.287 +	l = backEnd.refdef.lights;
  91.288 +	for(i = 0; i < backEnd.refdef.numLights; i++, l++)
  91.289 +	{
  91.290 +		if(!l->isStatic)
  91.291 +			continue;
  91.292  
  91.293 -	if(tr.world)
  91.294 -		fog = tr.world->fogs;
  91.295 -
  91.296 -	for (i=0 ; i<backEnd.refdef.num_dlights ; i++, l++) {
  91.297 -
  91.298 -		if(fog)
  91.299 -		{
  91.300 -			// find which fog volume the light is in 
  91.301 -			for ( j = 1 ; j < tr.world->numfogs ; j++ ) {
  91.302 -				fog = &tr.world->fogs[j];
  91.303 -				for ( k = 0 ; k < 3 ; k++ ) {
  91.304 -					if ( l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k] ) {
  91.305 -						break;
  91.306 -					}
  91.307 -				}
  91.308 -				if ( k == 3 ) {
  91.309 -					break;
  91.310 -				}
  91.311 -			}
  91.312 -			if ( j == tr.world->numfogs ) {
  91.313 -				j = 0;
  91.314 -			}
  91.315 -		}
  91.316 -		else
  91.317 -			j = 0;
  91.318 -
  91.319 -		RB_AddFlare( (void *)l, j, l->origin, l->color, NULL );
  91.320 +		RB_AddFlare((void *)l, l->l.origin, l->l.color, NULL);
  91.321  	}
  91.322  }
  91.323  
  91.324 @@ -259,11 +249,12 @@
  91.325  RB_TestFlare
  91.326  ==================
  91.327  */
  91.328 -void RB_TestFlare( flare_t *f ) {
  91.329 -	float			depth;
  91.330 -	qboolean		visible;
  91.331 -	float			fade;
  91.332 -	float			screenZ;
  91.333 +void RB_TestFlare(flare_t * f)
  91.334 +{
  91.335 +	float           depth;
  91.336 +	qboolean        visible;
  91.337 +	float           fade;
  91.338 +	float           screenZ;
  91.339  
  91.340  	backEnd.pc.c_flareTests++;
  91.341  
  91.342 @@ -272,147 +263,151 @@
  91.343  	glState.finishCalled = qfalse;
  91.344  
  91.345  	// read back the z buffer contents
  91.346 -	qglReadPixels( f->windowX, f->windowY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth );
  91.347 +	qglReadPixels(f->windowX, f->windowY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
  91.348  
  91.349 -	screenZ = backEnd.viewParms.projectionMatrix[14] / 
  91.350 -		( ( 2*depth - 1 ) * backEnd.viewParms.projectionMatrix[11] - backEnd.viewParms.projectionMatrix[10] );
  91.351 +	screenZ = backEnd.viewParms.projectionMatrix[14] /
  91.352 +		((2 * depth - 1) * backEnd.viewParms.projectionMatrix[11] - backEnd.viewParms.projectionMatrix[10]);
  91.353  
  91.354 -	visible = ( -f->eyeZ - -screenZ ) < 24;
  91.355 +	visible = (-f->eyeZ - -screenZ) < 24;
  91.356  
  91.357 -	if ( visible ) {
  91.358 -		if ( !f->visible ) {
  91.359 +	if(visible)
  91.360 +	{
  91.361 +		if(!f->visible)
  91.362 +		{
  91.363  			f->visible = qtrue;
  91.364 -			f->fadeTime = backEnd.refdef.time - 1;
  91.365 +			f->fadeTime = backEnd.refdef.time - 1500;
  91.366  		}
  91.367 -		fade = ( ( backEnd.refdef.time - f->fadeTime ) /1000.0f ) * r_flareFade->value;
  91.368 -	} else {
  91.369 -		if ( f->visible ) {
  91.370 +		fade = ((backEnd.refdef.time - f->fadeTime) / 1000.0f) * r_flareFade->value;
  91.371 +	}
  91.372 +	else
  91.373 +	{
  91.374 +		if(f->visible)
  91.375 +		{
  91.376  			f->visible = qfalse;
  91.377  			f->fadeTime = backEnd.refdef.time - 1;
  91.378  		}
  91.379 -		fade = 1.0f - ( ( backEnd.refdef.time - f->fadeTime ) / 1000.0f ) * r_flareFade->value;
  91.380 +		fade = 1.0f - ((backEnd.refdef.time - f->fadeTime) / 1000.0f) * r_flareFade->value;
  91.381  	}
  91.382  
  91.383 -	if ( fade < 0 ) {
  91.384 +	if(fade < 0)
  91.385 +	{
  91.386  		fade = 0;
  91.387  	}
  91.388 -	if ( fade > 1 ) {
  91.389 +	if(fade > 1)
  91.390 +	{
  91.391  		fade = 1;
  91.392  	}
  91.393  
  91.394  	f->drawIntensity = fade;
  91.395  }
  91.396  
  91.397 -
  91.398  /*
  91.399  ==================
  91.400  RB_RenderFlare
  91.401  ==================
  91.402  */
  91.403 -void RB_RenderFlare( flare_t *f ) {
  91.404 -	float			size;
  91.405 -	vec3_t			color;
  91.406 -	int				iColor[3];
  91.407 -	float distance, intensity, factor;
  91.408 -	byte fogFactors[3] = {255, 255, 255};
  91.409 +void RB_RenderFlare(flare_t * f)
  91.410 +{
  91.411 +	float           size;
  91.412 +	vec3_t          color;
  91.413  
  91.414  	backEnd.pc.c_flareRenders++;
  91.415  
  91.416 -	// We don't want too big values anyways when dividing by distance.
  91.417 +#if 1
  91.418 +	//VectorScale(f->color, f->drawIntensity, color);
  91.419 +	VectorScale(colorWhite, f->drawIntensity, color);
  91.420 +
  91.421 +	size = backEnd.viewParms.viewportWidth * (r_flareSize->value / 640.0f + 8 / -f->eyeZ);
  91.422 +#else
  91.423 +	/*
  91.424 +	   As flare sizes stay nearly constant with increasing distance we must decrease the intensity
  91.425 +	   to achieve a reasonable visual result. The intensity is ~ (size^2 / distance^2) which can be
  91.426 +	   got by considering the ratio of  (flaresurface on screen) : (Surface of sphere defined by flare origin and distance from flare)
  91.427 +	   An important requirement is: intensity <= 1 for all distances.
  91.428 +
  91.429 +	   The formula used here to compute the intensity is as follows:
  91.430 +	   intensity = flareCoeff * size^2 / (distance + size*sqrt(flareCoeff))^2.
  91.431 +	   As you can see, the intensity will have a max. of 1 when the distance is 0.
  91.432 +
  91.433 +	   The coefficient flareCoeff will determine the falloff speed with increasing distance.
  91.434 +	 */
  91.435 +	float           distance, intensity, factor;
  91.436 +
  91.437 +	// We don't want too big values anyways when dividing by distance
  91.438  	if(f->eyeZ > -1.0f)
  91.439  		distance = 1.0f;
  91.440  	else
  91.441  		distance = -f->eyeZ;
  91.442  
  91.443 -	// calculate the flare size..
  91.444 -	size = backEnd.viewParms.viewportWidth * ( r_flareSize->value/640.0f + 8 / distance );
  91.445 -
  91.446 -/*
  91.447 - * This is an alternative to intensity scaling. It changes the size of the flare on screen instead
  91.448 - * with growing distance. See in the description at the top why this is not the way to go.
  91.449 -	// size will change ~ 1/r.
  91.450 -	size = backEnd.viewParms.viewportWidth * (r_flareSize->value / (distance * -2.0f));
  91.451 -*/
  91.452 -
  91.453 -/*
  91.454 - * As flare sizes stay nearly constant with increasing distance we must decrease the intensity
  91.455 - * to achieve a reasonable visual result. The intensity is ~ (size^2 / distance^2) which can be
  91.456 - * got by considering the ratio of
  91.457 - * (flaresurface on screen) : (Surface of sphere defined by flare origin and distance from flare)
  91.458 - * An important requirement is:
  91.459 - * intensity <= 1 for all distances.
  91.460 - *
  91.461 - * The formula used here to compute the intensity is as follows:
  91.462 - * intensity = flareCoeff * size^2 / (distance + size*sqrt(flareCoeff))^2
  91.463 - * As you can see, the intensity will have a max. of 1 when the distance is 0.
  91.464 - * The coefficient flareCoeff will determine the falloff speed with increasing distance.
  91.465 - */
  91.466 +	// calculate the flare size
  91.467 +	size = backEnd.viewParms.viewportWidth * (r_flareSize->value / 640.0f + 8 / distance);
  91.468  
  91.469  	factor = distance + size * sqrt(flareCoeff);
  91.470 -	
  91.471  	intensity = flareCoeff * size * size / (factor * factor);
  91.472  
  91.473  	VectorScale(f->color, f->drawIntensity * intensity, color);
  91.474 +	iColor[0] = color[0] * 255;
  91.475 +	iColor[1] = color[1] * 255;
  91.476 +	iColor[2] = color[2] * 255;
  91.477 +#endif
  91.478  
  91.479 -// Calculations for fogging
  91.480 -	if(tr.world && f->fogNum < tr.world->numfogs)
  91.481 -	{
  91.482 -		tess.numVertexes = 1;
  91.483 -		VectorCopy(f->origin, tess.xyz[0]);
  91.484 -		tess.fogNum = f->fogNum;
  91.485 -	
  91.486 -		RB_CalcModulateColorsByFog(fogFactors);
  91.487 -		
  91.488 -		// We don't need to render the flare if colors are 0 anyways.
  91.489 -		if(!(fogFactors[0] || fogFactors[1] || fogFactors[2]))
  91.490 -			return;
  91.491 -	}
  91.492 -
  91.493 -	iColor[0] = color[0] * fogFactors[0];
  91.494 -	iColor[1] = color[1] * fogFactors[1];
  91.495 -	iColor[2] = color[2] * fogFactors[2];
  91.496 -	
  91.497 -	RB_BeginSurface( tr.flareShader, f->fogNum );
  91.498 +	Tess_Begin(Tess_StageIteratorGeneric, tr.flareShader, NULL, qfalse, qfalse, -1);
  91.499  
  91.500  	// FIXME: use quadstamp?
  91.501  	tess.xyz[tess.numVertexes][0] = f->windowX - size;
  91.502  	tess.xyz[tess.numVertexes][1] = f->windowY - size;
  91.503 -	tess.texCoords[tess.numVertexes][0][0] = 0;
  91.504 -	tess.texCoords[tess.numVertexes][0][1] = 0;
  91.505 -	tess.vertexColors[tess.numVertexes][0] = iColor[0];
  91.506 -	tess.vertexColors[tess.numVertexes][1] = iColor[1];
  91.507 -	tess.vertexColors[tess.numVertexes][2] = iColor[2];
  91.508 -	tess.vertexColors[tess.numVertexes][3] = 255;
  91.509 +	tess.xyz[tess.numVertexes][2] = 0;
  91.510 +	tess.xyz[tess.numVertexes][3] = 1;
  91.511 +	tess.texCoords[tess.numVertexes][0] = 0;
  91.512 +	tess.texCoords[tess.numVertexes][1] = 0;
  91.513 +	tess.texCoords[tess.numVertexes][2] = 0;
  91.514 +	tess.texCoords[tess.numVertexes][3] = 1;
  91.515 +	tess.colors[tess.numVertexes][0] = color[0];
  91.516 +	tess.colors[tess.numVertexes][1] = color[1];
  91.517 +	tess.colors[tess.numVertexes][2] = color[2];
  91.518 +	tess.colors[tess.numVertexes][3] = 1;
  91.519  	tess.numVertexes++;
  91.520  
  91.521  	tess.xyz[tess.numVertexes][0] = f->windowX - size;
  91.522  	tess.xyz[tess.numVertexes][1] = f->windowY + size;
  91.523 -	tess.texCoords[tess.numVertexes][0][0] = 0;
  91.524 -	tess.texCoords[tess.numVertexes][0][1] = 1;
  91.525 -	tess.vertexColors[tess.numVertexes][0] = iColor[0];
  91.526 -	tess.vertexColors[tess.numVertexes][1] = iColor[1];
  91.527 -	tess.vertexColors[tess.numVertexes][2] = iColor[2];
  91.528 -	tess.vertexColors[tess.numVertexes][3] = 255;
  91.529 +	tess.xyz[tess.numVertexes][2] = 0;
  91.530 +	tess.xyz[tess.numVertexes][3] = 1;
  91.531 +	tess.texCoords[tess.numVertexes][0] = 0;
  91.532 +	tess.texCoords[tess.numVertexes][1] = 1;
  91.533 +	tess.texCoords[tess.numVertexes][2] = 0;
  91.534 +	tess.texCoords[tess.numVertexes][3] = 1;
  91.535 +	tess.colors[tess.numVertexes][0] = color[0];
  91.536 +	tess.colors[tess.numVertexes][1] = color[1];
  91.537 +	tess.colors[tess.numVertexes][2] = color[2];
  91.538 +	tess.colors[tess.numVertexes][3] = 1;
  91.539  	tess.numVertexes++;
  91.540  
  91.541  	tess.xyz[tess.numVertexes][0] = f->windowX + size;
  91.542  	tess.xyz[tess.numVertexes][1] = f->windowY + size;
  91.543 -	tess.texCoords[tess.numVertexes][0][0] = 1;
  91.544 -	tess.texCoords[tess.numVertexes][0][1] = 1;
  91.545 -	tess.vertexColors[tess.numVertexes][0] = iColor[0];
  91.546 -	tess.vertexColors[tess.numVertexes][1] = iColor[1];
  91.547 -	tess.vertexColors[tess.numVertexes][2] = iColor[2];
  91.548 -	tess.vertexColors[tess.numVertexes][3] = 255;
  91.549 +	tess.xyz[tess.numVertexes][2] = 0;
  91.550 +	tess.xyz[tess.numVertexes][3] = 1;
  91.551 +	tess.texCoords[tess.numVertexes][0] = 1;
  91.552 +	tess.texCoords[tess.numVertexes][1] = 1;
  91.553 +	tess.texCoords[tess.numVertexes][2] = 0;
  91.554 +	tess.texCoords[tess.numVertexes][3] = 1;
  91.555 +	tess.colors[tess.numVertexes][0] = color[0];
  91.556 +	tess.colors[tess.numVertexes][1] = color[1];
  91.557 +	tess.colors[tess.numVertexes][2] = color[2];
  91.558 +	tess.colors[tess.numVertexes][3] = 1;
  91.559  	tess.numVertexes++;
  91.560  
  91.561  	tess.xyz[tess.numVertexes][0] = f->windowX + size;
  91.562  	tess.xyz[tess.numVertexes][1] = f->windowY - size;
  91.563 -	tess.texCoords[tess.numVertexes][0][0] = 1;
  91.564 -	tess.texCoords[tess.numVertexes][0][1] = 0;
  91.565 -	tess.vertexColors[tess.numVertexes][0] = iColor[0];
  91.566 -	tess.vertexColors[tess.numVertexes][1] = iColor[1];
  91.567 -	tess.vertexColors[tess.numVertexes][2] = iColor[2];
  91.568 -	tess.vertexColors[tess.numVertexes][3] = 255;
  91.569 +	tess.xyz[tess.numVertexes][2] = 0;
  91.570 +	tess.xyz[tess.numVertexes][3] = 1;
  91.571 +	tess.texCoords[tess.numVertexes][0] = 1;
  91.572 +	tess.texCoords[tess.numVertexes][1] = 0;
  91.573 +	tess.texCoords[tess.numVertexes][2] = 0;
  91.574 +	tess.texCoords[tess.numVertexes][3] = 1;
  91.575 +	tess.colors[tess.numVertexes][0] = color[0];
  91.576 +	tess.colors[tess.numVertexes][1] = color[1];
  91.577 +	tess.colors[tess.numVertexes][2] = color[2];
  91.578 +	tess.colors[tess.numVertexes][3] = 1;
  91.579  	tess.numVertexes++;
  91.580  
  91.581  	tess.indexes[tess.numIndexes++] = 0;
  91.582 @@ -422,7 +417,7 @@
  91.583  	tess.indexes[tess.numIndexes++] = 2;
  91.584  	tess.indexes[tess.numIndexes++] = 3;
  91.585  
  91.586 -	RB_EndSurface();
  91.587 +	Tess_End();
  91.588  }
  91.589  
  91.590  /*
  91.591 @@ -441,38 +436,47 @@
  91.592  extend past the portal edge will be overwritten.
  91.593  ==================
  91.594  */
  91.595 -void RB_RenderFlares (void) {
  91.596 -	flare_t		*f;
  91.597 -	flare_t		**prev;
  91.598 -	qboolean	draw;
  91.599 +void RB_RenderFlares(void)
  91.600 +{
  91.601 +	flare_t        *f;
  91.602 +	flare_t       **prev;
  91.603 +	qboolean        draw;
  91.604 +	matrix_t        ortho;
  91.605  
  91.606 -	if ( !r_flares->integer ) {
  91.607 +	if(!r_flares->integer)
  91.608  		return;
  91.609 -	}
  91.610  
  91.611 +#if 0
  91.612  	if(r_flareCoeff->modified)
  91.613  	{
  91.614  		if(r_flareCoeff->value == 0.0f)
  91.615 -			flareCoeff = atof(FLARE_STDCOEFF);
  91.616 +			flareCoeff = atof("150");
  91.617  		else
  91.618  			flareCoeff = r_flareCoeff->value;
  91.619 -			
  91.620 +
  91.621  		r_flareCoeff->modified = qfalse;
  91.622  	}
  91.623 +#endif
  91.624  
  91.625 -	// Reset currentEntity to world so that any previously referenced entities
  91.626 -	// don't have influence on the rendering of these flares (i.e. RF_ renderer flags).
  91.627 +	// reset currentEntity to world so that any previously referenced entities don't have influence
  91.628 +	// on the rendering of these flares (i.e. RF_ renderer flags).
  91.629  	backEnd.currentEntity = &tr.worldEntity;
  91.630 -	backEnd.or = backEnd.viewParms.world;
  91.631 +	backEnd.orientation = backEnd.viewParms.world;
  91.632 +	GL_LoadModelViewMatrix(backEnd.viewParms.world.modelViewMatrix);
  91.633  
  91.634 -//	RB_AddDlightFlares();
  91.635 +	if(tr.world != NULL)		// thx Thilo
  91.636 +	{
  91.637 +		RB_AddLightFlares();
  91.638 +	}
  91.639  
  91.640  	// perform z buffer readback on each flare in this view
  91.641  	draw = qfalse;
  91.642  	prev = &r_activeFlares;
  91.643 -	while ( ( f = *prev ) != NULL ) {
  91.644 +	while((f = *prev) != NULL)
  91.645 +	{
  91.646  		// throw out any flares that weren't added last frame
  91.647 -		if ( f->addedFrame < backEnd.viewParms.frameCount - 1 ) {
  91.648 +		if(f->addedFrame < backEnd.viewParms.frameCount - 1)
  91.649 +		{
  91.650  			*prev = f->next;
  91.651  			f->next = r_inactiveFlares;
  91.652  			r_inactiveFlares = f;
  91.653 @@ -481,12 +485,16 @@
  91.654  
  91.655  		// don't draw any here that aren't from this scene / portal
  91.656  		f->drawIntensity = 0;
  91.657 -		if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum
  91.658 -			&& f->inPortal == backEnd.viewParms.isPortal ) {
  91.659 -			RB_TestFlare( f );
  91.660 -			if ( f->drawIntensity ) {
  91.661 +		if(f->frameSceneNum == backEnd.viewParms.frameSceneNum && f->inPortal == backEnd.viewParms.isPortal)
  91.662 +		{
  91.663 +			RB_TestFlare(f);
  91.664 +
  91.665 +			if(f->drawIntensity)
  91.666 +			{
  91.667  				draw = qtrue;
  91.668 -			} else {
  91.669 +			}
  91.670 +			else
  91.671 +			{
  91.672  				// this flare has completely faded out, so remove it from the chain
  91.673  				*prev = f->next;
  91.674  				f->next = r_inactiveFlares;
  91.675 @@ -498,33 +506,35 @@
  91.676  		prev = &f->next;
  91.677  	}
  91.678  
  91.679 -	if ( !draw ) {
  91.680 -		return;		// none visible
  91.681 +	if(!draw)
  91.682 +	{
  91.683 +		// none visible
  91.684 +		return;
  91.685  	}
  91.686  
  91.687 -	if ( backEnd.viewParms.isPortal ) {
  91.688 -		qglDisable (GL_CLIP_PLANE0);
  91.689 +	if(backEnd.viewParms.isPortal)
  91.690 +	{
  91.691 +		qglDisable(GL_CLIP_PLANE0);
  91.692  	}
  91.693  
  91.694 -	qglPushMatrix();
  91.695 -    qglLoadIdentity();
  91.696 -	qglMatrixMode( GL_PROJECTION );
  91.697 -	qglPushMatrix();
  91.698 -    qglLoadIdentity();
  91.699 -	qglOrtho( backEnd.viewParms.viewportX, backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
  91.700 -			  backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
  91.701 -			  -99999, 99999 );
  91.702 +	GL_CheckErrors();
  91.703  
  91.704 -	for ( f = r_activeFlares ; f ; f = f->next ) {
  91.705 -		if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum
  91.706 -			&& f->inPortal == backEnd.viewParms.isPortal
  91.707 -			&& f->drawIntensity ) {
  91.708 -			RB_RenderFlare( f );
  91.709 -		}
  91.710 +	GL_PushMatrix();
  91.711 +	MatrixSetupOrthogonalProjection(ortho, backEnd.viewParms.viewportX,
  91.712 +									backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
  91.713 +									backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
  91.714 +									-99999, 99999);
  91.715 +	GL_LoadProjectionMatrix(ortho);
  91.716 +	GL_LoadModelViewMatrix(matrixIdentity);
  91.717 +
  91.718 +
  91.719 +	for(f = r_activeFlares; f; f = f->next)
  91.720 +	{
  91.721 +		if(f->frameSceneNum == backEnd.viewParms.frameSceneNum && f->inPortal == backEnd.viewParms.isPortal && f->drawIntensity)
  91.722 +			RB_RenderFlare(f);
  91.723  	}
  91.724  
  91.725 -	qglPopMatrix();
  91.726 -	qglMatrixMode( GL_MODELVIEW );
  91.727 -	qglPopMatrix();
  91.728 +	GL_PopMatrix();
  91.729 +
  91.730 +	GL_CheckErrors();
  91.731  }
  91.732 -
    92.1 --- a/src/renderer/tr_font.c	Sat Jun 06 03:54:16 2009 +0800
    92.2 +++ b/src/renderer/tr_font.c	Wed Jun 10 09:31:46 2009 +0800
    92.3 @@ -529,7 +529,7 @@
    92.4        }
    92.5  
    92.6  			Com_sprintf(name, sizeof(name), "%s_%i_%i.tga", strippedName, imageNumber++, pointSize);
    92.7 -			if(!ri.FS_FileExists(name) && r_saveFontData->integer)  
    92.8 +			if(!ri.FS_FileExists(name) && 0)  
    92.9  			{
   92.10  			  WriteTGA(name, imageBuff, 256, 256);
   92.11  			}
   92.12 @@ -537,7 +537,7 @@
   92.13              /*`image = R_CreateImage(name, imageBuff, 256, 256, IF_NOPICMIP, FT_LINEAR, WT_CLAMP);`*/
   92.14              image = R_CreateImage(name, imageBuff, 256, 256, qfalse, qfalse, GL_CLAMP_TO_EDGE);
   92.15              /*`h = RE_RegisterShaderFromImage(name, image, qfalse);`*/
   92.16 -            h = RE_RegisterShaderFromImage(name, LIGHTMAP_2D, image, qfalse);
   92.17 +            h = RE_RegisterShaderFromImage(name, image, qfalse);
   92.18  			
   92.19  		  Com_Memset(out, 0, 1024*1024);
   92.20        xOut = 0;
   92.21 @@ -577,7 +577,7 @@
   92.22  	Q_strncpyz(font->name, name, sizeof(font->name));
   92.23  	Com_Memcpy(&registeredFont[registeredFontCount++], font, sizeof(fontInfo_t));
   92.24  
   92.25 -	if(!ri.FS_FileExists(name) && r_saveFontData->integer) 
   92.26 +	if(!ri.FS_FileExists(name) && 0) 
   92.27  	{
   92.28          ri.FS_WriteFile(name, font, sizeof(fontInfo_t));
   92.29  	}
    93.1 --- a/src/renderer/tr_image.c	Sat Jun 06 03:54:16 2009 +0800
    93.2 +++ b/src/renderer/tr_image.c	Wed Jun 10 09:31:46 2009 +0800
    93.3 @@ -1,54 +1,60 @@
    93.4  /*
    93.5  ===========================================================================
    93.6  Copyright (C) 1999-2005 Id Software, Inc.
    93.7 -Copyright (C) 2000-2006 Tim Angus
    93.8 -
    93.9 -This file is part of Tremfusion.
   93.10 -
   93.11 -Tremfusion is free software; you can redistribute it
   93.12 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
   93.13 +
   93.14 +This file is part of XreaL source code.
   93.15 +
   93.16 +XreaL source code is free software; you can redistribute it
   93.17  and/or modify it under the terms of the GNU General Public License as
   93.18  published by the Free Software Foundation; either version 2 of the License,
   93.19  or (at your option) any later version.
   93.20  
   93.21 -Tremfusion is distributed in the hope that it will be
   93.22 +XreaL source code is distributed in the hope that it will be
   93.23  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   93.24  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   93.25  GNU General Public License for more details.
   93.26  
   93.27  You should have received a copy of the GNU General Public License
   93.28 -along with Tremfusion; if not, write to the Free Software
   93.29 +along with XreaL source code; if not, write to the Free Software
   93.30  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   93.31  ===========================================================================
   93.32  */
   93.33  // tr_image.c
   93.34  #include "tr_local.h"
   93.35  
   93.36 -static byte			 s_intensitytable[256];
   93.37 +
   93.38 +
   93.39 +
   93.40 +static byte     s_intensitytable[256];
   93.41  static unsigned char s_gammatable[256];
   93.42  
   93.43 -int		gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
   93.44 -int		gl_filter_max = GL_LINEAR;
   93.45 -
   93.46 -#define FILE_HASH_SIZE		1024
   93.47 -static	image_t*		hashTable[FILE_HASH_SIZE];
   93.48 +int             gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
   93.49 +int             gl_filter_max = GL_LINEAR;
   93.50 +
   93.51 +#define FILE_HASH_SIZE		(1024 * 2)
   93.52 +static image_t *hashTable[FILE_HASH_SIZE];
   93.53  
   93.54  /*
   93.55  ** R_GammaCorrect
   93.56  */
   93.57 -void R_GammaCorrect( byte *buffer, int bufSize ) {
   93.58 -	int i;
   93.59 -
   93.60 -	for ( i = 0; i < bufSize; i++ ) {
   93.61 +void R_GammaCorrect(byte * buffer, int bufSize)
   93.62 +{
   93.63 +	int             i;
   93.64 +
   93.65 +	for(i = 0; i < bufSize; i++)
   93.66 +	{
   93.67  		buffer[i] = s_gammatable[buffer[i]];
   93.68  	}
   93.69  }
   93.70  
   93.71 -typedef struct {
   93.72 -	char *name;
   93.73 -	int	minimize, maximize;
   93.74 +typedef struct
   93.75 +{
   93.76 +	char           *name;
   93.77 +	int             minimize, maximize;
   93.78  } textureMode_t;
   93.79  
   93.80 -textureMode_t modes[] = {
   93.81 +textureMode_t   modes[] = {
   93.82  	{"GL_NEAREST", GL_NEAREST, GL_NEAREST},
   93.83  	{"GL_LINEAR", GL_LINEAR, GL_LINEAR},
   93.84  	{"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
   93.85 @@ -57,26 +63,36 @@
   93.86  	{"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
   93.87  };
   93.88  
   93.89 +
   93.90  /*
   93.91  ================
   93.92  return a hash value for the filename
   93.93  ================
   93.94  */
   93.95 -static long generateHashValue( const char *fname ) {
   93.96 -	int		i;
   93.97 -	long	hash;
   93.98 -	char	letter;
   93.99 +static long generateHashValue(const char *fname)
  93.100 +{
  93.101 +	int             i;
  93.102 +	long            hash;
  93.103 +	char            letter;
  93.104 +
  93.105 +//  ri.Printf(PRINT_ALL, "tr_image::generateHashValue: '%s'\n", fname);
  93.106  
  93.107  	hash = 0;
  93.108  	i = 0;
  93.109 -	while (fname[i] != '\0') {
  93.110 +	while(fname[i] != '\0')
  93.111 +	{
  93.112  		letter = tolower(fname[i]);
  93.113 -		if (letter =='.') break;				// don't include extension
  93.114 -		if (letter =='\\') letter = '/';		// damn path names
  93.115 -		hash+=(long)(letter)*(i+119);
  93.116 +
  93.117 +		//if(letter == '.')
  93.118 +		//  break;              // don't include extension
  93.119 +
  93.120 +		if(letter == '\\')
  93.121 +			letter = '/';		// damn path names
  93.122 +
  93.123 +		hash += (long)(letter) * (i + 119);
  93.124  		i++;
  93.125  	}
  93.126 -	hash &= (FILE_HASH_SIZE-1);
  93.127 +	hash &= (FILE_HASH_SIZE - 1);
  93.128  	return hash;
  93.129  }
  93.130  
  93.131 @@ -85,57 +101,57 @@
  93.132  GL_TextureMode
  93.133  ===============
  93.134  */
  93.135 -void GL_TextureMode( const char *string ) {
  93.136 -	int		i;
  93.137 -	image_t	*glt;
  93.138 -
  93.139 -	for ( i=0 ; i< 6 ; i++ ) {
  93.140 -		if ( !Q_stricmp( modes[i].name, string ) ) {
  93.141 +void GL_TextureMode(const char *string)
  93.142 +{
  93.143 +	int             i;
  93.144 +	image_t        *image;
  93.145 +
  93.146 +	for(i = 0; i < 6; i++)
  93.147 +	{
  93.148 +		if(!Q_stricmp(modes[i].name, string))
  93.149 +		{
  93.150  			break;
  93.151  		}
  93.152  	}
  93.153  
  93.154 -	// hack to prevent trilinear from being set on voodoo,
  93.155 -	// because their driver freaks...
  93.156 -	if ( i == 5 && glConfig.hardwareType == GLHW_3DFX_2D3D ) {
  93.157 -		ri.Printf( PRINT_ALL, "Refusing to set trilinear on a voodoo.\n" );
  93.158 -		i = 3;
  93.159 -	}
  93.160 -
  93.161 -
  93.162 -	if ( i == 6 ) {
  93.163 -		ri.Printf (PRINT_ALL, "bad filter name\n");
  93.164 +	if(i == 6)
  93.165 +	{
  93.166 +		ri.Printf(PRINT_ALL, "bad filter name\n");
  93.167  		return;
  93.168  	}
  93.169  
  93.170  	gl_filter_min = modes[i].minimize;
  93.171  	gl_filter_max = modes[i].maximize;
  93.172 -    
  93.173 -    // bound texture anisotropy
  93.174 -    
  93.175 -    if(glConfig.textureFilterAnisotropic)
  93.176 -    {
  93.177 -        if(r_ext_texture_filter_anisotropic->value > glConfig.maxAnisotropy)
  93.178 -        {
  93.179 -            ri.Cvar_Set("r_ext_texture_filter_anisotropic", va("%d", glConfig.maxAnisotropy));
  93.180 -        }
  93.181 -        else if(r_ext_texture_filter_anisotropic->value < 1.0)
  93.182 -        {
  93.183 -             ri.Cvar_Set("r_ext_texture_filter_anisotropic", "1.0");
  93.184 -        }
  93.185 -    }
  93.186 -    
  93.187 +
  93.188 +	// bound texture anisotropy
  93.189 +	if(glConfig.textureAnisotropyAvailable)
  93.190 +	{
  93.191 +		if(r_ext_texture_filter_anisotropic->value > glConfig.maxTextureAnisotropy)
  93.192 +		{
  93.193 +			ri.Cvar_Set("r_ext_texture_filter_anisotropic", va("%f", glConfig.maxTextureAnisotropy));
  93.194 +		}
  93.195 +		else if(r_ext_texture_filter_anisotropic->value < 1.0)
  93.196 +		{
  93.197 +			ri.Cvar_Set("r_ext_texture_filter_anisotropic", "1.0");
  93.198 +		}
  93.199 +	}
  93.200 +
  93.201  	// change all the existing mipmap texture objects
  93.202 -	for ( i = 0 ; i < tr.numImages ; i++ ) {
  93.203 -		glt = tr.images[ i ];
  93.204 -		if ( glt->mipmap ) {
  93.205 -			GL_Bind (glt);
  93.206 -			qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
  93.207 -			qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  93.208 -            
  93.209 -            // set texture anisotropy
  93.210 -            if(glConfig.textureFilterAnisotropic)
  93.211 -                qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_ext_texture_filter_anisotropic->value);
  93.212 +	for(i = 0; i < tr.images.currentElements; i++)
  93.213 +	{
  93.214 +		image = Com_GrowListElement(&tr.images, i);
  93.215 +
  93.216 +		if(image->filterType == FT_DEFAULT)
  93.217 +		{
  93.218 +			GL_Bind(image);
  93.219 +
  93.220 +			// set texture filter
  93.221 +			qglTexParameterf(image->type, GL_TEXTURE_MIN_FILTER, gl_filter_min);
  93.222 +			qglTexParameterf(image->type, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  93.223 +
  93.224 +			// set texture anisotropy
  93.225 +			if(glConfig.textureAnisotropyAvailable)
  93.226 +				qglTexParameterf(image->type, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_ext_texture_filter_anisotropic->value);
  93.227  		}
  93.228  	}
  93.229  }
  93.230 @@ -145,14 +161,20 @@
  93.231  R_SumOfUsedImages
  93.232  ===============
  93.233  */
  93.234 -int R_SumOfUsedImages( void ) {
  93.235 -	int	total;
  93.236 -	int i;
  93.237 +int R_SumOfUsedImages(void)
  93.238 +{
  93.239 +	int             total;
  93.240 +	int             i;
  93.241 +	image_t			*image;
  93.242  
  93.243  	total = 0;
  93.244 -	for ( i = 0; i < tr.numImages; i++ ) {
  93.245 -		if ( tr.images[i]->frameUsed == tr.frameCount ) {
  93.246 -			total += tr.images[i]->uploadWidth * tr.images[i]->uploadHeight;
  93.247 +	for(i = 0; i < tr.images.currentElements; i++)
  93.248 +	{
  93.249 +		image = Com_GrowListElement(&tr.images, i);
  93.250 +
  93.251 +		if(image->frameUsed == tr.frameCount)
  93.252 +		{
  93.253 +			total += image->uploadWidth * image->uploadHeight;
  93.254  		}
  93.255  	}
  93.256  
  93.257 @@ -164,75 +186,194 @@
  93.258  R_ImageList_f
  93.259  ===============
  93.260  */
  93.261 -void R_ImageList_f( void ) {
  93.262 -	int		i;
  93.263 -	image_t	*image;
  93.264 -	int		texels;
  93.265 -	const char *yesno[] = {
  93.266 +void R_ImageList_f(void)
  93.267 +{
  93.268 +	int             i;
  93.269 +	image_t        *image;
  93.270 +	int             texels;
  93.271 +	int             dataSize;
  93.272 +	int				imageDataSize;
  93.273 +	const char     *yesno[] = {
  93.274  		"no ", "yes"
  93.275  	};
  93.276  
  93.277 -	ri.Printf (PRINT_ALL, "\n      -w-- -h-- -mm- -TMU- -if-- wrap --name-------\n");
  93.278 +	ri.Printf(PRINT_ALL, "\n      -w-- -h-- -mm- -type-   -if-- wrap --name-------\n");
  93.279 +
  93.280  	texels = 0;
  93.281 -
  93.282 -	for ( i = 0 ; i < tr.numImages ; i++ ) {
  93.283 -		image = tr.images[ i ];
  93.284 -
  93.285 -		texels += image->uploadWidth*image->uploadHeight;
  93.286 -		ri.Printf (PRINT_ALL,  "%4i: %4i %4i  %s   %d   ",
  93.287 -			i, image->uploadWidth, image->uploadHeight, yesno[image->mipmap], image->TMU );
  93.288 -		switch ( image->internalFormat ) {
  93.289 -		case 1:
  93.290 -			ri.Printf( PRINT_ALL, "I    " );
  93.291 -			break;
  93.292 -		case 2:
  93.293 -			ri.Printf( PRINT_ALL, "IA   " );
  93.294 -			break;
  93.295 -		case 3:
  93.296 -			ri.Printf( PRINT_ALL, "RGB  " );
  93.297 -			break;
  93.298 -		case 4:
  93.299 -			ri.Printf( PRINT_ALL, "RGBA " );
  93.300 -			break;
  93.301 -		case GL_RGBA8:
  93.302 -			ri.Printf( PRINT_ALL, "RGBA8" );
  93.303 -			break;
  93.304 -		case GL_RGB8:
  93.305 -			ri.Printf( PRINT_ALL, "RGB8" );
  93.306 -			break;
  93.307 -		case GL_RGB4_S3TC:
  93.308 -		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
  93.309 -			ri.Printf( PRINT_ALL, "S3TC " );
  93.310 -			break;
  93.311 -		case GL_RGBA4:
  93.312 -			ri.Printf( PRINT_ALL, "RGBA4" );
  93.313 -			break;
  93.314 -		case GL_RGB5:
  93.315 -			ri.Printf( PRINT_ALL, "RGB5 " );
  93.316 -			break;
  93.317 -		default:
  93.318 -			ri.Printf( PRINT_ALL, "???? " );
  93.319 +	dataSize = 0;
  93.320 +
  93.321 +	for(i = 0; i < tr.images.currentElements; i++)
  93.322 +	{
  93.323 +		image = Com_GrowListElement(&tr.images, i);
  93.324 +
  93.325 +		ri.Printf(PRINT_ALL, "%4i: %4i %4i  %s   ",
  93.326 +				  i, image->uploadWidth, image->uploadHeight, yesno[image->filterType == FT_DEFAULT]);
  93.327 +
  93.328 +		switch (image->type)
  93.329 +		{
  93.330 +			case GL_TEXTURE_2D:
  93.331 +				texels += image->uploadWidth * image->uploadHeight;
  93.332 +				imageDataSize = image->uploadWidth * image->uploadHeight;
  93.333 +
  93.334 +				ri.Printf(PRINT_ALL, "2D   ");
  93.335 +				break;
  93.336 +
  93.337 +			case GL_TEXTURE_CUBE_MAP_ARB:
  93.338 +				texels += image->uploadWidth * image->uploadHeight * 6;
  93.339 +				imageDataSize = image->uploadWidth * image->uploadHeight * 6;
  93.340 +
  93.341 +				ri.Printf(PRINT_ALL, "CUBE ");
  93.342 +				break;
  93.343 +
  93.344 +			default:
  93.345 +				ri.Printf(PRINT_ALL, "???? ");
  93.346 +				imageDataSize = image->uploadWidth * image->uploadHeight;
  93.347 +				break;
  93.348  		}
  93.349  
  93.350 -		switch ( image->wrapClampMode ) {
  93.351 -		case GL_REPEAT:
  93.352 -			ri.Printf( PRINT_ALL, "rept " );
  93.353 -			break;
  93.354 -		case GL_CLAMP_TO_EDGE:
  93.355 -			ri.Printf( PRINT_ALL, "clmp " );
  93.356 -			break;
  93.357 -		default:
  93.358 -			ri.Printf( PRINT_ALL, "%4i ", image->wrapClampMode );
  93.359 -			break;
  93.360 +		switch (image->internalFormat)
  93.361 +		{
  93.362 +			case GL_RGB8:
  93.363 +				ri.Printf(PRINT_ALL, "RGB8     ");
  93.364 +				imageDataSize *= 3;
  93.365 +				break;
  93.366 +
  93.367 +			case GL_RGBA8:
  93.368 +				ri.Printf(PRINT_ALL, "RGBA8    ");
  93.369 +				imageDataSize *= 4;
  93.370 +				break;
  93.371 +
  93.372 +			case GL_RGB16:
  93.373 +				ri.Printf(PRINT_ALL, "RGB      ");
  93.374 +				imageDataSize *= 6;
  93.375 +				break;
  93.376 +
  93.377 +			case GL_RGB16F_ARB:
  93.378 +				ri.Printf(PRINT_ALL, "RGB16F   ");
  93.379 +				imageDataSize *= 6;
  93.380 +				break;
  93.381 +
  93.382 +			case GL_RGB32F_ARB:
  93.383 +				ri.Printf(PRINT_ALL, "RGB32F   ");
  93.384 +				imageDataSize *= 12;
  93.385 +				break;
  93.386 +
  93.387 +			case GL_RGBA16F_ARB:
  93.388 +				ri.Printf(PRINT_ALL, "RGBA16F  ");
  93.389 +				imageDataSize *= 8;
  93.390 +				break;
  93.391 +
  93.392 +			case GL_RGBA32F_ARB:
  93.393 +				ri.Printf(PRINT_ALL, "RGBA32F  ");
  93.394 +				imageDataSize *= 16;
  93.395 +				break;
  93.396 +
  93.397 +			case GL_ALPHA16F_ARB:
  93.398 +				ri.Printf(PRINT_ALL, "A16F     ");
  93.399 +				imageDataSize *= 2;
  93.400 +				break;
  93.401 +
  93.402 +			case GL_ALPHA32F_ARB:
  93.403 +				ri.Printf(PRINT_ALL, "A32F     ");
  93.404 +				imageDataSize *= 4;
  93.405 +				break;
  93.406 +
  93.407 +			case GL_LUMINANCE_ALPHA16F_ARB:
  93.408 +				ri.Printf(PRINT_ALL, "LA16F    ");
  93.409 +				imageDataSize *= 4;
  93.410 +				break;
  93.411 +
  93.412 +			case GL_LUMINANCE_ALPHA32F_ARB:
  93.413 +				ri.Printf(PRINT_ALL, "LA32F    ");
  93.414 +				imageDataSize *= 8;
  93.415 +				break;
  93.416 +
  93.417 +			case GL_COMPRESSED_RGBA_ARB:
  93.418 +				ri.Printf(PRINT_ALL, "ARB      ");
  93.419 +				imageDataSize *= 4;	// FIXME
  93.420 +				break;
  93.421 +
  93.422 +			case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
  93.423 +				ri.Printf(PRINT_ALL, "DXT1     ");
  93.424 +				imageDataSize *= 4 / 8;
  93.425 +				break;
  93.426 +
  93.427 +			case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
  93.428 +				ri.Printf(PRINT_ALL, "DXT1a    ");
  93.429 +				imageDataSize *= 4 / 8;
  93.430 +				break;
  93.431 +
  93.432 +			case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
  93.433 +				ri.Printf(PRINT_ALL, "DXT3     ");
  93.434 +				imageDataSize *= 4 / 4;
  93.435 +				break;
  93.436 +
  93.437 +			case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
  93.438 +				ri.Printf(PRINT_ALL, "DXT5     ");
  93.439 +				imageDataSize *= 4 / 4;
  93.440 +				break;
  93.441 +
  93.442 +			case GL_DEPTH_COMPONENT16_ARB:
  93.443 +				ri.Printf(PRINT_ALL, "D16      ");
  93.444 +				imageDataSize *= 2;
  93.445 +				break;
  93.446 +
  93.447 +			case GL_DEPTH_COMPONENT24_ARB:
  93.448 +				ri.Printf(PRINT_ALL, "D24      ");
  93.449 +				imageDataSize *= 3;
  93.450 +				break;
  93.451 +
  93.452 +			case GL_DEPTH_COMPONENT32_ARB:
  93.453 +				ri.Printf(PRINT_ALL, "D32      ");
  93.454 +				imageDataSize *= 4;
  93.455 +				break;
  93.456 +
  93.457 +			default:
  93.458 +				ri.Printf(PRINT_ALL, "????     ");
  93.459 +				imageDataSize *= 4;
  93.460 +				break;
  93.461  		}
  93.462 -		
  93.463 -		ri.Printf( PRINT_ALL, " %s\n", image->imgName );
  93.464 +
  93.465 +		switch (image->wrapType)
  93.466 +		{
  93.467 +			case WT_REPEAT:
  93.468 +				ri.Printf(PRINT_ALL, "rept  ");
  93.469 +				break;
  93.470 +
  93.471 +			case WT_CLAMP:
  93.472 +				ri.Printf(PRINT_ALL, "clmp  ");
  93.473 +				break;
  93.474 +
  93.475 +			case WT_EDGE_CLAMP:
  93.476 +				ri.Printf(PRINT_ALL, "eclmp ");
  93.477 +				break;
  93.478 +
  93.479 +			case WT_ZERO_CLAMP:
  93.480 +				ri.Printf(PRINT_ALL, "zclmp ");
  93.481 +				break;
  93.482 +
  93.483 +			case WT_ALPHA_ZERO_CLAMP:
  93.484 +				ri.Printf(PRINT_ALL, "azclmp");
  93.485 +				break;
  93.486 +
  93.487 +			default:
  93.488 +				ri.Printf(PRINT_ALL, "%4i  ", image->wrapType);
  93.489 +				break;
  93.490 +		}
  93.491 +
  93.492 +		dataSize += imageDataSize;
  93.493 +
  93.494 +		ri.Printf(PRINT_ALL, " %s\n", image->name);
  93.495  	}
  93.496 -	ri.Printf (PRINT_ALL, " ---------\n");
  93.497 -	ri.Printf (PRINT_ALL, " %i total texels (not including mipmaps)\n", texels);
  93.498 -	ri.Printf (PRINT_ALL, " %i total images\n\n", tr.numImages );
  93.499 +	ri.Printf(PRINT_ALL, " ---------\n");
  93.500 +	ri.Printf(PRINT_ALL, " %i total texels (not including mipmaps)\n", texels);
  93.501 +	ri.Printf(PRINT_ALL, " %d.%02d MB total image memory\n", dataSize / (1024 * 1024),
  93.502 +			  (dataSize % (1024 * 1024)) * 100 / (1024 * 1024));
  93.503 +	ri.Printf(PRINT_ALL, " %i total images\n\n", tr.images.currentElements);
  93.504  }
  93.505  
  93.506 +
  93.507 +
  93.508  //=======================================================================
  93.509  
  93.510  /*
  93.511 @@ -244,51 +385,112 @@
  93.512  This will only be filtered properly if the resampled size
  93.513  is greater than half the original size.
  93.514  
  93.515 -If a larger shrinking is needed, use the mipmap function 
  93.516 +If a larger shrinking is needed, use the mipmap function
  93.517  before or after.
  93.518  ================
  93.519  */
  93.520 -static void ResampleTexture( unsigned *in, int inwidth, int inheight, unsigned *out,  
  93.521 -							int outwidth, int outheight ) {
  93.522 -	int		i, j;
  93.523 -	unsigned	*inrow, *inrow2;
  93.524 -	unsigned	frac, fracstep;
  93.525 -	unsigned	p1[2048], p2[2048];
  93.526 -	byte		*pix1, *pix2, *pix3, *pix4;
  93.527 -
  93.528 -	if (outwidth>2048)
  93.529 -		ri.Error(ERR_DROP, "ResampleTexture: max width");
  93.530 -								
  93.531 -	fracstep = inwidth*0x10000/outwidth;
  93.532 -
  93.533 -	frac = fracstep>>2;
  93.534 -	for ( i=0 ; i<outwidth ; i++ ) {
  93.535 -		p1[i] = 4*(frac>>16);
  93.536 +static void ResampleTexture(unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight,
  93.537 +							qboolean normalMap)
  93.538 +{
  93.539 +	int             x, y;
  93.540 +	unsigned       *inrow, *inrow2;
  93.541 +	unsigned        frac, fracstep;
  93.542 +	unsigned        p1[2048], p2[2048];
  93.543 +	byte           *pix1, *pix2, *pix3, *pix4;
  93.544 +	float           inv127 = 1.0f / 127.0f;
  93.545 +	vec3_t          n, n2, n3, n4;
  93.546 +
  93.547 +	// NOTE: Tr3B - limitation not needed anymore
  93.548 +//  if(outwidth > 2048)
  93.549 +//      ri.Error(ERR_DROP, "ResampleTexture: max width");
  93.550 +
  93.551 +	fracstep = inwidth * 0x10000 / outwidth;
  93.552 +
  93.553 +	frac = fracstep >> 2;
  93.554 +	for(x = 0; x < outwidth; x++)
  93.555 +	{
  93.556 +		p1[x] = 4 * (frac >> 16);
  93.557  		frac += fracstep;
  93.558  	}
  93.559 -	frac = 3*(fracstep>>2);
  93.560 -	for ( i=0 ; i<outwidth ; i++ ) {
  93.561 -		p2[i] = 4*(frac>>16);
  93.562 +	frac = 3 * (fracstep >> 2);
  93.563 +	for(x = 0; x < outwidth; x++)
  93.564 +	{
  93.565 +		p2[x] = 4 * (frac >> 16);
  93.566  		frac += fracstep;
  93.567  	}
  93.568  
  93.569 -	for (i=0 ; i<outheight ; i++, out += outwidth) {
  93.570 -		inrow = in + inwidth*(int)((i+0.25)*inheight/outheight);
  93.571 -		inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight);
  93.572 -		frac = fracstep >> 1;
  93.573 -		for (j=0 ; j<outwidth ; j++) {
  93.574 -			pix1 = (byte *)inrow + p1[j];
  93.575 -			pix2 = (byte *)inrow + p2[j];
  93.576 -			pix3 = (byte *)inrow2 + p1[j];
  93.577 -			pix4 = (byte *)inrow2 + p2[j];
  93.578 -			((byte *)(out+j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0])>>2;
  93.579 -			((byte *)(out+j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2;
  93.580 -			((byte *)(out+j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2;
  93.581 -			((byte *)(out+j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2;
  93.582 +	if(normalMap)
  93.583 +	{
  93.584 +		for(y = 0; y < outheight; y++, out += outwidth)
  93.585 +		{
  93.586 +			inrow = in + inwidth * (int)((y + 0.25) * inheight / outheight);
  93.587 +			inrow2 = in + inwidth * (int)((y + 0.75) * inheight / outheight);
  93.588 +
  93.589 +			//frac = fracstep >> 1;
  93.590 +
  93.591 +			for(x = 0; x < outwidth; x++)
  93.592 +			{
  93.593 +				pix1 = (byte *) inrow + p1[x];
  93.594 +				pix2 = (byte *) inrow + p2[x];
  93.595 +				pix3 = (byte *) inrow2 + p1[x];
  93.596 +				pix4 = (byte *) inrow2 + p2[x];
  93.597 +
  93.598 +				n[0] = (pix1[0] * inv127 - 1.0);
  93.599 +				n[1] = (pix1[1] * inv127 - 1.0);
  93.600 +				n[2] = (pix1[2] * inv127 - 1.0);
  93.601 +
  93.602 +				n2[0] = (pix2[0] * inv127 - 1.0);
  93.603 +				n2[1] = (pix2[1] * inv127 - 1.0);
  93.604 +				n2[2] = (pix2[2] * inv127 - 1.0);
  93.605 +
  93.606 +				n3[0] = (pix3[0] * inv127 - 1.0);
  93.607 +				n3[1] = (pix3[1] * inv127 - 1.0);
  93.608 +				n3[2] = (pix3[2] * inv127 - 1.0);
  93.609 +
  93.610 +				n4[0] = (pix4[0] * inv127 - 1.0);
  93.611 +				n4[1] = (pix4[1] * inv127 - 1.0);
  93.612 +				n4[2] = (pix4[2] * inv127 - 1.0);
  93.613 +
  93.614 +				VectorAdd(n, n2, n);
  93.615 +				VectorAdd(n, n3, n);
  93.616 +				VectorAdd(n, n4, n);
  93.617 +
  93.618 +				if(!VectorNormalize(n))
  93.619 +					VectorSet(n, 0, 0, 1);
  93.620 +
  93.621 +				((byte *) (out + x))[0] = (byte) (128 + 127 * n[0]);
  93.622 +				((byte *) (out + x))[1] = (byte) (128 + 127 * n[1]);
  93.623 +				((byte *) (out + x))[2] = (byte) (128 + 127 * n[2]);
  93.624 +				((byte *) (out + x))[3] = (byte) (128 + 127 * 1.0);
  93.625 +			}
  93.626 +		}
  93.627 +	}
  93.628 +	else
  93.629 +	{
  93.630 +		for(y = 0; y < outheight; y++, out += outwidth)
  93.631 +		{
  93.632 +			inrow = in + inwidth * (int)((y + 0.25) * inheight / outheight);
  93.633 +			inrow2 = in + inwidth * (int)((y + 0.75) * inheight / outheight);
  93.634 +
  93.635 +			//frac = fracstep >> 1;
  93.636 +
  93.637 +			for(x = 0; x < outwidth; x++)
  93.638 +			{
  93.639 +				pix1 = (byte *) inrow + p1[x];
  93.640 +				pix2 = (byte *) inrow + p2[x];
  93.641 +				pix3 = (byte *) inrow2 + p1[x];
  93.642 +				pix4 = (byte *) inrow2 + p2[x];
  93.643 +
  93.644 +				((byte *) (out + x))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0]) >> 2;
  93.645 +				((byte *) (out + x))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1]) >> 2;
  93.646 +				((byte *) (out + x))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2]) >> 2;
  93.647 +				((byte *) (out + x))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3]) >> 2;
  93.648 +			}
  93.649  		}
  93.650  	}
  93.651  }
  93.652  
  93.653 +
  93.654  /*
  93.655  ================
  93.656  R_LightScaleTexture
  93.657 @@ -297,19 +499,19 @@
  93.658  lighting range
  93.659  ================
  93.660  */
  93.661 -void R_LightScaleTexture (unsigned *in, int inwidth, int inheight, qboolean only_gamma )
  93.662 +void R_LightScaleTexture(unsigned *in, int inwidth, int inheight, qboolean onlyGamma)
  93.663  {
  93.664 -	if ( only_gamma )
  93.665 +	if(onlyGamma)
  93.666  	{
  93.667 -		if ( !glConfig.deviceSupportsGamma )
  93.668 +		if(!glConfig.deviceSupportsGamma)
  93.669  		{
  93.670 -			int		i, c;
  93.671 -			byte	*p;
  93.672 -
  93.673 -			p = (byte *)in;
  93.674 -
  93.675 -			c = inwidth*inheight;
  93.676 -			for (i=0 ; i<c ; i++, p+=4)
  93.677 +			int             i, c;
  93.678 +			byte           *p;
  93.679 +
  93.680 +			p = (byte *) in;
  93.681 +
  93.682 +			c = inwidth * inheight;
  93.683 +			for(i = 0; i < c; i++, p += 4)
  93.684  			{
  93.685  				p[0] = s_gammatable[p[0]];
  93.686  				p[1] = s_gammatable[p[1]];
  93.687 @@ -319,25 +521,29 @@
  93.688  	}
  93.689  	else
  93.690  	{
  93.691 -		int		i, c;
  93.692 -		byte	*p;
  93.693 -
  93.694 -		p = (byte *)in;
  93.695 -
  93.696 -		c = inwidth*inheight;
  93.697 -
  93.698 -		if ( glConfig.deviceSupportsGamma )
  93.699 +		int             i, c;
  93.700 +		byte           *p;
  93.701 +
  93.702 +		p = (byte *) in;
  93.703 +
  93.704 +		c = inwidth * inheight;
  93.705 +
  93.706 +		if(glConfig.deviceSupportsGamma)
  93.707  		{
  93.708 -			for (i=0 ; i<c ; i++, p+=4)
  93.709 +			// raynorpat: small optimization
  93.710 +			if(r_intensity->value != 1.0f)
  93.711  			{
  93.712 -				p[0] = s_intensitytable[p[0]];
  93.713 -				p[1] = s_intensitytable[p[1]];
  93.714 -				p[2] = s_intensitytable[p[2]];
  93.715 +				for(i = 0; i < c; i++, p += 4)
  93.716 +				{
  93.717 +					p[0] = s_intensitytable[p[0]];
  93.718 +					p[1] = s_intensitytable[p[1]];
  93.719 +					p[2] = s_intensitytable[p[2]];
  93.720 +				}
  93.721  			}
  93.722  		}
  93.723  		else
  93.724  		{
  93.725 -			for (i=0 ; i<c ; i++, p+=4)
  93.726 +			for(i = 0; i < c; i++, p += 4)
  93.727  			{
  93.728  				p[0] = s_gammatable[s_intensitytable[p[0]]];
  93.729  				p[1] = s_gammatable[s_intensitytable[p[1]]];
  93.730 @@ -348,6 +554,7 @@
  93.731  }
  93.732  
  93.733  
  93.734 +
  93.735  /*
  93.736  ================
  93.737  R_MipMap2
  93.738 @@ -356,52 +563,53 @@
  93.739  Proper linear filter
  93.740  ================
  93.741  */
  93.742 -static void R_MipMap2( unsigned *in, int inWidth, int inHeight ) {
  93.743 -	int			i, j, k;
  93.744 -	byte		*outpix;
  93.745 -	int			inWidthMask, inHeightMask;
  93.746 -	int			total;
  93.747 -	int			outWidth, outHeight;
  93.748 -	unsigned	*temp;
  93.749 +static void R_MipMap2(unsigned *in, int inWidth, int inHeight)
  93.750 +{
  93.751 +	int             i, j, k;
  93.752 +	byte           *outpix;
  93.753 +	int             inWidthMask, inHeightMask;
  93.754 +	int             total;
  93.755 +	int             outWidth, outHeight;
  93.756 +	unsigned       *temp;
  93.757  
  93.758  	outWidth = inWidth >> 1;
  93.759  	outHeight = inHeight >> 1;
  93.760 -	temp = ri.Hunk_AllocateTempMemory( outWidth * outHeight * 4 );
  93.761 +	temp = ri.Hunk_AllocateTempMemory(outWidth * outHeight * 4);
  93.762  
  93.763  	inWidthMask = inWidth - 1;
  93.764  	inHeightMask = inHeight - 1;
  93.765  
  93.766 -	for ( i = 0 ; i < outHeight ; i++ ) {
  93.767 -		for ( j = 0 ; j < outWidth ; j++ ) {
  93.768 -			outpix = (byte *) ( temp + i * outWidth + j );
  93.769 -			for ( k = 0 ; k < 4 ; k++ ) {
  93.770 -				total = 
  93.771 -					1 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] +
  93.772 -					2 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] +
  93.773 -					2 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] +
  93.774 -					1 * ((byte *)&in[ ((i*2-1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] +
  93.775 -
  93.776 -					2 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] +
  93.777 -					4 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] +
  93.778 -					4 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] +
  93.779 -					2 * ((byte *)&in[ ((i*2)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] +
  93.780 -
  93.781 -					2 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] +
  93.782 -					4 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] +
  93.783 -					4 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] +
  93.784 -					2 * ((byte *)&in[ ((i*2+1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k] +
  93.785 -
  93.786 -					1 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask) ])[k] +
  93.787 -					2 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2)&inWidthMask) ])[k] +
  93.788 -					2 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask) ])[k] +
  93.789 -					1 * ((byte *)&in[ ((i*2+2)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask) ])[k];
  93.790 +	for(i = 0; i < outHeight; i++)
  93.791 +	{
  93.792 +		for(j = 0; j < outWidth; j++)
  93.793 +		{
  93.794 +			outpix = (byte *) (temp + i * outWidth + j);
  93.795 +			for(k = 0; k < 4; k++)
  93.796 +			{
  93.797 +				total =
  93.798 +					1 * ((byte *) & in[((i * 2 - 1) & inHeightMask) * inWidth + ((j * 2 - 1) & inWidthMask)])[k] +
  93.799 +					2 * ((byte *) & in[((i * 2 - 1) & inHeightMask) * inWidth + ((j * 2) & inWidthMask)])[k] +
  93.800 +					2 * ((byte *) & in[((i * 2 - 1) & inHeightMask) * inWidth + ((j * 2 + 1) & inWidthMask)])[k] +
  93.801 +					1 * ((byte *) & in[((i * 2 - 1) & inHeightMask) * inWidth + ((j * 2 + 2) & inWidthMask)])[k] +
  93.802 +					2 * ((byte *) & in[((i * 2) & inHeightMask) * inWidth + ((j * 2 - 1) & inWidthMask)])[k] +
  93.803 +					4 * ((byte *) & in[((i * 2) & inHeightMask) * inWidth + ((j * 2) & inWidthMask)])[k] +
  93.804 +					4 * ((byte *) & in[((i * 2) & inHeightMask) * inWidth + ((j * 2 + 1) & inWidthMask)])[k] +
  93.805 +					2 * ((byte *) & in[((i * 2) & inHeightMask) * inWidth + ((j * 2 + 2) & inWidthMask)])[k] +
  93.806 +					2 * ((byte *) & in[((i * 2 + 1) & inHeightMask) * inWidth + ((j * 2 - 1) & inWidthMask)])[k] +
  93.807 +					4 * ((byte *) & in[((i * 2 + 1) & inHeightMask) * inWidth + ((j * 2) & inWidthMask)])[k] +
  93.808 +					4 * ((byte *) & in[((i * 2 + 1) & inHeightMask) * inWidth + ((j * 2 + 1) & inWidthMask)])[k] +
  93.809 +					2 * ((byte *) & in[((i * 2 + 1) & inHeightMask) * inWidth + ((j * 2 + 2) & inWidthMask)])[k] +
  93.810 +					1 * ((byte *) & in[((i * 2 + 2) & inHeightMask) * inWidth + ((j * 2 - 1) & inWidthMask)])[k] +
  93.811 +					2 * ((byte *) & in[((i * 2 + 2) & inHeightMask) * inWidth + ((j * 2) & inWidthMask)])[k] +
  93.812 +					2 * ((byte *) & in[((i * 2 + 2) & inHeightMask) * inWidth + ((j * 2 + 1) & inWidthMask)])[k] +
  93.813 +					1 * ((byte *) & in[((i * 2 + 2) & inHeightMask) * inWidth + ((j * 2 + 2) & inWidthMask)])[k];
  93.814  				outpix[k] = total / 36;
  93.815  			}
  93.816  		}
  93.817  	}
  93.818  
  93.819 -	Com_Memcpy( in, temp, outWidth * outHeight * 4 );
  93.820 -	ri.Hunk_FreeTempMemory( temp );
  93.821 +	Com_Memcpy(in, temp, outWidth * outHeight * 4);
  93.822 +	ri.Hunk_FreeTempMemory(temp);
  93.823  }
  93.824  
  93.825  /*
  93.826 @@ -411,17 +619,20 @@
  93.827  Operates in place, quartering the size of the texture
  93.828  ================
  93.829  */
  93.830 -static void R_MipMap (byte *in, int width, int height) {
  93.831 -	int		i, j;
  93.832 -	byte	*out;
  93.833 -	int		row;
  93.834 -
  93.835 -	if ( !r_simpleMipMaps->integer ) {
  93.836 -		R_MipMap2( (unsigned *)in, width, height );
  93.837 +static void R_MipMap(byte * in, int width, int height)
  93.838 +{
  93.839 +	int             i, j;
  93.840 +	byte           *out;
  93.841 +	int             row;
  93.842 +
  93.843 +	if(!r_simpleMipMaps->integer)
  93.844 +	{
  93.845 +		R_MipMap2((unsigned *)in, width, height);
  93.846  		return;
  93.847  	}
  93.848  
  93.849 -	if ( width == 1 && height == 1 ) {
  93.850 +	if(width == 1 && height == 1)
  93.851 +	{
  93.852  		return;
  93.853  	}
  93.854  
  93.855 @@ -430,28 +641,337 @@
  93.856  	width >>= 1;
  93.857  	height >>= 1;
  93.858  
  93.859 -	if ( width == 0 || height == 0 ) {
  93.860 -		width += height;	// get largest
  93.861 -		for (i=0 ; i<width ; i++, out+=4, in+=8 ) {
  93.862 -			out[0] = ( in[0] + in[4] )>>1;
  93.863 -			out[1] = ( in[1] + in[5] )>>1;
  93.864 -			out[2] = ( in[2] + in[6] )>>1;
  93.865 -			out[3] = ( in[3] + in[7] )>>1;
  93.866 +	if(width == 0 || height == 0)
  93.867 +	{
  93.868 +		width += height;		// get largest
  93.869 +		for(i = 0; i < width; i++, out += 4, in += 8)
  93.870 +		{
  93.871 +			out[0] = (in[0] + in[4]) >> 1;
  93.872 +			out[1] = (in[1] + in[5]) >> 1;
  93.873 +			out[2] = (in[2] + in[6]) >> 1;
  93.874 +			out[3] = (in[3] + in[7]) >> 1;
  93.875  		}
  93.876  		return;
  93.877  	}
  93.878  
  93.879 -	for (i=0 ; i<height ; i++, in+=row) {
  93.880 -		for (j=0 ; j<width ; j++, out+=4, in+=8) {
  93.881 -			out[0] = (in[0] + in[4] + in[row+0] + in[row+4])>>2;
  93.882 -			out[1] = (in[1] + in[5] + in[row+1] + in[row+5])>>2;
  93.883 -			out[2] = (in[2] + in[6] + in[row+2] + in[row+6])>>2;
  93.884 -			out[3] = (in[3] + in[7] + in[row+3] + in[row+7])>>2;
  93.885 +	for(i = 0; i < height; i++, in += row)
  93.886 +	{
  93.887 +		for(j = 0; j < width; j++, out += 4, in += 8)
  93.888 +		{
  93.889 +			out[0] = (in[0] + in[4] + in[row + 0] + in[row + 4]) >> 2;
  93.890 +			out[1] = (in[1] + in[5] + in[row + 1] + in[row + 5]) >> 2;
  93.891 +			out[2] = (in[2] + in[6] + in[row + 2] + in[row + 6]) >> 2;
  93.892 +			out[3] = (in[3] + in[7] + in[row + 3] + in[row + 7]) >> 2;
  93.893  		}
  93.894  	}
  93.895  }
  93.896  
  93.897  
  93.898 +
  93.899 +/*
  93.900 +================
  93.901 +R_MipNormalMap
  93.902 +
  93.903 +Operates in place, quartering the size of the texture
  93.904 +================
  93.905 +*/
  93.906 +// *INDENT-OFF*
  93.907 +static void R_MipNormalMap(byte * in, int width, int height)
  93.908 +{
  93.909 +	int             i, j;
  93.910 +	byte           *out;
  93.911 +	vec4_t          n;
  93.912 +	vec_t           length;
  93.913 +
  93.914 +	float			inv255 = 1.0f / 255.0f;
  93.915 +
  93.916 +	if(width == 1 && height == 1)
  93.917 +	{
  93.918 +		return;
  93.919 +	}
  93.920 +
  93.921 +	out = in;
  93.922 +//	width >>= 1;
  93.923 +	width <<= 2;
  93.924 +	height >>= 1;
  93.925 +
  93.926 +	for(i = 0; i < height; i++, in += width)
  93.927 +	{
  93.928 +		for(j = 0; j < width; j += 8, out += 4, in += 8)
  93.929 +		{
  93.930 +			n[0] =	(in[0] * inv255 - 0.5) * 2.0 +
  93.931 +					(in[4] * inv255 - 0.5) * 2.0 +
  93.932 +					(in[width + 0] * inv255 - 0.5) * 2.0 +
  93.933 +					(in[width + 4] * inv255 - 0.5) * 2.0;
  93.934 +
  93.935 +			n[1] =	(in[1] * inv255 - 0.5) * 2.0 +
  93.936 +					(in[5] * inv255 - 0.5) * 2.0 +
  93.937 +					(in[width + 1] * inv255 - 0.5) * 2.0 +
  93.938 +					(in[width + 5] * inv255 - 0.5) * 2.0;
  93.939 +
  93.940 +			n[2] =	(in[2] * inv255 - 0.5) * 2.0 +
  93.941 +					(in[6] * inv255 - 0.5) * 2.0 +
  93.942 +					(in[width + 2] * inv255 - 0.5) * 2.0 +
  93.943 +					(in[width + 6] * inv255 - 0.5) * 2.0;
  93.944 +
  93.945 +			n[3] =	(inv255 * in[3]) +
  93.946 +					(inv255 * in[7]) +
  93.947 +					(inv255 * in[width + 3]) +
  93.948 +					(inv255 * in[width + 7]);
  93.949 +
  93.950 +			length = VectorLength(n);
  93.951 +
  93.952 +			if(length)
  93.953 +			{
  93.954 +				n[0] /= length;
  93.955 +				n[1] /= length;
  93.956 +				n[2] /= length;
  93.957 +			}
  93.958 +			else
  93.959 +			{
  93.960 +				VectorSet(n, 0.0, 0.0, 1.0);
  93.961 +			}
  93.962 +
  93.963 +			out[0] = (byte) (128 + 127 * n[0]);
  93.964 +			out[1] = (byte) (128 + 127 * n[1]);
  93.965 +			out[2] = (byte) (128 + 127 * n[2]);
  93.966 +			out[3] = (byte) (n[3] * 255.0 / 4.0);
  93.967 +			//out[3] = (in[3] + in[7] + in[width + 3] + in[width + 7]) >> 2;
  93.968 +		}
  93.969 +	}
  93.970 +}
  93.971 +// *INDENT-ON*
  93.972 +
  93.973 +static void R_HeightMapToNormalMap(byte * in, int width, int height, float scale)
  93.974 +{
  93.975 +	int             x, y;
  93.976 +	float           r, g, b;
  93.977 +	float           c, cx, cy;
  93.978 +	float           dcx, dcy;
  93.979 +	float           inv255 = 1.0f / 255.0f;
  93.980 +	vec3_t          n;
  93.981 +	byte           *out;
  93.982 +
  93.983 +	out = in;
  93.984 +
  93.985 +	for(y = 0; y < height; y++)
  93.986 +	{
  93.987 +		for(x = 0; x < width; x++)
  93.988 +		{
  93.989 +			// convert the pixel at x, y in the bump map to a normal (float)
  93.990 +
  93.991 +			// expand [0,255] texel values to the [0,1] range
  93.992 +			r = in[4 * (y * width + x) + 0];
  93.993 +			g = in[4 * (y * width + x) + 1];
  93.994 +			b = in[4 * (y * width + x) + 2];
  93.995 +
  93.996 +			c = (r + g + b) * inv255;
  93.997 +
  93.998 +			// expand the texel to its right
  93.999 +			if(x == width - 1)
 93.1000 +			{
 93.1001 +				r = in[4 * (y * width + x) + 0];
 93.1002 +				g = in[4 * (y * width + x) + 1];
 93.1003 +				b = in[4 * (y * width + x) + 2];
 93.1004 +			}
 93.1005 +			else
 93.1006 +			{
 93.1007 +				r = in[4 * (y * width + ((x + 1) % width)) + 0];
 93.1008 +				g = in[4 * (y * width + ((x + 1) % width)) + 1];
 93.1009 +				b = in[4 * (y * width + ((x + 1) % width)) + 2];
 93.1010 +			}
 93.1011 +
 93.1012 +			cx = (r + g + b) * inv255;
 93.1013 +
 93.1014 +			// expand the texel one up
 93.1015 +			if(y == height - 1)
 93.1016 +			{
 93.1017 +				r = in[4 * (y * width + x) + 0];
 93.1018 +				g = in[4 * (y * width + x) + 1];
 93.1019 +				b = in[4 * (y * width + x) + 2];
 93.1020 +			}
 93.1021 +			else
 93.1022 +			{
 93.1023 +				r = in[4 * (((y + 1) % height) * width + x) + 0];
 93.1024 +				g = in[4 * (((y + 1) % height) * width + x) + 1];
 93.1025 +				b = in[4 * (((y + 1) % height) * width + x) + 2];
 93.1026 +			}
 93.1027 +
 93.1028 +			cy = (r + g + b) * inv255;
 93.1029 +
 93.1030 +			dcx = scale * (c - cx);
 93.1031 +			dcy = scale * (c - cy);
 93.1032 +
 93.1033 +			// normalize the vector
 93.1034 +			VectorSet(n, dcx, dcy, 1.0);	//scale);
 93.1035 +			if(!VectorNormalize(n))
 93.1036 +				VectorSet(n, 0, 0, 1);
 93.1037 +
 93.1038 +			// repack the normalized vector into an RGB unsigned byte
 93.1039 +			// vector in the normal map image
 93.1040 +			*out++ = (byte) (128 + 127 * n[0]);
 93.1041 +			*out++ = (byte) (128 + 127 * n[1]);
 93.1042 +			*out++ = (byte) (128 + 127 * n[2]);
 93.1043 +
 93.1044 +			// put in no height as displacement map by default
 93.1045 +			*out++ = (byte) 0;	//(Q_bound(0, c * 255.0 / 3.0, 255));
 93.1046 +		}
 93.1047 +	}
 93.1048 +}
 93.1049 +
 93.1050 +static void R_DisplaceMap(byte * in, byte * in2, int width, int height)
 93.1051 +{
 93.1052 +	int             x, y;
 93.1053 +	vec3_t          n;
 93.1054 +	int             avg;
 93.1055 +	float           inv255 = 1.0f / 255.0f;
 93.1056 +	byte           *out;
 93.1057 +
 93.1058 +	out = in;
 93.1059 +
 93.1060 +	for(y = 0; y < height; y++)
 93.1061 +	{
 93.1062 +		for(x = 0; x < width; x++)
 93.1063 +		{
 93.1064 +			n[0] = (in[4 * (y * width + x) + 0] * inv255 - 0.5) * 2.0;
 93.1065 +			n[1] = (in[4 * (y * width + x) + 1] * inv255 - 0.5) * 2.0;
 93.1066 +			n[2] = (in[4 * (y * width + x) + 2] * inv255 - 0.5) * 2.0;
 93.1067 +
 93.1068 +			avg = 0;
 93.1069 +			avg += in2[4 * (y * width + x) + 0];
 93.1070 +			avg += in2[4 * (y * width + x) + 1];
 93.1071 +			avg += in2[4 * (y * width + x) + 2];
 93.1072 +			avg /= 3;
 93.1073 +
 93.1074 +			*out++ = (byte) (128 + 127 * n[0]);
 93.1075 +			*out++ = (byte) (128 + 127 * n[1]);
 93.1076 +			*out++ = (byte) (128 + 127 * n[2]);
 93.1077 +			*out++ = (byte) (avg);
 93.1078 +		}
 93.1079 +	}
 93.1080 +}
 93.1081 +
 93.1082 +static void R_AddNormals(byte * in, byte * in2, int width, int height)
 93.1083 +{
 93.1084 +	int             x, y;
 93.1085 +	vec3_t          n;
 93.1086 +	byte            a;
 93.1087 +	vec3_t          n2;
 93.1088 +	byte            a2;
 93.1089 +	float           inv255 = 1.0f / 255.0f;
 93.1090 +	byte           *out;
 93.1091 +
 93.1092 +	out = in;
 93.1093 +
 93.1094 +	for(y = 0; y < height; y++)
 93.1095 +	{
 93.1096 +		for(x = 0; x < width; x++)
 93.1097 +		{
 93.1098 +			n[0] = (in[4 * (y * width + x) + 0] * inv255 - 0.5) * 2.0;
 93.1099 +			n[1] = (in[4 * (y * width + x) + 1] * inv255 - 0.5) * 2.0;
 93.1100 +			n[2] = (in[4 * (y * width + x) + 2] * inv255 - 0.5) * 2.0;
 93.1101 +			a = in[4 * (y * width + x) + 3];
 93.1102 +
 93.1103 +			n2[0] = (in2[4 * (y * width + x) + 0] * inv255 - 0.5) * 2.0;
 93.1104 +			n2[1] = (in2[4 * (y * width + x) + 1] * inv255 - 0.5) * 2.0;
 93.1105 +			n2[2] = (in2[4 * (y * width + x) + 2] * inv255 - 0.5) * 2.0;
 93.1106 +			a2 = in2[4 * (y * width + x) + 3];
 93.1107 +
 93.1108 +			VectorAdd(n, n2, n);
 93.1109 +
 93.1110 +			if(!VectorNormalize(n))
 93.1111 +				VectorSet(n, 0, 0, 1);
 93.1112 +
 93.1113 +			*out++ = (byte) (128 + 127 * n[0]);
 93.1114 +			*out++ = (byte) (128 + 127 * n[1]);
 93.1115 +			*out++ = (byte) (128 + 127 * n[2]);
 93.1116 +			*out++ = (byte) (Q_bound(0, a + a2, 255));
 93.1117 +		}
 93.1118 +	}
 93.1119 +}
 93.1120 +
 93.1121 +static void R_InvertAlpha(byte * in, int width, int height)
 93.1122 +{
 93.1123 +	int             x, y;
 93.1124 +	byte           *out;
 93.1125 +
 93.1126 +	out = in;
 93.1127 +
 93.1128 +	for(y = 0; y < height; y++)
 93.1129 +	{
 93.1130 +		for(x = 0; x < width; x++)
 93.1131 +		{
 93.1132 +			out[4 * (y * width + x) + 3] = 255 - in[4 * (y * width + x) + 3];
 93.1133 +		}
 93.1134 +	}
 93.1135 +}
 93.1136 +
 93.1137 +static void R_InvertColor(byte * in, int width, int height)
 93.1138 +{
 93.1139 +	int             x, y;
 93.1140 +	byte           *out;
 93.1141 +
 93.1142 +	out = in;
 93.1143 +
 93.1144 +	for(y = 0; y < height; y++)
 93.1145 +	{
 93.1146 +		for(x = 0; x < width; x++)
 93.1147 +		{
 93.1148 +			out[4 * (y * width + x) + 0] = 255 - in[4 * (y * width + x) + 0];
 93.1149 +			out[4 * (y * width + x) + 1] = 255 - in[4 * (y * width + x) + 1];
 93.1150 +			out[4 * (y * width + x) + 2] = 255 - in[4 * (y * width + x) + 2];
 93.1151 +		}
 93.1152 +	}
 93.1153 +}
 93.1154 +
 93.1155 +static void R_MakeIntensity(byte * in, int width, int height)
 93.1156 +{
 93.1157 +	int             x, y;
 93.1158 +	byte           *out;
 93.1159 +	byte            red;
 93.1160 +
 93.1161 +	out = in;
 93.1162 +
 93.1163 +	for(y = 0; y < height; y++)
 93.1164 +	{
 93.1165 +		for(x = 0; x < width; x++)
 93.1166 +		{
 93.1167 +			red = out[4 * (y * width + x) + 0];
 93.1168 +
 93.1169 +			out[4 * (y * width + x) + 1] = red;
 93.1170 +			out[4 * (y * width + x) + 2] = red;
 93.1171 +			out[4 * (y * width + x) + 3] = red;
 93.1172 +		}
 93.1173 +	}
 93.1174 +}
 93.1175 +
 93.1176 +static void R_MakeAlpha(byte * in, int width, int height)
 93.1177 +{
 93.1178 +	int             x, y;
 93.1179 +	byte           *out;
 93.1180 +	int             avg;
 93.1181 +
 93.1182 +	out = in;
 93.1183 +
 93.1184 +	for(y = 0; y < height; y++)
 93.1185 +	{
 93.1186 +		for(x = 0; x < width; x++)
 93.1187 +		{
 93.1188 +			avg = 0;
 93.1189 +			avg += out[4 * (y * width + x) + 0];
 93.1190 +			avg += out[4 * (y * width + x) + 1];
 93.1191 +			avg += out[4 * (y * width + x) + 2];
 93.1192 +			avg /= 3;
 93.1193 +
 93.1194 +			out[4 * (y * width + x) + 0] = 255;
 93.1195 +			out[4 * (y * width + x) + 1] = 255;
 93.1196 +			out[4 * (y * width + x) + 2] = 255;
 93.1197 +			out[4 * (y * width + x) + 3] = (byte) avg;
 93.1198 +		}
 93.1199 +	}
 93.1200 +}
 93.1201 +
 93.1202 +
 93.1203  /*
 93.1204  ==================
 93.1205  R_BlendOverTexture
 93.1206 @@ -459,905 +979,1053 @@
 93.1207  Apply a color blend over a set of pixels
 93.1208  ==================
 93.1209  */
 93.1210 -static void R_BlendOverTexture( byte *data, int pixelCount, byte blend[4] ) {
 93.1211 -	int		i;
 93.1212 -	int		inverseAlpha;
 93.1213 -	int		premult[3];
 93.1214 +static void R_BlendOverTexture(byte * data, int pixelCount, byte blend[4])
 93.1215 +{
 93.1216 +	int             i;
 93.1217 +	int             inverseAlpha;
 93.1218 +	int             premult[3];
 93.1219  
 93.1220  	inverseAlpha = 255 - blend[3];
 93.1221  	premult[0] = blend[0] * blend[3];
 93.1222  	premult[1] = blend[1] * blend[3];
 93.1223  	premult[2] = blend[2] * blend[3];
 93.1224  
 93.1225 -	for ( i = 0 ; i < pixelCount ; i++, data+=4 ) {
 93.1226 -		data[0] = ( data[0] * inverseAlpha + premult[0] ) >> 9;
 93.1227 -		data[1] = ( data[1] * inverseAlpha + premult[1] ) >> 9;
 93.1228 -		data[2] = ( data[2] * inverseAlpha + premult[2] ) >> 9;
 93.1229 +	for(i = 0; i < pixelCount; i++, data += 4)
 93.1230 +	{
 93.1231 +		data[0] = (data[0] * inverseAlpha + premult[0]) >> 9;
 93.1232 +		data[1] = (data[1] * inverseAlpha + premult[1]) >> 9;
 93.1233 +		data[2] = (data[2] * inverseAlpha + premult[2]) >> 9;
 93.1234  	}
 93.1235  }
 93.1236  
 93.1237 -byte	mipBlendColors[16][4] = {
 93.1238 -	{0,0,0,0},
 93.1239 -	{255,0,0,128},
 93.1240 -	{0,255,0,128},
 93.1241 -	{0,0,255,128},
 93.1242 -	{255,0,0,128},
 93.1243 -	{0,255,0,128},
 93.1244 -	{0,0,255,128},
 93.1245 -	{255,0,0,128},
 93.1246 -	{0,255,0,128},
 93.1247 -	{0,0,255,128},
 93.1248 -	{255,0,0,128},
 93.1249 -	{0,255,0,128},
 93.1250 -	{0,0,255,128},
 93.1251 -	{255,0,0,128},
 93.1252 -	{0,255,0,128},
 93.1253 -	{0,0,255,128},
 93.1254 +
 93.1255 +byte            mipBlendColors[16][4] = {
 93.1256 +	{0, 0, 0, 0}
 93.1257 +	,
 93.1258 +	{255, 0, 0, 128}
 93.1259 +	,
 93.1260 +	{0, 255, 0, 128}
 93.1261 +	,
 93.1262 +	{0, 0, 255, 128}
 93.1263 +	,
 93.1264 +	{255, 0, 0, 128}
 93.1265 +	,
 93.1266 +	{0, 255, 0, 128}
 93.1267 +	,
 93.1268 +	{0, 0, 255, 128}
 93.1269 +	,
 93.1270 +	{255, 0, 0, 128}
 93.1271 +	,
 93.1272 +	{0, 255, 0, 128}
 93.1273 +	,
 93.1274 +	{0, 0, 255, 128}
 93.1275 +	,
 93.1276 +	{255, 0, 0, 128}
 93.1277 +	,
 93.1278 +	{0, 255, 0, 128}
 93.1279 +	,
 93.1280 +	{0, 0, 255, 128}
 93.1281 +	,
 93.1282 +	{255, 0, 0, 128}
 93.1283 +	,
 93.1284 +	{0, 255, 0, 128}
 93.1285 +	,
 93.1286 +	{0, 0, 255, 128}
 93.1287 +	,
 93.1288  };
 93.1289  
 93.1290  
 93.1291  /*
 93.1292  ===============
 93.1293 -Upload32
 93.1294 -
 93.1295 +R_UploadImage
 93.1296  ===============
 93.1297  */
 93.1298 -extern qboolean charSet;
 93.1299 -static void Upload32( unsigned *data, 
 93.1300 -						  int width, int height, 
 93.1301 -						  qboolean mipmap, 
 93.1302 -						  qboolean picmip, 
 93.1303 -							qboolean lightMap,
 93.1304 -						  int *format, 
 93.1305 -						  int *pUploadWidth, int *pUploadHeight )
 93.1306 +void R_UploadImage(const byte ** dataArray, int numData, image_t * image)
 93.1307  {
 93.1308 -	int			samples;
 93.1309 -	unsigned	*scaledBuffer = NULL;
 93.1310 -	unsigned	*resampledBuffer = NULL;
 93.1311 -	int			scaled_width, scaled_height;
 93.1312 -	int			i, c;
 93.1313 -	byte		*scan;
 93.1314 -	GLenum		internalFormat = GL_RGB;
 93.1315 -	float		rMax = 0, gMax = 0, bMax = 0;
 93.1316 -
 93.1317 -	//
 93.1318 -	// convert to exact power of 2 sizes
 93.1319 -	//
 93.1320 -	for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
 93.1321 -		;
 93.1322 -	for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
 93.1323 -		;
 93.1324 -	if ( r_roundImagesDown->integer && scaled_width > width )
 93.1325 -		scaled_width >>= 1;
 93.1326 -	if ( r_roundImagesDown->integer && scaled_height > height )
 93.1327 -		scaled_height >>= 1;
 93.1328 -
 93.1329 -	if ( scaled_width != width || scaled_height != height ) {
 93.1330 -		resampledBuffer = ri.Hunk_AllocateTempMemory( scaled_width * scaled_height * 4 );
 93.1331 -		ResampleTexture (data, width, height, resampledBuffer, scaled_width, scaled_height);
 93.1332 -		data = resampledBuffer;
 93.1333 -		width = scaled_width;
 93.1334 -		height = scaled_height;
 93.1335 +	const byte     *data = dataArray[0];
 93.1336 +	byte           *scaledBuffer = NULL;
 93.1337 +	int             scaledWidth, scaledHeight;
 93.1338 +	int             i, c;
 93.1339 +	const byte     *scan;
 93.1340 +	GLenum          target;
 93.1341 +	GLenum          format = GL_RGBA;
 93.1342 +	GLenum          internalFormat = GL_RGB;
 93.1343 +	float           rMax = 0, gMax = 0, bMax = 0;
 93.1344 +	vec4_t          zeroClampBorder = { 0, 0, 0, 1 };
 93.1345 +	vec4_t          alphaZeroClampBorder = { 0, 0, 0, 0 };
 93.1346 +
 93.1347 +	if(glConfig.textureNPOTAvailable)
 93.1348 +	{
 93.1349 +		scaledWidth = image->width;
 93.1350 +		scaledHeight = image->height;
 93.1351  	}
 93.1352 -
 93.1353 -	//
 93.1354 +	else
 93.1355 +	{
 93.1356 +		// convert to exact power of 2 sizes
 93.1357 +		for(scaledWidth = 1; scaledWidth < image->width; scaledWidth <<= 1)
 93.1358 +			;
 93.1359 +		for(scaledHeight = 1; scaledHeight < image->height; scaledHeight <<= 1)
 93.1360 +			;
 93.1361 +	}
 93.1362 +
 93.1363 +	if(r_roundImagesDown->integer && scaledWidth > image->width)
 93.1364 +		scaledWidth >>= 1;
 93.1365 +	if(r_roundImagesDown->integer && scaledHeight > image->height)
 93.1366 +		scaledHeight >>= 1;
 93.1367 +
 93.1368  	// perform optional picmip operation
 93.1369 -	//
 93.1370 -	if ( picmip ) {
 93.1371 -		scaled_width >>= r_picmip->integer;
 93.1372 -		scaled_height >>= r_picmip->integer;
 93.1373 +	if(!(image->bits & IF_NOPICMIP))
 93.1374 +	{
 93.1375 +		scaledWidth >>= r_picmip->integer;
 93.1376 +		scaledHeight >>= r_picmip->integer;
 93.1377  	}
 93.1378  
 93.1379 -	//
 93.1380  	// clamp to minimum size
 93.1381 -	//
 93.1382 -	if (scaled_width < 1) {
 93.1383 -		scaled_width = 1;
 93.1384 +	if(scaledWidth < 1)
 93.1385 +	{
 93.1386 +		scaledWidth = 1;
 93.1387  	}
 93.1388 -	if (scaled_height < 1) {
 93.1389 -		scaled_height = 1;
 93.1390 +	if(scaledHeight < 1)
 93.1391 +	{
 93.1392 +		scaledHeight = 1;
 93.1393  	}
 93.1394  
 93.1395 -	//
 93.1396  	// clamp to the current upper OpenGL limit
 93.1397  	// scale both axis down equally so we don't have to
 93.1398  	// deal with a half mip resampling
 93.1399 -	//
 93.1400 -	while ( scaled_width > glConfig.maxTextureSize
 93.1401 -		|| scaled_height > glConfig.maxTextureSize ) {
 93.1402 -		scaled_width >>= 1;
 93.1403 -		scaled_height >>= 1;
 93.1404 -	}
 93.1405 -
 93.1406 -	scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height );
 93.1407 -
 93.1408 -	//
 93.1409 -	// scan the texture for each channel's max values
 93.1410 -	// and verify if the alpha channel is being used or not
 93.1411 -	//
 93.1412 -	c = width*height;
 93.1413 -	scan = ((byte *)data);
 93.1414 -	samples = 3;
 93.1415 -
 93.1416 -	if(lightMap)
 93.1417 +	if(image->type == GL_TEXTURE_CUBE_MAP_ARB)
 93.1418  	{
 93.1419 -		if(r_greyscale->integer)
 93.1420 -			internalFormat = GL_LUMINANCE;
 93.1421 -		else
 93.1422 -			internalFormat = GL_RGB;
 93.1423 +		while(scaledWidth > glConfig.maxCubeMapTextureSize || scaledHeight > glConfig.maxCubeMapTextureSize)
 93.1424 +		{
 93.1425 +			scaledWidth >>= 1;
 93.1426 +			scaledHeight >>= 1;
 93.1427 +		}
 93.1428  	}
 93.1429  	else
 93.1430  	{
 93.1431 -		for ( i = 0; i < c; i++ )
 93.1432 +		while(scaledWidth > glConfig.maxTextureSize || scaledHeight > glConfig.maxTextureSize)
 93.1433  		{
 93.1434 -			if ( scan[i*4+0] > rMax )
 93.1435 +			scaledWidth >>= 1;
 93.1436 +			scaledHeight >>= 1;
 93.1437 +		}
 93.1438 +	}
 93.1439 +
 93.1440 +	scaledBuffer = ri.Hunk_AllocateTempMemory(sizeof(byte) * scaledWidth * scaledHeight * 4);
 93.1441 +
 93.1442 +	// set target
 93.1443 +	switch (image->type)
 93.1444 +	{
 93.1445 +		case GL_TEXTURE_CUBE_MAP_ARB:
 93.1446 +			target = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
 93.1447 +			break;
 93.1448 +
 93.1449 +		default:
 93.1450 +			target = GL_TEXTURE_2D;
 93.1451 +			break;
 93.1452 +	}
 93.1453 +
 93.1454 +	// scan the texture for each channel's max values
 93.1455 +	// and verify if the alpha channel is being used or not
 93.1456 +	c = scaledWidth * scaledHeight;
 93.1457 +	scan = data;
 93.1458 +
 93.1459 +	if(image->bits & (IF_DEPTH16 | IF_DEPTH24 | IF_DEPTH32))
 93.1460 +	{
 93.1461 +		format = GL_DEPTH_COMPONENT;
 93.1462 +
 93.1463 +		if(image->bits & IF_DEPTH16)
 93.1464 +		{
 93.1465 +			internalFormat = GL_DEPTH_COMPONENT16_ARB;
 93.1466 +		}
 93.1467 +		else if(image->bits & IF_DEPTH24)
 93.1468 +		{
 93.1469 +			internalFormat = GL_DEPTH_COMPONENT24_ARB;
 93.1470 +		}
 93.1471 +		else if(image->bits & IF_DEPTH32)
 93.1472 +		{
 93.1473 +			internalFormat = GL_DEPTH_COMPONENT32_ARB;
 93.1474 +		}
 93.1475 +	}
 93.1476 +	else if(image->bits & (IF_PACKED_DEPTH24_STENCIL8))
 93.1477 +	{
 93.1478 +		format = GL_DEPTH_STENCIL_EXT;
 93.1479 +		internalFormat = GL_DEPTH24_STENCIL8_EXT;
 93.1480 +	}
 93.1481 +	else if(glConfig.textureFloatAvailable &&
 93.1482 +			(image->bits & (IF_RGBA16F | IF_RGBA32F | IF_RGBA16 | IF_LA16F | IF_LA32F | IF_ALPHA16F | IF_ALPHA32F)))
 93.1483 +	{
 93.1484 +		if(image->bits & IF_RGBA16F)
 93.1485 +		{
 93.1486 +			internalFormat = GL_RGBA16F_ARB;
 93.1487 +		}
 93.1488 +		else if(image->bits & IF_RGBA32F)
 93.1489 +		{
 93.1490 +			internalFormat = GL_RGBA32F_ARB;
 93.1491 +		}
 93.1492 +		else if(image->bits & IF_LA16F)
 93.1493 +		{
 93.1494 +			internalFormat = GL_LUMINANCE_ALPHA16F_ARB;
 93.1495 +		}
 93.1496 +		else if(image->bits & IF_LA32F)
 93.1497 +		{
 93.1498 +			internalFormat = GL_LUMINANCE_ALPHA32F_ARB;
 93.1499 +		}
 93.1500 +		else if(image->bits & IF_RGBA16)
 93.1501 +		{
 93.1502 +			internalFormat = GL_RGBA16;
 93.1503 +		}
 93.1504 +		else if(image->bits & IF_ALPHA16F)
 93.1505 +		{
 93.1506 +			internalFormat = GL_ALPHA16F_ARB;
 93.1507 +		}
 93.1508 +		else if(image->bits & IF_ALPHA32F)
 93.1509 +		{
 93.1510 +			internalFormat = GL_ALPHA32F_ARB;
 93.1511 +		}
 93.1512 +	}
 93.1513 +	else if(image->bits & IF_RGBE)
 93.1514 +	{
 93.1515 +		internalFormat = GL_RGBA8;
 93.1516 +	}
 93.1517 +	else
 93.1518 +	{
 93.1519 +		int             samples;
 93.1520 +
 93.1521 +		samples = 3;
 93.1522 +
 93.1523 +		// Tr3B: normalmaps have the displacement maps in the alpha channel
 93.1524 +		// samples 3 would cause an opaque alpha channel and odd displacements!
 93.1525 +		if(image->bits & IF_NORMALMAP)
 93.1526 +		{
 93.1527 +			if(image->bits & (IF_DISPLACEMAP | IF_ALPHATEST))
 93.1528 +				samples = 4;
 93.1529 +			else
 93.1530 +				samples = 3;
 93.1531 +		}
 93.1532 +		else if(image->bits & IF_LIGHTMAP)
 93.1533 +		{
 93.1534 +			samples = 3;
 93.1535 +		}
 93.1536 +		else
 93.1537 +		{
 93.1538 +			for(i = 0; i < c; i++)
 93.1539  			{
 93.1540 -				rMax = scan[i*4+0];
 93.1541 -			}
 93.1542 -			if ( scan[i*4+1] > gMax )
 93.1543 -			{
 93.1544 -				gMax = scan[i*4+1];
 93.1545 -			}
 93.1546 -			if ( scan[i*4+2] > bMax )
 93.1547 -			{
 93.1548 -				bMax = scan[i*4+2];
 93.1549 -			}
 93.1550 -			if ( scan[i*4 + 3] != 255 ) 
 93.1551 -			{
 93.1552 -				samples = 4;
 93.1553 -				break;
 93.1554 +				if(scan[i * 4 + 0] > rMax)
 93.1555 +				{
 93.1556 +					rMax = scan[i * 4 + 0];
 93.1557 +				}
 93.1558 +				if(scan[i * 4 + 1] > gMax)
 93.1559 +				{
 93.1560 +					gMax = scan[i * 4 + 1];
 93.1561 +				}
 93.1562 +				if(scan[i * 4 + 2] > bMax)
 93.1563 +				{
 93.1564 +					bMax = scan[i * 4 + 2];
 93.1565 +				}
 93.1566 +				if(scan[i * 4 + 3] != 255)
 93.1567 +				{
 93.1568 +					samples = 4;
 93.1569 +					break;
 93.1570 +				}
 93.1571  			}
 93.1572  		}
 93.1573 +
 93.1574  		// select proper internal format
 93.1575 -		if ( samples == 3 )
 93.1576 +		if(samples == 3)
 93.1577  		{
 93.1578 -			if(r_greyscale->integer)
 93.1579 +			if(glConfig.textureCompression == TC_S3TC && !(image->bits & IF_NOCOMPRESSION))
 93.1580  			{
 93.1581 -				if(r_texturebits->integer == 16)
 93.1582 -					internalFormat = GL_LUMINANCE8;
 93.1583 -				else if(r_texturebits->integer == 32)
 93.1584 -					internalFormat = GL_LUMINANCE16;
 93.1585 -				else
 93.1586 -					internalFormat = GL_LUMINANCE;
 93.1587 +				internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
 93.1588  			}
 93.1589  			else
 93.1590  			{
 93.1591 -				if ( glConfig.textureCompression == TC_S3TC_ARB )
 93.1592 +				internalFormat = GL_RGB8;
 93.1593 +			}
 93.1594 +		}
 93.1595 +		else if(samples == 4)
 93.1596 +		{
 93.1597 +			if(image->bits & IF_INTENSITY)
 93.1598 +			{
 93.1599 +				internalFormat = GL_INTENSITY8;
 93.1600 +			}
 93.1601 +			else if(image->bits & IF_ALPHA)
 93.1602 +			{
 93.1603 +				internalFormat = GL_ALPHA8;
 93.1604 +			}
 93.1605 +			else
 93.1606 +			{
 93.1607 +				if(glConfig.textureCompression == TC_S3TC && !(image->bits & IF_NOCOMPRESSION))
 93.1608  				{
 93.1609 -					internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
 93.1610 -				}
 93.1611 -				else if ( glConfig.textureCompression == TC_S3TC )
 93.1612 -				{
 93.1613 -					internalFormat = GL_RGB4_S3TC;
 93.1614 -				}
 93.1615 -				else if ( r_texturebits->integer == 16 )
 93.1616 -				{
 93.1617 -					internalFormat = GL_RGB5;
 93.1618 -				}
 93.1619 -				else if ( r_texturebits->integer == 32 )
 93.1620 -				{
 93.1621 -					internalFormat = GL_RGB8;
 93.1622 +					if(image->bits & IF_DISPLACEMAP)
 93.1623 +					{
 93.1624 +						internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
 93.1625 +					}
 93.1626 +					else if(image->bits & IF_ALPHATEST)
 93.1627 +					{
 93.1628 +						internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
 93.1629 +					}
 93.1630 +					else
 93.1631 +					{
 93.1632 +						internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
 93.1633 +					}
 93.1634  				}
 93.1635  				else
 93.1636  				{
 93.1637 -					internalFormat = GL_RGB;
 93.1638 -				}
 93.1639 -			}
 93.1640 -		}
 93.1641 -		else if ( samples == 4 )
 93.1642 -		{
 93.1643 -			if(r_greyscale->integer)
 93.1644 -			{
 93.1645 -				if(r_texturebits->integer == 16)
 93.1646 -					internalFormat = GL_LUMINANCE8_ALPHA8;
 93.1647 -				else if(r_texturebits->integer == 32)
 93.1648 -					internalFormat = GL_LUMINANCE16_ALPHA16;
 93.1649 -				else
 93.1650 -					internalFormat = GL_LUMINANCE_ALPHA;
 93.1651 -			}
 93.1652 -			else
 93.1653 -			{
 93.1654 -				if ( r_texturebits->integer == 16 )
 93.1655 -				{
 93.1656 -					internalFormat = GL_RGBA4;
 93.1657 -				}
 93.1658 -				else if ( r_texturebits->integer == 32 )
 93.1659 -				{
 93.1660  					internalFormat = GL_RGBA8;
 93.1661  				}
 93.1662 -				else
 93.1663 -				{
 93.1664 -					internalFormat = GL_RGBA;
 93.1665 -				}
 93.1666  			}
 93.1667  		}
 93.1668  	}
 93.1669  
 93.1670 -	// copy or resample data as appropriate for first MIP level
 93.1671 -	if ( ( scaled_width == width ) && 
 93.1672 -		( scaled_height == height ) ) {
 93.1673 -		if (!mipmap)
 93.1674 +	for(i = 0; i < numData; i++)
 93.1675 +	{
 93.1676 +		data = dataArray[i];
 93.1677 +
 93.1678 +		// copy or resample data as appropriate for first MIP level
 93.1679 +		if((scaledWidth == image->width) && (scaledHeight == image->height))
 93.1680  		{
 93.1681 -			qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
 93.1682 -			*pUploadWidth = scaled_width;
 93.1683 -			*pUploadHeight = scaled_height;
 93.1684 -			*format = internalFormat;
 93.1685 -
 93.1686 -			goto done;
 93.1687 +			Com_Memcpy(scaledBuffer, data, scaledWidth * scaledHeight * 4);
 93.1688  		}
 93.1689 -		Com_Memcpy (scaledBuffer, data, width*height*4);
 93.1690 +		else
 93.1691 +		{
 93.1692 +			ResampleTexture((unsigned *)data, image->width, image->height, (unsigned *)scaledBuffer, scaledWidth, scaledHeight,
 93.1693 +							(image->bits & IF_NORMALMAP));
 93.1694 +		}
 93.1695 +
 93.1696 +		if(!(image->bits & (IF_NORMALMAP | IF_RGBA16F | IF_RGBA32F | IF_LA16F | IF_LA32F)))
 93.1697 +		{
 93.1698 +			R_LightScaleTexture((unsigned *)scaledBuffer, scaledWidth, scaledHeight, image->filterType == FT_DEFAULT);
 93.1699 +		}
 93.1700 +
 93.1701 +		image->uploadWidth = scaledWidth;
 93.1702 +		image->uploadHeight = scaledHeight;
 93.1703 +		image->internalFormat = internalFormat;
 93.1704 +
 93.1705 +		if(image->filterType == FT_DEFAULT && glConfig.generateMipmapAvailable)
 93.1706 +		{
 93.1707 +			// raynorpat: if hardware mipmap generation is available, use it
 93.1708 +			//qglHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);	// make sure its nice
 93.1709 +			qglTexParameteri(image->type, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
 93.1710 +			qglTexParameteri(image->type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);	// default to trilinear
 93.1711 +		}
 93.1712 +
 93.1713 +		switch (image->type)
 93.1714 +		{
 93.1715 +			case GL_TEXTURE_CUBE_MAP_ARB:
 93.1716 +				qglTexImage2D(target + i, 0, internalFormat, scaledWidth, scaledHeight, 0, format, GL_UNSIGNED_BYTE,
 93.1717 +							  scaledBuffer);
 93.1718 +				break;
 93.1719 +
 93.1720 +			default:
 93.1721 +				if(image->bits & IF_PACKED_DEPTH24_STENCIL8)
 93.1722 +				{
 93.1723 +					qglTexImage2D(target, 0, internalFormat, scaledWidth, scaledHeight, 0, format, GL_UNSIGNED_INT_24_8_EXT, NULL);
 93.1724 +				}
 93.1725 +				else
 93.1726 +				{
 93.1727 +					qglTexImage2D(target, 0, internalFormat, scaledWidth, scaledHeight, 0, format, GL_UNSIGNED_BYTE, scaledBuffer);
 93.1728 +				}
 93.1729 +				break;
 93.1730 +		}
 93.1731 +
 93.1732 +		if(!glConfig.generateMipmapAvailable)
 93.1733 +		{
 93.1734 +			if(image->filterType == FT_DEFAULT && !(image->bits & (IF_DEPTH16 | IF_DEPTH24 | IF_DEPTH32 | IF_PACKED_DEPTH24_STENCIL8)))
 93.1735 +			{
 93.1736 +				int             mipLevel;
 93.1737 +				int             mipWidth, mipHeight;
 93.1738 +
 93.1739 +				mipLevel = 0;
 93.1740 +				mipWidth = scaledWidth;
 93.1741 +				mipHeight = scaledHeight;
 93.1742 +
 93.1743 +				while(mipWidth > 1 || mipHeight > 1)
 93.1744 +				{
 93.1745 +					if(image->bits & IF_NORMALMAP)
 93.1746 +						R_MipNormalMap(scaledBuffer, mipWidth, mipHeight);
 93.1747 +					else
 93.1748 +						R_MipMap(scaledBuffer, mipWidth, mipHeight);
 93.1749 +
 93.1750 +					mipWidth >>= 1;
 93.1751 +					mipHeight >>= 1;
 93.1752 +
 93.1753 +					if(mipWidth < 1)
 93.1754 +						mipWidth = 1;
 93.1755 +
 93.1756 +					if(mipHeight < 1)
 93.1757 +						mipHeight = 1;
 93.1758 +
 93.1759 +					mipLevel++;
 93.1760 +
 93.1761 +					if(r_colorMipLevels->integer && !(image->bits & IF_NORMALMAP))
 93.1762 +					{
 93.1763 +						R_BlendOverTexture(scaledBuffer, mipWidth * mipHeight, mipBlendColors[mipLevel]);
 93.1764 +					}
 93.1765 +
 93.1766 +					switch (image->type)
 93.1767 +					{
 93.1768 +						case GL_TEXTURE_CUBE_MAP_ARB:
 93.1769 +							qglTexImage2D(target + i, mipLevel, internalFormat, mipWidth, mipHeight, 0, format, GL_UNSIGNED_BYTE,
 93.1770 +										  scaledBuffer);
 93.1771 +							break;
 93.1772 +
 93.1773 +						default:
 93.1774 +							qglTexImage2D(target, mipLevel, internalFormat, mipWidth, mipHeight, 0, format, GL_UNSIGNED_BYTE,
 93.1775 +										  scaledBuffer);
 93.1776 +							break;
 93.1777 +					}
 93.1778 +				}
 93.1779 +			}
 93.1780 +		}
 93.1781 +	}
 93.1782 +
 93.1783 +	GL_CheckErrors();
 93.1784 +
 93.1785 +	// set filter type
 93.1786 +	switch (image->filterType)
 93.1787 +	{
 93.1788 +		case FT_DEFAULT:
 93.1789 +			// set texture anisotropy
 93.1790 +			if(glConfig.textureAnisotropyAvailable)
 93.1791 +				qglTexParameterf(image->type, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_ext_texture_filter_anisotropic->value);
 93.1792 +
 93.1793 +			qglTexParameterf(image->type, GL_TEXTURE_MIN_FILTER, gl_filter_min);
 93.1794 +			qglTexParameterf(image->type, GL_TEXTURE_MAG_FILTER, gl_filter_max);
 93.1795 +			break;
 93.1796 +
 93.1797 +		case FT_LINEAR:
 93.1798 +			qglTexParameterf(image->type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 93.1799 +			qglTexParameterf(image->type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 93.1800 +			break;
 93.1801 +
 93.1802 +		case FT_NEAREST:
 93.1803 +			qglTexParameterf(image->type, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 93.1804 +			qglTexParameterf(image->type, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 93.1805 +			break;
 93.1806 +
 93.1807 +		default:
 93.1808 +			ri.Printf(PRINT_WARNING, "WARNING: unknown filter type for image '%s'\n", image->name);
 93.1809 +			qglTexParameterf(image->type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 93.1810 +			qglTexParameterf(image->type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 93.1811 +			break;
 93.1812 +	}
 93.1813 +
 93.1814 +	GL_CheckErrors();
 93.1815 +
 93.1816 +	// set wrap type
 93.1817 +	switch (image->wrapType)
 93.1818 +	{
 93.1819 +		case WT_REPEAT:
 93.1820 +			qglTexParameterf(image->type, GL_TEXTURE_WRAP_S, GL_REPEAT);
 93.1821 +			qglTexParameterf(image->type, GL_TEXTURE_WRAP_T, GL_REPEAT);
 93.1822 +			break;
 93.1823 +
 93.1824 +		case WT_CLAMP:
 93.1825 +			qglTexParameterf(image->type, GL_TEXTURE_WRAP_S, GL_CLAMP);
 93.1826 +			qglTexParameterf(image->type, GL_TEXTURE_WRAP_T, GL_CLAMP);
 93.1827 +			break;
 93.1828 +
 93.1829 +		case WT_EDGE_CLAMP:
 93.1830 +			qglTexParameterf(image->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 93.1831 +			qglTexParameterf(image->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 93.1832 +			break;
 93.1833 +
 93.1834 +		case WT_ZERO_CLAMP:
 93.1835 +			qglTexParameterf(image->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
 93.1836 +			qglTexParameterf(image->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
 93.1837 +			qglTexParameterfv(image->type, GL_TEXTURE_BORDER_COLOR, zeroClampBorder);
 93.1838 +			break;
 93.1839 +
 93.1840 +		case WT_ALPHA_ZERO_CLAMP:
 93.1841 +			qglTexParameterf(image->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
 93.1842 +			qglTexParameterf(image->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
 93.1843 +			qglTexParameterfv(image->type, GL_TEXTURE_BORDER_COLOR, alphaZeroClampBorder);
 93.1844 +			break;
 93.1845 +
 93.1846 +		default:
 93.1847 +			ri.Printf(PRINT_WARNING, "WARNING: unknown wrap type for image '%s'\n", image->name);
 93.1848 +			qglTexParameterf(image->type, GL_TEXTURE_WRAP_S, GL_REPEAT);
 93.1849 +			qglTexParameterf(image->type, GL_TEXTURE_WRAP_T, GL_REPEAT);
 93.1850 +			break;
 93.1851 +	}
 93.1852 +
 93.1853 +	GL_CheckErrors();
 93.1854 +
 93.1855 +	if(scaledBuffer != 0)
 93.1856 +		ri.Hunk_FreeTempMemory(scaledBuffer);
 93.1857 +}
 93.1858 +
 93.1859 +
 93.1860 +
 93.1861 +/*
 93.1862 +================
 93.1863 +R_AllocImage
 93.1864 +================
 93.1865 +*/
 93.1866 +image_t        *R_AllocImage(const char *name, qboolean linkIntoHashTable)
 93.1867 +{
 93.1868 +	image_t        *image;
 93.1869 +	long            hash;
 93.1870 +	char            buffer[1024];
 93.1871 +
 93.1872 +//  if(strlen(name) >= MAX_QPATH)
 93.1873 +	if(strlen(name) >= 1024)
 93.1874 +	{
 93.1875 +		ri.Error(ERR_DROP, "R_AllocImage: \"%s\" image name is too long\n", name);
 93.1876 +		return NULL;
 93.1877 +	}
 93.1878 +
 93.1879 +	/*
 93.1880 +	if(tr.numImages == MAX_DRAWIMAGES)
 93.1881 +	{
 93.1882 +		ri.Error(ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit\n");
 93.1883 +		return NULL;
 93.1884 +	}
 93.1885 +	*/
 93.1886 +
 93.1887 +	image = ri.Hunk_Alloc(sizeof(image_t), h_low);
 93.1888 +	Com_Memset(image, 0, sizeof(image_t));
 93.1889 +	qglGenTextures(1, &image->texnum);
 93.1890 +
 93.1891 +	Com_AddToGrowList(&tr.images, image);
 93.1892 +
 93.1893 +	Q_strncpyz(image->name, name, sizeof(image->name));
 93.1894 +
 93.1895 +	if(linkIntoHashTable)
 93.1896 +	{
 93.1897 +		Q_strncpyz(buffer, name, sizeof(buffer));
 93.1898 +		hash = generateHashValue(buffer);
 93.1899 +		image->next = hashTable[hash];
 93.1900 +		hashTable[hash] = image;
 93.1901 +	}
 93.1902 +
 93.1903 +	return image;
 93.1904 +}
 93.1905 +
 93.1906 +
 93.1907 +/*
 93.1908 +================
 93.1909 +R_CreateImage
 93.1910 +================
 93.1911 +*/
 93.1912 +image_t        *R_CreateImage(const char *name,
 93.1913 +							  const byte * pic, int width, int height, int bits, filterType_t filterType, wrapType_t wrapType)
 93.1914 +{
 93.1915 +	image_t        *image;
 93.1916 +
 93.1917 +	image = R_AllocImage(name, qtrue);
 93.1918 +	if(!image)
 93.1919 +		return NULL;
 93.1920 +
 93.1921 +	image->type = GL_TEXTURE_2D;
 93.1922 +
 93.1923 +	image->width = width;
 93.1924 +	image->height = height;
 93.1925 +
 93.1926 +	image->bits = bits;
 93.1927 +	image->filterType = filterType;
 93.1928 +	image->wrapType = wrapType;
 93.1929 +
 93.1930 +	GL_Bind(image);
 93.1931 +
 93.1932 +	R_UploadImage(&pic, 1, image);
 93.1933 +
 93.1934 +	//GL_Unbind();
 93.1935 +	qglBindTexture(image->type, 0);
 93.1936 +
 93.1937 +	return image;
 93.1938 +}
 93.1939 +
 93.1940 +/*
 93.1941 +================
 93.1942 +R_CreateCubeImage
 93.1943 +================
 93.1944 +*/
 93.1945 +image_t        *R_CreateCubeImage(const char *name,
 93.1946 +								  const byte * pic[6],
 93.1947 +								  int width, int height, int bits, filterType_t filterType, wrapType_t wrapType)
 93.1948 +{
 93.1949 +	image_t        *image;
 93.1950 +
 93.1951 +	image = R_AllocImage(name, qtrue);
 93.1952 +	if(!image)
 93.1953 +		return NULL;
 93.1954 +
 93.1955 +	image->type = GL_TEXTURE_CUBE_MAP_ARB;
 93.1956 +
 93.1957 +	image->width = width;
 93.1958 +	image->height = height;
 93.1959 +
 93.1960 +	image->bits = bits;
 93.1961 +	image->filterType = filterType;
 93.1962 +	image->wrapType = wrapType;
 93.1963 +
 93.1964 +	GL_Bind(image);
 93.1965 +
 93.1966 +	R_UploadImage(pic, 6, image);
 93.1967 +
 93.1968 +	qglBindTexture(image->type, 0);
 93.1969 +
 93.1970 +	return image;
 93.1971 +}
 93.1972 +
 93.1973 +
 93.1974 +
 93.1975 +
 93.1976 +static void     R_LoadImage(char **buffer, byte ** pic, int *width, int *height, int *bits);
 93.1977 +image_t        *R_LoadDDSImage(const char *name, int bits, filterType_t filterType, wrapType_t wrapType);
 93.1978 +
 93.1979 +static void ParseHeightMap(char **text, byte ** pic, int *width, int *height, int *bits)
 93.1980 +{
 93.1981 +	char           *token;
 93.1982 +	float           scale;
 93.1983 +
 93.1984 +	token = Com_ParseExt(text, qfalse);
 93.1985 +	if(token[0] != '(')
 93.1986 +	{
 93.1987 +		ri.Printf(PRINT_WARNING, "WARNING: expecting '(', found '%s' for heightMap\n", token);
 93.1988 +		return;
 93.1989 +	}
 93.1990 +
 93.1991 +	R_LoadImage(text, pic, width, height, bits);
 93.1992 +	if(!pic)
 93.1993 +	{
 93.1994 +		ri.Printf(PRINT_WARNING, "WARNING: failed loading of image for heightMap\n", token);
 93.1995 +		return;
 93.1996 +	}
 93.1997 +
 93.1998 +	token = Com_ParseExt(text, qfalse);
 93.1999 +	if(token[0] != ',')
 93.2000 +	{
 93.2001 +		ri.Printf(PRINT_WARNING, "WARNING: no matching ',' found\n");
 93.2002 +		return;
 93.2003 +	}
 93.2004 +
 93.2005 +	token = Com_ParseExt(text, qfalse);
 93.2006 +	scale = atof(token);
 93.2007 +
 93.2008 +	token = Com_ParseExt(text, qfalse);
 93.2009 +	if(token[0] != ')')
 93.2010 +	{
 93.2011 +		ri.Printf(PRINT_WARNING, "WARNING: expecting ')', found '%s' for heightMap\n", token);
 93.2012 +		return;
 93.2013 +	}
 93.2014 +
 93.2015 +	R_HeightMapToNormalMap(*pic, *width, *height, scale);
 93.2016 +
 93.2017 +	*bits &= ~IF_INTENSITY;
 93.2018 +	*bits &= ~IF_ALPHA;
 93.2019 +	*bits |= IF_NORMALMAP;
 93.2020 +}
 93.2021 +
 93.2022 +static void ParseDisplaceMap(char **text, byte ** pic, int *width, int *height, int *bits)
 93.2023 +{
 93.2024 +	char           *token;
 93.2025 +	byte           *pic2;
 93.2026 +	int             width2, height2;
 93.2027 +
 93.2028 +	token = Com_ParseExt(text, qfalse);
 93.2029 +	if(token[0] != '(')
 93.2030 +	{
 93.2031 +		ri.Printf(PRINT_WARNING, "WARNING: expecting '(', found '%s' for displaceMap\n", token);
 93.2032 +		return;
 93.2033 +	}
 93.2034 +
 93.2035 +	R_LoadImage(text, pic, width, height, bits);
 93.2036 +	if(!pic)
 93.2037 +	{
 93.2038 +		ri.Printf(PRINT_WARNING, "WARNING: failed loading of first image for displaceMap\n");
 93.2039 +		return;
 93.2040 +	}
 93.2041 +
 93.2042 +	token = Com_ParseExt(text, qfalse);
 93.2043 +	if(token[0] != ',')
 93.2044 +	{
 93.2045 +		ri.Printf(PRINT_WARNING, "WARNING: no matching ',' found\n");
 93.2046 +		return;
 93.2047 +	}
 93.2048 +
 93.2049 +	R_LoadImage(text, &pic2, &width2, &height2, bits);
 93.2050 +	if(!pic2)
 93.2051 +	{
 93.2052 +		ri.Printf(PRINT_WARNING, "WARNING: failed loading of second image for displaceMap\n");
 93.2053 +		return;
 93.2054 +	}
 93.2055 +
 93.2056 +	token = Com_ParseExt(text, qfalse);
 93.2057 +	if(token[0] != ')')
 93.2058 +	{
 93.2059 +		ri.Printf(PRINT_WARNING, "WARNING: expecting ')', found '%s' for displaceMap\n", token);
 93.2060 +	}
 93.2061 +
 93.2062 +	if(*width != width2 || *height != height2)
 93.2063 +	{
 93.2064 +		ri.Printf(PRINT_WARNING, "WARNING: images for displaceMap have different dimensions (%i x %i != %i x %i)\n",
 93.2065 +				  *width, *height, width2, height2);
 93.2066 +
 93.2067 +		//ri.Free(*pic);
 93.2068 +		//*pic = NULL;
 93.2069 +
 93.2070 +		ri.Free(pic2);
 93.2071 +		return;
 93.2072 +	}
 93.2073 +
 93.2074 +	R_DisplaceMap(*pic, pic2, *width, *height);
 93.2075 +
 93.2076 +	ri.Free(pic2);
 93.2077 +
 93.2078 +	*bits &= ~IF_INTENSITY;
 93.2079 +	*bits &= ~IF_ALPHA;
 93.2080 +	*bits |= IF_NORMALMAP;
 93.2081 +	*bits |= IF_DISPLACEMAP;
 93.2082 +}
 93.2083 +
 93.2084 +static void ParseAddNormals(char **text, byte ** pic, int *width, int *height, int *bits)
 93.2085 +{
 93.2086 +	char           *token;
 93.2087 +	byte           *pic2;
 93.2088 +	int             width2, height2;
 93.2089 +
 93.2090 +	token = Com_ParseExt(text, qfalse);
 93.2091 +	if(token[0] != '(')
 93.2092 +	{
 93.2093 +		ri.Printf(PRINT_WARNING, "WARNING: expecting '(', found '%s' for addNormals\n", token);
 93.2094 +		return;
 93.2095 +	}
 93.2096 +
 93.2097 +	R_LoadImage(text, pic, width, height, bits);
 93.2098 +	if(!pic)
 93.2099 +	{
 93.2100 +		ri.Printf(PRINT_WARNING, "WARNING: failed loading of first image for addNormals\n");
 93.2101 +		return;
 93.2102 +	}
 93.2103 +
 93.2104 +	token = Com_ParseExt(text, qfalse);
 93.2105 +	if(token[0] != ',')
 93.2106 +	{
 93.2107 +		ri.Printf(PRINT_WARNING, "WARNING: no matching ',' found\n");
 93.2108 +		return;
 93.2109 +	}
 93.2110 +
 93.2111 +	R_LoadImage(text, &pic2, &width2, &height2, bits);
 93.2112 +	if(!pic2)
 93.2113 +	{
 93.2114 +		ri.Printf(PRINT_WARNING, "WARNING: failed loading of second image for addNormals\n");
 93.2115 +		return;
 93.2116 +	}
 93.2117 +
 93.2118 +	token = Com_ParseExt(text, qfalse);
 93.2119 +	if(token[0] != ')')
 93.2120 +	{
 93.2121 +		ri.Printf(PRINT_WARNING, "WARNING: expecting ')', found '%s' for addNormals\n", token);
 93.2122 +	}
 93.2123 +
 93.2124 +	if(*width != width2 || *height != height2)
 93.2125 +	{
 93.2126 +		ri.Printf(PRINT_WARNING, "WARNING: images for addNormals have different dimensions (%i x %i != %i x %i)\n",
 93.2127 +				  *width, *height, width2, height2);
 93.2128 +
 93.2129 +		//ri.Free(*pic);
 93.2130 +		//*pic = NULL;
 93.2131 +
 93.2132 +		ri.Free(pic2);
 93.2133 +		return;
 93.2134 +	}
 93.2135 +
 93.2136 +	R_AddNormals(*pic, pic2, *width, *height);
 93.2137 +
 93.2138 +	ri.Free(pic2);
 93.2139 +
 93.2140 +	*bits &= ~IF_INTENSITY;
 93.2141 +	*bits &= ~IF_ALPHA;
 93.2142 +	*bits |= IF_NORMALMAP;
 93.2143 +}
 93.2144 +
 93.2145 +static void ParseInvertAlpha(char **text, byte ** pic, int *width, int *height, int *bits)
 93.2146 +{
 93.2147 +	char           *token;
 93.2148 +
 93.2149 +	token = Com_ParseExt(text, qfalse);
 93.2150 +	if(token[0] != '(')
 93.2151 +	{
 93.2152 +		ri.Printf(PRINT_WARNING, "WARNING: expecting '(', found '%s' for invertAlpha\n", token);
 93.2153 +		return;
 93.2154 +	}
 93.2155 +
 93.2156 +	R_LoadImage(text, pic, width, height, bits);
 93.2157 +	if(!pic)
 93.2158 +	{
 93.2159 +		ri.Printf(PRINT_WARNING, "WARNING: failed loading of image for invertAlpha\n");
 93.2160 +		return;
 93.2161 +	}
 93.2162 +
 93.2163 +	token = Com_ParseExt(text, qfalse);
 93.2164 +	if(token[0] != ')')
 93.2165 +	{
 93.2166 +		ri.Printf(PRINT_WARNING, "WARNING: expecting ')', found '%s' for invertAlpha\n", token);
 93.2167 +		return;
 93.2168 +	}
 93.2169 +
 93.2170 +	R_InvertAlpha(*pic, *width, *height);
 93.2171 +}
 93.2172 +
 93.2173 +static void ParseInvertColor(char **text, byte ** pic, int *width, int *height, int *bits)
 93.2174 +{
 93.2175 +	char           *token;
 93.2176 +
 93.2177 +	token = Com_ParseExt(text, qfalse);
 93.2178 +	if(token[0] != '(')
 93.2179 +	{
 93.2180 +		ri.Printf(PRINT_WARNING, "WARNING: expecting '(', found '%s' for invertColor\n", token);
 93.2181 +		return;
 93.2182 +	}
 93.2183 +
 93.2184 +	R_LoadImage(text, pic, width, height, bits);
 93.2185 +	if(!pic)
 93.2186 +	{
 93.2187 +		ri.Printf(PRINT_WARNING, "WARNING: failed loading of image for invertColor\n");
 93.2188 +		return;
 93.2189 +	}
 93.2190 +
 93.2191 +	token = Com_ParseExt(text, qfalse);
 93.2192 +	if(token[0] != ')')
 93.2193 +	{
 93.2194 +		ri.Printf(PRINT_WARNING, "WARNING: expecting ')', found '%s' for invertColor\n", token);
 93.2195 +		return;
 93.2196 +	}
 93.2197 +
 93.2198 +	R_InvertColor(*pic, *width, *height);
 93.2199 +}
 93.2200 +
 93.2201 +static void ParseMakeIntensity(char **text, byte ** pic, int *width, int *height, int *bits)
 93.2202 +{
 93.2203 +	char           *token;
 93.2204 +
 93.2205 +	token = Com_ParseExt(text, qfalse);
 93.2206 +	if(token[0] != '(')
 93.2207 +	{
 93.2208 +		ri.Printf(PRINT_WARNING, "WARNING: expecting '(', found '%s' for makeIntensity\n", token);
 93.2209 +		return;
 93.2210 +	}
 93.2211 +
 93.2212 +	R_LoadImage(text, pic, width, height, bits);
 93.2213 +	if(!pic)
 93.2214 +	{
 93.2215 +		ri.Printf(PRINT_WARNING, "WARNING: failed loading of image for makeIntensity\n");
 93.2216 +		return;
 93.2217 +	}
 93.2218 +
 93.2219 +	token = Com_ParseExt(text, qfalse);
 93.2220 +	if(token[0] != ')')
 93.2221 +	{
 93.2222 +		ri.Printf(PRINT_WARNING, "WARNING: expecting ')', found '%s' for makeIntensity\n", token);
 93.2223 +		return;
 93.2224 +	}
 93.2225 +
 93.2226 +	R_MakeIntensity(*pic, *width, *height);
 93.2227 +
 93.2228 +//	*bits |= IF_INTENSITY;
 93.2229 +	*bits &= ~IF_ALPHA;
 93.2230 +	*bits &= ~IF_NORMALMAP;
 93.2231 +}
 93.2232 +
 93.2233 +static void ParseMakeAlpha(char **text, byte ** pic, int *width, int *height, int *bits)
 93.2234 +{
 93.2235 +	char           *token;
 93.2236 +
 93.2237 +	token = Com_ParseExt(text, qfalse);
 93.2238 +	if(token[0] != '(')
 93.2239 +	{
 93.2240 +		ri.Printf(PRINT_WARNING, "WARNING: expecting '(', found '%s' for makeAlpha\n", token);
 93.2241 +		return;
 93.2242 +	}
 93.2243 +
 93.2244 +	R_LoadImage(text, pic, width, height, bits);
 93.2245 +	if(!pic)
 93.2246 +	{
 93.2247 +		ri.Printf(PRINT_WARNING, "WARNING: failed loading of image for makeAlpha\n");
 93.2248 +		return;
 93.2249 +	}
 93.2250 +
 93.2251 +	token = Com_ParseExt(text, qfalse);
 93.2252 +	if(token[0] != ')')
 93.2253 +	{
 93.2254 +		ri.Printf(PRINT_WARNING, "WARNING: expecting ')', found '%s' for makeAlpha\n", token);
 93.2255 +		return;
 93.2256 +	}
 93.2257 +
 93.2258 +	R_MakeAlpha(*pic, *width, *height);
 93.2259 +
 93.2260 +	*bits &= ~IF_INTENSITY;
 93.2261 +//	*bits |= IF_ALPHA;
 93.2262 +	*bits &= IF_NORMALMAP;
 93.2263 +}
 93.2264 +
 93.2265 +typedef struct
 93.2266 +{
 93.2267 +	char           *ext;
 93.2268 +	void            (*ImageLoader) (const char *, unsigned char **, int *, int *, byte);
 93.2269 +} imageExtToLoaderMap_t;
 93.2270 +
 93.2271 +// Note that the ordering indicates the order of preference used
 93.2272 +// when there are multiple images of different formats available
 93.2273 +static imageExtToLoaderMap_t imageLoaders[] = {
 93.2274 +	{"tga", LoadTGA},
 93.2275 +	{"png", LoadPNG},
 93.2276 +	{"jpg", LoadJPG},
 93.2277 +	{"jpeg", LoadJPG},
 93.2278 +	{"bmp",  R_LoadBMP},
 93.2279 +//	{"dds", LoadDDS},	// need to write some direct uploader routines first
 93.2280 +//	{"hdr", LoadRGBE}	// RGBE just sucks
 93.2281 +};
 93.2282 +
 93.2283 +static int      numImageLoaders = sizeof(imageLoaders) / sizeof(imageLoaders[0]);
 93.2284 +
 93.2285 +/*
 93.2286 +=================
 93.2287 +R_LoadImage
 93.2288 +
 93.2289 +Loads any of the supported image types into a canonical
 93.2290 +32 bit format.
 93.2291 +=================
 93.2292 +*/
 93.2293 +static void R_LoadImage(char **buffer, byte ** pic, int *width, int *height, int *bits)
 93.2294 +{
 93.2295 +	char           *token;
 93.2296 +
 93.2297 +	*pic = NULL;
 93.2298 +	*width = 0;
 93.2299 +	*height = 0;
 93.2300 +
 93.2301 +	token = Com_ParseExt(buffer, qfalse);
 93.2302 +	if(!token[0])
 93.2303 +	{
 93.2304 +		ri.Printf(PRINT_WARNING, "WARNING: NULL parameter for R_LoadImage\n");
 93.2305 +		return;
 93.2306 +	}
 93.2307 +
 93.2308 +	//ri.Printf(PRINT_ALL, "R_LoadImage: token '%s'\n", token);
 93.2309 +
 93.2310 +	// heightMap(<map>, <float>)  Turns a grayscale height map into a normal map. <float> varies the bumpiness
 93.2311 +	if(!Q_stricmp(token, "heightMap"))
 93.2312 +	{
 93.2313 +		ParseHeightMap(buffer, pic, width, height, bits);
 93.2314 +	}
 93.2315 +	// displaceMap(<map>, <map>)  Sets the alpha channel to an average of the second image's RGB channels.
 93.2316 +	else if(!Q_stricmp(token, "displaceMap"))
 93.2317 +	{
 93.2318 +		ParseDisplaceMap(buffer, pic, width, height, bits);
 93.2319 +	}
 93.2320 +	// addNormals(<map>, <map>)  Adds two normal maps together. Result is normalized.
 93.2321 +	else if(!Q_stricmp(token, "addNormals"))
 93.2322 +	{
 93.2323 +		ParseAddNormals(buffer, pic, width, height, bits);
 93.2324 +	}
 93.2325 +	// smoothNormals(<map>)  Does a box filter on the normal map, and normalizes the result.
 93.2326 +	else if(!Q_stricmp(token, "smoothNormals"))
 93.2327 +	{
 93.2328 +		ri.Printf(PRINT_WARNING, "WARNING: smoothNormals(<map>) keyword not supported\n");
 93.2329 +	}
 93.2330 +	// add(<map>, <map>)  Adds two images without normalizing the result
 93.2331 +	else if(!Q_stricmp(token, "add"))
 93.2332 +	{
 93.2333 +		ri.Printf(PRINT_WARNING, "WARNING: add(<map>, <map>) keyword not supported\n");
 93.2334 +	}
 93.2335 +	// scale(<map>, <float> [,float] [,float] [,float])  Scales the RGBA by the specified factors. Defaults to 0.
 93.2336 +	else if(!Q_stricmp(token, "scale"))
 93.2337 +	{
 93.2338 +		ri.Printf(PRINT_WARNING, "WARNING: scale(<map>, <float> [,float] [,float] [,float]) keyword not supported\n");
 93.2339 +	}
 93.2340 +	// invertAlpha(<map>)  Inverts the alpha channel (0 becomes 1, 1 becomes 0)
 93.2341 +	else if(!Q_stricmp(token, "invertAlpha"))
 93.2342 +	{
 93.2343 +		ParseInvertAlpha(buffer, pic, width, height, bits);
 93.2344 +	}
 93.2345 +	// invertColor(<map>)  Inverts the R, G, and B channels
 93.2346 +	else if(!Q_stricmp(token, "invertColor"))
 93.2347 +	{
 93.2348 +		ParseInvertColor(buffer, pic, width, height, bits);
 93.2349 +	}
 93.2350 +	// makeIntensity(<map>)  Copies the red channel to the G, B, and A channels
 93.2351 +	else if(!Q_stricmp(token, "makeIntensity"))
 93.2352 +	{
 93.2353 +		ParseMakeIntensity(buffer, pic, width, height, bits);
 93.2354 +	}
 93.2355 +	// makeAlpha(<map>)  Sets the alpha channel to an average of the RGB channels. Sets the RGB channels to white.
 93.2356 +	else if(!Q_stricmp(token, "makeAlpha"))
 93.2357 +	{
 93.2358 +		ParseMakeAlpha(buffer, pic, width, height, bits);
 93.2359  	}
 93.2360  	else
 93.2361  	{
 93.2362 -		// use the normal mip-mapping function to go down from here
 93.2363 -		while ( width > scaled_width || height > scaled_height ) {
 93.2364 -			R_MipMap( (byte *)data, width, height );
 93.2365 -			width >>= 1;
 93.2366 -			height >>= 1;
 93.2367 -			if ( width < 1 ) {
 93.2368 -				width = 1;
 93.2369 +		qboolean        orgNameFailed = qfalse;
 93.2370 +		int             i;
 93.2371 +		const char     *ext;
 93.2372 +		char            filename[MAX_QPATH];
 93.2373 +		byte            alphaByte;
 93.2374 +
 93.2375 +		// Tr3B: clear alpha of normalmaps for displacement mapping
 93.2376 +		if(*bits & IF_NORMALMAP)
 93.2377 +			alphaByte = 0x00;
 93.2378 +		else
 93.2379 +			alphaByte = 0xFF;
 93.2380 +
 93.2381 +		Q_strncpyz(filename, token, sizeof(filename));
 93.2382 +
 93.2383 +		ext = Com_GetExtension(filename);
 93.2384 +
 93.2385 +		if(*ext)
 93.2386 +		{
 93.2387 +			// look for the correct loader and use it
 93.2388 +			for(i = 0; i < numImageLoaders; i++)
 93.2389 +			{
 93.2390 +				if(!Q_stricmp(ext, imageLoaders[i].ext))
 93.2391 +				{
 93.2392 +					// load
 93.2393 +					imageLoaders[i].ImageLoader(filename, pic, width, height, alphaByte);
 93.2394 +					break;
 93.2395 +				}
 93.2396  			}
 93.2397 -			if ( height < 1 ) {
 93.2398 -				height = 1;
 93.2399 +
 93.2400 +			// a loader was found
 93.2401 +			if(i < numImageLoaders)
 93.2402 +			{
 93.2403 +				if(*pic == NULL)
 93.2404 +				{
 93.2405 +					// loader failed, most likely because the file isn't there;
 93.2406 +					// try again without the extension
 93.2407 +					orgNameFailed = qtrue;
 93.2408 +					Com_StripExtension(token, filename, MAX_QPATH);
 93.2409 +				}
 93.2410 +				else
 93.2411 +				{
 93.2412 +					// something loaded
 93.2413 +					return;
 93.2414 +				}
 93.2415  			}
 93.2416  		}
 93.2417 -		Com_Memcpy( scaledBuffer, data, width * height * 4 );
 93.2418 -	}
 93.2419 -
 93.2420 -	R_LightScaleTexture (scaledBuffer, scaled_width, scaled_height, !mipmap );
 93.2421 -
 93.2422 -	*pUploadWidth = scaled_width;
 93.2423 -	*pUploadHeight = scaled_height;
 93.2424 -	*format = internalFormat;
 93.2425 -
 93.2426 -	qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaledBuffer );
 93.2427 -
 93.2428 -	if (mipmap)
 93.2429 -	{
 93.2430 -		int		miplevel;
 93.2431 -
 93.2432 -		miplevel = 0;
 93.2433 -		while (scaled_width > 1 || scaled_height > 1)
 93.2434 +
 93.2435 +		// try and find a suitable match using all the image formats supported
 93.2436 +		for(i = 0; i < numImageLoaders; i++)
 93.2437  		{
 93.2438 -			R_MipMap( (byte *)scaledBuffer, scaled_width, scaled_height );
 93.2439 -			scaled_width >>= 1;
 93.2440 -			scaled_height >>= 1;
 93.2441 -			if (scaled_width < 1)
 93.2442 -				scaled_width = 1;
 93.2443 -			if (scaled_height < 1)
 93.2444 -				scaled_height = 1;
 93.2445 -			miplevel++;
 93.2446 -
 93.2447 -			if ( r_colorMipLevels->integer ) {
 93.2448 -				R_BlendOverTexture( (byte *)scaledBuffer, scaled_width * scaled_height, mipBlendColors[miplevel] );
 93.2449 +			char           *altName = va("%s.%s", filename, imageLoaders[i].ext);
 93.2450 +
 93.2451 +			// load
 93.2452 +			imageLoaders[i].ImageLoader(altName, pic, width, height, alphaByte);
 93.2453 +
 93.2454 +			if(*pic)
 93.2455 +			{
 93.2456 +				if(orgNameFailed)
 93.2457 +				{
 93.2458 +					ri.Printf(PRINT_DEVELOPER, "WARNING: %s not present, using %s instead\n", token, altName);
 93.2459 +				}
 93.2460 +
 93.2461 +				break;
 93.2462  			}
 93.2463 -
 93.2464 -			qglTexImage2D (GL_TEXTURE_2D, miplevel, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaledBuffer );
 93.2465 -		}
 93.2466 -	}
 93.2467 -done:
 93.2468 -
 93.2469 -	if (mipmap)
 93.2470 -	{
 93.2471 -		if ( glConfig.textureFilterAnisotropic )
 93.2472 -			qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
 93.2473 -					(GLint)Com_Clamp( 1, glConfig.maxAnisotropy, r_ext_max_anisotropy->integer ) );
 93.2474 -
 93.2475 -		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
 93.2476 -		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
 93.2477 -	}
 93.2478 -	else
 93.2479 -	{
 93.2480 -		if ( glConfig.textureFilterAnisotropic )
 93.2481 -			qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 );
 93.2482 -
 93.2483 -		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
 93.2484 -		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
 93.2485 -	}
 93.2486 -
 93.2487 -	GL_CheckErrors();
 93.2488 -
 93.2489 -	if ( scaledBuffer != 0 )
 93.2490 -		ri.Hunk_FreeTempMemory( scaledBuffer );
 93.2491 -	if ( resampledBuffer != 0 )
 93.2492 -		ri.Hunk_FreeTempMemory( resampledBuffer );
 93.2493 -}
 93.2494 -
 93.2495 -
 93.2496 -/*
 93.2497 -================
 93.2498 -R_CreateImage
 93.2499 -
 93.2500 -This is the only way any image_t are created
 93.2501 -================
 93.2502 -*/
 93.2503 -image_t *R_CreateImage( const char *name, const byte *pic, int width, int height, 
 93.2504 -					   qboolean mipmap, qboolean allowPicmip, int glWrapClampMode ) {
 93.2505 -	image_t		*image;
 93.2506 -	qboolean	isLightmap = qfalse;
 93.2507 -	long		hash;
 93.2508 -
 93.2509 -	if (strlen(name) >= MAX_QPATH ) {
 93.2510 -		ri.Error (ERR_DROP, "R_CreateImage: \"%s\" is too long\n", name);
 93.2511 -	}
 93.2512 -	if ( !strncmp( name, "*lightmap", 9 ) ) {
 93.2513 -		isLightmap = qtrue;
 93.2514 -	}
 93.2515 -
 93.2516 -	if ( tr.numImages == MAX_DRAWIMAGES ) {
 93.2517 -		ri.Error( ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit\n");
 93.2518 -	}
 93.2519 -
 93.2520 -	image = tr.images[tr.numImages] = ri.Hunk_Alloc( sizeof( image_t ), h_low );
 93.2521 -	image->texnum = 1024 + tr.numImages;
 93.2522 -	tr.numImages++;
 93.2523 -
 93.2524 -	image->mipmap = mipmap;
 93.2525 -	image->allowPicmip = allowPicmip;
 93.2526 -
 93.2527 -	strcpy (image->imgName, name);
 93.2528 -
 93.2529 -	image->width = width;
 93.2530 -	image->height = height;
 93.2531 -	image->wrapClampMode = glWrapClampMode;
 93.2532 -
 93.2533 -	// lightmaps are always allocated on TMU 1
 93.2534 -	if ( qglActiveTextureARB && isLightmap ) {
 93.2535 -		image->TMU = 1;
 93.2536 -	} else {
 93.2537 -		image->TMU = 0;
 93.2538 -	}
 93.2539 -
 93.2540 -	if ( qglActiveTextureARB ) {
 93.2541 -		GL_SelectTexture( image->TMU );
 93.2542 -	}
 93.2543 -
 93.2544 -	GL_Bind(image);
 93.2545 -
 93.2546 -	Upload32( (unsigned *)pic, image->width, image->height, 
 93.2547 -								image->mipmap,
 93.2548 -								allowPicmip,
 93.2549 -								isLightmap,
 93.2550 -								&image->internalFormat,
 93.2551 -								&image->uploadWidth,
 93.2552 -								&image->uploadHeight );
 93.2553 -
 93.2554 -	qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode );
 93.2555 -	qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode );
 93.2556 -
 93.2557 -	qglBindTexture( GL_TEXTURE_2D, 0 );
 93.2558 -
 93.2559 -	if ( image->TMU == 1 ) {
 93.2560 -		GL_SelectTexture( 0 );
 93.2561 -	}
 93.2562 -
 93.2563 -	hash = generateHashValue(name);
 93.2564 -	image->next = hashTable[hash];
 93.2565 -	hashTable[hash] = image;
 93.2566 -
 93.2567 -	return image;
 93.2568 -}
 93.2569 -
 93.2570 -/****************************
 93.2571 -RGB GET/SET
 93.2572 -****************************/
 93.2573 - 
 93.2574 -//RED
 93.2575 -static byte getImageR(byte *targa_rgba, int x, int y, int columns, int rows)
 93.2576 -{
 93.2577 -	byte	*pixbuf;
 93.2578 -	
 93.2579 -	x*=((x<0)?-1:1);
 93.2580 -	y*=((y<0)?-1:1);
 93.2581 -  if(rows<=y)
 93.2582 -		y=y%rows;
 93.2583 -  if(columns<=x)
 93.2584 -		x=x%columns;
 93.2585 -	x*=((x<0)?-1:1);
 93.2586 -	y*=((y<0)?-1:1);
 93.2587 -  
 93.2588 -	
 93.2589 -	pixbuf = targa_rgba + y*columns*4;
 93.2590 -	
 93.2591 -	pixbuf+=(x*4);
 93.2592 -	
 93.2593 -	return *pixbuf;
 93.2594 -}
 93.2595 -
 93.2596 -static void setImageR(byte *targa_rgba, int x, int y, int columns, int rows, byte value)
 93.2597 -{
 93.2598 -	byte	*pixbuf;
 93.2599 -	
 93.2600 -	x*=((x<0)?-1:1);
 93.2601 -	y*=((y<0)?-1:1);
 93.2602 -	
 93.2603 -	pixbuf = targa_rgba + y*columns*4;
 93.2604 -	
 93.2605 -	pixbuf+=(x*4);
 93.2606 -	
 93.2607 -	*pixbuf=value;
 93.2608 -}
 93.2609 -//GREEN
 93.2610 -static byte getImageG(byte *targa_rgba, int x, int y, int columns, int rows)
 93.2611 -{
 93.2612 -	byte	*pixbuf;
 93.2613 -	
 93.2614 -	x*=((x<0)?-1:1);
 93.2615 -	y*=((y<0)?-1:1);
 93.2616 -  if(rows<=y)
 93.2617 -		y=y%rows;
 93.2618 -  if(columns<=x)
 93.2619 -		x=x%columns;
 93.2620 -	x*=((x<0)?-1:1);
 93.2621 -	y*=((y<0)?-1:1);
 93.2622 -	
 93.2623 -	pixbuf = targa_rgba + y*columns*4;
 93.2624 -	
 93.2625 -	pixbuf+=(x*4);
 93.2626 -	
 93.2627 -	pixbuf++;
 93.2628 -	return *pixbuf;
 93.2629 -}
 93.2630 -
 93.2631 -static void setImageG(byte *targa_rgba, int x, int y, int columns, int rows, byte value)
 93.2632 -{
 93.2633 -	byte	*pixbuf;
 93.2634 -
 93.2635 -	x*=((x<0)?-1:1);
 93.2636 -	y*=((y<0)?-1:1);
 93.2637 -
 93.2638 -	pixbuf = targa_rgba + y*columns*4;
 93.2639 -	
 93.2640 -	pixbuf+=(x*4);
 93.2641 -	pixbuf++;
 93.2642 -	*pixbuf=value;
 93.2643 -}
 93.2644 -//BLUE
 93.2645 -static byte getImageB(byte *targa_rgba, int x, int y, int columns, int rows)
 93.2646 -{
 93.2647 -	byte	*pixbuf;
 93.2648 -	
 93.2649 -	x*=((x<0)?-1:1);
 93.2650 -	y*=((y<0)?-1:1);
 93.2651 -  if(rows<=y)
 93.2652 -		y=y%rows;
 93.2653 -  if(columns<=x)
 93.2654 -		x=x%columns;
 93.2655 -	x*=((x<0)?-1:1);
 93.2656 -	y*=((y<0)?-1:1);
 93.2657 -	
 93.2658 -	pixbuf = targa_rgba + y*columns*4;
 93.2659 -	
 93.2660 -	pixbuf+=(x*4);
 93.2661 -	pixbuf+=2;
 93.2662 -	return *pixbuf;
 93.2663 -}
 93.2664 -
 93.2665 -static void setImageB(byte *targa_rgba, int x, int y, int columns, int rows, byte value)
 93.2666 -{
 93.2667 -	byte	*pixbuf;
 93.2668 -	
 93.2669 -	x*=((x<0)?-1:1);
 93.2670 -	y*=((y<0)?-1:1);
 93.2671 -	
 93.2672 -	pixbuf = targa_rgba + y*columns*4;
 93.2673 -	
 93.2674 -	pixbuf+=(x*4);
 93.2675 -	pixbuf+=2;
 93.2676 -	*pixbuf=value;
 93.2677 -}
 93.2678 -
 93.2679 -//RGB
 93.2680 -static void getImageRGB(byte *targa_rgba, int x, int y, int columns, int rows, vec3_t rgb)
 93.2681 -{
 93.2682 -	byte	*pixbuf;
 93.2683 -	
 93.2684 -	x*=((x<0)?-1:1);
 93.2685 -	y*=((y<0)?-1:1);
 93.2686 -  //if(rows<=y)
 93.2687 -	y=y%rows;
 93.2688 -  //if(columns<=x)
 93.2689 -	x=x%columns;
 93.2690 -	//x*=((x<0)?-1:1);
 93.2691 -	//y*=((y<0)?-1:1);
 93.2692 -	
 93.2693 -	pixbuf = targa_rgba + y*columns*4 + x*4;
 93.2694 -	
 93.2695 -	rgb[0]=*pixbuf;
 93.2696 -	rgb[1]=*(pixbuf+1);
 93.2697 -	rgb[2]=*(pixbuf+2);
 93.2698 -}
 93.2699 -
 93.2700 -static void setImageRGB(byte *targa_rgba, int x, int y, int columns, int rows, vec3_t rgb)
 93.2701 -{
 93.2702 -	byte	*pixbuf;
 93.2703 -	
 93.2704 -	//x*=((x<0)?-1:1);
 93.2705 -	//y*=((y<0)?-1:1);
 93.2706 -	
 93.2707 -	pixbuf = targa_rgba + y*columns*4 + (x*4);
 93.2708 -	
 93.2709 -	*pixbuf=(byte)(rgb[0]);
 93.2710 -	*(pixbuf+1)=(byte)(rgb[1]);
 93.2711 -	*(pixbuf+2)=(byte)(rgb[2]);
 93.2712 -}
 93.2713 -
 93.2714 -/****************************
 93.2715 -NO BRAINER'S BLUR
 93.2716 -****************************/
 93.2717 -static void blur(int columns, int rows, byte *targa_rgba)
 93.2718 -{
 93.2719 -	int		row, column;
 93.2720 -	float sum;
 93.2721 -	
 93.2722 -	
 93.2723 -		for(row=0; row<rows; row++) 
 93.2724 -		{
 93.2725 -			//pixbuf = targa_rgba + row*columns*4;
 93.2726 -			for(column=0; column<columns; column++) 
 93.2727 -			{
 93.2728 -				sum=0;
 93.2729 -				sum+=getImageR(targa_rgba,column-1,row-1,columns,rows);
 93.2730 -				sum+=getImageR(targa_rgba,column,row-1,columns,rows);
 93.2731 -				sum+=getImageR(targa_rgba,column+1,row-1,columns,rows);
 93.2732 -				sum+=getImageR(targa_rgba,column-1,row,columns,rows);
 93.2733 -				sum+=getImageR(targa_rgba,column,row,columns,rows);
 93.2734 -				sum+=getImageR(targa_rgba,column+1,row,columns,rows);
 93.2735 -				sum+=getImageR(targa_rgba,column-1,row+1,columns,rows);
 93.2736 -				sum+=getImageR(targa_rgba,column,row+1,columns,rows);
 93.2737 -				sum+=getImageR(targa_rgba,column+1,row+1,columns,rows);
 93.2738 -				
 93.2739 -				sum/=9.0f;
 93.2740 -				
 93.2741 -				setImageR(targa_rgba, column, row, columns, rows, (byte)sum);
 93.2742 -				////////////////////
 93.2743 -				sum=0;
 93.2744 -				sum+=getImageG(targa_rgba,column-1,row-1,columns,rows);
 93.2745 -				sum+=getImageG(targa_rgba,column,row-1,columns,rows);
 93.2746 -				sum+=getImageG(targa_rgba,column+1,row-1,columns,rows);
 93.2747 -				sum+=getImageG(targa_rgba,column-1,row,columns,rows);
 93.2748 -				sum+=getImageG(targa_rgba,column,row,columns,rows);
 93.2749 -				sum+=getImageG(targa_rgba,column+1,row,columns,rows);
 93.2750 -				sum+=getImageG(targa_rgba,column-1,row+1,columns,rows);
 93.2751 -				sum+=getImageG(targa_rgba,column,row+1,columns,rows);
 93.2752 -				sum+=getImageG(targa_rgba,column+1,row+1,columns,rows);
 93.2753 -				
 93.2754 -				sum/=9.0f;
 93.2755 -				
 93.2756 -				setImageG(targa_rgba, column, row, columns, rows, (byte)sum);
 93.2757 -				////////////////////////
 93.2758 -				sum=0;
 93.2759 -				sum+=getImageB(targa_rgba,column-1,row-1,columns,rows);
 93.2760 -				sum+=getImageB(targa_rgba,column,row-1,columns,rows);
 93.2761 -				sum+=getImageB(targa_rgba,column+1,row-1,columns,rows);
 93.2762 -				sum+=getImageB(targa_rgba,column-1,row,columns,rows);
 93.2763 -				sum+=getImageB(targa_rgba,column,row,columns,rows);
 93.2764 -				sum+=getImageB(targa_rgba,column+1,row,columns,rows);
 93.2765 -				sum+=getImageB(targa_rgba,column-1,row+1,columns,rows);
 93.2766 -				sum+=getImageB(targa_rgba,column,row+1,columns,rows);
 93.2767 -				sum+=getImageB(targa_rgba,column+1,row+1,columns,rows);
 93.2768 -				
 93.2769 -				sum/=9.0f;
 93.2770 -				
 93.2771 -				setImageB(targa_rgba, column, row, columns, rows, (byte)sum);
 93.2772 -				
 93.2773 -				// "halftoning"
 93.2774 -				/*if((row%5==0)&&(column%5==1))
 93.2775 -				{
 93.2776 -					gris=0;
 93.2777 -					gris+=red;
 93.2778 -					gris+=green;
 93.2779 -					gris+=blue;
 93.2780 -					gris/=3;
 93.2781 -					
 93.2782 -					gris=255-gris;
 93.2783 -					if(gris<0)
 93.2784 -						gris=0;
 93.2785 -						
 93.2786 -						setImageR(targa_rgba, column, row, columns, rows, (byte)gris);
 93.2787 -						setImageG(targa_rgba, column, row, columns, rows, (byte)gris);
 93.2788 -						setImageB(targa_rgba, column, row, columns, rows, (byte)gris);
 93.2789 -					
 93.2790 -				}*/
 93.2791 -			
 93.2792 -			}
 93.2793 -		}
 93.2794 -
 93.2795 -}
 93.2796 -
 93.2797 -int diffSquare(int mean, int val){
 93.2798 -	float variance = (val-mean)/255.0f;
 93.2799 -	float radius = mean<128?mean:255-mean;
 93.2800 -	return mean+(radius*variance);
 93.2801 -}
 93.2802 -
 93.2803 -/****************************
 93.2804 -KUWAHARA ,FAILS SOMEWHERE
 93.2805 -****************************/
 93.2806 -#define KWH_RADIUS 2
 93.2807 -static void mean_variance(int x0, int y0, int x1, int y1, int columns, int rows, byte *targa_rgba, vec4_t mv )
 93.2808 -{
 93.2809 -	short min=255*3, max=0;
 93.2810 -	unsigned short count= 0;
 93.2811 -	short row, column;
 93.2812 -	unsigned short value;
 93.2813 -	vec3_t rgb;
 93.2814 -	
 93.2815 -	mv[0]=mv[1]=mv[2]=mv[3]=0;
 93.2816 -
 93.2817 -	for(row=y0;row<=y1;row++)
 93.2818 -	{
 93.2819 -		for(column=x0;column<=x1;column++)
 93.2820 -		{
 93.2821 -			getImageRGB(targa_rgba,column,row,columns,rows,rgb);
 93.2822 -			
 93.2823 -			VectorAdd(mv,rgb,mv);
 93.2824 -			
 93.2825 -			count++;
 93.2826 -			value=rgb[0]+rgb[1]+rgb[2];
 93.2827 -			if(value<min) min=value;
 93.2828 -			if(value>max) max=value;
 93.2829 -		}
 93.2830 -	}
 93.2831 -
 93.2832 -	mv[0]/=count;
 93.2833 -	mv[1]/=count;
 93.2834 -	mv[2]/=count;
 93.2835 -	mv[3]= (max-min)/3.0f;
 93.2836 -}
 93.2837 -
 93.2838 -
 93.2839 -static void rgb_kuwahara(int x, int y, int columns, int rows, byte *targa_rgba, vec4_t bmv)
 93.2840 -{
 93.2841 -  vec4_t mv;
 93.2842 -	bmv[0]=bmv[1]=bmv[2]=bmv[3]=255;
 93.2843 -	
 93.2844 -	mean_variance(x-KWH_RADIUS, y-KWH_RADIUS, x, y, columns, rows, targa_rgba, mv);
 93.2845 -	if( mv[3] < bmv[3] )
 93.2846 -	{
 93.2847 -		Vector4Copy(mv,bmv);
 93.2848 -	}
 93.2849 -	
 93.2850 -	mean_variance(x, y-KWH_RADIUS, x+KWH_RADIUS, y, columns, rows, targa_rgba, mv);
 93.2851 -	if( mv[3] < bmv[3] )
 93.2852 -	{
 93.2853 -		Vector4Copy(mv,bmv);
 93.2854 -	}
 93.2855 -	
 93.2856 -	mean_variance(x, y, x+KWH_RADIUS, y+KWH_RADIUS, columns, rows, targa_rgba, mv);
 93.2857 -	if( mv[3] < bmv[3] )
 93.2858 -	{
 93.2859 -		Vector4Copy(mv,bmv);
 93.2860 -	}
 93.2861 -	
 93.2862 -	mean_variance(x-KWH_RADIUS, y, x, y+KWH_RADIUS, columns, rows, targa_rgba, mv);
 93.2863 -	if( mv[3] < bmv[3] )
 93.2864 -	{
 93.2865 -		Vector4Copy(mv,bmv);
 93.2866 -	}
 93.2867 -}
 93.2868 -
 93.2869 -static void kuwahara(int columns, int rows, byte *targa_rgba){
 93.2870 -	int		row, column;
 93.2871 -	vec4_t rgbv;
 93.2872 -	
 93.2873 -	for(row=0;row<rows;row++){
 93.2874 -		for(column=0;column<columns;column++){
 93.2875 -			rgb_kuwahara(column, row, columns, rows, targa_rgba, rgbv);
 93.2876 -			setImageRGB(targa_rgba,column,row,columns,rows,rgbv);
 93.2877  		}
 93.2878  	}
 93.2879  }
 93.2880  
 93.2881 -/****************************
 93.2882 -Symmetric Nearest Neighbour
 93.2883 -****************************/
 93.2884 -
 93.2885 -#define SNN_RADIUS 3
 93.2886 -
 93.2887 -static int deltaE(int l1,int a1,int b1,int l2,int a2,int b2)
 93.2888 -{
 93.2889 -	return (l1-l2)*(l1-l2) + (a1-a2)*(a1-a2) + (b1-b2)*(b1-b2);
 93.2890 -}
 93.2891 -
 93.2892 -static void snn(int columns, int rows, byte *targa_rgba)
 93.2893 -{
 93.2894 -	
 93.2895 -	int row, column;
 93.2896 -	unsigned short sumR, sumG, sumB;
 93.2897 -	unsigned short count;
 93.2898 -	short u, v;
 93.2899 -	byte r, g, b;
 93.2900 -	byte r1, g1, b1;
 93.2901 -	byte r2, g2, b2;
 93.2902 -	for(row=0;row<rows;row++){
 93.2903 -		for(column=0;column<columns;column++){
 93.2904 -			sumR=0;
 93.2905 -			sumG=0;
 93.2906 -			sumB=0;
 93.2907 -			count=0;
 93.2908 -			
 93.2909 -			r=getImageR(targa_rgba,column,row,columns,rows);
 93.2910 -			g=getImageG(targa_rgba,column,row,columns,rows);
 93.2911 -			b=getImageB(targa_rgba,column,row,columns,rows);
 93.2912 -			
 93.2913 -			for(v=-SNN_RADIUS;v<=0;v++)
 93.2914 -			{
 93.2915 -				for(u=-SNN_RADIUS;u<=SNN_RADIUS;u++)
 93.2916 -				{
 93.2917 -					if(v==0&&u>=0) break;
 93.2918 -					// Sum pixels values
 93.2919 -					r1=getImageR(targa_rgba,column+u,row+v,columns,rows);
 93.2920 -					g1=getImageG(targa_rgba,column+u,row+v,columns,rows);
 93.2921 -					b1=getImageB(targa_rgba,column+u,row+v,columns,rows);
 93.2922 -					
 93.2923 -					r2=getImageR(targa_rgba,column-u,row-v,columns,rows);
 93.2924 -					g2=getImageG(targa_rgba,column-u,row-v,columns,rows);
 93.2925 -					b2=getImageB(targa_rgba,column-u,row-v,columns,rows);
 93.2926 -					
 93.2927 -					if ( deltaE(r,g,b,r1,g1,b1) < deltaE(r,g,b,r2,g2,b2))
 93.2928 -					{
 93.2929 -						sumR += r1;
 93.2930 -						sumG += g1;
 93.2931 -						sumB += b1;
 93.2932 -					}
 93.2933 -					else
 93.2934 -					{
 93.2935 -						sumR += r2;
 93.2936 -						sumG += g2;
 93.2937 -						sumB += b2;
 93.2938 -					}
 93.2939 -					count++;
 93.2940 -				}
 93.2941 -			}
 93.2942 -			
 93.2943 -			r=(byte)((int)(2*sumR+r)/(int)(2*count+1));
 93.2944 -			g=(byte)((int)(2*sumG+g)/(int)(2*count+1));
 93.2945 -			b=(byte)((int)(2*sumB+b)/(int)(2*count+1));
 93.2946 -			
 93.2947 -			setImageR(targa_rgba,column,row,columns,rows,r);
 93.2948 -			setImageG(targa_rgba,column,row,columns,rows,g);
 93.2949 -			setImageB(targa_rgba,column,row,columns,rows,b);
 93.2950 -		}
 93.2951 -	}
 93.2952 -}
 93.2953 -
 93.2954 -//===================================================================
 93.2955 -
 93.2956 -typedef struct
 93.2957 -{
 93.2958 -	char *ext;
 93.2959 -	void (*ImageLoader)( const char *, unsigned char **, int *, int * );
 93.2960 -} imageExtToLoaderMap_t;
 93.2961 -
 93.2962 -// Note that the ordering indicates the order of preference used
 93.2963 -// when there are multiple images of different formats available
 93.2964 -static imageExtToLoaderMap_t imageLoaders[ ] =
 93.2965 -{
 93.2966 -	{ "tga",  R_LoadTGA },
 93.2967 -	{ "jpg",  R_LoadJPG },
 93.2968 -	{ "jpeg", R_LoadJPG },
 93.2969 -	{ "png",  R_LoadPNG },
 93.2970 -	{ "pcx",  R_LoadPCX },
 93.2971 -	{ "bmp",  R_LoadBMP }
 93.2972 -};
 93.2973 -
 93.2974 -static int numImageLoaders = sizeof( imageLoaders ) /
 93.2975 -		sizeof( imageLoaders[ 0 ] );
 93.2976 -
 93.2977 -/*
 93.2978 -=================
 93.2979 -R_LoadImage
 93.2980 -
 93.2981 -Loads any of the supported image types into a cannonical
 93.2982 -32 bit format.
 93.2983 -=================
 93.2984 -*/
 93.2985 -void R_LoadImage( const char *name, byte **pic, int *width, int *height )
 93.2986 -{
 93.2987 -	qboolean orgNameFailed = qfalse;
 93.2988 -	int i;
 93.2989 -	char localName[ MAX_QPATH ];
 93.2990 -	const char *ext;
 93.2991 -
 93.2992 -	*pic = NULL;
 93.2993 -	*width = 0;
 93.2994 -	*height = 0;
 93.2995 -
 93.2996 -	Q_strncpyz( localName, name, MAX_QPATH );
 93.2997 -
 93.2998 -	ext = COM_GetExtension( localName );
 93.2999 -
 93.3000 -	if( *ext )
 93.3001 -	{
 93.3002 -		// Look for the correct loader and use it
 93.3003 -		for( i = 0; i < numImageLoaders; i++ )
 93.3004 -		{
 93.3005 -			if( !Q_stricmp( ext, imageLoaders[ i ].ext ) )
 93.3006 -			{
 93.3007 -				// Load
 93.3008 -				imageLoaders[ i ].ImageLoader( localName, pic, width, height );
 93.3009 -				break;
 93.3010 -			}
 93.3011 -		}
 93.3012 -
 93.3013 -		// A loader was found
 93.3014 -		if( i < numImageLoaders )
 93.3015 -		{
 93.3016 -			if( *pic == NULL )
 93.3017 -			{
 93.3018 -				// Loader failed, most likely because the file isn't there;
 93.3019 -				// try again without the extension
 93.3020 -				orgNameFailed = qtrue;
 93.3021 -				COM_StripExtension( name, localName, MAX_QPATH );
 93.3022 -			}
 93.3023 -			else
 93.3024 -			{
 93.3025 -				// Something loaded
 93.3026 -				return;
 93.3027 -			}
 93.3028 -		}
 93.3029 -	}
 93.3030 -
 93.3031 -	// Try and find a suitable match using all
 93.3032 -	// the image formats supported
 93.3033 -	for( i = 0; i < numImageLoaders; i++ )
 93.3034 -	{
 93.3035 -		char *altName = va( "%s.%s", localName, imageLoaders[ i ].ext );
 93.3036 -
 93.3037 -		// Load
 93.3038 -		imageLoaders[ i ].ImageLoader( altName, pic, width, height );
 93.3039 -
 93.3040 -		if( *pic )
 93.3041 -		{
 93.3042 -			if( orgNameFailed )
 93.3043 -			{
 93.3044 -				ri.Printf( PRINT_DEVELOPER, "WARNING: %s not present, using %s instead\n",
 93.3045 -						name, altName );
 93.3046 -			}
 93.3047 -
 93.3048 -			break;
 93.3049 -		}
 93.3050 -	}
 93.3051 -	
 93.3052 -	switch(r_celshadalgo->integer)
 93.3053 -	{
 93.3054 -		case 1:
 93.3055 -			kuwahara(*width,*height,*pic);
 93.3056 -			break;
 93.3057 -		case 2:
 93.3058 -			blur(*width,*height,*pic);
 93.3059 -			kuwahara(*width,*height,*pic);
 93.3060 -			break;
 93.3061 -		case 3:
 93.3062 -			kuwahara(*width,*height,*pic);
 93.3063 -			blur(*width,*height,*pic);
 93.3064 -			break;
 93.3065 -		case 4:
 93.3066 -			blur(*width,*height,*pic);
 93.3067 -			kuwahara(*width,*height,*pic);
 93.3068 -			blur(*width,*height,*pic);
 93.3069 -			break;
 93.3070 -		case 5:
 93.3071 -			snn(*width,*height,*pic);
 93.3072 -			break;
 93.3073 -		case 6:
 93.3074 -			blur(*width,*height,*pic);
 93.3075 -			snn(*width,*height,*pic);
 93.3076 -			break;
 93.3077 -		case 7:
 93.3078 -			snn(*width,*height,*pic);
 93.3079 -			blur(*width,*height,*pic);
 93.3080 -			break;
 93.3081 -		case 8:
 93.3082 -			blur(*width,*height,*pic);
 93.3083 -			snn(*width,*height,*pic);
 93.3084 -			blur(*width,*height,*pic);
 93.3085 -			break;
 93.3086 -		default:
 93.3087 -			break;
 93.3088 -	}
 93.3089 -}
 93.3090  
 93.3091  
 93.3092  /*
 93.3093 @@ -1368,384 +2036,1246 @@
 93.3094  Returns NULL if it fails, not a default image.
 93.3095  ==============
 93.3096  */
 93.3097 -image_t	*R_FindImageFile( const char *name, qboolean mipmap, qboolean allowPicmip, int glWrapClampMode ) {
 93.3098 -	image_t	*image;
 93.3099 -	int		width, height;
 93.3100 -	byte	*pic;
 93.3101 -	long	hash;
 93.3102 -
 93.3103 -	if (!name) {
 93.3104 +image_t        *R_FindImageFile(const char *name, int bits, filterType_t filterType, wrapType_t wrapType)
 93.3105 +{
 93.3106 +	image_t        *image = NULL;
 93.3107 +	int             width = 0, height = 0;
 93.3108 +	byte           *pic = NULL;
 93.3109 +	long            hash;
 93.3110 +	char            buffer[1024];
 93.3111 +	char            ddsName[1024];
 93.3112 +	char           *buffer_p;
 93.3113 +	unsigned long   diff;
 93.3114 +
 93.3115 +	if(!name)
 93.3116 +	{
 93.3117  		return NULL;
 93.3118  	}
 93.3119  
 93.3120 -	hash = generateHashValue(name);
 93.3121 -
 93.3122 -	//
 93.3123 +	Q_strncpyz(buffer, name, sizeof(buffer));
 93.3124 +	hash = generateHashValue(buffer);
 93.3125 +
 93.3126 +//  ri.Printf(PRINT_ALL, "R_FindImageFile: buffer '%s'\n", buffer);
 93.3127 +
 93.3128  	// see if the image is already loaded
 93.3129 -	//
 93.3130 -	for (image=hashTable[hash]; image; image=image->next) {
 93.3131 -		if ( !strcmp( name, image->imgName ) ) {
 93.3132 +	for(image = hashTable[hash]; image; image = image->next)
 93.3133 +	{
 93.3134 +		if(!Q_stricmpn(buffer, image->name, sizeof(image->name)))
 93.3135 +		{
 93.3136  			// the white image can be used with any set of parms, but other mismatches are errors
 93.3137 -			if ( strcmp( name, "*white" ) ) {
 93.3138 -				if ( image->mipmap != mipmap ) {
 93.3139 -					ri.Printf( PRINT_DEVELOPER, "WARNING: reused image %s with mixed mipmap parm\n", name );
 93.3140 +			if(Q_stricmp(buffer, "_white"))
 93.3141 +			{
 93.3142 +				diff = bits ^ image->bits;
 93.3143 +
 93.3144 +				/*
 93.3145 +				   if(diff & IF_NOMIPMAPS)
 93.3146 +				   {
 93.3147 +				   ri.Printf(PRINT_DEVELOPER, "WARNING: reused image %s with mixed mipmap parm\n", name);
 93.3148 +				   }
 93.3149 +				 */
 93.3150 +
 93.3151 +				if(diff & IF_NOPICMIP)
 93.3152 +				{
 93.3153 +					ri.Printf(PRINT_DEVELOPER, "WARNING: reused image %s with mixed allowPicmip parm\n", name);
 93.3154  				}
 93.3155 -				if ( image->allowPicmip != allowPicmip ) {
 93.3156 -					ri.Printf( PRINT_DEVELOPER, "WARNING: reused image %s with mixed allowPicmip parm\n", name );
 93.3157 -				}
 93.3158 -				if ( image->wrapClampMode != glWrapClampMode ) {
 93.3159 -					ri.Printf( PRINT_ALL, "WARNING: reused image %s with mixed glWrapClampMode parm\n", name );
 93.3160 +
 93.3161 +				if(image->wrapType != wrapType)
 93.3162 +				{
 93.3163 +					ri.Printf(PRINT_ALL, "WARNING: reused image %s with mixed glWrapType parm\n", name);
 93.3164  				}
 93.3165  			}
 93.3166  			return image;
 93.3167  		}
 93.3168  	}
 93.3169  
 93.3170 -	//
 93.3171 +	if(glConfig.textureCompression == TC_S3TC && !(bits & IF_NOCOMPRESSION) && Q_stricmpn(name, "fonts", 5))
 93.3172 +	{
 93.3173 +		Q_strncpyz(ddsName, name, sizeof(ddsName));
 93.3174 +		Com_StripExtension(ddsName, ddsName, sizeof(ddsName));
 93.3175 +		Q_strcat(ddsName, sizeof(ddsName), ".dds");
 93.3176 +
 93.3177 +		// try to load a customized .dds texture
 93.3178 +		image = R_LoadDDSImage(ddsName, bits, filterType, wrapType);
 93.3179 +		if(image != NULL)
 93.3180 +		{
 93.3181 +			ri.Printf(PRINT_ALL, "found custom .dds '%s'\n", ddsName);
 93.3182 +			return image;
 93.3183 +		}
 93.3184 +	}
 93.3185 +#if 0
 93.3186 +	else if(r_tryCachedDDSImages->integer && !(bits & IF_NOCOMPRESSION) && Q_strncasecmp(name, "fonts", 5))
 93.3187 +	{
 93.3188 +		Q_strncpyz(ddsName, "dds/", sizeof(ddsName));
 93.3189 +		Q_strcat(ddsName, sizeof(ddsName), name);
 93.3190 +		Com_StripExtension(ddsName, ddsName, sizeof(ddsName));
 93.3191 +		Q_strcat(ddsName, sizeof(ddsName), ".dds");
 93.3192 +
 93.3193 +		// try to load a cached .dds texture from the XreaL/<mod>/dds/ folder
 93.3194 +		image = R_LoadDDSImage(ddsName, bits, filterType, wrapType);
 93.3195 +		if(image != NULL)
 93.3196 +		{
 93.3197 +			ri.Printf(PRINT_ALL, "found cached .dds '%s'\n", ddsName);
 93.3198 +			return image;
 93.3199 +		}
 93.3200 +	}
 93.3201 +#endif
 93.3202 +
 93.3203  	// load the pic from disk
 93.3204 -	//
 93.3205 -	R_LoadImage( name, &pic, &width, &height );
 93.3206 -	if ( pic == NULL ) {
 93.3207 +	buffer_p = &buffer[0];
 93.3208 +	R_LoadImage(&buffer_p, &pic, &width, &height, &bits);
 93.3209 +	if(pic == NULL)
 93.3210 +	{
 93.3211  		return NULL;
 93.3212  	}
 93.3213  
 93.3214 -	image = R_CreateImage( ( char * ) name, pic, width, height, mipmap, allowPicmip, glWrapClampMode );
 93.3215 -	ri.Free( pic );
 93.3216 +#if 0
 93.3217 +	//if(r_tryCachedDDSImages->integer && !(bits & IF_NOCOMPRESSION) && Q_strncasecmp(name, "fonts", 5))
 93.3218 +	{
 93.3219 +		// try to cache a .dds texture to the XreaL/<mod>/dds/ folder
 93.3220 +		SavePNG(ddsName, pic, width, height, 4, qtrue);
 93.3221 +	}
 93.3222 +#endif
 93.3223 +
 93.3224 +	image = R_CreateImage((char *)buffer, pic, width, height, bits, filterType, wrapType);
 93.3225 +	ri.Free(pic);
 93.3226  	return image;
 93.3227  }
 93.3228  
 93.3229  
 93.3230 -/*
 93.3231 -================
 93.3232 -R_CreateDlightImage
 93.3233 -================
 93.3234 -*/
 93.3235 -#define	DLIGHT_SIZE	16
 93.3236 -static void R_CreateDlightImage( void ) {
 93.3237 -	int		x,y;
 93.3238 -	byte	data[DLIGHT_SIZE][DLIGHT_SIZE][4];
 93.3239 -	int		b;
 93.3240 -
 93.3241 -	// make a centered inverse-square falloff blob for dynamic lighting
 93.3242 -	for (x=0 ; x<DLIGHT_SIZE ; x++) {
 93.3243 -		for (y=0 ; y<DLIGHT_SIZE ; y++) {
 93.3244 -			float	d;
 93.3245 -
 93.3246 -			d = ( DLIGHT_SIZE/2 - 0.5f - x ) * ( DLIGHT_SIZE/2 - 0.5f - x ) +
 93.3247 -				( DLIGHT_SIZE/2 - 0.5f - y ) * ( DLIGHT_SIZE/2 - 0.5f - y );
 93.3248 -			b = 4000 / d;
 93.3249 -			if (b > 255) {
 93.3250 -				b = 255;
 93.3251 -			} else if ( b < 75 ) {
 93.3252 -				b = 0;
 93.3253 -			}
 93.3254 -			data[y][x][0] = 
 93.3255 -			data[y][x][1] = 
 93.3256 -			data[y][x][2] = b;
 93.3257 -			data[y][x][3] = 255;			
 93.3258 +static ID_INLINE void SwapPixel(byte * inout, int x, int y, int x2, int y2, int width, int height)
 93.3259 +{
 93.3260 +	byte			color[4];
 93.3261 +	byte			color2[4];
 93.3262 +
 93.3263 +	color[0] =  inout[4 * (y * width + x) + 0];
 93.3264 +	color[1] =  inout[4 * (y * width + x) + 1];
 93.3265 +	color[2] =  inout[4 * (y * width + x) + 2];
 93.3266 +	color[3] =  inout[4 * (y * width + x) + 3];
 93.3267 +
 93.3268 +	color2[0] =  inout[4 * (y2 * width + x2) + 0];
 93.3269 +	color2[1] =  inout[4 * (y2 * width + x2) + 1];
 93.3270 +	color2[2] =  inout[4 * (y2 * width + x2) + 2];
 93.3271 +	color2[3] =  inout[4 * (y2 * width + x2) + 3];
 93.3272 +
 93.3273 +	inout[4 * (y * width + x) + 0] = color2[0];
 93.3274 +	inout[4 * (y * width + x) + 1] = color2[1];
 93.3275 +	inout[4 * (y * width + x) + 2] = color2[2];
 93.3276 +	inout[4 * (y * width + x) + 3] = color2[3];
 93.3277 +
 93.3278 +	inout[4 * (y2 * width + x2) + 0] = color[0];
 93.3279 +	inout[4 * (y2 * width + x2) + 1] = color[1];
 93.3280 +	inout[4 * (y2 * width + x2) + 2] = color[2];
 93.3281 +	inout[4 * (y2 * width + x2) + 3] = color[3];
 93.3282 +}
 93.3283 +
 93.3284 +static void R_Flip(byte * in, int width, int height)
 93.3285 +{
 93.3286 +	int             x, y;
 93.3287 +	byte           *out;
 93.3288 +
 93.3289 +	out = in;
 93.3290 +
 93.3291 +	for(y = 0; y < height; y++)
 93.3292 +	{
 93.3293 +		for(x = 0; x < width / 2; x++)
 93.3294 +		{
 93.3295 +			SwapPixel(in, x, y, (width -1 -x), y, width, height);
 93.3296  		}
 93.3297  	}
 93.3298 -	tr.dlightImage = R_CreateImage("*dlight", (byte *)data, DLIGHT_SIZE, DLIGHT_SIZE, qfalse, qfalse, GL_CLAMP_TO_EDGE );
 93.3299  }
 93.3300  
 93.3301 -
 93.3302 -/*
 93.3303 -=================
 93.3304 -R_InitFogTable
 93.3305 -=================
 93.3306 -*/
 93.3307 -void R_InitFogTable( void ) {
 93.3308 -	int		i;
 93.3309 -	float	d;
 93.3310 -	float	exp;
 93.3311 -	
 93.3312 -	exp = 0.5;
 93.3313 -
 93.3314 -	for ( i = 0 ; i < FOG_TABLE_SIZE ; i++ ) {
 93.3315 -		d = pow ( (float)i/(FOG_TABLE_SIZE-1), exp );
 93.3316 -
 93.3317 -		tr.fogTable[i] = d;
 93.3318 +static void R_Flop(byte * in, int width, int height)
 93.3319 +{
 93.3320 +	int             x, y;
 93.3321 +	byte           *out;
 93.3322 +
 93.3323 +	out = in;
 93.3324 +
 93.3325 +	for(y = 0; y < height / 2; y++)
 93.3326 +	{
 93.3327 +		for(x = 0; x < width; x++)
 93.3328 +		{
 93.3329 +			SwapPixel(in, x, y, x, (height -1 -y), width, height);
 93.3330 +		}
 93.3331  	}
 93.3332  }
 93.3333  
 93.3334 -/*
 93.3335 -================
 93.3336 -R_FogFactor
 93.3337 -
 93.3338 -Returns a 0.0 to 1.0 fog density value
 93.3339 -This is called for each texel of the fog texture on startup
 93.3340 -and for each vertex of transparent shaders in fog dynamically
 93.3341 -================
 93.3342 -*/
 93.3343 -float	R_FogFactor( float s, float t ) {
 93.3344 -	float	d;
 93.3345 -
 93.3346 -	s -= 1.0/512;
 93.3347 -	if ( s < 0 ) {
 93.3348 -		return 0;
 93.3349 -	}
 93.3350 -	if ( t < 1.0/32 ) {
 93.3351 -		return 0;
 93.3352 -	}
 93.3353 -	if ( t < 31.0/32 ) {
 93.3354 -		s *= (t - 1.0f/32.0f) / (30.0f/32.0f);
 93.3355 -	}
 93.3356 -
 93.3357 -	// we need to leave a lot of clamp range
 93.3358 -	s *= 8;
 93.3359 -
 93.3360 -	if ( s > 1.0 ) {
 93.3361 -		s = 1.0;
 93.3362 -	}
 93.3363 -
 93.3364 -	d = tr.fogTable[ (int)(s * (FOG_TABLE_SIZE-1)) ];
 93.3365 -
 93.3366 -	return d;
 93.3367 -}
 93.3368 -
 93.3369 -/*
 93.3370 -================
 93.3371 -R_CreateFogImage
 93.3372 -================
 93.3373 -*/
 93.3374 -#define	FOG_S	256
 93.3375 -#define	FOG_T	32
 93.3376 -static void R_CreateFogImage( void ) {
 93.3377 -	int		x,y;
 93.3378 -	byte	*data;
 93.3379 -	float	g;
 93.3380 -	float	d;
 93.3381 -	float	borderColor[4];
 93.3382 -
 93.3383 -	data = ri.Hunk_AllocateTempMemory( FOG_S * FOG_T * 4 );
 93.3384 -
 93.3385 -	g = 2.0;
 93.3386 -
 93.3387 -	// S is distance, T is depth
 93.3388 -	for (x=0 ; x<FOG_S ; x++) {
 93.3389 -		for (y=0 ; y<FOG_T ; y++) {
 93.3390 -			d = R_FogFactor( ( x + 0.5f ) / FOG_S, ( y + 0.5f ) / FOG_T );
 93.3391 -
 93.3392 -			data[(y*FOG_S+x)*4+0] = 
 93.3393 -			data[(y*FOG_S+x)*4+1] = 
 93.3394 -			data[(y*FOG_S+x)*4+2] = 255;
 93.3395 -			data[(y*FOG_S+x)*4+3] = 255*d;
 93.3396 +static void R_Rotate(byte * in, int width, int height, int degrees)
 93.3397 +{
 93.3398 +	byte			color[4];
 93.3399 +	int             x, y, x2, y2;
 93.3400 +	byte           *out, *tmp;
 93.3401 +
 93.3402 +	tmp = Com_Allocate(width * height * 4);
 93.3403 +
 93.3404 +	// rotate into tmp buffer
 93.3405 +	for(y = 0; y < height; y++)
 93.3406 +	{
 93.3407 +		for(x = 0; x < width; x++)
 93.3408 +		{
 93.3409 +			color[0] =  in[4 * (y * width + x) + 0];
 93.3410 +			color[1] =  in[4 * (y * width + x) + 1];
 93.3411 +			color[2] =  in[4 * (y * width + x) + 2];
 93.3412 +			color[3] =  in[4 * (y * width + x) + 3];
 93.3413 +
 93.3414 +			if(degrees == 90)
 93.3415 +			{
 93.3416 +				x2 = y;
 93.3417 +				y2 = (height -(1 + x));
 93.3418 +
 93.3419 +				tmp[4 * (y2 * width + x2) + 0] = color[0];
 93.3420 +				tmp[4 * (y2 * width + x2) + 1] = color[1];
 93.3421 +				tmp[4 * (y2 * width + x2) + 2] = color[2];
 93.3422 +				tmp[4 * (y2 * width + x2) + 3] = color[3];
 93.3423 +			}
 93.3424 +			else if(degrees == -90)
 93.3425 +			{
 93.3426 +				x2 = (width -(1 + y));
 93.3427 +				y2 = x;
 93.3428 +
 93.3429 +				tmp[4 * (y2 * width + x2) + 0] = color[0];
 93.3430 +				tmp[4 * (y2 * width + x2) + 1] = color[1];
 93.3431 +				tmp[4 * (y2 * width + x2) + 2] = color[2];
 93.3432 +				tmp[4 * (y2 * width + x2) + 3] = color[3];
 93.3433 +			}
 93.3434 +			else
 93.3435 +			{
 93.3436 +				tmp[4 * (y * width + x) + 0] = color[0];
 93.3437 +				tmp[4 * (y * width + x) + 1] = color[1];
 93.3438 +				tmp[4 * (y * width + x) + 2] = color[2];
 93.3439 +				tmp[4 * (y * width + x) + 3] = color[3];
 93.3440 +			}
 93.3441 +
 93.3442  		}
 93.3443  	}
 93.3444 -	// standard openGL clamping doesn't really do what we want -- it includes
 93.3445 -	// the border color at the edges.  OpenGL 1.2 has clamp-to-edge, which does
 93.3446 -	// what we want.
 93.3447 -	tr.fogImage = R_CreateImage("*fog", (byte *)data, FOG_S, FOG_T, qfalse, qfalse, GL_CLAMP_TO_EDGE );
 93.3448 -	ri.Hunk_FreeTempMemory( data );
 93.3449 -
 93.3450 -	borderColor[0] = 1.0;
 93.3451 -	borderColor[1] = 1.0;
 93.3452 -	borderColor[2] = 1.0;
 93.3453 -	borderColor[3] = 1;
 93.3454 -
 93.3455 -	qglTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor );
 93.3456 +
 93.3457 +	// copy back to input
 93.3458 +	out = in;
 93.3459 +	for(y = 0; y < height; y++)
 93.3460 +	{
 93.3461 +		for(x = 0; x < width; x++)
 93.3462 +		{
 93.3463 +			out[4 * (y * width + x) + 0] = tmp[4 * (y * width + x) + 0];
 93.3464 +			out[4 * (y * width + x) + 1] = tmp[4 * (y * width + x) + 1];
 93.3465 +			out[4 * (y * width + x) + 2] = tmp[4 * (y * width + x) + 2];
 93.3466 +			out[4 * (y * width + x) + 3] = tmp[4 * (y * width + x) + 3];
 93.3467 +		}
 93.3468 +	}
 93.3469 +
 93.3470 +	Com_Dealloc(tmp);
 93.3471  }
 93.3472  
 93.3473  /*
 93.3474 +===============
 93.3475 +R_FindCubeImage
 93.3476 +
 93.3477 +Finds or loads the given image.
 93.3478 +Returns NULL if it fails, not a default image.
 93.3479 +
 93.3480 +Tr3B: fear the use of goto
 93.3481 +==============
 93.3482 +*/
 93.3483 +image_t        *R_FindCubeImage(const char *name, int bits, filterType_t filterType, wrapType_t wrapType)
 93.3484 +{
 93.3485 +	int             i;
 93.3486 +	image_t        *image = NULL;
 93.3487 +	int             width = 0, height = 0;
 93.3488 +	byte           *pic[6];
 93.3489 +	long            hash;
 93.3490 +
 93.3491 +	static char    *openglSuffices[6] = { "px", "nx", "py", "ny", "pz", "nz" };
 93.3492 +
 93.3493 +	/*
 93.3494 +		convert $1_forward.tga -flip -rotate 90 $1_px.png
 93.3495 +		convert $1_back.tga -flip -rotate -90 $1_nx.png
 93.3496 +
 93.3497 +		convert $1_left.tga -flip $1_py.png
 93.3498 +		convert $1_right.tga -flop $1_ny.png
 93.3499 +
 93.3500 +		convert $1_up.tga -flip -rotate 90 $1_pz.png
 93.3501 +		convert $1_down.tga -flop -rotate -90 $1_nz.png
 93.3502 +	 */
 93.3503 +
 93.3504 +	static char    *doom3Suffices[6] = { "forward", "back", "left", "right", "up", "down" };
 93.3505 +	static qboolean doom3FlipX[6] = { qtrue,	qtrue, 	qfalse,	qtrue,	qtrue,	qfalse };
 93.3506 +	static qboolean doom3FlipY[6] = { qfalse,	qfalse,	qtrue,	qfalse,	qfalse,	qtrue };
 93.3507 +	static int		doom3Rot[6] =	{ 90, 		-90,	0,		0,		90,		-90 };
 93.3508 +
 93.3509 +	/*
 93.3510 +		convert $1_rt.tga -flip -rotate 90 $1_px.tga
 93.3511 +		convert $1_lf.tga -flip -rotate -90 $1_nx.tga
 93.3512 +
 93.3513 +		convert $1_bk.tga -flip $1_py.tga
 93.3514 +		convert $1_ft.tga -flop $1_ny.tga
 93.3515 +
 93.3516 +		convert $1_up.tga -flip -rotate 90 $1_pz.tga
 93.3517 +		convert $1_dn.tga -flop -rotate -90 $1_nz.tga
 93.3518 +	 */
 93.3519 +	static char    *quakeSuffices[6] = { "rt", "lf", "bk", "ft", "up", "dn" };
 93.3520 +	static qboolean quakeFlipX[6] = { qtrue,	qtrue, 	qfalse,	qtrue,	qtrue,	qfalse };
 93.3521 +	static qboolean quakeFlipY[6] = { qfalse,	qfalse,	qtrue,	qfalse,	qfalse,	qtrue };
 93.3522 +	static int		quakeRot[6] =	{ 90, 		-90,	0,		0,		90,		-90 };
 93.3523 +
 93.3524 +
 93.3525 +	int             bitsIgnore;
 93.3526 +	char            buffer[1024], filename[1024];
 93.3527 +	char            ddsName[1024];
 93.3528 +	char           *filename_p;
 93.3529 +
 93.3530 +	if(!name)
 93.3531 +	{
 93.3532 +		return NULL;
 93.3533 +	}
 93.3534 +
 93.3535 +	Q_strncpyz(buffer, name, sizeof(buffer));
 93.3536 +	hash = generateHashValue(buffer);
 93.3537 +
 93.3538 +	// see if the image is already loaded
 93.3539 +	for(image = hashTable[hash]; image; image = image->next)
 93.3540 +	{
 93.3541 +		if(!Q_stricmp(buffer, image->name))
 93.3542 +		{
 93.3543 +			return image;
 93.3544 +		}
 93.3545 +	}
 93.3546 +
 93.3547 +
 93.3548 +	if(glConfig.textureCompression == TC_S3TC && !(bits & IF_NOCOMPRESSION) && Q_stricmpn(name, "fonts", 5))
 93.3549 +	{
 93.3550 +		Q_strncpyz(ddsName, name, sizeof(ddsName));
 93.3551 +		Com_StripExtension(ddsName, ddsName, sizeof(ddsName));
 93.3552 +		Q_strcat(ddsName, sizeof(ddsName), ".dds");
 93.3553 +
 93.3554 +		// try to load a customized .dds texture
 93.3555 +		image = R_LoadDDSImage(ddsName, bits, filterType, wrapType);
 93.3556 +		if(image != NULL)
 93.3557 +		{
 93.3558 +			ri.Printf(PRINT_ALL, "found custom .dds '%s'\n", ddsName);
 93.3559 +			return image;
 93.3560 +		}
 93.3561 +	}
 93.3562 +#if 0
 93.3563 +	else if(r_tryCachedDDSImages->integer && !(bits & IF_NOCOMPRESSION) && Q_strncasecmp(name, "fonts", 5))
 93.3564 +	{
 93.3565 +		Q_strncpyz(ddsName, "dds/", sizeof(ddsName));
 93.3566 +		Q_strcat(ddsName, sizeof(ddsName), name);
 93.3567 +		Com_StripExtension(ddsName, ddsName, sizeof(ddsName));
 93.3568 +		Q_strcat(ddsName, sizeof(ddsName), ".dds");
 93.3569 +
 93.3570 +		// try to load a cached .dds texture from the XreaL/<mod>/dds/ folder
 93.3571 +		image = R_LoadDDSImage(ddsName, bits, filterType, wrapType);
 93.3572 +		if(image != NULL)
 93.3573 +		{
 93.3574 +			ri.Printf(PRINT_ALL, "found cached .dds '%s'\n", ddsName);
 93.3575 +			return image;
 93.3576 +		}
 93.3577 +	}
 93.3578 +#endif
 93.3579 +
 93.3580 +	for(i = 0; i < 6; i++)
 93.3581 +	{
 93.3582 +		pic[i] = NULL;
 93.3583 +	}
 93.3584 +
 93.3585 +	for(i = 0; i < 6; i++)
 93.3586 +	{
 93.3587 +		Com_sprintf(filename, sizeof(filename), "%s_%s", buffer, openglSuffices[i]);
 93.3588 +
 93.3589 +		filename_p = &filename[0];
 93.3590 +		R_LoadImage(&filename_p, &pic[i], &width, &height, &bitsIgnore);
 93.3591 +
 93.3592 +		if(!pic[i] || width != height)
 93.3593 +		{
 93.3594 +			image = NULL;
 93.3595 +			goto tryDoom3Suffices;
 93.3596 +		}
 93.3597 +	}
 93.3598 +	goto createCubeImage;
 93.3599 +
 93.3600 +  tryDoom3Suffices:
 93.3601 +	for(i = 0; i < 6; i++)
 93.3602 +  	{
 93.3603 +  		Com_sprintf(filename, sizeof(filename), "%s_%s", buffer, doom3Suffices[i]);
 93.3604 +
 93.3605 +  		filename_p = &filename[0];
 93.3606 +  		R_LoadImage(&filename_p, &pic[i], &width, &height, &bitsIgnore);
 93.3607 +
 93.3608 +  		if(!pic[i] || width != height)
 93.3609 +		{
 93.3610 +			image = NULL;
 93.3611 +			goto tryQuakeSuffices;
 93.3612 +		}
 93.3613 +
 93.3614 +  		if(doom3FlipX[i])
 93.3615 +  		{
 93.3616 +  			R_Flip(pic[i], width, height);
 93.3617 +  		}
 93.3618 +
 93.3619 +  		if(doom3FlipY[i])
 93.3620 +		{
 93.3621 +			R_Flop(pic[i], width, height);
 93.3622 +		}
 93.3623 +
 93.3624 +  		R_Rotate(pic[i], width, height, doom3Rot[i]);
 93.3625 +  	}
 93.3626 +	goto createCubeImage;
 93.3627 +
 93.3628 +  tryQuakeSuffices:
 93.3629 +	for(i = 0; i < 6; i++)
 93.3630 +	{
 93.3631 +		Com_sprintf(filename, sizeof(filename), "%s_%s", buffer, quakeSuffices[i]);
 93.3632 +
 93.3633 +		filename_p = &filename[0];
 93.3634 +		R_LoadImage(&filename_p, &pic[i], &width, &height, &bitsIgnore);
 93.3635 +
 93.3636 +		if(!pic[i] || width != height)
 93.3637 +		{
 93.3638 +			image = NULL;
 93.3639 +			goto skipCubeImage;
 93.3640 +		}
 93.3641 +
 93.3642 +		if(quakeFlipX[i])
 93.3643 +		{
 93.3644 +			R_Flip(pic[i], width, height);
 93.3645 +		}
 93.3646 +
 93.3647 +		if(quakeFlipY[i])
 93.3648 +		{
 93.3649 +			R_Flop(pic[i], width, height);
 93.3650 +		}
 93.3651 +
 93.3652 +		R_Rotate(pic[i], width, height, quakeRot[i]);
 93.3653 +	}
 93.3654 +
 93.3655 +  createCubeImage:
 93.3656 +	image = R_CreateCubeImage((char *)buffer, (const byte **)pic, width, height, bits, filterType, wrapType);
 93.3657 +
 93.3658 +  skipCubeImage:
 93.3659 +	for(i = 0; i < 6; i++)
 93.3660 +	{
 93.3661 +		if(pic[i])
 93.3662 +			ri.Free(pic[i]);
 93.3663 +	}
 93.3664 +	return image;
 93.3665 +}
 93.3666 +
 93.3667 +
 93.3668 +
 93.3669 +/*
 93.3670  ==================
 93.3671  R_CreateDefaultImage
 93.3672  ==================
 93.3673  */
 93.3674 -#define	DEFAULT_SIZE	16
 93.3675 -static void R_CreateDefaultImage( void ) {
 93.3676 -	int		x;
 93.3677 -	byte	data[DEFAULT_SIZE][DEFAULT_SIZE][4];
 93.3678 +#define	DEFAULT_SIZE	128
 93.3679 +static void R_CreateDefaultImage(void)
 93.3680 +{
 93.3681 +	int             x;
 93.3682 +	byte            data[DEFAULT_SIZE][DEFAULT_SIZE][4];
 93.3683  
 93.3684  	// the default image will be a box, to allow you to see the mapping coordinates
 93.3685 -	Com_Memset( data, 32, sizeof( data ) );
 93.3686 -	for ( x = 0 ; x < DEFAULT_SIZE ; x++ ) {
 93.3687 -		data[0][x][0] =
 93.3688 -		data[0][x][1] =
 93.3689 -		data[0][x][2] =
 93.3690 -		data[0][x][3] = 255;
 93.3691 -
 93.3692 -		data[x][0][0] =
 93.3693 -		data[x][0][1] =
 93.3694 -		data[x][0][2] =
 93.3695 -		data[x][0][3] = 255;
 93.3696 -
 93.3697 -		data[DEFAULT_SIZE-1][x][0] =
 93.3698 -		data[DEFAULT_SIZE-1][x][1] =
 93.3699 -		data[DEFAULT_SIZE-1][x][2] =
 93.3700 -		data[DEFAULT_SIZE-1][x][3] = 255;
 93.3701 -
 93.3702 -		data[x][DEFAULT_SIZE-1][0] =
 93.3703 -		data[x][DEFAULT_SIZE-1][1] =
 93.3704 -		data[x][DEFAULT_SIZE-1][2] =
 93.3705 -		data[x][DEFAULT_SIZE-1][3] = 255;
 93.3706 +	Com_Memset(data, 32, sizeof(data));
 93.3707 +	for(x = 0; x < DEFAULT_SIZE; x++)
 93.3708 +	{
 93.3709 +		data[0][x][0] = data[0][x][1] = data[0][x][2] = data[0][x][3] = 255;
 93.3710 +		data[x][0][0] = data[x][0][1] = data[x][0][2] = data[x][0][3] = 255;
 93.3711 +
 93.3712 +		data[DEFAULT_SIZE - 1][x][0] =
 93.3713 +			data[DEFAULT_SIZE - 1][x][1] = data[DEFAULT_SIZE - 1][x][2] = data[DEFAULT_SIZE - 1][x][3] = 255;
 93.3714 +
 93.3715 +		data[x][DEFAULT_SIZE - 1][0] =
 93.3716 +			data[x][DEFAULT_SIZE - 1][1] = data[x][DEFAULT_SIZE - 1][2] = data[x][DEFAULT_SIZE - 1][3] = 255;
 93.3717  	}
 93.3718 -	tr.defaultImage = R_CreateImage("*default", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, qtrue, qfalse, GL_REPEAT );
 93.3719 +	tr.defaultImage = R_CreateImage("_default", (byte *) data, DEFAULT_SIZE, DEFAULT_SIZE, IF_NOPICMIP, FT_DEFAULT, WT_REPEAT);
 93.3720  }
 93.3721  
 93.3722 +static void R_CreateNoFalloffImage(void)
 93.3723 +{
 93.3724 +	byte            data[DEFAULT_SIZE][DEFAULT_SIZE][4];
 93.3725 +
 93.3726 +	// we use a solid white image instead of disabling texturing
 93.3727 +	Com_Memset(data, 255, sizeof(data));
 93.3728 +	tr.noFalloffImage = R_CreateImage("_noFalloff", (byte *) data, 8, 8, IF_NOPICMIP, FT_LINEAR, WT_EDGE_CLAMP);
 93.3729 +}
 93.3730 +
 93.3731 +#define	ATTENUATION_XY_SIZE	128
 93.3732 +static void R_CreateAttenuationXYImage(void)
 93.3733 +{
 93.3734 +	int             x, y;
 93.3735 +	byte            data[ATTENUATION_XY_SIZE][ATTENUATION_XY_SIZE][4];
 93.3736 +	int             b;
 93.3737 +
 93.3738 +	// make a centered inverse-square falloff blob for dynamic lighting
 93.3739 +	for(x = 0; x < ATTENUATION_XY_SIZE; x++)
 93.3740 +	{
 93.3741 +		for(y = 0; y < ATTENUATION_XY_SIZE; y++)
 93.3742 +		{
 93.3743 +			float           d;
 93.3744 +
 93.3745 +			d = (ATTENUATION_XY_SIZE / 2 - 0.5f - x) * (ATTENUATION_XY_SIZE / 2 - 0.5f - x) +
 93.3746 +				(ATTENUATION_XY_SIZE / 2 - 0.5f - y) * (ATTENUATION_XY_SIZE / 2 - 0.5f - y);
 93.3747 +			b = 4000 / d;
 93.3748 +			if(b > 255)
 93.3749 +			{
 93.3750 +				b = 255;
 93.3751 +			}
 93.3752 +			else if(b < 75)
 93.3753 +			{
 93.3754 +				b = 0;
 93.3755 +			}
 93.3756 +			data[y][x][0] = data[y][x][1] = data[y][x][2] = b;
 93.3757 +			data[y][x][3] = 255;
 93.3758 +		}
 93.3759 +	}
 93.3760 +	tr.attenuationXYImage =
 93.3761 +		R_CreateImage("_attenuationXY", (byte *) data, ATTENUATION_XY_SIZE, ATTENUATION_XY_SIZE, IF_NOPICMIP, FT_LINEAR,
 93.3762 +					  WT_CLAMP);
 93.3763 +}
 93.3764 +
 93.3765 +static void R_CreateContrastRenderFBOImage(void)
 93.3766 +{
 93.3767 +	int             width, height;
 93.3768 +	byte           *data;
 93.3769 +
 93.3770 +	if(glConfig.textureNPOTAvailable)
 93.3771 +	{
 93.3772 +		width = glConfig.vidWidth * 0.25f;
 93.3773 +		height = glConfig.vidHeight * 0.25f;
 93.3774 +	}
 93.3775 +	else
 93.3776 +	{
 93.3777 +		width = NearestPowerOfTwo(glConfig.vidWidth) * 0.25f;
 93.3778 +		height = NearestPowerOfTwo(glConfig.vidHeight) * 0.25f;
 93.3779 +	}
 93.3780 +
 93.3781 +	data = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.3782 +
 93.3783 +	if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
 93.3784 +	{
 93.3785 +		tr.contrastRenderFBOImage = R_CreateImage("_contrastRenderFBO", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION | IF_RGBA16F, FT_LINEAR, WT_CLAMP);
 93.3786 +	}
 93.3787 +	else
 93.3788 +	{
 93.3789 +		tr.contrastRenderFBOImage = R_CreateImage("_contrastRenderFBO", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_LINEAR, WT_CLAMP);
 93.3790 +	}
 93.3791 +
 93.3792 +	ri.Hunk_FreeTempMemory(data);
 93.3793 +}
 93.3794 +
 93.3795 +static void R_CreateBloomRenderFBOImage(void)
 93.3796 +{
 93.3797 +	int				i;
 93.3798 +	int             width, height;
 93.3799 +	byte           *data;
 93.3800 +
 93.3801 +	if(glConfig.textureNPOTAvailable)
 93.3802 +	{
 93.3803 +		width = glConfig.vidWidth * 0.25f;
 93.3804 +		height = glConfig.vidHeight * 0.25f;
 93.3805 +	}
 93.3806 +	else
 93.3807 +	{
 93.3808 +		width = NearestPowerOfTwo(glConfig.vidWidth) * 0.25f;
 93.3809 +		height = NearestPowerOfTwo(glConfig.vidHeight) * 0.25f;
 93.3810 +	}
 93.3811 +
 93.3812 +	data = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.3813 +
 93.3814 +	for(i = 0; i < 2; i++)
 93.3815 +	{
 93.3816 +		if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
 93.3817 +		{
 93.3818 +			tr.bloomRenderFBOImage[i] = R_CreateImage(va("_bloomRenderFBO%d", i), data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION | IF_RGBA16F, FT_LINEAR, WT_CLAMP);
 93.3819 +		}
 93.3820 +		else
 93.3821 +		{
 93.3822 +			tr.bloomRenderFBOImage[i] = R_CreateImage(va("_bloomRenderFBO%d", i), data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_LINEAR, WT_CLAMP);
 93.3823 +		}
 93.3824 +	}
 93.3825 +
 93.3826 +	ri.Hunk_FreeTempMemory(data);
 93.3827 +}
 93.3828 +
 93.3829 +static void R_CreateCurrentRenderImage(void)
 93.3830 +{
 93.3831 +	int             width, height;
 93.3832 +	byte           *data;
 93.3833 +
 93.3834 +	if(glConfig.textureNPOTAvailable)
 93.3835 +	{
 93.3836 +		width = glConfig.vidWidth;
 93.3837 +		height = glConfig.vidHeight;
 93.3838 +	}
 93.3839 +	else
 93.3840 +	{
 93.3841 +		width = NearestPowerOfTwo(glConfig.vidWidth);
 93.3842 +		height = NearestPowerOfTwo(glConfig.vidHeight);
 93.3843 +	}
 93.3844 +
 93.3845 +	data = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.3846 +
 93.3847 +	tr.currentRenderImage = R_CreateImage("_currentRender", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_NEAREST, WT_CLAMP);
 93.3848 +
 93.3849 +	ri.Hunk_FreeTempMemory(data);
 93.3850 +}
 93.3851 +
 93.3852 +static void R_CreateDepthRenderImage(void)
 93.3853 +{
 93.3854 +	int             width, height;
 93.3855 +	byte           *data;
 93.3856 +
 93.3857 +	if(glConfig.textureNPOTAvailable)
 93.3858 +	{
 93.3859 +		width = glConfig.vidWidth;
 93.3860 +		height = glConfig.vidHeight;
 93.3861 +	}
 93.3862 +	else
 93.3863 +	{
 93.3864 +		width = NearestPowerOfTwo(glConfig.vidWidth);
 93.3865 +		height = NearestPowerOfTwo(glConfig.vidHeight);
 93.3866 +	}
 93.3867 +
 93.3868 +	data = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.3869 +
 93.3870 +	if(glConfig.hardwareType == GLHW_ATI || glConfig.hardwareType == GLHW_ATI_DX10)// || glConfig.hardwareType == GLHW_NV_DX10)
 93.3871 +	{
 93.3872 +		tr.depthRenderImage = R_CreateImage("_depthRender", data, width, height, IF_NOPICMIP | IF_DEPTH16, FT_NEAREST, WT_CLAMP);
 93.3873 +	}
 93.3874 +	else if(glConfig.framebufferPackedDepthStencilAvailable)
 93.3875 +	{
 93.3876 +		tr.depthRenderImage = R_CreateImage("_depthRender", data, width, height, IF_NOPICMIP | IF_PACKED_DEPTH24_STENCIL8, FT_NEAREST, WT_CLAMP);
 93.3877 +	}
 93.3878 +	else
 93.3879 +	{
 93.3880 +		tr.depthRenderImage = R_CreateImage("_depthRender", data, width, height, IF_NOPICMIP | IF_DEPTH24, FT_NEAREST, WT_CLAMP);
 93.3881 +	}
 93.3882 +	ri.Hunk_FreeTempMemory(data);
 93.3883 +}
 93.3884 +
 93.3885 +static void R_CreatePortalRenderImage(void)
 93.3886 +{
 93.3887 +	int             width, height;
 93.3888 +	byte           *data;
 93.3889 +
 93.3890 +	if(glConfig.textureNPOTAvailable)
 93.3891 +	{
 93.3892 +		width = glConfig.vidWidth;
 93.3893 +		height = glConfig.vidHeight;
 93.3894 +	}
 93.3895 +	else
 93.3896 +	{
 93.3897 +		width = NearestPowerOfTwo(glConfig.vidWidth);
 93.3898 +		height = NearestPowerOfTwo(glConfig.vidHeight);
 93.3899 +	}
 93.3900 +
 93.3901 +	data = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.3902 +
 93.3903 +	if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
 93.3904 +	{
 93.3905 +		tr.portalRenderImage = R_CreateImage("_portalRender", data, width, height, IF_NOPICMIP | IF_RGBA16F, FT_NEAREST, WT_CLAMP);
 93.3906 +	}
 93.3907 +	else
 93.3908 +	{
 93.3909 +		tr.portalRenderImage = R_CreateImage("_portalRender", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_NEAREST, WT_CLAMP);
 93.3910 +	}
 93.3911 +
 93.3912 +	ri.Hunk_FreeTempMemory(data);
 93.3913 +}
 93.3914 +
 93.3915 +static void R_CreateOcclusionRenderFBOImage(void)
 93.3916 +{
 93.3917 +	int             width, height;
 93.3918 +	byte           *data;
 93.3919 +
 93.3920 +	if(glConfig.textureNPOTAvailable)
 93.3921 +	{
 93.3922 +		width = glConfig.vidWidth;
 93.3923 +		height = glConfig.vidHeight;
 93.3924 +	}
 93.3925 +	else
 93.3926 +	{
 93.3927 +		width = NearestPowerOfTwo(glConfig.vidWidth);
 93.3928 +		height = NearestPowerOfTwo(glConfig.vidHeight);
 93.3929 +	}
 93.3930 +
 93.3931 +	data = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.3932 +
 93.3933 +	//
 93.3934 +#if 0
 93.3935 +	if(glConfig.hardwareType == GLHW_ATI_DX10 || glConfig.hardwareType == GLHW_NV_DX10)
 93.3936 +	{
 93.3937 +		tr.occlusionRenderFBOImage = R_CreateImage("_occlusionFBORender", data, width, height, IF_NOPICMIP | IF_ALPHA16F, FT_NEAREST, WT_CLAMP);
 93.3938 +	}
 93.3939 +	else if(glConfig.framebufferPackedDepthStencilAvailable)
 93.3940 +	{
 93.3941 +		tr.occlusionRenderFBOImage = R_CreateImage("_occlusionFBORender", data, width, height, IF_NOPICMIP | IF_ALPHA32F, FT_NEAREST, WT_CLAMP);
 93.3942 +	}
 93.3943 +	else
 93.3944 +#endif
 93.3945 +	{
 93.3946 +		tr.occlusionRenderFBOImage = R_CreateImage("_occlusionFBORender", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_NEAREST, WT_CLAMP);
 93.3947 +	}
 93.3948 +
 93.3949 +	ri.Hunk_FreeTempMemory(data);
 93.3950 +}
 93.3951 +
 93.3952 +static void R_CreateDepthToColorFBOImages(void)
 93.3953 +{
 93.3954 +	int             width, height;
 93.3955 +	byte           *data;
 93.3956 +
 93.3957 +	if(glConfig.textureNPOTAvailable)
 93.3958 +	{
 93.3959 +		width = glConfig.vidWidth;
 93.3960 +		height = glConfig.vidHeight;
 93.3961 +	}
 93.3962 +	else
 93.3963 +	{
 93.3964 +		width = NearestPowerOfTwo(glConfig.vidWidth);
 93.3965 +		height = NearestPowerOfTwo(glConfig.vidHeight);
 93.3966 +	}
 93.3967 +
 93.3968 +	data = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.3969 +
 93.3970 +#if 0
 93.3971 +	if(glConfig.hardwareType == GLHW_ATI_DX10)
 93.3972 +	{
 93.3973 +		tr.depthToColorBackFacesFBOImage = R_CreateImage("_depthToColorBackFacesFBORender", data, width, height, IF_NOPICMIP | IF_ALPHA16F, FT_NEAREST, WT_CLAMP);
 93.3974 +		tr.depthToColorFrontFacesFBOImage = R_CreateImage("_depthToColorFrontFacesFBORender", data, width, height, IF_NOPICMIP | IF_ALPHA16F, FT_NEAREST, WT_CLAMP);
 93.3975 +	}
 93.3976 +	else if(glConfig.hardwareType == GLHW_NV_DX10)
 93.3977 +	{
 93.3978 +		tr.depthToColorBackFacesFBOImage = R_CreateImage("_depthToColorBackFacesFBORender", data, width, height, IF_NOPICMIP | IF_ALPHA32F, FT_NEAREST, WT_CLAMP);
 93.3979 +		tr.depthToColorFrontFacesFBOImage = R_CreateImage("_depthToColorFrontFacesFBORender", data, width, height, IF_NOPICMIP | IF_ALPHA32F, FT_NEAREST, WT_CLAMP);
 93.3980 +	}
 93.3981 +	else if(glConfig.framebufferPackedDepthStencilAvailable)
 93.3982 +	{
 93.3983 +		tr.depthToColorBackFacesFBOImage = R_CreateImage("_depthToColorBackFacesFBORender", data, width, height, IF_NOPICMIP | IF_ALPHA32F, FT_NEAREST, WT_CLAMP);
 93.3984 +		tr.depthToColorFrontFacesFBOImage = R_CreateImage("_depthToColorFrontFacesFBORender", data, width, height, IF_NOPICMIP | IF_ALPHA32F, FT_NEAREST, WT_CLAMP);
 93.3985 +	}
 93.3986 +	else
 93.3987 +#endif
 93.3988 +	{
 93.3989 +		tr.depthToColorBackFacesFBOImage = R_CreateImage("_depthToColorBackFacesFBORender", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_NEAREST, WT_CLAMP);
 93.3990 +		tr.depthToColorFrontFacesFBOImage = R_CreateImage("_depthToColorFrontFacesFBORender", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_NEAREST, WT_CLAMP);
 93.3991 +	}
 93.3992 +
 93.3993 +	ri.Hunk_FreeTempMemory(data);
 93.3994 +}
 93.3995 +
 93.3996 +// Tr3B: clean up this mess some day ...
 93.3997 +static void R_CreateDownScaleFBOImages(void)
 93.3998 +{
 93.3999 +	byte           *data;
 93.4000 +	int				width, height;
 93.4001 +
 93.4002 +
 93.4003 +	if(glConfig.textureNPOTAvailable)
 93.4004 +	{
 93.4005 +		width = glConfig.vidWidth * 0.25f;
 93.4006 +		height = glConfig.vidHeight * 0.25f;
 93.4007 +	}
 93.4008 +	else
 93.4009 +	{
 93.4010 +		width = NearestPowerOfTwo(glConfig.vidWidth * 0.25f);
 93.4011 +		height = NearestPowerOfTwo(glConfig.vidHeight * 0.25f);
 93.4012 +	}
 93.4013 +
 93.4014 +	data = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.4015 +	if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
 93.4016 +	{
 93.4017 +		tr.downScaleFBOImage_quarter = R_CreateImage("_downScaleFBOImage_quarter", data, width, height, IF_NOPICMIP | IF_RGBA16F, FT_NEAREST, WT_CLAMP);
 93.4018 +	}
 93.4019 +	else
 93.4020 +	{
 93.4021 +		tr.downScaleFBOImage_quarter = R_CreateImage("_downScaleFBOImage_quarter", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_NEAREST, WT_CLAMP);
 93.4022 +	}
 93.4023 +	ri.Hunk_FreeTempMemory(data);
 93.4024 +
 93.4025 +
 93.4026 +	width = height = 64;
 93.4027 +	data = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.4028 +	if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
 93.4029 +	{
 93.4030 +		tr.downScaleFBOImage_64x64 = R_CreateImage("_downScaleFBOImage_64x64", data, width, height, IF_NOPICMIP | IF_RGBA16F, FT_NEAREST, WT_CLAMP);
 93.4031 +	}
 93.4032 +	else
 93.4033 +	{
 93.4034 +		tr.downScaleFBOImage_64x64 = R_CreateImage("_downScaleFBOImage_64x64", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_NEAREST, WT_CLAMP);
 93.4035 +	}
 93.4036 +	ri.Hunk_FreeTempMemory(data);
 93.4037 +
 93.4038 +#if 0
 93.4039 +	width = height = 16;
 93.4040 +	data = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.4041 +	if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
 93.4042 +	{
 93.4043 +		tr.downScaleFBOImage_16x16 = R_CreateImage("_downScaleFBOImage_16x16", data, width, height, IF_NOPICMIP | IF_RGBA16F, FT_NEAREST, WT_CLAMP);
 93.4044 +	}
 93.4045 +	else
 93.4046 +	{
 93.4047 +		tr.downScaleFBOImage_16x16 = R_CreateImage("_downScaleFBOImage_16x16", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_NEAREST, WT_CLAMP);
 93.4048 +	}
 93.4049 +	ri.Hunk_FreeTempMemory(data);
 93.4050 +
 93.4051 +
 93.4052 +	width = height = 4;
 93.4053 +	data = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.4054 +	if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
 93.4055 +	{
 93.4056 +		tr.downScaleFBOImage_4x4 = R_CreateImage("_downScaleFBOImage_4x4", data, width, height, IF_NOPICMIP | IF_RGBA16F, FT_NEAREST, WT_CLAMP);
 93.4057 +	}
 93.4058 +	else
 93.4059 +	{
 93.4060 +		tr.downScaleFBOImage_4x4 = R_CreateImage("_downScaleFBOImage_4x4", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_NEAREST, WT_CLAMP);
 93.4061 +	}
 93.4062 +	ri.Hunk_FreeTempMemory(data);
 93.4063 +
 93.4064 +
 93.4065 +	width = height = 1;
 93.4066 +	data = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.4067 +	if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
 93.4068 +	{
 93.4069 +		tr.downScaleFBOImage_1x1 = R_CreateImage("_downScaleFBOImage_1x1", data, width, height, IF_NOPICMIP | IF_RGBA16F, FT_NEAREST, WT_CLAMP);
 93.4070 +	}
 93.4071 +	else
 93.4072 +	{
 93.4073 +		tr.downScaleFBOImage_1x1 = R_CreateImage("_downScaleFBOImage_1x1", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_NEAREST, WT_CLAMP);
 93.4074 +	}
 93.4075 +	ri.Hunk_FreeTempMemory(data);
 93.4076 +#endif
 93.4077 +}
 93.4078 +
 93.4079 +static void R_CreateDeferredRenderFBOImages(void)
 93.4080 +{
 93.4081 +	int             width, height;
 93.4082 +	byte           *data;
 93.4083 +
 93.4084 +	if(glConfig.textureNPOTAvailable)
 93.4085 +	{
 93.4086 +		width = glConfig.vidWidth;
 93.4087 +		height = glConfig.vidHeight;
 93.4088 +	}
 93.4089 +	else
 93.4090 +	{
 93.4091 +		width = NearestPowerOfTwo(glConfig.vidWidth);
 93.4092 +		height = NearestPowerOfTwo(glConfig.vidHeight);
 93.4093 +	}
 93.4094 +
 93.4095 +	data = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.4096 +
 93.4097 +	if(r_deferredShading->integer && glConfig.maxColorAttachments >= 4 && glConfig.textureFloatAvailable &&
 93.4098 +		   glConfig.drawBuffersAvailable && glConfig.maxDrawBuffers >= 4)
 93.4099 +	{
 93.4100 +		tr.deferredDiffuseFBOImage = R_CreateImage("_deferredDiffuseFBO", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_NEAREST, WT_CLAMP);
 93.4101 +		tr.deferredNormalFBOImage = R_CreateImage("_deferredNormalFBO", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_NEAREST, WT_CLAMP);
 93.4102 +		tr.deferredSpecularFBOImage = R_CreateImage("_deferredSpecularFBO", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_NEAREST, WT_CLAMP);
 93.4103 +	}
 93.4104 +
 93.4105 +	if(r_hdrRendering->integer && glConfig.textureFloatAvailable)
 93.4106 +	{
 93.4107 +		tr.deferredRenderFBOImage = R_CreateImage("_deferredRenderFBO", data, width, height, IF_NOPICMIP | IF_RGBA16F, FT_NEAREST, WT_CLAMP);
 93.4108 +	}
 93.4109 +	else
 93.4110 +	{
 93.4111 +		tr.deferredRenderFBOImage = R_CreateImage("_deferredRenderFBO", data, width, height, IF_NOPICMIP | IF_NOCOMPRESSION, FT_NEAREST, WT_CLAMP);
 93.4112 +	}
 93.4113 +
 93.4114 +	ri.Hunk_FreeTempMemory(data);
 93.4115 +}
 93.4116 +
 93.4117 +// *INDENT-OFF*
 93.4118 +static void R_CreateShadowMapFBOImage(void)
 93.4119 +{
 93.4120 +	int             i;
 93.4121 +	int             width, height;
 93.4122 +	byte           *data;
 93.4123 +
 93.4124 +	if(!glConfig.textureFloatAvailable || r_shadows->integer <= 3)
 93.4125 +		return;
 93.4126 +
 93.4127 +	for(i = 0; i < 5; i++)
 93.4128 +	{
 93.4129 +		width = height = shadowMapResolutions[i];
 93.4130 +
 93.4131 +		data = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.4132 +
 93.4133 +		if(glConfig.hardwareType == GLHW_ATI)
 93.4134 +		{
 93.4135 +			tr.shadowMapFBOImage[i] = R_CreateImage(va("_shadowMapFBO%d", i), data, width, height, IF_NOPICMIP | IF_RGBA16, (r_shadowMapLinearFilter->integer ? FT_LINEAR : FT_NEAREST), WT_CLAMP);
 93.4136 +		}
 93.4137 +		else if((glConfig.hardwareType == GLHW_NV_DX10 || glConfig.hardwareType == GLHW_ATI_DX10) && r_shadows->integer == 4)
 93.4138 +		{
 93.4139 +			tr.shadowMapFBOImage[i] = R_CreateImage(va("_shadowMapFBO%d", i), data, width, height, IF_NOPICMIP | IF_LA16F, (r_shadowMapLinearFilter->integer ? FT_LINEAR : FT_NEAREST), WT_CLAMP);
 93.4140 +		}
 93.4141 +		else if((glConfig.hardwareType == GLHW_NV_DX10 || glConfig.hardwareType == GLHW_ATI_DX10) && r_shadows->integer == 5)
 93.4142 +		{
 93.4143 +			tr.shadowMapFBOImage[i] = R_CreateImage(va("_shadowMapFBO%d", i), data, width, height, IF_NOPICMIP | IF_LA32F, (r_shadowMapLinearFilter->integer ? FT_LINEAR : FT_NEAREST), WT_CLAMP);
 93.4144 +		}
 93.4145 +		else if((glConfig.hardwareType == GLHW_NV_DX10 || glConfig.hardwareType == GLHW_ATI_DX10) && r_shadows->integer == 6)
 93.4146 +		{
 93.4147 +			tr.shadowMapFBOImage[i] = R_CreateImage(va("_shadowMapFBO%d", i), data, width, height, IF_NOPICMIP | IF_ALPHA32F, (r_shadowMapLinearFilter->integer ? FT_LINEAR : FT_NEAREST), WT_CLAMP);
 93.4148 +		}
 93.4149 +		else
 93.4150 +		{
 93.4151 +			tr.shadowMapFBOImage[i] = R_CreateImage(va("_shadowMapFBO%d", i), data, width, height, IF_NOPICMIP | IF_RGBA16F, (r_shadowMapLinearFilter->integer ? FT_LINEAR : FT_NEAREST), WT_CLAMP);
 93.4152 +		}
 93.4153 +
 93.4154 +		ri.Hunk_FreeTempMemory(data);
 93.4155 +	}
 93.4156 +}
 93.4157 +// *INDENT-ON*
 93.4158 +
 93.4159 +// *INDENT-OFF*
 93.4160 +static void R_CreateShadowCubeFBOImage(void)
 93.4161 +{
 93.4162 +	int             i, j;
 93.4163 +	int             width, height;
 93.4164 +	byte           *data[6];
 93.4165 +
 93.4166 +	if(!glConfig.textureFloatAvailable || r_shadows->integer <= 3)
 93.4167 +		return;
 93.4168 +
 93.4169 +	for(j = 0; j < 5; j++)
 93.4170 +	{
 93.4171 +		width = height = shadowMapResolutions[j];
 93.4172 +
 93.4173 +		for(i = 0; i < 6; i++)
 93.4174 +		{
 93.4175 +			data[i] = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.4176 +		}
 93.4177 +
 93.4178 +		if(glConfig.hardwareType == GLHW_ATI)
 93.4179 +		{
 93.4180 +			tr.shadowCubeFBOImage[j] = R_CreateCubeImage(va("_shadowCubeFBO%d", j), (const byte **)data, width, height, IF_NOPICMIP | IF_RGBA16, (r_shadowMapLinearFilter->integer ? FT_LINEAR : FT_NEAREST), WT_EDGE_CLAMP);
 93.4181 +		}
 93.4182 +		else if((glConfig.hardwareType == GLHW_NV_DX10 || glConfig.hardwareType == GLHW_ATI_DX10) && r_shadows->integer == 4)
 93.4183 +		{
 93.4184 +			tr.shadowCubeFBOImage[j] = R_CreateCubeImage(va("_shadowCubeFBO%d", j), (const byte **)data, width, height, IF_NOPICMIP | IF_LA16F, (r_shadowMapLinearFilter->integer ? FT_LINEAR : FT_NEAREST), WT_EDGE_CLAMP);
 93.4185 +		}
 93.4186 +		else if((glConfig.hardwareType == GLHW_NV_DX10 || glConfig.hardwareType == GLHW_ATI_DX10) && r_shadows->integer == 5)
 93.4187 +		{
 93.4188 +			tr.shadowCubeFBOImage[j] = R_CreateCubeImage(va("_shadowCubeFBO%d", j), (const byte **)data, width, height, IF_NOPICMIP | IF_LA32F, (r_shadowMapLinearFilter->integer ? FT_LINEAR : FT_NEAREST), WT_EDGE_CLAMP);
 93.4189 +		}
 93.4190 +		else if((glConfig.hardwareType == GLHW_NV_DX10 || glConfig.hardwareType == GLHW_ATI_DX10) && r_shadows->integer == 6)
 93.4191 +		{
 93.4192 +			tr.shadowCubeFBOImage[j] = R_CreateCubeImage(va("_shadowCubeFBO%d", j), (const byte **)data, width, height, IF_NOPICMIP | IF_ALPHA32F, (r_shadowMapLinearFilter->integer ? FT_LINEAR : FT_NEAREST), WT_EDGE_CLAMP);
 93.4193 +		}
 93.4194 +		else
 93.4195 +		{
 93.4196 +			tr.shadowCubeFBOImage[j] = R_CreateCubeImage(va("_shadowCubeFBO%d", j), (const byte **)data, width, height, IF_NOPICMIP | IF_RGBA16F, (r_shadowMapLinearFilter->integer ? FT_LINEAR : FT_NEAREST), WT_EDGE_CLAMP);
 93.4197 +		}
 93.4198 +
 93.4199 +		for(i = 5; i >= 0; i--)
 93.4200 +		{
 93.4201 +			ri.Hunk_FreeTempMemory(data[i]);
 93.4202 +		}
 93.4203 +	}
 93.4204 +}
 93.4205 +// *INDENT-ON*
 93.4206 +
 93.4207 +// *INDENT-OFF*
 93.4208 +static void R_CreateBlackCubeImage(void)
 93.4209 +{
 93.4210 +	int             i;
 93.4211 +	int             width, height;
 93.4212 +	byte           *data[6];
 93.4213 +
 93.4214 +	width = REF_CUBEMAP_SIZE;
 93.4215 +	height = REF_CUBEMAP_SIZE;
 93.4216 +
 93.4217 +	for(i = 0; i < 6; i++)
 93.4218 +	{
 93.4219 +		data[i] = ri.Hunk_AllocateTempMemory(width * height * 4);
 93.4220 +		Com_Memset(data[i], 0, width * height * 4);
 93.4221 +	}
 93.4222 +
 93.4223 +	tr.blackCubeImage = R_CreateCubeImage("_blackCube", (const byte **)data, width, height, IF_NOPICMIP, FT_LINEAR, WT_EDGE_CLAMP);
 93.4224 +	tr.autoCubeImage = R_CreateCubeImage("_autoCube", (const byte **)data, width, height, IF_NOPICMIP, FT_LINEAR, WT_EDGE_CLAMP);
 93.4225 +
 93.4226 +	for(i = 5; i >= 0; i--)
 93.4227 +	{
 93.4228 +		ri.Hunk_FreeTempMemory(data[i]);
 93.4229 +	}
 93.4230 +}
 93.4231 +// *INDENT-ON*
 93.4232 +
 93.4233  /*
 93.4234  ==================
 93.4235  R_CreateBuiltinImages
 93.4236  ==================
 93.4237  */
 93.4238 -void R_CreateBuiltinImages( void ) {
 93.4239 -	int		x,y;
 93.4240 -	byte	data[DEFAULT_SIZE][DEFAULT_SIZE][4];
 93.4241 +void R_CreateBuiltinImages(void)
 93.4242 +{
 93.4243 +	int             x, y;
 93.4244 +	byte            data[DEFAULT_SIZE][DEFAULT_SIZE][4];
 93.4245 +	byte           *out;
 93.4246 +	float           s, value;
 93.4247 +	byte            intensity;
 93.4248  
 93.4249  	R_CreateDefaultImage();
 93.4250  
 93.4251  	// we use a solid white image instead of disabling texturing
 93.4252 -	Com_Memset( data, 255, sizeof( data ) );
 93.4253 -	tr.whiteImage = R_CreateImage("*white", (byte *)data, 8, 8, qfalse, qfalse, GL_REPEAT );
 93.4254 -
 93.4255 -	// with overbright bits active, we need an image which is some fraction of full color,
 93.4256 -	// for default lightmaps, etc
 93.4257 -	for (x=0 ; x<DEFAULT_SIZE ; x++) {
 93.4258 -		for (y=0 ; y<DEFAULT_SIZE ; y++) {
 93.4259 -			data[y][x][0] = 
 93.4260 -			data[y][x][1] = 
 93.4261 -			data[y][x][2] = tr.identityLightByte;
 93.4262 -			data[y][x][3] = 255;			
 93.4263 +	Com_Memset(data, 255, sizeof(data));
 93.4264 +	tr.whiteImage = R_CreateImage("_white", (byte *) data, 8, 8, IF_NOPICMIP, FT_LINEAR, WT_REPEAT);
 93.4265 +
 93.4266 +	// we use a solid black image instead of disabling texturing
 93.4267 +	Com_Memset(data, 0, sizeof(data));
 93.4268 +	tr.blackImage = R_CreateImage("_black", (byte *) data, 8, 8, IF_NOPICMIP, FT_LINEAR, WT_REPEAT);
 93.4269 +
 93.4270 +	// generate a default normalmap with a zero heightmap
 93.4271 +	for(x = 0; x < DEFAULT_SIZE; x++)
 93.4272 +	{
 93.4273 +		for(y = 0; y < DEFAULT_SIZE; y++)
 93.4274 +		{
 93.4275 +			data[y][x][0] = 128;
 93.4276 +			data[y][x][1] = 128;
 93.4277 +			data[y][x][2] = 255;
 93.4278 +			data[y][x][3] = 0;
 93.4279  		}
 93.4280  	}
 93.4281 -
 93.4282 -	tr.identityLightImage = R_CreateImage("*identityLight", (byte *)data, 8, 8, qfalse, qfalse, GL_REPEAT );
 93.4283 -
 93.4284 -
 93.4285 -	for(x=0;x<32;x++) {
 93.4286 +	tr.flatImage = R_CreateImage("_flat", (byte *) data, 8, 8, IF_NOPICMIP | IF_NORMALMAP, FT_LINEAR, WT_REPEAT);
 93.4287 +
 93.4288 +	for(x = 0; x < 32; x++)
 93.4289 +	{
 93.4290  		// scratchimage is usually used for cinematic drawing
 93.4291 -		tr.scratchImage[x] = R_CreateImage("*scratch", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, qfalse, qtrue, GL_CLAMP_TO_EDGE );
 93.4292 +		tr.scratchImage[x] = R_CreateImage("_scratch", (byte *) data, DEFAULT_SIZE, DEFAULT_SIZE, IF_NONE, FT_LINEAR, WT_CLAMP);
 93.4293  	}
 93.4294  
 93.4295 -	R_CreateDlightImage();
 93.4296 -	R_CreateFogImage();
 93.4297 +	out = data;
 93.4298 +	for(y = 0; y < 8; y++)
 93.4299 +	{
 93.4300 +		for(x = 0; x < 32; x++, out += 4)
 93.4301 +		{
 93.4302 +			s = (((float)x + 0.5f) * (2.0f / 32) - 1.0f);
 93.4303 +
 93.4304 +			s = Q_fabs(s) - (1.0f / 32);
 93.4305 +
 93.4306 +			value = 1.0f - (s * 2.0f) + (s * s);
 93.4307 +
 93.4308 +			intensity = ClampByte(Q_ftol(value * 255.0f));
 93.4309 +
 93.4310 +			out[0] = intensity;
 93.4311 +			out[1] = intensity;
 93.4312 +			out[2] = intensity;
 93.4313 +			out[3] = intensity;
 93.4314 +		}
 93.4315 +	}
 93.4316 +
 93.4317 +	tr.quadraticImage =
 93.4318 +		R_CreateImage("_quadratic", (byte *) data, DEFAULT_SIZE, DEFAULT_SIZE, IF_NOPICMIP | IF_NOCOMPRESSION, FT_LINEAR,
 93.4319 +					  WT_CLAMP);
 93.4320 +
 93.4321 +	R_CreateNoFalloffImage();
 93.4322 +	R_CreateAttenuationXYImage();
 93.4323 +	R_CreateContrastRenderFBOImage();
 93.4324 +	R_CreateBloomRenderFBOImage();
 93.4325 +	R_CreateCurrentRenderImage();
 93.4326 +	R_CreateDepthRenderImage();
 93.4327 +	R_CreatePortalRenderImage();
 93.4328 +	R_CreateOcclusionRenderFBOImage();
 93.4329 +	R_CreateDepthToColorFBOImages();
 93.4330 +	R_CreateDownScaleFBOImages();
 93.4331 +	R_CreateDeferredRenderFBOImages();
 93.4332 +	R_CreateShadowMapFBOImage();
 93.4333 +	R_CreateShadowCubeFBOImage();
 93.4334 +	R_CreateBlackCubeImage();
 93.4335  }
 93.4336  
 93.4337  
 93.4338 +
 93.4339 +
 93.4340  /*
 93.4341  ===============
 93.4342  R_SetColorMappings
 93.4343  ===============
 93.4344  */
 93.4345 -void R_SetColorMappings( void ) {
 93.4346 -	int		i, j;
 93.4347 -	float	g;
 93.4348 -	int		inf;
 93.4349 -	int		shift;
 93.4350 +void R_SetColorMappings(void)
 93.4351 +{
 93.4352 +	int             i, j;
 93.4353 +	float           g;
 93.4354 +	int             inf;
 93.4355 +	int             shift;
 93.4356  
 93.4357  	// setup the overbright lighting
 93.4358  	tr.overbrightBits = r_overBrightBits->integer;
 93.4359 -	if ( !glConfig.deviceSupportsGamma ) {
 93.4360 -		tr.overbrightBits = 0;		// need hardware gamma for overbright
 93.4361 +	if(!glConfig.deviceSupportsGamma)
 93.4362 +	{
 93.4363 +		tr.overbrightBits = 0;	// need hardware gamma for overbright
 93.4364  	}
 93.4365  
 93.4366  	// never overbright in windowed mode
 93.4367 -	if ( !glConfig.isFullscreen ) 
 93.4368 +	if(!glConfig.isFullscreen)
 93.4369  	{
 93.4370  		tr.overbrightBits = 0;
 93.4371  	}
 93.4372  
 93.4373  	// allow 2 overbright bits in 24 bit, but only 1 in 16 bit
 93.4374 -	if ( glConfig.colorBits > 16 ) {
 93.4375 -		if ( tr.overbrightBits > 2 ) {
 93.4376 +	if(glConfig.colorBits > 16)
 93.4377 +	{
 93.4378 +		if(tr.overbrightBits > 2)
 93.4379 +		{
 93.4380  			tr.overbrightBits = 2;
 93.4381  		}
 93.4382 -	} else {
 93.4383 -		if ( tr.overbrightBits > 1 ) {
 93.4384 +	}
 93.4385 +	else
 93.4386 +	{
 93.4387 +		if(tr.overbrightBits > 1)
 93.4388 +		{
 93.4389  			tr.overbrightBits = 1;
 93.4390  		}
 93.4391  	}
 93.4392 -	if ( tr.overbrightBits < 0 ) {
 93.4393 +	if(tr.overbrightBits < 0)
 93.4394 +	{
 93.4395  		tr.overbrightBits = 0;
 93.4396  	}
 93.4397  
 93.4398 -	tr.identityLight = 1.0f / ( 1 << tr.overbrightBits );
 93.4399 -	tr.identityLightByte = 255 * tr.identityLight;
 93.4400 -
 93.4401 -
 93.4402 -	if ( r_intensity->value <= 1 ) {
 93.4403 -		ri.Cvar_Set( "r_intensity", "1" );
 93.4404 +	tr.identityLight = 1.0f / (1 << tr.overbrightBits);
 93.4405 +
 93.4406 +	if(r_intensity->value <= 1)
 93.4407 +	{
 93.4408 +		ri.Cvar_Set("r_intensity", "1");
 93.4409  	}
 93.4410  
 93.4411 -	if ( r_gamma->value < 0.5f ) {
 93.4412 -		ri.Cvar_Set( "r_gamma", "0.5" );
 93.4413 -	} else if ( r_gamma->value > 3.0f ) {
 93.4414 -		ri.Cvar_Set( "r_gamma", "3.0" );
 93.4415 +	if(r_gamma->value < 0.5f)
 93.4416 +	{
 93.4417 +		ri.Cvar_Set("r_gamma", "0.5");
 93.4418  	}
 93.4419 +	else if(r_gamma->value > 3.0f)
 93.4420 +	{
 93.4421 +		ri.Cvar_Set("r_gamma", "3.0");
 93.4422 +	}
 93.4423  
 93.4424  	g = r_gamma->value;
 93.4425  
 93.4426  	shift = tr.overbrightBits;
 93.4427  
 93.4428 -	for ( i = 0; i < 256; i++ ) {
 93.4429 -		if ( g == 1 ) {
 93.4430 +	for(i = 0; i < 256; i++)
 93.4431 +	{
 93.4432 +		if(g == 1)
 93.4433 +		{
 93.4434  			inf = i;
 93.4435 -		} else {
 93.4436 -			inf = 255 * pow ( i/255.0f, 1.0f / g ) + 0.5f;
 93.4437 +		}
 93.4438 +		else
 93.4439 +		{
 93.4440 +			inf = 255 * pow(i / 255.0f, 1.0f / g) + 0.5f;
 93.4441  		}
 93.4442  		inf <<= shift;
 93.4443 -		if (inf < 0) {
 93.4444 +		if(inf < 0)
 93.4445 +		{
 93.4446  			inf = 0;
 93.4447  		}
 93.4448 -		if (inf > 255) {
 93.4449 +		if(inf > 255)
 93.4450 +		{
 93.4451  			inf = 255;
 93.4452  		}
 93.4453  		s_gammatable[i] = inf;
 93.4454  	}
 93.4455  
 93.4456 -	for (i=0 ; i<256 ; i++) {
 93.4457 +	for(i = 0; i < 256; i++)
 93.4458 +	{
 93.4459  		j = i * r_intensity->value;
 93.4460 -		if (j > 255) {
 93.4461 +		if(j > 255)
 93.4462 +		{
 93.4463  			j = 255;
 93.4464  		}
 93.4465  		s_intensitytable[i] = j;
 93.4466  	}
 93.4467  
 93.4468 -	if ( glConfig.deviceSupportsGamma )
 93.4469 +	if(glConfig.deviceSupportsGamma)
 93.4470  	{
 93.4471 -		GLimp_SetGamma( s_gammatable, s_gammatable, s_gammatable );
 93.4472 +		GLimp_SetGamma(s_gammatable, s_gammatable, s_gammatable);
 93.4473  	}
 93.4474  }
 93.4475  
 93.4476 +
 93.4477  /*
 93.4478  ===============
 93.4479  R_InitImages
 93.4480  ===============
 93.4481  */
 93.4482 -void	R_InitImages( void ) {
 93.4483 +void R_InitImages(void)
 93.4484 +{
 93.4485 +	const char *charsetImage = "gfx/2d/charset-bezerk-plain-rc2.png";
 93.4486 +
 93.4487 +	ri.Printf(PRINT_ALL, "------- R_InitImages -------\n");
 93.4488 +
 93.4489  	Com_Memset(hashTable, 0, sizeof(hashTable));
 93.4490 +	Com_InitGrowList(&tr.images, 4096);
 93.4491 +	Com_InitGrowList(&tr.lightmaps, 128);
 93.4492 +	Com_InitGrowList(&tr.deluxemaps, 128);
 93.4493 +
 93.4494  	// build brightness translation tables
 93.4495  	R_SetColorMappings();
 93.4496  
 93.4497  	// create default texture and white texture
 93.4498  	R_CreateBuiltinImages();
 93.4499 +
 93.4500 +	/*tr.charsetImage = R_FindImageFile(charsetImage, IF_NOCOMPRESSION | IF_NOPICMIP, FT_DEFAULT, WT_CLAMP);
 93.4501 +	if(!tr.charsetImage)
 93.4502 +	{
 93.4503 +		ri.Error(ERR_FATAL, "R_InitImages: could not load '%s'", charsetImage);
 93.4504 +	}*/
 93.4505  }
 93.4506  
 93.4507 +
 93.4508  /*
 93.4509  ===============
 93.4510 -R_DeleteTextures
 93.4511 +R_ShutdownImages
 93.4512  ===============
 93.4513  */
 93.4514 -void R_DeleteTextures( void ) {
 93.4515 -	int		i;
 93.4516 -
 93.4517 -	for ( i=0; i<tr.numImages ; i++ ) {
 93.4518 -		qglDeleteTextures( 1, &tr.images[i]->texnum );
 93.4519 +void R_ShutdownImages(void)
 93.4520 +{
 93.4521 +	int             i;
 93.4522 +	image_t			*image;
 93.4523 +
 93.4524 +	ri.Printf(PRINT_ALL, "------- R_ShutdownImages -------\n");
 93.4525 +
 93.4526 +	for(i = 0; i < tr.images.currentElements; i++)
 93.4527 +	{
 93.4528 +		image = Com_GrowListElement(&tr.images, i);
 93.4529 +		qglDeleteTextures(1, &image->texnum);
 93.4530  	}
 93.4531 -	Com_Memset( tr.images, 0, sizeof( tr.images ) );
 93.4532 -
 93.4533 -	tr.numImages = 0;
 93.4534 -
 93.4535 -	Com_Memset( glState.currenttextures, 0, sizeof( glState.currenttextures ) );
 93.4536 -	if ( qglActiveTextureARB ) {
 93.4537 -		GL_SelectTexture( 1 );
 93.4538 -		qglBindTexture( GL_TEXTURE_2D, 0 );
 93.4539 -		GL_SelectTexture( 0 );
 93.4540 -		qglBindTexture( GL_TEXTURE_2D, 0 );
 93.4541 -	} else {
 93.4542 -		qglBindTexture( GL_TEXTURE_2D, 0 );
 93.4543 +
 93.4544 +	Com_Memset(glState.currenttextures, 0, sizeof(glState.currenttextures));
 93.4545 +	if(qglBindTexture)
 93.4546 +	{
 93.4547 +		if(qglActiveTextureARB)
 93.4548 +		{
 93.4549 +			for(i = 8 - 1; i >= 0; i--)
 93.4550 +			{
 93.4551 +				GL_SelectTexture(i);
 93.4552 +				qglBindTexture(GL_TEXTURE_2D, 0);
 93.4553 +			}
 93.4554 +		}
 93.4555 +		else
 93.4556 +		{
 93.4557 +			qglBindTexture(GL_TEXTURE_2D, 0);
 93.4558 +		}
 93.4559  	}
 93.4560 +
 93.4561 +	Com_DestroyGrowList(&tr.images);
 93.4562 +	Com_DestroyGrowList(&tr.lightmaps);
 93.4563 +	Com_DestroyGrowList(&tr.deluxemaps);
 93.4564 +	Com_DestroyGrowList(&tr.cubeProbes);
 93.4565 +	FreeVertexHashTable(tr.cubeHashTable);
 93.4566  }
 93.4567  
 93.4568 +
 93.4569 +
 93.4570 +
 93.4571 +
 93.4572 +
 93.4573 +
 93.4574 +
 93.4575 +
 93.4576 +
 93.4577 +
 93.4578 +
 93.4579 +
 93.4580 +
 93.4581 +
 93.4582 +
 93.4583 +
 93.4584  /*
 93.4585  ============================================================================
 93.4586  
 93.4587 @@ -1762,25 +3292,30 @@
 93.4588  compatable with our normal parsing rules.
 93.4589  ==================
 93.4590  */
 93.4591 -static char *CommaParse( char **data_p ) {
 93.4592 -	int c = 0, len;
 93.4593 -	char *data;
 93.4594 -	static	char	com_token[MAX_TOKEN_CHARS];
 93.4595 +static char    *CommaParse(char **data_p)
 93.4596 +{
 93.4597 +	int             c = 0, len;
 93.4598 +	char           *data;
 93.4599 +	static char     com_token[MAX_TOKEN_CHARS];
 93.4600  
 93.4601  	data = *data_p;
 93.4602  	len = 0;
 93.4603  	com_token[0] = 0;
 93.4604  
 93.4605  	// make sure incoming data is valid
 93.4606 -	if ( !data ) {
 93.4607 +	if(!data)
 93.4608 +	{
 93.4609  		*data_p = NULL;
 93.4610  		return com_token;
 93.4611  	}
 93.4612  
 93.4613 -	while ( 1 ) {
 93.4614 +	while(1)
 93.4615 +	{
 93.4616  		// skip whitespace
 93.4617 -		while( (c = *data) <= ' ') {
 93.4618 -			if( !c ) {
 93.4619 +		while((c = *data) <= ' ')
 93.4620 +		{
 93.4621 +			if(!c)
 93.4622 +			{
 93.4623  				break;
 93.4624  			}
 93.4625  			data++;
 93.4626 @@ -1790,19 +3325,19 @@
 93.4627  		c = *data;
 93.4628  
 93.4629  		// skip double slash comments
 93.4630 -		if ( c == '/' && data[1] == '/' )
 93.4631 +		if(c == '/' && data[1] == '/')
 93.4632  		{
 93.4633 -			while (*data && *data != '\n')
 93.4634 +			while(*data && *data != '\n')
 93.4635  				data++;
 93.4636  		}
 93.4637  		// skip /* */ comments
 93.4638 -		else if ( c=='/' && data[1] == '*' ) 
 93.4639 +		else if(c == '/' && data[1] == '*')
 93.4640  		{
 93.4641 -			while ( *data && ( *data != '*' || data[1] != '/' ) ) 
 93.4642 +			while(*data && (*data != '*' || data[1] != '/'))
 93.4643  			{
 93.4644  				data++;
 93.4645  			}
 93.4646 -			if ( *data ) 
 93.4647 +			if(*data)
 93.4648  			{
 93.4649  				data += 2;
 93.4650  			}
 93.4651 @@ -1813,24 +3348,25 @@
 93.4652  		}
 93.4653  	}
 93.4654  
 93.4655 -	if ( c == 0 ) {
 93.4656 +	if(c == 0)
 93.4657 +	{
 93.4658  		return "";
 93.4659  	}
 93.4660  
 93.4661  	// handle quoted strings
 93.4662 -	if (c == '\"')
 93.4663 +	if(c == '\"')
 93.4664  	{
 93.4665  		data++;
 93.4666 -		while (1)
 93.4667 +		while(1)
 93.4668  		{
 93.4669  			c = *data++;
 93.4670 -			if (c=='\"' || !c)
 93.4671 +			if(c == '\"' || !c)
 93.4672  			{
 93.4673  				com_token[len] = 0;
 93.4674 -				*data_p = ( char * ) data;
 93.4675 +				*data_p = (char *)data;
 93.4676  				return com_token;
 93.4677  			}
 93.4678 -			if (len < MAX_TOKEN_CHARS)
 93.4679 +			if(len < MAX_TOKEN_CHARS)
 93.4680  			{
 93.4681  				com_token[len] = c;
 93.4682  				len++;
 93.4683 @@ -1841,61 +3377,64 @@
 93.4684  	// parse a regular word
 93.4685  	do
 93.4686  	{
 93.4687 -		if (len < MAX_TOKEN_CHARS)
 93.4688 +		if(len < MAX_TOKEN_CHARS)
 93.4689  		{
 93.4690  			com_token[len] = c;
 93.4691  			len++;
 93.4692  		}
 93.4693  		data++;
 93.4694  		c = *data;
 93.4695 -	} while (c>32 && c != ',' );
 93.4696 -
 93.4697 -	if (len == MAX_TOKEN_CHARS)
 93.4698 +	} while(c > 32 && c != ',');
 93.4699 +
 93.4700 +	if(len == MAX_TOKEN_CHARS)
 93.4701  	{
 93.4702 -//		Com_Printf ("Token exceeded %i chars, discarded.\n", MAX_TOKEN_CHARS);
 93.4703 +//      Com_Printf ("Token exceeded %i chars, discarded.\n", MAX_TOKEN_CHARS);
 93.4704  		len = 0;
 93.4705  	}
 93.4706  	com_token[len] = 0;
 93.4707  
 93.4708 -	*data_p = ( char * ) data;
 93.4709 +	*data_p = (char *)data;
 93.4710  	return com_token;
 93.4711  }
 93.4712  
 93.4713  
 93.4714 +
 93.4715  /*
 93.4716  ===============
 93.4717  RE_RegisterSkin
 93.4718  
 93.4719  ===============
 93.4720  */
 93.4721 -qhandle_t RE_RegisterSkin( const char *name ) {
 93.4722 -	qhandle_t	hSkin;
 93.4723 -	skin_t		*skin;
 93.4724 -	skinSurface_t	*surf;
 93.4725 -	union {
 93.4726 -		char *c;
 93.4727 -		void *v;
 93.4728 -	} text;
 93.4729 -	char		*text_p;
 93.4730 -	char		*token;
 93.4731 -	char		surfName[MAX_QPATH];
 93.4732 -
 93.4733 -	if ( !name || !name[0] ) {
 93.4734 -		Com_Printf( "Empty name passed to RE_RegisterSkin\n" );
 93.4735 +qhandle_t RE_RegisterSkin(const char *name)
 93.4736 +{
 93.4737 +	qhandle_t       hSkin;
 93.4738 +	skin_t         *skin;
 93.4739 +	skinSurface_t  *surf;
 93.4740 +	char           *text, *text_p;
 93.4741 +	char           *token;
 93.4742 +	char            surfName[MAX_QPATH];
 93.4743 +
 93.4744 +	if(!name || !name[0])
 93.4745 +	{
 93.4746 +		Com_Printf("Empty name passed to RE_RegisterSkin\n");
 93.4747  		return 0;
 93.4748  	}
 93.4749  
 93.4750 -	if ( strlen( name ) >= MAX_QPATH ) {
 93.4751 -		Com_Printf( "Skin name exceeds MAX_QPATH\n" );
 93.4752 +	if(strlen(name) >= MAX_QPATH)
 93.4753 +	{
 93.4754 +		Com_Printf("Skin name exceeds MAX_QPATH\n");
 93.4755  		return 0;
 93.4756  	}
 93.4757  
 93.4758  
 93.4759  	// see if the skin is already loaded
 93.4760 -	for ( hSkin = 1; hSkin < tr.numSkins ; hSkin++ ) {
 93.4761 +	for(hSkin = 1; hSkin < tr.numSkins; hSkin++)
 93.4762 +	{
 93.4763  		skin = tr.skins[hSkin];
 93.4764 -		if ( !Q_stricmp( skin->name, name ) ) {
 93.4765 -			if( skin->numSurfaces == 0 ) {
 93.4766 +		if(!Q_stricmp(skin->name, name))
 93.4767 +		{
 93.4768 +			if(skin->numSurfaces == 0)
 93.4769 +			{
 93.4770  				return 0;		// default skin
 93.4771  			}
 93.4772  			return hSkin;
 93.4773 @@ -1903,89 +3442,99 @@
 93.4774  	}
 93.4775  
 93.4776  	// allocate a new skin
 93.4777 -	if ( tr.numSkins == MAX_SKINS ) {
 93.4778 -		ri.Printf( PRINT_WARNING, "WARNING: RE_RegisterSkin( '%s' ) MAX_SKINS hit\n", name );
 93.4779 +	if(tr.numSkins == MAX_SKINS)
 93.4780 +	{
 93.4781 +		ri.Printf(PRINT_WARNING, "WARNING: RE_RegisterSkin( '%s' ) MAX_SKINS hit\n", name);
 93.4782  		return 0;
 93.4783  	}
 93.4784  	tr.numSkins++;
 93.4785 -	skin = ri.Hunk_Alloc( sizeof( skin_t ), h_low );
 93.4786 +	skin = ri.Hunk_Alloc(sizeof(skin_t), h_low);
 93.4787  	tr.skins[hSkin] = skin;
 93.4788 -	Q_strncpyz( skin->name, name, sizeof( skin->name ) );
 93.4789 +	Q_strncpyz(skin->name, name, sizeof(skin->name));
 93.4790  	skin->numSurfaces = 0;
 93.4791  
 93.4792  	// make sure the render thread is stopped
 93.4793  	R_SyncRenderThread();
 93.4794  
 93.4795  	// If not a .skin file, load as a single shader
 93.4796 -	if ( strcmp( name + strlen( name ) - 5, ".skin" ) ) {
 93.4797 +	if(strcmp(name + strlen(name) - 5, ".skin"))
 93.4798 +	{
 93.4799  		skin->numSurfaces = 1;
 93.4800 -		skin->surfaces[0] = ri.Hunk_Alloc( sizeof(skin->surfaces[0]), h_low );
 93.4801 -		skin->surfaces[0]->shader = R_FindShader( name, LIGHTMAP_NONE, qtrue );
 93.4802 +		skin->surfaces[0] = ri.Hunk_Alloc(sizeof(skin->surfaces[0]), h_low);
 93.4803 +		skin->surfaces[0]->shader = R_FindShader(name, SHADER_3D_DYNAMIC, qtrue);
 93.4804  		return hSkin;
 93.4805  	}
 93.4806  
 93.4807  	// load and parse the skin file
 93.4808 -    ri.FS_ReadFile( name, &text.v );
 93.4809 -	if ( !text.c ) {
 93.4810 +	ri.FS_ReadFile(name, (void **)&text);
 93.4811 +	if(!text)
 93.4812 +	{
 93.4813  		return 0;
 93.4814  	}
 93.4815  
 93.4816 -	text_p = text.c;
 93.4817 -	while ( text_p && *text_p ) {
 93.4818 +	text_p = text;
 93.4819 +	while(text_p && *text_p)
 93.4820 +	{
 93.4821  		// get surface name
 93.4822 -		token = CommaParse( &text_p );
 93.4823 -		Q_strncpyz( surfName, token, sizeof( surfName ) );
 93.4824 -
 93.4825 -		if ( !token[0] ) {
 93.4826 +		token = CommaParse(&text_p);
 93.4827 +		Q_strncpyz(surfName, token, sizeof(surfName));
 93.4828 +
 93.4829 +		if(!token[0])
 93.4830 +		{
 93.4831  			break;
 93.4832  		}
 93.4833  		// lowercase the surface name so skin compares are faster
 93.4834 -		Q_strlwr( surfName );
 93.4835 -
 93.4836 -		if ( *text_p == ',' ) {
 93.4837 +		Q_strlwr(surfName);
 93.4838 +
 93.4839 +		if(*text_p == ',')
 93.4840 +		{
 93.4841  			text_p++;
 93.4842  		}
 93.4843  
 93.4844 -		if ( strstr( token, "tag_" ) ) {
 93.4845 +		if(strstr(token, "tag_"))
 93.4846 +		{
 93.4847  			continue;
 93.4848  		}
 93.4849 -		
 93.4850 +
 93.4851  		// parse the shader name
 93.4852 -		token = CommaParse( &text_p );
 93.4853 -
 93.4854 -		surf = skin->surfaces[ skin->numSurfaces ] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low );
 93.4855 -		Q_strncpyz( surf->name, surfName, sizeof( surf->name ) );
 93.4856 -		surf->shader = R_FindShader( token, LIGHTMAP_NONE, qtrue );
 93.4857 +		token = CommaParse(&text_p);
 93.4858 +
 93.4859 +		surf = skin->surfaces[skin->numSurfaces] = ri.Hunk_Alloc(sizeof(*skin->surfaces[0]), h_low);
 93.4860 +		Q_strncpyz(surf->name, surfName, sizeof(surf->name));
 93.4861 +		surf->shader = R_FindShader(token, SHADER_3D_DYNAMIC, qtrue);
 93.4862  		skin->numSurfaces++;
 93.4863  	}
 93.4864  
 93.4865 -	ri.FS_FreeFile( text.v );
 93.4866 +	ri.FS_FreeFile(text);
 93.4867  
 93.4868  
 93.4869  	// never let a skin have 0 shaders
 93.4870 -	if ( skin->numSurfaces == 0 ) {
 93.4871 -		return 0;		// use default skin
 93.4872 +	if(skin->numSurfaces == 0)
 93.4873 +	{
 93.4874 +		return 0;				// use default skin
 93.4875  	}
 93.4876  
 93.4877  	return hSkin;
 93.4878  }
 93.4879  
 93.4880  
 93.4881 +
 93.4882  /*
 93.4883  ===============
 93.4884  R_InitSkins
 93.4885  ===============
 93.4886  */
 93.4887 -void	R_InitSkins( void ) {
 93.4888 -	skin_t		*skin;
 93.4889 +void R_InitSkins(void)
 93.4890 +{
 93.4891 +	skin_t         *skin;
 93.4892  
 93.4893  	tr.numSkins = 1;
 93.4894  
 93.4895  	// make the default skin have all default shaders
 93.4896 -	skin = tr.skins[0] = ri.Hunk_Alloc( sizeof( skin_t ), h_low );
 93.4897 -	Q_strncpyz( skin->name, "<default skin>", sizeof( skin->name )  );
 93.4898 +	skin = tr.skins[0] = ri.Hunk_Alloc(sizeof(skin_t), h_low);
 93.4899 +	Q_strncpyz(skin->name, "<default skin>", sizeof(skin->name));
 93.4900  	skin->numSurfaces = 1;
 93.4901 -	skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces ), h_low );
 93.4902 +	skin->surfaces[0] = ri.Hunk_Alloc(sizeof(*skin->surfaces), h_low);
 93.4903  	skin->surfaces[0]->shader = tr.defaultShader;
 93.4904  }
 93.4905  
 93.4906 @@ -1994,11 +3543,13 @@
 93.4907  R_GetSkinByHandle
 93.4908  ===============
 93.4909  */
 93.4910 -skin_t	*R_GetSkinByHandle( qhandle_t hSkin ) {
 93.4911 -	if ( hSkin < 1 || hSkin >= tr.numSkins ) {
 93.4912 +skin_t         *R_GetSkinByHandle(qhandle_t hSkin)
 93.4913 +{
 93.4914 +	if(hSkin < 1 || hSkin >= tr.numSkins)
 93.4915 +	{
 93.4916  		return tr.skins[0];
 93.4917  	}
 93.4918 -	return tr.skins[ hSkin ];
 93.4919 +	return tr.skins[hSkin];
 93.4920  }
 93.4921  
 93.4922  /*
 93.4923 @@ -2006,21 +3557,22 @@
 93.4924  R_SkinList_f
 93.4925  ===============
 93.4926  */
 93.4927 -void	R_SkinList_f( void ) {
 93.4928 -	int			i, j;
 93.4929 -	skin_t		*skin;
 93.4930 -
 93.4931 -	ri.Printf (PRINT_ALL, "------------------\n");
 93.4932 -
 93.4933 -	for ( i = 0 ; i < tr.numSkins ; i++ ) {
 93.4934 +void R_SkinList_f(void)
 93.4935 +{
 93.4936 +	int             i, j;
 93.4937 +	skin_t         *skin;
 93.4938 +
 93.4939 +	ri.Printf(PRINT_ALL, "------------------\n");
 93.4940 +
 93.4941 +	for(i = 0; i < tr.numSkins; i++)
 93.4942 +	{
 93.4943  		skin = tr.skins[i];
 93.4944  
 93.4945 -		ri.Printf( PRINT_ALL, "%3i:%s\n", i, skin->name );
 93.4946 -		for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
 93.4947 -			ri.Printf( PRINT_ALL, "       %s = %s\n", 
 93.4948 -				skin->surfaces[j]->name, skin->surfaces[j]->shader->name );
 93.4949 +		ri.Printf(PRINT_ALL, "%3i:%s\n", i, skin->name);
 93.4950 +		for(j = 0; j < skin->numSurfaces; j++)
 93.4951 +		{
 93.4952 +			ri.Printf(PRINT_ALL, "       %s = %s\n", skin->surfaces[j]->name, skin->surfaces[j]->shader->name);
 93.4953  		}
 93.4954  	}
 93.4955 -	ri.Printf (PRINT_ALL, "------------------\n");
 93.4956 +	ri.Printf(PRINT_ALL, "------------------\n");
 93.4957  }
 93.4958 -
    94.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.2 +++ b/src/renderer/tr_image_dds.c	Wed Jun 10 09:31:46 2009 +0800
    94.3 @@ -0,0 +1,1194 @@
    94.4 +/*
    94.5 +===========================================================================
    94.6 +Copyright (C) 1999-2005 Id Software, Inc.
    94.7 +Copyright (C) 2007 HermitWorks Entertainment Corporation
    94.8 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
    94.9 +
   94.10 +This file is part of XreaL source code.
   94.11 +
   94.12 +XreaL source code is free software; you can redistribute it
   94.13 +and/or modify it under the terms of the GNU General Public License as
   94.14 +published by the Free Software Foundation; either version 2 of the License,
   94.15 +or (at your option) any later version.
   94.16 +
   94.17 +XreaL source code is distributed in the hope that it will be
   94.18 +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   94.19 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   94.20 +GNU General Public License for more details.
   94.21 +
   94.22 +You should have received a copy of the GNU General Public License
   94.23 +along with XreaL source code; if not, write to the Free Software
   94.24 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   94.25 +===========================================================================
   94.26 +*/
   94.27 +
   94.28 +#include "tr_local.h"
   94.29 +
   94.30 +typedef struct
   94.31 +{
   94.32 +	unsigned int   dwColorSpaceLowValue;	// low boundary of color space that is to
   94.33 +	// be treated as Color Key, inclusive
   94.34 +
   94.35 +	unsigned int   dwColorSpaceHighValue;	// high boundary of color space that is
   94.36 +	// to be treated as Color Key, inclusive
   94.37 +} DDCOLORKEY_t;
   94.38 +
   94.39 +typedef struct
   94.40 +{
   94.41 +	unsigned int   dwCaps;		// capabilities of surface wanted
   94.42 +	unsigned int   dwCaps2;
   94.43 +	unsigned int   dwCaps3;
   94.44 +	union
   94.45 +	{
   94.46 +		unsigned int   dwCaps4;
   94.47 +		unsigned int   dwVolumeDepth;
   94.48 +	} u0;
   94.49 +} DDSCAPS2_t;
   94.50 +
   94.51 +typedef struct
   94.52 +{
   94.53 +	unsigned int   dwSize;		// size of structure
   94.54 +	unsigned int   dwFlags;	// pixel format flags
   94.55 +	unsigned int   dwFourCC;	// (FOURCC code)
   94.56 +
   94.57 +	union
   94.58 +	{
   94.59 +		unsigned int   dwRGBBitCount;	// how many bits per pixel
   94.60 +		unsigned int   dwYUVBitCount;	// how many bits per pixel
   94.61 +		unsigned int   dwZBufferBitDepth;	// how many total bits/pixel in z buffer (including any stencil bits)
   94.62 +		unsigned int   dwAlphaBitDepth;	// how many bits for alpha channels
   94.63 +		unsigned int   dwLuminanceBitCount;	// how many bits per pixel
   94.64 +		unsigned int   dwBumpBitCount;	// how many bits per "buxel", total
   94.65 +		unsigned int   dwPrivateFormatBitCount;	// Bits per pixel of private driver formats. Only valid in texture
   94.66 +		// format list and if DDPF_D3DFORMAT is set
   94.67 +	} u0;
   94.68 +
   94.69 +	union
   94.70 +	{
   94.71 +		unsigned int   dwRBitMask;	// mask for red bit
   94.72 +		unsigned int   dwYBitMask;	// mask for Y bits
   94.73 +		unsigned int   dwStencilBitDepth;	// how many stencil bits (note: dwZBufferBitDepth-dwStencilBitDepth is total Z-only bits)
   94.74 +		unsigned int   dwLuminanceBitMask;	// mask for luminance bits
   94.75 +		unsigned int   dwBumpDuBitMask;	// mask for bump map U delta bits
   94.76 +		unsigned int   dwOperations;	// DDPF_D3DFORMAT Operations
   94.77 +	} u1;
   94.78 +
   94.79 +	union
   94.80 +	{
   94.81 +		unsigned int   dwGBitMask;	// mask for green bits
   94.82 +		unsigned int   dwUBitMask;	// mask for U bits
   94.83 +		unsigned int   dwZBitMask;	// mask for Z bits
   94.84 +		unsigned int   dwBumpDvBitMask;	// mask for bump map V delta bits
   94.85 +		struct
   94.86 +		{
   94.87 +			unsigned short  wFlipMSTypes;	// Multisample methods supported via flip for this D3DFORMAT
   94.88 +			unsigned short  wBltMSTypes;	// Multisample methods supported via blt for this D3DFORMAT
   94.89 +		} MultiSampleCaps;
   94.90 +
   94.91 +	} u2;
   94.92 +
   94.93 +	union
   94.94 +	{
   94.95 +		unsigned int   dwBBitMask;	// mask for blue bits
   94.96 +		unsigned int   dwVBitMask;	// mask for V bits
   94.97 +		unsigned int   dwStencilBitMask;	// mask for stencil bits
   94.98 +		unsigned int   dwBumpLuminanceBitMask;	// mask for luminance in bump map
   94.99 +	} u3;
  94.100 +
  94.101 +	union
  94.102 +	{
  94.103 +		unsigned int   dwRGBAlphaBitMask;	// mask for alpha channel
  94.104 +		unsigned int   dwYUVAlphaBitMask;	// mask for alpha channel
  94.105 +		unsigned int   dwLuminanceAlphaBitMask;	// mask for alpha channel
  94.106 +		unsigned int   dwRGBZBitMask;	// mask for Z channel
  94.107 +		unsigned int   dwYUVZBitMask;	// mask for Z channel
  94.108 +	} u4;
  94.109 +} DDPIXELFORMAT_t;
  94.110 +
  94.111 +typedef struct
  94.112 +{
  94.113 +	unsigned int   dwSize;		// size of the DDSURFACEDESC structure
  94.114 +	unsigned int   dwFlags;	// determines what fields are valid
  94.115 +	unsigned int   dwHeight;	// height of surface to be created
  94.116 +	unsigned int   dwWidth;	// width of input surface
  94.117 +
  94.118 +	union
  94.119 +	{
  94.120 +		int            lPitch;	// distance to start of next line (return value only)
  94.121 +		unsigned int   dwLinearSize;	// Formless late-allocated optimized surface size
  94.122 +	} u0;
  94.123 +
  94.124 +	union
  94.125 +	{
  94.126 +		unsigned int   dwBackBufferCount;	// number of back buffers requested
  94.127 +		unsigned int   dwDepth;	// the depth if this is a volume texture
  94.128 +	} u1;
  94.129 +
  94.130 +	union
  94.131 +	{
  94.132 +		unsigned int   dwMipMapCount;	// number of mip-map levels requestde
  94.133 +		// dwZBufferBitDepth removed, use ddpfPixelFormat one instead
  94.134 +		unsigned int   dwRefreshRate;	// refresh rate (used when display mode is described)
  94.135 +		unsigned int   dwSrcVBHandle;	// The source used in VB::Optimize
  94.136 +	} u2;
  94.137 +
  94.138 +	unsigned int   dwAlphaBitDepth;	// depth of alpha buffer requested
  94.139 +	unsigned int   dwReserved;	// reserved
  94.140 +	void           *lpSurface;	// pointer to the associated surface memory
  94.141 +
  94.142 +	union
  94.143 +	{
  94.144 +		DDCOLORKEY_t    ddckCKDestOverlay;	// color key for destination overlay use
  94.145 +		unsigned int   dwEmptyFaceColor;	// Physical color for empty cubemap faces
  94.146 +	} u3;
  94.147 +	DDCOLORKEY_t    ddckCKDestBlt;	// color key for destination blt use
  94.148 +	DDCOLORKEY_t    ddckCKSrcOverlay;	// color key for source overlay use
  94.149 +	DDCOLORKEY_t    ddckCKSrcBlt;	// color key for source blt use
  94.150 +	union
  94.151 +	{
  94.152 +		DDPIXELFORMAT_t ddpfPixelFormat;	// pixel format description of the surface
  94.153 +		unsigned int   dwFVF;	// vertex format description of vertex buffers
  94.154 +	} u4;
  94.155 +	DDSCAPS2_t      ddsCaps;	// direct draw surface capabilities
  94.156 +	unsigned int   dwTextureStage;	// stage in multitexture cascade
  94.157 +} DDSURFACEDESC2_t;
  94.158 +
  94.159 +//
  94.160 +// DDSURFACEDESC2 flags that mark the validity of the struct data
  94.161 +//
  94.162 +#define DDSD_CAPS								0x00000001l	// default
  94.163 +#define DDSD_HEIGHT								0x00000002l	// default
  94.164 +#define DDSD_WIDTH								0x00000004l	// default
  94.165 +#define DDSD_PIXELFORMAT						0x00001000l	// default
  94.166 +#define DDSD_PITCH								0x00000008l	// For uncompressed formats
  94.167 +#define DDSD_MIPMAPCOUNT						0x00020000l
  94.168 +#define DDSD_LINEARSIZE							0x00080000l	// For compressed formats
  94.169 +#define DDSD_DEPTH								0x00800000l	// Volume Textures
  94.170 +
  94.171 +//
  94.172 +// DDPIXELFORMAT flags
  94.173 +//
  94.174 +#define DDPF_ALPHAPIXELS						0x00000001l
  94.175 +#define DDPF_FOURCC								0x00000004l	// Compressed formats
  94.176 +#define DDPF_RGB								0x00000040l	// Uncompressed formats
  94.177 +#define DDPF_ALPHA								0x00000002l
  94.178 +#define DDPF_COMPRESSED							0x00000080l
  94.179 +#define DDPF_LUMINANCE							0x00020000l
  94.180 +#define DDPF_PALETTEINDEXED4					0x00000008l
  94.181 +#define DDPF_PALETTEINDEXEDTO8					0x00000010l
  94.182 +#define DDPF_PALETTEINDEXED8					0x00000020l
  94.183 +
  94.184 +//
  94.185 +// DDSCAPS flags
  94.186 +//
  94.187 +#define DDSCAPS_COMPLEX							0x00000008l
  94.188 +#define DDSCAPS_TEXTURE							0x00001000l	// default
  94.189 +#define DDSCAPS_MIPMAP							0x00400000l
  94.190 +
  94.191 +#define DDSCAPS2_VOLUME							0x00200000l
  94.192 +#define DDSCAPS2_CUBEMAP						0x00000200L
  94.193 +#define DDSCAPS2_CUBEMAP_POSITIVEX				0x00000400L
  94.194 +#define DDSCAPS2_CUBEMAP_NEGATIVEX				0x00000800L
  94.195 +#define DDSCAPS2_CUBEMAP_POSITIVEY				0x00001000L
  94.196 +#define DDSCAPS2_CUBEMAP_NEGATIVEY				0x00002000L
  94.197 +#define DDSCAPS2_CUBEMAP_POSITIVEZ				0x00004000L
  94.198 +#define DDSCAPS2_CUBEMAP_NEGATIVEZ				0x00008000L
  94.199 +
  94.200 +#ifndef MAKEFOURCC
  94.201 +
  94.202 +#define MAKEFOURCC(ch0, ch1, ch2, ch3)											\
  94.203 +    ((unsigned int)(char)(ch0) | ((unsigned int)(char)(ch1) << 8) |			\
  94.204 +    ((unsigned int)(char)(ch2) << 16) | ((unsigned int)(char)(ch3) << 24 ))
  94.205 +
  94.206 +#endif
  94.207 +
  94.208 +#define FOURCC_DDS		MAKEFOURCC( 'D', 'D', 'S', ' ' )
  94.209 +
  94.210 +//FOURCC codes for DXTn compressed-texture pixel formats
  94.211 +#define FOURCC_DXT1		MAKEFOURCC( 'D', 'X', 'T', '1' )
  94.212 +#define FOURCC_DXT2		MAKEFOURCC( 'D', 'X', 'T', '2' )
  94.213 +#define FOURCC_DXT3		MAKEFOURCC( 'D', 'X', 'T', '3' )
  94.214 +#define FOURCC_DXT4		MAKEFOURCC( 'D', 'X', 'T', '4' )
  94.215 +#define FOURCC_DXT5		MAKEFOURCC( 'D', 'X', 'T', '5' )
  94.216 +
  94.217 +#define R_LoadDDSImage_MAX_MIPS 16
  94.218 +
  94.219 +static ID_INLINE void UnpackRGB565(byte rgb[3], uint16_t cl)
  94.220 +{
  94.221 +	byte            r = (byte) ((cl >> 11) & 0x1F);
  94.222 +	byte            g = (byte) ((cl >> 5) & 0x3F);
  94.223 +	byte            b = (byte) (cl & 0x1F);
  94.224 +
  94.225 +	rgb[0] = (r << 3) | (r >> 2);	//multiply by 8.22 -> 8.25
  94.226 +	rgb[1] = (g << 2) | (g >> 4);	//multiply by 4.047 -> 4.0625
  94.227 +	rgb[2] = (b << 3) | (b >> 2);	//multiply by 8.22 -> 8.25
  94.228 +}
  94.229 +
  94.230 +static void R_DecodeS3TCBlock(byte out[4][4][4], int bx, int by, int format, int iw, int ih, const void *image_base)
  94.231 +{
  94.232 +	int             x, y;
  94.233 +
  94.234 +	int             blocksize;
  94.235 +	const byte     *block_base, *color_base, *alpha_base;
  94.236 +
  94.237 +	uint16_t          c0, c1;
  94.238 +	byte            rgba[4][4];
  94.239 +
  94.240 +	switch (format)
  94.241 +	{
  94.242 +		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
  94.243 +		case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
  94.244 +			blocksize = 8;
  94.245 +			break;
  94.246 +
  94.247 +		case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
  94.248 +		case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
  94.249 +			blocksize = 16;
  94.250 +			break;
  94.251 +
  94.252 +		default:
  94.253 +			ri.Printf(PRINT_WARNING, "invalid compressed image format\n");
  94.254 +			return;
  94.255 +	}
  94.256 +
  94.257 +	block_base = (byte *) image_base + blocksize * (((iw + 3) / 4) * (by / 4) + bx / 4);
  94.258 +
  94.259 +	switch (format)
  94.260 +	{
  94.261 +		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
  94.262 +		case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
  94.263 +			color_base = block_base;
  94.264 +			alpha_base = NULL;
  94.265 +			break;
  94.266 +
  94.267 +		case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
  94.268 +		case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
  94.269 +			alpha_base = block_base;
  94.270 +			color_base = block_base + 8;
  94.271 +			break;
  94.272 +	}
  94.273 +
  94.274 +	c0 = (uint16_t) color_base[0] | ((uint16_t) color_base[1] << 8);
  94.275 +	c1 = (uint16_t) color_base[2] | ((uint16_t) color_base[3] << 8);
  94.276 +
  94.277 +	UnpackRGB565(rgba[0], c0);
  94.278 +	UnpackRGB565(rgba[1], c1);
  94.279 +
  94.280 +	rgba[0][3] = 0xFF;
  94.281 +	rgba[1][3] = 0xFF;
  94.282 +	rgba[2][3] = 0xFF;
  94.283 +	rgba[3][3] = 0xFF;
  94.284 +
  94.285 +	switch (format)
  94.286 +	{
  94.287 +		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
  94.288 +			if(c0 <= c1)
  94.289 +				rgba[3][3] = 0;
  94.290 +			//fallthrough
  94.291 +
  94.292 +		case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
  94.293 +			if(c0 <= c1)
  94.294 +			{
  94.295 +				rgba[2][0] = (byte) ((rgba[0][0] + rgba[1][0]) / 2);
  94.296 +				rgba[2][1] = (byte) ((rgba[0][1] + rgba[1][1]) / 2);
  94.297 +				rgba[2][2] = (byte) ((rgba[0][2] + rgba[1][2]) / 2);
  94.298 +
  94.299 +				rgba[3][0] = 0;
  94.300 +				rgba[3][1] = 0;
  94.301 +				rgba[3][2] = 0;
  94.302 +
  94.303 +				break;
  94.304 +			}
  94.305 +			//fallthrough
  94.306 +
  94.307 +		case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
  94.308 +		case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
  94.309 +			rgba[2][0] = (byte) ((rgba[0][0] * 2 + rgba[1][0]) / 3);
  94.310 +			rgba[2][1] = (byte) ((rgba[0][1] * 2 + rgba[1][1]) / 3);
  94.311 +			rgba[2][2] = (byte) ((rgba[0][2] * 2 + rgba[1][2]) / 3);
  94.312 +
  94.313 +			rgba[3][0] = (byte) ((rgba[1][0] * 2 + rgba[0][0]) / 3);
  94.314 +			rgba[3][1] = (byte) ((rgba[1][1] * 2 + rgba[0][1]) / 3);
  94.315 +			rgba[3][2] = (byte) ((rgba[1][2] * 2 + rgba[0][2]) / 3);
  94.316 +			break;
  94.317 +	}
  94.318 +
  94.319 +	for(y = 0; y < 4; y++)
  94.320 +	{
  94.321 +		for(x = 0; x < 4; x++)
  94.322 +		{
  94.323 +			int             idx = (color_base[4 + y] >> (x * 2)) & 0x3;
  94.324 +
  94.325 +			out[y][x][0] = rgba[idx][0];
  94.326 +			out[y][x][1] = rgba[idx][1];
  94.327 +			out[y][x][2] = rgba[idx][2];
  94.328 +			out[y][x][3] = rgba[idx][3];
  94.329 +		}
  94.330 +	}
  94.331 +
  94.332 +	switch (format)
  94.333 +	{
  94.334 +		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
  94.335 +		case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
  94.336 +			break;
  94.337 +
  94.338 +		case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
  94.339 +			for(y = 0; y < 4; y++)
  94.340 +			{
  94.341 +				for(x = 0; x < 4; x++)
  94.342 +				{
  94.343 +					byte            b = (alpha_base[(y * 2) + (x / 2)] >> ((x & 1) * 4)) & 0x0F;
  94.344 +
  94.345 +					out[y][x][3] = b | (b << 4);	//multiply by 17, this one works out exactly
  94.346 +				}
  94.347 +			}
  94.348 +			break;
  94.349 +
  94.350 +		case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
  94.351 +		{
  94.352 +			byte            a[8];
  94.353 +			int             idxs;
  94.354 +
  94.355 +			a[0] = alpha_base[0];
  94.356 +			a[1] = alpha_base[1];
  94.357 +
  94.358 +			if(a[0] > a[1])
  94.359 +			{
  94.360 +				a[2] = (6 * a[0] + 1 * a[1]) / 7;
  94.361 +				a[3] = (5 * a[0] + 2 * a[1]) / 7;
  94.362 +				a[4] = (4 * a[0] + 3 * a[1]) / 7;
  94.363 +				a[5] = (3 * a[0] + 4 * a[1]) / 7;
  94.364 +				a[6] = (2 * a[0] + 5 * a[1]) / 7;
  94.365 +				a[7] = (1 * a[0] + 6 * a[1]) / 7;
  94.366 +			}
  94.367 +			else
  94.368 +			{
  94.369 +				a[2] = (4 * a[0] + 1 * a[1]) / 5;
  94.370 +				a[3] = (3 * a[0] + 2 * a[1]) / 5;
  94.371 +				a[4] = (2 * a[0] + 3 * a[1]) / 5;
  94.372 +				a[5] = (1 * a[0] + 4 * a[1]) / 5;
  94.373 +				a[6] = 0;
  94.374 +				a[7] = 1;
  94.375 +			}
  94.376 +
  94.377 +			//do 2 sets of 3 bytes at a time (easier to cope with 3-bit indices crossing byte boundaries)
  94.378 +			idxs = alpha_base[2] | (alpha_base[3] << 8) | (alpha_base[4] << 16);
  94.379 +
  94.380 +			for(y = 0; y < 2; y++)
  94.381 +			{
  94.382 +				for(x = 0; x < 4; x++)
  94.383 +				{
  94.384 +					int             idx = idxs >> 3 * (y * 4 + x) & 0x7;
  94.385 +
  94.386 +					out[y][x][3] = a[idx];
  94.387 +				}
  94.388 +			}
  94.389 +
  94.390 +			idxs = alpha_base[5] | (alpha_base[6] << 8) | (alpha_base[7] << 16);
  94.391 +
  94.392 +			for(y = 0; y < 2; y++)
  94.393 +			{
  94.394 +				for(x = 0; x < 4; x++)
  94.395 +				{
  94.396 +					int             idx = idxs >> 3 * (y * 4 + x) & 0x7;
  94.397 +
  94.398 +					out[y + 2][x][3] = a[idx];
  94.399 +				}
  94.400 +			}
  94.401 +			break;
  94.402 +		}
  94.403 +	}
  94.404 +}
  94.405 +
  94.406 +static void R_DecodeRGB565Block(byte out[4][4][4], int bx, int by, int format, int iw, int ih, const void *image_base)
  94.407 +{
  94.408 +	int             x, y;
  94.409 +	const byte     *row;
  94.410 +	size_t          pitch;
  94.411 +
  94.412 +//	REF_PARAM(format);
  94.413 +
  94.414 +	pitch = iw * 2;
  94.415 +	row = (byte *) image_base + (by * iw + bx) * 2;
  94.416 +
  94.417 +	for(y = 0; y < 4; y++)
  94.418 +	{
  94.419 +		for(x = 0; x < 4; x++)
  94.420 +		{
  94.421 +			uint16_t          c;
  94.422 +
  94.423 +			const byte     *px = row + x * 2;
  94.424 +
  94.425 +			c = (uint16_t) px[0] | ((uint16_t) px[1] << 8);
  94.426 +
  94.427 +			UnpackRGB565(out[y][x], c);
  94.428 +			out[y][x][3] = 0xFF;
  94.429 +		}
  94.430 +
  94.431 +		row += pitch;
  94.432 +	}
  94.433 +}
  94.434 +
  94.435 +static void R_UploadEncodedImageDirect(GLenum target, int level, GLenum format, GLenum int_fmat, int width, int height,
  94.436 +									   const void *data, void (*decoder) (byte out[4][4][4], int bx, int by, int format, int iw,
  94.437 +																		  int ih, const void *image_base))
  94.438 +{
  94.439 +	int             x, y;
  94.440 +	byte            block[4][4][4];	//y, x, rgba
  94.441 +
  94.442 +	qglTexImage2D(target, level, int_fmat, width, height, 0, GL_RGBA, GL_BYTE, NULL);
  94.443 +
  94.444 +	//decode the data
  94.445 +	for(y = 0; y < height; y += 4)
  94.446 +	{
  94.447 +		for(x = 0; x < width; x += 4)
  94.448 +		{
  94.449 +			int             uw = width - x;
  94.450 +			int             uh = height - y;
  94.451 +
  94.452 +			if(uw > 4)
  94.453 +				uw = 4;
  94.454 +			if(uh > 4)
  94.455 +				uh = 4;
  94.456 +
  94.457 +			decoder(block, x, y, format, width, height, data);
  94.458 +			qglTexSubImage2D(target, level, x, y, uw, uh, GL_RGBA, GL_UNSIGNED_BYTE, block);
  94.459 +		}
  94.460 +	}
  94.461 +}
  94.462 +
  94.463 +static void R_UploadCompressedImage2D(image_t * img, GLenum target, int level, GLenum format, int width, int height, int size,
  94.464 +									  const void *data)
  94.465 +{
  94.466 +	GLenum          int_fmat;
  94.467 +
  94.468 +	if(glConfig.ARBTextureCompressionAvailable && glConfig.textureCompression == TC_S3TC)
  94.469 +	{
  94.470 +		qglCompressedTexImage2DARB(target, level, format, width, height, 0, size, data);
  94.471 +		return;
  94.472 +	}
  94.473 +
  94.474 +	switch (format)
  94.475 +	{
  94.476 +		case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
  94.477 +			int_fmat = GL_RGB;
  94.478 +			break;
  94.479 +
  94.480 +		case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
  94.481 +		case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
  94.482 +		case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
  94.483 +			int_fmat = GL_RGBA;
  94.484 +			break;
  94.485 +
  94.486 +		default:
  94.487 +			ri.Printf(PRINT_WARNING, "invalid compressed image format\n");
  94.488 +			return;
  94.489 +	}
  94.490 +
  94.491 +	if(img->filterType == FT_DEFAULT && (img->uploadWidth * img->uploadHeight) > (256 * 256))
  94.492 +	{
  94.493 +		//skip high-level mips
  94.494 +		img->uploadWidth /= 2;
  94.495 +		img->uploadHeight /= 2;
  94.496 +
  94.497 +		if(img->uploadWidth == 0)
  94.498 +			img->uploadWidth = 1;
  94.499 +
  94.500 +		if(img->uploadHeight == 0)
  94.501 +			img->uploadHeight = 1;
  94.502 +
  94.503 +		return;
  94.504 +	}
  94.505 +
  94.506 +	level = 0;
  94.507 +
  94.508 +	{
  94.509 +		int             x, t;
  94.510 +
  94.511 +		if(img->uploadWidth > img->uploadHeight)
  94.512 +		{
  94.513 +			t = img->uploadWidth;
  94.514 +			x = width;
  94.515 +		}
  94.516 +		else
  94.517 +		{
  94.518 +			t = img->uploadHeight;
  94.519 +			x = height;
  94.520 +		}
  94.521 +
  94.522 +		while(t > x)
  94.523 +		{
  94.524 +			t /= 2;
  94.525 +			level++;
  94.526 +		}
  94.527 +	}
  94.528 +
  94.529 +	R_UploadEncodedImageDirect(target, level, format, int_fmat, width, height, data, R_DecodeS3TCBlock);
  94.530 +}
  94.531 +
  94.532 +static void R_UploadImage2D(image_t * img, GLenum target, int level, GLenum int_fmat,
  94.533 +							int width, int height, GLenum format, GLenum type, const void *data)
  94.534 +{
  94.535 +
  94.536 +/*
  94.537 +#ifdef Q3_BIG_ENDIAN
  94.538 +	// OSX 10.3.9 has problems with GL_UNSIGNED_SHORT_5_6_5 which gives us the multicolored lightmaps
  94.539 +	if(type == GL_UNSIGNED_SHORT_5_6_5)
  94.540 +#else
  94.541 +	if(type == GL_UNSIGNED_SHORT_5_6_5 && !GLEW_VERSION_1_2)
  94.542 +#endif
  94.543 +	{
  94.544 +		R_UploadEncodedImageDirect(target, level, format, int_fmat, width, height, data, R_DecodeRGB565Block);
  94.545 +		return;
  94.546 +	}
  94.547 +*/
  94.548 +	qglTexImage2D(target, level, int_fmat, width, height, 0, format, type, data);
  94.549 +}
  94.550 +
  94.551 +image_t        *R_LoadDDSImageData(void *pImageData, const char *name, int bits, filterType_t filterType, wrapType_t wrapType)
  94.552 +{
  94.553 +	image_t        *ret = NULL;
  94.554 +
  94.555 +	byte           *buff;
  94.556 +
  94.557 +	DDSURFACEDESC2_t *ddsd;		//used to get at the dds header in the read buffer
  94.558 +
  94.559 +	//based on texture type:
  94.560 +	//  cube        width != 0, height == 0, depth == 0
  94.561 +	//  2D          width != 0, height != 0, depth == 0
  94.562 +	//  volume      width != 0, height != 0, depth != 0
  94.563 +	int             width, height, depth;
  94.564 +
  94.565 +	//mip count and pointers to image data for each mip
  94.566 +	//level, idx 0 = top level last pointer does not start
  94.567 +	//a mip level, it's just there to mark off the end of
  94.568 +	//the final mip data segment (thus the odd + 1)
  94.569 +	//
  94.570 +	//for cube textures we only find the offsets into the
  94.571 +	//first face of the cube, subsequent faces will use the
  94.572 +	//same offsets, just shifted over
  94.573 +	int             mipLevels;
  94.574 +	byte           *mipOffsets[R_LoadDDSImage_MAX_MIPS + 1];
  94.575 +
  94.576 +	qboolean        usingAlpha;
  94.577 +
  94.578 +	qboolean        compressed;
  94.579 +	GLuint          format = 0;
  94.580 +	GLuint          internal_format = 0;
  94.581 +	GLenum          type = GL_UNSIGNED_BYTE;
  94.582 +
  94.583 +	vec4_t          zeroClampBorder = { 0, 0, 0, 1 };
  94.584 +	vec4_t          alphaZeroClampBorder = { 0, 0, 0, 0 };
  94.585 +
  94.586 +	//comes from R_CreateImage
  94.587 +	/*
  94.588 +	if(tr.numImages == MAX_DRAWIMAGES)
  94.589 +	{
  94.590 +		ri.Printf(PRINT_WARNING, "R_LoadDDSImage: MAX_DRAWIMAGES hit\n");
  94.591 +		return NULL;
  94.592 +	}
  94.593 +	*/
  94.594 +
  94.595 +	buff = (byte *) pImageData;
  94.596 +
  94.597 +	if(strncmp((const char *)buff, "DDS ", 4) != 0)
  94.598 +	{
  94.599 +		ri.Printf(PRINT_WARNING, "R_LoadDDSImage: invalid dds header \"%s\"\n", name);
  94.600 +		goto ret_error;
  94.601 +	}
  94.602 +
  94.603 +	ddsd = (DDSURFACEDESC2_t *) (buff + 4);
  94.604 +
  94.605 +	//Byte Swapping for the DDS headers.
  94.606 +	//beware: we ignore some of the shorts.
  94.607 +#ifdef Q3_BIG_ENDIAN
  94.608 +	{
  94.609 +		int             i;
  94.610 +		int           *field;
  94.611 +		for(i = 0; i < sizeof(DDSURFACEDESC2_t) / sizeof(int); i++)
  94.612 +		{
  94.613 +			field = (int *)ddsd;
  94.614 +			field[i] = LittleLong(field[i]);
  94.615 +		}
  94.616 +
  94.617 +	}
  94.618 +
  94.619 +#endif
  94.620 +
  94.621 +	if(ddsd->dwSize != sizeof(DDSURFACEDESC2_t) || ddsd->u4.ddpfPixelFormat.dwSize != sizeof(DDPIXELFORMAT_t))
  94.622 +	{
  94.623 +		ri.Printf(PRINT_WARNING, "R_LoadDDSImage: invalid dds header \"%s\"\n", name);
  94.624 +		goto ret_error;
  94.625 +	}
  94.626 +
  94.627 +	usingAlpha = (ddsd->u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) ? qtrue : qfalse;
  94.628 +	mipLevels = ((ddsd->dwFlags & DDSD_MIPMAPCOUNT) && (ddsd->u2.dwMipMapCount > 1)) ? ddsd->u2.dwMipMapCount : 1;
  94.629 +
  94.630 +	if(mipLevels > R_LoadDDSImage_MAX_MIPS)
  94.631 +	{
  94.632 +		ri.Printf(PRINT_WARNING, "R_LoadDDSImage: dds image has too many mip levels \"%s\"\n", name);
  94.633 +		goto ret_error;
  94.634 +	}
  94.635 +
  94.636 +	compressed = (ddsd->u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) ? qtrue : qfalse;
  94.637 +
  94.638 +	// either a cube or a volume
  94.639 +	if(ddsd->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP)
  94.640 +	{
  94.641 +		// cube texture
  94.642 +
  94.643 +		if(ddsd->dwWidth != ddsd->dwHeight)
  94.644 +		{
  94.645 +			ri.Printf(PRINT_WARNING, "R_LoadDDSImage: invalid dds image \"%s\"\n", name);
  94.646 +			goto ret_error;
  94.647 +		}
  94.648 +
  94.649 +		width = ddsd->dwWidth;
  94.650 +		height = 0;
  94.651 +		depth = 0;
  94.652 +
  94.653 +		if(width & (width - 1))
  94.654 +		{
  94.655 +			//cubes must be a power of two
  94.656 +			ri.Printf(PRINT_WARNING, "R_LoadDDSImage: cube images must be power of two \"%s\"\n", name);
  94.657 +			goto ret_error;
  94.658 +		}
  94.659 +	}
  94.660 +	else if((ddsd->ddsCaps.dwCaps2 & DDSCAPS2_VOLUME) && (ddsd->dwFlags & DDSD_DEPTH))
  94.661 +	{
  94.662 +		// 3D texture
  94.663 +
  94.664 +		width = ddsd->dwWidth;
  94.665 +		height = ddsd->dwHeight;
  94.666 +		depth = ddsd->u1.dwDepth;
  94.667 +
  94.668 +		if(width & (width - 1) || height & (height - 1) || depth & (depth - 1))
  94.669 +		{
  94.670 +			ri.Printf(PRINT_WARNING, "R_LoadDDSImage: volume images must be power of two \"%s\"\n", name);
  94.671 +			goto ret_error;
  94.672 +		}
  94.673 +	}
  94.674 +	else
  94.675 +	{
  94.676 +		// 2D texture
  94.677 +
  94.678 +		width = ddsd->dwWidth;
  94.679 +		height = ddsd->dwHeight;
  94.680 +		depth = 0;
  94.681 +
  94.682 +		//these are allowed to be non power of two, will be dealt with later on
  94.683 +		//except for compressed images!
  94.684 +		if(compressed && (width & (width - 1) || height & (height - 1)))
  94.685 +		{
  94.686 +			ri.Printf(PRINT_WARNING, "R_LoadDDSImage: compressed texture images must be power of two \"%s\"\n", name);
  94.687 +			goto ret_error;
  94.688 +		}
  94.689 +	}
  94.690 +
  94.691 +	if(compressed)
  94.692 +	{
  94.693 +		int             blockSize;
  94.694 +
  94.695 +		if(depth != 0)
  94.696 +		{
  94.697 +			ri.Printf(PRINT_WARNING, "R_LoadDDSImage: compressed volume textures are not supported \"%s\"\n", name);
  94.698 +			goto ret_error;
  94.699 +		}
  94.700 +
  94.701 +		//compressed FOURCC formats
  94.702 +		switch (ddsd->u4.ddpfPixelFormat.dwFourCC)
  94.703 +		{
  94.704 +			case FOURCC_DXT1:
  94.705 +				blockSize = 8;
  94.706 +				usingAlpha = qtrue;
  94.707 +				format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
  94.708 +				break;
  94.709 +
  94.710 +			case FOURCC_DXT3:
  94.711 +				blockSize = 16;
  94.712 +				usingAlpha = qtrue;
  94.713 +				format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
  94.714 +				break;
  94.715 +
  94.716 +			case FOURCC_DXT5:
  94.717 +				blockSize = 16;
  94.718 +				usingAlpha = qtrue;
  94.719 +				format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
  94.720 +				break;
  94.721 +
  94.722 +			default:
  94.723 +				ri.Printf(PRINT_WARNING, "R_LoadDDSImage: unsupported FOURCC \"%s\", \"%s\"\n",
  94.724 +						  &ddsd->u4.ddpfPixelFormat.dwFourCC, name);
  94.725 +				goto ret_error;
  94.726 +		}
  94.727 +
  94.728 +		//get mip offsets
  94.729 +		if(format)
  94.730 +		{
  94.731 +			int             w = width;
  94.732 +			int             h = height;
  94.733 +			int             offset = 0;
  94.734 +			int             i;
  94.735 +
  94.736 +			if(h == 0)
  94.737 +				h = w;			//cube map
  94.738 +
  94.739 +			for(i = 0; (i < mipLevels) && (w || h); i++)
  94.740 +			{
  94.741 +				int             qw, qh;
  94.742 +
  94.743 +				mipOffsets[i] = buff + 4 + sizeof(DDSURFACEDESC2_t) + offset;
  94.744 +
  94.745 +				if(w == 0)
  94.746 +					w = 1;
  94.747 +				if(h == 0)
  94.748 +					h = 1;
  94.749 +
  94.750 +				//size formula comes from DX docs (August 2005 SDK reference)
  94.751 +				qw = w >> 2;
  94.752 +				if(qw == 0)
  94.753 +					qw = 1;
  94.754 +				qh = h >> 2;
  94.755 +				if(qh == 0)
  94.756 +					qh = 1;
  94.757 +
  94.758 +				offset += qw * qh * blockSize;
  94.759 +
  94.760 +				w >>= 1;
  94.761 +				h >>= 1;
  94.762 +			}
  94.763 +
  94.764 +			//put in the trailing offset
  94.765 +			mipOffsets[i] = buff + 4 + sizeof(DDSURFACEDESC2_t) + offset;
  94.766 +		}
  94.767 +		else
  94.768 +		{
  94.769 +			ri.Printf(PRINT_WARNING, "R_LoadDDSImage: error reading DDS image \"%s\"\n", name);
  94.770 +			goto ret_error;
  94.771 +		}
  94.772 +
  94.773 +		internal_format = format;
  94.774 +	}
  94.775 +	else
  94.776 +	{
  94.777 +		// uncompressed format
  94.778 +		if(ddsd->u4.ddpfPixelFormat.dwFlags & DDPF_RGB)
  94.779 +		{
  94.780 +			switch (ddsd->u4.ddpfPixelFormat.u0.dwRGBBitCount)
  94.781 +			{
  94.782 +				case 32:
  94.783 +					internal_format = usingAlpha ? GL_RGBA8 : GL_RGB8;
  94.784 +					format = GL_BGRA_EXT;
  94.785 +					break;
  94.786 +
  94.787 +				case 24:
  94.788 +					internal_format = GL_RGB8;
  94.789 +					format = GL_BGR_EXT;
  94.790 +					break;
  94.791 +
  94.792 +				case 16:
  94.793 +					if(usingAlpha)
  94.794 +					{
  94.795 +						//must be A1R5G5B5
  94.796 +						ri.Printf(PRINT_WARNING, "R_LoadDDSImage: unsupported format, 5551 \"%s\"\n", name);
  94.797 +						goto ret_error;
  94.798 +					}
  94.799 +					else
  94.800 +					{
  94.801 +						//find out if it's X1R5G5B5 or R5G6B5
  94.802 +
  94.803 +						internal_format = GL_RGB5;
  94.804 +						format = GL_RGB;
  94.805 +
  94.806 +						if(ddsd->u4.ddpfPixelFormat.u2.dwGBitMask == 0x7E0)
  94.807 +							type = GL_UNSIGNED_SHORT_5_6_5;
  94.808 +						else
  94.809 +						{
  94.810 +							ri.Printf(PRINT_WARNING, "R_LoadDDSImage: unsupported format, 5551 \"%s\"\n", name);
  94.811 +							goto ret_error;
  94.812 +						}
  94.813 +					}
  94.814 +					break;
  94.815 +
  94.816 +				default:
  94.817 +					ri.Printf(PRINT_WARNING, "R_LoadDDSImage: unsupported RGB bit depth \"%s\"\n", name);
  94.818 +					goto ret_error;
  94.819 +			}
  94.820 +		}
  94.821 +		else if(ddsd->u4.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE)
  94.822 +		{
  94.823 +			internal_format = usingAlpha ? GL_LUMINANCE8_ALPHA8 : GL_LUMINANCE8;
  94.824 +			format = usingAlpha ? GL_LUMINANCE_ALPHA : GL_LUMINANCE;
  94.825 +		}
  94.826 +		else if(ddsd->u4.ddpfPixelFormat.dwFlags & DDPF_ALPHA)
  94.827 +		{
  94.828 +			internal_format = GL_ALPHA8;
  94.829 +			format = GL_ALPHA;
  94.830 +		}
  94.831 +		else if(ddsd->u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)
  94.832 +		{
  94.833 +			internal_format = usingAlpha ? GL_RGB5_A1 : GL_RGB5;
  94.834 +			format = GL_COLOR_INDEX4_EXT;
  94.835 +		}
  94.836 +		else if(ddsd->u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
  94.837 +		{
  94.838 +			internal_format = usingAlpha ? GL_RGBA : GL_RGB;
  94.839 +			format = GL_COLOR_INDEX8_EXT;
  94.840 +		}
  94.841 +		else
  94.842 +		{
  94.843 +			ri.Printf(PRINT_WARNING, "R_LoadDDSImage: unsupported DDS image type \"%s\"\n", name);
  94.844 +			goto ret_error;
  94.845 +		}
  94.846 +
  94.847 +		if(format)
  94.848 +		{
  94.849 +			int             offset = 0;
  94.850 +			int             w = width;
  94.851 +			int             h = height;
  94.852 +			int             d = depth;
  94.853 +			int             i;
  94.854 +
  94.855 +			if(h == 0)
  94.856 +				h = w;			//cube map
  94.857 +
  94.858 +			for(i = 0; (i < mipLevels) && (w || h || d); i++)
  94.859 +			{
  94.860 +				mipOffsets[i] = buff + 4 + sizeof(DDSURFACEDESC2_t) + offset;
  94.861 +
  94.862 +				if(w == 0)
  94.863 +					w = 1;
  94.864 +				if(h == 0)
  94.865 +					h = 1;
  94.866 +				if(d == 0)
  94.867 +					d = 1;
  94.868 +
  94.869 +				offset += (w * h * d * (ddsd->u4.ddpfPixelFormat.u0.dwRGBBitCount / 8));
  94.870 +
  94.871 +				w >>= 1;
  94.872 +				h >>= 1;
  94.873 +				d >>= 1;
  94.874 +			}
  94.875 +
  94.876 +			//put in the trailing offset
  94.877 +			mipOffsets[i] = buff + 4 + sizeof(DDSURFACEDESC2_t) + offset;
  94.878 +		}
  94.879 +		else
  94.880 +		{
  94.881 +			ri.Printf(PRINT_WARNING, "R_LoadDDSImage: Unexpected error reading DDS image \"%s\"\n", name);
  94.882 +			goto ret_error;
  94.883 +		}
  94.884 +	}
  94.885 +
  94.886 +	//we now have a full description of our image set up
  94.887 +	//if we fail after this point we still want our image_t
  94.888 +	//record in the hash so that we don't go trying to read
  94.889 +	//the file again - been printing an error and returning
  94.890 +	//NULL up to this point...
  94.891 +	ret = R_AllocImage(name, qtrue);
  94.892 +
  94.893 +	ret->uploadWidth = ret->width = width;
  94.894 +	ret->uploadHeight = ret->height = height;
  94.895 +
  94.896 +	ret->internalFormat = internal_format;
  94.897 +//	ret->hasAlpha = usingAlpha;
  94.898 +
  94.899 +	ret->filterType = ((filterType == FT_DEFAULT) && (mipLevels > 1)) ? FT_DEFAULT : FT_LINEAR;
  94.900 +
  94.901 +	if(ret->filterType == FT_LINEAR)
  94.902 +		mipLevels = 1;
  94.903 +
  94.904 +	if(depth)
  94.905 +	{
  94.906 +		// volume texture - must be power of 2
  94.907 +
  94.908 +		int             w = width;
  94.909 +		int             h = height;
  94.910 +		int             d = depth;
  94.911 +
  94.912 +		int             i;
  94.913 +
  94.914 +		if(!glConfig.texture3DAvailable)
  94.915 +		{
  94.916 +			ri.Printf(PRINT_WARNING, "R_LoadDDSImage: Tried to load 3D texture but missing hardware support \"%s\"\n", name);
  94.917 +			goto ret_error;
  94.918 +		}
  94.919 +
  94.920 +		//ret->depth = depth;
  94.921 +		//ret->uploadDepth = depth;
  94.922 +
  94.923 +		ret->type = GL_TEXTURE_3D_EXT;
  94.924 +		//ret->addrMode = TAM_Normalized;
  94.925 +
  94.926 +		GL_Bind(ret);
  94.927 +
  94.928 +		if(filterType == FT_DEFAULT && mipLevels == 1 && glConfig.generateMipmapAvailable)
  94.929 +			qglTexParameteri(ret->type, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
  94.930 +
  94.931 +		for(i = 0; i < mipLevels; i++)
  94.932 +		{
  94.933 +			qglTexImage3DEXT(GL_TEXTURE_3D_EXT, i, internal_format, w, h, d, 0, format, type, mipOffsets[i]);
  94.934 +
  94.935 +			w >>= 1;
  94.936 +			if(w == 0)
  94.937 +				w = 1;
  94.938 +			h >>= 1;
  94.939 +			if(h == 0)
  94.940 +				h = 1;
  94.941 +			d >>= 1;
  94.942 +			if(d == 0)
  94.943 +				d = 1;
  94.944 +		}
  94.945 +	}
  94.946 +	else if(!height)
  94.947 +	{
  94.948 +		// cube texture - must be power of 2
  94.949 +
  94.950 +		int             w;
  94.951 +		int             i;
  94.952 +		size_t          shift = mipOffsets[mipLevels] - mipOffsets[0];
  94.953 +
  94.954 +		/*
  94.955 +		if(!GARB_texture_cube_map && !GLEW_EXT_texture_cube_map && !GLEW_VERSION_1_2)
  94.956 +		{
  94.957 +			ri.Printf(PRINT_WARNING, "R_LoadDDSImage: Tried to load Cube texture but missing hardware support \"%s\"\n", name);
  94.958 +			goto ret_error;
  94.959 +		}
  94.960 +		*/
  94.961 +
  94.962 +		ret->type = GL_TEXTURE_CUBE_MAP_ARB;
  94.963 +
  94.964 +		GL_Bind(ret);
  94.965 +
  94.966 +		//macros so this doesn't get disgustingly huge
  94.967 +#define	loadCubeFace( glTarget )													\
  94.968 +		w = width;																	\
  94.969 +																					\
  94.970 +		for( i = 0; i < mipLevels; i++ )											\
  94.971 +		{																			\
  94.972 +			if( compressed )														\
  94.973 +			{																		\
  94.974 +				GLsizei size = mipOffsets[ i + 1 ] - mipOffsets[ i ];				\
  94.975 +				R_UploadCompressedImage2D( ret, glTarget, i, format, w, w,			\
  94.976 +					size, mipOffsets[ i ] );										\
  94.977 +			}																		\
  94.978 +			else																	\
  94.979 +			{																		\
  94.980 +				R_UploadImage2D( ret, glTarget, i, internal_format, w, w,			\
  94.981 +					internal_format, type, mipOffsets[ i ] );						\
  94.982 +			}																		\
  94.983 +																					\
  94.984 +			w >>= 1; if( w == 0 ) w = 1;											\
  94.985 +		}
  94.986 +
  94.987 +#define shiftMipOffsets()															\
  94.988 +		for( i = 0; i <= mipLevels; i++ )											\
  94.989 +			mipOffsets[ i ] += shift
  94.990 +
  94.991 +		if(filterType == FT_DEFAULT && mipLevels == 1 && glConfig.generateMipmapAvailable)
  94.992 +			qglTexParameteri(ret->type, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
  94.993 +
  94.994 +		//the faces are stored in the order +x, -x, +y, -y, +z, -z
  94.995 +		//but there may be missing faces in the sequence which we cannot upload
  94.996 +		if(ddsd->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEX)
  94.997 +		{
  94.998 +			loadCubeFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB);
  94.999 +			shiftMipOffsets();
 94.1000 +		}
 94.1001 +
 94.1002 +		if(ddsd->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEX)
 94.1003 +		{
 94.1004 +			loadCubeFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB);
 94.1005 +			shiftMipOffsets();
 94.1006 +		}
 94.1007 +
 94.1008 +		if(ddsd->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEY)
 94.1009 +		{
 94.1010 +			loadCubeFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB);
 94.1011 +			shiftMipOffsets();
 94.1012 +		}
 94.1013 +
 94.1014 +		if(ddsd->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEY)
 94.1015 +		{
 94.1016 +			loadCubeFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB);
 94.1017 +			shiftMipOffsets();
 94.1018 +		}
 94.1019 +
 94.1020 +		if(ddsd->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEZ)
 94.1021 +		{
 94.1022 +			loadCubeFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB);
 94.1023 +			shiftMipOffsets();
 94.1024 +		}
 94.1025 +
 94.1026 +		if(ddsd->ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ)
 94.1027 +		{
 94.1028 +			loadCubeFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB);
 94.1029 +			shiftMipOffsets();
 94.1030 +		}
 94.1031 +	}
 94.1032 +	else
 94.1033 +	{
 94.1034 +		// planar texture
 94.1035 +
 94.1036 +		int             w = width;
 94.1037 +		int             h = height;
 94.1038 +
 94.1039 +		int             i;
 94.1040 +
 94.1041 +		GLuint          texnum;
 94.1042 +
 94.1043 +		if(w & (w - 1) || h & (h - 1))
 94.1044 +		{
 94.1045 +			// non-pow2: check extensions
 94.1046 +
 94.1047 +			if(glConfig.textureNPOTAvailable)
 94.1048 +			{
 94.1049 +				ret->type = GL_TEXTURE_2D;
 94.1050 +			}
 94.1051 +			else
 94.1052 +			{
 94.1053 +				ret->type = GL_TEXTURE_2D; // FIXME R_StateGetRectTarget();
 94.1054 +			}
 94.1055 +		}
 94.1056 +		else
 94.1057 +		{
 94.1058 +			ret->type = GL_TEXTURE_2D;
 94.1059 +		}
 94.1060 +
 94.1061 +		texnum = ret->texnum;
 94.1062 +
 94.1063 +		GL_Bind(ret);
 94.1064 +
 94.1065 +		if(filterType == FT_DEFAULT && mipLevels == 1)
 94.1066 +			qglTexParameteri(ret->type, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
 94.1067 +
 94.1068 +		for(i = 0; i < mipLevels; i++)
 94.1069 +		{
 94.1070 +			if(compressed)
 94.1071 +			{
 94.1072 +				GLsizei         size = mipOffsets[i + 1] - mipOffsets[i];
 94.1073 +
 94.1074 +				R_UploadCompressedImage2D(ret, ret->type, i, internal_format, w, h, size, mipOffsets[i]);
 94.1075 +			}
 94.1076 +			else
 94.1077 +			{
 94.1078 +				R_UploadImage2D(ret, ret->type, i, internal_format, w, h, format, type, mipOffsets[i]);
 94.1079 +			}
 94.1080 +
 94.1081 +			w >>= 1;
 94.1082 +			if(w == 0)
 94.1083 +				w = 1;
 94.1084 +			h >>= 1;
 94.1085 +			if(h == 0)
 94.1086 +				h = 1;
 94.1087 +		}
 94.1088 +	}
 94.1089 +
 94.1090 +
 94.1091 +	GL_CheckErrors();
 94.1092 +
 94.1093 +	// set filter type
 94.1094 +	ret->filterType = filterType;
 94.1095 +	switch (filterType)
 94.1096 +	{
 94.1097 +		case FT_DEFAULT:
 94.1098 +			// set texture anisotropy
 94.1099 +			if(glConfig.textureAnisotropyAvailable)
 94.1100 +				qglTexParameterf(ret->type, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_ext_texture_filter_anisotropic->value);
 94.1101 +
 94.1102 +			qglTexParameterf(ret->type, GL_TEXTURE_MIN_FILTER, gl_filter_min);
 94.1103 +			qglTexParameterf(ret->type, GL_TEXTURE_MAG_FILTER, gl_filter_max);
 94.1104 +			break;
 94.1105 +
 94.1106 +		case FT_LINEAR:
 94.1107 +			qglTexParameterf(ret->type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 94.1108 +			qglTexParameterf(ret->type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 94.1109 +			break;
 94.1110 +
 94.1111 +		case FT_NEAREST:
 94.1112 +			qglTexParameterf(ret->type, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 94.1113 +			qglTexParameterf(ret->type, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 94.1114 +			break;
 94.1115 +
 94.1116 +		default:
 94.1117 +			ri.Printf(PRINT_WARNING, "WARNING: unknown filter type for image '%s'\n", ret->name);
 94.1118 +			qglTexParameterf(ret->type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 94.1119 +			qglTexParameterf(ret->type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 94.1120 +			break;
 94.1121 +	}
 94.1122 +
 94.1123 +	GL_CheckErrors();
 94.1124 +
 94.1125 +	// set wrap type
 94.1126 +	ret->wrapType = wrapType;
 94.1127 +	switch (wrapType)
 94.1128 +	{
 94.1129 +		case WT_REPEAT:
 94.1130 +			qglTexParameterf(ret->type, GL_TEXTURE_WRAP_S, GL_REPEAT);
 94.1131 +			qglTexParameterf(ret->type, GL_TEXTURE_WRAP_T, GL_REPEAT);
 94.1132 +			break;
 94.1133 +
 94.1134 +		case WT_CLAMP:
 94.1135 +			qglTexParameterf(ret->type, GL_TEXTURE_WRAP_S, GL_CLAMP);
 94.1136 +			qglTexParameterf(ret->type, GL_TEXTURE_WRAP_T, GL_CLAMP);
 94.1137 +			break;
 94.1138 +
 94.1139 +		case WT_EDGE_CLAMP:
 94.1140 +			qglTexParameterf(ret->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 94.1141 +			qglTexParameterf(ret->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 94.1142 +			break;
 94.1143 +
 94.1144 +		case WT_ZERO_CLAMP:
 94.1145 +			qglTexParameterf(ret->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
 94.1146 +			qglTexParameterf(ret->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
 94.1147 +			qglTexParameterfv(ret->type, GL_TEXTURE_BORDER_COLOR, zeroClampBorder);
 94.1148 +			break;
 94.1149 +
 94.1150 +		case WT_ALPHA_ZERO_CLAMP:
 94.1151 +			qglTexParameterf(ret->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
 94.1152 +			qglTexParameterf(ret->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
 94.1153 +			qglTexParameterfv(ret->type, GL_TEXTURE_BORDER_COLOR, alphaZeroClampBorder);
 94.1154 +			break;
 94.1155 +
 94.1156 +		default:
 94.1157 +			ri.Printf(PRINT_WARNING, "WARNING: unknown wrap type for image '%s'\n", ret->name);
 94.1158 +			qglTexParameterf(ret->type, GL_TEXTURE_WRAP_S, GL_REPEAT);
 94.1159 +			qglTexParameterf(ret->type, GL_TEXTURE_WRAP_T, GL_REPEAT);
 94.1160 +			break;
 94.1161 +	}
 94.1162 +
 94.1163 +	GL_CheckErrors();
 94.1164 +
 94.1165 +	//GL_Unbind();
 94.1166 +	qglBindTexture(ret->type, 0);
 94.1167 +
 94.1168 +  ret_error:
 94.1169 +	return ret;
 94.1170 +}
 94.1171 +
 94.1172 +
 94.1173 +image_t        *R_LoadDDSImage(const char *name, int bits, filterType_t filterType, wrapType_t wrapType)
 94.1174 +{
 94.1175 +	image_t        *ret;
 94.1176 +	byte           *buff;
 94.1177 +	int             len;
 94.1178 +
 94.1179 +	// comes from R_CreateImage
 94.1180 +	/*
 94.1181 +	if(tr.numImages == MAX_DRAWIMAGES)
 94.1182 +	{
 94.1183 +		ri.Printf(PRINT_WARNING, "R_LoadDDSImage: MAX_DRAWIMAGES hit\n");
 94.1184 +		return NULL;
 94.1185 +	}
 94.1186 +	*/
 94.1187 +
 94.1188 +	len = ri.FS_ReadFile(name, (void **)&buff);
 94.1189 +	if(!buff)
 94.1190 +		return 0;
 94.1191 +
 94.1192 +	ret = R_LoadDDSImageData(buff, name, bits, filterType, wrapType);
 94.1193 +
 94.1194 +	ri.FS_FreeFile(buff);
 94.1195 +
 94.1196 +	return ret;
 94.1197 +}
    95.1 --- a/src/renderer/tr_image_jpg.c	Sat Jun 06 03:54:16 2009 +0800
    95.2 +++ b/src/renderer/tr_image_jpg.c	Wed Jun 10 09:31:46 2009 +0800
    95.3 @@ -33,7 +33,7 @@
    95.4  #define JPEG_INTERNALS
    95.5  #include "../jpeg-6b/jpeglib.h"
    95.6  
    95.7 -void R_LoadJPG( const char *filename, unsigned char **pic, int *width, int *height ) {
    95.8 +void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height, byte alphaByte ) {
    95.9    /* This struct contains the JPEG decompression parameters and pointers to
   95.10     * working space (which is allocated as needed by the JPEG library).
   95.11     */
    96.1 --- a/src/renderer/tr_image_png.c	Sat Jun 06 03:54:16 2009 +0800
    96.2 +++ b/src/renderer/tr_image_png.c	Wed Jun 10 09:31:46 2009 +0800
    96.3 @@ -1903,7 +1903,7 @@
    96.4   *  The PNG loader
    96.5   */
    96.6  
    96.7 -void R_LoadPNG(const char *name, byte **pic, int *width, int *height)
    96.8 +void LoadPNG(const char *name, byte **pic, int *width, int *height, byte alphaByte)
    96.9  {
   96.10  	struct BufferedFile *ThePNG;
   96.11  	byte *OutBuffer;
    97.1 --- a/src/renderer/tr_image_tga.c	Sat Jun 06 03:54:16 2009 +0800
    97.2 +++ b/src/renderer/tr_image_tga.c	Wed Jun 10 09:31:46 2009 +0800
    97.3 @@ -38,7 +38,7 @@
    97.4  	unsigned char	pixel_size, attributes;
    97.5  } TargaHeader;
    97.6  
    97.7 -void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
    97.8 +void LoadTGA ( const char *name, byte **pic, int *width, int *height, byte alphaByte)
    97.9  {
   97.10  	unsigned	columns, rows, numPixels;
   97.11  	byte	*pixbuf;
    98.1 --- a/src/renderer/tr_init.c	Sat Jun 06 03:54:16 2009 +0800
    98.2 +++ b/src/renderer/tr_init.c	Wed Jun 10 09:31:46 2009 +0800
    98.3 @@ -1,263 +1,405 @@
    98.4  /*
    98.5  ===========================================================================
    98.6  Copyright (C) 1999-2005 Id Software, Inc.
    98.7 -Copyright (C) 2000-2006 Tim Angus
    98.8 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    98.9  
   98.10 -This file is part of Tremfusion.
   98.11 +This file is part of XreaL source code.
   98.12  
   98.13 -Tremfusion is free software; you can redistribute it
   98.14 +XreaL source code is free software; you can redistribute it
   98.15  and/or modify it under the terms of the GNU General Public License as
   98.16  published by the Free Software Foundation; either version 2 of the License,
   98.17  or (at your option) any later version.
   98.18  
   98.19 -Tremfusion is distributed in the hope that it will be
   98.20 +XreaL source code is distributed in the hope that it will be
   98.21  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   98.22  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   98.23  GNU General Public License for more details.
   98.24  
   98.25  You should have received a copy of the GNU General Public License
   98.26 -along with Tremfusion; if not, write to the Free Software
   98.27 +along with XreaL source code; if not, write to the Free Software
   98.28  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   98.29  ===========================================================================
   98.30  */
   98.31  // tr_init.c -- functions that are not called every frame
   98.32 -
   98.33  #include "tr_local.h"
   98.34  
   98.35 -glconfig_t  glConfig;
   98.36 -glstate_t	glState;
   98.37 +glConfig_t      glConfig;
   98.38 +glstate_t       glState;
   98.39 +float           displayAspect = 0.0f;
   98.40  
   98.41 -static void GfxInfo_f( void );
   98.42 +static void     GfxInfo_f(void);
   98.43  
   98.44 -cvar_t	*r_flareSize;
   98.45 -cvar_t	*r_flareFade;
   98.46 -cvar_t	*r_flareCoeff;
   98.47 +cvar_t         *r_flares;
   98.48 +cvar_t         *r_flareSize;
   98.49 +cvar_t         *r_flareFade;
   98.50  
   98.51 -cvar_t	*r_railWidth;
   98.52 -cvar_t	*r_railCoreWidth;
   98.53 -cvar_t	*r_railSegmentLength;
   98.54 +cvar_t         *r_railWidth;
   98.55 +cvar_t         *r_railCoreWidth;
   98.56 +cvar_t         *r_railSegmentLength;
   98.57  
   98.58 -cvar_t	*r_ignoreFastPath;
   98.59 +cvar_t         *r_verbose;
   98.60 +cvar_t         *r_ignore;
   98.61  
   98.62 -cvar_t	*r_verbose;
   98.63 -cvar_t	*r_ignore;
   98.64 +cvar_t         *r_displayRefresh;
   98.65  
   98.66 -cvar_t	*r_displayRefresh;
   98.67 +cvar_t         *r_znear;
   98.68 +cvar_t         *r_zfar;
   98.69  
   98.70 -cvar_t	*r_detailTextures;
   98.71 +cvar_t         *r_smp;
   98.72 +cvar_t         *r_showSmp;
   98.73 +cvar_t         *r_skipBackEnd;
   98.74  
   98.75 -cvar_t	*r_znear;
   98.76 -cvar_t	*r_zproj;
   98.77 -cvar_t	*r_stereoSeparation;
   98.78 +cvar_t         *r_ignorehwgamma;
   98.79 +cvar_t         *r_measureOverdraw;
   98.80  
   98.81 -cvar_t	*r_smp;
   98.82 -cvar_t	*r_showSmp;
   98.83 -cvar_t	*r_skipBackEnd;
   98.84 +cvar_t         *r_inGameVideo;
   98.85 +cvar_t         *r_fastsky;
   98.86 +cvar_t         *r_drawSun;
   98.87  
   98.88 -cvar_t	*r_stereoEnabled;
   98.89 -cvar_t	*r_anaglyphMode;
   98.90 +cvar_t         *r_lodbias;
   98.91 +cvar_t         *r_lodscale;
   98.92  
   98.93 -cvar_t	*r_greyscale;
   98.94 +cvar_t         *r_norefresh;
   98.95 +cvar_t         *r_drawentities;
   98.96 +cvar_t         *r_drawworld;
   98.97 +cvar_t         *r_speeds;
   98.98 +cvar_t         *r_novis;
   98.99 +cvar_t         *r_nocull;
  98.100 +cvar_t         *r_facePlaneCull;
  98.101 +cvar_t         *r_showcluster;
  98.102 +cvar_t         *r_nocurves;
  98.103 +cvar_t         *r_nobatching;
  98.104 +cvar_t         *r_noLightScissors;
  98.105 +cvar_t         *r_noLightVisCull;
  98.106 +cvar_t         *r_noInteractionSort;
  98.107 +cvar_t         *r_noDynamicLighting;
  98.108 +cvar_t         *r_noStaticLighting;
  98.109 +cvar_t         *r_dynamicLightsCastShadows;
  98.110 +cvar_t         *r_precomputedLighting;
  98.111 +cvar_t         *r_vertexLighting;
  98.112 +cvar_t         *r_heatHazeFix;
  98.113 +cvar_t         *r_atiFlippedImageFix;
  98.114 +cvar_t         *r_noMarksOnTrisurfs;
  98.115  
  98.116 -cvar_t	*r_ignorehwgamma;
  98.117 -cvar_t	*r_measureOverdraw;
  98.118 +cvar_t         *r_ext_texture_compression;
  98.119 +cvar_t         *r_ext_occlusion_query;
  98.120 +cvar_t         *r_ext_texture_non_power_of_two;
  98.121 +cvar_t         *r_ext_draw_buffers;
  98.122 +cvar_t         *r_ext_vertex_array_object;
  98.123 +cvar_t         *r_ext_half_float_pixel;
  98.124 +cvar_t         *r_ext_texture_float;
  98.125 +cvar_t         *r_ext_stencil_wrap;
  98.126 +cvar_t         *r_ext_texture_filter_anisotropic;
  98.127 +cvar_t         *r_ext_stencil_two_side;
  98.128 +cvar_t         *r_ext_separate_stencil;
  98.129 +cvar_t         *r_ext_depth_bounds_test;
  98.130 +cvar_t         *r_ext_framebuffer_object;
  98.131 +cvar_t         *r_ext_packed_depth_stencil;
  98.132 +cvar_t         *r_ext_framebuffer_blit;
  98.133 +cvar_t         *r_extx_framebuffer_mixed_formats;
  98.134 +cvar_t         *r_ext_generate_mipmap;
  98.135  
  98.136 -cvar_t	*r_inGameVideo;
  98.137 -cvar_t	*r_fastsky;
  98.138 -cvar_t	*r_drawSun;
  98.139 -cvar_t	*r_dynamiclight;
  98.140 -cvar_t	*r_dlightBacks;
  98.141 +cvar_t         *r_ignoreGLErrors;
  98.142 +cvar_t         *r_logFile;
  98.143  
  98.144 -cvar_t	*r_minEntityLight;
  98.145 +cvar_t         *r_stencilbits;
  98.146 +cvar_t         *r_depthbits;
  98.147 +cvar_t         *r_colorbits;
  98.148 +cvar_t         *r_stereo;
  98.149  
  98.150 -cvar_t	*r_specularLighting;
  98.151 -cvar_t	*r_specularLightingExponent;
  98.152 +cvar_t         *r_drawBuffer;
  98.153 +cvar_t         *r_uiFullScreen;
  98.154 +cvar_t         *r_shadows;
  98.155 +cvar_t         *r_softShadows;
  98.156 +cvar_t         *r_shadowBlur;
  98.157 +cvar_t         *r_shadowMapQuality;
  98.158 +cvar_t         *r_shadowMapSizeUltra;
  98.159 +cvar_t         *r_shadowMapSizeVeryHigh;
  98.160 +cvar_t         *r_shadowMapSizeHigh;
  98.161 +cvar_t         *r_shadowMapSizeMedium;
  98.162 +cvar_t         *r_shadowMapSizeLow;
  98.163 +cvar_t         *r_shadowOffsetFactor;
  98.164 +cvar_t         *r_shadowOffsetUnits;
  98.165 +cvar_t         *r_shadowLodBias;
  98.166 +cvar_t         *r_shadowLodScale;
  98.167 +cvar_t         *r_noShadowPyramids;
  98.168 +cvar_t         *r_cullShadowPyramidFaces;
  98.169 +cvar_t         *r_cullShadowPyramidCurves;
  98.170 +cvar_t         *r_cullShadowPyramidTriangles;
  98.171 +cvar_t         *r_debugShadowMaps;
  98.172 +cvar_t         *r_noShadowFrustums;
  98.173 +cvar_t         *r_noLightFrustums;
  98.174 +cvar_t         *r_shadowMapLuminanceAlpha;
  98.175 +cvar_t         *r_shadowMapLinearFilter;
  98.176 +cvar_t         *r_lightBleedReduction;
  98.177 +cvar_t         *r_overDarkeningFactor;
  98.178 +cvar_t         *r_shadowMapDepthScale;
  98.179  
  98.180 -cvar_t	*r_lodbias;
  98.181 -cvar_t	*r_lodscale;
  98.182 +cvar_t         *r_mode;
  98.183 +cvar_t         *r_collapseStages;
  98.184 +cvar_t         *r_nobind;
  98.185 +cvar_t         *r_singleShader;
  98.186 +cvar_t         *r_roundImagesDown;
  98.187 +cvar_t         *r_colorMipLevels;
  98.188 +cvar_t         *r_picmip;
  98.189 +cvar_t         *r_finish;
  98.190 +cvar_t         *r_clear;
  98.191 +cvar_t         *r_swapInterval;
  98.192 +cvar_t         *r_textureMode;
  98.193 +cvar_t         *r_offsetFactor;
  98.194 +cvar_t         *r_offsetUnits;
  98.195 +cvar_t         *r_forceSpecular;
  98.196 +cvar_t         *r_specularExponent;
  98.197 +cvar_t         *r_specularScale;
  98.198 +cvar_t         *r_normalScale;
  98.199 +cvar_t         *r_normalMapping;
  98.200 +cvar_t         *r_gamma;
  98.201 +cvar_t         *r_intensity;
  98.202 +cvar_t         *r_lockpvs;
  98.203 +cvar_t         *r_noportals;
  98.204 +cvar_t         *r_portalOnly;
  98.205  
  98.206 -cvar_t	*r_norefresh;
  98.207 -cvar_t	*r_drawentities;
  98.208 -cvar_t	*r_drawworld;
  98.209 -cvar_t	*r_speeds;
  98.210 -cvar_t	*r_fullbright;
  98.211 -cvar_t	*r_novis;
  98.212 -cvar_t	*r_nocull;
  98.213 -cvar_t	*r_facePlaneCull;
  98.214 -cvar_t	*r_showcluster;
  98.215 -cvar_t	*r_nocurves;
  98.216 +cvar_t         *r_subdivisions;
  98.217 +cvar_t         *r_stitchCurves;
  98.218  
  98.219 -cvar_t	*r_allowExtensions;
  98.220 +cvar_t         *r_fullscreen;
  98.221  
  98.222 -cvar_t	*r_ext_compressed_textures;
  98.223 -cvar_t	*r_ext_multitexture;
  98.224 -cvar_t	*r_ext_compiled_vertex_array;
  98.225 -cvar_t	*r_ext_texture_env_add;
  98.226 -cvar_t	*r_ext_texture_filter_anisotropic;
  98.227 -cvar_t	*r_ext_max_anisotropy;
  98.228 +cvar_t         *r_customwidth;
  98.229 +cvar_t         *r_customheight;
  98.230 +cvar_t         *r_customaspect;
  98.231  
  98.232 -cvar_t	*r_ignoreGLErrors;
  98.233 -cvar_t	*r_logFile;
  98.234 +cvar_t         *r_overBrightBits;
  98.235 +cvar_t         *r_mapOverBrightBits;
  98.236  
  98.237 -cvar_t	*r_stencilbits;
  98.238 -cvar_t	*r_depthbits;
  98.239 -cvar_t	*r_colorbits;
  98.240 -cvar_t	*r_primitives;
  98.241 -cvar_t	*r_texturebits;
  98.242 +cvar_t         *r_debugSurface;
  98.243 +cvar_t         *r_simpleMipMaps;
  98.244  
  98.245 -cvar_t	*r_drawBuffer;
  98.246 -cvar_t	*r_lightmap;
  98.247 -cvar_t	*r_vertexLight;
  98.248 -cvar_t	*r_uiFullScreen;
  98.249 -cvar_t	*r_shadows;
  98.250 -cvar_t	*r_flares;
  98.251 -cvar_t	*r_nobind;
  98.252 -cvar_t	*r_singleShader;
  98.253 -cvar_t	*r_roundImagesDown;
  98.254 -cvar_t	*r_colorMipLevels;
  98.255 -cvar_t	*r_picmip;
  98.256 -cvar_t	*r_showtris;
  98.257 -cvar_t	*r_showsky;
  98.258 -cvar_t	*r_shownormals;
  98.259 -cvar_t	*r_finish;
  98.260 -cvar_t	*r_clear;
  98.261 -cvar_t	*r_swapInterval;
  98.262 -cvar_t	*r_textureMode;
  98.263 -cvar_t	*r_offsetFactor;
  98.264 -cvar_t	*r_offsetUnits;
  98.265 -cvar_t	*r_gamma;
  98.266 -cvar_t	*r_intensity;
  98.267 -cvar_t	*r_lockpvs;
  98.268 -cvar_t	*r_noportals;
  98.269 -cvar_t	*r_portalOnly;
  98.270 +cvar_t         *r_showImages;
  98.271  
  98.272 -cvar_t	*r_subdivisions;
  98.273 -cvar_t	*r_lodCurveError;
  98.274 +cvar_t         *r_forceFog;
  98.275 +cvar_t         *r_noFog;
  98.276  
  98.277 -cvar_t	*r_fullscreen;
  98.278 -cvar_t	*r_minimize;
  98.279 +cvar_t         *r_forceAmbient;
  98.280 +cvar_t         *r_ambientScale;
  98.281 +cvar_t         *r_lightScale;
  98.282 +cvar_t         *r_debugLight;
  98.283 +cvar_t         *r_debugSort;
  98.284 +cvar_t         *r_printShaders;
  98.285  
  98.286 -cvar_t	*r_width;
  98.287 -cvar_t	*r_height;
  98.288 -cvar_t	*r_pixelAspect;
  98.289 +cvar_t         *r_maxPolys;
  98.290 +cvar_t         *r_maxPolyVerts;
  98.291  
  98.292 -// compatibility
  98.293 -cvar_t  *r_mode;
  98.294 -cvar_t  *r_customwidth;
  98.295 -cvar_t  *r_customheight;
  98.296 -cvar_t  *r_custompixelAspect;
  98.297 +cvar_t         *r_showTris;
  98.298 +cvar_t         *r_showSky;
  98.299 +cvar_t         *r_showShadowVolumes;
  98.300 +cvar_t         *r_showShadowLod;
  98.301 +cvar_t         *r_showSkeleton;
  98.302 +cvar_t         *r_showEntityTransforms;
  98.303 +cvar_t         *r_showLightTransforms;
  98.304 +cvar_t         *r_showLightInteractions;
  98.305 +cvar_t         *r_showLightScissors;
  98.306 +cvar_t         *r_showLightBatches;
  98.307 +cvar_t         *r_showOcclusionQueries;
  98.308 +cvar_t         *r_showBatches;
  98.309 +cvar_t         *r_showLightMaps;
  98.310 +cvar_t         *r_showDeluxeMaps;
  98.311 +cvar_t         *r_showAreaPortals;
  98.312 +cvar_t         *r_showCubeProbes;
  98.313  
  98.314 -cvar_t	*r_overBrightBits;
  98.315 -cvar_t	*r_mapOverBrightBits;
  98.316 +cvar_t         *r_showDeferredDiffuse;
  98.317 +cvar_t         *r_showDeferredNormal;
  98.318 +cvar_t         *r_showDeferredSpecular;
  98.319 +cvar_t         *r_showDeferredPosition;
  98.320 +cvar_t         *r_showDeferredRender;
  98.321  
  98.322 -cvar_t	*r_debugSurface;
  98.323 -cvar_t	*r_simpleMipMaps;
  98.324 +cvar_t         *r_vboFaces;
  98.325 +cvar_t         *r_vboCurves;
  98.326 +cvar_t         *r_vboTriangles;
  98.327 +cvar_t         *r_vboShadows;
  98.328 +cvar_t         *r_vboLighting;
  98.329 +cvar_t         *r_vboDynamicLighting;
  98.330 +cvar_t         *r_vboModels;
  98.331 +cvar_t         *r_vboWorld;
  98.332 +cvar_t         *r_vboOptimizeVertices;
  98.333 +cvar_t         *r_vboVertexSkinning;
  98.334 +cvar_t         *r_vboSmoothNormals;
  98.335  
  98.336 -cvar_t	*r_showImages;
  98.337 +cvar_t         *r_precacheLightIndexes;
  98.338 +cvar_t         *r_precacheShadowIndexes;
  98.339  
  98.340 -cvar_t	*r_ambientScale;
  98.341 -cvar_t	*r_directedScale;
  98.342 -cvar_t	*r_debugLight;
  98.343 -cvar_t	*r_debugSort;
  98.344 -cvar_t	*r_printShaders;
  98.345 -cvar_t	*r_saveFontData;
  98.346 +cvar_t         *r_deferredShading;
  98.347 +cvar_t         *r_parallaxMapping;
  98.348 +cvar_t         *r_parallaxDepthScale;
  98.349  
  98.350 -// Next one added for cell shading algorithm selection
  98.351 -cvar_t	*r_celshadalgo;
  98.352 -//. next one for enable/disable cel bordering all together.
  98.353 -cvar_t	*r_celoutline;
  98.354 +cvar_t         *r_hdrRendering;
  98.355 +cvar_t         *r_hdrMinLuminance;
  98.356 +cvar_t         *r_hdrMaxLuminance;
  98.357 +cvar_t         *r_hdrKey;
  98.358 +cvar_t         *r_hdrContrastThreshold;
  98.359 +cvar_t         *r_hdrContrastOffset;
  98.360 +cvar_t         *r_hdrLightmap;
  98.361 +cvar_t         *r_hdrLightmapExposure;
  98.362 +cvar_t         *r_hdrLightmapGamma;
  98.363 +cvar_t         *r_hdrLightmapCompensate;
  98.364 +cvar_t         *r_hdrToneMappingOperator;
  98.365 +cvar_t         *r_hdrGamma;
  98.366  
  98.367 -cvar_t	*r_maxpolys;
  98.368 -int		max_polys;
  98.369 -cvar_t	*r_maxpolyverts;
  98.370 -int		max_polyverts;
  98.371 +cvar_t         *r_screenSpaceAmbientOcclusion;
  98.372 +cvar_t         *r_depthOfField;
  98.373 +cvar_t         *r_bloom;
  98.374 +cvar_t         *r_bloomBlur;
  98.375 +cvar_t         *r_bloomPasses;
  98.376 +cvar_t         *r_rotoscope;
  98.377  
  98.378 -#define GENERIC_HW_R_PICMIP_DEFAULT				"0"
  98.379 -#define GENERIC_HW_R_TEXTUREMODE_DEFAULT	"GL_LINEAR_MIPMAP_LINEAR"
  98.380 +// GL_ARB_multitexture
  98.381 +void            (APIENTRY * qglActiveTextureARB) (GLenum texture);
  98.382  
  98.383 -/*
  98.384 -==================
  98.385 -GL_ResolveHardwareType
  98.386 +// GL_ARB_texture_compression
  98.387 +void            (APIENTRY * qglCompressedTexImage3DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
  98.388 +void            (APIENTRY * qglCompressedTexImage2DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
  98.389 +void            (APIENTRY * qglCompressedTexImage1DARB) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
  98.390 +void            (APIENTRY * qglCompressedTexSubImage3DARB) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
  98.391 +void            (APIENTRY * qglCompressedTexSubImage2DARB) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
  98.392 +void            (APIENTRY * qglCompressedTexSubImage1DARB) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
  98.393 +void            (APIENTRY * qglGetCompressedTexImageARB) (GLenum target, GLint level, GLvoid *img);
  98.394  
  98.395 -Chipset specific configuration
  98.396 -==================
  98.397 -*/
  98.398 -void GL_ResolveHardwareType( void )
  98.399 -{
  98.400 -	char		buf[ 1024 ];
  98.401 -	cvar_t	*lastValidRenderer = ri.Cvar_Get(
  98.402 -			"r_lastValidRenderer", "(uninitialized)", CVAR_ARCHIVE );
  98.403 +// GL_ARB_vertex_program
  98.404 +void            (APIENTRY * qglVertexAttrib4fARB) (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
  98.405 +void            (APIENTRY * qglVertexAttrib4fvARB) (GLuint, const GLfloat *);
  98.406 +void            (APIENTRY * qglVertexAttribPointerARB) (GLuint index, GLint size, GLenum type, GLboolean normalized,
  98.407 +														GLsizei stride, const GLvoid * pointer);
  98.408 +void            (APIENTRY * qglEnableVertexAttribArrayARB) (GLuint index);
  98.409 +void            (APIENTRY * qglDisableVertexAttribArrayARB) (GLuint index);
  98.410  
  98.411 -	Q_strncpyz( buf, glConfig.renderer_string, sizeof( buf ) );
  98.412 -	Q_strlwr( buf );
  98.413 +// GL_ARB_vertex_buffer_object
  98.414 +void            (APIENTRY * qglBindBufferARB) (GLenum target, GLuint buffer);
  98.415 +void            (APIENTRY * qglDeleteBuffersARB) (GLsizei n, const GLuint * buffers);
  98.416 +void            (APIENTRY * qglGenBuffersARB) (GLsizei n, GLuint * buffers);
  98.417  
  98.418 -	// NOTE: if changing cvars, do it within this block.  This allows them
  98.419 -	// to be overridden when testing driver fixes, etc. but only sets
  98.420 -	// them to their default state when the hardware is first installed/run.
  98.421 -	if( Q_stricmp( lastValidRenderer->string, glConfig.renderer_string ) )
  98.422 -	{
  98.423 -		glConfig.hardwareType = GLHW_GENERIC;
  98.424 +GLboolean(APIENTRY * qglIsBufferARB) (GLuint buffer);
  98.425 +void            (APIENTRY * qglBufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage);
  98.426 +void            (APIENTRY * qglBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data);
  98.427 +void            (APIENTRY * qglGetBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data);
  98.428  
  98.429 -		ri.Cvar_Set( "r_textureMode", GENERIC_HW_R_TEXTUREMODE_DEFAULT );
  98.430 +// GL_ARB_occlusion_query
  98.431 +void            (APIENTRY * qglGenQueriesARB) (GLsizei n, GLuint * ids);
  98.432 +void            (APIENTRY * qglDeleteQueriesARB) (GLsizei n, const GLuint * ids);
  98.433  
  98.434 -		// VOODOO GRAPHICS w/ 2MB
  98.435 -		if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) )
  98.436 -		{
  98.437 -			ri.Cvar_Set( "r_picmip", "2" );
  98.438 -			ri.Cvar_Get( "r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH );
  98.439 -		}
  98.440 -		else
  98.441 -		{
  98.442 -			ri.Cvar_Set( "r_picmip", GENERIC_HW_R_PICMIP_DEFAULT );
  98.443 +GLboolean(APIENTRY * qglIsQueryARB) (GLuint id);
  98.444 +void            (APIENTRY * qglBeginQueryARB) (GLenum target, GLuint id);
  98.445 +void            (APIENTRY * qglEndQueryARB) (GLenum target);
  98.446 +void            (APIENTRY * qglGetQueryivARB) (GLenum target, GLenum pname, GLint * params);
  98.447 +void            (APIENTRY * qglGetQueryObjectivARB) (GLuint id, GLenum pname, GLint * params);
  98.448 +void            (APIENTRY * qglGetQueryObjectuivARB) (GLuint id, GLenum pname, GLuint * params);
  98.449  
  98.450 -			if ( strstr( buf, "rage 128" ) || strstr( buf, "rage128" ) )
  98.451 -			{
  98.452 -				ri.Cvar_Set( "r_finish", "0" );
  98.453 -			}
  98.454 -			// Savage3D and Savage4 should always have trilinear enabled
  98.455 -			else if ( strstr( buf, "savage3d" ) || strstr( buf, "s3 savage4" ) )
  98.456 -			{
  98.457 -				ri.Cvar_Set( "r_texturemode", "GL_LINEAR_MIPMAP_LINEAR" );
  98.458 -			}
  98.459 -		}
  98.460 -	}
  98.461 -	
  98.462 -	//
  98.463 -	// this is where hardware specific workarounds that should be
  98.464 -	// detected/initialized every startup should go.
  98.465 -	//
  98.466 -	if ( strstr( buf, "banshee" ) || strstr( buf, "voodoo3" ) )
  98.467 -	{
  98.468 -		glConfig.hardwareType = GLHW_3DFX_2D3D;
  98.469 -	}
  98.470 -	// VOODOO GRAPHICS w/ 2MB
  98.471 -	else if ( strstr( buf, "voodoo graphics/1 tmu/2 mb" ) )
  98.472 -	{
  98.473 -	}
  98.474 -	else if ( strstr( buf, "glzicd" ) )
  98.475 -	{
  98.476 -	}
  98.477 -	else if ( strstr( buf, "rage pro" ) ||
  98.478 -			strstr( buf, "Rage Pro" ) ||
  98.479 -			strstr( buf, "ragepro" ) )
  98.480 -	{
  98.481 -		glConfig.hardwareType = GLHW_RAGEPRO;
  98.482 -	}
  98.483 -	else if ( strstr( buf, "rage 128" ) )
  98.484 -	{
  98.485 -	}
  98.486 -	else if ( strstr( buf, "permedia2" ) )
  98.487 -	{
  98.488 -		glConfig.hardwareType = GLHW_PERMEDIA2;
  98.489 -	}
  98.490 -	else if ( strstr( buf, "riva 128" ) )
  98.491 -	{
  98.492 -		glConfig.hardwareType = GLHW_RIVA128;
  98.493 -	}
  98.494 -	else if ( strstr( buf, "riva tnt " ) )
  98.495 -	{
  98.496 -	}
  98.497 -}
  98.498 +GLboolean(APIENTRY * qglUnmapBufferARB) (GLenum target);
  98.499 +void            (APIENTRY * qglGetBufferParameterivARB) (GLenum target, GLenum pname, GLint * params);
  98.500 +void            (APIENTRY * qglGetBufferPointervARB) (GLenum target, GLenum pname, GLvoid * *params);
  98.501 +
  98.502 +// GL_ARB_shader_objects
  98.503 +void            (APIENTRY * qglDeleteObjectARB) (GLhandleARB obj);
  98.504 +
  98.505 +GLhandleARB(APIENTRY * qglGetHandleARB) (GLenum pname);
  98.506 +void            (APIENTRY * qglDetachObjectARB) (GLhandleARB containerObj, GLhandleARB attachedObj);
  98.507 +
  98.508 +GLhandleARB(APIENTRY * qglCreateShaderObjectARB) (GLenum shaderType);
  98.509 +void            (APIENTRY * qglShaderSourceARB) (GLhandleARB shaderObj, GLsizei count, const GLcharARB * *string,
  98.510 +												 const GLint * length);
  98.511 +void            (APIENTRY * qglCompileShaderARB) (GLhandleARB shaderObj);
  98.512 +
  98.513 +GLhandleARB(APIENTRY * qglCreateProgramObjectARB) (void);
  98.514 +void            (APIENTRY * qglAttachObjectARB) (GLhandleARB containerObj, GLhandleARB obj);
  98.515 +void            (APIENTRY * qglLinkProgramARB) (GLhandleARB programObj);
  98.516 +void            (APIENTRY * qglUseProgramObjectARB) (GLhandleARB programObj);
  98.517 +void            (APIENTRY * qglValidateProgramARB) (GLhandleARB programObj);
  98.518 +void            (APIENTRY * qglUniform1fARB) (GLint location, GLfloat v0);
  98.519 +void            (APIENTRY * qglUniform2fARB) (GLint location, GLfloat v0, GLfloat v1);
  98.520 +void            (APIENTRY * qglUniform3fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
  98.521 +void            (APIENTRY * qglUniform4fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
  98.522 +void            (APIENTRY * qglUniform1iARB) (GLint location, GLint v0);
  98.523 +void            (APIENTRY * qglUniform2iARB) (GLint location, GLint v0, GLint v1);
  98.524 +void            (APIENTRY * qglUniform3iARB) (GLint location, GLint v0, GLint v1, GLint v2);
  98.525 +void            (APIENTRY * qglUniform4iARB) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
  98.526 +void            (APIENTRY * qglUniform2fvARB) (GLint location, GLsizei count, const GLfloat * value);
  98.527 +void            (APIENTRY * qglUniform3fvARB) (GLint location, GLsizei count, const GLfloat * value);
  98.528 +void            (APIENTRY * qglUniform4fvARB) (GLint location, GLsizei count, const GLfloat * value);
  98.529 +void            (APIENTRY * qglUniform2ivARB) (GLint location, GLsizei count, const GLint * value);
  98.530 +void            (APIENTRY * qglUniform3ivARB) (GLint location, GLsizei count, const GLint * value);
  98.531 +void            (APIENTRY * qglUniform4ivARB) (GLint location, GLsizei count, const GLint * value);
  98.532 +void            (APIENTRY * qglUniformMatrix2fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
  98.533 +void            (APIENTRY * qglUniformMatrix3fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
  98.534 +void            (APIENTRY * qglUniformMatrix4fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
  98.535 +void            (APIENTRY * qglGetObjectParameterfvARB) (GLhandleARB obj, GLenum pname, GLfloat * params);
  98.536 +void            (APIENTRY * qglGetObjectParameterivARB) (GLhandleARB obj, GLenum pname, GLint * params);
  98.537 +void            (APIENTRY * qglGetInfoLogARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog);
  98.538 +void            (APIENTRY * qglGetAttachedObjectsARB) (GLhandleARB containerObj, GLsizei maxCount, GLsizei * count,
  98.539 +													   GLhandleARB * obj);
  98.540 +GLint(APIENTRY * qglGetUniformLocationARB) (GLhandleARB programObj, const GLcharARB * name);
  98.541 +void            (APIENTRY * qglGetActiveUniformARB) (GLhandleARB programObj, GLuint index, GLsizei maxIndex, GLsizei * length,
  98.542 +													 GLint * size, GLenum * type, GLcharARB * name);
  98.543 +void            (APIENTRY * qglGetUniformfvARB) (GLhandleARB programObj, GLint location, GLfloat * params);
  98.544 +void            (APIENTRY * qglGetUniformivARB) (GLhandleARB programObj, GLint location, GLint * params);
  98.545 +void            (APIENTRY * qglGetShaderSourceARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * source);
  98.546 +
  98.547 +// GL_ARB_vertex_shader
  98.548 +void            (APIENTRY * qglBindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB * name);
  98.549 +void            (APIENTRY * qglGetActiveAttribARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length,
  98.550 +													GLint * size, GLenum * type, GLcharARB * name);
  98.551 +GLint(APIENTRY * qglGetAttribLocationARB) (GLhandleARB programObj, const GLcharARB * name);
  98.552 +
  98.553 +// GL_ARB_draw_buffers
  98.554 +void            (APIENTRY * qglDrawBuffersARB) (GLsizei n, const GLenum * bufs);
  98.555 +
  98.556 +// GL_ARB_vertex_array_object
  98.557 +void			(APIENTRY * qglBindVertexArray) (GLuint array);
  98.558 +void			(APIENTRY * qglDeleteVertexArrays) (GLsizei n, const GLuint *arrays);
  98.559 +void			(APIENTRY * qglGenVertexArrays) (GLsizei n, GLuint *arrays);
  98.560 +GLboolean		(APIENTRY * qglIsVertexArray) (GLuint array);
  98.561 +
  98.562 +// GL_EXT_texture3D
  98.563 +void			(APIENTRY * qglTexImage3DEXT) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
  98.564 +void			(APIENTRY * qglTexSubImage3DEXT) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
  98.565 +
  98.566 +// GL_EXT_stencil_two_side
  98.567 +void            (APIENTRY * qglActiveStencilFaceEXT) (GLenum face);
  98.568 +
  98.569 +// GL_ATI_separate_stencil
  98.570 +void            (APIENTRY * qglStencilFuncSeparateATI) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
  98.571 +void            (APIENTRY * qglStencilOpSeparateATI) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
  98.572 +
  98.573 +// GL_EXT_depth_bounds_test
  98.574 +void            (APIENTRY * qglDepthBoundsEXT) (GLclampd zmin, GLclampd zmax);
  98.575 +
  98.576 +// GL_EXT_framebuffer_object
  98.577 +GLboolean(APIENTRY * qglIsRenderbufferEXT) (GLuint renderbuffer);
  98.578 +void            (APIENTRY * qglBindRenderbufferEXT) (GLenum target, GLuint renderbuffer);
  98.579 +void            (APIENTRY * qglDeleteRenderbuffersEXT) (GLsizei n, const GLuint * renderbuffers);
  98.580 +void            (APIENTRY * qglGenRenderbuffersEXT) (GLsizei n, GLuint * renderbuffers);
  98.581 +void            (APIENTRY * qglRenderbufferStorageEXT) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
  98.582 +void            (APIENTRY * qglGetRenderbufferParameterivEXT) (GLenum target, GLenum pname, GLint * params);
  98.583 +
  98.584 +GLboolean(APIENTRY * qglIsFramebufferEXT) (GLuint framebuffer);
  98.585 +void            (APIENTRY * qglBindFramebufferEXT) (GLenum target, GLuint framebuffer);
  98.586 +void            (APIENTRY * qglDeleteFramebuffersEXT) (GLsizei n, const GLuint * framebuffers);
  98.587 +void            (APIENTRY * qglGenFramebuffersEXT) (GLsizei n, GLuint * framebuffers);
  98.588 +
  98.589 +GLenum(APIENTRY * qglCheckFramebufferStatusEXT) (GLenum target);
  98.590 +void            (APIENTRY * qglFramebufferTexture1DEXT) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
  98.591 +														 GLint level);
  98.592 +void            (APIENTRY * qglFramebufferTexture2DEXT) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
  98.593 +														 GLint level);
  98.594 +void            (APIENTRY * qglFramebufferTexture3DEXT) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
  98.595 +														 GLint level, GLint zoffset);
  98.596 +void            (APIENTRY * qglFramebufferRenderbufferEXT) (GLenum target, GLenum attachment, GLenum renderbuffertarget,
  98.597 +															GLuint renderbuffer);
  98.598 +void            (APIENTRY * qglGetFramebufferAttachmentParameterivEXT) (GLenum target, GLenum attachment, GLenum pname,
  98.599 +																		GLint * params);
  98.600 +void            (APIENTRY * qglGenerateMipmapEXT) (GLenum target);
  98.601 +
  98.602 +// GL_EXT_framebuffer_blit
  98.603 +void			(APIENTRY * qglBlitFramebufferEXT) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
  98.604 +
  98.605 +
  98.606  
  98.607  /*
  98.608  ** InitOpenGL
  98.609 @@ -267,36 +409,37 @@
  98.610  ** setting variables, checking GL constants, and reporting the gfx system config
  98.611  ** to the user.
  98.612  */
  98.613 -static void InitOpenGL( void )
  98.614 +static void InitOpenGL(void)
  98.615  {
  98.616 -	char renderer_buffer[1024];
  98.617 +	char            renderer_buffer[1024];
  98.618  
  98.619  	//
  98.620  	// initialize OS specific portions of the renderer
  98.621  	//
  98.622  	// GLimp_Init directly or indirectly references the following cvars:
  98.623 -	//		- r_fullscreen
  98.624 -	//		- r_(width|height|pixelAspect)
  98.625 -	//		- r_(color|depth|stencil)bits
  98.626 -	//		- r_ignorehwgamma
  98.627 -	//		- r_gamma
  98.628 +	//      - r_fullscreen
  98.629 +	//      - r_glDriver
  98.630 +	//      - r_mode
  98.631 +	//      - r_(color|depth|stencil)bits
  98.632 +	//      - r_ignorehwgamma
  98.633 +	//      - r_gamma
  98.634  	//
  98.635 -	
  98.636 -	if ( glConfig.vidWidth == 0 )
  98.637 +
  98.638 +	if(glConfig.vidWidth == 0)
  98.639  	{
  98.640 -		GLint		temp;
  98.641 -		
  98.642 +		GLint           temp;
  98.643 +
  98.644  		GLimp_Init();
  98.645  
  98.646 -		strcpy( renderer_buffer, glConfig.renderer_string );
  98.647 -		Q_strlwr( renderer_buffer );
  98.648 +		strcpy(renderer_buffer, glConfig.renderer_string);
  98.649 +		Q_strlwr(renderer_buffer);
  98.650  
  98.651  		// OpenGL driver constants
  98.652 -		qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp );
  98.653 +		qglGetIntegerv(GL_MAX_TEXTURE_SIZE, &temp);
  98.654  		glConfig.maxTextureSize = temp;
  98.655  
  98.656  		// stubbed or broken drivers may have reported 0...
  98.657 -		if ( glConfig.maxTextureSize <= 0 ) 
  98.658 +		if(glConfig.maxTextureSize <= 0)
  98.659  		{
  98.660  			glConfig.maxTextureSize = 0;
  98.661  		}
  98.662 @@ -306,8 +449,7 @@
  98.663  	R_InitCommandBuffers();
  98.664  
  98.665  	// print info
  98.666 -	if( com_developer->integer )
  98.667 -		GfxInfo_f();
  98.668 +	GfxInfo_f();
  98.669  
  98.670  	// set default state
  98.671  	GL_SetDefaultState();
  98.672 @@ -318,142 +460,278 @@
  98.673  GL_CheckErrors
  98.674  ==================
  98.675  */
  98.676 -void GL_CheckErrors( void ) {
  98.677 -	int		err;
  98.678 -	char	s[64];
  98.679 +void GL_CheckErrors_(const char *filename, int line)
  98.680 +{
  98.681 +	int             err;
  98.682 +	char            s[128];
  98.683 +
  98.684 +	if(glConfig.smpActive)
  98.685 +	{
  98.686 +		// we can't print onto the console while rendering in another thread
  98.687 +		return;
  98.688 +	}
  98.689 +
  98.690 +	if(r_ignoreGLErrors->integer)
  98.691 +	{
  98.692 +		return;
  98.693 +	}
  98.694  
  98.695  	err = qglGetError();
  98.696 -	if ( err == GL_NO_ERROR ) {
  98.697 +	if(err == GL_NO_ERROR)
  98.698 +	{
  98.699  		return;
  98.700  	}
  98.701 -	if ( r_ignoreGLErrors->integer ) {
  98.702 -		return;
  98.703 -	}
  98.704 -	switch( err ) {
  98.705 +
  98.706 +	switch (err)
  98.707 +	{
  98.708  		case GL_INVALID_ENUM:
  98.709 -			strcpy( s, "GL_INVALID_ENUM" );
  98.710 +			strcpy(s, "GL_INVALID_ENUM");
  98.711  			break;
  98.712  		case GL_INVALID_VALUE:
  98.713 -			strcpy( s, "GL_INVALID_VALUE" );
  98.714 +			strcpy(s, "GL_INVALID_VALUE");
  98.715  			break;
  98.716  		case GL_INVALID_OPERATION:
  98.717 -			strcpy( s, "GL_INVALID_OPERATION" );
  98.718 +			strcpy(s, "GL_INVALID_OPERATION");
  98.719  			break;
  98.720  		case GL_STACK_OVERFLOW:
  98.721 -			strcpy( s, "GL_STACK_OVERFLOW" );
  98.722 +			strcpy(s, "GL_STACK_OVERFLOW");
  98.723  			break;
  98.724  		case GL_STACK_UNDERFLOW:
  98.725 -			strcpy( s, "GL_STACK_UNDERFLOW" );
  98.726 +			strcpy(s, "GL_STACK_UNDERFLOW");
  98.727  			break;
  98.728  		case GL_OUT_OF_MEMORY:
  98.729 -			strcpy( s, "GL_OUT_OF_MEMORY" );
  98.730 +			strcpy(s, "GL_OUT_OF_MEMORY");
  98.731 +			break;
  98.732 +		case GL_TABLE_TOO_LARGE:
  98.733 +			strcpy(s, "GL_TABLE_TOO_LARGE");
  98.734 +			break;
  98.735 +		case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
  98.736 +			strcpy(s, "GL_INVALID_FRAMEBUFFER_OPERATION_EXT");
  98.737  			break;
  98.738  		default:
  98.739 -			Com_sprintf( s, sizeof(s), "%i", err);
  98.740 +			Com_sprintf(s, sizeof(s), "0x%X", err);
  98.741  			break;
  98.742  	}
  98.743  
  98.744 -	ri.Error( ERR_FATAL, "GL_CheckErrors: %s", s );
  98.745 +	ri.Error(ERR_FATAL, "caught OpenGL error: %s in file %s line %i", s, filename, line);
  98.746  }
  98.747  
  98.748  
  98.749 -/* 
  98.750 -============================================================================== 
  98.751 - 
  98.752 -						SCREEN SHOTS 
  98.753 +/*
  98.754 +** R_GetModeInfo
  98.755 +*/
  98.756 +typedef struct vidmode_s
  98.757 +{
  98.758 +	const char     *description;
  98.759 +	int             width, height;
  98.760 +	float           pixelAspect;	// pixel width / height
  98.761 +} vidmode_t;
  98.762  
  98.763 -NOTE TTimo
  98.764 -some thoughts about the screenshots system:
  98.765 +vidmode_t       r_vidModes[] = {
  98.766 +	{"Mode  0: 320x240", 320, 240, 1},
  98.767 +	{"Mode  1: 400x300", 400, 300, 1},
  98.768 +	{"Mode  2: 512x384", 512, 384, 1},
  98.769 +	{"Mode  3: 640x480", 640, 480, 1},
  98.770 +	{"Mode  4: 800x600", 800, 600, 1},
  98.771 +	{"Mode  5: 960x720", 960, 720, 1},
  98.772 +	{"Mode  6: 1024x768", 1024, 768, 1},
  98.773 +	{"Mode  7: 1152x864", 1152, 864, 1},
  98.774 +	{"Mode  9: 1280x720 (16:9)", 1280, 720, 1},
  98.775 +	{"Mode 10: 1280x768 (16:10)", 1280, 768, 1},
  98.776 +	{"Mode 11: 1280x800 (16:10)", 1280, 800, 1},
  98.777 +	{"Mode 12: 1280x1024", 1280, 1024, 1},
  98.778 +	{"Mode 13: 1360x768 (16:9)", 1360, 768, 1},
  98.779 +	{"Mode 14: 1440x900 (16:10)", 1440, 900, 1},
  98.780 +	{"Mode 15: 1680x1050 (16:10)", 1680, 1050, 1},
  98.781 +	{"Mode 16: 1600x1200", 1600, 1200, 1},
  98.782 +	{"Mode 17: 1920x1080 (16:9)", 1920, 1080, 1},
  98.783 +	{"Mode 18: 1920x1200 (16:10)", 1920, 1200, 1},
  98.784 +	{"Mode 19: 2048x1536", 2048, 1536, 1},
  98.785 +	{"Mode 20: 2560x1600 (16:10)", 2560, 1600, 1},
  98.786 +};
  98.787 +static int      s_numVidModes = (sizeof(r_vidModes) / sizeof(r_vidModes[0]));
  98.788 +
  98.789 +qboolean R_GetModeInfo(int *width, int *height, float *windowAspect, int mode)
  98.790 +{
  98.791 +	vidmode_t      *vm;
  98.792 +
  98.793 +	if(mode < -1)
  98.794 +	{
  98.795 +		return qfalse;
  98.796 +	}
  98.797 +	if(mode >= s_numVidModes)
  98.798 +	{
  98.799 +		return qfalse;
  98.800 +	}
  98.801 +
  98.802 +	if(mode == -1)
  98.803 +	{
  98.804 +		*width = r_customwidth->integer;
  98.805 +		*height = r_customheight->integer;
  98.806 +		*windowAspect = r_customaspect->value;
  98.807 +		return qtrue;
  98.808 +	}
  98.809 +
  98.810 +	vm = &r_vidModes[mode];
  98.811 +
  98.812 +	*width = vm->width;
  98.813 +	*height = vm->height;
  98.814 +	*windowAspect = (float)vm->width / (vm->height * vm->pixelAspect);
  98.815 +
  98.816 +	return qtrue;
  98.817 +}
  98.818 +
  98.819 +/*
  98.820 +** R_ModeList_f
  98.821 +*/
  98.822 +static void R_ModeList_f(void)
  98.823 +{
  98.824 +	int             i;
  98.825 +
  98.826 +	ri.Printf(PRINT_ALL, "\n");
  98.827 +	for(i = 0; i < s_numVidModes; i++)
  98.828 +	{
  98.829 +		ri.Printf(PRINT_ALL, "%s\n", r_vidModes[i].description);
  98.830 +	}
  98.831 +	ri.Printf(PRINT_ALL, "\n");
  98.832 +}
  98.833 +
  98.834 +
  98.835 +
  98.836 +/*
  98.837 +==============================================================================
  98.838 +
  98.839 +						SCREEN SHOTS
  98.840 +
  98.841  screenshots get written in fs_homepath + fs_gamedir
  98.842 -vanilla q3 .. baseq3/screenshots/ *.tga
  98.843 -team arena .. missionpack/screenshots/ *.tga
  98.844 +.. base/screenshots/*.*
  98.845  
  98.846 -two commands: "screenshot" and "screenshotJPEG"
  98.847 -we use statics to store a count and start writing the first screenshot/screenshot????.tga (.jpg) available
  98.848 -(with FS_FileExists / FS_FOpenFileWrite calls)
  98.849 -FIXME: the statics don't get a reinit between fs_game changes
  98.850 +three commands: "screenshot", "screenshotJPEG" and "screenshotPNG"
  98.851  
  98.852 -============================================================================== 
  98.853 -*/ 
  98.854 +the format is xreal-YYYY_MM_DD-HH_MM_SS-MS.tga/jpeg/png
  98.855  
  98.856 -/* 
  98.857 -================== 
  98.858 +==============================================================================
  98.859 +*/
  98.860 +
  98.861 +/*
  98.862 +==================
  98.863  RB_TakeScreenshot
  98.864 -================== 
  98.865 -*/  
  98.866 -void RB_TakeScreenshot( int x, int y, int width, int height, char *fileName ) {
  98.867 -	byte		*buffer;
  98.868 -	int			i, c, temp;
  98.869 -		
  98.870 -	buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*3+18);
  98.871 +==================
  98.872 +*/
  98.873 +static void RB_TakeScreenshot(int x, int y, int width, int height, char *fileName)
  98.874 +{
  98.875 +	byte           *buffer;
  98.876 +	int             i, c, temp;
  98.877  
  98.878 -	Com_Memset (buffer, 0, 18);
  98.879 -	buffer[2] = 2;		// uncompressed type
  98.880 +	buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth * glConfig.vidHeight * 3 + 18);
  98.881 +
  98.882 +	Com_Memset(buffer, 0, 18);
  98.883 +	buffer[2] = 2;				// uncompressed type
  98.884  	buffer[12] = width & 255;
  98.885  	buffer[13] = width >> 8;
  98.886  	buffer[14] = height & 255;
  98.887  	buffer[15] = height >> 8;
  98.888 -	buffer[16] = 24;	// pixel size
  98.889 +	buffer[16] = 24;			// pixel size
  98.890  
  98.891 -	qglReadPixels( x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); 
  98.892 +	qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer + 18);
  98.893  
  98.894  	// swap rgb to bgr
  98.895  	c = 18 + width * height * 3;
  98.896 -	for (i=18 ; i<c ; i+=3) {
  98.897 +	for(i = 18; i < c; i += 3)
  98.898 +	{
  98.899  		temp = buffer[i];
  98.900 -		buffer[i] = buffer[i+2];
  98.901 -		buffer[i+2] = temp;
  98.902 +		buffer[i] = buffer[i + 2];
  98.903 +		buffer[i + 2] = temp;
  98.904  	}
  98.905  
  98.906  	// gamma correct
  98.907 -	if ( glConfig.deviceSupportsGamma ) {
  98.908 -		R_GammaCorrect( buffer + 18, glConfig.vidWidth * glConfig.vidHeight * 3 );
  98.909 +	if((tr.overbrightBits > 0) && glConfig.deviceSupportsGamma)
  98.910 +	{
  98.911 +		R_GammaCorrect(buffer + 18, glConfig.vidWidth * glConfig.vidHeight * 3);
  98.912  	}
  98.913  
  98.914 -	ri.FS_WriteFile( fileName, buffer, c );
  98.915 +	ri.FS_WriteFile(fileName, buffer, c);
  98.916  
  98.917 -	ri.Hunk_FreeTempMemory( buffer );
  98.918 +	ri.Hunk_FreeTempMemory(buffer);
  98.919  }
  98.920  
  98.921 -/* 
  98.922 -================== 
  98.923 +/*
  98.924 +==================
  98.925  RB_TakeScreenshotJPEG
  98.926 -================== 
  98.927 -*/  
  98.928 -void RB_TakeScreenshotJPEG( int x, int y, int width, int height, char *fileName ) {
  98.929 -	byte		*buffer;
  98.930 +==================
  98.931 +*/
  98.932 +static void RB_TakeScreenshotJPEG(int x, int y, int width, int height, char *fileName)
  98.933 +{
  98.934 +	byte           *buffer;
  98.935  
  98.936 -	buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*4);
  98.937 +	buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth * glConfig.vidHeight * 4);
  98.938  
  98.939 -	qglReadPixels( x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer ); 
  98.940 +	qglReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
  98.941  
  98.942  	// gamma correct
  98.943 -	if ( glConfig.deviceSupportsGamma ) {
  98.944 -		R_GammaCorrect( buffer, glConfig.vidWidth * glConfig.vidHeight * 4 );
  98.945 +	if((tr.overbrightBits > 0) && glConfig.deviceSupportsGamma)
  98.946 +	{
  98.947 +		R_GammaCorrect(buffer, glConfig.vidWidth * glConfig.vidHeight * 4);
  98.948  	}
  98.949  
  98.950 -	ri.FS_WriteFile( fileName, buffer, 1 );		// create path
  98.951 -	SaveJPG( fileName, 90, glConfig.vidWidth, glConfig.vidHeight, buffer);
  98.952 +	ri.FS_WriteFile(fileName, buffer, 1);	// create path
  98.953 +	SaveJPG(fileName, 90, glConfig.vidWidth, glConfig.vidHeight, buffer);
  98.954  
  98.955 -	ri.Hunk_FreeTempMemory( buffer );
  98.956 +	ri.Hunk_FreeTempMemory(buffer);
  98.957  }
  98.958  
  98.959  /*
  98.960  ==================
  98.961 +RB_TakeScreenshotPNG
  98.962 +==================
  98.963 +*/
  98.964 +/*static void RB_TakeScreenshotPNG(int x, int y, int width, int height, char *fileName)
  98.965 +{
  98.966 +	byte           *buffer;
  98.967 +
  98.968 +	buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth * glConfig.vidHeight * 3);
  98.969 +
  98.970 +	qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
  98.971 +
  98.972 +	// gamma correct
  98.973 +	if((tr.overbrightBits > 0) && glConfig.deviceSupportsGamma)
  98.974 +	{
  98.975 +		R_GammaCorrect(buffer, glConfig.vidWidth * glConfig.vidHeight * 3);
  98.976 +	}
  98.977 +
  98.978 +	ri.FS_WriteFile(fileName, buffer, 1);	// create path
  98.979 +	SavePNG(fileName, buffer, glConfig.vidWidth, glConfig.vidHeight, 3, qfalse);
  98.980 +
  98.981 +	ri.Hunk_FreeTempMemory(buffer);
  98.982 +}*/
  98.983 +
  98.984 +/*
  98.985 +==================
  98.986  RB_TakeScreenshotCmd
  98.987  ==================
  98.988  */
  98.989 -const void *RB_TakeScreenshotCmd( const void *data ) {
  98.990 -	const screenshotCommand_t	*cmd;
  98.991 -	
  98.992 +const void     *RB_TakeScreenshotCmd(const void *data)
  98.993 +{
  98.994 +	const screenshotCommand_t *cmd;
  98.995 +
  98.996  	cmd = (const screenshotCommand_t *)data;
  98.997 -	
  98.998 -	if (cmd->jpeg)
  98.999 -		RB_TakeScreenshotJPEG( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
 98.1000 -	else
 98.1001 -		RB_TakeScreenshot( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
 98.1002 -	
 98.1003 -	return (const void *)(cmd + 1);	
 98.1004 +
 98.1005 +	switch (cmd->format)
 98.1006 +	{
 98.1007 +		case SSF_TGA:
 98.1008 +			RB_TakeScreenshot(cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
 98.1009 +			break;
 98.1010 +
 98.1011 +		case SSF_JPEG:
 98.1012 +			RB_TakeScreenshotJPEG(cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
 98.1013 +			break;
 98.1014 +
 98.1015 +		/*case SSF_PNG:
 98.1016 +			RB_TakeScreenshotPNG(cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
 98.1017 +			break;*/
 98.1018 +	}
 98.1019 +
 98.1020 +	return (const void *)(cmd + 1);
 98.1021  }
 98.1022  
 98.1023  /*
 98.1024 @@ -461,74 +739,81 @@
 98.1025  R_TakeScreenshot
 98.1026  ==================
 98.1027  */
 98.1028 -void R_TakeScreenshot( int x, int y, int width, int height, char *name, qboolean jpeg ) {
 98.1029 -	static char	fileName[MAX_OSPATH]; // bad things if two screenshots per frame?
 98.1030 -	screenshotCommand_t	*cmd;
 98.1031 +void R_TakeScreenshot(char *name, ssFormat_t format)
 98.1032 +{
 98.1033 +	static char     fileName[MAX_OSPATH];	// bad things may happen if two screenshots per frame are taken.
 98.1034 +	screenshotCommand_t *cmd;
 98.1035 +	int             lastNumber;
 98.1036  
 98.1037 -	cmd = R_GetCommandBuffer( sizeof( *cmd ) );
 98.1038 -	if ( !cmd ) {
 98.1039 -		return;
 98.1040 -	}
 98.1041 -	cmd->commandId = RC_SCREENSHOT;
 98.1042 -
 98.1043 -	cmd->x = x;
 98.1044 -	cmd->y = y;
 98.1045 -	cmd->width = width;
 98.1046 -	cmd->height = height;
 98.1047 -	Q_strncpyz( fileName, name, sizeof(fileName) );
 98.1048 -	cmd->fileName = fileName;
 98.1049 -	cmd->jpeg = jpeg;
 98.1050 -}
 98.1051 -
 98.1052 -/* 
 98.1053 -================== 
 98.1054 -R_ScreenshotFilename
 98.1055 -================== 
 98.1056 -*/  
 98.1057 -void R_ScreenshotFilename( int lastNumber, char *fileName ) {
 98.1058 -	int		a,b,c,d;
 98.1059 -
 98.1060 -	if ( lastNumber < 0 || lastNumber > 9999 ) {
 98.1061 -		Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.tga" );
 98.1062 +	cmd = R_GetCommandBuffer(sizeof(*cmd));
 98.1063 +	if(!cmd)
 98.1064 +	{
 98.1065  		return;
 98.1066  	}
 98.1067  
 98.1068 -	a = lastNumber / 1000;
 98.1069 -	lastNumber -= a*1000;
 98.1070 -	b = lastNumber / 100;
 98.1071 -	lastNumber -= b*100;
 98.1072 -	c = lastNumber / 10;
 98.1073 -	lastNumber -= c*10;
 98.1074 -	d = lastNumber;
 98.1075 +	if(ri.Cmd_Argc() == 2)
 98.1076 +	{
 98.1077 +		Com_sprintf(fileName, sizeof(fileName), "screenshots/xreal-%s.%s", ri.Cmd_Argv(1), name);
 98.1078 +	}
 98.1079 +	else
 98.1080 +	{
 98.1081 +		qtime_t         t;
 98.1082  
 98.1083 -	Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.tga"
 98.1084 -		, a, b, c, d );
 98.1085 +		Com_RealTime(&t);
 98.1086 +
 98.1087 +		// scan for a free filename
 98.1088 +		for(lastNumber = 0; lastNumber <= 999; lastNumber++)
 98.1089 +		{
 98.1090 +			Com_sprintf(fileName, sizeof(fileName), "screenshots/xreal-%04d%02d%02d-%02d%02d%02d-%03d.%s",
 98.1091 +						1900 + t.tm_year, 1 + t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, lastNumber, name);
 98.1092 +
 98.1093 +			if(!ri.FS_FileExists(fileName))
 98.1094 +			{
 98.1095 +				break;			// file doesn't exist
 98.1096 +			}
 98.1097 +		}
 98.1098 +
 98.1099 +		if(lastNumber == 1000)
 98.1100 +		{
 98.1101 +			ri.Printf(PRINT_ALL, "ScreenShot: Couldn't create a file\n");
 98.1102 +			return;
 98.1103 +		}
 98.1104 +
 98.1105 +		lastNumber++;
 98.1106 +	}
 98.1107 +	ri.Printf(PRINT_ALL, "Wrote %s\n", fileName);
 98.1108 +
 98.1109 +	cmd->commandId = RC_SCREENSHOT;
 98.1110 +	cmd->x = 0;
 98.1111 +	cmd->y = 0;
 98.1112 +	cmd->width = glConfig.vidWidth;
 98.1113 +	cmd->height = glConfig.vidHeight;
 98.1114 +	cmd->fileName = fileName;
 98.1115 +	cmd->format = format;
 98.1116  }
 98.1117  
 98.1118 -/* 
 98.1119 -================== 
 98.1120 -R_ScreenshotFilename
 98.1121 -================== 
 98.1122 -*/  
 98.1123 -void R_ScreenshotFilenameJPEG( int lastNumber, char *fileName ) {
 98.1124 -	int		a,b,c,d;
 98.1125 +/*
 98.1126 +==================
 98.1127 +R_ScreenShot_f
 98.1128  
 98.1129 -	if ( lastNumber < 0 || lastNumber > 9999 ) {
 98.1130 -		Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.jpg" );
 98.1131 -		return;
 98.1132 -	}
 98.1133 +screenshot
 98.1134 +screenshot [filename]
 98.1135 +==================
 98.1136 +*/
 98.1137 +static void R_ScreenShot_f(void)
 98.1138 +{
 98.1139 +	R_TakeScreenshot("tga", SSF_TGA);
 98.1140 +}
 98.1141  
 98.1142 -	a = lastNumber / 1000;
 98.1143 -	lastNumber -= a*1000;
 98.1144 -	b = lastNumber / 100;
 98.1145 -	lastNumber -= b*100;
 98.1146 -	c = lastNumber / 10;
 98.1147 -	lastNumber -= c*10;
 98.1148 -	d = lastNumber;
 98.1149 +static void R_ScreenShotJPEG_f(void)
 98.1150 +{
 98.1151 +	R_TakeScreenshot("jpg", SSF_JPEG);
 98.1152 +}
 98.1153  
 98.1154 -	Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.jpg"
 98.1155 -		, a, b, c, d );
 98.1156 -}
 98.1157 +/*static void R_ScreenShotPNG_f(void)
 98.1158 +{
 98.1159 +	R_TakeScreenshot("png", SSF_PNG);
 98.1160 +}*/
 98.1161  
 98.1162  /*
 98.1163  ====================
 98.1164 @@ -538,44 +823,49 @@
 98.1165  the menu system, sampled down from full screen distorted images
 98.1166  ====================
 98.1167  */
 98.1168 -void R_LevelShot( void ) {
 98.1169 -	char		checkname[MAX_OSPATH];
 98.1170 -	byte		*buffer;
 98.1171 -	byte		*source;
 98.1172 -	byte		*src, *dst;
 98.1173 -	int			x, y;
 98.1174 -	int			r, g, b;
 98.1175 -	float		xScale, yScale;
 98.1176 -	int			xx, yy;
 98.1177 +static void R_LevelShot(void)
 98.1178 +{
 98.1179 +	char            checkname[MAX_OSPATH];
 98.1180 +	byte           *buffer;
 98.1181 +	byte           *source;
 98.1182 +	byte           *src, *dst;
 98.1183 +	int             x, y;
 98.1184 +	int             r, g, b;
 98.1185 +	float           xScale, yScale;
 98.1186 +	int             xx, yy;
 98.1187  
 98.1188 -	sprintf( checkname, "levelshots/%s.tga", tr.world->baseName );
 98.1189 +	sprintf(checkname, "levelshots/%s.tga", tr.world->baseName);
 98.1190  
 98.1191 -	source = ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight * 3 );
 98.1192 +	source = ri.Hunk_AllocateTempMemory(glConfig.vidWidth * glConfig.vidHeight * 3);
 98.1193  
 98.1194 -	buffer = ri.Hunk_AllocateTempMemory( 128 * 128*3 + 18);
 98.1195 -	Com_Memset (buffer, 0, 18);
 98.1196 -	buffer[2] = 2;		// uncompressed type
 98.1197 +	buffer = ri.Hunk_AllocateTempMemory(128 * 128 * 3 + 18);
 98.1198 +	Com_Memset(buffer, 0, 18);
 98.1199 +	buffer[2] = 2;				// uncompressed type
 98.1200  	buffer[12] = 128;
 98.1201  	buffer[14] = 128;
 98.1202 -	buffer[16] = 24;	// pixel size
 98.1203 +	buffer[16] = 24;			// pixel size
 98.1204  
 98.1205 -	qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGB, GL_UNSIGNED_BYTE, source ); 
 98.1206 +	qglReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGB, GL_UNSIGNED_BYTE, source);
 98.1207  
 98.1208  	// resample from source
 98.1209  	xScale = glConfig.vidWidth / 512.0f;
 98.1210  	yScale = glConfig.vidHeight / 384.0f;
 98.1211 -	for ( y = 0 ; y < 128 ; y++ ) {
 98.1212 -		for ( x = 0 ; x < 128 ; x++ ) {
 98.1213 +	for(y = 0; y < 128; y++)
 98.1214 +	{
 98.1215 +		for(x = 0; x < 128; x++)
 98.1216 +		{
 98.1217  			r = g = b = 0;
 98.1218 -			for ( yy = 0 ; yy < 3 ; yy++ ) {
 98.1219 -				for ( xx = 0 ; xx < 4 ; xx++ ) {
 98.1220 -					src = source + 3 * ( glConfig.vidWidth * (int)( (y*3+yy)*yScale ) + (int)( (x*4+xx)*xScale ) );
 98.1221 +			for(yy = 0; yy < 3; yy++)
 98.1222 +			{
 98.1223 +				for(xx = 0; xx < 4; xx++)
 98.1224 +				{
 98.1225 +					src = source + 3 * (glConfig.vidWidth * (int)((y * 3 + yy) * yScale) + (int)((x * 4 + xx) * xScale));
 98.1226  					r += src[0];
 98.1227  					g += src[1];
 98.1228  					b += src[2];
 98.1229  				}
 98.1230  			}
 98.1231 -			dst = buffer + 18 + 3 * ( y * 128 + x );
 98.1232 +			dst = buffer + 18 + 3 * (y * 128 + x);
 98.1233  			dst[0] = b / 12;
 98.1234  			dst[1] = g / 12;
 98.1235  			dst[2] = r / 12;
 98.1236 @@ -583,135 +873,170 @@
 98.1237  	}
 98.1238  
 98.1239  	// gamma correct
 98.1240 -	if ( glConfig.deviceSupportsGamma ) {
 98.1241 -		R_GammaCorrect( buffer + 18, 128 * 128 * 3 );
 98.1242 +	if((tr.overbrightBits > 0) && glConfig.deviceSupportsGamma)
 98.1243 +	{
 98.1244 +		R_GammaCorrect(buffer + 18, 128 * 128 * 3);
 98.1245  	}
 98.1246  
 98.1247 -	ri.FS_WriteFile( checkname, buffer, 128 * 128*3 + 18 );
 98.1248 +	ri.FS_WriteFile(checkname, buffer, 128 * 128 * 3 + 18);
 98.1249  
 98.1250 -	ri.Hunk_FreeTempMemory( buffer );
 98.1251 -	ri.Hunk_FreeTempMemory( source );
 98.1252 +	ri.Hunk_FreeTempMemory(buffer);
 98.1253 +	ri.Hunk_FreeTempMemory(source);
 98.1254  
 98.1255 -	ri.Printf( PRINT_ALL, "Wrote %s\n", checkname );
 98.1256 +	ri.Printf(PRINT_ALL, "Wrote %s\n", checkname);
 98.1257  }
 98.1258  
 98.1259 -/* 
 98.1260 -================== 
 98.1261 -R_ScreenShot_f
 98.1262 +static int QDECL MaterialNameCompare(const void *a, const void *b)
 98.1263 +{
 98.1264 +	char           *s1, *s2;
 98.1265 +	int             c1, c2;
 98.1266  
 98.1267 -screenshot
 98.1268 -screenshot [silent]
 98.1269 -screenshot [levelshot]
 98.1270 -screenshot [filename]
 98.1271 +	s1 = *(char **)a;
 98.1272 +	s2 = *(char **)b;
 98.1273  
 98.1274 -Doesn't print the pacifier message if there is a second arg
 98.1275 -================== 
 98.1276 -*/  
 98.1277 -void R_ScreenShot_f (void) {
 98.1278 -	char	checkname[MAX_OSPATH];
 98.1279 -	static	int	lastNumber = -1;
 98.1280 -	qboolean	silent;
 98.1281 +	do
 98.1282 +	{
 98.1283 +		c1 = *s1++;
 98.1284 +		c2 = *s2++;
 98.1285  
 98.1286 -	if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
 98.1287 -		R_LevelShot();
 98.1288 +		if(c1 >= 'a' && c1 <= 'z')
 98.1289 +		{
 98.1290 +			c1 -= ('a' - 'A');
 98.1291 +		}
 98.1292 +		if(c2 >= 'a' && c2 <= 'z')
 98.1293 +		{
 98.1294 +			c2 -= ('a' - 'A');
 98.1295 +		}
 98.1296 +
 98.1297 +		if(c1 == '\\' || c1 == ':')
 98.1298 +		{
 98.1299 +			c1 = '/';
 98.1300 +		}
 98.1301 +		if(c2 == '\\' || c2 == ':')
 98.1302 +		{
 98.1303 +			c2 = '/';
 98.1304 +		}
 98.1305 +
 98.1306 +		if(c1 < c2)
 98.1307 +		{
 98.1308 +			// strings not equal
 98.1309 +			return -1;
 98.1310 +		}
 98.1311 +		if(c1 > c2)
 98.1312 +		{
 98.1313 +			return 1;
 98.1314 +		}
 98.1315 +	} while(c1);
 98.1316 +
 98.1317 +	// strings are equal
 98.1318 +	return 0;
 98.1319 +}
 98.1320 +
 98.1321 +static void R_GenerateMaterialFile_f(void)
 98.1322 +{
 98.1323 +	char          **dirnames;
 98.1324 +	int             ndirs;
 98.1325 +	int             i;
 98.1326 +	fileHandle_t    f;
 98.1327 +	char            fileName[MAX_QPATH];
 98.1328 +	char            fileName2[MAX_QPATH];
 98.1329 +	char            cleanName[MAX_QPATH];
 98.1330 +	char            cleanName2[MAX_QPATH];
 98.1331 +	char            baseName[MAX_QPATH];
 98.1332 +	char            baseName2[MAX_QPATH];
 98.1333 +	char            path[MAX_QPATH];
 98.1334 +	char            extension[MAX_QPATH];
 98.1335 +	int				len;
 98.1336 +
 98.1337 +	if(Cmd_Argc() < 3)
 98.1338 +	{
 98.1339 +		Com_Printf("usage: generatemtr <directory> [image extension]\n");
 98.1340  		return;
 98.1341  	}
 98.1342  
 98.1343 -	if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) {
 98.1344 -		silent = qtrue;
 98.1345 -	} else {
 98.1346 -		silent = qfalse;
 98.1347 -	}
 98.1348 +	Q_strncpyz(path, Cmd_Argv(1), sizeof(path));
 98.1349  
 98.1350 -	if ( ri.Cmd_Argc() == 2 && !silent ) {
 98.1351 -		// explicit filename
 98.1352 -		Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.tga", ri.Cmd_Argv( 1 ) );
 98.1353 -	} else {
 98.1354 -		// scan for a free filename
 98.1355 +	Q_strncpyz(extension, Cmd_Argv(2), sizeof(extension));
 98.1356 +	Q_strreplace(extension, sizeof(extension), ".", "");
 98.1357  
 98.1358 -		// if we have saved a previous screenshot, don't scan
 98.1359 -		// again, because recording demo avis can involve
 98.1360 -		// thousands of shots
 98.1361 -		if ( lastNumber == -1 ) {
 98.1362 -			lastNumber = 0;
 98.1363 -		}
 98.1364 -		// scan for a free number
 98.1365 -		for ( ; lastNumber <= 9999 ; lastNumber++ ) {
 98.1366 -			R_ScreenshotFilename( lastNumber, checkname );
 98.1367 -
 98.1368 -      if (!ri.FS_FileExists( checkname ))
 98.1369 -      {
 98.1370 -        break; // file doesn't exist
 98.1371 -      }
 98.1372 -		}
 98.1373 -
 98.1374 -		if ( lastNumber >= 9999 ) {
 98.1375 -			ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n"); 
 98.1376 -			return;
 98.1377 - 		}
 98.1378 -
 98.1379 -		lastNumber++;
 98.1380 -	}
 98.1381 -
 98.1382 -	R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qfalse );
 98.1383 -
 98.1384 -	if ( !silent ) {
 98.1385 -		ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
 98.1386 -	}
 98.1387 -} 
 98.1388 -
 98.1389 -void R_ScreenShotJPEG_f (void) {
 98.1390 -	char		checkname[MAX_OSPATH];
 98.1391 -	static	int	lastNumber = -1;
 98.1392 -	qboolean	silent;
 98.1393 -
 98.1394 -	if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
 98.1395 -		R_LevelShot();
 98.1396 +	Q_strncpyz(fileName, Cmd_Argv(1), sizeof(fileName));
 98.1397 +	Com_DefaultExtension(fileName, sizeof(fileName), ".mtr");
 98.1398 +	Com_Printf("Writing %s.\n", fileName);
 98.1399 +	f = FS_FOpenFileWrite(fileName);
 98.1400 +	if(!f)
 98.1401 +	{
 98.1402 +		Com_Printf("Couldn't write %s.\n", fileName);
 98.1403  		return;
 98.1404  	}
 98.1405  
 98.1406 -	if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) {
 98.1407 -		silent = qtrue;
 98.1408 -	} else {
 98.1409 -		silent = qfalse;
 98.1410 -	}
 98.1411 +	FS_Printf(f, "// generated by XreaL\n\n");
 98.1412  
 98.1413 -	if ( ri.Cmd_Argc() == 2 && !silent ) {
 98.1414 -		// explicit filename
 98.1415 -		Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.jpg", ri.Cmd_Argv( 1 ) );
 98.1416 -	} else {
 98.1417 -		// scan for a free filename
 98.1418 +	dirnames = FS_ListFiles(path, extension, &ndirs);
 98.1419  
 98.1420 -		// if we have saved a previous screenshot, don't scan
 98.1421 -		// again, because recording demo avis can involve
 98.1422 -		// thousands of shots
 98.1423 -		if ( lastNumber == -1 ) {
 98.1424 -			lastNumber = 0;
 98.1425 -		}
 98.1426 -		// scan for a free number
 98.1427 -		for ( ; lastNumber <= 9999 ; lastNumber++ ) {
 98.1428 -			R_ScreenshotFilenameJPEG( lastNumber, checkname );
 98.1429 +	qsort(dirnames, ndirs, sizeof(char *), MaterialNameCompare);
 98.1430  
 98.1431 -      if (!ri.FS_FileExists( checkname ))
 98.1432 -      {
 98.1433 -        break; // file doesn't exist
 98.1434 -      }
 98.1435 +	for(i = 0; i < ndirs; i++)
 98.1436 +	{
 98.1437 +		// clean name
 98.1438 +		Q_strncpyz(fileName, dirnames[i], sizeof(fileName));
 98.1439 +		Q_strncpyz(cleanName, dirnames[i], sizeof(cleanName));
 98.1440 +
 98.1441 +		Q_strreplace(cleanName, sizeof(cleanName), "MaPZone[", "");
 98.1442 +		Q_strreplace(cleanName, sizeof(cleanName), "]", "");
 98.1443 +		Q_strreplace(cleanName, sizeof(cleanName), "&", "_");
 98.1444 +
 98.1445 +		if(strcmp(fileName, cleanName))
 98.1446 +		{
 98.1447 +			Com_sprintf(fileName2, sizeof(fileName2), "%s/%s", path, fileName);
 98.1448 +			Com_sprintf(cleanName2, sizeof(cleanName2), "%s/%s", path, cleanName);
 98.1449 +
 98.1450 +			Com_Printf("renaming '%s' into '%s'\n", fileName2, cleanName2);
 98.1451 +			FS_Rename(fileName2, cleanName2);
 98.1452  		}
 98.1453  
 98.1454 -		if ( lastNumber == 10000 ) {
 98.1455 -			ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n"); 
 98.1456 -			return;
 98.1457 - 		}
 98.1458 +		Com_StripExtension(cleanName, cleanName, sizeof(cleanName));
 98.1459 +		if(!Q_stristr(cleanName, "_nm") && !Q_stristr(cleanName, "blend"))
 98.1460 +		{
 98.1461 +			Q_strncpyz(baseName, cleanName, sizeof(baseName));
 98.1462 +			Q_strreplace(baseName, sizeof(baseName), "_diffuse", "");
 98.1463  
 98.1464 -		lastNumber++;
 98.1465 +			FS_Printf(f, "%s/%s\n", path, baseName);
 98.1466 +			FS_Printf(f, "{\n");
 98.1467 +			FS_Printf(f, "\t qer_editorImage\t %s/%s.%s\n", path, cleanName, extension);
 98.1468 +			FS_Printf(f, "\n");
 98.1469 +			FS_Printf(f, "\t parallax\n");
 98.1470 +			FS_Printf(f, "\n");
 98.1471 +			FS_Printf(f, "\t diffuseMap\t\t %s/%s.%s\n", path, baseName, extension);
 98.1472 +
 98.1473 +			Com_sprintf(fileName, sizeof(fileName), "%s/%s_nm.%s", path, baseName, extension);
 98.1474 +			if(ri.FS_ReadFile(fileName, NULL) > 0)
 98.1475 +			{
 98.1476 +				FS_Printf(f, "\t normalMap\t\t %s/%s_nm.%s\n", path, baseName, extension);
 98.1477 +			}
 98.1478 +
 98.1479 +			Q_strncpyz(baseName2, baseName, sizeof(baseName2));
 98.1480 +			len = strlen(baseName);
 98.1481 +			baseName2[len -1] = '\0';
 98.1482 +
 98.1483 +			Com_sprintf(fileName, sizeof(fileName), "%s/speculars/%s_s.%s", path, baseName2, extension);
 98.1484 +			if(ri.FS_ReadFile(fileName, NULL) > 0)
 98.1485 +			{
 98.1486 +				FS_Printf(f, "\t specularMap\t %s/speculars/%s_s.%s\n", path, baseName2, extension);
 98.1487 +			}
 98.1488 +
 98.1489 +			Com_sprintf(fileName, sizeof(fileName), "%s/%s.blend.%s", path, baseName, extension);
 98.1490 +			if(ri.FS_ReadFile(fileName, NULL) > 0)
 98.1491 +			{
 98.1492 +				FS_Printf(f, "\t glowMap\t\t %s/%s.blend.%s\n", path, baseName, extension);
 98.1493 +			}
 98.1494 +
 98.1495 +			FS_Printf(f, "}\n\n");
 98.1496 +		}
 98.1497  	}
 98.1498 +	FS_FreeFileList(dirnames);
 98.1499  
 98.1500 -	R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qtrue );
 98.1501 -
 98.1502 -	if ( !silent ) {
 98.1503 -		ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
 98.1504 -	}
 98.1505 -} 
 98.1506 +	FS_FCloseFile(f);
 98.1507 +}
 98.1508  
 98.1509  //============================================================================
 98.1510  
 98.1511 @@ -720,42 +1045,40 @@
 98.1512  RB_TakeVideoFrameCmd
 98.1513  ==================
 98.1514  */
 98.1515 -const void *RB_TakeVideoFrameCmd( const void *data )
 98.1516 +const void     *RB_TakeVideoFrameCmd(const void *data)
 98.1517  {
 98.1518 -	const videoFrameCommand_t	*cmd;
 98.1519 -	int												frameSize;
 98.1520 -	int												i;
 98.1521 -	
 98.1522 +	const videoFrameCommand_t *cmd;
 98.1523 +	int             frameSize;
 98.1524 +	int             i;
 98.1525 +
 98.1526  	cmd = (const videoFrameCommand_t *)data;
 98.1527 -	
 98.1528 -	qglReadPixels( 0, 0, cmd->width, cmd->height, GL_RGBA,
 98.1529 -			GL_UNSIGNED_BYTE, cmd->captureBuffer );
 98.1530 +
 98.1531 +	qglReadPixels(0, 0, cmd->width, cmd->height, GL_RGBA, GL_UNSIGNED_BYTE, cmd->captureBuffer);
 98.1532  
 98.1533  	// gamma correct
 98.1534 -	if( glConfig.deviceSupportsGamma )
 98.1535 -		R_GammaCorrect( cmd->captureBuffer, cmd->width * cmd->height * 4 );
 98.1536 +	if((tr.overbrightBits > 0) && glConfig.deviceSupportsGamma)
 98.1537 +		R_GammaCorrect(cmd->captureBuffer, cmd->width * cmd->height * 4);
 98.1538  
 98.1539 -	if( cmd->motionJpeg )
 98.1540 +	if(cmd->motionJpeg)
 98.1541  	{
 98.1542 -		frameSize = SaveJPGToBuffer( cmd->encodeBuffer, 90,
 98.1543 -				cmd->width, cmd->height, cmd->captureBuffer );
 98.1544 -		ri.CL_WriteAVIVideoFrame( cmd->encodeBuffer, frameSize );
 98.1545 +		frameSize = SaveJPGToBuffer(cmd->encodeBuffer, 90, cmd->width, cmd->height, cmd->captureBuffer);
 98.1546 +		ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, frameSize);
 98.1547  	}
 98.1548  	else
 98.1549  	{
 98.1550  		frameSize = cmd->width * cmd->height;
 98.1551  
 98.1552 -		for( i = 0; i < frameSize; i++)    // Pack to 24bpp and swap R and B
 98.1553 +		for(i = 0; i < frameSize; i++)	// Pack to 24bpp and swap R and B
 98.1554  		{
 98.1555 -			cmd->encodeBuffer[ i*3 ]     = cmd->captureBuffer[ i*4 + 2 ];
 98.1556 -			cmd->encodeBuffer[ i*3 + 1 ] = cmd->captureBuffer[ i*4 + 1 ];
 98.1557 -			cmd->encodeBuffer[ i*3 + 2 ] = cmd->captureBuffer[ i*4 ];
 98.1558 +			cmd->encodeBuffer[i * 3] = cmd->captureBuffer[i * 4 + 2];
 98.1559 +			cmd->encodeBuffer[i * 3 + 1] = cmd->captureBuffer[i * 4 + 1];
 98.1560 +			cmd->encodeBuffer[i * 3 + 2] = cmd->captureBuffer[i * 4];
 98.1561  		}
 98.1562  
 98.1563 -		ri.CL_WriteAVIVideoFrame( cmd->encodeBuffer, frameSize * 3 );
 98.1564 +		ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, frameSize * 3);
 98.1565  	}
 98.1566  
 98.1567 -	return (const void *)(cmd + 1);	
 98.1568 +	return (const void *)(cmd + 1);
 98.1569  }
 98.1570  
 98.1571  //============================================================================
 98.1572 @@ -763,141 +1086,227 @@
 98.1573  /*
 98.1574  ** GL_SetDefaultState
 98.1575  */
 98.1576 -void GL_SetDefaultState( void )
 98.1577 +void GL_SetDefaultState(void)
 98.1578  {
 98.1579 -	qglClearDepth( 1.0f );
 98.1580 +	int             i;
 98.1581  
 98.1582 -	qglCullFace(GL_FRONT);
 98.1583 +	GLimp_LogComment("--- GL_SetDefaultState ---\n");
 98.1584  
 98.1585 -	qglColor4f (1,1,1,1);
 98.1586 +	GL_ClearDepth(1.0f);
 98.1587  
 98.1588 -	// initialize downstream texture unit if we're running
 98.1589 -	// in a multitexture environment
 98.1590 -	if ( qglActiveTextureARB ) {
 98.1591 -		GL_SelectTexture( 1 );
 98.1592 -		GL_TextureMode( r_textureMode->string );
 98.1593 -		GL_TexEnv( GL_MODULATE );
 98.1594 -		qglDisable( GL_TEXTURE_2D );
 98.1595 -		GL_SelectTexture( 0 );
 98.1596 +	if(glConfig.stencilBits >= 4)
 98.1597 +	{
 98.1598 +		GL_ClearStencil(128);
 98.1599  	}
 98.1600  
 98.1601 -	qglEnable(GL_TEXTURE_2D);
 98.1602 -	GL_TextureMode( r_textureMode->string );
 98.1603 -	GL_TexEnv( GL_MODULATE );
 98.1604 +	GL_FrontFace(GL_CCW);
 98.1605 +	GL_CullFace(GL_FRONT);
 98.1606  
 98.1607 -	qglShadeModel( GL_SMOOTH );
 98.1608 -	qglDepthFunc( GL_LEQUAL );
 98.1609 +	qglVertexAttrib4fARB(ATTR_INDEX_COLOR, 1, 1, 1, 1);
 98.1610 +
 98.1611 +	// initialize downstream texture units if we're running
 98.1612 +	// in a multitexture environment
 98.1613 +	if(qglActiveTextureARB)
 98.1614 +	{
 98.1615 +		for(i = glConfig.maxTextureUnits - 1; i >= 0; i--)
 98.1616 +		{
 98.1617 +			GL_SelectTexture(i);
 98.1618 +			GL_TextureMode(r_textureMode->string);
 98.1619 +
 98.1620 +			if(i != 0)
 98.1621 +				qglDisable(GL_TEXTURE_2D);
 98.1622 +			else
 98.1623 +				qglEnable(GL_TEXTURE_2D);
 98.1624 +		}
 98.1625 +	}
 98.1626 +
 98.1627 +	GL_DepthFunc(GL_LEQUAL);
 98.1628 +
 98.1629 +	// make sure our GL state vector is set correctly
 98.1630 +	glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE;
 98.1631 +	glState.vertexAttribsState = 0;
 98.1632 +	glState.vertexAttribPointersSet = 0;
 98.1633 +
 98.1634 +	glState.currentProgram = 0;
 98.1635 +	qglUseProgramObjectARB(0);
 98.1636 +
 98.1637 +	qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
 98.1638 +	qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
 98.1639 +	glState.currentVBO = NULL;
 98.1640 +	glState.currentIBO = NULL;
 98.1641  
 98.1642  	// the vertex array is always enabled, but the color and texture
 98.1643  	// arrays are enabled and disabled around the compiled vertex array call
 98.1644 -	qglEnableClientState (GL_VERTEX_ARRAY);
 98.1645 +	qglEnableVertexAttribArrayARB(ATTR_INDEX_POSITION);
 98.1646  
 98.1647 -	//
 98.1648 -	// make sure our GL state vector is set correctly
 98.1649 -	//
 98.1650 -	glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE;
 98.1651 +	/*
 98.1652 +	   OpenGL 3.0 spec: E.1. PROFILES AND DEPRECATED FEATURES OF OPENGL 3.0 405
 98.1653 +	   Calling VertexAttribPointer when no buffer object or no
 98.1654 +	   vertex array object is bound will generate an INVALID OPERATION error,
 98.1655 +	   as will calling any array drawing command when no vertex array object is
 98.1656 +	   bound.
 98.1657 +	 */
 98.1658  
 98.1659 -	qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
 98.1660 -	qglDepthMask( GL_TRUE );
 98.1661 -	qglDisable( GL_DEPTH_TEST );
 98.1662 -	qglEnable( GL_SCISSOR_TEST );
 98.1663 -	qglDisable( GL_CULL_FACE );
 98.1664 -	qglDisable( GL_BLEND );
 98.1665 +	if(glConfig.framebufferObjectAvailable)
 98.1666 +	{
 98.1667 +		qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
 98.1668 +		qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
 98.1669 +		glState.currentFBO = NULL;
 98.1670 +	}
 98.1671 +
 98.1672 +
 98.1673 +	/*
 98.1674 +	   if(glConfig.drawBuffersAvailable && glConfig.maxDrawBuffers >= 4)
 98.1675 +	   {
 98.1676 +	   // enable all attachments as draw buffers
 98.1677 +	   GLenum drawbuffers[] = {GL_DRAW_BUFFER0_ARB,
 98.1678 +	   GL_DRAW_BUFFER1_ARB,
 98.1679 +	   GL_DRAW_BUFFER2_ARB,
 98.1680 +	   GL_DRAW_BUFFER3_ARB};
 98.1681 +
 98.1682 +	   qglDrawBuffersARB(4, drawbuffers);
 98.1683 +	   }
 98.1684 +	 */
 98.1685 +
 98.1686 +	GL_PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 98.1687 +	qglDepthMask(GL_TRUE);
 98.1688 +	qglDisable(GL_DEPTH_TEST);
 98.1689 +	qglEnable(GL_SCISSOR_TEST);
 98.1690 +	qglDisable(GL_CULL_FACE);
 98.1691 +	qglDisable(GL_BLEND);
 98.1692 +
 98.1693 +	glState.stackIndex = 0;
 98.1694 +	for(i = 0; i < MAX_GLSTACK; i++)
 98.1695 +	{
 98.1696 +		MatrixIdentity(glState.modelViewMatrix[i]);
 98.1697 +		MatrixIdentity(glState.projectionMatrix[i]);
 98.1698 +		MatrixIdentity(glState.modelViewProjectionMatrix[i]);
 98.1699 +	}
 98.1700  }
 98.1701  
 98.1702  
 98.1703 +
 98.1704  /*
 98.1705  ================
 98.1706  GfxInfo_f
 98.1707  ================
 98.1708  */
 98.1709 -void GfxInfo_f( void ) 
 98.1710 +void GfxInfo_f(void)
 98.1711  {
 98.1712 -	const char *enablestrings[] =
 98.1713 -	{
 98.1714 +	const char     *enablestrings[] = {
 98.1715  		"disabled",
 98.1716  		"enabled"
 98.1717  	};
 98.1718 -	const char *fsstrings[] =
 98.1719 -	{
 98.1720 +	const char     *fsstrings[] = {
 98.1721  		"windowed",
 98.1722  		"fullscreen"
 98.1723  	};
 98.1724  
 98.1725 -	ri.Printf( PRINT_ALL, "\nGL_VENDOR: %s\n", glConfig.vendor_string );
 98.1726 -	ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glConfig.renderer_string );
 98.1727 -	ri.Printf( PRINT_ALL, "GL_VERSION: %s\n", glConfig.version_string );
 98.1728 -	ri.Printf( PRINT_ALL, "GL_EXTENSIONS: %s\n", glConfig.extensions_string );
 98.1729 -	ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize );
 98.1730 -	ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_UNITS_ARB: %d\n", glConfig.numTextureUnits );
 98.1731 -	ri.Printf( PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits );
 98.1732 -	ri.Printf( PRINT_ALL, "MODE: %d x %d %s hz:", glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen->integer == 1] );
 98.1733 -	if ( glConfig.displayFrequency )
 98.1734 +	ri.Printf(PRINT_ALL, "\nGL_VENDOR: %s\n", glConfig.vendor_string);
 98.1735 +	ri.Printf(PRINT_ALL, "GL_RENDERER: %s\n", glConfig.renderer_string);
 98.1736 +	ri.Printf(PRINT_ALL, "GL_VERSION: %s\n", glConfig.version_string);
 98.1737 +	ri.Printf(PRINT_ALL, "GL_EXTENSIONS: %s\n", glConfig.extensions_string);
 98.1738 +	ri.Printf(PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize);
 98.1739 +	ri.Printf(PRINT_ALL, "GL_MAX_TEXTURE_UNITS_ARB: %d\n", glConfig.maxTextureUnits);
 98.1740 +
 98.1741 +	/*
 98.1742 +	   if(glConfig.fragmentProgramAvailable)
 98.1743 +	   {
 98.1744 +	   ri.Printf(PRINT_ALL, "GL_MAX_TEXTURE_IMAGE_UNITS_ARB: %d\n", glConfig.maxTextureImageUnits);
 98.1745 +	   }
 98.1746 +	 */
 98.1747 +
 98.1748 +	ri.Printf(PRINT_ALL, "GL_SHADING_LANGUAGE_VERSION_ARB: %s\n", glConfig.shadingLanguageVersion);
 98.1749 +
 98.1750 +	ri.Printf(PRINT_ALL, "GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB %d\n", glConfig.maxVertexUniforms);
 98.1751 +	ri.Printf(PRINT_ALL, "GL_MAX_VARYING_FLOATS_ARB %d\n", glConfig.maxVaryingFloats);
 98.1752 +	ri.Printf(PRINT_ALL, "GL_MAX_VERTEX_ATTRIBS_ARB %d\n", glConfig.maxVertexAttribs);
 98.1753 +
 98.1754 +	if(glConfig.occlusionQueryAvailable)
 98.1755  	{
 98.1756 -		ri.Printf( PRINT_ALL, "%d\n", glConfig.displayFrequency );
 98.1757 +		ri.Printf(PRINT_ALL, "%d occlusion query bits\n", glConfig.occlusionQueryBits);
 98.1758 +	}
 98.1759 +
 98.1760 +	if(glConfig.drawBuffersAvailable)
 98.1761 +	{
 98.1762 +		ri.Printf(PRINT_ALL, "GL_MAX_DRAW_BUFFERS_ARB: %d\n", glConfig.maxDrawBuffers);
 98.1763 +	}
 98.1764 +
 98.1765 +	if(glConfig.textureAnisotropyAvailable)
 98.1766 +	{
 98.1767 +		ri.Printf(PRINT_ALL, "GL_TEXTURE_MAX_ANISOTROPY_EXT: %f\n", glConfig.maxTextureAnisotropy);
 98.1768 +	}
 98.1769 +
 98.1770 +	if(glConfig.framebufferObjectAvailable)
 98.1771 +	{
 98.1772 +		ri.Printf(PRINT_ALL, "GL_MAX_RENDERBUFFER_SIZE_EXT: %d\n", glConfig.maxRenderbufferSize);
 98.1773 +		ri.Printf(PRINT_ALL, "GL_MAX_COLOR_ATTACHMENTS_EXT: %d\n", glConfig.maxColorAttachments);
 98.1774 +	}
 98.1775 +
 98.1776 +	ri.Printf(PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits,
 98.1777 +			  glConfig.depthBits, glConfig.stencilBits);
 98.1778 +	ri.Printf(PRINT_ALL, "MODE: %d, %d x %d %s hz:", r_mode->integer, glConfig.vidWidth, glConfig.vidHeight,
 98.1779 +			  fsstrings[r_fullscreen->integer == 1]);
 98.1780 +
 98.1781 +	if(glConfig.displayFrequency)
 98.1782 +	{
 98.1783 +		ri.Printf(PRINT_ALL, "%d\n", glConfig.displayFrequency);
 98.1784  	}
 98.1785  	else
 98.1786  	{
 98.1787 -		ri.Printf( PRINT_ALL, "N/A\n" );
 98.1788 +		ri.Printf(PRINT_ALL, "N/A\n");
 98.1789  	}
 98.1790 -	if ( glConfig.deviceSupportsGamma )
 98.1791 +
 98.1792 +	if(glConfig.deviceSupportsGamma)
 98.1793  	{
 98.1794 -		ri.Printf( PRINT_ALL, "GAMMA: hardware w/ %d overbright bits\n", tr.overbrightBits );
 98.1795 +		ri.Printf(PRINT_ALL, "GAMMA: hardware w/ %d overbright bits\n", tr.overbrightBits);
 98.1796  	}
 98.1797  	else
 98.1798  	{
 98.1799 -		ri.Printf( PRINT_ALL, "GAMMA: software w/ %d overbright bits\n", tr.overbrightBits );
 98.1800 +		ri.Printf(PRINT_ALL, "GAMMA: software w/ %d overbright bits\n", tr.overbrightBits);
 98.1801  	}
 98.1802  
 98.1803 -	// rendering primitives
 98.1804 +	ri.Printf(PRINT_ALL, "texturemode: %s\n", r_textureMode->string);
 98.1805 +	ri.Printf(PRINT_ALL, "picmip: %d\n", r_picmip->integer);
 98.1806 +
 98.1807 +	if(glConfig.driverType == GLDRV_OPENGL3)
 98.1808  	{
 98.1809 -		int		primitives;
 98.1810 -
 98.1811 -		// default is to use triangles if compiled vertex arrays are present
 98.1812 -		ri.Printf( PRINT_ALL, "rendering primitives: " );
 98.1813 -		primitives = r_primitives->integer;
 98.1814 -		if ( primitives == 0 ) {
 98.1815 -			if ( qglLockArraysEXT ) {
 98.1816 -				primitives = 2;
 98.1817 -			} else {
 98.1818 -				primitives = 1;
 98.1819 -			}
 98.1820 -		}
 98.1821 -		if ( primitives == -1 ) {
 98.1822 -			ri.Printf( PRINT_ALL, "none\n" );
 98.1823 -		} else if ( primitives == 2 ) {
 98.1824 -			ri.Printf( PRINT_ALL, "single glDrawElements\n" );
 98.1825 -		} else if ( primitives == 1 ) {
 98.1826 -			ri.Printf( PRINT_ALL, "multiple glArrayElement\n" );
 98.1827 -		} else if ( primitives == 3 ) {
 98.1828 -			ri.Printf( PRINT_ALL, "multiple glColor4ubv + glTexCoord2fv + glVertex3fv\n" );
 98.1829 -		}
 98.1830 +		ri.Printf(PRINT_ALL, "Using OpenGL 3.1 context\n");
 98.1831  	}
 98.1832  
 98.1833 -	ri.Printf( PRINT_ALL, "texturemode: %s\n", r_textureMode->string );
 98.1834 -	ri.Printf( PRINT_ALL, "picmip: %d\n", r_picmip->integer );
 98.1835 -	ri.Printf( PRINT_ALL, "texture bits: %d\n", r_texturebits->integer );
 98.1836 -	ri.Printf( PRINT_ALL, "multitexture: %s\n", enablestrings[qglActiveTextureARB != 0] );
 98.1837 -	ri.Printf( PRINT_ALL, "compiled vertex arrays: %s\n", enablestrings[qglLockArraysEXT != 0 ] );
 98.1838 -	ri.Printf( PRINT_ALL, "texenv add: %s\n", enablestrings[glConfig.textureEnvAddAvailable != 0] );
 98.1839 -	ri.Printf( PRINT_ALL, "compressed textures: %s\n", enablestrings[glConfig.textureCompression!=TC_NONE] );
 98.1840 -	if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 )
 98.1841 +	if(glConfig.hardwareType == GLHW_ATI)
 98.1842  	{
 98.1843 -		ri.Printf( PRINT_ALL, "HACK: using vertex lightmap approximation\n" );
 98.1844 +		ri.Printf(PRINT_ALL, "HACK: ATI approximations\n");
 98.1845  	}
 98.1846 -	if ( glConfig.hardwareType == GLHW_RAGEPRO )
 98.1847 +
 98.1848 +	if(glConfig.textureCompression != TC_NONE)
 98.1849  	{
 98.1850 -		ri.Printf( PRINT_ALL, "HACK: ragePro approximations\n" );
 98.1851 +		ri.Printf(PRINT_ALL, "Using S3TC (DXTC) texture compression\n");
 98.1852  	}
 98.1853 -	if ( glConfig.hardwareType == GLHW_RIVA128 )
 98.1854 +
 98.1855 +	if(glConfig.hardwareType == GLHW_ATI_DX10)
 98.1856  	{
 98.1857 -		ri.Printf( PRINT_ALL, "HACK: riva128 approximations\n" );
 98.1858 +		ri.Printf(PRINT_ALL, "Using ATI DirectX 10 hardware features\n");
 98.1859  	}
 98.1860 -	if ( glConfig.smpActive ) {
 98.1861 -		ri.Printf( PRINT_ALL, "Using dual processor acceleration\n" );
 98.1862 +
 98.1863 +	if(glConfig.hardwareType == GLHW_NV_DX10)
 98.1864 +	{
 98.1865 +		ri.Printf(PRINT_ALL, "Using NVIDIA DirectX 10 hardware features\n");
 98.1866  	}
 98.1867 -	if ( r_finish->integer ) {
 98.1868 -		ri.Printf( PRINT_ALL, "Forcing glFinish\n" );
 98.1869 +
 98.1870 +	if(glConfig.vboVertexSkinningAvailable)
 98.1871 +	{
 98.1872 +		ri.Printf(PRINT_ALL, "Using GPU vertex skinning with max %i bones in a single pass\n", glConfig.maxVertexSkinningBones);
 98.1873 +	}
 98.1874 +
 98.1875 +	if(glConfig.smpActive)
 98.1876 +	{
 98.1877 +		ri.Printf(PRINT_ALL, "Using dual processor acceleration\n");
 98.1878 +	}
 98.1879 +
 98.1880 +	if(r_finish->integer)
 98.1881 +	{
 98.1882 +		ri.Printf(PRINT_ALL, "Forcing glFinish\n");
 98.1883  	}
 98.1884  }
 98.1885  
 98.1886 @@ -906,169 +1315,280 @@
 98.1887  R_Register
 98.1888  ===============
 98.1889  */
 98.1890 -void R_Register( void ) 
 98.1891 +void R_Register(void)
 98.1892  {
 98.1893 -	//
 98.1894  	// latched and archived variables
 98.1895 -	//
 98.1896 -	r_allowExtensions = ri.Cvar_Get( "r_allowExtensions", "1", CVAR_ARCHIVE | CVAR_LATCH );
 98.1897 -	r_ext_compressed_textures = ri.Cvar_Get( "r_ext_compressed_textures", "0", CVAR_ARCHIVE | CVAR_LATCH );
 98.1898 -	r_ext_multitexture = ri.Cvar_Get( "r_ext_multitexture", "1", CVAR_ARCHIVE | CVAR_LATCH );
 98.1899 -	r_ext_compiled_vertex_array = ri.Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE | CVAR_LATCH);
 98.1900 -	r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "1", CVAR_ARCHIVE | CVAR_LATCH);
 98.1901 +	r_ext_texture_compression = ri.Cvar_Get("r_ext_texture_compression", "1", CVAR_ARCHIVE | CVAR_LATCH);
 98.1902 +	r_ext_occlusion_query = ri.Cvar_Get("r_ext_occlusion_query", "1", CVAR_CHEAT | CVAR_LATCH);
 98.1903 +	r_ext_texture_non_power_of_two = ri.Cvar_Get("r_ext_texture_non_power_of_two", "1", CVAR_CHEAT | CVAR_LATCH);
 98.1904 +	r_ext_draw_buffers = ri.Cvar_Get("r_ext_draw_buffers", "1", CVAR_CHEAT | CVAR_LATCH);
 98.1905 +	r_ext_vertex_array_object = ri.Cvar_Get("r_ext_vertex_array_object", "1", CVAR_CHEAT | CVAR_LATCH);
 98.1906 +	r_ext_half_float_pixel = ri.Cvar_Get("r_ext_half_float_pixel", "1", CVAR_CHEAT | CVAR_LATCH);
 98.1907 +	r_ext_texture_float = ri.Cvar_Get("r_ext_texture_float", "1", CVAR_CHEAT | CVAR_LATCH);
 98.1908 +	r_ext_stencil_wrap = ri.Cvar_Get("r_ext_stencil_wrap", "1", CVAR_CHEAT | CVAR_LATCH);
 98.1909 +	r_ext_texture_filter_anisotropic = ri.Cvar_Get("r_ext_texture_filter_anisotropic", "4", CVAR_ARCHIVE | CVAR_LATCH);
 98.1910 +	r_ext_stencil_two_side = ri.Cvar_Get("r_ext_stencil_two_side", "1", CVAR_CHEAT | CVAR_LATCH);
 98.1911 +	r_ext_separate_stencil = ri.Cvar_Get("r_ext_separate_stencil", "1", CVAR_CHEAT | CVAR_LATCH);
 98.1912 +	r_ext_depth_bounds_test = ri.Cvar_Get("r_ext_depth_bounds_test", "1", CVAR_CHEAT | CVAR_LATCH);
 98.1913 +	r_ext_framebuffer_object = ri.Cvar_Get("r_ext_framebuffer_object", "1", CVAR_ARCHIVE | CVAR_LATCH);
 98.1914 +	r_ext_packed_depth_stencil = ri.Cvar_Get("r_ext_packed_depth_stencil", "0", CVAR_CHEAT | CVAR_LATCH);
 98.1915 +	r_ext_framebuffer_blit = ri.Cvar_Get("r_ext_framebuffer_blit", "1", CVAR_CHEAT | CVAR_LATCH);
 98.1916 +	r_extx_framebuffer_mixed_formats = ri.Cvar_Get("r_extx_framebuffer_mixed_formats", "1", CVAR_ARCHIVE | CVAR_LATCH);
 98.1917 +	r_ext_generate_mipmap = ri.Cvar_Get("r_ext_generate_mipmap", "1", CVAR_CHEAT | CVAR_LATCH);
 98.1918  
 98.1919 -	r_picmip = ri.Cvar_Get ("r_picmip", GENERIC_HW_R_PICMIP_DEFAULT,
 98.1920 -			CVAR_ARCHIVE | CVAR_LATCH );
 98.1921 -	r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic",
 98.1922 -			"0", CVAR_ARCHIVE | CVAR_LATCH );
 98.1923 -	r_ext_max_anisotropy = ri.Cvar_Get( "r_ext_max_anisotropy", "2", CVAR_ARCHIVE | CVAR_LATCH );
 98.1924 +	r_collapseStages = ri.Cvar_Get("r_collapseStages", "1", CVAR_LATCH | CVAR_CHEAT);
 98.1925 +	r_picmip = ri.Cvar_Get("r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH);
 98.1926 +	ri.Cvar_CheckRange(r_picmip, 0, 3, qtrue);
 98.1927 +	r_roundImagesDown = ri.Cvar_Get("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH);
 98.1928 +	r_colorMipLevels = ri.Cvar_Get("r_colorMipLevels", "0", CVAR_LATCH);
 98.1929 +	r_colorbits = ri.Cvar_Get("r_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1930 +	r_stereo = ri.Cvar_Get("r_stereo", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1931 +	r_stencilbits = ri.Cvar_Get("r_stencilbits", "8", CVAR_ARCHIVE | CVAR_LATCH);
 98.1932 +	r_depthbits = ri.Cvar_Get("r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1933 +	r_ignorehwgamma = ri.Cvar_Get("r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1934 +	r_mode = ri.Cvar_Get("r_mode", "3", CVAR_ARCHIVE | CVAR_LATCH);
 98.1935 +	r_fullscreen = ri.Cvar_Get("r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH);
 98.1936 +	r_customwidth = ri.Cvar_Get("r_customwidth", "1600", CVAR_ARCHIVE | CVAR_LATCH);
 98.1937 +	r_customheight = ri.Cvar_Get("r_customheight", "1024", CVAR_ARCHIVE | CVAR_LATCH);
 98.1938 +	r_customaspect = ri.Cvar_Get("r_customaspect", "1", CVAR_ARCHIVE | CVAR_LATCH);
 98.1939 +	r_simpleMipMaps = ri.Cvar_Get("r_simpleMipMaps", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1940 +	r_uiFullScreen = ri.Cvar_Get("r_uifullscreen", "0", 0);
 98.1941 +	r_subdivisions = ri.Cvar_Get("r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH);
 98.1942 +	r_deferredShading = ri.Cvar_Get("r_deferredShading", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1943 +	r_parallaxMapping = ri.Cvar_Get("r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1944 +	r_dynamicLightsCastShadows = ri.Cvar_Get("r_dynamicLightsCastShadows", "1", CVAR_ARCHIVE);
 98.1945 +	r_precomputedLighting = ri.Cvar_Get("r_precomputedLighting", "1", CVAR_CHEAT | CVAR_LATCH);
 98.1946 +	r_vertexLighting = ri.Cvar_Get("r_vertexLighting", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1947 +	r_heatHazeFix = ri.Cvar_Get("r_heatHazeFix", "0", CVAR_CHEAT | CVAR_LATCH);
 98.1948 +	r_atiFlippedImageFix = ri.Cvar_Get("r_atiFlippedImageFix", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1949 +	r_noMarksOnTrisurfs = ri.Cvar_Get("r_noMarksOnTrisurfs", "1", CVAR_CHEAT);
 98.1950  
 98.1951 -	r_roundImagesDown = ri.Cvar_Get ("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH );
 98.1952 -	r_colorMipLevels = ri.Cvar_Get ("r_colorMipLevels", "0", CVAR_LATCH );
 98.1953 -	ri.Cvar_CheckRange( r_picmip, 0, 16, qtrue );
 98.1954 -	r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH );
 98.1955 -	r_texturebits = ri.Cvar_Get( "r_texturebits", "0", CVAR_ARCHIVE | CVAR_LATCH );
 98.1956 -	r_colorbits = ri.Cvar_Get( "r_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
 98.1957 -	r_stencilbits = ri.Cvar_Get( "r_stencilbits", "8", CVAR_ARCHIVE | CVAR_LATCH );
 98.1958 -	r_depthbits = ri.Cvar_Get( "r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
 98.1959 -	r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "0", CVAR_ARCHIVE | CVAR_LATCH );
 98.1960 -	r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1961 -	r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE );
 98.1962 -	r_minimize = ri.Cvar_Get( "r_minimize", "0", 0 );
 98.1963 -	r_width = ri.Cvar_Get( "r_width", "0", CVAR_ARCHIVE | CVAR_LATCH );
 98.1964 -	r_height = ri.Cvar_Get( "r_height", "0", CVAR_ARCHIVE | CVAR_LATCH );
 98.1965 -	r_pixelAspect = ri.Cvar_Get( "r_pixelAspect", "1", CVAR_ARCHIVE | CVAR_LATCH );
 98.1966 +	r_forceFog = ri.Cvar_Get("r_forceFog", "0", CVAR_ARCHIVE /* | CVAR_LATCH */ );
 98.1967 +	ri.Cvar_CheckRange(r_forceFog, 0.0f, 1.0f, qfalse);
 98.1968 +	r_noFog = ri.Cvar_Get("r_noFog", "0", CVAR_ARCHIVE);
 98.1969  
 98.1970 -	// legacy variables
 98.1971 -	r_mode = ri.Cvar_Get( "r_mode", "-1", 0 );
 98.1972 -	ri.Cvar_CheckRange( r_mode, -1, 11, qtrue );
 98.1973 -	r_customwidth = ri.Cvar_Get( "r_customwidth", r_width->string, 0 );
 98.1974 -	r_customheight = ri.Cvar_Get( "r_customheight", r_height->string, 0 );
 98.1975 -	r_custompixelAspect = ri.Cvar_Get( "r_custompixelAspect", r_pixelAspect->string, 0 );
 98.1976 +	r_screenSpaceAmbientOcclusion = ri.Cvar_Get("r_screenSpaceAmbientOcclusion", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1977 +	ri.Cvar_CheckRange(r_screenSpaceAmbientOcclusion, 0, 2, qtrue);
 98.1978  
 98.1979 -	r_simpleMipMaps = ri.Cvar_Get( "r_simpleMipMaps", "1", CVAR_ARCHIVE | CVAR_LATCH );
 98.1980 -	r_vertexLight = ri.Cvar_Get( "r_vertexLight", "0", CVAR_ARCHIVE | CVAR_LATCH );
 98.1981 -	r_uiFullScreen = ri.Cvar_Get( "r_uifullscreen", "0", 0);
 98.1982 -	r_subdivisions = ri.Cvar_Get ("r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH);
 98.1983 -	r_smp = ri.Cvar_Get( "r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1984 -	r_stereoEnabled = ri.Cvar_Get( "r_stereoEnabled", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1985 -	r_ignoreFastPath = ri.Cvar_Get( "r_ignoreFastPath", "1", CVAR_ARCHIVE | CVAR_LATCH );
 98.1986 -	r_greyscale = ri.Cvar_Get("r_greyscale", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1987 -	r_specularLighting = ri.Cvar_Get("r_specularLighting", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1988 -	r_specularLightingExponent = ri.Cvar_Get("r_specularLightingExponent", "1", CVAR_ARCHIVE | CVAR_LATCH);
 98.1989 -	ri.Cvar_CheckRange( r_specularLightingExponent, 0.0f, 1, qfalse );
 98.1990 +	r_depthOfField = ri.Cvar_Get("r_depthOfField", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1991  
 98.1992 -	//
 98.1993 +	r_forceAmbient = ri.Cvar_Get("r_forceAmbient", "0.125", CVAR_ARCHIVE | CVAR_LATCH);
 98.1994 +	ri.Cvar_CheckRange(r_forceAmbient, 0.0f, 0.3f, qfalse);
 98.1995 +
 98.1996 +	r_smp = ri.Cvar_Get("r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.1997 +
 98.1998  	// temporary latched variables that can only change over a restart
 98.1999 -	//
 98.2000 -	r_displayRefresh = ri.Cvar_Get( "r_displayRefresh", "0", CVAR_LATCH );
 98.2001 -	ri.Cvar_CheckRange( r_displayRefresh, 0, 200, qtrue );
 98.2002 -	r_fullbright = ri.Cvar_Get ("r_fullbright", "0", CVAR_LATCH|CVAR_CHEAT );
 98.2003 -	r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "2", CVAR_LATCH );
 98.2004 -	r_intensity = ri.Cvar_Get ("r_intensity", "1", CVAR_LATCH );
 98.2005 -	r_singleShader = ri.Cvar_Get ("r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH );
 98.2006 +	r_displayRefresh = ri.Cvar_Get("r_displayRefresh", "0", CVAR_LATCH);
 98.2007 +	ri.Cvar_CheckRange(r_displayRefresh, 0, 200, qtrue);
 98.2008 +#if defined(COMPAT_Q3A)
 98.2009 +	r_overBrightBits = ri.Cvar_Get("r_overBrightBits", "1", CVAR_CHEAT | CVAR_LATCH);
 98.2010 +	r_mapOverBrightBits = ri.Cvar_Get("r_mapOverBrightBits", "2", CVAR_CHEAT | CVAR_LATCH);
 98.2011 +#else
 98.2012 +	r_overBrightBits = ri.Cvar_Get("r_overBrightBits", "0", CVAR_CHEAT | CVAR_LATCH);
 98.2013 +	r_mapOverBrightBits = ri.Cvar_Get("r_mapOverBrightBits", "0", CVAR_CHEAT | CVAR_LATCH);
 98.2014 +#endif
 98.2015 +	r_intensity = ri.Cvar_Get("r_intensity", "1", CVAR_LATCH);
 98.2016 +	r_singleShader = ri.Cvar_Get("r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH);
 98.2017 +	r_precacheLightIndexes = ri.Cvar_Get("r_precacheLightIndexes", "1", CVAR_CHEAT | CVAR_LATCH);
 98.2018 +	r_precacheShadowIndexes = ri.Cvar_Get("r_precacheShadowIndexes", "1", CVAR_CHEAT | CVAR_LATCH);
 98.2019 +	r_stitchCurves = ri.Cvar_Get("r_stitchCurves", "1", CVAR_CHEAT | CVAR_LATCH);
 98.2020 +	r_debugShadowMaps = ri.Cvar_Get("r_debugShadowMaps", "0", CVAR_CHEAT | CVAR_LATCH);
 98.2021 +	r_shadowMapLuminanceAlpha = ri.Cvar_Get("r_shadowMapLuminanceAlpha", "1", CVAR_ARCHIVE | CVAR_LATCH);
 98.2022 +	r_shadowMapLinearFilter = ri.Cvar_Get("r_shadowMapLinearFilter", "1", CVAR_CHEAT | CVAR_LATCH);
 98.2023 +	r_lightBleedReduction = ri.Cvar_Get("r_lightBleedReduction", "0", CVAR_CHEAT | CVAR_LATCH);
 98.2024 +	r_overDarkeningFactor = ri.Cvar_Get("r_overDarkeningFactor", "40.0", CVAR_CHEAT | CVAR_LATCH);
 98.2025 +	r_shadowMapDepthScale = ri.Cvar_Get("r_shadowMapDepthScale", "1.41", CVAR_CHEAT | CVAR_LATCH);
 98.2026  
 98.2027 -	//
 98.2028  	// archived variables that can change at any time
 98.2029 -	//
 98.2030 -	r_lodCurveError = ri.Cvar_Get( "r_lodCurveError", "250", CVAR_ARCHIVE|CVAR_CHEAT );
 98.2031 -	r_lodbias = ri.Cvar_Get( "r_lodbias", "0", CVAR_ARCHIVE );
 98.2032 -	r_flares = ri.Cvar_Get ("r_flares", "0", CVAR_ARCHIVE );
 98.2033 -	r_znear = ri.Cvar_Get( "r_znear", "1", CVAR_CHEAT );
 98.2034 -	ri.Cvar_CheckRange( r_znear, 0.001f, 200, qfalse );
 98.2035 -	r_zproj = ri.Cvar_Get( "r_zproj", "64", CVAR_ARCHIVE );
 98.2036 -	r_stereoSeparation = ri.Cvar_Get( "r_stereoSeparation", "64", CVAR_ARCHIVE );
 98.2037 -	r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE );
 98.2038 -	r_fastsky = ri.Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE );
 98.2039 -	r_inGameVideo = ri.Cvar_Get( "r_inGameVideo", "1", CVAR_ARCHIVE );
 98.2040 -	r_drawSun = ri.Cvar_Get( "r_drawSun", "0", CVAR_ARCHIVE );
 98.2041 -	r_dynamiclight = ri.Cvar_Get( "r_dynamiclight", "1", CVAR_ARCHIVE );
 98.2042 -	r_dlightBacks = ri.Cvar_Get( "r_dlightBacks", "1", CVAR_ARCHIVE );
 98.2043 -	r_finish = ri.Cvar_Get ("r_finish", "0", CVAR_ARCHIVE);
 98.2044 -	r_textureMode = ri.Cvar_Get( "r_textureMode",
 98.2045 -			GENERIC_HW_R_TEXTUREMODE_DEFAULT, CVAR_ARCHIVE );
 98.2046 -	r_swapInterval = ri.Cvar_Get( "r_swapInterval", "0",
 98.2047 -					CVAR_ARCHIVE | CVAR_LATCH );
 98.2048 -	r_gamma = ri.Cvar_Get( "r_gamma", "1.5", CVAR_ARCHIVE );
 98.2049 -	r_facePlaneCull = ri.Cvar_Get ("r_facePlaneCull", "1", CVAR_ARCHIVE );
 98.2050 +	r_lodbias = ri.Cvar_Get("r_lodbias", "0", CVAR_ARCHIVE);
 98.2051 +	r_flares = ri.Cvar_Get("r_flares", "0", CVAR_ARCHIVE);
 98.2052 +	r_znear = ri.Cvar_Get("r_znear", "4", CVAR_CHEAT);
 98.2053 +	r_zfar = ri.Cvar_Get("r_zfar", "0", CVAR_CHEAT);
 98.2054 +	r_ignoreGLErrors = ri.Cvar_Get("r_ignoreGLErrors", "1", CVAR_ARCHIVE);
 98.2055 +	r_fastsky = ri.Cvar_Get("r_fastsky", "0", CVAR_ARCHIVE);
 98.2056 +	r_inGameVideo = ri.Cvar_Get("r_inGameVideo", "1", CVAR_ARCHIVE);
 98.2057 +	r_drawSun = ri.Cvar_Get("r_drawSun", "0", CVAR_ARCHIVE);
 98.2058 +	r_finish = ri.Cvar_Get("r_finish", "0", CVAR_CHEAT);
 98.2059 +	r_textureMode = ri.Cvar_Get("r_textureMode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE);
 98.2060 +	r_swapInterval = ri.Cvar_Get("r_swapInterval", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.2061 +	r_gamma = ri.Cvar_Get("r_gamma", "1", CVAR_ARCHIVE);
 98.2062 +	r_facePlaneCull = ri.Cvar_Get("r_facePlaneCull", "1", CVAR_ARCHIVE);
 98.2063  
 98.2064 -	r_railWidth = ri.Cvar_Get( "r_railWidth", "16", CVAR_ARCHIVE );
 98.2065 -	r_railCoreWidth = ri.Cvar_Get( "r_railCoreWidth", "6", CVAR_ARCHIVE );
 98.2066 -	r_railSegmentLength = ri.Cvar_Get( "r_railSegmentLength", "32", CVAR_ARCHIVE );
 98.2067 +	r_railWidth = ri.Cvar_Get("r_railWidth", "96", CVAR_ARCHIVE);
 98.2068 +	r_railCoreWidth = ri.Cvar_Get("r_railCoreWidth", "16", CVAR_ARCHIVE);
 98.2069 +	r_railSegmentLength = ri.Cvar_Get("r_railSegmentLength", "32", CVAR_ARCHIVE);
 98.2070  
 98.2071 -	r_primitives = ri.Cvar_Get( "r_primitives", "0", CVAR_ARCHIVE );
 98.2072 +	r_ambientScale = ri.Cvar_Get("r_ambientScale", "0.6", CVAR_CHEAT);
 98.2073 +	r_lightScale = ri.Cvar_Get("r_lightScale", "3", CVAR_CHEAT);
 98.2074  
 98.2075 -	r_ambientScale = ri.Cvar_Get( "r_ambientScale", "0.6", CVAR_CHEAT );
 98.2076 -	r_directedScale = ri.Cvar_Get( "r_directedScale", "1", CVAR_CHEAT );
 98.2077 +	r_vboFaces = ri.Cvar_Get("r_vboFaces", "0", CVAR_CHEAT);
 98.2078 +	r_vboCurves = ri.Cvar_Get("r_vboCurves", "0", CVAR_CHEAT);
 98.2079 +	r_vboTriangles = ri.Cvar_Get("r_vboTriangles", "1", CVAR_CHEAT);
 98.2080 +	r_vboShadows = ri.Cvar_Get("r_vboShadows", "1", CVAR_CHEAT);
 98.2081 +	r_vboLighting = ri.Cvar_Get("r_vboLighting", "1", CVAR_CHEAT);
 98.2082 +	r_vboDynamicLighting = ri.Cvar_Get("r_vboDynamicLighting", "0", CVAR_CHEAT);
 98.2083 +	r_vboModels = ri.Cvar_Get("r_vboModels", "1", CVAR_CHEAT);
 98.2084 +	r_vboWorld = ri.Cvar_Get("r_vboWorld", "1", CVAR_CHEAT);
 98.2085 +	r_vboOptimizeVertices = ri.Cvar_Get("r_vboOptimizeVertices", "1", CVAR_CHEAT | CVAR_LATCH);
 98.2086 +	r_vboVertexSkinning = ri.Cvar_Get("r_vboVertexSkinning", "1", CVAR_CHEAT | CVAR_LATCH);
 98.2087 +	r_vboSmoothNormals = ri.Cvar_Get("r_vboSmoothNormals", "1", CVAR_ARCHIVE | CVAR_LATCH);
 98.2088  
 98.2089 -	r_anaglyphMode = ri.Cvar_Get("r_anaglyphMode", "0", CVAR_ARCHIVE);
 98.2090 +	r_hdrRendering = ri.Cvar_Get("r_hdrRendering", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.2091 +	r_hdrMinLuminance = ri.Cvar_Get("r_hdrMinLuminance", "0.18", CVAR_CHEAT);
 98.2092 +	r_hdrMaxLuminance = ri.Cvar_Get("r_hdrMaxLuminance", "3000", CVAR_CHEAT);
 98.2093 +	r_hdrKey = ri.Cvar_Get("r_hdrKey", "0.72", CVAR_CHEAT);
 98.2094 +	r_hdrContrastThreshold = ri.Cvar_Get("r_hdrContrastThreshold", "0.71", CVAR_CHEAT | CVAR_LATCH);
 98.2095 +	r_hdrContrastOffset = ri.Cvar_Get("r_hdrContrastOffset", "1.0", CVAR_CHEAT | CVAR_LATCH);
 98.2096 +	r_hdrLightmap = ri.Cvar_Get("r_hdrLightmap", "1", CVAR_CHEAT | CVAR_LATCH);
 98.2097 +	r_hdrLightmapExposure = ri.Cvar_Get("r_hdrLightmapExposure", "1.0", CVAR_CHEAT | CVAR_LATCH);
 98.2098 +	r_hdrLightmapGamma = ri.Cvar_Get("r_hdrLightmapGamma", "1.7", CVAR_CHEAT | CVAR_LATCH);
 98.2099 +	r_hdrLightmapCompensate = ri.Cvar_Get("r_hdrLightmapCompensate", "1.0", CVAR_CHEAT | CVAR_LATCH);
 98.2100 +	r_hdrToneMappingOperator = ri.Cvar_Get("r_hdrToneMappingOperator", "1", CVAR_CHEAT | CVAR_LATCH);
 98.2101 +	r_hdrGamma = ri.Cvar_Get("r_hdrGamma", "1.1", CVAR_CHEAT | CVAR_LATCH);
 98.2102  
 98.2103 -	r_minEntityLight = ri.Cvar_Get("r_minEntityLight", "0.5", CVAR_ARCHIVE);
 98.2104 -	ri.Cvar_CheckRange( r_minEntityLight, 0.0f, 1, qfalse );
 98.2105 +	r_printShaders = ri.Cvar_Get("r_printShaders", "0", CVAR_ARCHIVE);
 98.2106  
 98.2107 -	//
 98.2108 +	r_bloom = ri.Cvar_Get("r_bloom", "0", CVAR_ARCHIVE);
 98.2109 +	r_bloomBlur = ri.Cvar_Get("r_bloomBlur", "7.0", CVAR_CHEAT);
 98.2110 +	r_bloomPasses = ri.Cvar_Get("r_bloomPasses", "1", CVAR_CHEAT);
 98.2111 +	r_rotoscope = ri.Cvar_Get("r_rotoscope", "0", CVAR_ARCHIVE);
 98.2112 +
 98.2113  	// temporary variables that can change at any time
 98.2114 -	//
 98.2115 -	r_showImages = ri.Cvar_Get( "r_showImages", "0", CVAR_TEMP );
 98.2116 +	r_showImages = ri.Cvar_Get("r_showImages", "0", CVAR_TEMP);
 98.2117  
 98.2118 -	r_debugLight = ri.Cvar_Get( "r_debuglight", "0", CVAR_TEMP );
 98.2119 -	r_debugSort = ri.Cvar_Get( "r_debugSort", "0", CVAR_CHEAT );
 98.2120 -	r_printShaders = ri.Cvar_Get( "r_printShaders", "0", 0 );
 98.2121 -	r_saveFontData = ri.Cvar_Get( "r_saveFontData", "0", 0 );
 98.2122 +	r_debugLight = ri.Cvar_Get("r_debuglight", "0", CVAR_TEMP);
 98.2123 +	r_debugSort = ri.Cvar_Get("r_debugSort", "0", CVAR_CHEAT);
 98.2124  
 98.2125 -	r_nocurves = ri.Cvar_Get ("r_nocurves", "0", CVAR_CHEAT );
 98.2126 -	r_drawworld = ri.Cvar_Get ("r_drawworld", "1", CVAR_CHEAT );
 98.2127 -	r_lightmap = ri.Cvar_Get ("r_lightmap", "0", 0 );
 98.2128 -	r_portalOnly = ri.Cvar_Get ("r_portalOnly", "0", CVAR_CHEAT );
 98.2129 +	r_nocurves = ri.Cvar_Get("r_nocurves", "0", CVAR_CHEAT);
 98.2130 +	r_nobatching = ri.Cvar_Get("r_nobatching", "0", CVAR_CHEAT);
 98.2131 +	r_noLightScissors = ri.Cvar_Get("r_noLightScissors", "0", CVAR_CHEAT);
 98.2132 +	r_noLightVisCull = ri.Cvar_Get("r_noLightVisCull", "0", CVAR_CHEAT);
 98.2133 +	r_noInteractionSort = ri.Cvar_Get("r_noInteractionSort", "0", CVAR_CHEAT);
 98.2134 +	r_noDynamicLighting = ri.Cvar_Get("r_noDynamicLighting", "0", CVAR_CHEAT);
 98.2135 +	r_noStaticLighting = ri.Cvar_Get("r_noStaticLighting", "0", CVAR_CHEAT);
 98.2136 +	r_drawworld = ri.Cvar_Get("r_drawworld", "1", CVAR_CHEAT);
 98.2137 +	r_portalOnly = ri.Cvar_Get("r_portalOnly", "0", CVAR_CHEAT);
 98.2138  
 98.2139 -	r_flareSize = ri.Cvar_Get ("r_flareSize", "40", CVAR_CHEAT);
 98.2140 -	r_flareFade = ri.Cvar_Get ("r_flareFade", "7", CVAR_CHEAT);
 98.2141 -	r_flareCoeff = ri.Cvar_Get ("r_flareCoeff", FLARE_STDCOEFF, CVAR_CHEAT);
 98.2142 +	r_flareSize = ri.Cvar_Get("r_flareSize", "40", CVAR_CHEAT);
 98.2143 +	r_flareFade = ri.Cvar_Get("r_flareFade", "7", CVAR_CHEAT);
 98.2144  
 98.2145 -	r_showSmp = ri.Cvar_Get ("r_showSmp", "0", CVAR_CHEAT);
 98.2146 -	r_skipBackEnd = ri.Cvar_Get ("r_skipBackEnd", "0", CVAR_CHEAT);
 98.2147 +	r_showSmp = ri.Cvar_Get("r_showSmp", "0", CVAR_CHEAT);
 98.2148 +	r_skipBackEnd = ri.Cvar_Get("r_skipBackEnd", "0", CVAR_CHEAT);
 98.2149  
 98.2150 -	r_measureOverdraw = ri.Cvar_Get( "r_measureOverdraw", "0", CVAR_CHEAT );
 98.2151 -	r_lodscale = ri.Cvar_Get( "r_lodscale", "5", CVAR_CHEAT );
 98.2152 -	r_norefresh = ri.Cvar_Get ("r_norefresh", "0", CVAR_CHEAT);
 98.2153 -	r_drawentities = ri.Cvar_Get ("r_drawentities", "1", CVAR_CHEAT );
 98.2154 -	r_ignore = ri.Cvar_Get( "r_ignore", "1", CVAR_CHEAT );
 98.2155 -	r_nocull = ri.Cvar_Get ("r_nocull", "0", CVAR_CHEAT);
 98.2156 -	r_novis = ri.Cvar_Get ("r_novis", "0", CVAR_CHEAT);
 98.2157 -	r_showcluster = ri.Cvar_Get ("r_showcluster", "0", CVAR_CHEAT);
 98.2158 -	r_speeds = ri.Cvar_Get ("r_speeds", "0", CVAR_CHEAT);
 98.2159 -	r_verbose = ri.Cvar_Get( "r_verbose", "0", CVAR_CHEAT );
 98.2160 -	r_logFile = ri.Cvar_Get( "r_logFile", "0", CVAR_CHEAT );
 98.2161 -	r_debugSurface = ri.Cvar_Get ("r_debugSurface", "0", CVAR_CHEAT);
 98.2162 -	r_nobind = ri.Cvar_Get ("r_nobind", "0", CVAR_CHEAT);
 98.2163 -	r_showtris = ri.Cvar_Get ("r_showtris", "0", CVAR_CHEAT);
 98.2164 -	r_showsky = ri.Cvar_Get ("r_showsky", "0", CVAR_CHEAT);
 98.2165 -	r_shownormals = ri.Cvar_Get ("r_shownormals", "0", CVAR_CHEAT);
 98.2166 -	r_clear = ri.Cvar_Get ("r_clear", "0", CVAR_CHEAT);
 98.2167 -	r_offsetFactor = ri.Cvar_Get( "r_offsetfactor", "-1", CVAR_CHEAT );
 98.2168 -	r_offsetUnits = ri.Cvar_Get( "r_offsetunits", "-2", CVAR_CHEAT );
 98.2169 -	r_drawBuffer = ri.Cvar_Get( "r_drawBuffer", "GL_BACK", CVAR_CHEAT );
 98.2170 -	r_lockpvs = ri.Cvar_Get ("r_lockpvs", "0", CVAR_CHEAT);
 98.2171 -	r_noportals = ri.Cvar_Get ("r_noportals", "0", CVAR_CHEAT);
 98.2172 -	r_shadows = ri.Cvar_Get( "cg_shadows", "1", 0 );
 98.2173 +	r_measureOverdraw = ri.Cvar_Get("r_measureOverdraw", "0", CVAR_CHEAT);
 98.2174 +	r_lodscale = ri.Cvar_Get("r_lodscale", "5", CVAR_CHEAT);
 98.2175 +	r_norefresh = ri.Cvar_Get("r_norefresh", "0", CVAR_CHEAT);
 98.2176 +	r_drawentities = ri.Cvar_Get("r_drawentities", "1", CVAR_CHEAT);
 98.2177 +	r_ignore = ri.Cvar_Get("r_ignore", "1", CVAR_CHEAT);
 98.2178 +	r_nocull = ri.Cvar_Get("r_nocull", "0", CVAR_CHEAT);
 98.2179 +	r_novis = ri.Cvar_Get("r_novis", "0", CVAR_CHEAT);
 98.2180 +	r_showcluster = ri.Cvar_Get("r_showcluster", "0", CVAR_CHEAT);
 98.2181 +	r_speeds = ri.Cvar_Get("r_speeds", "0", 0);
 98.2182 +	r_verbose = ri.Cvar_Get("r_verbose", "0", CVAR_CHEAT);
 98.2183 +	r_logFile = ri.Cvar_Get("r_logFile", "0", CVAR_CHEAT);
 98.2184 +	r_debugSurface = ri.Cvar_Get("r_debugSurface", "0", CVAR_CHEAT);
 98.2185 +	r_nobind = ri.Cvar_Get("r_nobind", "0", CVAR_CHEAT);
 98.2186 +	r_clear = ri.Cvar_Get("r_clear", "1", CVAR_CHEAT);
 98.2187 +	r_offsetFactor = ri.Cvar_Get("r_offsetFactor", "-1", CVAR_CHEAT);
 98.2188 +	r_offsetUnits = ri.Cvar_Get("r_offsetUnits", "-2", CVAR_CHEAT);
 98.2189 +	r_forceSpecular = ri.Cvar_Get("r_forceSpecular", "0", CVAR_CHEAT);
 98.2190 +	r_specularExponent = ri.Cvar_Get("r_specularExponent", "16", CVAR_CHEAT);
 98.2191 +	r_specularScale = ri.Cvar_Get("r_specularScale", "1.4", CVAR_CHEAT | CVAR_LATCH);
 98.2192 +	r_normalScale = ri.Cvar_Get("r_normalScale", "1.1", CVAR_CHEAT | CVAR_LATCH);
 98.2193 +	r_normalMapping = ri.Cvar_Get("r_normalMapping", "1", CVAR_ARCHIVE | CVAR_LATCH);
 98.2194 +	r_parallaxDepthScale = ri.Cvar_Get("r_parallaxDepthScale", "0.03", CVAR_CHEAT);
 98.2195 +	r_drawBuffer = ri.Cvar_Get("r_drawBuffer", "GL_BACK", CVAR_CHEAT);
 98.2196 +	r_lockpvs = ri.Cvar_Get("r_lockpvs", "0", CVAR_CHEAT);
 98.2197 +	r_noportals = ri.Cvar_Get("r_noportals", "0", CVAR_CHEAT);
 98.2198  
 98.2199 -	r_maxpolys = ri.Cvar_Get( "r_maxpolys", va("%d", MAX_POLYS), 0);
 98.2200 -	r_maxpolyverts = ri.Cvar_Get( "r_maxpolyverts", va("%d", MAX_POLYVERTS), 0);
 98.2201 -	
 98.2202 -	// for cell shading algorithm selection
 98.2203 -	r_celshadalgo = ri.Cvar_Get ("r_celshadalgo", "0", CVAR_LATCH | CVAR_ARCHIVE);
 98.2204 -	// cel outline option
 98.2205 -	r_celoutline = ri.Cvar_Get("r_celoutline","0", CVAR_ARCHIVE);
 98.2206 +	r_shadows = ri.Cvar_Get("cg_shadows", "1", CVAR_ARCHIVE | CVAR_LATCH);
 98.2207 +	ri.Cvar_CheckRange(r_shadows, 0, 6, qtrue);
 98.2208  
 98.2209 -	// make sure all the commands added here are also
 98.2210 -	// removed in R_Shutdown
 98.2211 -	ri.Cmd_AddCommand( "imagelist", R_ImageList_f );
 98.2212 -	ri.Cmd_AddCommand( "shaderlist", R_ShaderList_f );
 98.2213 -	ri.Cmd_AddCommand( "skinlist", R_SkinList_f );
 98.2214 -	ri.Cmd_AddCommand( "modellist", R_Modellist_f );
 98.2215 -	ri.Cmd_AddCommand( "screenshot", R_ScreenShot_f );
 98.2216 -	ri.Cmd_AddCommand( "screenshotJPEG", R_ScreenShotJPEG_f );
 98.2217 -	ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
 98.2218 +	r_softShadows = ri.Cvar_Get("r_softShadows", "0", CVAR_ARCHIVE | CVAR_LATCH);
 98.2219 +	ri.Cvar_CheckRange(r_softShadows, 0, 6, qtrue);
 98.2220 +
 98.2221 +	r_shadowBlur = ri.Cvar_Get("r_shadowBlur", "2", CVAR_ARCHIVE);
 98.2222 +
 98.2223 +	r_shadowMapQuality = ri.Cvar_Get("r_shadowMapQuality", "3", CVAR_ARCHIVE | CVAR_LATCH);
 98.2224 +	ri.Cvar_CheckRange(r_shadowMapQuality, 0, 4, qtrue);
 98.2225 +
 98.2226 +	r_shadowMapSizeUltra = ri.Cvar_Get("r_shadowMapSizeUltra", "1024", CVAR_ARCHIVE | CVAR_LATCH);
 98.2227 +	ri.Cvar_CheckRange(r_shadowMapSizeUltra, 32, 2048, qtrue);
 98.2228 +
 98.2229 +	r_shadowMapSizeVeryHigh = ri.Cvar_Get("r_shadowMapSizeVeryHigh", "512", CVAR_ARCHIVE | CVAR_LATCH);
 98.2230 +	ri.Cvar_CheckRange(r_shadowMapSizeVeryHigh, 32, 2048, qtrue);
 98.2231 +
 98.2232 +	r_shadowMapSizeHigh = ri.Cvar_Get("r_shadowMapSizeHigh", "256", CVAR_ARCHIVE | CVAR_LATCH);
 98.2233 +	ri.Cvar_CheckRange(r_shadowMapSizeHigh, 32, 2048, qtrue);
 98.2234 +
 98.2235 +	r_shadowMapSizeMedium = ri.Cvar_Get("r_shadowMapSizeMedium", "128", CVAR_ARCHIVE | CVAR_LATCH);
 98.2236 +	ri.Cvar_CheckRange(r_shadowMapSizeMedium, 32, 2048, qtrue);
 98.2237 +
 98.2238 +	r_shadowMapSizeLow = ri.Cvar_Get("r_shadowMapSizeLow", "64", CVAR_ARCHIVE | CVAR_LATCH);
 98.2239 +	ri.Cvar_CheckRange(r_shadowMapSizeLow, 32, 2048, qtrue);
 98.2240 +
 98.2241 +
 98.2242 +	shadowMapResolutions[0] = r_shadowMapSizeUltra->integer;
 98.2243 +	shadowMapResolutions[1] = r_shadowMapSizeVeryHigh->integer;
 98.2244 +	shadowMapResolutions[2] = r_shadowMapSizeHigh->integer;
 98.2245 +	shadowMapResolutions[3] = r_shadowMapSizeMedium->integer;
 98.2246 +	shadowMapResolutions[4] = r_shadowMapSizeLow->integer;
 98.2247 +
 98.2248 +	r_shadowOffsetFactor = ri.Cvar_Get("r_shadowOffsetFactor", "0", CVAR_CHEAT);
 98.2249 +	r_shadowOffsetUnits = ri.Cvar_Get("r_shadowOffsetUnits", "0", CVAR_CHEAT);
 98.2250 +	r_shadowLodBias = ri.Cvar_Get("r_shadowLodBias", "0", CVAR_CHEAT);
 98.2251 +	r_shadowLodScale = ri.Cvar_Get("r_shadowLodScale", "0.8", CVAR_CHEAT);
 98.2252 +	r_noShadowPyramids = ri.Cvar_Get("r_noShadowPyramids", "0", CVAR_CHEAT);
 98.2253 +	r_cullShadowPyramidFaces = ri.Cvar_Get("r_cullShadowPyramidFaces", "0", CVAR_CHEAT);
 98.2254 +	r_cullShadowPyramidCurves = ri.Cvar_Get("r_cullShadowPyramidCurves", "1", CVAR_CHEAT);
 98.2255 +	r_cullShadowPyramidTriangles = ri.Cvar_Get("r_cullShadowPyramidTriangles", "1", CVAR_CHEAT);
 98.2256 +	r_noShadowFrustums = ri.Cvar_Get("r_noShadowFrustums", "0", CVAR_CHEAT);
 98.2257 +	r_noLightFrustums = ri.Cvar_Get("r_noLightFrustums", "0", CVAR_CHEAT);
 98.2258 +
 98.2259 +	r_maxPolys = ri.Cvar_Get("r_maxpolys", "20000", 0);	// 600 in vanilla Q3A
 98.2260 +	ri.Cvar_CheckRange(r_maxPolys, 600, 30000, qtrue);
 98.2261 +
 98.2262 +	r_maxPolyVerts = ri.Cvar_Get("r_maxpolyverts", "100000", 0);	// 3000 in vanilla Q3A
 98.2263 +	ri.Cvar_CheckRange(r_maxPolyVerts, 3000, 200000, qtrue);
 98.2264 +
 98.2265 +	r_showTris = ri.Cvar_Get("r_showTris", "0", CVAR_CHEAT);
 98.2266 +	r_showSky = ri.Cvar_Get("r_showSky", "0", CVAR_CHEAT);
 98.2267 +	r_showShadowVolumes = ri.Cvar_Get("r_showShadowVolumes", "0", CVAR_CHEAT);
 98.2268 +	r_showShadowLod = ri.Cvar_Get("r_showShadowLod", "0", CVAR_CHEAT);
 98.2269 +	r_showSkeleton = ri.Cvar_Get("r_showSkeleton", "0", CVAR_CHEAT);
 98.2270 +	r_showEntityTransforms = ri.Cvar_Get("r_showEntityTransforms", "0", CVAR_CHEAT);
 98.2271 +	r_showLightTransforms = ri.Cvar_Get("r_showLightTransforms", "0", CVAR_CHEAT);
 98.2272 +	r_showLightInteractions = ri.Cvar_Get("r_showLightInteractions", "0", CVAR_CHEAT);
 98.2273 +	r_showLightScissors = ri.Cvar_Get("r_showLightScissors", "0", CVAR_CHEAT);
 98.2274 +	r_showLightBatches = ri.Cvar_Get("r_showLightBatches", "0", CVAR_CHEAT);
 98.2275 +	r_showOcclusionQueries = ri.Cvar_Get("r_showOcclusionQueries", "0", CVAR_CHEAT);
 98.2276 +	r_showBatches = ri.Cvar_Get("r_showBatches", "0", CVAR_CHEAT);
 98.2277 +	r_showLightMaps = ri.Cvar_Get("r_showLightMaps", "0", CVAR_CHEAT | CVAR_LATCH);
 98.2278 +	r_showDeluxeMaps = ri.Cvar_Get("r_showDeluxeMaps", "0", CVAR_CHEAT | CVAR_LATCH);
 98.2279 +	r_showAreaPortals = ri.Cvar_Get("r_showAreaPortals", "0", CVAR_CHEAT);
 98.2280 +	r_showCubeProbes = ri.Cvar_Get("r_showCubeProbes", "0", CVAR_CHEAT);
 98.2281 +
 98.2282 +	r_showDeferredDiffuse = ri.Cvar_Get("r_showDeferredDiffuse", "0", CVAR_CHEAT);
 98.2283 +	r_showDeferredNormal = ri.Cvar_Get("r_showDeferredNormal", "0", CVAR_CHEAT);
 98.2284 +	r_showDeferredSpecular = ri.Cvar_Get("r_showDeferredSpecular", "0", CVAR_CHEAT);
 98.2285 +	r_showDeferredPosition = ri.Cvar_Get("r_showDeferredPosition", "0", CVAR_CHEAT);
 98.2286 +	r_showDeferredRender = ri.Cvar_Get("r_showDeferredRender", "0", CVAR_CHEAT);
 98.2287 +
 98.2288 +	// make sure all the commands added here are also removed in R_Shutdown
 98.2289 +	ri.Cmd_AddCommand("imagelist", R_ImageList_f);
 98.2290 +	ri.Cmd_AddCommand("shaderlist", R_ShaderList_f);
 98.2291 +	ri.Cmd_AddCommand("shaderexp", R_ShaderExp_f);
 98.2292 +	ri.Cmd_AddCommand("skinlist", R_SkinList_f);
 98.2293 +	ri.Cmd_AddCommand("modellist", R_Modellist_f);
 98.2294 +	ri.Cmd_AddCommand("modelist", R_ModeList_f);
 98.2295 +	ri.Cmd_AddCommand("animationlist", R_AnimationList_f);
 98.2296 +	ri.Cmd_AddCommand("fbolist", R_FBOList_f);
 98.2297 +	ri.Cmd_AddCommand("vbolist", R_VBOList_f);
 98.2298 +	ri.Cmd_AddCommand("screenshot", R_ScreenShot_f);
 98.2299 +	ri.Cmd_AddCommand("screenshotJPEG", R_ScreenShotJPEG_f);
 98.2300 +	//ri.Cmd_AddCommand("screenshotPNG", R_ScreenShotPNG_f);
 98.2301 +	ri.Cmd_AddCommand("gfxinfo", GfxInfo_f);
 98.2302 +	ri.Cmd_AddCommand("generatemtr", R_GenerateMaterialFile_f);
 98.2303  }
 98.2304  
 98.2305  /*
 98.2306 @@ -1076,100 +1596,112 @@
 98.2307  R_Init
 98.2308  ===============
 98.2309  */
 98.2310 -void R_Init( void ) {	
 98.2311 -	int	err;
 98.2312 -	int i;
 98.2313 -	byte *ptr;
 98.2314 +void R_Init(void)
 98.2315 +{
 98.2316 +	int             err;
 98.2317 +	int             i;
 98.2318 +	byte           *ptr;
 98.2319  
 98.2320 -	ri.Printf( PRINT_ALL, "----- R_Init -----\n" );
 98.2321 +	ri.Printf(PRINT_ALL, "----- R_Init -----\n");
 98.2322  
 98.2323  	// clear all our internal state
 98.2324 -	Com_Memset( &tr, 0, sizeof( tr ) );
 98.2325 -	Com_Memset( &backEnd, 0, sizeof( backEnd ) );
 98.2326 -	Com_Memset( &tess, 0, sizeof( tess ) );
 98.2327 +	Com_Memset(&tr, 0, sizeof(tr));
 98.2328 +	Com_Memset(&backEnd, 0, sizeof(backEnd));
 98.2329 +	Com_Memset(&tess, 0, sizeof(tess));
 98.2330  
 98.2331 -//	Swap_Init();
 98.2332 +	if((intptr_t) tess.xyz & 15)
 98.2333 +		Com_Printf("WARNING: tess.xyz not 16 byte aligned\n");
 98.2334  
 98.2335 -	if ( (intptr_t)tess.xyz & 15 ) {
 98.2336 -		Com_Printf( "WARNING: tess.xyz not 16 byte aligned\n" );
 98.2337 -	}
 98.2338 -	Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) );
 98.2339 -
 98.2340 -	//
 98.2341  	// init function tables
 98.2342 -	//
 98.2343 -	for ( i = 0; i < FUNCTABLE_SIZE; i++ )
 98.2344 +	for(i = 0; i < FUNCTABLE_SIZE; i++)
 98.2345  	{
 98.2346 -		tr.sinTable[i]		= sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) );
 98.2347 -		tr.squareTable[i]	= ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f;
 98.2348 +		tr.sinTable[i] = sin(DEG2RAD(i * 360.0f / ((float)(FUNCTABLE_SIZE - 1))));
 98.2349 +		tr.squareTable[i] = (i < FUNCTABLE_SIZE / 2) ? 1.0f : -1.0f;
 98.2350  		tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE;
 98.2351  		tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i];
 98.2352  
 98.2353 -		if ( i < FUNCTABLE_SIZE / 2 )
 98.2354 +		if(i < FUNCTABLE_SIZE / 2)
 98.2355  		{
 98.2356 -			if ( i < FUNCTABLE_SIZE / 4 )
 98.2357 +			if(i < FUNCTABLE_SIZE / 4)
 98.2358  			{
 98.2359 -				tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 );
 98.2360 +				tr.triangleTable[i] = (float)i / (FUNCTABLE_SIZE / 4);
 98.2361  			}
 98.2362  			else
 98.2363  			{
 98.2364 -				tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4];
 98.2365 +				tr.triangleTable[i] = 1.0f - tr.triangleTable[i - FUNCTABLE_SIZE / 4];
 98.2366  			}
 98.2367  		}
 98.2368  		else
 98.2369  		{
 98.2370 -			tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2];
 98.2371 +			tr.triangleTable[i] = -tr.triangleTable[i - FUNCTABLE_SIZE / 2];
 98.2372  		}
 98.2373  	}
 98.2374  
 98.2375 -	R_InitFogTable();
 98.2376 -
 98.2377  	R_NoiseInit();
 98.2378  
 98.2379  	R_Register();
 98.2380 -	
 98.2381 -	R_BloomInit();
 98.2382  
 98.2383 -	max_polys = r_maxpolys->integer;
 98.2384 -	if (max_polys < MAX_POLYS)
 98.2385 -		max_polys = MAX_POLYS;
 98.2386 -
 98.2387 -	max_polyverts = r_maxpolyverts->integer;
 98.2388 -	if (max_polyverts < MAX_POLYVERTS)
 98.2389 -		max_polyverts = MAX_POLYVERTS;
 98.2390 -
 98.2391 -	ptr = ri.Hunk_Alloc( sizeof( *backEndData[0] ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low);
 98.2392 +	ptr =
 98.2393 +		ri.Hunk_Alloc(sizeof(*backEndData[0]) + sizeof(srfPoly_t) * r_maxPolys->integer +
 98.2394 +					  sizeof(polyVert_t) * r_maxPolyVerts->integer, h_low);
 98.2395  	backEndData[0] = (backEndData_t *) ptr;
 98.2396 -	backEndData[0]->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData[0] ));
 98.2397 -	backEndData[0]->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData[0] ) + sizeof(srfPoly_t) * max_polys);
 98.2398 -	if ( r_smp->integer ) {
 98.2399 -		ptr = ri.Hunk_Alloc( sizeof( *backEndData[1] ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low);
 98.2400 +	backEndData[0]->polys = (srfPoly_t *) ((char *)ptr + sizeof(*backEndData[0]));
 98.2401 +	backEndData[0]->polyVerts = (polyVert_t *) ((char *)ptr + sizeof(*backEndData[0]) + sizeof(srfPoly_t) * r_maxPolys->integer);
 98.2402 +	if(r_smp->integer)
 98.2403 +	{
 98.2404 +		ptr =
 98.2405 +			ri.Hunk_Alloc(sizeof(*backEndData[1]) + sizeof(srfPoly_t) * r_maxPolys->integer +
 98.2406 +						  sizeof(polyVert_t) * r_maxPolyVerts->integer, h_low);
 98.2407  		backEndData[1] = (backEndData_t *) ptr;
 98.2408 -		backEndData[1]->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData[1] ));
 98.2409 -		backEndData[1]->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData[1] ) + sizeof(srfPoly_t) * max_polys);
 98.2410 -	} else {
 98.2411 +		backEndData[1]->polys = (srfPoly_t *) ((char *)ptr + sizeof(*backEndData[1]));
 98.2412 +		backEndData[1]->polyVerts =
 98.2413 +			(polyVert_t *) ((char *)ptr + sizeof(*backEndData[1]) + sizeof(srfPoly_t) * r_maxPolys->integer);
 98.2414 +	}
 98.2415 +	else
 98.2416 +	{
 98.2417  		backEndData[1] = NULL;
 98.2418  	}
 98.2419 +
 98.2420  	R_ToggleSmpFrame();
 98.2421  
 98.2422  	InitOpenGL();
 98.2423  
 98.2424 +	GLSL_InitGPUShaders();
 98.2425 +
 98.2426  	R_InitImages();
 98.2427  
 98.2428 +	R_InitFBOs();
 98.2429 +
 98.2430 +	R_InitVBOs();
 98.2431 +
 98.2432  	R_InitShaders();
 98.2433  
 98.2434  	R_InitSkins();
 98.2435  
 98.2436  	R_ModelInit();
 98.2437  
 98.2438 +	R_InitAnimations();
 98.2439 +
 98.2440  	R_InitFreeType();
 98.2441  
 98.2442 +	if(glConfig.textureAnisotropyAvailable)
 98.2443 +	{
 98.2444 +		ri.Cvar_CheckRange(r_ext_texture_filter_anisotropic, 0, glConfig.maxTextureAnisotropy, qfalse);
 98.2445 +	}
 98.2446 +
 98.2447 +	if(glConfig.occlusionQueryBits && glConfig.driverType != GLDRV_MESA)
 98.2448 +	{
 98.2449 +		qglGenQueriesARB(MAX_OCCLUSION_QUERIES, tr.occlusionQueryObjects);
 98.2450 +	}
 98.2451  
 98.2452  	err = qglGetError();
 98.2453 -	if ( err != GL_NO_ERROR )
 98.2454 -		ri.Printf (PRINT_ALL, "glGetError() = 0x%x\n", err);
 98.2455 +	if(err != GL_NO_ERROR)
 98.2456 +	{
 98.2457 +		ri.Error(ERR_FATAL, "R_Init() - glGetError() failed = 0x%x\n", err);
 98.2458 +		//ri.Printf(PRINT_ALL, "glGetError() = 0x%x\n", err);
 98.2459 +	}
 98.2460  
 98.2461 -	ri.Printf( PRINT_ALL, "----- finished R_Init -----\n" );
 98.2462 +	ri.Printf(PRINT_ALL, "----- finished R_Init -----\n");
 98.2463  }
 98.2464  
 98.2465  /*
 98.2466 @@ -1177,31 +1709,54 @@
 98.2467  RE_Shutdown
 98.2468  ===============
 98.2469  */
 98.2470 -void RE_Shutdown( qboolean destroyWindow ) {	
 98.2471 +void RE_Shutdown(qboolean destroyWindow)
 98.2472 +{
 98.2473 +	ri.Printf(PRINT_ALL, "RE_Shutdown( destroyWindow = %i )\n", destroyWindow);
 98.2474  
 98.2475 -	ri.Printf( PRINT_DEVELOPER, "RE_Shutdown( %i )\n", destroyWindow );
 98.2476 +	ri.Cmd_RemoveCommand("modellist");
 98.2477 +	ri.Cmd_RemoveCommand("screenshotPNG");
 98.2478 +	ri.Cmd_RemoveCommand("screenshotJPEG");
 98.2479 +	ri.Cmd_RemoveCommand("screenshot");
 98.2480 +	ri.Cmd_RemoveCommand("imagelist");
 98.2481 +	ri.Cmd_RemoveCommand("shaderlist");
 98.2482 +	ri.Cmd_RemoveCommand("shaderexp");
 98.2483 +	ri.Cmd_RemoveCommand("skinlist");
 98.2484 +	ri.Cmd_RemoveCommand("gfxinfo");
 98.2485 +	ri.Cmd_RemoveCommand("modelist");
 98.2486 +	ri.Cmd_RemoveCommand("shaderstate");
 98.2487 +	ri.Cmd_RemoveCommand("animationlist");
 98.2488 +	ri.Cmd_RemoveCommand("fbolist");
 98.2489 +	ri.Cmd_RemoveCommand("vbolist");
 98.2490 +	ri.Cmd_RemoveCommand("generatemtr");
 98.2491  
 98.2492 -	ri.Cmd_RemoveCommand ("modellist");
 98.2493 -	ri.Cmd_RemoveCommand ("screenshotJPEG");
 98.2494 -	ri.Cmd_RemoveCommand ("screenshot");
 98.2495 -	ri.Cmd_RemoveCommand ("imagelist");
 98.2496 -	ri.Cmd_RemoveCommand ("shaderlist");
 98.2497 -	ri.Cmd_RemoveCommand ("skinlist");
 98.2498 -	ri.Cmd_RemoveCommand ("gfxinfo");
 98.2499 -	ri.Cmd_RemoveCommand( "modelist" );
 98.2500 -	ri.Cmd_RemoveCommand( "shaderstate" );
 98.2501 +	if(tr.registered)
 98.2502 +	{
 98.2503 +		R_SyncRenderThread();
 98.2504  
 98.2505 +		R_ShutdownCommandBuffers();
 98.2506 +		R_ShutdownImages();
 98.2507 +		R_ShutdownVBOs();
 98.2508 +		R_ShutdownFBOs();
 98.2509  
 98.2510 -	if ( tr.registered ) {
 98.2511 -		R_SyncRenderThread();
 98.2512 -		R_ShutdownCommandBuffers();
 98.2513 -		R_DeleteTextures();
 98.2514 +		if(glConfig.occlusionQueryBits && glConfig.driverType != GLDRV_MESA)
 98.2515 +		{
 98.2516 +			qglDeleteQueriesARB(MAX_OCCLUSION_QUERIES, tr.occlusionQueryObjects);
 98.2517 +		}
 98.2518 +
 98.2519 +		GLSL_ShutdownGPUShaders();
 98.2520 +
 98.2521 +		//GLimp_ShutdownRenderThread();
 98.2522  	}
 98.2523  
 98.2524  	R_DoneFreeType();
 98.2525  
 98.2526  	// shut down platform specific OpenGL stuff
 98.2527 -	if ( destroyWindow ) {
 98.2528 +
 98.2529 +	// Tr3B: this should be always executed if we want to avoid some GLSL problems with SMP
 98.2530 +#if !defined(SMP)
 98.2531 +	if(destroyWindow)
 98.2532 +#endif
 98.2533 +	{
 98.2534  		GLimp_Shutdown();
 98.2535  	}
 98.2536  
 98.2537 @@ -1216,42 +1771,48 @@
 98.2538  Touch all images to make sure they are resident
 98.2539  =============
 98.2540  */
 98.2541 -void RE_EndRegistration( void ) {
 98.2542 +void RE_EndRegistration(void)
 98.2543 +{
 98.2544  	R_SyncRenderThread();
 98.2545 -	if (!Sys_LowPhysicalMemory()) {
 98.2546 -		RB_ShowImages();
 98.2547 -	}
 98.2548 +
 98.2549 +	/*
 98.2550 +	   if(!Sys_LowPhysicalMemory())
 98.2551 +	   {
 98.2552 +	   RB_ShowImages();
 98.2553 +	   }
 98.2554 +	 */
 98.2555  }
 98.2556  
 98.2557  
 98.2558  /*
 98.2559 -@@@@@@@@@@@@@@@@@@@@@
 98.2560 +=====================
 98.2561  GetRefAPI
 98.2562 -
 98.2563 -@@@@@@@@@@@@@@@@@@@@@
 98.2564 +=====================
 98.2565  */
 98.2566 -refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) {
 98.2567 -	static refexport_t	re;
 98.2568 +refexport_t    *GetRefAPI(int apiVersion, refimport_t * rimp)
 98.2569 +{
 98.2570 +	static refexport_t re;
 98.2571  
 98.2572  	ri = *rimp;
 98.2573  
 98.2574 -	Com_Memset( &re, 0, sizeof( re ) );
 98.2575 +	Com_Memset(&re, 0, sizeof(re));
 98.2576  
 98.2577 -	if ( apiVersion != REF_API_VERSION ) {
 98.2578 -		ri.Printf(PRINT_ALL, "Mismatched REF_API_VERSION: expected %i, got %i\n", 
 98.2579 -			REF_API_VERSION, apiVersion );
 98.2580 +	if(apiVersion != REF_API_VERSION)
 98.2581 +	{
 98.2582 +		ri.Printf(PRINT_ALL, "Mismatched REF_API_VERSION: expected %i, got %i\n", REF_API_VERSION, apiVersion);
 98.2583  		return NULL;
 98.2584  	}
 98.2585  
 98.2586  	// the RE_ functions are Renderer Entry points
 98.2587 -
 98.2588  	re.Shutdown = RE_Shutdown;
 98.2589  
 98.2590  	re.BeginRegistration = RE_BeginRegistration;
 98.2591  	re.RegisterModel = RE_RegisterModel;
 98.2592 +	re.RegisterAnimation = RE_RegisterAnimation;
 98.2593  	re.RegisterSkin = RE_RegisterSkin;
 98.2594  	re.RegisterShader = RE_RegisterShader;
 98.2595  	re.RegisterShaderNoMip = RE_RegisterShaderNoMip;
 98.2596 +	re.RegisterShaderLightAttenuation = RE_RegisterShaderLightAttenuation;
 98.2597  	re.LoadWorld = RE_LoadWorldMap;
 98.2598  	re.SetWorldVisData = RE_SetWorldVisData;
 98.2599  	re.EndRegistration = RE_EndRegistration;
 98.2600 @@ -1260,11 +1821,20 @@
 98.2601  	re.EndFrame = RE_EndFrame;
 98.2602  
 98.2603  	re.MarkFragments = R_MarkFragments;
 98.2604 -	re.LerpTag = R_LerpTag;
 98.2605 +	re.LerpTag = RE_LerpTag;
 98.2606 +
 98.2607 +	re.CheckSkeleton = RE_CheckSkeleton;
 98.2608 +	re.BuildSkeleton = RE_BuildSkeleton;
 98.2609 +	re.BlendSkeleton = RE_BlendSkeleton;
 98.2610 +	re.BoneIndex = RE_BoneIndex;
 98.2611 +	re.AnimNumFrames = RE_AnimNumFrames;
 98.2612 +	re.AnimFrameRate = RE_AnimFrameRate;
 98.2613 +
 98.2614  	re.ModelBounds = R_ModelBounds;
 98.2615  
 98.2616  	re.ClearScene = RE_ClearScene;
 98.2617  	re.AddRefEntityToScene = RE_AddRefEntityToScene;
 98.2618 +	re.AddRefLightToScene = RE_AddRefLightToScene;
 98.2619  	re.AddPolyToScene = RE_AddPolyToScene;
 98.2620  	re.LightForPoint = R_LightForPoint;
 98.2621  	re.AddLightToScene = RE_AddLightToScene;
    99.1 --- a/src/renderer/tr_light.c	Sat Jun 06 03:54:16 2009 +0800
    99.2 +++ b/src/renderer/tr_light.c	Wed Jun 10 09:31:46 2009 +0800
    99.3 @@ -1,106 +1,138 @@
    99.4  /*
    99.5  ===========================================================================
    99.6  Copyright (C) 1999-2005 Id Software, Inc.
    99.7 -Copyright (C) 2000-2006 Tim Angus
    99.8 +Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
    99.9  
   99.10 -This file is part of Tremfusion.
   99.11 +This file is part of XreaL source code.
   99.12  
   99.13 -Tremfusion is free software; you can redistribute it
   99.14 +XreaL source code is free software; you can redistribute it
   99.15  and/or modify it under the terms of the GNU General Public License as
   99.16  published by the Free Software Foundation; either version 2 of the License,
   99.17  or (at your option) any later version.
   99.18  
   99.19 -Tremfusion is distributed in the hope that it will be
   99.20 +XreaL source code is distributed in the hope that it will be
   99.21  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   99.22  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   99.23  GNU General Public License for more details.
   99.24  
   99.25  You should have received a copy of the GNU General Public License
   99.26 -along with Tremfusion; if not, write to the Free Software
   99.27 +along with XreaL source code; if not, write to the Free Software
   99.28  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   99.29  ===========================================================================
   99.30  */
   99.31  // tr_light.c
   99.32 -
   99.33  #include "tr_local.h"
   99.34  
   99.35 -#define	DLIGHT_AT_RADIUS		16
   99.36 -// at the edge of a dlight's influence, this amount of light will be added
   99.37 -
   99.38 -#define	DLIGHT_MINIMUM_RADIUS	16		
   99.39 -// never calculate a range less than this to prevent huge light numbers
   99.40 -
   99.41 -
   99.42 -/*
   99.43 -===============
   99.44 -R_TransformDlights
   99.45 -
   99.46 -Transforms the origins of an array of dlights.
   99.47 -Used by both the front end (for DlightBmodel) and
   99.48 -the back end (before doing the lighting calculation)
   99.49 -===============
   99.50 -*/
   99.51 -void R_TransformDlights( int count, dlight_t *dl, orientationr_t *or) {
   99.52 -	int		i;
   99.53 -	vec3_t	temp;
   99.54 -
   99.55 -	for ( i = 0 ; i < count ; i++, dl++ ) {
   99.56 -		VectorSubtract( dl->origin, or->origin, temp );
   99.57 -		dl->transformed[0] = DotProduct( temp, or->axis[0] );
   99.58 -		dl->transformed[1] = DotProduct( temp, or->axis[1] );
   99.59 -		dl->transformed[2] = DotProduct( temp, or->axis[2] );
   99.60 -	}
   99.61 -}
   99.62 -
   99.63  /*
   99.64  =============
   99.65 -R_DlightBmodel
   99.66 +R_AddBrushModelInteractions
   99.67  
   99.68  Determine which dynamic lights may effect this bmodel
   99.69  =============
   99.70  */
   99.71 -void R_DlightBmodel( bmodel_t *bmodel ) {
   99.72 -	int			i, j;
   99.73 -	dlight_t	*dl;
   99.74 -	int			mask;
   99.75 -	msurface_t	*surf;
   99.76 +void R_AddBrushModelInteractions(trRefEntity_t * ent, trRefLight_t * light)
   99.77 +{
   99.78 +	int             i;
   99.79 +	bspSurface_t   *surf;
   99.80 +	bspModel_t     *bspModel = NULL;
   99.81 +	model_t        *pModel = NULL;
   99.82 +	byte            cubeSideBits;
   99.83 +	interactionType_t iaType = IA_DEFAULT;
   99.84  
   99.85 -	// transform all the lights
   99.86 -	R_TransformDlights( tr.refdef.num_dlights, tr.refdef.dlights, &tr.or );
   99.87 -
   99.88 -	mask = 0;
   99.89 -	for ( i=0 ; i<tr.refdef.num_dlights ; i++ ) {
   99.90 -		dl = &tr.refdef.dlights[i];
   99.91 -
   99.92 -		// see if the point is close enough to the bounds to matter
   99.93 -		for ( j = 0 ; j < 3 ; j++ ) {
   99.94 -			if ( dl->transformed[j] - bmodel->bounds[1][j] > dl->radius ) {
   99.95 -				break;
   99.96 -			}
   99.97 -			if ( bmodel->bounds[0][j] - dl->transformed[j] > dl->radius ) {
   99.98 -				break;
   99.99 -			}
  99.100 -		}
  99.101 -		if ( j < 3 ) {
  99.102 -			continue;
  99.103 -		}
  99.104 -
  99.105 -		// we need to check this light
  99.106 -		mask |= 1 << i;
  99.107 +	// cull the entire model if it is outside the view frustum
  99.108 +	// and we don't care about proper shadowing
  99.109 +	if(ent->cull == CULL_OUT)
  99.110 +	{
  99.111 +		if(r_shadows->integer <= 2 || light->l.noShadows)
  99.112 +			return;
  99.113 +		else
  99.114 +			iaType = IA_SHADOWONLY;
  99.115  	}
  99.116  
  99.117 -	tr.currentEntity->needDlights = (mask != 0);
  99.118 +	// avoid drawing of certain objects
  99.119 +	if(light->l.inverseShadows)
  99.120 +	{
  99.121 +		if(iaType != IA_LIGHTONLY && (light->l.noShadowID && (light->l.noShadowID != ent->e.noShadowID)))
  99.122 +			return;
  99.123 +	}
  99.124 +	else
  99.125 +	{
  99.126 +		if(iaType != IA_LIGHTONLY && (light->l.noShadowID && (light->l.noShadowID == ent->e.noShadowID)))
  99.127 +			return;
  99.128 +	}
  99.129  
  99.130 -	// set the dlight bits in all the surfaces
  99.131 -	for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) {
  99.132 -		surf = bmodel->firstSurface + i;
  99.133 +	pModel = R_GetModelByHandle(ent->e.hModel);
  99.134 +	bspModel = pModel->bsp;
  99.135  
  99.136 -		if ( *surf->data == SF_FACE ) {
  99.137 -			((srfSurfaceFace_t *)surf->data)->dlightBits[ tr.smpFrame ] = mask;
  99.138 -		} else if ( *surf->data == SF_GRID ) {
  99.139 -			((srfGridMesh_t *)surf->data)->dlightBits[ tr.smpFrame ] = mask;
  99.140 -		} else if ( *surf->data == SF_TRIANGLES ) {
  99.141 -			((srfTriangles_t *)surf->data)->dlightBits[ tr.smpFrame ] = mask;
  99.142 +	// do a quick AABB cull
  99.143 +	if(!BoundsIntersect(light->worldBounds[0], light->worldBounds[1], ent->worldBounds[0], ent->worldBounds[1]))
  99.144 +	{
  99.145 +		tr.pc.c_dlightSurfacesCulled += bspModel->numSurfaces;
  99.146 +		return;
  99.147 +	}
  99.148 +
  99.149 +	// do a more expensive and precise light frustum cull
  99.150 +	if(!r_noLightFrustums->integer)
  99.151 +	{
  99.152 +		if(R_CullLightWorldBounds(light, ent->worldBounds) == CULL_OUT)
  99.153 +		{
  99.154 +			tr.pc.c_dlightSurfacesCulled += bspModel->numSurfaces;
  99.155 +			return;
  99.156 +		}
  99.157 +	}
  99.158 +
  99.159 +	cubeSideBits = R_CalcLightCubeSideBits(light, ent->worldBounds);
  99.160 +
  99.161 +	if(r_vboModels->integer && bspModel->numVBOSurfaces)
  99.162 +	{
  99.163 +		srfVBOMesh_t   *vboSurface;
  99.164 +		shader_t       *shader;
  99.165 +
  99.166 +		// static VBOs are fine for lighting and shadow mapping
  99.167 +		for(i = 0; i < bspModel->numVBOSurfaces; i++)
  99.168 +		{
  99.169 +			vboSurface = bspModel->vboSurfaces[i];
  99.170 +			shader = vboSurface->shader;
  99.171 +
  99.172 +			// skip all surfaces that don't matter for lighting only pass
  99.173 +			if(shader->isSky || (!shader->interactLight && shader->noShadows))
  99.174 +				continue;
  99.175 +
  99.176 +			R_AddLightInteraction(light, (void *)vboSurface, shader, cubeSideBits, iaType);
  99.177 +			tr.pc.c_dlightSurfaces++;
  99.178 +		}
  99.179 +	}
  99.180 +	else
  99.181 +	{
  99.182 +
  99.183 +		// set the light bits in all the surfaces
  99.184 +		for(i = 0; i < bspModel->numSurfaces; i++)
  99.185 +		{
  99.186 +			surf = bspModel->firstSurface + i;
  99.187 +
  99.188 +			// FIXME: do more culling?
  99.189 +
  99.190 +			/*
  99.191 +			   if(*surf->data == SF_FACE)
  99.192 +			   {
  99.193 +			   ((srfSurfaceFace_t *) surf->data)->dlightBits[tr.smpFrame] = mask;
  99.194 +			   }
  99.195 +			   else if(*surf->data == SF_GRID)
  99.196 +			   {
  99.197 +			   ((srfGridMesh_t *) surf->data)->dlightBits[tr.smpFrame] = mask;
  99.198 +			   }
  99.199 +			   else if(*surf->data == SF_TRIANGLES)
  99.200 +			   {
  99.201 +			   ((srfTriangles_t *) surf->data)->dlightBits[tr.smpFrame] = mask;
  99.202 +			   }
  99.203 +			 */
  99.204 +
  99.205 +			// skip all surfaces that don't matter for lighting only pass
  99.206 +			if(surf->shader->isSky || (!surf->shader->interactLight && surf->shader->noShadows))
  99.207 +				continue;
  99.208 +
  99.209 +			R_AddLightInteraction(light, surf->data, surf->shader, cubeSideBits, iaType);
  99.210 +			tr.pc.c_dlightSurfaces++;
  99.211  		}
  99.212  	}
  99.213  }
  99.214 @@ -114,132 +146,135 @@
  99.215  =============================================================================
  99.216  */
  99.217  
  99.218 -extern	cvar_t	*r_ambientScale;
  99.219 -extern	cvar_t	*r_directedScale;
  99.220 -extern	cvar_t	*r_debugLight;
  99.221 +
  99.222  
  99.223  /*
  99.224  =================
  99.225  R_SetupEntityLightingGrid
  99.226 -
  99.227  =================
  99.228  */
  99.229 -static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) {
  99.230 -	vec3_t	lightOrigin;
  99.231 -	int		pos[3];
  99.232 -	int		i, j;
  99.233 -	byte	*gridData;
  99.234 -	float	frac[3];
  99.235 -	int		gridStep[3];
  99.236 -	vec3_t	direction;
  99.237 -	float	totalFactor;
  99.238 +static void R_SetupEntityLightingGrid(trRefEntity_t * ent)
  99.239 +{
  99.240 +	vec3_t          lightOrigin;
  99.241 +	int             pos[3];
  99.242 +	int             i, j;
  99.243 +	bspGridPoint_t  *gridPoint;
  99.244 +	bspGridPoint_t  *gridPoint2;
  99.245 +	float           frac[3];
  99.246 +	int             gridStep[3];
  99.247 +	vec3_t          direction;
  99.248 +	float           totalFactor;
  99.249  
  99.250 -	if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
  99.251 +	if(ent->e.renderfx & RF_LIGHTING_ORIGIN)
  99.252 +	{
  99.253  		// seperate lightOrigins are needed so an object that is
  99.254  		// sinking into the ground can still be lit, and so
  99.255  		// multi-part models can be lit identically
  99.256 -		VectorCopy( ent->e.lightingOrigin, lightOrigin );
  99.257 -	} else {
  99.258 -		VectorCopy( ent->e.origin, lightOrigin );
  99.259 +		VectorCopy(ent->e.lightingOrigin, lightOrigin);
  99.260 +	}
  99.261 +	else
  99.262 +	{
  99.263 +		VectorCopy(ent->e.origin, lightOrigin);
  99.264  	}
  99.265  
  99.266 -	VectorSubtract( lightOrigin, tr.world->lightGridOrigin, lightOrigin );
  99.267 -	for ( i = 0 ; i < 3 ; i++ ) {
  99.268 -		float	v;
  99.269 +	VectorSubtract(lightOrigin, tr.world->lightGridOrigin, lightOrigin);
  99.270 +	for(i = 0; i < 3; i++)
  99.271 +	{
  99.272 +		float           v;
  99.273  
  99.274 -		v = lightOrigin[i]*tr.world->lightGridInverseSize[i];
  99.275 -		pos[i] = floor( v );
  99.276 +		v = lightOrigin[i] * tr.world->lightGridInverseSize[i];
  99.277 +		pos[i] = floor(v);
  99.278  		frac[i] = v - pos[i];
  99.279 -		if ( pos[i] < 0 ) {
  99.280 +		if(pos[i] < 0)
  99.281 +		{
  99.282  			pos[i] = 0;
  99.283 -		} else if ( pos[i] >= tr.world->lightGridBounds[i] - 1 ) {
  99.284 +		}
  99.285 +		else if(pos[i] >= tr.world->lightGridBounds[i] - 1)
  99.286 +		{
  99.287  			pos[i] = tr.world->lightGridBounds[i] - 1;
  99.288  		}
  99.289  	}
  99.290  
  99.291 -	VectorClear( ent->ambientLight );
  99.292 -	VectorClear( ent->directedLight );
  99.293 -	VectorClear( direction );
  99.294 -
  99.295 -	assert( tr.world->lightGridData ); // NULL with -nolight maps
  99.296 +	VectorClear(ent->ambientLight);
  99.297 +	VectorClear(ent->directedLight);
  99.298 +	VectorClear(direction);
  99.299  
  99.300  	// trilerp the light value
  99.301 -	gridStep[0] = 8;
  99.302 -	gridStep[1] = 8 * tr.world->lightGridBounds[0];
  99.303 -	gridStep[2] = 8 * tr.world->lightGridBounds[0] * tr.world->lightGridBounds[1];
  99.304 -	gridData = tr.world->lightGridData + pos[0] * gridStep[0]
  99.305 -		+ pos[1] * gridStep[1] + pos[2] * gridStep[2];
  99.306 +	gridStep[0] = 1; //sizeof(bspGridPoint_t);
  99.307 +	gridStep[1] = tr.world->lightGridBounds[0];// * sizeof(bspGridPoint_t);
  99.308 +	gridStep[2] = tr.world->lightGridBounds[0] * tr.world->lightGridBounds[1];// * sizeof(bspGridPoint_t);
  99.309 +	gridPoint = tr.world->lightGridData + pos[0] * gridStep[0] + pos[1] * gridStep[1] + pos[2] * gridStep[2];
  99.310  
  99.311  	totalFactor = 0;
  99.312 -	for ( i = 0 ; i < 8 ; i++ ) {
  99.313 -		float	factor;
  99.314 -		byte	*data;
  99.315 -		int		lat, lng;
  99.316 -		vec3_t	normal;
  99.317 -		#if idppc
  99.318 -		float d0, d1, d2, d3, d4, d5;
  99.319 -		#endif
  99.320 +	for(i = 0; i < 8; i++)
  99.321 +	{
  99.322 +		float           factor;
  99.323 +		int             lat, lng;
  99.324 +		vec3_t          normal;
  99.325 +
  99.326  		factor = 1.0;
  99.327 -		data = gridData;
  99.328 -		for ( j = 0 ; j < 3 ; j++ ) {
  99.329 -			if ( i & (1<<j) ) {
  99.330 +		gridPoint2 = gridPoint;
  99.331 +		for(j = 0; j < 3; j++)
  99.332 +		{
  99.333 +			if(i & (1 << j))
  99.334 +			{
  99.335  				factor *= frac[j];
  99.336 -				data += gridStep[j];
  99.337 -			} else {
  99.338 +				gridPoint2 += gridStep[j];
  99.339 +			}
  99.340 +			else
  99.341 +			{
  99.342  				factor *= (1.0f - frac[j]);
  99.343  			}
  99.344  		}
  99.345  
  99.346 -		if ( !(data[0]+data[1]+data[2]) ) {
  99.347 -			continue;	// ignore samples in walls
  99.348 +		if(!(gridPoint2->ambient[0] + gridPoint2->ambient[1] + gridPoint2->ambient[2]))
  99.349 +		{
  99.350 +			continue;			// ignore samples in walls
  99.351  		}
  99.352 +
  99.353  		totalFactor += factor;
  99.354 -		#if idppc
  99.355 -		d0 = data[0]; d1 = data[1]; d2 = data[2];
  99.356 -		d3 = data[3]; d4 = data[4]; d5 = data[5];
  99.357  
  99.358 -		ent->ambientLight[0] += factor * d0;
  99.359 -		ent->ambientLight[1] += factor * d1;
  99.360 -		ent->ambientLight[2] += factor * d2;
  99.361 +		ent->ambientLight[0] += factor * gridPoint2->ambient[0];
  99.362 +		ent->ambientLight[1] += factor * gridPoint2->ambient[1];
  99.363 +		ent->ambientLight[2] += factor * gridPoint2->ambient[2];
  99.364  
  99.365 -		ent->directedLight[0] += factor * d3;
  99.366 -		ent->directedLight[1] += factor * d4;
  99.367 -		ent->directedLight[2] += factor * d5;
  99.368 -		#else
  99.369 -		ent->ambientLight[0] += factor * data[0];
  99.370 -		ent->ambientLight[1] += factor * data[1];
  99.371 -		ent->ambientLight[2] += factor * data[2];
  99.372 +		ent->directedLight[0] += factor * gridPoint2->directed[0];
  99.373 +		ent->directedLight[1] += factor * gridPoint2->directed[1];
  99.374 +		ent->directedLight[2] += factor * gridPoint2->directed[2];
  99.375  
  99.376 -		ent->directedLight[0] += factor * data[3];
  99.377 -		ent->directedLight[1] += factor * data[4];
  99.378 -		ent->directedLight[2] += factor * data[5];
  99.379 -		#endif
  99.380 -		lat = data[7];
  99.381 -		lng = data[6];
  99.382 -		lat *= (FUNCTABLE_SIZE/256);
  99.383 -		lng *= (FUNCTABLE_SIZE/256);
  99.384 +		lat = gridPoint2->latLong[0];
  99.385 +		lng = gridPoint2->latLong[1];
  99.386 +		lat *= (FUNCTABLE_SIZE / 256);
  99.387 +		lng *= (FUNCTABLE_SIZE / 256);
  99.388  
  99.389  		// decode X as cos( lat ) * sin( long )
  99.390  		// decode Y as sin( lat ) * sin( long )
  99.391  		// decode Z as cos( long )
  99.392  
  99.393 -		normal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
  99.394 +		normal[0] = tr.sinTable[(lat + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK] * tr.sinTable[lng];
  99.395  		normal[1] = tr.sinTable[lat] * tr.sinTable[lng];
  99.396 -		normal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
  99.397 +		normal[2] = tr.sinTable[(lng + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK];
  99.398  
  99.399 -		VectorMA( direction, factor, normal, direction );
  99.400 +		VectorMA(direction, factor, normal, direction);
  99.401  	}
  99.402  
  99.403 -	if ( totalFactor > 0 && totalFactor < 0.99 ) {
  99.404 +#if 1
  99.405 +	if(totalFactor > 0 && totalFactor < 0.99)
  99.406 +	{
  99.407  		totalFactor = 1.0f / totalFactor;
  99.408 -		VectorScale( ent->ambientLight, totalFactor, ent->ambientLight );
  99.409 -		VectorScale( ent->directedLight, totalFactor, ent->directedLight );
  99.410 +		VectorScale(ent->ambientLight, totalFactor, ent->ambientLight);
  99.411 +		VectorScale(ent->directedLight, totalFactor, ent->directedLight);
  99.412  	}
  99.413 +#endif
  99.414  
  99.415 -	VectorScale( ent->ambientLight, r_ambientScale->value, ent->ambientLight );
  99.416 -	VectorScale( ent->directedLight, r_directedScale->value, ent->directedLight );
  99.417 +	VectorNormalize2(direction, ent->lightDir);
  99.418  
  99.419 -	VectorNormalize2( direction, ent->lightDir );
  99.420 +	if(VectorLength(ent->ambientLight) < r_forceAmbient->value)
  99.421 +	{
  99.422 +		ent->ambientLight[0] = r_forceAmbient->value;
  99.423 +		ent->ambientLight[1] = r_forceAmbient->value;
  99.424 +		ent->ambientLight[2] = r_forceAmbient->value;
  99.425 +	}
  99.426  }
  99.427  
  99.428  
  99.429 @@ -248,28 +283,36 @@
  99.430  LogLight
  99.431  ===============
  99.432  */
  99.433 -static void LogLight( trRefEntity_t *ent ) {
  99.434 -	int	max1, max2;
  99.435 +static void LogLight(trRefEntity_t * ent)
  99.436 +{
  99.437 +	int             max1, max2;
  99.438  
  99.439 -	if ( !(ent->e.renderfx & RF_FIRST_PERSON ) ) {
  99.440 +	if(!(ent->e.renderfx & RF_FIRST_PERSON))
  99.441 +	{
  99.442  		return;
  99.443  	}
  99.444  
  99.445  	max1 = ent->ambientLight[0];
  99.446 -	if ( ent->ambientLight[1] > max1 ) {
  99.447 +	if(ent->ambientLight[1] > max1)
  99.448 +	{
  99.449  		max1 = ent->ambientLight[1];
  99.450 -	} else if ( ent->ambientLight[2] > max1 ) {
  99.451 +	}
  99.452 +	else if(ent->ambientLight[2] > max1)
  99.453 +	{
  99.454  		max1 = ent->ambientLight[2];
  99.455  	}
  99.456  
  99.457  	max2 = ent->directedLight[0];
  99.458 -	if ( ent->directedLight[1] > max2 ) {
  99.459 +	if(ent->directedLight[1] > max2)
  99.460 +	{
  99.461  		max2 = ent->directedLight[1];
  99.462 -	} else if ( ent->directedLight[2] > max2 ) {
  99.463 +	}
  99.464 +	else if(ent->directedLight[2] > max2)
  99.465 +	{
  99.466  		max2 = ent->directedLight[2];
  99.467  	}
  99.468  
  99.469 -	ri.Printf( PRINT_ALL, "amb:%i  dir:%i\n", max1, max2 );
  99.470 +	ri.Printf(PRINT_ALL, "amb:%i  dir:%i\n", max1, max2);
  99.471  }
  99.472  
  99.473  /*
  99.474 @@ -280,96 +323,102 @@
  99.475  by the Calc_* functions
  99.476  =================
  99.477  */
  99.478 -void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) {
  99.479 -	int				i;
  99.480 -	dlight_t		*dl;
  99.481 -	float			power;
  99.482 -	vec3_t			dir;
  99.483 -	float			d;
  99.484 -	vec3_t			lightDir;
  99.485 -	vec3_t			lightOrigin;
  99.486 +void R_SetupEntityLighting(const trRefdef_t * refdef, trRefEntity_t * ent)
  99.487 +{
  99.488 +	int             i;
  99.489 +	vec3_t          lightDir;
  99.490 +	vec3_t          lightOrigin;
  99.491 +	float           d;
  99.492  
  99.493 -	// lighting calculations 
  99.494 -	if ( ent->lightingCalculated ) {
  99.495 +	// lighting calculations
  99.496 +	if(ent->lightingCalculated)
  99.497 +	{
  99.498  		return;
  99.499  	}
  99.500  	ent->lightingCalculated = qtrue;
  99.501  
  99.502 -	//
  99.503  	// trace a sample point down to find ambient light
  99.504 -	//
  99.505 -	if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
  99.506 +	if(ent->e.renderfx & RF_LIGHTING_ORIGIN)
  99.507 +	{
  99.508  		// seperate lightOrigins are needed so an object that is
  99.509  		// sinking into the ground can still be lit, and so
  99.510  		// multi-part models can be lit identically
  99.511 -		VectorCopy( ent->e.lightingOrigin, lightOrigin );
  99.512 -	} else {
  99.513 -		VectorCopy( ent->e.origin, lightOrigin );
  99.514 +		VectorCopy(ent->e.lightingOrigin, lightOrigin);
  99.515 +	}
  99.516 +	else
  99.517 +	{
  99.518 +		VectorCopy(ent->e.origin, lightOrigin);
  99.519  	}
  99.520  
  99.521  	// if NOWORLDMODEL, only use dynamic lights (menu system, etc)
  99.522 -	if ( !(refdef->rdflags & RDF_NOWORLDMODEL ) 
  99.523 -		&& tr.world->lightGridData ) {
  99.524 -		R_SetupEntityLightingGrid( ent );
  99.525 -	} else {
  99.526 -		ent->ambientLight[0] = ent->ambientLight[1] = 
  99.527 -			ent->ambientLight[2] = tr.identityLight * ( r_minEntityLight->value * 150 );
  99.528 -		ent->directedLight[0] = ent->directedLight[1] = 
  99.529 -			ent->directedLight[2] = tr.identityLight * ( r_minEntityLight->value * 150 );
  99.530 -		VectorCopy( tr.sunDirection, ent->lightDir );
  99.531 +	if(!(refdef->rdflags & RDF_NOWORLDMODEL) && tr.world->lightGridData)
  99.532 +	{
  99.533 +		R_SetupEntityLightingGrid(ent);
  99.534  	}
  99.535 +	else
  99.536 +	{
  99.537 +		if(!(refdef->rdflags & RDF_NOWORLDMODEL))
  99.538 +		{
  99.539 +			ent->ambientLight[0] = tr.worldEntity.ambientLight[0];
  99.540 +			ent->ambientLight[1] = tr.worldEntity.ambientLight[1];
  99.541 +			ent->ambientLight[2] = tr.worldEntity.ambientLight[2];
  99.542 +		}
  99.543 +		else
  99.544 +		{
  99.545 +			ent->ambientLight[0] = r_forceAmbient->value;
  99.546 +			ent->ambientLight[1] = r_forceAmbient->value;
  99.547 +			ent->ambientLight[2] = r_forceAmbient->value;
  99.548 +		}
  99.549  
  99.550 -	// bonus items and view weapons have a fixed minimum add
  99.551 -	if ( 1 /* ent->e.renderfx & RF_MINLIGHT */ ) {
  99.552 -		// give everything a minimum light add
  99.553 -		ent->ambientLight[0] += tr.identityLight * ( r_minEntityLight->value * 32 );
  99.554 -		ent->ambientLight[1] += tr.identityLight * ( r_minEntityLight->value * 32 );
  99.555 -		ent->ambientLight[2] += tr.identityLight * ( r_minEntityLight->value * 32 );
  99.556 -	}
  99.557 +		ent->directedLight[0] = ent->directedLight[1] = ent->directedLight[2] = tr.identityLight * (150.0f / 255.0f);
  99.558  
  99.559 -	//
  99.560 -	// modify the light by dynamic lights
  99.561 -	//
  99.562 -	d = VectorLength( ent->directedLight );
  99.563 -	VectorScale( ent->lightDir, d, lightDir );
  99.564 -
  99.565 -	for ( i = 0 ; i < refdef->num_dlights ; i++ ) {
  99.566 -		dl = &refdef->dlights[i];
  99.567 -		VectorSubtract( dl->origin, lightOrigin, dir );
  99.568 -		d = VectorNormalize( dir );
  99.569 -
  99.570 -		power = DLIGHT_AT_RADIUS * ( dl->radius * dl->radius );
  99.571 -		if ( d < DLIGHT_MINIMUM_RADIUS ) {
  99.572 -			d = DLIGHT_MINIMUM_RADIUS;
  99.573 +		if(ent->e.renderfx & RF_LIGHTING_ORIGIN)
  99.574 +		{
  99.575 +			VectorSubtract(ent->e.lightingOrigin, ent->e.origin, ent->lightDir);
  99.576 +			VectorNormalize(ent->lightDir);
  99.577  		}
  99.578 -		d = power / ( d * d );
  99.579 -
  99.580 -		VectorMA( ent->directedLight, d, dl->color, ent->directedLight );
  99.581 -		VectorMA( lightDir, d, dir, lightDir );
  99.582 -	}
  99.583 -
  99.584 -	// clamp ambient
  99.585 -	for ( i = 0 ; i < 3 ; i++ ) {
  99.586 -		if ( ent->ambientLight[i] > tr.identityLightByte ) {
  99.587 -			ent->ambientLight[i] = tr.identityLightByte;
  99.588 +		else
  99.589 +		{
  99.590 +			VectorCopy(tr.sunDirection, ent->lightDir);
  99.591  		}
  99.592  	}
  99.593  
  99.594 -	if ( r_debugLight->integer ) {
  99.595 -		LogLight( ent );
  99.596 +#if 0
  99.597 +	// bonus items and view weapons have a fixed minimum add
  99.598 +	if((ent->e.renderfx & RF_MINLIGHT) && VectorLength(ent->ambientLight) <= 0)
  99.599 +	{
  99.600 +		// give everything a minimum light add
  99.601 +		ent->ambientLight[0] += tr.identityLight * 0.125f;
  99.602 +		ent->ambientLight[1] += tr.identityLight * 0.125f;
  99.603 +		ent->ambientLight[2] += tr.identityLight * 0.125f;
  99.604 +	}
  99.605 +#endif
  99.606 +
  99.607 +#if 0
  99.608 +	// clamp ambient
  99.609 +	for(i = 0; i < 3; i++)
  99.610 +	{
  99.611 +		if(ent->ambientLight[i] > tr.identityLight)
  99.612 +		{
  99.613 +			ent->ambientLight[i] = tr.identityLight;
  99.614 +		}
  99.615 +	}
  99.616 +#endif
  99.617 +
  99.618 +	if(r_debugLight->integer)
  99.619 +	{
  99.620 +		LogLight(ent);
  99.621  	}
  99.622  
  99.623 -	// save out the byte packet version
  99.624 -	((byte *)&ent->ambientLightInt)[0] = myftol( ent->ambientLight[0] );
  99.625 -	((byte *)&ent->ambientLightInt)[1] = myftol( ent->ambientLight[1] );
  99.626 -	((byte *)&ent->ambientLightInt)[2] = myftol( ent->ambientLight[2] );
  99.627 -	((byte *)&ent->ambientLightInt)[3] = 0xff;
  99.628 -	
  99.629  	// transform the direction to local space
  99.630 -	VectorNormalize( lightDir );
  99.631 -	ent->lightDir[0] = DotProduct( lightDir, ent->e.axis[0] );
  99.632 -	ent->lightDir[1] = DotProduct( lightDir, ent->e.axis[1] );
  99.633 -	ent->lightDir[2] = DotProduct( lightDir, ent->e.axis[2] );
  99.634 +	d = VectorLength(ent->directedLight);
  99.635 +	VectorScale(ent->lightDir, d, lightDir);
  99.636 +	VectorNormalize(lightDir);
  99.637 +
  99.638 +	// keep it in world space
  99.639 +//	ent->lightDir[0] = DotProduct(lightDir, ent->e.axis[0]);
  99.640 +//	ent->lightDir[1] = DotProduct(lightDir, ent->e.axis[1]);
  99.641 +//	ent->lightDir[2] = DotProduct(lightDir, ent->e.axis[2]);
  99.642  }
  99.643  
  99.644  /*
  99.645 @@ -377,19 +426,1172 @@
  99.646  R_LightForPoint
  99.647  =================
  99.648  */
  99.649 -int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir )
  99.650 +int R_LightForPoint(vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir)
  99.651  {
  99.652 -	trRefEntity_t ent;
  99.653 -	
  99.654 -	if ( tr.world->lightGridData == NULL )
  99.655 -	  return qfalse;
  99.656 +	trRefEntity_t   ent;
  99.657 +
  99.658 +	// bk010103 - this segfaults with -nolight maps
  99.659 +	if(tr.world->lightGridData == NULL)
  99.660 +		return qfalse;
  99.661  
  99.662  	Com_Memset(&ent, 0, sizeof(ent));
  99.663 -	VectorCopy( point, ent.e.origin );
  99.664 -	R_SetupEntityLightingGrid( &ent );
  99.665 +	VectorCopy(point, ent.e.origin);
  99.666 +	R_SetupEntityLightingGrid(&ent);
  99.667  	VectorCopy(ent.ambientLight, ambientLight);
  99.668  	VectorCopy(ent.directedLight, directedLight);
  99.669  	VectorCopy(ent.lightDir, lightDir);
  99.670  
  99.671  	return qtrue;
  99.672  }
  99.673 +
  99.674 +
  99.675 +/*
  99.676 +=================
  99.677 +R_SetupLightOrigin
  99.678 +Tr3B - needs finished transformMatrix
  99.679 +=================
  99.680 +*/
  99.681 +void R_SetupLightOrigin(trRefLight_t * light)
  99.682 +{
  99.683 +	vec3_t          transformed;
  99.684 +
  99.685 +	MatrixTransformNormal(light->transformMatrix, light->l.center, transformed);
  99.686 +	VectorAdd(light->l.origin, transformed, light->origin);
  99.687 +}
  99.688 +
  99.689 +/*
  99.690 +=================
  99.691 +R_SetupLightLocalBounds
  99.692 +=================
  99.693 +*/
  99.694 +void R_SetupLightLocalBounds(trRefLight_t * light)
  99.695 +{
  99.696 +	switch (light->l.rlType)
  99.697 +	{
  99.698 +		case RL_OMNI:
  99.699 +		{
  99.700 +			light->localBounds[0][0] = -light->l.radius[0];
  99.701 +			light->localBounds[0][1] = -light->l.radius[1];
  99.702 +			light->localBounds[0][2] = -light->l.radius[2];
  99.703 +			light->localBounds[1][0] = light->l.radius[0];
  99.704 +			light->localBounds[1][1] = light->l.radius[1];
  99.705 +			light->localBounds[1][2] = light->l.radius[2];
  99.706 +			break;
  99.707 +		}
  99.708 +
  99.709 +		case RL_PROJ:
  99.710 +		{
  99.711 +			float           xMin, xMax, yMin, yMax;
  99.712 +			float           zNear, zFar;
  99.713 +
  99.714 +			zNear = light->l.distNear;
  99.715 +			zFar = light->l.distFar;
  99.716 +
  99.717 +			xMax = zNear * tan(light->l.fovX * M_PI / 360.0f);
  99.718 +			xMin = -xMax;
  99.719 +
  99.720 +			yMax = zNear * tan(light->l.fovY * M_PI / 360.0f);
  99.721 +			yMin = -yMax;
  99.722 +
  99.723 +			light->localBounds[0][0] = -zNear;
  99.724 +			light->localBounds[0][1] = xMin * zFar;
  99.725 +			light->localBounds[0][2] = yMin * zFar;
  99.726 +			light->localBounds[1][0] = zFar;
  99.727 +			light->localBounds[1][1] = xMax * zFar;
  99.728 +			light->localBounds[1][2] = yMax * zFar;
  99.729 +			break;
  99.730 +		}
  99.731 +
  99.732 +		default:
  99.733 +			break;
  99.734 +	}
  99.735 +
  99.736 +	light->sphereRadius = RadiusFromBounds(light->localBounds[0], light->localBounds[1]);
  99.737 +}
  99.738 +
  99.739 +/*
  99.740 +=================
  99.741 +R_SetupLightWorldBounds
  99.742 +Tr3B - needs finished transformMatrix
  99.743 +=================
  99.744 +*/
  99.745 +void R_SetupLightWorldBounds(trRefLight_t * light)
  99.746 +{
  99.747 +	int             j;
  99.748 +	vec3_t          v, transformed;
  99.749 +
  99.750 +	ClearBounds(light->worldBounds[0], light->worldBounds[1]);
  99.751 +
  99.752 +	for(j = 0; j < 8; j++)
  99.753 +	{
  99.754 +		v[0] = light->localBounds[j & 1][0];
  99.755 +		v[1] = light->localBounds[(j >> 1) & 1][1];
  99.756 +		v[2] = light->localBounds[(j >> 2) & 1][2];
  99.757 +
  99.758 +		// transform local bounds vertices into world space
  99.759 +		MatrixTransformPoint(light->transformMatrix, v, transformed);
  99.760 +
  99.761 +		AddPointToBounds(transformed, light->worldBounds[0], light->worldBounds[1]);
  99.762 +	}
  99.763 +}
  99.764 +
  99.765 +/*
  99.766 +=================
  99.767 +R_SetupLightView
  99.768 +=================
  99.769 +*/
  99.770 +void R_SetupLightView(trRefLight_t * light)
  99.771 +{
  99.772 +	switch (light->l.rlType)
  99.773 +	{
  99.774 +		case RL_OMNI:
  99.775 +		{
  99.776 +			MatrixAffineInverse(light->transformMatrix, light->viewMatrix);
  99.777 +			break;
  99.778 +		}
  99.779 +
  99.780 +		case RL_PROJ:
  99.781 +		{
  99.782 +			matrix_t        viewMatrix;
  99.783 +
  99.784 +			MatrixAffineInverse(light->transformMatrix, viewMatrix);
  99.785 +
  99.786 +			// convert from our coordinate system (looking down X)
  99.787 +			// to OpenGL's coordinate system (looking down -Z)
  99.788 +			MatrixMultiply(quakeToOpenGLMatrix, viewMatrix, light->viewMatrix);
  99.789 +			break;
  99.790 +		}
  99.791 +
  99.792 +		default:
  99.793 +			ri.Error(ERR_DROP, "R_SetupLightView: Bad rlType");
  99.794 +	}
  99.795 +}
  99.796 +
  99.797 +/*
  99.798 +=================
  99.799 +R_SetupLightFrustum
  99.800 +=================
  99.801 +*/
  99.802 +void R_SetupLightFrustum(trRefLight_t * light)
  99.803 +{
  99.804 +	switch (light->l.rlType)
  99.805 +	{
  99.806 +		case RL_OMNI:
  99.807 +		{
  99.808 +			int             i;
  99.809 +			vec3_t          planeNormal;
  99.810 +			vec3_t          planeOrigin;
  99.811 +			axis_t          axis;
  99.812 +
  99.813 +			QuatToAxis(light->l.rotation, axis);
  99.814 +
  99.815 +			for(i = 0; i < 3; i++)
  99.816 +			{
  99.817 +				VectorMA(light->l.origin, light->l.radius[i], axis[i], planeOrigin);
  99.818 +				VectorNegate(axis[i], planeNormal);
  99.819 +				VectorNormalize(planeNormal);
  99.820 +
  99.821 +				VectorCopy(planeNormal, light->frustum[i].normal);
  99.822 +				light->frustum[i].dist = DotProduct(planeOrigin, planeNormal);
  99.823 +			}
  99.824 +
  99.825 +			for(i = 0; i < 3; i++)
  99.826 +			{
  99.827 +				VectorMA(light->l.origin, -light->l.radius[i], axis[i], planeOrigin);
  99.828 +				VectorCopy(axis[i], planeNormal);
  99.829 +				VectorNormalize(planeNormal);
  99.830 +
  99.831 +				VectorCopy(planeNormal, light->frustum[i + 3].normal);
  99.832 +				light->frustum[i + 3].dist = DotProduct(planeOrigin, planeNormal);
  99.833 +			}
  99.834 +
  99.835 +			for(i = 0; i < 6; i++)
  99.836 +			{
  99.837 +				vec_t           length, ilength;
  99.838 +
  99.839 +				light->frustum[i].type = PLANE_NON_AXIAL;
  99.840 +
  99.841 +				// normalize
  99.842 +				length = VectorLength(light->frustum[i].normal);
  99.843 +				if(length)
  99.844 +				{
  99.845 +					ilength = 1.0 / length;
  99.846 +					light->frustum[i].normal[0] *= ilength;
  99.847 +					light->frustum[i].normal[1] *= ilength;
  99.848 +					light->frustum[i].normal[2] *= ilength;
  99.849 +					light->frustum[i].dist *= ilength;
  99.850 +				}
  99.851 +
  99.852 +				SetPlaneSignbits(&light->frustum[i]);
  99.853 +			}
  99.854 +			break;
  99.855 +		}
  99.856 +
  99.857 +		case RL_PROJ:
  99.858 +		{
  99.859 +			// calculate frustum planes using the modelview projection matrix
  99.860 +			R_SetupFrustum(light->frustum, light->viewMatrix, light->projectionMatrix);
  99.861 +			break;
  99.862 +		}
  99.863 +
  99.864 +		default:
  99.865 +			break;
  99.866 +	}
  99.867 +}
  99.868 +
  99.869 +
  99.870 +/*
  99.871 +=================
  99.872 +R_SetupLightProjection
  99.873 +=================
  99.874 +*/
  99.875 +// *INDENT-OFF*
  99.876 +void R_SetupLightProjection(trRefLight_t * light)
  99.877 +{
  99.878 +	switch (light->l.rlType)
  99.879 +	{
  99.880 +		case RL_OMNI:
  99.881 +		{
  99.882 +			MatrixSetupScale(light->projectionMatrix, 1.0 / light->l.radius[0], 1.0 / light->l.radius[1], 1.0 / light->l.radius[2]);
  99.883 +			break;
  99.884 +		}
  99.885 +
  99.886 +		case RL_PROJ:
  99.887 +		{
  99.888 +			float           xMin, xMax, yMin, yMax;
  99.889 +			float           width, height, depth;
  99.890 +			float           zNear, zFar;
  99.891 +			float          *proj = light->projectionMatrix;
  99.892 +
  99.893 +			zNear = light->l.distNear;
  99.894 +			zFar = light->l.distFar;
  99.895 +
  99.896 +#if 1
  99.897 +			xMax = zNear * tan(light->l.fovX * M_PI / 360.0f);
  99.898 +			xMin = -xMax;
  99.899 +#else
  99.900 +			// flip X projection
  99.901 +			xMin = zNear * tan(light->l.fovX * M_PI / 360.0f);
  99.902 +			xMax = -xMin;
  99.903 +#endif
  99.904 +
  99.905 +#if 1
  99.906 +			yMax = zNear * tan(light->l.fovY * M_PI / 360.0f);
  99.907 +			yMin = -yMax;
  99.908 +#else
  99.909 +			// HACK: flip Y projection to remove the mirror view from projected .RoQ videos
  99.910 +			yMin = zNear * tan(light->l.fovY * M_PI / 360.0f);
  99.911 +			yMax = -yMin;
  99.912 +#endif
  99.913 +
  99.914 +			width = xMax - xMin;
  99.915 +			height = yMax - yMin;
  99.916 +			depth = zFar - zNear;
  99.917 +
  99.918 +			// OpenGL projection matrix
  99.919 +			proj[0] = (2 * zNear) / width;	proj[4] = 0;					proj[8] = (xMax + xMin) / width;	proj[12] = 0;
  99.920 +			proj[1] = 0;					proj[5] = (2 * zNear) / height;	proj[9] = (yMax + yMin) / height;	proj[13] = 0;
  99.921 +			proj[2] = 0;					proj[6] = 0;					proj[10] = -(zFar + zNear) / depth;	proj[14] = -(2 * zFar * zNear) / depth;
  99.922 +			proj[3] = 0;					proj[7] = 0;					proj[11] = -1;						proj[15] = 0;
  99.923 +			break;
  99.924 +		}
  99.925 +
  99.926 +		default:
  99.927 +			ri.Error(ERR_DROP, "R_SetupLightProjection: Bad rlType");
  99.928 +	}
  99.929 +}
  99.930 +// *INDENT-ON*
  99.931 +
  99.932 +
  99.933 +
  99.934 +/*
  99.935 +=================
  99.936 +R_AddLightInteraction
  99.937 +=================
  99.938 +*/
  99.939 +qboolean R_AddLightInteraction(trRefLight_t * light, surfaceType_t * surface, shader_t * surfaceShader, byte cubeSideBits,
  99.940 +							   interactionType_t iaType)
  99.941 +{
  99.942 +	int             iaIndex;
  99.943 +	interaction_t  *ia;
  99.944 +
  99.945 +	// skip all surfaces that don't matter for lighting only pass
  99.946 +	if(surfaceShader)
  99.947 +	{
  99.948 +		if(surfaceShader->isSky || (!surfaceShader->interactLight && surfaceShader->noShadows))
  99.949 +			return qfalse;
  99.950 +	}
  99.951 +
  99.952 +	// instead of checking for overflow, we just mask the index
  99.953 +	// so it wraps around
  99.954 +	iaIndex = tr.refdef.numInteractions & INTERACTION_MASK;
  99.955 +	ia = &tr.refdef.interactions[iaIndex];
  99.956 +	tr.refdef.numInteractions++;
  99.957 +
  99.958 +	light->noSort = iaIndex == 0;
  99.959 +
  99.960 +	// connect to interaction grid
  99.961 +	if(!light->firstInteraction)
  99.962 +	{
  99.963 +		light->firstInteraction = ia;
  99.964 +	}
  99.965 +
  99.966 +	if(light->lastInteraction)
  99.967 +	{
  99.968 +		light->lastInteraction->next = ia;
  99.969 +	}
  99.970 +
  99.971 +	light->lastInteraction = ia;
  99.972 +
  99.973 +	// update counters
  99.974 +	light->numInteractions++;
  99.975 +
  99.976 +	switch (iaType)
  99.977 +	{
  99.978 +		case IA_SHADOWONLY:
  99.979 +			light->numShadowOnlyInteractions++;
  99.980 +			break;
  99.981 +
  99.982 +		case IA_LIGHTONLY:
  99.983 +			light->numLightOnlyInteractions++;
  99.984 +			break;
  99.985 +
  99.986 +		default:
  99.987 +			break;
  99.988 +	}
  99.989 +
  99.990 +	ia->next = NULL;
  99.991 +
  99.992 +	ia->type = iaType;
  99.993 +
  99.994 +	ia->light = light;
  99.995 +	ia->entity = tr.currentEntity;
  99.996 +	ia->surface = surface;
  99.997 +	ia->surfaceShader = surfaceShader;
  99.998 +
  99.999 +	ia->cubeSideBits = cubeSideBits;
 99.1000 +
 99.1001 +	ia->scissorX = light->scissor.coords[0];
 99.1002 +	ia->scissorY = light->scissor.coords[1];
 99.1003 +	ia->scissorWidth = light->scissor.coords[2] - light->scissor.coords[0];
 99.1004 +	ia->scissorHeight = light->scissor.coords[3] - light->scissor.coords[1];
 99.1005 +
 99.1006 +	if(r_shadows->integer == 3 && qglDepthBoundsEXT)
 99.1007 +	{
 99.1008 +		ia->depthNear = light->depthNear;
 99.1009 +		ia->depthFar = light->depthFar;
 99.1010 +		ia->noDepthBoundsTest = light->noDepthBoundsTest;
 99.1011 +	}
 99.1012 +
 99.1013 +	if(glConfig.occlusionQueryAvailable)
 99.1014 +	{
 99.1015 +		ia->noOcclusionQueries = light->noOcclusionQueries;
 99.1016 +	}
 99.1017 +
 99.1018 +	if(light->isStatic)
 99.1019 +	{
 99.1020 +		tr.pc.c_slightInteractions++;
 99.1021 +	}
 99.1022 +	else
 99.1023 +	{
 99.1024 +		tr.pc.c_dlightInteractions++;
 99.1025 +	}
 99.1026 +
 99.1027 +	return qtrue;
 99.1028 +}
 99.1029 +
 99.1030 +
 99.1031 +/*
 99.1032 +=================
 99.1033 +InteractionCompare
 99.1034 +compare function for qsort()
 99.1035 +=================
 99.1036 +*/
 99.1037 +static int InteractionCompare(const void *a, const void *b)
 99.1038 +{
 99.1039 +#if 1
 99.1040 +	// shader first
 99.1041 +	if(((interaction_t *) a)->surfaceShader < ((interaction_t *) b)->surfaceShader)
 99.1042 +		return -1;
 99.1043 +
 99.1044 +	else if(((interaction_t *) a)->surfaceShader > ((interaction_t *) b)->surfaceShader)
 99.1045 +		return 1;
 99.1046 +#endif
 99.1047 +
 99.1048 +#if 1
 99.1049 +	// then entity
 99.1050 +	if(((interaction_t *) a)->entity == &tr.worldEntity && ((interaction_t *) b)->entity != &tr.worldEntity)
 99.1051 +		return -1;
 99.1052 +
 99.1053 +	else if(((interaction_t *) a)->entity != &tr.worldEntity && ((interaction_t *) b)->entity == &tr.worldEntity)
 99.1054 +		return 1;
 99.1055 +
 99.1056 +	else if(((interaction_t *) a)->entity < ((interaction_t *) b)->entity)
 99.1057 +		return -1;
 99.1058 +
 99.1059 +	else if(((interaction_t *) a)->entity > ((interaction_t *) b)->entity)
 99.1060 +		return 1;
 99.1061 +#endif
 99.1062 +
 99.1063 +	return 0;
 99.1064 +}
 99.1065 +
 99.1066 +/*
 99.1067 +=================
 99.1068 +R_SortInteractions
 99.1069 +=================
 99.1070 +*/
 99.1071 +void R_SortInteractions(trRefLight_t * light)
 99.1072 +{
 99.1073 +	int             i;
 99.1074 +	int             iaFirstIndex;
 99.1075 +	interaction_t  *iaFirst;
 99.1076 +	interaction_t  *ia;
 99.1077 +	interaction_t  *iaLast;
 99.1078 +
 99.1079 +	if(r_noInteractionSort->integer)
 99.1080 +	{
 99.1081 +		return;
 99.1082 +	}
 99.1083 +
 99.1084 +	if(!light->numInteractions || light->noSort)
 99.1085 +	{
 99.1086 +		return;
 99.1087 +	}
 99.1088 +
 99.1089 +	iaFirst = light->firstInteraction;
 99.1090 +	iaFirstIndex = light->firstInteraction - tr.refdef.interactions;
 99.1091 +
 99.1092 +	// sort by material etc. for geometry batching in the renderer backend
 99.1093 +	qsort(iaFirst, light->numInteractions, sizeof(interaction_t), InteractionCompare);
 99.1094 +
 99.1095 +	// fix linked list
 99.1096 +	iaLast = NULL;
 99.1097 +	for(i = 0; i < light->numInteractions; i++)
 99.1098 +	{
 99.1099 +		ia = &tr.refdef.interactions[iaFirstIndex + i];
 99.1100 +
 99.1101 +		if(iaLast)
 99.1102 +		{
 99.1103 +			iaLast->next = ia;
 99.1104 +		}
 99.1105 +
 99.1106 +		ia->next = NULL;
 99.1107 +
 99.1108 +		iaLast = ia;
 99.1109 +	}
 99.1110 +}
 99.1111 +
 99.1112 +
 99.1113 +/*
 99.1114 +=================
 99.1115 +R_IntersectRayPlane
 99.1116 +=================
 99.1117 +*/
 99.1118 +static void R_IntersectRayPlane(const vec3_t v1, const vec3_t v2, cplane_t * plane, vec3_t res)
 99.1119 +{
 99.1120 +	vec3_t          v;
 99.1121 +	float           sect;
 99.1122 +
 99.1123 +	VectorSubtract(v1, v2, v);
 99.1124 +	sect = -(DotProduct(plane->normal, v1) - plane->dist) / DotProduct(plane->normal, v);
 99.1125 +	VectorScale(v, sect, v);
 99.1126 +	VectorAdd(v1, v, res);
 99.1127 +}
 99.1128 +
 99.1129 +
 99.1130 +/*
 99.1131 +=================
 99.1132 +R_AddPointToLightScissor
 99.1133 +=================
 99.1134 +*/
 99.1135 +static void R_AddPointToLightScissor(trRefLight_t * light, const vec3_t world)
 99.1136 +{
 99.1137 +	vec4_t          eye, clip, normalized, window;
 99.1138 +
 99.1139 +	R_TransformWorldToClip(world, tr.viewParms.world.viewMatrix, tr.viewParms.projectionMatrix, eye, clip);
 99.1140 +	R_TransformClipToWindow(clip, &tr.viewParms, normalized, window);
 99.1141 +
 99.1142 +	if(window[0] > light->scissor.coords[2])
 99.1143 +		light->scissor.coords[2] = (int)window[0];
 99.1144 +
 99.1145 +	if(window[0] < light->scissor.coords[0])
 99.1146 +		light->scissor.coords[0] = (int)window[0];
 99.1147 +
 99.1148 +	if(window[1] > light->scissor.coords[3])
 99.1149 +		light->scissor.coords[3] = (int)window[1];
 99.1150 +
 99.1151 +	if(window[1] < light->scissor.coords[1])
 99.1152 +		light->scissor.coords[1] = (int)window[1];
 99.1153 +}
 99.1154 +
 99.1155 +/*
 99.1156 +=================
 99.1157 +R_AddEdgeToLightScissor
 99.1158 +=================
 99.1159 +*/
 99.1160 +static void R_AddEdgeToLightScissor(trRefLight_t * light, vec3_t local1, vec3_t local2)
 99.1161 +{
 99.1162 +	int             i;
 99.1163 +	vec3_t          intersect;
 99.1164 +	vec3_t          world1, world2;
 99.1165 +	qboolean        side1, side2;
 99.1166 +	cplane_t       *frust;
 99.1167 +
 99.1168 +	for(i = 0; i < FRUSTUM_PLANES; i++)
 99.1169 +	{
 99.1170 +		R_LocalPointToWorld(local1, world1);
 99.1171 +		R_LocalPointToWorld(local2, world2);
 99.1172 +
 99.1173 +		frust = &tr.viewParms.frustum[i];
 99.1174 +
 99.1175 +		// check edge to frustrum plane
 99.1176 +		side1 = ((DotProduct(frust->normal, world1) - frust->dist) >= 0.0);
 99.1177 +		side2 = ((DotProduct(frust->normal, world2) - frust->dist) >= 0.0);
 99.1178 +
 99.1179 +		if(glConfig.occlusionQueryAvailable && i == FRUSTUM_NEAR)
 99.1180 +		{
 99.1181 +			if(!side1 || !side2)
 99.1182 +			{
 99.1183 +				light->noOcclusionQueries = qtrue;
 99.1184 +			}
 99.1185 +		}
 99.1186 +
 99.1187 +		if(!side1 && !side2)
 99.1188 +			continue;			// edge behind plane
 99.1189 +
 99.1190 +		if(!side1 || !side2)
 99.1191 +			R_IntersectRayPlane(world1, world2, frust, intersect);
 99.1192 +
 99.1193 +		if(!side1)
 99.1194 +		{
 99.1195 +			VectorCopy(intersect, world1);
 99.1196 +		}
 99.1197 +		else if(!side2)
 99.1198 +		{
 99.1199 +			VectorCopy(intersect, world2);
 99.1200 +		}
 99.1201 +
 99.1202 +		R_AddPointToLightScissor(light, world1);
 99.1203 +		R_AddPointToLightScissor(light, world2);
 99.1204 +	}
 99.1205 +}
 99.1206 +
 99.1207 +/*
 99.1208 +=================
 99.1209 +R_SetLightScissor
 99.1210 +Recturns the screen space rectangle taken by the box.
 99.1211 +	(Clips the box to the near plane to have correct results even if the box intersects the near plane)
 99.1212 +Tr3B - recoded from Tenebrae2
 99.1213 +=================
 99.1214 +*/
 99.1215 +void R_SetupLightScissor(trRefLight_t * light)
 99.1216 +{
 99.1217 +	vec3_t          v1, v2;
 99.1218 +
 99.1219 +	light->scissor.coords[0] = tr.viewParms.viewportX;
 99.1220 +	light->scissor.coords[1] = tr.viewParms.viewportY;
 99.1221 +	light->scissor.coords[2] = tr.viewParms.viewportX + tr.viewParms.viewportWidth;
 99.1222 +	light->scissor.coords[3] = tr.viewParms.viewportY + tr.viewParms.viewportHeight;
 99.1223 +
 99.1224 +	if(glConfig.occlusionQueryAvailable)
 99.1225 +	{
 99.1226 +		light->noOcclusionQueries = qfalse;
 99.1227 +	}
 99.1228 +
 99.1229 +	if(r_noLightScissors->integer || R_CullLightPoint(light, tr.viewParms.orientation.origin) == CULL_IN)
 99.1230 +	{
 99.1231 +		if(glConfig.occlusionQueryAvailable)
 99.1232 +		{
 99.1233 +			light->noOcclusionQueries = qtrue;
 99.1234 +		}
 99.1235 +		return;
 99.1236 +	}
 99.1237 +
 99.1238 +	// transform local light corners to world space -> eye space -> clip space -> window space
 99.1239 +	// and extend the light scissor's mins maxs by resulting window coords
 99.1240 +	light->scissor.coords[0] = 100000000;
 99.1241 +	light->scissor.coords[1] = 100000000;
 99.1242 +	light->scissor.coords[2] = -100000000;
 99.1243 +	light->scissor.coords[3] = -100000000;
 99.1244 +
 99.1245 +	switch (light->l.rlType)
 99.1246 +	{
 99.1247 +		case RL_OMNI:
 99.1248 +		{
 99.1249 +			// top plane
 99.1250 +			VectorSet(v1, light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2]);
 99.1251 +			VectorSet(v2, light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2]);
 99.1252 +			R_AddEdgeToLightScissor(light, v1, v2);
 99.1253 +
 99.1254 +			VectorSet(v1, light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2]);
 99.1255 +			VectorSet(v2, light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2]);
 99.1256 +			R_AddEdgeToLightScissor(light, v1, v2);
 99.1257 +
 99.1258 +			VectorSet(v1, light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2]);
 99.1259 +			VectorSet(v2, light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2]);
 99.1260 +			R_AddEdgeToLightScissor(light, v1, v2);
 99.1261 +
 99.1262 +			VectorSet(v1, light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2]);
 99.1263 +			VectorSet(v2, light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2]);
 99.1264 +			R_AddEdgeToLightScissor(light, v1, v2);
 99.1265 +
 99.1266 +			// bottom plane
 99.1267 +			VectorSet(v1, light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2]);
 99.1268 +			VectorSet(v2, light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2]);
 99.1269 +			R_AddEdgeToLightScissor(light, v1, v2);
 99.1270 +
 99.1271 +			VectorSet(v1, light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2]);
 99.1272 +			VectorSet(v2, light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2]);
 99.1273 +			R_AddEdgeToLightScissor(light, v1, v2);
 99.1274 +
 99.1275 +			VectorSet(v1, light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2]);
 99.1276 +			VectorSet(v2, light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2]);
 99.1277 +			R_AddEdgeToLightScissor(light, v1, v2);
 99.1278 +
 99.1279 +			VectorSet(v1, light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2]);
 99.1280 +			VectorSet(v2, light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2]);
 99.1281 +			R_AddEdgeToLightScissor(light, v1, v2);
 99.1282 +
 99.1283 +			// sides
 99.1284 +			VectorSet(v1, light->localBounds[0][0], light->localBounds[1][1], light->localBounds[0][2]);
 99.1285 +			VectorSet(v2, light->localBounds[0][0], light->localBounds[1][1], light->localBounds[1][2]);
 99.1286 +			R_AddEdgeToLightScissor(light, v1, v2);
 99.1287 +
 99.1288 +			VectorSet(v1, light->localBounds[1][0], light->localBounds[1][1], light->localBounds[0][2]);
 99.1289 +			VectorSet(v2, light->localBounds[1][0], light->localBounds[1][1], light->localBounds[1][2]);
 99.1290 +			R_AddEdgeToLightScissor(light, v1, v2);
 99.1291 +
 99.1292 +			VectorSet(v1, light->localBounds[0][0], light->localBounds[0][1], light->localBounds[0][2]);
 99.1293 +			VectorSet(v2, light->localBounds[0][0], light->localBounds[0][1], light->localBounds[1][2]);
 99.1294 +			R_AddEdgeToLightScissor(light, v1, v2);
 99.1295 +
 99.1296 +			VectorSet(v1, light->localBounds[1][0], light->localBounds[0][1], light->localBounds[0][2]);
 99.1297 +			VectorSet(v2, light->localBounds[1][0], light->localBounds[0][1], light->localBounds[1][2]);
 99.1298 +			R_AddEdgeToLightScissor(light, v1, v2);
 99.1299 +			break;
 99.1300 +		}
 99.1301 +
 99.1302 +		case RL_PROJ:
 99.1303 +		{
 99.1304 +			int             j;
 99.1305 +			float           xMin, xMax, yMin, yMax;
 99.1306 +			float           zNear, zFar;
 99.1307 +			vec3_t          corners[4];
 99.1308 +
 99.1309 +			zNear = light->l.distNear;
 99.1310 +			zFar = light->l.distFar;
 99.1311 +
 99.1312 +			xMax = zNear * tan(light->l.fovX * M_PI / 360.0f);
 99.1313 +			xMin = -xMax;
 99.1314 +
 99.1315 +			yMax = zNear * tan(light->l.fovY * M_PI / 360.0f);
 99.1316 +			yMin = -yMax;
 99.1317 +
 99.1318 +			corners[0][0] = zFar;
 99.1319 +			corners[0][1] = xMin * zFar;
 99.1320 +			corners[0][2] = yMin * zFar;
 99.1321 +
 99.1322 +			corners[1][0] = zFar;
 99.1323 +			corners[1][1] = xMax * zFar;
 99.1324 +			corners[1][2] = yMin * zFar;
 99.1325 +
 99.1326 +			corners[2][0] = zFar;
 99.1327 +			corners[2][1] = xMax * zFar;
 99.1328 +			corners[2][2] = yMax * zFar;
 99.1329 +
 99.1330 +			corners[3][0] = zFar;
 99.1331 +			corners[3][1] = xMin * zFar;
 99.1332 +			corners[3][2] = yMax * zFar;
 99.1333 +
 99.1334 +			// draw pyramid
 99.1335 +			for(j = 0; j < 4; j++)
 99.1336 +			{
 99.1337 +				R_AddEdgeToLightScissor(light, corners[j], corners[(j + 1) % 4]);
 99.1338 +				R_AddEdgeToLightScissor(light, vec3_origin, corners[j]);
 99.1339 +			}
 99.1340 +			break;
 99.1341 +		}
 99.1342 +	}
 99.1343 +}
 99.1344 +
 99.1345 +
 99.1346 +/*
 99.1347 +=================
 99.1348 +R_SetupLightDepthBounds
 99.1349 +=================
 99.1350 +*/
 99.1351 +void R_SetupLightDepthBounds(trRefLight_t * light)
 99.1352 +{
 99.1353 +	int             i, j;
 99.1354 +	vec3_t          v, world;
 99.1355 +	vec4_t          eye, clip, normalized, window;
 99.1356 +	float           depthMin, depthMax;
 99.1357 +
 99.1358 +	if(r_shadows->integer == 3 && qglDepthBoundsEXT)
 99.1359 +	{
 99.1360 +		tr.pc.c_depthBoundsTestsRejected++;
 99.1361 +
 99.1362 +		depthMin = 1.0;
 99.1363 +		depthMax = 0.0;
 99.1364 +
 99.1365 +		for(j = 0; j < 8; j++)
 99.1366 +		{
 99.1367 +			v[0] = light->localBounds[j & 1][0];
 99.1368 +			v[1] = light->localBounds[(j >> 1) & 1][1];
 99.1369 +			v[2] = light->localBounds[(j >> 2) & 1][2];
 99.1370 +
 99.1371 +			// transform local bounds vertices into world space
 99.1372 +			MatrixTransformPoint(light->transformMatrix, v, world);
 99.1373 +			R_TransformWorldToClip(world, tr.viewParms.world.viewMatrix, tr.viewParms.projectionMatrix, eye, clip);
 99.1374 +
 99.1375 +			//R_TransformModelToClip(v, tr.or.modelViewMatrix, tr.viewParms.projectionMatrix, eye, clip);
 99.1376 +
 99.1377 +			// check to see if the point is completely off screen
 99.1378 +			for(i = 0; i < 3; i++)
 99.1379 +			{
 99.1380 +				if(clip[i] >= clip[3] || clip[i] <= -clip[3])
 99.1381 +				{
 99.1382 +					light->noDepthBoundsTest = qtrue;
 99.1383 +					return;
 99.1384 +				}
 99.1385 +			}
 99.1386 +
 99.1387 +			R_TransformClipToWindow(clip, &tr.viewParms, normalized, window);
 99.1388 +
 99.1389 +			if(window[0] < 0 || window[0] >= tr.viewParms.viewportWidth
 99.1390 +			   || window[1] < 0 || window[1] >= tr.viewParms.viewportHeight)
 99.1391 +			{
 99.1392 +				// shouldn't happen, since we check the clip[] above, except for FP rounding
 99.1393 +				light->noDepthBoundsTest = qtrue;
 99.1394 +				return;
 99.1395 +			}
 99.1396 +
 99.1397 +			depthMin = min(normalized[2], depthMin);
 99.1398 +			depthMax = max(normalized[2], depthMax);
 99.1399 +		}
 99.1400 +
 99.1401 +		if(depthMin > depthMax)
 99.1402 +		{
 99.1403 +			// light behind near plane or clipped
 99.1404 +			light->noDepthBoundsTest = qtrue;
 99.1405 +		}
 99.1406 +		else
 99.1407 +		{
 99.1408 +			light->noDepthBoundsTest = qfalse;
 99.1409 +			light->depthNear = depthMin;
 99.1410 +			light->depthFar = depthMax;
 99.1411 +
 99.1412 +			tr.pc.c_depthBoundsTestsRejected--;
 99.1413 +			tr.pc.c_depthBoundsTests++;
 99.1414 +		}
 99.1415 +	}
 99.1416 +}
 99.1417 +
 99.1418 +/*
 99.1419 +=============
 99.1420 +R_CalcLightCubeSideBits
 99.1421 +=============
 99.1422 +*/
 99.1423 +// *INDENT-OFF*
 99.1424 +byte R_CalcLightCubeSideBits(trRefLight_t * light, vec3_t worldBounds[2])
 99.1425 +{
 99.1426 +	int             i;
 99.1427 +	int             cubeSide;
 99.1428 +	byte            cubeSideBits;
 99.1429 +	float           xMin, xMax, yMin, yMax;
 99.1430 +	float           width, height, depth;
 99.1431 +	float           zNear, zFar;
 99.1432 +	float           fovX, fovY;
 99.1433 +	float          *proj;
 99.1434 +	vec3_t          angles;
 99.1435 +	matrix_t        tmpMatrix, rotationMatrix, transformMatrix, viewMatrix, modelViewMatrix, projectionMatrix;
 99.1436 +	frustum_t       frustum;
 99.1437 +	cplane_t       *clipPlane;
 99.1438 +	int             r;
 99.1439 +	qboolean        anyClip;
 99.1440 +	qboolean		culled;
 99.1441 +
 99.1442 +#if 0
 99.1443 +	static int		count = 0;
 99.1444 +	cubeSideBits = 0;
 99.1445 +	for(cubeSide = 0; cubeSide < 6; cubeSide++)
 99.1446 +	{
 99.1447 +		if(count % 2 == 0)
 99.1448 +		{
 99.1449 +			cubeSideBits |= (1 << cubeSide);
 99.1450 +		}
 99.1451 +	}
 99.1452 +	return cubeSideBits;
 99.1453 +#endif
 99.1454 +
 99.1455 +	if(light->l.rlType != RL_OMNI || r_shadows->integer < 4 || r_noShadowPyramids->integer)
 99.1456 +		return CUBESIDE_CLIPALL;
 99.1457 +
 99.1458 +	cubeSideBits = 0;
 99.1459 +	for(cubeSide = 0; cubeSide < 6; cubeSide++)
 99.1460 +	{
 99.1461 +		switch (cubeSide)
 99.1462 +		{
 99.1463 +			case 0:
 99.1464 +			{
 99.1465 +				// view parameters
 99.1466 +				VectorSet(angles, 0, 0, 0);
 99.1467 +				break;
 99.1468 +			}
 99.1469 +
 99.1470 +			case 1:
 99.1471 +			{
 99.1472 +				VectorSet(angles, 0, 180, 0);
 99.1473 +				break;
 99.1474 +			}
 99.1475 +
 99.1476 +			case 2:
 99.1477 +			{
 99.1478 +				VectorSet(angles, 0, 90, 0);
 99.1479 +				break;
 99.1480 +			}
 99.1481 +
 99.1482 +			case 3:
 99.1483 +			{
 99.1484 +				VectorSet(angles, 0, 270, 0);
 99.1485 +				break;
 99.1486 +			}
 99.1487 +
 99.1488 +			case 4:
 99.1489 +			{
 99.1490 +				VectorSet(angles, -90, 0, 0);
 99.1491 +				break;
 99.1492 +			}
 99.1493 +
 99.1494 +			case 5:
 99.1495 +			{
 99.1496 +				VectorSet(angles, 90, 0, 0);
 99.1497 +				break;
 99.1498 +			}
 99.1499 +
 99.1500 +			default:
 99.1501 +			{
 99.1502 +				// shut up compiler
 99.1503 +				VectorSet(angles, 0, 0, 0);
 99.1504 +				break;
 99.1505 +			}
 99.1506 +		}
 99.1507 +
 99.1508 +		// Quake -> OpenGL view matrix from light perspective
 99.1509 +		MatrixFromAngles(rotationMatrix, angles[PITCH], angles[YAW], angles[ROLL]);
 99.1510 +		MatrixSetupTransformFromRotation(transformMatrix, rotationMatrix, light->origin);
 99.1511 +		MatrixAffineInverse(transformMatrix, tmpMatrix);
 99.1512 +
 99.1513 +		// convert from our coordinate system (looking down X)
 99.1514 +		// to OpenGL's coordinate system (looking down -Z)
 99.1515 +		MatrixMultiply(quakeToOpenGLMatrix, tmpMatrix, viewMatrix);
 99.1516 +		MatrixCopy(viewMatrix, modelViewMatrix); // because world transform is the identity matrix
 99.1517 +
 99.1518 +		// OpenGL projection matrix
 99.1519 +		fovX = 90;
 99.1520 +		fovY = 90; //R_CalcFov(fovX, shadowMapResolutions[light->shadowLOD], shadowMapResolutions[light->shadowLOD]);
 99.1521 +
 99.1522 +		zNear = 1.0;
 99.1523 +		zFar = light->sphereRadius;
 99.1524 +
 99.1525 +		xMax = zNear * tan(fovX * M_PI / 360.0f);
 99.1526 +		xMin = -xMax;
 99.1527 +
 99.1528 +		yMax = zNear * tan(fovY * M_PI / 360.0f);
 99.1529 +		yMin = -yMax;
 99.1530 +
 99.1531 +		width = xMax - xMin;
 99.1532 +		height = yMax - yMin;
 99.1533 +		depth = zFar - zNear;
 99.1534 +
 99.1535 +		proj = projectionMatrix;
 99.1536 +		proj[0] = (2 * zNear) / width;	proj[4] = 0;					proj[8] = (xMax + xMin) / width;	proj[12] = 0;
 99.1537 +		proj[1] = 0;					proj[5] = (2 * zNear) / height;	proj[9] = (yMax + yMin) / height;	proj[13] = 0;
 99.1538 +		proj[2] = 0;					proj[6] = 0;					proj[10] = -(zFar + zNear) / depth;	proj[14] = -(2 * zFar * zNear) / depth;
 99.1539 +		proj[3] = 0;					proj[7] = 0;					proj[11] = -1;						proj[15] = 0;
 99.1540 +
 99.1541 +		// calculate frustum planes using the modelview projection matrix
 99.1542 +		R_SetupFrustum(frustum, modelViewMatrix, projectionMatrix);
 99.1543 +
 99.1544 +		// use the frustum planes to cut off shadowmaps beyond the light volume
 99.1545 +		anyClip = qfalse;
 99.1546 +		culled = qfalse;
 99.1547 +		for(i = 0; i < 5; i++)
 99.1548 +		{
 99.1549 +			clipPlane = &frustum[i];
 99.1550 +
 99.1551 +			r = BoxOnPlaneSide(worldBounds[0], worldBounds[1], clipPlane);
 99.1552 +			if(r == 2)
 99.1553 +			{
 99.1554 +				culled = qtrue;
 99.1555 +				break;
 99.1556 +			}
 99.1557 +			if(r == 3)
 99.1558 +			{
 99.1559 +				anyClip = qtrue;
 99.1560 +			}
 99.1561 +		}
 99.1562 +
 99.1563 +		if(!culled)
 99.1564 +		{
 99.1565 +			if(!anyClip)
 99.1566 +			{
 99.1567 +				// completely inside frustum
 99.1568 +				tr.pc.c_pyramid_cull_ent_in++;
 99.1569 +			}
 99.1570 +			else
 99.1571 +			{
 99.1572 +				// partially clipped
 99.1573 +				tr.pc.c_pyramid_cull_ent_clip++;
 99.1574 +			}
 99.1575 +
 99.1576 +			cubeSideBits |= (1 << cubeSide);
 99.1577 +		}
 99.1578 +		else
 99.1579 +		{
 99.1580 +			// completely outside frustum
 99.1581 +			tr.pc.c_pyramid_cull_ent_out++;
 99.1582 +		}
 99.1583 +	}
 99.1584 +
 99.1585 +	tr.pc.c_pyramidTests++;
 99.1586 +
 99.1587 +	return cubeSideBits;
 99.1588 +}
 99.1589 +// *INDENT-ON*
 99.1590 +
 99.1591 +
 99.1592 +/*
 99.1593 +=================
 99.1594 +R_SetupLightLOD
 99.1595 +=================
 99.1596 +*/
 99.1597 +void R_SetupLightLOD(trRefLight_t * light)
 99.1598 +{
 99.1599 +	float           radius;
 99.1600 +	float           flod, lodscale;
 99.1601 +	float           projectedRadius;
 99.1602 +	int             lod;
 99.1603 +	int             numLods;
 99.1604 +
 99.1605 +	numLods = 5;
 99.1606 +
 99.1607 +	// compute projected bounding sphere
 99.1608 +	// and use that as a criteria for selecting LOD
 99.1609 +	radius = light->sphereRadius;
 99.1610 +
 99.1611 +	if((projectedRadius = R_ProjectRadius(radius, light->l.origin)) != 0)
 99.1612 +	{
 99.1613 +		lodscale = r_shadowLodScale->value;
 99.1614 +
 99.1615 +		if(lodscale > 20)
 99.1616 +			lodscale = 20;
 99.1617 +
 99.1618 +		flod = 1.0f - projectedRadius * lodscale;
 99.1619 +	}
 99.1620 +	else
 99.1621 +	{
 99.1622 +		// object intersects near view plane, e.g. view weapon
 99.1623 +		flod = 0;
 99.1624 +	}
 99.1625 +
 99.1626 +	flod *= numLods;
 99.1627 +	lod = Q_ftol(flod);
 99.1628 +
 99.1629 +	if(lod < 0)
 99.1630 +	{
 99.1631 +		lod = 0;
 99.1632 +	}
 99.1633 +	else if(lod >= numLods)
 99.1634 +	{
 99.1635 +		//lod = numLods - 1;
 99.1636 +	}
 99.1637 +
 99.1638 +	lod += r_shadowLodBias->integer;
 99.1639 +
 99.1640 +	if(lod < 0)
 99.1641 +	{
 99.1642 +		lod = 0;
 99.1643 +	}
 99.1644 +
 99.1645 +	if(lod >= numLods)
 99.1646 +	{
 99.1647 +		// don't draw any shadow
 99.1648 +		lod = -1;
 99.1649 +
 99.1650 +		//lod = numLods - 1;
 99.1651 +	}
 99.1652 +
 99.1653 +	// never give ultra quality for point lights
 99.1654 +	if(lod == 0 && light->l.rlType == RL_OMNI)
 99.1655 +		lod = 1;
 99.1656 +
 99.1657 +	light->shadowLOD = lod;
 99.1658 +}
 99.1659 +
 99.1660 +
 99.1661 +/*
 99.1662 +=================
 99.1663 +R_SetupLightShader
 99.1664 +=================
 99.1665 +*/
 99.1666 +void R_SetupLightShader(trRefLight_t * light)
 99.1667 +{
 99.1668 +	if(!light->l.attenuationShader)
 99.1669 +	{
 99.1670 +		if(light->isStatic)
 99.1671 +		{
 99.1672 +			switch (light->l.rlType)
 99.1673 +			{
 99.1674 +				default:
 99.1675 +				case RL_OMNI:
 99.1676 +					light->shader = tr.defaultPointLightShader;
 99.1677 +					break;
 99.1678 +
 99.1679 +				case RL_PROJ:
 99.1680 +					light->shader = tr.defaultProjectedLightShader;
 99.1681 +					break;
 99.1682 +			}
 99.1683 +		}
 99.1684 +		else
 99.1685 +		{
 99.1686 +			switch (light->l.rlType)
 99.1687 +			{
 99.1688 +				default:
 99.1689 +				case RL_OMNI:
 99.1690 +					light->shader = tr.defaultDynamicLightShader;
 99.1691 +					break;
 99.1692 +
 99.1693 +				case RL_PROJ:
 99.1694 +					light->shader = tr.defaultProjectedLightShader;
 99.1695 +					break;
 99.1696 +			}
 99.1697 +		}
 99.1698 +	}
 99.1699 +	else
 99.1700 +	{
 99.1701 +		light->shader = R_GetShaderByHandle(light->l.attenuationShader);
 99.1702 +	}
 99.1703 +}
 99.1704 +
 99.1705 +/*
 99.1706 +===============
 99.1707 +R_ComputeFinalAttenuation
 99.1708 +===============
 99.1709 +*/
 99.1710 +void R_ComputeFinalAttenuation(shaderStage_t * pStage, trRefLight_t * light)
 99.1711 +{
 99.1712 +	matrix_t        matrix;
 99.1713 +
 99.1714 +	GLimp_LogComment("--- R_ComputeFinalAttenuation ---\n");
 99.1715 +
 99.1716 +	RB_CalcTexMatrix(&pStage->bundle[TB_COLORMAP], matrix);
 99.1717 +
 99.1718 +	MatrixMultiply(matrix, light->attenuationMatrix, light->attenuationMatrix2);
 99.1719 +}
 99.1720 +
 99.1721 +/*
 99.1722 +=================
 99.1723 +R_CullLightPoint
 99.1724 +
 99.1725 +Returns CULL_IN, CULL_CLIP, or CULL_OUT
 99.1726 +=================
 99.1727 +*/
 99.1728 +int R_CullLightPoint(trRefLight_t * light, const vec3_t p)
 99.1729 +{
 99.1730 +	int             i;
 99.1731 +	cplane_t       *frust;
 99.1732 +	float           dist;
 99.1733 +
 99.1734 +	// check against frustum planes
 99.1735 +	for(i = 0; i < 6; i++)
 99.1736 +	{
 99.1737 +		frust = &light->frustum[i];
 99.1738 +
 99.1739 +		dist = DotProduct(p, frust->normal) - frust->dist;
 99.1740 +		if(dist < 0)
 99.1741 +		{
 99.1742 +			// completely outside frustum
 99.1743 +			return CULL_OUT;
 99.1744 +		}
 99.1745 +	}
 99.1746 +
 99.1747 +	// completely inside frustum
 99.1748 +	return CULL_IN;
 99.1749 +}
 99.1750 +
 99.1751 +/*
 99.1752 +=================
 99.1753 +R_CullLightTriangle
 99.1754 +
 99.1755 +Returns CULL_IN, CULL_CLIP, or CULL_OUT
 99.1756 +=================
 99.1757 +*/
 99.1758 +int R_CullLightTriangle(trRefLight_t * light, vec3_t verts[3])
 99.1759 +{
 99.1760 +	int             i;
 99.1761 +	vec3_t          worldBounds[2];
 99.1762 +
 99.1763 +	if(r_nocull->integer)
 99.1764 +	{
 99.1765 +		return CULL_CLIP;
 99.1766 +	}
 99.1767 +
 99.1768 +	// calc AABB of the triangle
 99.1769 +	ClearBounds(worldBounds[0], worldBounds[1]);
 99.1770 +	for(i = 0; i < 3; i++)
 99.1771 +	{
 99.1772 +		AddPointToBounds(verts[i], worldBounds[0], worldBounds[1]);
 99.1773 +	}
 99.1774 +
 99.1775 +	return R_CullLightWorldBounds(light, worldBounds);
 99.1776 +}
 99.1777 +
 99.1778 +/*
 99.1779 +=================
 99.1780 +R_CullLightTriangle
 99.1781 +
 99.1782 +Returns CULL_IN, CULL_CLIP, or CULL_OUT
 99.1783 +=================
 99.1784 +*/
 99.1785 +int R_CullLightWorldBounds(trRefLight_t * light, vec3_t worldBounds[2])
 99.1786 +{
 99.1787 +	int             i;
 99.1788 +	cplane_t       *frust;
 99.1789 +	qboolean        anyClip;
 99.1790 +	int             r;
 99.1791 +
 99.1792 +	if(r_nocull->integer)
 99.1793 +	{
 99.1794 +		return CULL_CLIP;
 99.1795 +	}
 99.1796 +
 99.1797 +	// check against frustum planes
 99.1798 +	anyClip = qfalse;
 99.1799 +	for(i = 0; i < 6; i++)
 99.1800 +	{
 99.1801 +		frust = &light->frustum[i];
 99.1802 +
 99.1803 +		r = BoxOnPlaneSide(worldBounds[0], worldBounds[1], frust);
 99.1804 +
 99.1805 +		if(r == 2)
 99.1806 +		{
 99.1807 +			// completely outside frustum
 99.1808 +			return CULL_OUT;
 99.1809 +		}
 99.1810 +		if(r == 3)
 99.1811 +		{
 99.1812 +			anyClip = qtrue;
 99.1813 +		}
 99.1814 +	}
 99.1815 +
 99.1816 +	if(!anyClip)
 99.1817 +	{
 99.1818 +		// completely inside frustum
 99.1819 +		return CULL_IN;
 99.1820 +	}
 99.1821 +
 99.1822 +	// partially clipped
 99.1823 +	return CULL_CLIP;
 99.1824 +}
   100.1 --- a/src/renderer/tr_local.h	Sat Jun 06 03:54:16 2009 +0800
   100.2 +++ b/src/renderer/tr_local.h	Wed Jun 10 09:31:46 2009 +0800
   100.3 @@ -1,27 +1,26 @@
   100.4  /*
   100.5  ===========================================================================
   100.6  Copyright (C) 1999-2005 Id Software, Inc.
   100.7 -Copyright (C) 2000-2006 Tim Angus
   100.8 -
   100.9 -This file is part of Tremfusion.
  100.10 -
  100.11 -Tremfusion is free software; you can redistribute it
  100.12 +Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
  100.13 +
  100.14 +This file is part of XreaL source code.
  100.15 +
  100.16 +XreaL source code is free software; you can redistribute it
  100.17  and/or modify it under the terms of the GNU General Public License as
  100.18  published by the Free Software Foundation; either version 2 of the License,
  100.19  or (at your option) any later version.
  100.20  
  100.21 -Tremfusion is distributed in the hope that it will be
  100.22 +XreaL source code is distributed in the hope that it will be
  100.23  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  100.24  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  100.25  GNU General Public License for more details.
  100.26  
  100.27  You should have received a copy of the GNU General Public License
  100.28 -along with Tremfusion; if not, write to the Free Software
  100.29 +along with XreaL source code; if not, write to the Free Software
  100.30  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  100.31  ===========================================================================
  100.32  */
  100.33  
  100.34 -
  100.35  #ifndef TR_LOCAL_H
  100.36  #define TR_LOCAL_H
  100.37  
  100.38 @@ -31,131 +30,393 @@
  100.39  #include "tr_public.h"
  100.40  #include "qgl.h"
  100.41  
  100.42 +#define COMPAT_Q3A
  100.43 +
  100.44 +#define Com_Parse COM_Parse
  100.45 +#define Com_ParseExt COM_ParseExt
  100.46 +#define Com_StripExtension COM_StripExtension
  100.47 +#define Com_GetExtension COM_GetExtension
  100.48 +#define Com_DefaultExtension COM_DefaultExtension
  100.49 +#define Com_SkipPath COM_SkipPath
  100.50 +#define Com_Compress COM_Compress
  100.51 +#define Com_BeginParseSession COM_BeginParseSession
  100.52 +#define Com_ParseWarning COM_ParseWarning
  100.53 +#define Com_SkipBracedSection SkipBracedSection
  100.54 +#define Com_SkipRestOfLine SkipRestOfLine
  100.55 +#define min MIN
  100.56 +#define max MAX
  100.57 +
  100.58 +#define PlaneFromPoints(p, a, b, c, cw) PlaneFromPoints(p, a, b, c)
  100.59 +
  100.60 +#undef VectorLerp
  100.61 +static ID_INLINE void VectorLerp(const vec3_t from, const vec3_t to, float frac, vec3_t out)
  100.62 +{
  100.63 +	out[0] = from[0] + ((to[0] - from[0]) * frac);
  100.64 +	out[1] = from[1] + ((to[1] - from[1]) * frac);
  100.65 +	out[2] = from[2] + ((to[2] - from[2]) * frac);
  100.66 +}
  100.67 +
  100.68 +#if 1
  100.69  #define GL_INDEX_TYPE		GL_UNSIGNED_INT
  100.70  typedef unsigned int glIndex_t;
  100.71 -
  100.72 -// fast float to int conversion
  100.73 -#if id386 && !defined(__GNUC__)
  100.74 -long myftol( float f );
  100.75  #else
  100.76 -#define	myftol(x) ((int)(x))
  100.77 +#define GL_INDEX_TYPE		GL_UNSIGNED_SHORT
  100.78 +typedef unsigned short glIndex_t;
  100.79  #endif
  100.80  
  100.81 +#define BUFFER_OFFSET(i) ((char *)NULL + (i))
  100.82  
  100.83  // everything that is needed by the backend needs
  100.84  // to be double buffered to allow it to run in
  100.85  // parallel on a dual cpu machine
  100.86  #define	SMP_FRAMES		2
  100.87  
  100.88 -// 12 bits
  100.89 -// see QSORT_SHADERNUM_SHIFT
  100.90 -#define	MAX_SHADERS				16384
  100.91 +#define	MAX_SHADERS				(1 << 12)
  100.92 +#define SHADERS_MASK			(MAX_SHADERS -1)
  100.93 +
  100.94 +#define MAX_SHADER_TABLES		1024
  100.95 +#define MAX_SHADER_STAGES		16
  100.96  
  100.97  //#define MAX_SHADER_STATES 2048
  100.98  #define MAX_STATES_PER_SHADER 32
  100.99  #define MAX_STATE_NAME 32
 100.100  
 100.101 -// can't be increased without changing bit packing for drawsurfs
 100.102 -
 100.103 -
 100.104 -typedef struct dlight_s {
 100.105 -	vec3_t	origin;
 100.106 -	vec3_t	color;				// range from 0.0 to 1.0, should be color normalized
 100.107 -	float	radius;
 100.108 -
 100.109 -	vec3_t	transformed;		// origin in local coordinate system
 100.110 -	int		additive;			// texture detail is lost tho when the lightmap is dark
 100.111 -} dlight_t;
 100.112 +#define MAX_OCCLUSION_QUERIES	128
 100.113 +
 100.114 +#define	MAX_FBOS				64
 100.115 +
 100.116 +#define MAX_VISCOUNTS			5
 100.117 +
 100.118 +//#define VOLUMETRIC_LIGHTING
 100.119 +
 100.120 +#define DEBUG_OPTIMIZEVERTICES 0
 100.121 +#define CALC_REDUNDANT_SHADOWVERTS 0
 100.122 +
 100.123 +#define REF_CUBEMAP_SIZE		64
 100.124 +
 100.125 +typedef enum
 100.126 +{
 100.127 +	CULL_IN,					// completely unclipped
 100.128 +	CULL_CLIP,					// clipped by one or more planes
 100.129 +	CULL_OUT,					// completely outside the clipping planes
 100.130 +} cullResult_t;
 100.131 +
 100.132 +typedef struct screenRect_s
 100.133 +{
 100.134 +	int             coords[4];
 100.135 +	struct screenRect_s *next;
 100.136 +} screenRect_t;
 100.137 +
 100.138 +typedef enum
 100.139 +{
 100.140 +	FRUSTUM_NEAR,
 100.141 +	FRUSTUM_LEFT,
 100.142 +	FRUSTUM_RIGHT,
 100.143 +	FRUSTUM_BOTTOM,
 100.144 +	FRUSTUM_TOP,
 100.145 +	FRUSTUM_FAR,
 100.146 +	FRUSTUM_PLANES = 5,
 100.147 +	FRUSTUM_CLIPALL = 1 | 2 | 4 | 8 | 16	//| 32
 100.148 +} frustumBits_t;
 100.149 +
 100.150 +typedef cplane_t frustum_t[6];
 100.151 +
 100.152 +enum
 100.153 +{
 100.154 +	CUBESIDE_PX = (1 << 0),
 100.155 +	CUBESIDE_PY = (1 << 1),
 100.156 +	CUBESIDE_PZ = (1 << 2),
 100.157 +	CUBESIDE_NX = (1 << 3),
 100.158 +	CUBESIDE_NY = (1 << 4),
 100.159 +	CUBESIDE_NZ = (1 << 5),
 100.160 +	CUBESIDE_CLIPALL = 1 | 2 | 4 | 8 | 16 | 32
 100.161 +};
 100.162 +
 100.163 +
 100.164 +// a trRefLight_t has all the information passed in by
 100.165 +// the client game, as well as some locally derived info
 100.166 +typedef struct trRefLight_s
 100.167 +{
 100.168 +	// public from client game
 100.169 +	refLight_t      l;
 100.170 +
 100.171 +	// local
 100.172 +	qboolean        isStatic;	// loaded from the BSP entities lump
 100.173 +	qboolean        noRadiosity;	// this is a pure realtime light that was not considered by XMap2
 100.174 +	qboolean        additive;	// texture detail is lost tho when the lightmap is dark
 100.175 +	vec3_t          origin;		// l.origin + rotated l.center
 100.176 +	vec3_t          transformed;	// origin in local coordinate system
 100.177 +	matrix_t        transformMatrix;	// light to world
 100.178 +	matrix_t        viewMatrix;	// object to light
 100.179 +	matrix_t        projectionMatrix;	// light frustum
 100.180 +
 100.181 +	matrix_t        attenuationMatrix;	// attenuation * (light view * entity transform)
 100.182 +	matrix_t        attenuationMatrix2;	// attenuation * tcMod matrices
 100.183 +
 100.184 +	cullResult_t    cull;
 100.185 +	vec3_t          localBounds[2];
 100.186 +	vec3_t          worldBounds[2];
 100.187 +	float           sphereRadius;	// calculated from localBounds
 100.188 +
 100.189 +	int             shadowLOD;	// Level of Detail for shadow mapping
 100.190 +
 100.191 +	// GL_EXT_depth_bounds_test
 100.192 +	float           depthNear;
 100.193 +	float           depthFar;
 100.194 +	qboolean        noDepthBoundsTest;
 100.195 +
 100.196 +	qboolean        noOcclusionQueries;
 100.197 +
 100.198 +	frustum_t       frustum;
 100.199 +
 100.200 +	screenRect_t    scissor;
 100.201 +
 100.202 +	struct shader_s *shader;
 100.203 +
 100.204 +	struct interactionCache_s *firstInteractionCache;	// only used by static lights
 100.205 +	struct interactionCache_s *lastInteractionCache;	// only used by static lights
 100.206 +
 100.207 +	struct interactionVBO_s *firstInteractionVBO;	// only used by static lights
 100.208 +	struct interactionVBO_s *lastInteractionVBO;	// only used by static lights
 100.209 +
 100.210 +	struct interaction_s *firstInteraction;
 100.211 +	struct interaction_s *lastInteraction;
 100.212 +
 100.213 +	int             numInteractions;	// total interactions
 100.214 +	int             numShadowOnlyInteractions;
 100.215 +	int             numLightOnlyInteractions;
 100.216 +	qboolean        noSort;		// don't sort interactions by material
 100.217 +
 100.218 +	int             visCounts[MAX_VISCOUNTS];	// node needs to be traversed if current
 100.219 +	struct bspNode_s **leafs;
 100.220 +	int             numLeafs;
 100.221 +} trRefLight_t;
 100.222  
 100.223  
 100.224  // a trRefEntity_t has all the information passed in by
 100.225  // the client game, as well as some locally derived info
 100.226 -typedef struct {
 100.227 -	refEntity_t	e;
 100.228 -
 100.229 -	float		axisLength;		// compensate for non-normalized axis
 100.230 -
 100.231 -	qboolean	needDlights;	// true for bmodels that touch a dlight
 100.232 -	qboolean	lightingCalculated;
 100.233 -	vec3_t		lightDir;		// normalized direction towards light
 100.234 -	vec3_t		ambientLight;	// color normalized to 0-255
 100.235 -	int			ambientLightInt;	// 32 bit rgba packed
 100.236 -	vec3_t		directedLight;
 100.237 +typedef struct
 100.238 +{
 100.239 +	// public from client game
 100.240 +	refEntity_t     e;
 100.241 +
 100.242 +	// local
 100.243 +	float           axisLength;	// compensate for non-normalized axis
 100.244 +	qboolean        lightingCalculated;
 100.245 +	vec3_t          lightDir;	// normalized direction towards light
 100.246 +	vec3_t          ambientLight;	// color normalized to 0-1
 100.247 +	vec3_t          directedLight;
 100.248 +	qboolean        needZFail;
 100.249 +
 100.250 +	cullResult_t    cull;
 100.251 +	vec3_t          localBounds[2];
 100.252 +	vec3_t          worldBounds[2];	// only set when not completely culled. use them for light interactions
 100.253 +	vec3_t          worldCorners[8];
 100.254  } trRefEntity_t;
 100.255  
 100.256 -
 100.257 -typedef struct {
 100.258 -	vec3_t		origin;			// in world coordinates
 100.259 -	vec3_t		axis[3];		// orientation in world
 100.260 -	vec3_t		viewOrigin;		// viewParms->or.origin in local coordinates
 100.261 -	float		modelMatrix[16];
 100.262 +typedef struct
 100.263 +{
 100.264 +	vec3_t          origin;		// in world coordinates
 100.265 +	vec3_t          axis[3];	// orientation in world
 100.266 +	vec3_t          viewOrigin;	// viewParms->or.origin in local coordinates
 100.267 +	matrix_t        transformMatrix;	// transforms object to world: either used by camera, model or light
 100.268 +	matrix_t        viewMatrix;	// affine inverse of transform matrix to transform other objects into this space
 100.269 +	matrix_t        viewMatrix2;	// without quake2opengl conversion
 100.270 +	matrix_t        modelViewMatrix;	// only used by models, camera viewMatrix * transformMatrix
 100.271  } orientationr_t;
 100.272  
 100.273 -typedef struct image_s {
 100.274 -	char		imgName[MAX_QPATH];		// game path, including extension
 100.275 -	int			width, height;				// source image
 100.276 -	int			uploadWidth, uploadHeight;	// after power of two and picmip but not including clamp to MAX_TEXTURE_SIZE
 100.277 -	GLuint		texnum;					// gl texture binding
 100.278 -
 100.279 -	int			frameUsed;			// for texture usage in frame statistics
 100.280 -
 100.281 -	int			internalFormat;
 100.282 -	int			TMU;				// only needed for voodoo2
 100.283 -
 100.284 -	qboolean	mipmap;
 100.285 -	qboolean	allowPicmip;
 100.286 -	int			wrapClampMode;		// GL_CLAMP_TO_EDGE or GL_REPEAT
 100.287 -
 100.288 -	struct image_s*	next;
 100.289 +// useful helper struct
 100.290 +typedef struct vertexHash_s
 100.291 +{
 100.292 +	vec3_t				xyz;
 100.293 +	void			    *data;
 100.294 +
 100.295 +	struct vertexHash_s	*next;
 100.296 +} vertexHash_t;
 100.297 +
 100.298 +enum
 100.299 +{
 100.300 +	IF_NONE,
 100.301 +	IF_NOPICMIP = BIT(0),
 100.302 +	IF_NOCOMPRESSION = BIT(1),
 100.303 +	IF_INTENSITY = BIT(2),
 100.304 +	IF_ALPHA = BIT(3),
 100.305 +	IF_NORMALMAP = BIT(4),
 100.306 +	IF_RGBA16F = BIT(5),
 100.307 +	IF_RGBA32F = BIT(6),
 100.308 +	IF_LA16F = BIT(7),
 100.309 +	IF_LA32F = BIT(8),
 100.310 +	IF_ALPHA16F = BIT(9),
 100.311 +	IF_ALPHA32F = BIT(10),
 100.312 +	IF_DEPTH16 = BIT(11),
 100.313 +	IF_DEPTH24 = BIT(12),
 100.314 +	IF_DEPTH32 = BIT(13),
 100.315 +	IF_PACKED_DEPTH24_STENCIL8 = BIT(14),
 100.316 +	IF_LIGHTMAP = BIT(15),
 100.317 +	IF_RGBA16 = BIT(16),
 100.318 +	IF_RGBE = BIT(17),
 100.319 +	IF_ALPHATEST = BIT(18),
 100.320 +	IF_DISPLACEMAP = BIT(19)
 100.321 +};
 100.322 +
 100.323 +typedef enum
 100.324 +{
 100.325 +	FT_DEFAULT,
 100.326 +	FT_LINEAR,
 100.327 +	FT_NEAREST
 100.328 +} filterType_t;
 100.329 +
 100.330 +typedef enum
 100.331 +{
 100.332 +	WT_REPEAT,
 100.333 +	WT_CLAMP,					// don't repeat the texture for texture coords outside [0, 1]
 100.334 +	WT_EDGE_CLAMP,
 100.335 +	WT_ZERO_CLAMP,				// guarantee 0,0,0,255 edge for projected textures
 100.336 +	WT_ALPHA_ZERO_CLAMP			// guarante 0 alpha edge for projected textures
 100.337 +} wrapType_t;
 100.338 +
 100.339 +typedef struct image_s
 100.340 +{
 100.341 +	char            name[1024];	// formerly MAX_QPATH, game path, including extension
 100.342 +	// can contain stuff like this now:
 100.343 +	// addnormals ( textures/base_floor/stetile4_local.tga ,
 100.344 +	// heightmap ( textures/base_floor/stetile4_bmp.tga , 4 ) )
 100.345 +	GLenum          type;
 100.346 +	int             width, height;	// source image
 100.347 +	int             uploadWidth, uploadHeight;	// after power of two and picmip but not including clamp to MAX_TEXTURE_SIZE
 100.348 +	GLuint          texnum;		// gl texture binding
 100.349 +
 100.350 +	int             frameUsed;	// for texture usage in frame statistics
 100.351 +
 100.352 +	int             internalFormat;
 100.353 +
 100.354 +	unsigned        bits;
 100.355 +	filterType_t    filterType;
 100.356 +	wrapType_t      wrapType;	// GL_CLAMP or GL_REPEAT
 100.357 +
 100.358 +	struct image_s *next;
 100.359  } image_t;
 100.360  
 100.361 +typedef struct FBO_s
 100.362 +{
 100.363 +	char            name[MAX_QPATH];
 100.364 +
 100.365 +	int             index;
 100.366 +
 100.367 +	GLuint          frameBuffer;
 100.368 +
 100.369 +	GLuint          colorBuffers[16];
 100.370 +	int             colorFormat;
 100.371 +
 100.372 +	GLuint          depthBuffer;
 100.373 +	int             depthFormat;
 100.374 +
 100.375 +	GLuint          stencilBuffer;
 100.376 +	int             stencilFormat;
 100.377 +
 100.378 +	GLuint          packedDepthStencilBuffer;
 100.379 +	int             packedDepthStencilFormat;
 100.380 +
 100.381 +	int             width;
 100.382 +	int             height;
 100.383 +} FBO_t;
 100.384 +
 100.385 +typedef struct VBO_s
 100.386 +{
 100.387 +	char            name[MAX_QPATH];
 100.388 +
 100.389 +	GLuint          vertexesVBO;
 100.390 +	int             vertexesSize;	// amount of memory data allocated for all vertices in bytes
 100.391 +	GLuint          ofsXYZ;
 100.392 +	GLuint          ofsTexCoords;
 100.393 +	GLuint          ofsLightCoords;
 100.394 +	GLuint          ofsTangents;
 100.395 +	GLuint          ofsBinormals;
 100.396 +	GLuint          ofsNormals;
 100.397 +	GLuint          ofsColors;
 100.398 +	GLuint			ofsPaintColors;		// for advanced terrain blending
 100.399 +	GLuint			ofsLightDirections;
 100.400 +	GLuint          ofsBoneIndexes;
 100.401 +	GLuint          ofsBoneWeights;
 100.402 +
 100.403 +	int             attribs;
 100.404 +} VBO_t;
 100.405 +
 100.406 +typedef struct IBO_s
 100.407 +{
 100.408 +	char            name[MAX_QPATH];
 100.409 +
 100.410 +	GLuint          indexesVBO;
 100.411 +	int             indexesSize;	// amount of memory data allocated for all triangles in bytes
 100.412 +//  GLuint          ofsIndexes;
 100.413 +} IBO_t;
 100.414 +
 100.415  //===============================================================================
 100.416  
 100.417 -typedef enum {
 100.418 +typedef enum
 100.419 +{
 100.420  	SS_BAD,
 100.421 -	SS_PORTAL,			// mirrors, portals, viewscreens
 100.422 -	SS_ENVIRONMENT,		// sky box
 100.423 -	SS_OPAQUE,			// opaque
 100.424 -
 100.425 -	SS_DECAL,			// scorch marks, etc.
 100.426 -	SS_SEE_THROUGH,		// ladders, grates, grills that may have small blended edges
 100.427 -						// in addition to alpha test
 100.428 +	SS_PORTAL,					// mirrors, portals, viewscreens
 100.429 +	SS_ENVIRONMENT,				// sky box
 100.430 +	SS_OPAQUE,					// opaque
 100.431 +
 100.432 +	SS_DECAL,					// scorch marks, etc.
 100.433 +	SS_SEE_THROUGH,				// ladders, grates, grills that may have small blended edges
 100.434 +	// in addition to alpha test
 100.435  	SS_BANNER,
 100.436  
 100.437  	SS_FOG,
 100.438  
 100.439 -	SS_UNDERWATER,		// for items that should be drawn in front of the water plane
 100.440 -
 100.441 -	SS_BLEND0,			// regular transparency and filters
 100.442 -	SS_BLEND1,			// generally only used for additive type effects
 100.443 +	SS_UNDERWATER,				// for items that should be drawn in front of the water plane
 100.444 +	SS_WATER,
 100.445 +
 100.446 +	SS_FAR,
 100.447 +	SS_MEDIUM,
 100.448 +	SS_CLOSE,
 100.449 +
 100.450 +	SS_BLEND0,					// regular transparency and filters
 100.451 +	SS_BLEND1,					// generally only used for additive type effects
 100.452  	SS_BLEND2,
 100.453  	SS_BLEND3,
 100.454  
 100.455  	SS_BLEND6,
 100.456 -	SS_STENCIL_SHADOW,
 100.457 -	SS_ALMOST_NEAREST,	// gun smoke puffs
 100.458 -
 100.459 -	SS_NEAREST			// blood blobs
 100.460 +
 100.461 +	SS_ALMOST_NEAREST,			// gun smoke puffs
 100.462 +
 100.463 +	SS_NEAREST,					// blood blobs
 100.464 +	SS_POST_PROCESS
 100.465  } shaderSort_t;
 100.466  
 100.467 -
 100.468 -#define MAX_SHADER_STAGES 8
 100.469 -
 100.470 -typedef enum {
 100.471 +typedef struct shaderTable_s
 100.472 +{
 100.473 +	char            name[MAX_QPATH];
 100.474 +
 100.475 +	int             index;
 100.476 +
 100.477 +	qboolean        clamp;
 100.478 +	qboolean        snap;
 100.479 +
 100.480 +	float          *values;
 100.481 +	int             numValues;
 100.482 +
 100.483 +	struct shaderTable_s *next;
 100.484 +} shaderTable_t;
 100.485 +
 100.486 +typedef enum
 100.487 +{
 100.488  	GF_NONE,
 100.489  
 100.490  	GF_SIN,
 100.491  	GF_SQUARE,
 100.492  	GF_TRIANGLE,
 100.493 -	GF_SAWTOOTH, 
 100.494 -	GF_INVERSE_SAWTOOTH, 
 100.495 +	GF_SAWTOOTH,
 100.496 +	GF_INVERSE_SAWTOOTH,
 100.497  
 100.498  	GF_NOISE
 100.499 -
 100.500  } genFunc_t;
 100.501  
 100.502 -
 100.503 -typedef enum {
 100.504 +typedef enum
 100.505 +{
 100.506  	DEFORM_NONE,
 100.507  	DEFORM_WAVE,
 100.508  	DEFORM_NORMALS,
 100.509 @@ -171,66 +432,137 @@
 100.510  	DEFORM_TEXT4,
 100.511  	DEFORM_TEXT5,
 100.512  	DEFORM_TEXT6,
 100.513 -	DEFORM_TEXT7
 100.514 +	DEFORM_TEXT7,
 100.515 +	DEFORM_SPRITE,
 100.516 +	DEFORM_FLARE
 100.517  } deform_t;
 100.518  
 100.519 -typedef enum {
 100.520 +typedef enum
 100.521 +{
 100.522  	AGEN_IDENTITY,
 100.523 -	AGEN_SKIP,
 100.524  	AGEN_ENTITY,
 100.525  	AGEN_ONE_MINUS_ENTITY,
 100.526  	AGEN_VERTEX,
 100.527  	AGEN_ONE_MINUS_VERTEX,
 100.528 -	AGEN_LIGHTING_SPECULAR,
 100.529  	AGEN_WAVEFORM,
 100.530 -	AGEN_PORTAL,
 100.531 -	AGEN_CONST
 100.532 +	AGEN_CONST,
 100.533 +	AGEN_CUSTOM
 100.534  } alphaGen_t;
 100.535  
 100.536 -typedef enum {
 100.537 +typedef enum
 100.538 +{
 100.539  	CGEN_BAD,
 100.540 -	CGEN_IDENTITY_LIGHTING,	// tr.identityLight
 100.541 -	CGEN_IDENTITY,			// always (1,1,1,1)
 100.542 -	CGEN_ENTITY,			// grabbed from entity's modulate field
 100.543 -	CGEN_ONE_MINUS_ENTITY,	// grabbed from 1 - entity.modulate
 100.544 -	CGEN_EXACT_VERTEX,		// tess.vertexColors
 100.545 -	CGEN_VERTEX,			// tess.vertexColors * tr.identityLight
 100.546 +	CGEN_IDENTITY_LIGHTING,		// tr.identityLight
 100.547 +	CGEN_IDENTITY,				// always (1,1,1,1)
 100.548 +	CGEN_ENTITY,				// grabbed from entity's modulate field
 100.549 +	CGEN_ONE_MINUS_ENTITY,		// grabbed from 1 - entity.modulate
 100.550 +	CGEN_VERTEX,				// tess.colors
 100.551  	CGEN_ONE_MINUS_VERTEX,
 100.552 -	CGEN_WAVEFORM,			// programmatically generated
 100.553 -	CGEN_LIGHTING_DIFFUSE,
 100.554 -	CGEN_FOG,				// standard fog
 100.555 -	CGEN_CONST				// fixed color
 100.556 +	CGEN_WAVEFORM,				// programmatically generated
 100.557 +	CGEN_CONST,					// fixed color
 100.558 +	CGEN_CUSTOM_RGB,			// like fixed color but generated dynamically, single arithmetic expression
 100.559 +	CGEN_CUSTOM_RGBs,			// multiple expressions
 100.560  } colorGen_t;
 100.561  
 100.562 -typedef enum {
 100.563 -	TCGEN_BAD,
 100.564 -	TCGEN_IDENTITY,			// clear to 0,0
 100.565 -	TCGEN_LIGHTMAP,
 100.566 -	TCGEN_TEXTURE,
 100.567 -	TCGEN_ENVIRONMENT_MAPPED,
 100.568 -	TCGEN_FOG,
 100.569 -	TCGEN_VECTOR			// S and T from world coordinates
 100.570 -} texCoordGen_t;
 100.571 -
 100.572 -typedef enum {
 100.573 -	ACFF_NONE,
 100.574 -	ACFF_MODULATE_RGB,
 100.575 -	ACFF_MODULATE_RGBA,
 100.576 -	ACFF_MODULATE_ALPHA
 100.577 -} acff_t;
 100.578 -
 100.579 -typedef struct {
 100.580 -	genFunc_t	func;
 100.581 -
 100.582 -	float base;
 100.583 -	float amplitude;
 100.584 -	float phase;
 100.585 -	float frequency;
 100.586 +typedef enum
 100.587 +{
 100.588 +	ATEST_NONE,
 100.589 +	ATEST_GT_0,
 100.590 +	ATEST_LT_128,
 100.591 +	ATEST_GE_128
 100.592 +} alphaTest_t;
 100.593 +
 100.594 +typedef enum
 100.595 +{
 100.596 +	OP_BAD,
 100.597 +	// logic operators
 100.598 +	OP_LAND,
 100.599 +	OP_LOR,
 100.600 +	OP_GE,
 100.601 +	OP_LE,
 100.602 +	OP_LEQ,
 100.603 +	OP_LNE,
 100.604 +	// arithmetic operators
 100.605 +	OP_ADD,
 100.606 +	OP_SUB,
 100.607 +	OP_DIV,
 100.608 +	OP_MOD,
 100.609 +	OP_MUL,
 100.610 +	OP_NEG,
 100.611 +	// logic operators
 100.612 +	OP_LT,
 100.613 +	OP_GT,
 100.614 +	// embracements
 100.615 +	OP_LPAREN,
 100.616 +	OP_RPAREN,
 100.617 +	OP_LBRACKET,
 100.618 +	OP_RBRACKET,
 100.619 +	// constants or variables
 100.620 +	OP_NUM,
 100.621 +	OP_TIME,
 100.622 +	OP_PARM0,
 100.623 +	OP_PARM1,
 100.624 +	OP_PARM2,
 100.625 +	OP_PARM3,
 100.626 +	OP_PARM4,
 100.627 +	OP_PARM5,
 100.628 +	OP_PARM6,
 100.629 +	OP_PARM7,
 100.630 +	OP_PARM8,
 100.631 +	OP_PARM9,
 100.632 +	OP_PARM10,
 100.633 +	OP_PARM11,
 100.634 +	OP_GLOBAL0,
 100.635 +	OP_GLOBAL1,
 100.636 +	OP_GLOBAL2,
 100.637 +	OP_GLOBAL3,
 100.638 +	OP_GLOBAL4,
 100.639 +	OP_GLOBAL5,
 100.640 +	OP_GLOBAL6,
 100.641 +	OP_GLOBAL7,
 100.642 +	OP_FRAGMENTSHADERS,
 100.643 +	OP_FRAMEBUFFEROBJECTS,
 100.644 +	OP_SOUND,
 100.645 +	OP_DISTANCE,
 100.646 +	// table access
 100.647 +	OP_TABLE
 100.648 +} opcode_t;
 100.649 +
 100.650 +typedef struct
 100.651 +{
 100.652 +	const char     *s;
 100.653 +	opcode_t        type;
 100.654 +} opstring_t;
 100.655 +
 100.656 +typedef struct
 100.657 +{
 100.658 +	opcode_t        type;
 100.659 +	float           value;
 100.660 +} expOperation_t;
 100.661 +
 100.662 +#define MAX_EXPRESSION_OPS	32
 100.663 +typedef struct
 100.664 +{
 100.665 +	expOperation_t  ops[MAX_EXPRESSION_OPS];
 100.666 +	int             numOps;
 100.667 +
 100.668 +	qboolean        active;		// no parsing problems
 100.669 +} expression_t;
 100.670 +
 100.671 +typedef struct
 100.672 +{
 100.673 +	genFunc_t       func;
 100.674 +
 100.675 +	float           base;
 100.676 +	float           amplitude;
 100.677 +	float           phase;
 100.678 +	float           frequency;
 100.679  } waveForm_t;
 100.680  
 100.681  #define TR_MAX_TEXMODS 4
 100.682  
 100.683 -typedef enum {
 100.684 +typedef enum
 100.685 +{
 100.686  	TMOD_NONE,
 100.687  	TMOD_TRANSFORM,
 100.688  	TMOD_TURBULENT,
 100.689 @@ -238,278 +570,1225 @@
 100.690  	TMOD_SCALE,
 100.691  	TMOD_STRETCH,
 100.692  	TMOD_ROTATE,
 100.693 -	TMOD_ENTITY_TRANSLATE
 100.694 +	TMOD_ENTITY_TRANSLATE,
 100.695 +
 100.696 +	TMOD_SCROLL2,
 100.697 +	TMOD_SCALE2,
 100.698 +	TMOD_CENTERSCALE,
 100.699 +	TMOD_SHEAR,
 100.700 +	TMOD_ROTATE2
 100.701  } texMod_t;
 100.702  
 100.703  #define	MAX_SHADER_DEFORMS	3
 100.704 -typedef struct {
 100.705 -	deform_t	deformation;			// vertex coordinate modification type
 100.706 -
 100.707 -	vec3_t		moveVector;
 100.708 -	waveForm_t	deformationWave;
 100.709 -	float		deformationSpread;
 100.710 -
 100.711 -	float		bulgeWidth;
 100.712 -	float		bulgeHeight;
 100.713 -	float		bulgeSpeed;
 100.714 +typedef struct
 100.715 +{
 100.716 +	deform_t        deformation;	// vertex coordinate modification type
 100.717 +
 100.718 +	vec3_t          moveVector;
 100.719 +	waveForm_t      deformationWave;
 100.720 +	float           deformationSpread;
 100.721 +
 100.722 +	float           bulgeWidth;
 100.723 +	float           bulgeHeight;
 100.724 +	float           bulgeSpeed;
 100.725 +
 100.726 +	float           flareSize;
 100.727  } deformStage_t;
 100.728  
 100.729 -
 100.730 -typedef struct {
 100.731 -	texMod_t		type;
 100.732 +typedef struct
 100.733 +{
 100.734 +	texMod_t        type;
 100.735  
 100.736  	// used for TMOD_TURBULENT and TMOD_STRETCH
 100.737 -	waveForm_t		wave;
 100.738 +	waveForm_t      wave;
 100.739  
 100.740  	// used for TMOD_TRANSFORM
 100.741 -	float			matrix[2][2];		// s' = s * m[0][0] + t * m[1][0] + trans[0]
 100.742 -	float			translate[2];		// t' = s * m[0][1] + t * m[0][1] + trans[1]
 100.743 +	matrix_t        matrix;		// s' = s * m[0][0] + t * m[1][0] + trans[0]
 100.744 +	// t' = s * m[0][1] + t * m[0][1] + trans[1]
 100.745  
 100.746  	// used for TMOD_SCALE
 100.747 -	float			scale[2];			// s *= scale[0]
 100.748 -	                                    // t *= scale[1]
 100.749 +	float           scale[2];	// s *= scale[0]
 100.750 +	// t *= scale[1]
 100.751  
 100.752  	// used for TMOD_SCROLL
 100.753 -	float			scroll[2];			// s' = s + scroll[0] * time
 100.754 -										// t' = t + scroll[1] * time
 100.755 +	float           scroll[2];	// s' = s + scroll[0] * time
 100.756 +	// t' = t + scroll[1] * time
 100.757  
 100.758  	// + = clockwise
 100.759  	// - = counterclockwise
 100.760 -	float			rotateSpeed;
 100.761 +	float           rotateSpeed;
 100.762 +
 100.763 +	// used by everything else
 100.764 +	expression_t    sExp;
 100.765 +	expression_t    tExp;
 100.766 +	expression_t    rExp;
 100.767  
 100.768  } texModInfo_t;
 100.769  
 100.770  
 100.771 -#define	MAX_IMAGE_ANIMATIONS	8
 100.772 -
 100.773 -typedef struct {
 100.774 -	image_t			*image[MAX_IMAGE_ANIMATIONS];
 100.775 -	int				numImageAnimations;
 100.776 -	float			imageAnimationSpeed;
 100.777 -
 100.778 -	texCoordGen_t	tcGen;
 100.779 -	vec3_t			tcGenVectors[2];
 100.780 -
 100.781 -	int				numTexMods;
 100.782 -	texModInfo_t	*texMods;
 100.783 -
 100.784 -	int				videoMapHandle;
 100.785 -	qboolean		isLightmap;
 100.786 -	qboolean		vertexLightmap;
 100.787 -	qboolean		isVideoMap;
 100.788 +#define	MAX_IMAGE_ANIMATIONS	16
 100.789 +
 100.790 +enum
 100.791 +{
 100.792 +	TB_COLORMAP = 0,
 100.793 +	TB_DIFFUSEMAP = 0,
 100.794 +	TB_NORMALMAP,
 100.795 +	TB_SPECULARMAP,
 100.796 +	MAX_TEXTURE_BUNDLES = 3
 100.797 +};
 100.798 +
 100.799 +typedef struct
 100.800 +{
 100.801 +	int				numImages;
 100.802 +	float           imageAnimationSpeed;
 100.803 +	image_t        *image[MAX_IMAGE_ANIMATIONS];
 100.804 +
 100.805 +	int             numTexMods;
 100.806 +	texModInfo_t   *texMods;
 100.807 +
 100.808 +	int             videoMapHandle;
 100.809 +	qboolean        isVideoMap;
 100.810  } textureBundle_t;
 100.811  
 100.812 -#define NUM_TEXTURE_BUNDLES 2
 100.813 -
 100.814 -typedef struct {
 100.815 -	qboolean		active;
 100.816 -	
 100.817 -	textureBundle_t	bundle[NUM_TEXTURE_BUNDLES];
 100.818 -
 100.819 -	waveForm_t		rgbWave;
 100.820 -	colorGen_t		rgbGen;
 100.821 -
 100.822 -	waveForm_t		alphaWave;
 100.823 -	alphaGen_t		alphaGen;
 100.824 -
 100.825 -	byte			constantColor[4];			// for CGEN_CONST and AGEN_CONST
 100.826 -
 100.827 -	unsigned		stateBits;					// GLS_xxxx mask
 100.828 -
 100.829 -	acff_t			adjustColorsForFog;
 100.830 -
 100.831 -	qboolean		isDetail;
 100.832 +typedef enum
 100.833 +{
 100.834 +	// material shader stage types
 100.835 +	ST_COLORMAP,				// vanilla Q3A style shader treatening
 100.836 +	ST_DIFFUSEMAP,
 100.837 +	ST_NORMALMAP,
 100.838 +	ST_SPECULARMAP,
 100.839 +	ST_REFLECTIONMAP,			// cubeMap based reflection
 100.840 +	ST_REFRACTIONMAP,
 100.841 +	ST_DISPERSIONMAP,
 100.842 +	ST_SKYBOXMAP,
 100.843 +	ST_SCREENMAP,				// 2d offscreen or portal rendering
 100.844 +	ST_PORTALMAP,
 100.845 +	ST_HEATHAZEMAP,				// heatHaze post process effect
 100.846 +	ST_LIQUIDMAP,
 100.847 +
 100.848 +#if defined(COMPAT_Q3A)
 100.849 +	ST_LIGHTMAP,
 100.850 +#endif
 100.851 +
 100.852 +	ST_COLLAPSE_lighting_DB,	// diffusemap + bumpmap
 100.853 +	ST_COLLAPSE_lighting_DBS,	// diffusemap + bumpmap + specularmap
 100.854 +	ST_COLLAPSE_reflection_CB,	// color cubemap + bumpmap
 100.855 +
 100.856 +	// light shader stage types
 100.857 +	ST_ATTENUATIONMAP_XY,
 100.858 +	ST_ATTENUATIONMAP_Z
 100.859 +} stageType_t;
 100.860 +
 100.861 +typedef enum
 100.862 +{
 100.863 +	COLLAPSE_none,
 100.864 +	COLLAPSE_genericMulti,
 100.865 +	COLLAPSE_lighting_DB,
 100.866 +	COLLAPSE_lighting_DBS,
 100.867 +	COLLAPSE_reflection_CB
 100.868 +} collapseType_t;
 100.869 +
 100.870 +typedef struct
 100.871 +{
 100.872 +	stageType_t     type;
 100.873 +
 100.874 +	qboolean        active;
 100.875 +
 100.876 +	textureBundle_t bundle[MAX_TEXTURE_BUNDLES];
 100.877 +
 100.878 +	expression_t    ifExp;
 100.879 +
 100.880 +	waveForm_t      rgbWave;
 100.881 +	colorGen_t      rgbGen;
 100.882 +	expression_t    rgbExp;
 100.883 +	expression_t    redExp;
 100.884 +	expression_t    greenExp;
 100.885 +	expression_t    blueExp;
 100.886 +
 100.887 +	waveForm_t      alphaWave;
 100.888 +	alphaGen_t      alphaGen;
 100.889 +	expression_t    alphaExp;
 100.890 +
 100.891 +	expression_t    alphaTestExp;
 100.892 +
 100.893 +	qboolean		tcGen_Environment;
 100.894 +
 100.895 +	byte            constantColor[4];	// for CGEN_CONST and AGEN_CONST
 100.896 +
 100.897 +	unsigned        stateBits;	// GLS_xxxx mask
 100.898 +
 100.899 +	qboolean        overrideNoPicMip;	// for images that must always be full resolution
 100.900 +	qboolean        overrideFilterType;	// for console fonts, 2D elements, etc.
 100.901 +	filterType_t    filterType;
 100.902 +	qboolean        overrideWrapType;
 100.903 +	wrapType_t      wrapType;
 100.904 +
 100.905 +	qboolean        uncompressed;
 100.906 +	qboolean        highQuality;
 100.907 +	qboolean        forceHighQuality;
 100.908 +
 100.909 +	qboolean        privatePolygonOffset;	// set for decals and other items that must be offset
 100.910 +	float           privatePolygonOffsetValue;
 100.911 +
 100.912 +	expression_t    refractionIndexExp;
 100.913 +
 100.914 +	expression_t    fresnelPowerExp;
 100.915 +	expression_t    fresnelScaleExp;
 100.916 +	expression_t    fresnelBiasExp;
 100.917 +
 100.918 +	expression_t	normalScaleExp;
 100.919 +
 100.920 +	expression_t    etaExp;
 100.921 +	expression_t    etaDeltaExp;
 100.922 +
 100.923 +	expression_t    fogDensityExp;
 100.924 +
 100.925 +	expression_t    depthScaleExp;
 100.926 +
 100.927 +	expression_t    deformMagnitudeExp;
 100.928 +
 100.929 +	expression_t    blurMagnitudeExp;
 100.930  } shaderStage_t;
 100.931  
 100.932  struct shaderCommands_s;
 100.933  
 100.934 -// any change in the LIGHTMAP_* defines here MUST be reflected in
 100.935 -// R_FindShader() in tr_bsp.c
 100.936 -#define LIGHTMAP_2D         -4	// shader is for 2D rendering
 100.937 -#define LIGHTMAP_BY_VERTEX  -3	// pre-lit triangle models
 100.938 -#define LIGHTMAP_WHITEIMAGE -2
 100.939 -#define LIGHTMAP_NONE       -1
 100.940 -
 100.941 -typedef enum {
 100.942 +typedef enum
 100.943 +{
 100.944  	CT_FRONT_SIDED,
 100.945  	CT_BACK_SIDED,
 100.946  	CT_TWO_SIDED
 100.947  } cullType_t;
 100.948  
 100.949 -typedef enum {
 100.950 -	FP_NONE,		// surface is translucent and will just be adjusted properly
 100.951 -	FP_EQUAL,		// surface is opaque but possibly alpha tested
 100.952 -	FP_LE			// surface is trnaslucent, but still needs a fog pass (fog surface)
 100.953 -} fogPass_t;
 100.954 -
 100.955 -typedef struct {
 100.956 -	float		cloudHeight;
 100.957 -	image_t		*outerbox[6], *innerbox[6];
 100.958 +typedef struct
 100.959 +{
 100.960 +	float           cloudHeight;
 100.961 +	image_t        *outerbox, *innerbox;
 100.962  } skyParms_t;
 100.963  
 100.964 -typedef struct {
 100.965 -	vec3_t	color;
 100.966 -	float	depthForOpaque;
 100.967 +typedef struct
 100.968 +{
 100.969 +	vec3_t          color;
 100.970 +	float           density;
 100.971  } fogParms_t;
 100.972  
 100.973 -
 100.974 -typedef struct shader_s {
 100.975 -	char		name[MAX_QPATH];		// game path, including extension
 100.976 -	int			lightmapIndex;			// for a shader to match, both name and lightmapIndex must match
 100.977 -
 100.978 -	int			index;					// this shader == tr.shaders[index]
 100.979 -	int			sortedIndex;			// this shader == tr.sortedShaders[sortedIndex]
 100.980 -
 100.981 -	float		sort;					// lower numbered shaders draw before higher numbered
 100.982 -
 100.983 -	qboolean	defaultShader;			// we want to return index 0 if the shader failed to
 100.984 -										// load for some reason, but R_FindShader should
 100.985 -										// still keep a name allocated for it, so if
 100.986 -										// something calls RE_RegisterShader again with
 100.987 -										// the same name, we don't try looking for it again
 100.988 -
 100.989 -	qboolean	explicitlyDefined;		// found in a .shader file
 100.990 -
 100.991 -	int			surfaceFlags;			// if explicitlyDefined, this will have SURF_* flags
 100.992 -	int			contentFlags;
 100.993 -
 100.994 -	qboolean	entityMergable;			// merge across entites optimizable (smoke, blood)
 100.995 -
 100.996 -	qboolean	isSky;
 100.997 -	skyParms_t	sky;
 100.998 -	fogParms_t	fogParms;
 100.999 -
100.1000 -	float		portalRange;			// distance to fog out at
100.1001 -
100.1002 -	int			multitextureEnv;		// 0, GL_MODULATE, GL_ADD (FIXME: put in stage)
100.1003 -
100.1004 -	cullType_t	cullType;				// CT_FRONT_SIDED, CT_BACK_SIDED, or CT_TWO_SIDED
100.1005 -	qboolean	polygonOffset;			// set for decals and other items that must be offset 
100.1006 -	qboolean	noMipMaps;				// for console fonts, 2D elements, etc.
100.1007 -	qboolean	noPicMip;				// for images that must always be full resolution
100.1008 -
100.1009 -	fogPass_t	fogPass;				// draw a blended pass, possibly with depth test equals
100.1010 -
100.1011 -	qboolean	needsNormal;			// not all shaders will need all data to be gathered
100.1012 -	qboolean	needsST1;
100.1013 -	qboolean	needsST2;
100.1014 -	qboolean	needsColor;
100.1015 -
100.1016 -	int			numDeforms;
100.1017 -	deformStage_t	deforms[MAX_SHADER_DEFORMS];
100.1018 -
100.1019 -	int			numUnfoggedPasses;
100.1020 -	shaderStage_t	*stages[MAX_SHADER_STAGES];		
100.1021 -
100.1022 -	void		(*optimalStageIteratorFunc)( void );
100.1023 -
100.1024 -  float clampTime;                                  // time this shader is clamped to
100.1025 -  float timeOffset;                                 // current time offset for this shader
100.1026 -
100.1027 -  int numStates;                                    // if non-zero this is a state shader
100.1028 -  struct shader_s *currentShader;                   // current state if this is a state shader
100.1029 -  struct shader_s *parentShader;                    // current state if this is a state shader
100.1030 -  int currentState;                                 // current state index for cycle purposes
100.1031 -  long expireTime;                                  // time in milliseconds this expires
100.1032 -
100.1033 -  struct shader_s *remappedShader;                  // current shader this one is remapped too
100.1034 -
100.1035 -  int shaderStates[MAX_STATES_PER_SHADER];          // index to valid shader states
100.1036 -
100.1037 -	struct	shader_s	*next;
100.1038 +typedef enum
100.1039 +{
100.1040 +	SHADER_2D,					// surface material: shader is for 2D rendering
100.1041 +	SHADER_3D_DYNAMIC,			// surface material: shader is for cGen diffuseLighting lighting
100.1042 +	SHADER_3D_STATIC,			// surface material: pre-lit triangle models
100.1043 +	SHADER_LIGHT				// light material: attenuation
100.1044 +} shaderType_t;
100.1045 +
100.1046 +typedef struct shader_s
100.1047 +{
100.1048 +	char            name[MAX_QPATH];	// game path, including extension
100.1049 +	shaderType_t    type;
100.1050 +
100.1051 +	int             index;		// this shader == tr.shaders[index]
100.1052 +	int             sortedIndex;	// this shader == tr.sortedShaders[sortedIndex]
100.1053 +
100.1054 +	float           sort;		// lower numbered shaders draw before higher numbered
100.1055 +
100.1056 +	qboolean        defaultShader;	// we want to return index 0 if the shader failed to
100.1057 +	// load for some reason, but R_FindShader should
100.1058 +	// still keep a name allocated for it, so if
100.1059 +	// something calls RE_RegisterShader again with
100.1060 +	// the same name, we don't try looking for it again
100.1061 +
100.1062 +	qboolean        explicitlyDefined;	// found in a .shader file
100.1063 +	qboolean        createdByGuide;	// created using a shader .guide template
100.1064 +
100.1065 +	int             surfaceFlags;	// if explicitlyDefined, this will have SURF_* flags
100.1066 +	int             contentFlags;
100.1067 +
100.1068 +	qboolean        entityMergable;	// merge across entites optimizable (smoke, blood)
100.1069 +	qboolean        alphaTest;		// helps merging shadowmap generating surfaces
100.1070 +
100.1071 +	qboolean		fogVolume;		// surface encapsulates a fog volume
100.1072 +	fogParms_t		fogParms;
100.1073 +
100.1074 +	qboolean		parallax;		// material has normalmaps suited for parallax mapping
100.1075 +
100.1076 +	qboolean        noShadows;
100.1077 +	qboolean        fogLight;
100.1078 +	qboolean        blendLight;
100.1079 +	qboolean        ambientLight;
100.1080 +	qboolean        volumetricLight;
100.1081 +	qboolean        translucent;
100.1082 +	qboolean        forceOpaque;
100.1083 +	qboolean        isSky;
100.1084 +	skyParms_t      sky;
100.1085 +
100.1086 +	float           portalRange;	// distance to fog out at
100.1087 +	qboolean        isPortal;
100.1088 +
100.1089 +	collapseType_t  collapseType;
100.1090 +	int             collapseTextureEnv;	// 0, GL_MODULATE, GL_ADD (FIXME: put in stage)
100.1091 +
100.1092 +	cullType_t      cullType;	// CT_FRONT_SIDED, CT_BACK_SIDED, or CT_TWO_SIDED
100.1093 +	qboolean        polygonOffset;	// set for decals and other items that must be offset
100.1094 +	float           polygonOffsetValue;
100.1095 +
100.1096 +	qboolean        noPicMip;	// for images that must always be full resolution
100.1097 +	filterType_t    filterType;	// for console fonts, 2D elements, etc.
100.1098 +	wrapType_t      wrapType;
100.1099 +
100.1100 +	// spectrums are used for "invisible writing" that can only be illuminated by a light of matching spectrum
100.1101 +	qboolean        spectrum;
100.1102 +	int             spectrumValue;
100.1103 +
100.1104 +	qboolean        interactLight;	// this shader can interact with light shaders
100.1105 +
100.1106 +	int             numDeforms;
100.1107 +	deformStage_t   deforms[MAX_SHADER_DEFORMS];
100.1108 +
100.1109 +	int             numStages;
100.1110 +	shaderStage_t  *stages[MAX_SHADER_STAGES];
100.1111 +
100.1112 +	int             numStates;	// if non-zero this is a state shader
100.1113 +	struct shader_s *currentShader;	// current state if this is a state shader
100.1114 +	struct shader_s *parentShader;	// current state if this is a state shader
100.1115 +	int             currentState;	// current state index for cycle purposes
100.1116 +	long            expireTime;	// time in milliseconds this expires
100.1117 +
100.1118 +	struct shader_s *remappedShader;	// current shader this one is remapped too
100.1119 +
100.1120 +	int             shaderStates[MAX_STATES_PER_SHADER];	// index to valid shader states
100.1121 +
100.1122 +	struct shader_s *next;
100.1123  } shader_t;
100.1124  
100.1125 -typedef struct shaderState_s {
100.1126 -  char shaderName[MAX_QPATH];     // name of shader this state belongs to
100.1127 -  char name[MAX_STATE_NAME];      // name of this state
100.1128 -  char stateShader[MAX_QPATH];    // shader this name invokes
100.1129 -  int cycleTime;                  // time this cycle lasts, <= 0 is forever
100.1130 -  shader_t *shader;
100.1131 +typedef struct shaderState_s
100.1132 +{
100.1133 +	char            shaderName[MAX_QPATH];	// name of shader this state belongs to
100.1134 +	char            name[MAX_STATE_NAME];	// name of this state
100.1135 +	char            stateShader[MAX_QPATH];	// shader this name invokes
100.1136 +	int             cycleTime;	// time this cycle lasts, <= 0 is forever
100.1137 +	shader_t       *shader;
100.1138  } shaderState_t;
100.1139  
100.1140 +#if 0
100.1141 +enum
100.1142 +{
100.1143 +	ATTR_INDEX_POSITION = 0,
100.1144 +	ATTR_INDEX_TEXCOORD0 = 8,
100.1145 +	ATTR_INDEX_TEXCOORD1 = 9,
100.1146 +//  ATTR_INDEX_TEXCOORD2 = 10,
100.1147 +//  ATTR_INDEX_TEXCOORD3 = 11,
100.1148 +	ATTR_INDEX_TANGENT = 12,
100.1149 +	ATTR_INDEX_BINORMAL = 13,
100.1150 +	ATTR_INDEX_NORMAL = 14,
100.1151 +	ATTR_INDEX_COLOR = 15,
100.1152 +	ATTR_INDEX_LIGHTCOLOR = 16,
100.1153 +	ATTR_INDEX_LIGHTDIRECTION = 17,
100.1154 +	ATTR_INDEX_BONE_INDEXES = 10,
100.1155 +	ATTR_INDEX_BONE_WEIGHTS = 11,
100.1156 +};
100.1157 +#else
100.1158 +enum
100.1159 +{
100.1160 +	ATTR_INDEX_POSITION = 0,
100.1161 +	ATTR_INDEX_TEXCOORD0 = 1,
100.1162 +	ATTR_INDEX_TEXCOORD1 = 2,
100.1163 +	ATTR_INDEX_TANGENT = 3,
100.1164 +	ATTR_INDEX_BINORMAL = 4,
100.1165 +	ATTR_INDEX_NORMAL = 5,
100.1166 +	ATTR_INDEX_COLOR = 6,
100.1167 +	ATTR_INDEX_PAINTCOLOR = 7,
100.1168 +	ATTR_INDEX_LIGHTDIRECTION = 8,
100.1169 +	ATTR_INDEX_BONE_INDEXES = 9,
100.1170 +	ATTR_INDEX_BONE_WEIGHTS = 10,
100.1171 +};
100.1172 +#endif
100.1173 +
100.1174 +// *INDENT-OFF*
100.1175 +enum
100.1176 +{
100.1177 +	GLS_SRCBLEND_ZERO					= (1 << 0),
100.1178 +	GLS_SRCBLEND_ONE					= (1 << 1),
100.1179 +	GLS_SRCBLEND_DST_COLOR				= (1 << 2),
100.1180 +	GLS_SRCBLEND_ONE_MINUS_DST_COLOR	= (1 << 3),
100.1181 +	GLS_SRCBLEND_SRC_ALPHA				= (1 << 4),
100.1182 +	GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA	= (1 << 5),
100.1183 +	GLS_SRCBLEND_DST_ALPHA				= (1 << 6),
100.1184 +	GLS_SRCBLEND_ONE_MINUS_DST_ALPHA	= (1 << 7),
100.1185 +	GLS_SRCBLEND_ALPHA_SATURATE			= (1 << 8),
100.1186 +
100.1187 +	GLS_SRCBLEND_BITS					= GLS_SRCBLEND_ZERO
100.1188 +											| GLS_SRCBLEND_ONE
100.1189 +											| GLS_SRCBLEND_DST_COLOR
100.1190 +											| GLS_SRCBLEND_ONE_MINUS_DST_COLOR
100.1191 +											| GLS_SRCBLEND_SRC_ALPHA
100.1192 +											| GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA
100.1193 +											| GLS_SRCBLEND_DST_ALPHA
100.1194 +											| GLS_SRCBLEND_ONE_MINUS_DST_ALPHA
100.1195 +											| GLS_SRCBLEND_ALPHA_SATURATE,
100.1196 +
100.1197 +	GLS_DSTBLEND_ZERO					= (1 << 9),
100.1198 +	GLS_DSTBLEND_ONE					= (1 << 10),
100.1199 +	GLS_DSTBLEND_SRC_COLOR				= (1 << 11),
100.1200 +	GLS_DSTBLEND_ONE_MINUS_SRC_COLOR	= (1 << 12),
100.1201 +	GLS_DSTBLEND_SRC_ALPHA				= (1 << 13),
100.1202 +	GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA	= (1 << 14),
100.1203 +	GLS_DSTBLEND_DST_ALPHA				= (1 << 15),
100.1204 +	GLS_DSTBLEND_ONE_MINUS_DST_ALPHA	= (1 << 16),
100.1205 +
100.1206 +	GLS_DSTBLEND_BITS					= GLS_DSTBLEND_ZERO
100.1207 +											| GLS_DSTBLEND_ONE
100.1208 +											| GLS_DSTBLEND_SRC_COLOR
100.1209 +											| GLS_DSTBLEND_ONE_MINUS_SRC_COLOR
100.1210 +											| GLS_DSTBLEND_SRC_ALPHA
100.1211 +											| GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA
100.1212 +											| GLS_DSTBLEND_DST_ALPHA
100.1213 +											| GLS_DSTBLEND_ONE_MINUS_DST_ALPHA,
100.1214 +
100.1215 +	GLS_DEPTHMASK_TRUE					= (1 << 17),
100.1216 +
100.1217 +	GLS_POLYMODE_LINE					= (1 << 18),
100.1218 +
100.1219 +	GLS_DEPTHTEST_DISABLE				= (1 << 19),
100.1220 +
100.1221 +	GLS_DEPTHFUNC_LESS					= (1 << 20),
100.1222 +	GLS_DEPTHFUNC_EQUAL					= (1 << 21),
100.1223 +
100.1224 +	GLS_DEPTHFUNC_BITS					= GLS_DEPTHFUNC_LESS
100.1225 +											| GLS_DEPTHFUNC_EQUAL,
100.1226 +
100.1227 +	GLS_ATEST_GT_0						= (1 << 22),
100.1228 +	GLS_ATEST_LT_128					= (1 << 23),
100.1229 +	GLS_ATEST_GE_128					= (1 << 24),
100.1230 +//	GLS_ATEST_GE_CUSTOM					= (1 << 25),
100.1231 +
100.1232 +	GLS_ATEST_BITS						= GLS_ATEST_GT_0
100.1233 +											| GLS_ATEST_LT_128
100.1234 +											| GLS_ATEST_GE_128,
100.1235 +//											| GLS_ATEST_GT_CUSTOM,
100.1236 +
100.1237 +	GLS_REDMASK_FALSE					= (1 << 26),
100.1238 +	GLS_GREENMASK_FALSE					= (1 << 27),
100.1239 +	GLS_BLUEMASK_FALSE					= (1 << 28),
100.1240 +	GLS_ALPHAMASK_FALSE					= (1 << 29),
100.1241 +
100.1242 +	GLS_COLORMASK_BITS					= GLS_REDMASK_FALSE
100.1243 +											| GLS_GREENMASK_FALSE
100.1244 +											| GLS_BLUEMASK_FALSE
100.1245 +											| GLS_ALPHAMASK_FALSE,
100.1246 +
100.1247 +	GLS_STENCILTEST_ENABLE				= (1 << 30),
100.1248 +
100.1249 +	GLS_DEFAULT							= GLS_DEPTHMASK_TRUE
100.1250 +};
100.1251 +// *INDENT-ON*
100.1252 +
100.1253 +enum
100.1254 +{
100.1255 +	ATTR_POSITION = BIT(0),
100.1256 +	ATTR_TEXCOORD = BIT(1),
100.1257 +	ATTR_LIGHTCOORD = BIT(2),
100.1258 +	ATTR_TANGENT = BIT(3),
100.1259 +	ATTR_BINORMAL = BIT(4),
100.1260 +	ATTR_NORMAL = BIT(5),
100.1261 +	ATTR_COLOR = BIT(6),
100.1262 +	ATTR_PAINTCOLOR = BIT(7),
100.1263 +	ATTR_LIGHTDIRECTION = BIT(8),
100.1264 +	ATTR_BONE_INDEXES = BIT(9),
100.1265 +	ATTR_BONE_WEIGHTS = BIT(10),
100.1266 +
100.1267 +	ATTR_DEFAULT = ATTR_POSITION,
100.1268 +	ATTR_BITS =	ATTR_POSITION |
100.1269 +				ATTR_TEXCOORD |
100.1270 +				ATTR_LIGHTCOORD |
100.1271 +				ATTR_TANGENT |
100.1272 +				ATTR_BINORMAL |
100.1273 +				ATTR_NORMAL |
100.1274 +				ATTR_COLOR |
100.1275 +				ATTR_PAINTCOLOR |
100.1276 +				ATTR_LIGHTDIRECTION |
100.1277 +				ATTR_BONE_INDEXES |
100.1278 +				ATTR_BONE_WEIGHTS
100.1279 +};
100.1280 +
100.1281 +// Tr3B - shaderProgram_t represents a pair of one
100.1282 +// GLSL vertex and one GLSL fragment shader
100.1283 +typedef struct shaderProgram_s
100.1284 +{
100.1285 +	char            name[MAX_QPATH];
100.1286 +
100.1287 +	GLhandleARB     program;
100.1288 +	unsigned int    attribs;	// vertex array attributes
100.1289 +
100.1290 +	// uniform parameters
100.1291 +	GLint           u_ColorMap;
100.1292 +	GLint           u_CurrentMap;
100.1293 +	GLint           u_ContrastMap;
100.1294 +	GLint           u_DiffuseMap;
100.1295 +	GLint           u_NormalMap;
100.1296 +	GLint           u_SpecularMap;
100.1297 +	GLint           u_LightMap;
100.1298 +	GLint           u_DeluxeMap;
100.1299 +	GLint           u_DepthMap;
100.1300 +	GLint           u_DepthMapBack;
100.1301 +	GLint           u_DepthMapFront;
100.1302 +	GLint           u_PortalMap;
100.1303 +	GLint           u_AttenuationMapXY;
100.1304 +	GLint           u_AttenuationMapZ;
100.1305 +	GLint           u_ShadowMap;
100.1306 +
100.1307 +	GLint           u_ColorTextureMatrix;
100.1308 +	matrix_t		t_ColorTextureMatrix;
100.1309 +
100.1310 +	GLint           u_DiffuseTextureMatrix;
100.1311 +	matrix_t		t_DiffuseTextureMatrix;
100.1312 +
100.1313 +	GLint           u_NormalTextureMatrix;
100.1314 +	matrix_t		t_NormalTextureMatrix;
100.1315 +
100.1316 +	GLint           u_SpecularTextureMatrix;
100.1317 +	matrix_t		t_SpecularTextureMatrix;
100.1318 +
100.1319 +	GLint           u_AlphaTest;
100.1320 +	alphaTest_t		t_AlphaTest;
100.1321 +
100.1322 +	GLint           u_ViewOrigin;
100.1323 +	vec3_t			t_ViewOrigin;
100.1324 +
100.1325 +	GLint           u_TCGen_Environment;
100.1326 +	qboolean		t_TCGen_Environment;
100.1327 +
100.1328 +	GLint           u_ColorGen;
100.1329 +	colorGen_t		t_ColorGen;
100.1330 +
100.1331 +	GLint           u_AlphaGen;
100.1332 +	alphaGen_t		t_AlphaGen;
100.1333 +
100.1334 +	GLint           u_Color;
100.1335 +	vec4_t			t_Color;
100.1336 +
100.1337 +	GLint           u_AmbientColor;
100.1338 +	vec3_t			t_AmbientColor;
100.1339 +
100.1340 +	GLint           u_LightDir;
100.1341 +	vec3_t			t_LightDir;
100.1342 +
100.1343 +	GLint           u_LightOrigin;
100.1344 +	vec3_t			t_LightOrigin;
100.1345 +
100.1346 +	GLint           u_LightColor;
100.1347 +	vec3_t			t_LightColor;
100.1348 +
100.1349 +	GLint           u_LightRadius;
100.1350 +	float			t_LightRadius;
100.1351 +
100.1352 +	GLint           u_LightScale;
100.1353 +	float			t_LightScale;
100.1354 +
100.1355 +	GLint           u_LightAttenuationMatrix;
100.1356 +	matrix_t		t_LightAttenuationMatrix;
100.1357 +
100.1358 +	GLint           u_LightFrustum;
100.1359 +	vec4_t			t_LightFrustum;
100.1360 +
100.1361 +
100.1362 +	GLint           u_ShadowMatrix;
100.1363 +	matrix_t		t_ShadowMatrix;
100.1364 +
100.1365 +	GLint           u_ShadowCompare;
100.1366 +	qboolean		t_ShadowCompare;
100.1367 +
100.1368 +	GLint           u_ShadowTexelSize;
100.1369 +	float			t_ShadowTexelSize;
100.1370 +
100.1371 +	GLint           u_ShadowBlur;
100.1372 +	float			t_ShadowBlur;
100.1373 +
100.1374 +
100.1375 +	GLint           u_RefractionIndex;
100.1376 +	float			t_RefractionIndex;
100.1377 +
100.1378 +
100.1379 +	GLint           u_FresnelPower;
100.1380 +	GLint           u_FresnelScale;
100.1381 +	GLint           u_FresnelBias;
100.1382 +
100.1383 +	GLint		u_NormalScale;
100.1384 +
100.1385 +	GLint           u_EtaRatio;
100.1386 +
100.1387 +	GLint           u_FogDensity;
100.1388 +	GLint           u_FogColor;
100.1389 +
100.1390 +	GLint           u_SSAOJitter;
100.1391 +	GLint           u_SSAORadius;
100.1392 +
100.1393 +	GLint			u_ParallaxMapping;
100.1394 +	qboolean		t_ParallaxMapping;
100.1395 +
100.1396 +	GLint           u_DepthScale;
100.1397 +	float			t_DepthScale;
100.1398 +
100.1399 +
100.1400 +	GLint			u_PortalClipping;
100.1401 +	qboolean		t_PortalClipping;
100.1402 +
100.1403 +	GLint			u_PortalPlane;
100.1404 +	vec4_t			t_PortalPlane;
100.1405 +
100.1406 +	GLint           u_PortalRange;
100.1407 +	float			t_PortalRange;
100.1408 +
100.1409 +
100.1410 +	GLint			u_HDRKey;
100.1411 +	GLint			u_HDRAverageLuminance;
100.1412 +	GLint			u_HDRMaxLuminance;
100.1413 +
100.1414 +	GLint           u_DeformMagnitude;
100.1415 +	GLint           u_BlurMagnitude;
100.1416 +
100.1417 +
100.1418 +	GLint           u_ModelMatrix;	// model -> world
100.1419 +	matrix_t		t_ModelMatrix;
100.1420 +
100.1421 +//	GLint           u_ViewMatrix;	// world -> camera
100.1422 +//	matrix_t		t_ViewMatrix;
100.1423 +
100.1424 +	GLint           u_ModelViewMatrix;	// model -> camera
100.1425 +	matrix_t		t_ModelViewMatrix;
100.1426 +
100.1427 +	GLint           u_ModelViewMatrixTranspose;
100.1428 +	matrix_t		t_ModelViewMatrixTranspose;
100.1429 +
100.1430 +	GLint           u_ProjectionMatrix;
100.1431 +	matrix_t		t_ProjectionMatrix;
100.1432 +
100.1433 +	GLint           u_ProjectionMatrixTranspose;
100.1434 +	matrix_t		t_ProjectionMatrixTranspose;
100.1435 +
100.1436 +	GLint           u_ModelViewProjectionMatrix;
100.1437 +	matrix_t		t_ModelViewProjectionMatrix;
100.1438 +
100.1439 +	GLint           u_UnprojectMatrix;
100.1440 +	matrix_t		t_UnprojectMatrix;
100.1441 +
100.1442 +	GLint           u_VertexSkinning;
100.1443 +	qboolean		t_VertexSkinning;
100.1444 +
100.1445 +	GLint           u_BoneMatrix;
100.1446 +} shaderProgram_t;
100.1447 +
100.1448 +//
100.1449 +// Tr3B: these are fire wall functions to avoid expensive redundant glUniform* calls
100.1450 +#define USE_UNIFORM_FIREWALL 1
100.1451 +static ID_INLINE void GLSL_SetUniform_ColorTextureMatrix(shaderProgram_t * program, const matrix_t m)
100.1452 +{
100.1453 +#if defined(USE_UNIFORM_FIREWALL)
100.1454 +	if(MatrixCompare(program->t_ColorTextureMatrix, m))
100.1455 +		return;
100.1456 +
100.1457 +	MatrixCopy(m, program->t_ColorTextureMatrix);
100.1458 +#endif
100.1459 +
100.1460 +	qglUniformMatrix4fvARB(program->u_ColorTextureMatrix, 1, GL_FALSE, m);
100.1461 +}
100.1462 +
100.1463 +static ID_INLINE void GLSL_SetUniform_DiffuseTextureMatrix(shaderProgram_t * program, const matrix_t m)
100.1464 +{
100.1465 +#if defined(USE_UNIFORM_FIREWALL)
100.1466 +	if(MatrixCompare(program->t_DiffuseTextureMatrix, m))
100.1467 +		return;
100.1468 +
100.1469 +	MatrixCopy(m, program->t_DiffuseTextureMatrix);
100.1470 +#endif
100.1471 +
100.1472 +	qglUniformMatrix4fvARB(program->u_DiffuseTextureMatrix, 1, GL_FALSE, m);
100.1473 +}
100.1474 +
100.1475 +static ID_INLINE void GLSL_SetUniform_NormalTextureMatrix(shaderProgram_t * program, const matrix_t m)
100.1476 +{
100.1477 +#if defined(USE_UNIFORM_FIREWALL)
100.1478 +	if(MatrixCompare(program->t_NormalTextureMatrix, m))
100.1479 +		return;
100.1480 +
100.1481 +	MatrixCopy(m, program->t_NormalTextureMatrix);
100.1482 +#endif
100.1483 +
100.1484 +	qglUniformMatrix4fvARB(program->u_NormalTextureMatrix, 1, GL_FALSE, m);
100.1485 +}
100.1486 +
100.1487 +static ID_INLINE void GLSL_SetUniform_SpecularTextureMatrix(shaderProgram_t * program, const matrix_t m)
100.1488 +{
100.1489 +#if defined(USE_UNIFORM_FIREWALL)
100.1490 +	if(MatrixCompare(program->t_SpecularTextureMatrix, m))
100.1491 +		return;
100.1492 +
100.1493 +	MatrixCopy(m, program->t_SpecularTextureMatrix);
100.1494 +#endif
100.1495 +
100.1496 +	qglUniformMatrix4fvARB(program->u_SpecularTextureMatrix, 1, GL_FALSE, m);
100.1497 +}
100.1498 +
100.1499 +
100.1500 +static ID_INLINE void GLSL_SetUniform_AlphaTest(shaderProgram_t * program, unsigned long stateBits)
100.1501 +{
100.1502 +	alphaTest_t			value;
100.1503 +
100.1504 +	switch (stateBits & GLS_ATEST_BITS)
100.1505 +	{
100.1506 +		case GLS_ATEST_GT_0:
100.1507 +			value = ATEST_GT_0;
100.1508 +			break;
100.1509 +
100.1510 +		case GLS_ATEST_LT_128:
100.1511 +			value = ATEST_LT_128;
100.1512 +			break;
100.1513 +
100.1514 +		case GLS_ATEST_GE_128:
100.1515 +			value = ATEST_GE_128;
100.1516 +			break;
100.1517 +
100.1518 +		default:
100.1519 +			value = ATEST_NONE;
100.1520 +	}
100.1521 +
100.1522 +#if defined(USE_UNIFORM_FIREWALL)
100.1523 +	if(program->t_AlphaTest == value)
100.1524 +		return;
100.1525 +
100.1526 +	program->t_AlphaTest = value;
100.1527 +#endif
100.1528 +
100.1529 +	qglUniform1iARB(program->u_AlphaTest, value);
100.1530 +}
100.1531 +
100.1532 +static ID_INLINE void GLSL_SetUniform_ViewOrigin(shaderProgram_t * program, const vec3_t v)
100.1533 +{
100.1534 +#if defined(USE_UNIFORM_FIREWALL)
100.1535 +	if(VectorCompare(program->t_ViewOrigin, v))
100.1536 +		return;
100.1537 +
100.1538 +	VectorCopy(v, program->t_ViewOrigin);
100.1539 +#endif
100.1540 +
100.1541 +	qglUniform3fARB(program->u_ViewOrigin, v[0], v[1], v[2]);
100.1542 +}
100.1543 +
100.1544 +static ID_INLINE void GLSL_SetUniform_TCGen_Environment(shaderProgram_t * program, qboolean value)
100.1545 +{
100.1546 +#if defined(USE_UNIFORM_FIREWALL)
100.1547 +	if(program->t_TCGen_Environment == value)
100.1548 +		return;
100.1549 +
100.1550 +	program->t_TCGen_Environment = value;
100.1551 +#endif
100.1552 +
100.1553 +	qglUniform1iARB(program->u_TCGen_Environment, value);
100.1554 +}
100.1555 +
100.1556 +static ID_INLINE void GLSL_SetUniform_ColorGen(shaderProgram_t * program, colorGen_t value)
100.1557 +{
100.1558 +#if 0
100.1559 +	float			floatValue;
100.1560 +
100.1561 +	switch (value)
100.1562 +	{
100.1563 +		case CGEN_VERTEX:
100.1564 +			floatValue = 1.0f;
100.1565 +			break;
100.1566 +
100.1567 +		case CGEN_ONE_MINUS_VERTEX:
100.1568 +			floatValue = -1.0f;
100.1569 +			break;
100.1570 +
100.1571 +		default:
100.1572 +			floatValue = 0.0f;
100.1573 +			break;
100.1574 +	}
100.1575 +
100.1576 +#if defined(USE_UNIFORM_FIREWALL)
100.1577 +	if(program->t_ColorGen == floatValue)
100.1578 +		return;
100.1579 +
100.1580 +	program->t_ColorGen = floatValue;
100.1581 +#endif
100.1582 +
100.1583 +	qglUniform1fARB(program->u_ColorGen, floatValue);
100.1584 +#else
100.1585 +#if defined(USE_UNIFORM_FIREWALL)
100.1586 +	if(program->t_ColorGen == value)
100.1587 +		return;
100.1588 +
100.1589 +	program->t_ColorGen = value;
100.1590 +#endif
100.1591 +
100.1592 +	qglUniform1iARB(program->u_ColorGen, value);
100.1593 +#endif
100.1594 +}
100.1595 +
100.1596 +static ID_INLINE void GLSL_SetUniform_AlphaGen(shaderProgram_t * program, alphaGen_t value)
100.1597 +{
100.1598 +#if 0
100.1599 +	float			floatValue;
100.1600 +
100.1601 +	switch (value)
100.1602 +	{
100.1603 +		case AGEN_VERTEX:
100.1604 +			floatValue = 1.0f;
100.1605 +			break;
100.1606 +
100.1607 +		case AGEN_ONE_MINUS_VERTEX:
100.1608 +			floatValue = -1.0f;
100.1609 +			break;
100.1610 +
100.1611 +		default:
100.1612 +			floatValue = 0.0f;
100.1613 +			break;
100.1614 +	}
100.1615 +
100.1616 +#if defined(USE_UNIFORM_FIREWALL)
100.1617 +	if(program->t_AlphaGen == floatValue)
100.1618 +		return;
100.1619 +
100.1620 +	program->t_AlphaGen = floatValue;
100.1621 +#endif
100.1622 +
100.1623 +	qglUniform1fARB(program->u_AlphaGen, floatValue);
100.1624 +
100.1625 +#else
100.1626 +#if defined(USE_UNIFORM_FIREWALL)
100.1627 +	if(program->t_AlphaGen == value)
100.1628 +		return;
100.1629 +
100.1630 +	program->t_AlphaGen = value;
100.1631 +#endif
100.1632 +
100.1633 +	qglUniform1iARB(program->u_AlphaGen, value);
100.1634 +#endif
100.1635 +}
100.1636 +
100.1637 +static ID_INLINE void GLSL_SetUniform_Color(shaderProgram_t * program, const vec4_t v)
100.1638 +{
100.1639 +#if defined(USE_UNIFORM_FIREWALL)
100.1640 +	if(VectorCompare4(program->t_Color, v))
100.1641 +		return;
100.1642 +
100.1643 +	VectorCopy4(v, program->t_Color);
100.1644 +#endif
100.1645 +
100.1646 +	qglUniform4fARB(program->u_Color, v[0], v[1], v[2], v[3]);
100.1647 +}
100.1648 +
100.1649 +static ID_INLINE void GLSL_SetUniform_AmbientColor(shaderProgram_t * program, const vec3_t v)
100.1650 +{
100.1651 +#if defined(USE_UNIFORM_FIREWALL)
100.1652 +	if(VectorCompare(program->t_AmbientColor, v))
100.1653 +		return;
100.1654 +
100.1655 +	VectorCopy(v, program->t_AmbientColor);
100.1656 +#endif
100.1657 +
100.1658 +	qglUniform3fARB(program->u_AmbientColor, v[0], v[1], v[2]);
100.1659 +}
100.1660 +
100.1661 +static ID_INLINE void GLSL_SetUniform_LightDir(shaderProgram_t * program, const vec3_t v)
100.1662 +{
100.1663 +#if defined(USE_UNIFORM_FIREWALL)
100.1664 +	if(VectorCompare(program->t_LightDir, v))
100.1665 +		return;
100.1666 +
100.1667 +	VectorCopy(v, program->t_LightDir);
100.1668 +#endif
100.1669 +
100.1670 +	qglUniform3fARB(program->u_LightDir, v[0], v[1], v[2]);
100.1671 +}
100.1672 +
100.1673 +static ID_INLINE void GLSL_SetUniform_LightOrigin(shaderProgram_t * program, const vec3_t v)
100.1674 +{
100.1675 +#if defined(USE_UNIFORM_FIREWALL)
100.1676 +	if(VectorCompare(program->t_LightOrigin, v))
100.1677 +		return;
100.1678 +
100.1679 +	VectorCopy(v, program->t_LightOrigin);
100.1680 +#endif
100.1681 +
100.1682 +	qglUniform3fARB(program->u_LightOrigin, v[0], v[1], v[2]);
100.1683 +}
100.1684 +
100.1685 +static ID_INLINE void GLSL_SetUniform_LightColor(shaderProgram_t * program, const vec3_t v)
100.1686 +{
100.1687 +#if defined(USE_UNIFORM_FIREWALL)
100.1688 +	if(VectorCompare(program->t_LightColor, v))
100.1689 +		return;
100.1690 +
100.1691 +	VectorCopy(v, program->t_LightColor);
100.1692 +#endif
100.1693 +
100.1694 +	qglUniform3fARB(program->u_LightColor, v[0], v[1], v[2]);
100.1695 +}
100.1696 +
100.1697 +static ID_INLINE void GLSL_SetUniform_LightRadius(shaderProgram_t * program, float value)
100.1698 +{
100.1699 +#if defined(USE_UNIFORM_FIREWALL)
100.1700 +	if(program->t_LightRadius == value)
100.1701 +		return;
100.1702 +
100.1703 +	program->t_LightRadius = value;
100.1704 +#endif
100.1705 +
100.1706 +	qglUniform1fARB(program->u_LightRadius, value);
100.1707 +}
100.1708 +
100.1709 +static ID_INLINE void GLSL_SetUniform_LightScale(shaderProgram_t * program, float value)
100.1710 +{
100.1711 +#if defined(USE_UNIFORM_FIREWALL)
100.1712 +	if(program->t_LightScale == value)
100.1713 +		return;
100.1714 +
100.1715 +	program->t_LightScale = value;
100.1716 +#endif
100.1717 +
100.1718 +	qglUniform1fARB(program->u_LightScale, value);
100.1719 +}
100.1720 +
100.1721 +static ID_INLINE void GLSL_SetUniform_LightAttenuationMatrix(shaderProgram_t * program, const matrix_t m)
100.1722 +{
100.1723 +#if defined(USE_UNIFORM_FIREWALL)
100.1724 +	if(MatrixCompare(program->t_LightAttenuationMatrix, m))
100.1725 +		return;
100.1726 +
100.1727 +	MatrixCopy(m, program->t_LightAttenuationMatrix);
100.1728 +#endif
100.1729 +
100.1730 +	qglUniformMatrix4fvARB(program->u_LightAttenuationMatrix, 1, GL_FALSE, m);
100.1731 +}
100.1732 +
100.1733 +/*
100.1734 +static ID_INLINE void GLSL_SetUniform_LightFrustum(shaderProgram_t * program, vec4_t lightFrustum[6])
100.1735 +{
100.1736 +	vec4_t          lightFrustum[6];
100.1737 +#if 1
100.1738 +	if(memcmp(program->t_LightFrustum, m))
100.1739 +		return;
100.1740 +#endif
100.1741 +
100.1742 +	qglUniform4fvARB(tr.deferredLightingShader_DBS_omni.u_LightFrustum, 6, &lightFrustum[0][0]);
100.1743 +}
100.1744 +*/
100.1745 +
100.1746 +
100.1747 +static ID_INLINE void GLSL_SetUniform_ShadowMatrix(shaderProgram_t * program, const matrix_t m)
100.1748 +{
100.1749 +#if defined(USE_UNIFORM_FIREWALL)
100.1750 +	if(MatrixCompare(program->t_ShadowMatrix, m))
100.1751 +		return;
100.1752 +
100.1753 +	MatrixCopy(m, program->t_ShadowMatrix);
100.1754 +#endif
100.1755 +
100.1756 +	qglUniformMatrix4fvARB(program->u_ShadowMatrix, 1, GL_FALSE, m);
100.1757 +}
100.1758 +
100.1759 +static ID_INLINE void GLSL_SetUniform_ShadowCompare(shaderProgram_t * program, qboolean value)
100.1760 +{
100.1761 +#if defined(USE_UNIFORM_FIREWALL)
100.1762 +	if(program->t_ShadowCompare == value)
100.1763 +		return;
100.1764 +
100.1765 +	program->t_ShadowCompare = value;
100.1766 +#endif
100.1767 +
100.1768 +	qglUniform1iARB(program->u_ShadowCompare, value);
100.1769 +}
100.1770 +
100.1771 +static ID_INLINE void GLSL_SetUniform_ShadowTexelSize(shaderProgram_t * program, float value)
100.1772 +{
100.1773 +#if defined(USE_UNIFORM_FIREWALL)
100.1774 +	if(program->t_ShadowTexelSize == value)
100.1775 +		return;
100.1776 +
100.1777 +	program->t_ShadowTexelSize = value;
100.1778 +#endif
100.1779 +
100.1780 +	qglUniform1fARB(program->u_ShadowTexelSize, value);
100.1781 +}
100.1782 +
100.1783 +static ID_INLINE void GLSL_SetUniform_ShadowBlur(shaderProgram_t * program, float value)
100.1784 +{
100.1785 +#if defined(USE_UNIFORM_FIREWALL)
100.1786 +	if(program->t_ShadowBlur == value)
100.1787 +		return;
100.1788 +
100.1789 +	program->t_ShadowBlur = value;
100.1790 +#endif
100.1791 +
100.1792 +	qglUniform1fARB(program->u_ShadowBlur, value);
100.1793 +}
100.1794 +
100.1795 +static ID_INLINE void GLSL_SetUniform_RefractionIndex(shaderProgram_t * program, float value)
100.1796 +{
100.1797 +#if defined(USE_UNIFORM_FIREWALL)
100.1798 +	if(program->t_RefractionIndex == value)
100.1799 +		return;
100.1800 +
100.1801 +	program->t_RefractionIndex = value;
100.1802 +#endif
100.1803 +
100.1804 +	qglUniform1fARB(program->u_RefractionIndex, value);
100.1805 +}
100.1806 +
100.1807 +static ID_INLINE void GLSL_SetUniform_ParallaxMapping(shaderProgram_t * program, qboolean value)
100.1808 +{
100.1809 +#if defined(USE_UNIFORM_FIREWALL)
100.1810 +	if(program->t_ParallaxMapping == value)
100.1811 +		return;
100.1812 +
100.1813 +	program->t_ParallaxMapping = value;
100.1814 +#endif
100.1815 +
100.1816 +	qglUniform1iARB(program->u_ParallaxMapping, value);
100.1817 +}
100.1818 +
100.1819 +static ID_INLINE void GLSL_SetUniform_DepthScale(shaderProgram_t * program, float value)
100.1820 +{
100.1821 +#if defined(USE_UNIFORM_FIREWALL)
100.1822 +	if(program->t_DepthScale == value)
100.1823 +		return;
100.1824 +
100.1825 +	program->t_DepthScale = value;
100.1826 +#endif
100.1827 +
100.1828 +	qglUniform1fARB(program->u_DepthScale, value);
100.1829 +}
100.1830 +
100.1831 +static ID_INLINE void GLSL_SetUniform_PortalClipping(shaderProgram_t * program, qboolean value)
100.1832 +{
100.1833 +#if defined(USE_UNIFORM_FIREWALL)
100.1834 +	if(program->t_PortalClipping == value)
100.1835 +		return;
100.1836 +
100.1837 +	program->t_PortalClipping = value;
100.1838 +#endif
100.1839 +
100.1840 +	qglUniform1iARB(program->u_PortalClipping, value);
100.1841 +}
100.1842 +
100.1843 +static ID_INLINE void GLSL_SetUniform_PortalPlane(shaderProgram_t * program, const vec4_t v)
100.1844 +{
100.1845 +#if defined(USE_UNIFORM_FIREWALL)
100.1846 +	if(VectorCompare4(program->t_PortalPlane, v))
100.1847 +		return;
100.1848 +
100.1849 +	VectorCopy(v, program->t_PortalPlane);
100.1850 +#endif
100.1851 +
100.1852 +	qglUniform4fARB(program->u_PortalPlane, v[0], v[1], v[2], v[3]);
100.1853 +}
100.1854 +
100.1855 +static ID_INLINE void GLSL_SetUniform_PortalRange(shaderProgram_t * program, float value)
100.1856 +{
100.1857 +#if defined(USE_UNIFORM_FIREWALL)
100.1858 +	if(program->t_PortalRange == value)
100.1859 +		return;
100.1860 +
100.1861 +	program->t_PortalRange = value;
100.1862 +#endif
100.1863 +
100.1864 +	qglUniform1fARB(program->u_PortalRange, value);
100.1865 +}
100.1866 +
100.1867 +static ID_INLINE void GLSL_SetUniform_ModelMatrix(shaderProgram_t * program, const matrix_t m)
100.1868 +{
100.1869 +#if defined(USE_UNIFORM_FIREWALL)
100.1870 +	if(MatrixCompare(program->t_ModelMatrix, m))
100.1871 +		return;
100.1872 +
100.1873 +	MatrixCopy(m, program->t_ModelMatrix);
100.1874 +#endif
100.1875 +
100.1876 +	qglUniformMatrix4fvARB(program->u_ModelMatrix, 1, GL_FALSE, m);
100.1877 +}
100.1878 +
100.1879 +static ID_INLINE void GLSL_SetUniform_ModelViewMatrix(shaderProgram_t * program, const matrix_t m)
100.1880 +{
100.1881 +#if defined(USE_UNIFORM_FIREWALL)
100.1882 +	if(MatrixCompare(program->t_ModelViewMatrix, m))
100.1883 +		return;
100.1884 +
100.1885 +	MatrixCopy(m, program->t_ModelViewMatrix);
100.1886 +#endif
100.1887 +
100.1888 +	qglUniformMatrix4fvARB(program->u_ModelViewMatrix, 1, GL_FALSE, m);
100.1889 +}
100.1890 +
100.1891 +static ID_INLINE void GLSL_SetUniform_ModelViewMatrixTranspose(shaderProgram_t * program, const matrix_t m)
100.1892 +{
100.1893 +#if defined(USE_UNIFORM_FIREWALL)
100.1894 +	if(MatrixCompare(program->t_ModelViewMatrixTranspose, m))
100.1895 +		return;
100.1896 +
100.1897 +	MatrixCopy(m, program->t_ModelViewMatrixTranspose);
100.1898 +#endif
100.1899 +
100.1900 +	qglUniformMatrix4fvARB(program->u_ModelViewMatrixTranspose, 1, GL_TRUE, m);
100.1901 +}
100.1902 +
100.1903 +static ID_INLINE void GLSL_SetUniform_ProjectionMatrix(shaderProgram_t * program, const matrix_t m)
100.1904 +{
100.1905 +#if defined(USE_UNIFORM_FIREWALL)
100.1906 +	if(MatrixCompare(program->t_ProjectionMatrix, m))
100.1907 +		return;
100.1908 +
100.1909 +	MatrixCopy(m, program->t_ProjectionMatrix);
100.1910 +#endif
100.1911 +
100.1912 +	qglUniformMatrix4fvARB(program->u_ProjectionMatrix, 1, GL_FALSE, m);
100.1913 +}
100.1914 +
100.1915 +static ID_INLINE void GLSL_SetUniform_ProjectionMatrixTranspose(shaderProgram_t * program, const matrix_t m)
100.1916 +{
100.1917 +#if defined(USE_UNIFORM_FIREWALL)
100.1918 +	if(MatrixCompare(program->t_ProjectionMatrixTranspose, m))
100.1919 +		return;
100.1920 +
100.1921 +	MatrixCopy(m, program->t_ProjectionMatrixTranspose);
100.1922 +#endif
100.1923 +
100.1924 +	qglUniformMatrix4fvARB(program->u_ProjectionMatrixTranspose, 1, GL_TRUE, m);
100.1925 +}
100.1926 +
100.1927 +static ID_INLINE void GLSL_SetUniform_ModelViewProjectionMatrix(shaderProgram_t * program, const matrix_t m)
100.1928 +{
100.1929 +#if defined(USE_UNIFORM_FIREWALL)
100.1930 +	if(MatrixCompare(program->t_ModelViewProjectionMatrix, m))
100.1931 +		return;
100.1932 +
100.1933 +	MatrixCopy(m, program->t_ModelViewProjectionMatrix);
100.1934 +#endif
100.1935 +
100.1936 +	qglUniformMatrix4fvARB(program->u_ModelViewProjectionMatrix, 1, GL_FALSE, m);
100.1937 +}
100.1938 +
100.1939 +static ID_INLINE void GLSL_SetUniform_UnprojectMatrix(shaderProgram_t * program, const matrix_t m)
100.1940 +{
100.1941 +#if defined(USE_UNIFORM_FIREWALL)
100.1942 +	if(MatrixCompare(program->t_UnprojectMatrix, m))
100.1943 +		return;
100.1944 +
100.1945 +	MatrixCopy(m, program->t_UnprojectMatrix);
100.1946 +#endif
100.1947 +
100.1948 +	qglUniformMatrix4fvARB(program->u_UnprojectMatrix, 1, GL_FALSE, m);
100.1949 +}
100.1950 +
100.1951 +static ID_INLINE void GLSL_SetUniform_VertexSkinning(shaderProgram_t * program, qboolean value)
100.1952 +{
100.1953 +#if defined(USE_UNIFORM_FIREWALL)
100.1954 +	if(program->t_VertexSkinning == value)
100.1955 +		return;
100.1956 +
100.1957 +	program->t_VertexSkinning = value;
100.1958 +#endif
100.1959 +
100.1960 +	qglUniform1iARB(program->u_VertexSkinning, value);
100.1961 +}
100.1962 +
100.1963 +
100.1964 +
100.1965 +
100.1966 +
100.1967 +
100.1968 +
100.1969 +
100.1970 +
100.1971 +
100.1972  
100.1973  // trRefdef_t holds everything that comes in refdef_t,
100.1974  // as well as the locally generated scene information
100.1975 -typedef struct {
100.1976 -	int			x, y, width, height;
100.1977 -	float		fov_x, fov_y;
100.1978 -	vec3_t		vieworg;
100.1979 -	vec3_t		viewaxis[3];		// transformation matrix
100.1980 -
100.1981 -	stereoFrame_t	stereoFrame;
100.1982 -
100.1983 -	int			time;				// time in milliseconds for shader effects and other time dependent rendering issues
100.1984 -	int			rdflags;			// RDF_NOWORLDMODEL, etc
100.1985 +typedef struct
100.1986 +{
100.1987 +	int             x, y, width, height;
100.1988 +	float           fov_x, fov_y;
100.1989 +	vec3_t          vieworg;
100.1990 +	vec3_t          viewaxis[3];	// transformation matrix
100.1991 +
100.1992 +	int             time;		// time in milliseconds for shader effects and other time dependent rendering issues
100.1993 +	int             rdflags;	// RDF_NOWORLDMODEL, etc
100.1994  
100.1995  	// 1 bits will prevent the associated area from rendering at all
100.1996 -	byte		areamask[MAX_MAP_AREA_BYTES];
100.1997 -	qboolean	areamaskModified;	// qtrue if areamask changed since last scene
100.1998 -
100.1999 -	float		floatTime;			// tr.refdef.time / 1000.0
100.2000 +	byte            areamask[MAX_MAP_AREA_BYTES];
100.2001 +	qboolean        areamaskModified;	// qtrue if areamask changed since last scene
100.2002 +
100.2003 +	float           floatTime;	// tr.refdef.time / 1000.0
100.2004  
100.2005  	// text messages for deform text shaders
100.2006 -	char		text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH];
100.2007 -
100.2008 -	int			num_entities;
100.2009 -	trRefEntity_t	*entities;
100.2010 -
100.2011 -	int			num_dlights;
100.2012 -	struct dlight_s	*dlights;
100.2013 -
100.2014 -	int			numPolys;
100.2015 -	struct srfPoly_s	*polys;
100.2016 -
100.2017 -	int			numDrawSurfs;
100.2018 -	struct drawSurf_s	*drawSurfs;
100.2019 -
100.2020 -
100.2021 +	char            text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH];
100.2022 +
100.2023 +	int             numEntities;
100.2024 +	trRefEntity_t  *entities;
100.2025 +
100.2026 +	int             numLights;
100.2027 +	trRefLight_t   *lights;
100.2028 +
100.2029 +	int             numPolys;
100.2030 +	struct srfPoly_s *polys;
100.2031 +
100.2032 +	int             numDrawSurfs;
100.2033 +	struct drawSurf_s *drawSurfs;
100.2034 +
100.2035 +	int             numInteractions;
100.2036 +	struct interaction_s *interactions;
100.2037 +
100.2038 +	byte           *pixelTarget;		//set this to Non Null to copy to a buffer after scene rendering
100.2039 +	int             pixelTargetWidth;
100.2040 +	int             pixelTargetHeight;
100.2041  } trRefdef_t;
100.2042  
100.2043  
100.2044  //=================================================================================
100.2045  
100.2046  // skins allow models to be retextured without modifying the model file
100.2047 -typedef struct {
100.2048 -	char		name[MAX_QPATH];
100.2049 -	shader_t	*shader;
100.2050 +typedef struct
100.2051 +{
100.2052 +	char            name[MAX_QPATH];
100.2053 +	shader_t       *shader;
100.2054  } skinSurface_t;
100.2055  
100.2056 -typedef struct skin_s {
100.2057 -	char		name[MAX_QPATH];		// game path, including extension
100.2058 -	int			numSurfaces;
100.2059 -	skinSurface_t	*surfaces[MD3_MAX_SURFACES];
100.2060 +typedef struct skin_s
100.2061 +{
100.2062 +	char            name[MAX_QPATH];	// game path, including extension
100.2063 +	int             numSurfaces;
100.2064 +	skinSurface_t  *surfaces[MD3_MAX_SURFACES];
100.2065  } skin_t;
100.2066  
100.2067 -
100.2068 -typedef struct {
100.2069 -	int			originalBrushNumber;
100.2070 -	vec3_t		bounds[2];
100.2071 -
100.2072 -	unsigned	colorInt;				// in packed byte format
100.2073 -	float		tcScale;				// texture coordinate vector scales
100.2074 -	fogParms_t	parms;
100.2075 -
100.2076 -	// for clipping distance in fog when outside
100.2077 -	qboolean	hasSurface;
100.2078 -	float		surface[4];
100.2079 -} fog_t;
100.2080 -
100.2081 -typedef struct {
100.2082 -	orientationr_t	or;
100.2083 -	orientationr_t	world;
100.2084 -	vec3_t		pvsOrigin;			// may be different than or.origin for portals
100.2085 -	qboolean	isPortal;			// true if this view is through a portal
100.2086 -	qboolean	isMirror;			// the portal is a mirror, invert the face culling
100.2087 -	int			frameSceneNum;		// copied from tr.frameSceneNum
100.2088 -	int			frameCount;			// copied from tr.frameCount
100.2089 -	cplane_t	portalPlane;		// clip anything behind this if mirroring
100.2090 -	int			viewportX, viewportY, viewportWidth, viewportHeight;
100.2091 -	float		fovX, fovY;
100.2092 -	float		projectionMatrix[16];
100.2093 -	cplane_t	frustum[4];
100.2094 -	vec3_t		visBounds[2];
100.2095 -	float		zFar;
100.2096 -	stereoFrame_t	stereoFrame;
100.2097 +typedef struct
100.2098 +{
100.2099 +	orientationr_t  orientation;
100.2100 +	orientationr_t  world;
100.2101 +
100.2102 +	vec3_t          pvsOrigin;	// may be different than or.origin for portals
100.2103 +
100.2104 +	qboolean        isPortal;	// true if this view is through a portal
100.2105 +	qboolean        isMirror;	// the portal is a mirror, invert the face culling
100.2106 +
100.2107 +	int             frameSceneNum;	// copied from tr.frameSceneNum
100.2108 +	int             frameCount;	// copied from tr.frameCount
100.2109 +
100.2110 +	cplane_t        portalPlane;	// clip anything behind this if mirroring
100.2111 +	int             viewportX, viewportY, viewportWidth, viewportHeight;
100.2112 +	vec4_t          viewportVerts[4];	// for immediate 2D quad rendering
100.2113 +
100.2114 +	float           fovX, fovY;
100.2115 +	matrix_t        projectionMatrix;
100.2116 +	matrix_t        unprojectionMatrix;	// transform pixel window space -> world space
100.2117 +
100.2118 +	frustum_t       frustum;
100.2119 +
100.2120 +	vec3_t          visBounds[2];
100.2121 +	float           skyFar;
100.2122 +
100.2123 +	int             numDrawSurfs;
100.2124 +	struct drawSurf_s *drawSurfs;
100.2125 +
100.2126 +	int             numInteractions;
100.2127 +	struct interaction_s *interactions;
100.2128  } viewParms_t;
100.2129  
100.2130  
100.2131 @@ -522,264 +1801,703 @@
100.2132  */
100.2133  
100.2134  // any changes in surfaceType must be mirrored in rb_surfaceTable[]
100.2135 -typedef enum {
100.2136 +typedef enum
100.2137 +{
100.2138  	SF_BAD,
100.2139 -	SF_SKIP,				// ignore
100.2140 +	SF_SKIP,					// ignore
100.2141  	SF_FACE,
100.2142  	SF_GRID,
100.2143  	SF_TRIANGLES,
100.2144  	SF_POLY,
100.2145 -	SF_MD3,
100.2146 -	SF_MD4,
100.2147 -#ifdef RAVENMD4
100.2148 -	SF_MDR,
100.2149 -#endif
100.2150 +	SF_MDX,
100.2151 +	SF_MD5,
100.2152  	SF_FLARE,
100.2153 -	SF_ENTITY,				// beams, rails, lightning, etc that can be determined by entity
100.2154 -	SF_DISPLAY_LIST,
100.2155 +	SF_ENTITY,					// beams, rails, lightning, etc that can be determined by entity
100.2156 +	SF_VBO_MESH,
100.2157 +	SF_VBO_MD5MESH,
100.2158 +	SF_VBO_SHADOW_VOLUME,
100.2159  
100.2160  	SF_NUM_SURFACE_TYPES,
100.2161  	SF_MAX = 0x7fffffff			// ensures that sizeof( surfaceType_t ) == sizeof( int )
100.2162  } surfaceType_t;
100.2163  
100.2164 -typedef struct drawSurf_s {
100.2165 -	unsigned			sort;			// bit combination for fast compares
100.2166 -	surfaceType_t		*surface;		// any of surface*_t
100.2167 +typedef struct drawSurf_s
100.2168 +{
100.2169 +	trRefEntity_t  *entity;
100.2170 +	int             shaderNum;
100.2171 +	int             lightmapNum;
100.2172 +
100.2173 +	surfaceType_t  *surface;	// any of surface*_t
100.2174  } drawSurf_t;
100.2175  
100.2176 +typedef enum
100.2177 +{
100.2178 +	IA_DEFAULT,					// lighting and shadowing
100.2179 +	IA_SHADOWONLY,
100.2180 +	IA_LIGHTONLY
100.2181 +} interactionType_t;
100.2182 +
100.2183 +// an interactionCache is a node between a light and a precached world surface
100.2184 +typedef struct interactionCache_s
100.2185 +{
100.2186 +	interactionType_t type;
100.2187 +
100.2188 +	struct bspSurface_s *surface;
100.2189 +
100.2190 +	byte            cubeSideBits;
100.2191 +	qboolean        redundant;
100.2192 +
100.2193 +	struct interactionCache_s *next;
100.2194 +} interactionCache_t;
100.2195 +
100.2196 +typedef struct interactionVBO_s
100.2197 +{
100.2198 +	interactionType_t type;
100.2199 +
100.2200 +	byte            cubeSideBits;
100.2201 +
100.2202 +	struct shader_s *shader;
100.2203 +	struct srfVBOMesh_s *vboLightMesh;
100.2204 +	struct srfVBOMesh_s *vboShadowMesh;
100.2205 +	struct srfVBOShadowVolume_s *vboShadowVolume;	// only if cg_shadows 3
100.2206 +
100.2207 +	struct interactionVBO_s *next;
100.2208 +} interactionVBO_t;
100.2209 +
100.2210 +// an interaction is a node between a light and any surface
100.2211 +typedef struct interaction_s
100.2212 +{
100.2213 +	interactionType_t type;
100.2214 +
100.2215 +	trRefLight_t   *light;
100.2216 +
100.2217 +	trRefEntity_t  *entity;
100.2218 +	surfaceType_t  *surface;	// any of surface*_t
100.2219 +	shader_t       *surfaceShader;
100.2220 +
100.2221 +	byte            cubeSideBits;
100.2222 +
100.2223 +	int             scissorX, scissorY, scissorWidth, scissorHeight;
100.2224 +
100.2225 +	float           depthNear;	// for GL_EXT_depth_bounds_test
100.2226 +	float           depthFar;
100.2227 +	qboolean        noDepthBoundsTest;
100.2228 +
100.2229 +	int             occlusionQuerySamples;	// visible fragment count
100.2230 +	qboolean        noOcclusionQueries;
100.2231 +
100.2232 +	struct interaction_s *next;
100.2233 +} interaction_t;
100.2234 +
100.2235 +typedef struct
100.2236 +{
100.2237 +	int             numDegenerated;	// number of bad triangles
100.2238 +	qboolean        degenerated[SHADER_MAX_TRIANGLES];
100.2239 +
100.2240 +	qboolean        facing[SHADER_MAX_TRIANGLES];
100.2241 +	int             numFacing;	// number of triangles facing the light origin
100.2242 +
100.2243 +	int             numIndexes;
100.2244 +	int             indexes[SHADER_MAX_INDEXES];
100.2245 +} shadowState_t;
100.2246 +
100.2247 +extern shadowState_t sh;
100.2248 +
100.2249 +
100.2250  #define	MAX_FACE_POINTS		64
100.2251  
100.2252 -#define	MAX_PATCH_SIZE		32			// max dimensions of a patch mesh in map file
100.2253 -#define	MAX_GRID_SIZE		65			// max dimensions of a grid mesh in memory
100.2254 +#define	MAX_PATCH_SIZE		64	// max dimensions of a patch mesh in map file
100.2255 +#define	MAX_GRID_SIZE		65	// max dimensions of a grid mesh in memory
100.2256  
100.2257  // when cgame directly specifies a polygon, it becomes a srfPoly_t
100.2258  // as soon as it is called
100.2259 -typedef struct srfPoly_s {
100.2260 -	surfaceType_t	surfaceType;
100.2261 -	qhandle_t		hShader;
100.2262 -	int				fogIndex;
100.2263 -	int				numVerts;
100.2264 -	polyVert_t		*verts;
100.2265 +typedef struct srfPoly_s
100.2266 +{
100.2267 +	surfaceType_t   surfaceType;
100.2268 +	qhandle_t       hShader;
100.2269 +	int             numVerts;
100.2270 +	polyVert_t     *verts;
100.2271  } srfPoly_t;
100.2272  
100.2273 -typedef struct srfDisplayList_s {
100.2274 -	surfaceType_t	surfaceType;
100.2275 -	int				listNum;
100.2276 -} srfDisplayList_t;
100.2277 -
100.2278 -
100.2279 -typedef struct srfFlare_s {
100.2280 -	surfaceType_t	surfaceType;
100.2281 -	vec3_t			origin;
100.2282 -	vec3_t			normal;
100.2283 -	vec3_t			color;
100.2284 +typedef struct srfFlare_s
100.2285 +{
100.2286 +	surfaceType_t   surfaceType;
100.2287 +	vec3_t          origin;
100.2288 +	vec3_t          normal;
100.2289 +	vec3_t          color;
100.2290  } srfFlare_t;
100.2291  
100.2292 -typedef struct srfGridMesh_s {
100.2293 -	surfaceType_t	surfaceType;
100.2294 -
100.2295 -	// dynamic lighting information
100.2296 -	int				dlightBits[SMP_FRAMES];
100.2297 +typedef struct
100.2298 +{
100.2299 +	vec3_t          xyz;
100.2300 +	vec2_t          st;
100.2301 +	vec2_t          lightmap;
100.2302 +	vec3_t          tangent;
100.2303 +	vec3_t          binormal;
100.2304 +	vec3_t          normal;
100.2305 +	vec4_t          paintColor;
100.2306 +	vec4_t          lightColor;
100.2307 +	vec3_t          lightDirection;
100.2308 +
100.2309 +#if DEBUG_OPTIMIZEVERTICES
100.2310 +	unsigned int    id;
100.2311 +#endif
100.2312 +} srfVert_t;
100.2313 +
100.2314 +typedef struct
100.2315 +{
100.2316 +	int             indexes[3];
100.2317 +	int             neighbors[3];
100.2318 +	vec4_t          plane;
100.2319 +	qboolean        facingLight;
100.2320 +	qboolean        degenerated;
100.2321 +} srfTriangle_t;
100.2322 +
100.2323 +typedef struct srfGridMesh_s
100.2324 +{
100.2325 +	surfaceType_t   surfaceType;
100.2326  
100.2327  	// culling information
100.2328 -	vec3_t			meshBounds[2];
100.2329 -	vec3_t			localOrigin;
100.2330 -	float			meshRadius;
100.2331 +	vec3_t          meshBounds[2];
100.2332 +	vec3_t          localOrigin;
100.2333 +	float           meshRadius;
100.2334  
100.2335  	// lod information, which may be different
100.2336  	// than the culling information to allow for
100.2337  	// groups of curves that LOD as a unit
100.2338 -	vec3_t			lodOrigin;
100.2339 -	float			lodRadius;
100.2340 -	int				lodFixed;
100.2341 -	int				lodStitched;
100.2342 -
100.2343 -	// vertexes
100.2344 -	int				width, height;
100.2345 -	float			*widthLodError;
100.2346 -	float			*heightLodError;
100.2347 -	drawVert_t		verts[1];		// variable sized
100.2348 +	vec3_t          lodOrigin;
100.2349 +	float           lodRadius;
100.2350 +	int             lodFixed;
100.2351 +	int             lodStitched;
100.2352 +
100.2353 +	// triangle definitions
100.2354 +	int             width, height;
100.2355 +	float          *widthLodError;
100.2356 +	float          *heightLodError;
100.2357 +
100.2358 +	int             numTriangles;
100.2359 +	srfTriangle_t  *triangles;
100.2360 +
100.2361 +	int             numVerts;
100.2362 +	srfVert_t      *verts;
100.2363 +
100.2364 +	// BSP VBO offsets
100.2365 +	int             firstVert;
100.2366 +	int             firstTriangle;
100.2367  } srfGridMesh_t;
100.2368  
100.2369 -
100.2370 -
100.2371 -#define	VERTEXSIZE	8
100.2372 -typedef struct {
100.2373 -	surfaceType_t	surfaceType;
100.2374 -	cplane_t	plane;
100.2375 -
100.2376 -	// dynamic lighting information
100.2377 -	int			dlightBits[SMP_FRAMES];
100.2378 -
100.2379 -	// triangle definitions (no normals at points)
100.2380 -	int			numPoints;
100.2381 -	int			numIndices;
100.2382 -	int			ofsIndices;
100.2383 -	float		points[1][VERTEXSIZE];	// variable sized
100.2384 -										// there is a variable length list of indices here also
100.2385 +typedef struct
100.2386 +{
100.2387 +	surfaceType_t   surfaceType;
100.2388 +
100.2389 +	// culling information
100.2390 +	cplane_t        plane;
100.2391 +	vec3_t          bounds[2];
100.2392 +
100.2393 +	// triangle definitions
100.2394 +	int             numTriangles;
100.2395 +	srfTriangle_t  *triangles;
100.2396 +
100.2397 +	int             numVerts;
100.2398 +	srfVert_t      *verts;
100.2399 +
100.2400 +	// BSP VBO offsets
100.2401 +	int             firstVert;
100.2402 +	int             firstTriangle;
100.2403  } srfSurfaceFace_t;
100.2404  
100.2405  
100.2406 -// misc_models in maps are turned into direct geometry by q3map
100.2407 -typedef struct {
100.2408 -	surfaceType_t	surfaceType;
100.2409 -
100.2410 -	// dynamic lighting information
100.2411 -	int				dlightBits[SMP_FRAMES];
100.2412 -
100.2413 -	// culling information (FIXME: use this!)
100.2414 -	vec3_t			bounds[2];
100.2415 -	vec3_t			localOrigin;
100.2416 -	float			radius;
100.2417 +// misc_models in maps are turned into direct geometry by xmap
100.2418 +typedef struct
100.2419 +{
100.2420 +	surfaceType_t   surfaceType;
100.2421 +
100.2422 +	// culling information
100.2423 +	vec3_t          bounds[2];
100.2424  
100.2425  	// triangle definitions
100.2426 -	int				numIndexes;
100.2427 -	int				*indexes;
100.2428 -
100.2429 -	int				numVerts;
100.2430 -	drawVert_t		*verts;
100.2431 +	int             numTriangles;
100.2432 +	srfTriangle_t  *triangles;
100.2433 +
100.2434 +	int             numVerts;
100.2435 +	srfVert_t      *verts;
100.2436 +
100.2437 +	// BSP VBO offsets
100.2438 +	int             firstVert;
100.2439 +	int             firstTriangle;
100.2440  } srfTriangles_t;
100.2441  
100.2442 -
100.2443 -extern	void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])(void *);
100.2444 +typedef struct srfVBOMesh_s
100.2445 +{
100.2446 +	surfaceType_t   surfaceType;
100.2447 +
100.2448 +	struct shader_s *shader;	// FIXME move this to somewhere else
100.2449 +	int             lightmapNum;	// FIXME get rid of this by merging all lightmaps at level load
100.2450 +
100.2451 +	// culling information
100.2452 +	vec3_t          bounds[2];
100.2453 +
100.2454 +	// backEnd stats
100.2455 +	int             numIndexes;
100.2456 +	int             numVerts;
100.2457 +
100.2458 +	// static render data
100.2459 +	VBO_t          *vbo;
100.2460 +	IBO_t          *ibo;
100.2461 +} srfVBOMesh_t;
100.2462 +
100.2463 +typedef struct srfVBOMD5Mesh_s
100.2464 +{
100.2465 +	surfaceType_t   surfaceType;
100.2466 +
100.2467 +	struct md5Model_s *md5Model;
100.2468 +	struct shader_s *shader;	// FIXME move this to somewhere else
100.2469 +
100.2470 +	int				skinIndex;
100.2471 +
100.2472 +	int				numBoneRemap;
100.2473 +	int				boneRemap[MAX_BONES];
100.2474 +	int				boneRemapInverse[MAX_BONES];
100.2475 +
100.2476 +	// backEnd stats
100.2477 +	int             numIndexes;
100.2478 +	int             numVerts;
100.2479 +
100.2480 +	// static render data
100.2481 +	VBO_t          *vbo;
100.2482 +	IBO_t          *ibo;
100.2483 +} srfVBOMD5Mesh_t;
100.2484 +
100.2485 +typedef struct srfVBOShadowVolume_s
100.2486 +{
100.2487 +	surfaceType_t   surfaceType;
100.2488 +
100.2489 +	// backEnd stats
100.2490 +	int             numIndexes;
100.2491 +	int             numVerts;
100.2492 +
100.2493 +	// static render data
100.2494 +	VBO_t          *vbo;
100.2495 +	IBO_t          *ibo;
100.2496 +} srfVBOShadowVolume_t;
100.2497 +
100.2498 +
100.2499 +extern void     (*rb_surfaceTable[SF_NUM_SURFACE_TYPES]) (void *);
100.2500  
100.2501  /*
100.2502  ==============================================================================
100.2503 -
100.2504 -BRUSH MODELS
100.2505 -
100.2506 +BRUSH MODELS - in memory representation
100.2507  ==============================================================================
100.2508  */
100.2509 -
100.2510 -
100.2511 -//
100.2512 -// in memory representation
100.2513 -//
100.2514 -
100.2515 -#define	SIDE_FRONT	0
100.2516 -#define	SIDE_BACK	1
100.2517 -#define	SIDE_ON		2
100.2518 -
100.2519 -typedef struct msurface_s {
100.2520 -	int					viewCount;		// if == tr.viewCount, already added
100.2521 -	struct shader_s		*shader;
100.2522 -	int					fogIndex;
100.2523 -
100.2524 -	surfaceType_t		*data;			// any of srf*_t
100.2525 -} msurface_t;
100.2526 -
100.2527 +typedef struct bspSurface_s
100.2528 +{
100.2529 +	int             viewCount;	// if == tr.viewCount, already added
100.2530 +	int             lightCount;
100.2531 +	struct shader_s *shader;
100.2532 +	int             lightmapNum;	// -1 = no lightmap
100.2533 +
100.2534 +	surfaceType_t  *data;		// any of srf*_t
100.2535 +} bspSurface_t;
100.2536  
100.2537  
100.2538  #define	CONTENTS_NODE		-1
100.2539 -typedef struct mnode_s {
100.2540 +typedef struct bspNode_s
100.2541 +{
100.2542  	// common with leaf and node
100.2543 -	int			contents;		// -1 for nodes, to differentiate from leafs
100.2544 -	int			visframe;		// node needs to be traversed if current
100.2545 -	vec3_t		mins, maxs;		// for bounding box culling
100.2546 -	struct mnode_s	*parent;
100.2547 +	int             contents;	// -1 for nodes, to differentiate from leafs
100.2548 +	int             visCounts[MAX_VISCOUNTS];	// node needs to be traversed if current
100.2549 +	int             lightCount;
100.2550 +	vec3_t          mins, maxs;	// for bounding box culling
100.2551 +	struct bspNode_s *parent;
100.2552  
100.2553  	// node specific
100.2554 -	cplane_t	*plane;
100.2555 -	struct mnode_s	*children[2];	
100.2556 +	cplane_t       *plane;
100.2557 +	struct bspNode_s *children[2];
100.2558  
100.2559  	// leaf specific
100.2560 -	int			cluster;
100.2561 -	int			area;
100.2562 -
100.2563 -	msurface_t	**firstmarksurface;
100.2564 -	int			nummarksurfaces;
100.2565 -} mnode_t;
100.2566 -
100.2567 -typedef struct {
100.2568 -	vec3_t		bounds[2];		// for culling
100.2569 -	msurface_t	*firstSurface;
100.2570 -	int			numSurfaces;
100.2571 -} bmodel_t;
100.2572 -
100.2573 -typedef struct {
100.2574 -	char		name[MAX_QPATH];		// ie: maps/tim_dm2.bsp
100.2575 -	char		baseName[MAX_QPATH];	// ie: tim_dm2
100.2576 -
100.2577 -	int			dataSize;
100.2578 -
100.2579 -	int			numShaders;
100.2580 -	dshader_t	*shaders;
100.2581 -
100.2582 -	bmodel_t	*bmodels;
100.2583 -
100.2584 -	int			numplanes;
100.2585 -	cplane_t	*planes;
100.2586 -
100.2587 -	int			numnodes;		// includes leafs
100.2588 -	int			numDecisionNodes;
100.2589 -	mnode_t		*nodes;
100.2590 -
100.2591 -	int			numsurfaces;
100.2592 -	msurface_t	*surfaces;
100.2593 -
100.2594 -	int			nummarksurfaces;
100.2595 -	msurface_t	**marksurfaces;
100.2596 -
100.2597 -	int			numfogs;
100.2598 -	fog_t		*fogs;
100.2599 -
100.2600 -	vec3_t		lightGridOrigin;
100.2601 -	vec3_t		lightGridSize;
100.2602 -	vec3_t		lightGridInverseSize;
100.2603 -	int			lightGridBounds[3];
100.2604 -	byte		*lightGridData;
100.2605 -
100.2606 -
100.2607 -	int			numClusters;
100.2608 -	int			clusterBytes;
100.2609 -	const byte	*vis;			// may be passed in by CM_LoadMap to save space
100.2610 -
100.2611 -	byte		*novis;			// clusterBytes of 0xff
100.2612 -
100.2613 -	char		*entityString;
100.2614 -	char		*entityParsePoint;
100.2615 +	int             cluster;
100.2616 +	int             area;
100.2617 +
100.2618 +	int             numMarkSurfaces;
100.2619 +	bspSurface_t  **markSurfaces;
100.2620 +} bspNode_t;
100.2621 +
100.2622 +typedef struct
100.2623 +{
100.2624 +	int             numMarkSurfaces;
100.2625 +	bspSurface_t  **markSurfaces;
100.2626 +
100.2627 +	vec3_t			origin;		// used for cubemaps
100.2628 +} bspCluster_t;
100.2629 +
100.2630 +/*
100.2631 +typedef struct
100.2632 +{
100.2633 +	int             numMarkSurfaces;
100.2634 +	bspSurface_t  **markSurfaces;
100.2635 +
100.2636 +	int             numVBOSurfaces;
100.2637 +	srfVBOMesh_t  **vboSurfaces;
100.2638 +} bspArea_t;
100.2639 +
100.2640 +typedef struct
100.2641 +{
100.2642 +	int             areas[2];
100.2643 +
100.2644 +	vec3_t          points[4];
100.2645 +} bspAreaPortal_t;
100.2646 +*/
100.2647 +
100.2648 +typedef struct
100.2649 +{
100.2650 +	vec3_t          bounds[2];	// for culling
100.2651 +
100.2652 +	int             numSurfaces;
100.2653 +	bspSurface_t   *firstSurface;
100.2654 +
100.2655 +	int             numVBOSurfaces;
100.2656 +	srfVBOMesh_t  **vboSurfaces;
100.2657 +} bspModel_t;
100.2658 +
100.2659 +typedef struct
100.2660 +{
100.2661 +	vec4_t          ambient;
100.2662 +	vec4_t          directed;
100.2663 +	byte            latLong[2];
100.2664 +} bspGridPoint_t;
100.2665 +
100.2666 +typedef struct
100.2667 +{
100.2668 +	char            name[MAX_QPATH];	// ie: maps/tim_dm2.bsp
100.2669 +	char            baseName[MAX_QPATH];	// ie: tim_dm2
100.2670 +
100.2671 +	int             dataSize;
100.2672 +
100.2673 +	int             numShaders;
100.2674 +	dshader_t      *shaders;
100.2675 +
100.2676 +	int             numModels;
100.2677 +	bspModel_t     *models;
100.2678 +
100.2679 +	int             numplanes;
100.2680 +	cplane_t       *planes;
100.2681 +
100.2682 +	int             numnodes;	// includes leafs
100.2683 +	int             numDecisionNodes;
100.2684 +	bspNode_t      *nodes;
100.2685 +
100.2686 +	int             numVerts;
100.2687 +	srfVert_t      *verts;
100.2688 +	int             redundantVertsCalculationNeeded;
100.2689 +	int            *redundantLightVerts;	// util to optimize IBOs
100.2690 +	int            *redundantShadowVerts;
100.2691 +	int            *redundantShadowAlphaTestVerts;
100.2692 +	VBO_t          *vbo;
100.2693 +
100.2694 +	int             numTriangles;
100.2695 +	srfTriangle_t  *triangles;
100.2696 +
100.2697 +//  int             numAreas;
100.2698 +//  bspArea_t      *areas;
100.2699 +
100.2700 +//  int             numAreaPortals;
100.2701 +//  bspAreaPortal_t *areaPortals;
100.2702 +
100.2703 +	int             numWorldSurfaces;
100.2704 +
100.2705 +	int             numSurfaces;
100.2706 +	bspSurface_t   *surfaces;
100.2707 +
100.2708 +	int             numMarkSurfaces;
100.2709 +	bspSurface_t  **markSurfaces;
100.2710 +
100.2711 +	vec3_t          lightGridOrigin;
100.2712 +	vec3_t          lightGridSize;
100.2713 +	vec3_t          lightGridInverseSize;
100.2714 +	int             lightGridBounds[3];
100.2715 +	bspGridPoint_t *lightGridData;
100.2716 +
100.2717 +	int             numLights;
100.2718 +	trRefLight_t   *lights;
100.2719 +
100.2720 +	int             numInteractions;
100.2721 +	interactionCache_t **interactions;
100.2722 +
100.2723 +	int             numClusters;
100.2724 +	bspCluster_t   *clusters;
100.2725 +	int             clusterBytes;
100.2726 +	const byte     *vis;		// may be passed in by CM_LoadMap to save space
100.2727 +	byte           *novis;		// clusterBytes of 0xff
100.2728 +
100.2729 +	int             numClusterVBOSurfaces[MAX_VISCOUNTS];
100.2730 +	growList_t      clusterVBOSurfaces[MAX_VISCOUNTS];	// updated every time when changing the view cluster
100.2731 +
100.2732 +	char           *entityString;
100.2733 +	char           *entityParsePoint;
100.2734  } world_t;
100.2735  
100.2736 +
100.2737 +
100.2738 +/*
100.2739 +==============================================================================
100.2740 +MDX MODELS - meta format for .md2, .md3, .mdc and so on
100.2741 +==============================================================================
100.2742 +*/
100.2743 +typedef struct
100.2744 +{
100.2745 +	float           bounds[2][3];
100.2746 +	float           localOrigin[3];
100.2747 +	float           radius;
100.2748 +} mdxFrame_t;
100.2749 +
100.2750 +typedef struct
100.2751 +{
100.2752 +	char            name[MAX_QPATH];	// tag name
100.2753 +	float           origin[3];
100.2754 +	float           axis[3][3];
100.2755 +} mdxTag_t;
100.2756 +
100.2757 +typedef struct
100.2758 +{
100.2759 +	short           xyz[3];
100.2760 +} mdxVertex_t;
100.2761 +
100.2762 +typedef struct
100.2763 +{
100.2764 +	float           st[2];
100.2765 +} mdxSt_t;
100.2766 +
100.2767 +typedef struct
100.2768 +{
100.2769 +	surfaceType_t   surfaceType;
100.2770 +
100.2771 +	char            name[MAX_QPATH];	// polyset name
100.2772 +
100.2773 +	shader_t       *shader;
100.2774 +
100.2775 +	int             numVerts;
100.2776 +	mdxVertex_t    *verts;
100.2777 +	mdxSt_t        *st;
100.2778 +
100.2779 +	int             numTriangles;
100.2780 +	srfTriangle_t  *triangles;
100.2781 +
100.2782 +	struct mdxModel_s *model;
100.2783 +} mdxSurface_t;
100.2784 +
100.2785 +typedef struct mdxModel_s
100.2786 +{
100.2787 +	int             numFrames;
100.2788 +	mdxFrame_t     *frames;
100.2789 +
100.2790 +	int             numTags;
100.2791 +	mdxTag_t       *tags;
100.2792 +
100.2793 +	int             numSurfaces;
100.2794 +	mdxSurface_t   *surfaces;
100.2795 +
100.2796 +	int             numVBOSurfaces;
100.2797 +	srfVBOMesh_t  **vboSurfaces;
100.2798 +
100.2799 +	int             numSkins;
100.2800 +} mdxModel_t;
100.2801 +
100.2802 +
100.2803 +/*
100.2804 +==============================================================================
100.2805 +MD5 MODELS - in memory representation
100.2806 +==============================================================================
100.2807 +*/
100.2808 +#define MD5_IDENTSTRING     "MD5Version"
100.2809 +#define MD5_VERSION			10
100.2810 +
100.2811 +typedef struct
100.2812 +{
100.2813 +	int             boneIndex;	// these are indexes into the boneReferences,
100.2814 +	float           boneWeight;	// not the global per-frame bone list
100.2815 +	vec3_t          offset;
100.2816 +} md5Weight_t;
100.2817 +
100.2818 +typedef struct
100.2819 +{
100.2820 +	vec3_t          position;
100.2821 +	vec2_t          texCoords;
100.2822 +	vec3_t          tangent;
100.2823 +	vec3_t          binormal;
100.2824 +	vec3_t          normal;
100.2825 +
100.2826 +	int             firstWeight;
100.2827 +	int             numWeights;
100.2828 +	md5Weight_t   **weights;
100.2829 +} md5Vertex_t;
100.2830 +
100.2831 +/*
100.2832 +typedef struct
100.2833 +{
100.2834 +	int             indexes[3];
100.2835 +	int             neighbors[3];
100.2836 +} md5Triangle_t;
100.2837 +*/
100.2838 +
100.2839 +typedef struct
100.2840 +{
100.2841 +	surfaceType_t   surfaceType;
100.2842 +
100.2843 +//  char            name[MAX_QPATH];    // polyset name
100.2844 +	char            shader[MAX_QPATH];
100.2845 +	int             shaderIndex;	// for in-game use
100.2846 +
100.2847 +	int             numVerts;
100.2848 +	md5Vertex_t    *verts;
100.2849 +
100.2850 +	int             numTriangles;
100.2851 +	srfTriangle_t  *triangles;
100.2852 +
100.2853 +	int             numWeights;
100.2854 +	md5Weight_t    *weights;
100.2855 +
100.2856 +	struct md5Model_s *model;
100.2857 +} md5Surface_t;
100.2858 +
100.2859 +typedef struct
100.2860 +{
100.2861 +	char            name[MAX_QPATH];
100.2862 +	int             parentIndex;	// parent index (-1 if root)
100.2863 +	vec3_t          origin;
100.2864 +	quat_t          rotation;
100.2865 +	matrix_t        inverseTransform;	// full inverse for tangent space transformation
100.2866 +} md5Bone_t;
100.2867 +
100.2868 +typedef struct md5Model_s
100.2869 +{
100.2870 +	int             numBones;
100.2871 +	md5Bone_t      *bones;
100.2872 +
100.2873 +	int             numSurfaces;
100.2874 +	md5Surface_t   *surfaces;
100.2875 +
100.2876 +	int             numVBOSurfaces;
100.2877 +	srfVBOMD5Mesh_t **vboSurfaces;
100.2878 +
100.2879 +	vec3_t          bounds[2];
100.2880 +} md5Model_t;
100.2881 +
100.2882 +
100.2883 +typedef enum
100.2884 +{
100.2885 +	AT_BAD,
100.2886 +	AT_MD5,
100.2887 +	AT_PSA
100.2888 +} animType_t;
100.2889 +
100.2890 +enum
100.2891 +{
100.2892 +	COMPONENT_BIT_TX = 1 << 0,
100.2893 +	COMPONENT_BIT_TY = 1 << 1,
100.2894 +	COMPONENT_BIT_TZ = 1 << 2,
100.2895 +	COMPONENT_BIT_QX = 1 << 3,
100.2896 +	COMPONENT_BIT_QY = 1 << 4,
100.2897 +	COMPONENT_BIT_QZ = 1 << 5
100.2898 +};
100.2899 +
100.2900 +typedef struct
100.2901 +{
100.2902 +	char            name[MAX_QPATH];
100.2903 +	int             parentIndex;
100.2904 +
100.2905 +	int             componentsBits;	// e.g. (COMPONENT_BIT_TX | COMPONENT_BIT_TY | COMPONENT_BIT_TZ)
100.2906 +	int             componentsOffset;
100.2907 +
100.2908 +	vec3_t          baseOrigin;
100.2909 +	quat_t          baseQuat;
100.2910 +} md5Channel_t;
100.2911 +
100.2912 +typedef struct
100.2913 +{
100.2914 +	vec3_t          bounds[2];	// bounds of all surfaces of all LOD's for this frame
100.2915 +	float          *components;	// numAnimatedComponents many
100.2916 +} md5Frame_t;
100.2917 +
100.2918 +typedef struct md5Animation_s
100.2919 +{
100.2920 +	int             numFrames;
100.2921 +	md5Frame_t     *frames;
100.2922 +
100.2923 +	int             numChannels;	// same as numBones in model
100.2924 +	md5Channel_t   *channels;
100.2925 +
100.2926 +	int             frameRate;
100.2927 +
100.2928 +	int             numAnimatedComponents;
100.2929 +} md5Animation_t;
100.2930 +
100.2931 +
100.2932 +typedef struct
100.2933 +{
100.2934 +	axAnimationInfo_t info;
100.2935 +
100.2936 +	int				  numBones;
100.2937 +	axReferenceBone_t *bones;
100.2938 +
100.2939 +	int				  numKeys;
100.2940 +	axAnimationKey_t *keys;
100.2941 +} psaAnimation_t;
100.2942 +
100.2943 +typedef struct
100.2944 +{
100.2945 +	char            name[MAX_QPATH];	// game path, including extension
100.2946 +	animType_t      type;
100.2947 +	int             index;		// anim = tr.animations[anim->index]
100.2948 +
100.2949 +	md5Animation_t *md5;
100.2950 +	psaAnimation_t *psa;
100.2951 +
100.2952 +} skelAnimation_t;
100.2953 +
100.2954 +
100.2955  //======================================================================
100.2956  
100.2957 -typedef enum {
100.2958 +typedef enum
100.2959 +{
100.2960  	MOD_BAD,
100.2961 -	MOD_BRUSH,
100.2962 -	MOD_MESH,
100.2963 -	MOD_MD4,
100.2964 -#ifdef RAVENMD4
100.2965 -	MOD_MDR
100.2966 -#endif
100.2967 +	MOD_BSP,
100.2968 +	MOD_MDX,
100.2969 +	MOD_MD5
100.2970  } modtype_t;
100.2971  
100.2972 -typedef struct model_s {
100.2973 -	char		name[MAX_QPATH];
100.2974 -	modtype_t	type;
100.2975 -	int			index;				// model = tr.models[model->index]
100.2976 -
100.2977 -	int			dataSize;			// just for listing purposes
100.2978 -	bmodel_t	*bmodel;			// only if type == MOD_BRUSH
100.2979 -	md3Header_t	*md3[MD3_MAX_LODS];	// only if type == MOD_MESH
100.2980 -	void	*md4;				// only if type == (MOD_MD4 | MOD_MDR)
100.2981 -
100.2982 -	int			 numLods;
100.2983 +typedef struct model_s
100.2984 +{
100.2985 +	char            name[MAX_QPATH];
100.2986 +	modtype_t       type;
100.2987 +	int             index;		// model = tr.models[model->index]
100.2988 +
100.2989 +	int             dataSize;	// just for listing purposes
100.2990 +	bspModel_t     *bsp;		// only if type == MOD_BSP
100.2991 +	mdxModel_t     *mdx[MD3_MAX_LODS];	// only if type == MOD_MD3
100.2992 +	md5Model_t     *md5;		// only if type == MOD_MD5
100.2993 +
100.2994 +	int             numLods;
100.2995  } model_t;
100.2996  
100.2997 -
100.2998 -#define	MAX_MOD_KNOWN	1024
100.2999 -
100.3000 -void		R_ModelInit (void);
100.3001 -model_t		*R_GetModelByHandle( qhandle_t hModel );
100.3002 -int			R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame, 
100.3003 -					 float frac, const char *tagName );
100.3004 -void		R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs );
100.3005 -
100.3006 -void		R_Modellist_f (void);
100.3007 +void            R_ModelInit(void);
100.3008 +model_t        *R_GetModelByHandle(qhandle_t hModel);
100.3009 +
100.3010 +int             RE_LerpTag(orientation_t * tag, qhandle_t handle, int startFrame, int endFrame, float frac, const char *tagName);
100.3011 +
100.3012 +int             RE_BoneIndex(qhandle_t hModel, const char *boneName);
100.3013 +
100.3014 +
100.3015 +void            R_ModelBounds(qhandle_t handle, vec3_t mins, vec3_t maxs);
100.3016 +
100.3017 +void            R_Modellist_f(void);
100.3018  
100.3019  //====================================================
100.3020 -extern	refimport_t		ri;
100.3021 -
100.3022 -#define	MAX_DRAWIMAGES			2048
100.3023 +extern refimport_t ri;
100.3024 +
100.3025 +#define	MAX_MOD_KNOWN			1024
100.3026 +#define	MAX_ANIMATIONFILES		4096
100.3027 +
100.3028 +//#define	MAX_DRAWIMAGES			4096
100.3029  #define	MAX_LIGHTMAPS			256
100.3030  #define	MAX_SKINS				1024
100.3031  
100.3032 @@ -787,488 +2505,804 @@
100.3033  #define	MAX_DRAWSURFS			0x10000
100.3034  #define	DRAWSURF_MASK			(MAX_DRAWSURFS-1)
100.3035  
100.3036 -/*
100.3037 -
100.3038 -the drawsurf sort data is packed into a single 32 bit value so it can be
100.3039 -compared quickly during the qsorting process
100.3040 -
100.3041 -the bits are allocated as follows:
100.3042 -
100.3043 -21 - 31	: sorted shader index
100.3044 -11 - 20	: entity index
100.3045 -2 - 6	: fog index
100.3046 -//2		: used to be clipped flag REMOVED - 03.21.00 rad
100.3047 -0 - 1	: dlightmap index
100.3048 -
100.3049 -	TTimo - 1.32
100.3050 -17-31 : sorted shader index
100.3051 -7-16  : entity index
100.3052 -2-6   : fog index
100.3053 -0-1   : dlightmap index
100.3054 -*/
100.3055 -#define	QSORT_SHADERNUM_SHIFT	17
100.3056 -#define	QSORT_ENTITYNUM_SHIFT	7
100.3057 -#define	QSORT_FOGNUM_SHIFT		2
100.3058 -
100.3059 -extern	int			gl_filter_min, gl_filter_max;
100.3060 +#define MAX_INTERACTIONS		MAX_DRAWSURFS*16
100.3061 +#define INTERACTION_MASK		(MAX_INTERACTIONS-1)
100.3062 +
100.3063 +extern int      gl_filter_min, gl_filter_max;
100.3064  
100.3065  /*
100.3066  ** performanceCounters_t
100.3067  */
100.3068 -typedef struct {
100.3069 -	int		c_sphere_cull_patch_in, c_sphere_cull_patch_clip, c_sphere_cull_patch_out;
100.3070 -	int		c_box_cull_patch_in, c_box_cull_patch_clip, c_box_cull_patch_out;
100.3071 -	int		c_sphere_cull_md3_in, c_sphere_cull_md3_clip, c_sphere_cull_md3_out;
100.3072 -	int		c_box_cull_md3_in, c_box_cull_md3_clip, c_box_cull_md3_out;
100.3073 -
100.3074 -	int		c_leafs;
100.3075 -	int		c_dlightSurfaces;
100.3076 -	int		c_dlightSurfacesCulled;
100.3077 +typedef struct
100.3078 +{
100.3079 +	int             c_sphere_cull_patch_in, c_sphere_cull_patch_clip, c_sphere_cull_patch_out;
100.3080 +	int             c_box_cull_patch_in, c_box_cull_patch_clip, c_box_cull_patch_out;
100.3081 +	int             c_sphere_cull_mdx_in, c_sphere_cull_mdx_clip, c_sphere_cull_mdx_out;
100.3082 +	int             c_box_cull_mdx_in, c_box_cull_mdx_clip, c_box_cull_mdx_out;
100.3083 +	int             c_box_cull_md5_in, c_box_cull_md5_clip, c_box_cull_md5_out;
100.3084 +	int             c_box_cull_light_in, c_box_cull_light_clip, c_box_cull_light_out;
100.3085 +	int             c_pvs_cull_light_out;
100.3086 +
100.3087 +	int             c_pyramidTests;
100.3088 +	int             c_pyramid_cull_ent_in, c_pyramid_cull_ent_clip, c_pyramid_cull_ent_out;
100.3089 +
100.3090 +	int             c_leafs;
100.3091 +
100.3092 +	int             c_slights;
100.3093 +	int             c_slightSurfaces;
100.3094 +	int             c_slightInteractions;
100.3095 +
100.3096 +	int             c_dlights;
100.3097 +	int             c_dlightSurfaces;
100.3098 +	int             c_dlightSurfacesCulled;
100.3099 +	int             c_dlightInteractions;
100.3100 +
100.3101 +	int             c_depthBoundsTests, c_depthBoundsTestsRejected;
100.3102  } frontEndCounters_t;
100.3103  
100.3104 -#define	FOG_TABLE_SIZE		256
100.3105  #define FUNCTABLE_SIZE		1024
100.3106  #define FUNCTABLE_SIZE2		10
100.3107  #define FUNCTABLE_MASK		(FUNCTABLE_SIZE-1)
100.3108  
100.3109  
100.3110 +#define MAX_GLSTACK			5
100.3111 +
100.3112  // the renderer front end should never modify glstate_t
100.3113 -typedef struct {
100.3114 -	int			currenttextures[2];
100.3115 -	int			currenttmu;
100.3116 -	qboolean	finishCalled;
100.3117 -	int			texEnv[2];
100.3118 -	int			faceCulling;
100.3119 -	unsigned long	glStateBits;
100.3120 +typedef struct
100.3121 +{
100.3122 +	int				blendSrc, blendDst;
100.3123 +	float			clearColorRed, clearColorGreen, clearColorBlue, clearColorAlpha;
100.3124 +	double			clearDepth;
100.3125 +	int				clearStencil;
100.3126 +	int				colorMaskRed, colorMaskGreen, colorMaskBlue, colorMaskAlpha;
100.3127 +	int				cullFace;
100.3128 +	int				depthFunc;
100.3129 +	int				depthMask;
100.3130 +	int				drawBuffer;
100.3131 +	int				frontFace;
100.3132 +	int				polygonFace, polygonMode;
100.3133 +	int             scissorX, scissorY, scissorWidth, scissorHeight;
100.3134 +	int             viewportX, viewportY, viewportWidth, viewportHeight;
100.3135 +
100.3136 +	int             currenttextures[32];
100.3137 +	int             currenttmu;
100.3138 +//  matrix_t        textureMatrix[32];
100.3139 +
100.3140 +	int             stackIndex;
100.3141 +//  matrix_t        modelMatrix[MAX_GLSTACK];
100.3142 +//  matrix_t        viewMatrix[MAX_GLSTACK];
100.3143 +	matrix_t        modelViewMatrix[MAX_GLSTACK];
100.3144 +	matrix_t        projectionMatrix[MAX_GLSTACK];
100.3145 +	matrix_t        modelViewProjectionMatrix[MAX_GLSTACK];
100.3146 +
100.3147 +	qboolean        finishCalled;
100.3148 +	int             faceCulling;	// FIXME redundant cullFace
100.3149 +	unsigned long   glStateBits;
100.3150 +	unsigned int	vertexAttribsState;
100.3151 +	unsigned int	vertexAttribPointersSet;
100.3152 +	shaderProgram_t *currentProgram;
100.3153 +	FBO_t          *currentFBO;
100.3154 +	VBO_t          *currentVBO;
100.3155 +	IBO_t          *currentIBO;
100.3156  } glstate_t;
100.3157  
100.3158  
100.3159 -typedef struct {
100.3160 -	int		c_surfaces, c_shaders, c_vertexes, c_indexes, c_totalIndexes;
100.3161 -	float	c_overDraw;
100.3162 -	
100.3163 -	int		c_dlightVertexes;
100.3164 -	int		c_dlightIndexes;
100.3165 -
100.3166 -	int		c_flareAdds;
100.3167 -	int		c_flareTests;
100.3168 -	int		c_flareRenders;
100.3169 -
100.3170 -	int		msec;			// total msec for backend run
100.3171 +typedef struct
100.3172 +{
100.3173 +	int             c_views;
100.3174 +	int             c_portals;
100.3175 +	int             c_batches;
100.3176 +	int             c_surfaces;
100.3177 +	int             c_vertexes;
100.3178 +	int             c_indexes;
100.3179 +	int             c_drawElements;
100.3180 +	float           c_overDraw;
100.3181 +	int             c_vboVertexBuffers;
100.3182 +	int             c_vboIndexBuffers;
100.3183 +	int             c_vboVertexes;
100.3184 +	int             c_vboIndexes;
100.3185 +
100.3186 +	int             c_flareAdds;
100.3187 +	int             c_flareTests;
100.3188 +	int             c_flareRenders;
100.3189 +
100.3190 +	int             c_occlusionQueries;
100.3191 +	int             c_occlusionQueriesAvailable;
100.3192 +	int             c_occlusionQueriesLightsCulled;
100.3193 +	int             c_occlusionQueriesInteractionsCulled;
100.3194 +	int             c_occlusionQueriesResponseTime;
100.3195 +
100.3196 +	int             c_forwardAmbientTime;
100.3197 +	int             c_forwardLightingTime;
100.3198 +
100.3199 +	int             c_deferredGBufferTime;
100.3200 +	int             c_deferredLightingTime;
100.3201 +
100.3202 +	int             msec;		// total msec for backend run
100.3203  } backEndCounters_t;
100.3204  
100.3205  // all state modified by the back end is seperated
100.3206  // from the front end state
100.3207 -typedef struct {
100.3208 -	int			smpFrame;
100.3209 -	trRefdef_t	refdef;
100.3210 -	viewParms_t	viewParms;
100.3211 -	orientationr_t	or;
100.3212 -	backEndCounters_t	pc;
100.3213 -	qboolean	isHyperspace;
100.3214 -	trRefEntity_t	*currentEntity;
100.3215 -	qboolean	skyRenderedThisView;	// flag for drawing sun
100.3216 -
100.3217 -	qboolean	projection2D;	// if qtrue, drawstretchpic doesn't need to change modes
100.3218 -	byte		color2D[4];
100.3219 -	qboolean	vertexes2D;		// shader needs to be finished
100.3220 -	trRefEntity_t	entity2D;	// currentEntity will point at this when doing 2D rendering
100.3221 -	qboolean	doneBloom;		// done bloom this frame
100.3222 -	qboolean	doneSurfaces;   // done any 3d surfaces already
100.3223 -	
100.3224 +typedef struct
100.3225 +{
100.3226 +	int             smpFrame;
100.3227 +	trRefdef_t      refdef;
100.3228 +	viewParms_t     viewParms;
100.3229 +	orientationr_t  orientation;
100.3230 +	backEndCounters_t pc;
100.3231 +	qboolean        isHyperspace;
100.3232 +	trRefEntity_t  *currentEntity;
100.3233 +	trRefLight_t   *currentLight;	// only used when lighting interactions
100.3234 +	qboolean        skyRenderedThisView;	// flag for drawing sun
100.3235 +
100.3236 +	float			hdrAverageLuminance;
100.3237 +	float			hdrMaxLuminance;
100.3238 +	float			hdrTime;
100.3239 +
100.3240 +	qboolean        projection2D;	// if qtrue, drawstretchpic doesn't need to change modes
100.3241 +	vec4_t          color2D;
100.3242 +	qboolean        vertexes2D;	// shader needs to be finished
100.3243 +	trRefEntity_t   entity2D;	// currentEntity will point at this when doing 2D rendering
100.3244  } backEndState_t;
100.3245  
100.3246 +typedef struct
100.3247 +{
100.3248 +	vec3_t          origin;
100.3249 +	image_t        *cubemap;
100.3250 +} cubemapProbe_t;
100.3251 +
100.3252 +
100.3253  /*
100.3254 -** trGlobals_t 
100.3255 +** trGlobals_t
100.3256  **
100.3257  ** Most renderer globals are defined here.
100.3258  ** backend functions should never modify any of these fields,
100.3259  ** but may read fields that aren't dynamically modified
100.3260  ** by the frontend.
100.3261  */
100.3262 -typedef struct {
100.3263 -	qboolean				registered;		// cleared at shutdown, set at beginRegistration
100.3264 -
100.3265 -	int						visCount;		// incremented every time a new vis cluster is entered
100.3266 -	int						frameCount;		// incremented every frame
100.3267 -	int						sceneCount;		// incremented every scene
100.3268 -	int						viewCount;		// incremented every view (twice a scene if portaled)
100.3269 -											// and every R_MarkFragments call
100.3270 -
100.3271 -	int						smpFrame;		// toggles from 0 to 1 every endFrame
100.3272 -
100.3273 -	int						frameSceneNum;	// zeroed at RE_BeginFrame
100.3274 -
100.3275 -	qboolean				worldMapLoaded;
100.3276 -	world_t					*world;
100.3277 -
100.3278 -	const byte				*externalVisData;	// from RE_SetWorldVisData, shared with CM_Load
100.3279 -
100.3280 -	image_t					*defaultImage;
100.3281 -	image_t					*scratchImage[32];
100.3282 -	image_t					*fogImage;
100.3283 -	image_t					*dlightImage;	// inverse-quare highlight for projective adding
100.3284 -	image_t					*flareImage;
100.3285 -	image_t					*whiteImage;			// full of 0xff
100.3286 -	image_t					*identityLightImage;	// full of tr.identityLightByte
100.3287 -
100.3288 -	shader_t				*defaultShader;
100.3289 -	shader_t				*shadowShader;
100.3290 -	shader_t				*projectionShadowShader;
100.3291 -
100.3292 -	shader_t				*flareShader;
100.3293 -	shader_t				*sunShader;
100.3294 -
100.3295 -	int						numLightmaps;
100.3296 -	image_t					*lightmaps[MAX_LIGHTMAPS];
100.3297 -
100.3298 -	trRefEntity_t			*currentEntity;
100.3299 -	trRefEntity_t			worldEntity;		// point currentEntity at this when rendering world
100.3300 -	int						currentEntityNum;
100.3301 -	int						shiftedEntityNum;	// currentEntityNum << QSORT_ENTITYNUM_SHIFT
100.3302 -	model_t					*currentModel;
100.3303 -
100.3304 -	viewParms_t				viewParms;
100.3305 -
100.3306 -	float					identityLight;		// 1.0 / ( 1 << overbrightBits )
100.3307 -	int						identityLightByte;	// identityLight * 255
100.3308 -	int						overbrightBits;		// r_overbrightBits->integer, but set to 0 if no hw gamma
100.3309 -
100.3310 -	orientationr_t			or;					// for current entity
100.3311 -
100.3312 -	trRefdef_t				refdef;
100.3313 -
100.3314 -	int						viewCluster;
100.3315 -
100.3316 -	vec3_t					sunLight;			// from the sky shader for this level
100.3317 -	vec3_t					sunDirection;
100.3318 -
100.3319 -	frontEndCounters_t		pc;
100.3320 -	int						frontEndMsec;		// not in pc due to clearing issue
100.3321 +typedef struct
100.3322 +{
100.3323 +	qboolean        registered;	// cleared at shutdown, set at beginRegistration
100.3324 +
100.3325 +	int             visIndex;
100.3326 +	int             visClusters[MAX_VISCOUNTS];
100.3327 +	int             visCounts[MAX_VISCOUNTS];	// incremented every time a new vis cluster is entered
100.3328 +
100.3329 +	int             frameCount;	// incremented every frame
100.3330 +	int             sceneCount;	// incremented every scene
100.3331 +	int             viewCount;	// incremented every view (twice a scene if portaled)
100.3332 +	int             lightCount;	// incremented every time a dlight traverses the world
100.3333 +	// and every R_MarkFragments call
100.3334 +
100.3335 +	int             smpFrame;	// toggles from 0 to 1 every endFrame
100.3336 +
100.3337 +	int             frameSceneNum;	// zeroed at RE_BeginFrame
100.3338 +
100.3339 +	qboolean        worldMapLoaded;
100.3340 +	qboolean        worldDeluxeMapping;
100.3341 +	qboolean		worldHDR_RGBE;
100.3342 +	world_t        *world;
100.3343 +
100.3344 +	const byte     *externalVisData;	// from RE_SetWorldVisData, shared with CM_Load
100.3345 +
100.3346 +	image_t        *defaultImage;
100.3347 +	image_t        *scratchImage[32];
100.3348 +	image_t        *quadraticImage;
100.3349 +	image_t        *whiteImage;	// full of 0xff
100.3350 +	image_t        *blackImage;	// full of 0x0
100.3351 +	image_t        *flatImage;	// use this as default normalmap
100.3352 +	image_t        *noFalloffImage;
100.3353 +	image_t        *attenuationXYImage;
100.3354 +	image_t        *blackCubeImage;
100.3355 +	image_t        *autoCubeImage;			// special pointer to the nearest cubemap probe
100.3356 +
100.3357 +	image_t        *contrastRenderFBOImage;
100.3358 +	image_t        *bloomRenderFBOImage[2];
100.3359 +	image_t        *currentRenderImage;
100.3360 +	image_t        *depthRenderImage;
100.3361 +	image_t        *portalRenderImage;
100.3362 +
100.3363 +	image_t        *deferredDiffuseFBOImage;
100.3364 +	image_t        *deferredNormalFBOImage;
100.3365 +	image_t        *deferredSpecularFBOImage;
100.3366 +	image_t        *deferredRenderFBOImage;
100.3367 +	image_t        *occlusionRenderFBOImage;
100.3368 +	image_t        *depthToColorBackFacesFBOImage;
100.3369 +	image_t        *depthToColorFrontFacesFBOImage;
100.3370 +	image_t        *downScaleFBOImage_quarter;
100.3371 +	image_t        *downScaleFBOImage_64x64;
100.3372 +//	image_t        *downScaleFBOImage_16x16;
100.3373 +//	image_t        *downScaleFBOImage_4x4;
100.3374 +//	image_t        *downScaleFBOImage_1x1;
100.3375 +	image_t        *shadowMapFBOImage[5];
100.3376 +	image_t        *shadowCubeFBOImage[5];
100.3377 +
100.3378 +	// external images
100.3379 +	image_t        *charsetImage;
100.3380 +
100.3381 +	// framebuffer objects
100.3382 +	FBO_t          *geometricRenderFBO;		// is the G-Buffer for deferred shading
100.3383 +	FBO_t          *deferredRenderFBO;		// is used by HDR rendering and deferred shading
100.3384 +	FBO_t          *portalRenderFBO;		// holds a copy of the last currentRender that was rendered into a FBO
100.3385 +	FBO_t          *occlusionRenderFBO;		// used for overlapping visibility determination
100.3386 +	FBO_t          *downScaleFBO_quarter;
100.3387 +	FBO_t          *downScaleFBO_64x64;
100.3388 +//	FBO_t          *downScaleFBO_16x16;
100.3389 +//	FBO_t          *downScaleFBO_4x4;
100.3390 +//	FBO_t          *downScaleFBO_1x1;
100.3391 +	FBO_t          *contrastRenderFBO;
100.3392 +	FBO_t          *bloomRenderFBO[2];
100.3393 +	FBO_t          *shadowMapFBO[5];
100.3394 +
100.3395 +	// internal shaders
100.3396 +	shader_t       *defaultShader;
100.3397 +	shader_t       *defaultPointLightShader;
100.3398 +	shader_t       *defaultProjectedLightShader;
100.3399 +	shader_t       *defaultDynamicLightShader;
100.3400 +
100.3401 +	// external shaders
100.3402 +	shader_t       *projectionShadowShader;
100.3403 +	shader_t       *flareShader;
100.3404 +	shader_t       *sunShader;
100.3405 +
100.3406 +	growList_t      lightmaps;
100.3407 +	growList_t      deluxemaps;
100.3408 +
100.3409 +	image_t        *fatLightmap;
100.3410 +	int				fatLightmapSize;
100.3411 +	int				fatLightmapStep;
100.3412 +
100.3413 +	// render entities
100.3414 +	trRefEntity_t  *currentEntity;
100.3415 +	trRefEntity_t   worldEntity;	// point currentEntity at this when rendering world
100.3416 +	model_t        *currentModel;
100.3417 +
100.3418 +	// render lights
100.3419 +	trRefLight_t   *currentLight;
100.3420 +
100.3421 +	//
100.3422 +	// GPU shader programs
100.3423 +	//
100.3424 +
100.3425 +	// Q3A standard simple vertex color rendering
100.3426 +	shaderProgram_t genericSingleShader;
100.3427 +
100.3428 +	// simple vertex color shading for entities
100.3429 +	shaderProgram_t vertexLightingShader_DBS_entity;
100.3430 +
100.3431 +	// simple vertex color shading for the world
100.3432 +	shaderProgram_t vertexLightingShader_DBS_world;
100.3433 +
100.3434 +	// standard light mapping
100.3435 +	shaderProgram_t lightMappingShader;
100.3436 +
100.3437 +	// directional light mapping
100.3438 +	shaderProgram_t deluxeMappingShader;
100.3439 +
100.3440 +	// deferred Geometric-Buffer processing
100.3441 +	shaderProgram_t geometricFillShader_DBS;
100.3442 +
100.3443 +	// deferred lighting
100.3444 +	shaderProgram_t deferredLightingShader_DBS_omni;
100.3445 +	shaderProgram_t deferredLightingShader_DBS_proj;
100.3446 +
100.3447 +	// black depth fill rendering with textures
100.3448 +	shaderProgram_t depthFillShader;
100.3449 +
100.3450 +	// colored depth test rendering with textures into gl_FragData[1]
100.3451 +	shaderProgram_t depthTestShader;
100.3452 +
100.3453 +	// depth to color encoding
100.3454 +	shaderProgram_t depthToColorShader;
100.3455 +
100.3456 +	// stencil shadow volume extrusion
100.3457 +	shaderProgram_t shadowExtrudeShader;
100.3458 +
100.3459 +	// shadowmap distance compression
100.3460 +	shaderProgram_t shadowFillShader;
100.3461 +
100.3462 +	// Doom3 style omni-directional multi-pass lighting
100.3463 +	shaderProgram_t forwardLightingShader_DBS_omni;
100.3464 +	shaderProgram_t forwardLightingShader_DBS_proj;
100.3465 +
100.3466 +#ifdef VOLUMETRIC_LIGHTING
100.3467 +	// volumetric lighting
100.3468 +	shaderProgram_t lightVolumeShader_omni;
100.3469 +#endif
100.3470 +
100.3471 +	// UT3 style player shadowing
100.3472 +	shaderProgram_t deferredShadowingShader_proj;
100.3473 +
100.3474 +	// environment mapping effects
100.3475 +	shaderProgram_t reflectionShader_C;
100.3476 +	shaderProgram_t reflectionShader_CB;
100.3477 +	shaderProgram_t refractionShader_C;
100.3478 +	shaderProgram_t dispersionShader_C;
100.3479 +	shaderProgram_t skyBoxShader;
100.3480 +
100.3481 +	// post process effects
100.3482 +	shaderProgram_t heatHazeShader;
100.3483 +	shaderProgram_t bloomShader;
100.3484 +	shaderProgram_t contrastShader;
100.3485 +	shaderProgram_t blurXShader;
100.3486 +	shaderProgram_t blurYShader;
100.3487 +	shaderProgram_t rotoscopeShader;
100.3488 +	shaderProgram_t screenShader;
100.3489 +	shaderProgram_t portalShader;
100.3490 +	shaderProgram_t liquidShader;
100.3491 +	shaderProgram_t uniformFogShader;
100.3492 +	shaderProgram_t volumetricFogShader;
100.3493 +	shaderProgram_t screenSpaceAmbientOcclusionShader;
100.3494 +	shaderProgram_t depthOfFieldShader;
100.3495 +	shaderProgram_t toneMappingShader;
100.3496 +
100.3497 +	// -----------------------------------------
100.3498 +
100.3499 +	viewParms_t     viewParms;
100.3500 +
100.3501 +	float           identityLight;	// 1.0 / ( 1 << overbrightBits )
100.3502 +	int             overbrightBits;	// r_overbrightBits->integer, but set to 0 if no hw gamma
100.3503 +
100.3504 +	orientationr_t  orientation;			// for current entity
100.3505 +
100.3506 +	trRefdef_t      refdef;
100.3507 +
100.3508 +	vec3_t          sunLight;	// from the sky shader for this level
100.3509 +	vec3_t          sunDirection;
100.3510 +
100.3511 +	vec3_t          fogColor;
100.3512 +	float           fogDensity;
100.3513 +
100.3514 +	frontEndCounters_t pc;
100.3515 +	int             frontEndMsec;	// not in pc due to clearing issue
100.3516  
100.3517  	//
100.3518  	// put large tables at the end, so most elements will be
100.3519  	// within the +/32K indexed range on risc processors
100.3520  	//
100.3521 -	model_t					*models[MAX_MOD_KNOWN];
100.3522 -	int						numModels;
100.3523 -
100.3524 -	int						numImages;
100.3525 -	image_t					*images[MAX_DRAWIMAGES];
100.3526 +	model_t        *models[MAX_MOD_KNOWN];
100.3527 +	int             numModels;
100.3528 +
100.3529 +	int             numAnimations;
100.3530 +	skelAnimation_t *animations[MAX_ANIMATIONFILES];
100.3531 +
100.3532 +	growList_t      images;
100.3533 +
100.3534 +	int             numFBOs;
100.3535 +	FBO_t          *fbos[MAX_FBOS];
100.3536 +
100.3537 +	growList_t      vbos;
100.3538 +	growList_t      ibos;
100.3539 +
100.3540 +	byte           *cubeTemp[6];	// 6 textures for cubemap storage
100.3541 +	growList_t		cubeProbes;		// all cubemaps in a linear growing list
100.3542 +	vertexHash_t  **cubeHashTable;	// hash table for faster access
100.3543  
100.3544  	// shader indexes from other modules will be looked up in tr.shaders[]
100.3545  	// shader indexes from drawsurfs will be looked up in sortedShaders[]
100.3546  	// lower indexed sortedShaders must be rendered first (opaque surfaces before translucent)
100.3547 -	int						numShaders;
100.3548 -	shader_t				*shaders[MAX_SHADERS];
100.3549 -	shader_t				*sortedShaders[MAX_SHADERS];
100.3550 -
100.3551 -	int						numSkins;
100.3552 -	skin_t					*skins[MAX_SKINS];
100.3553 -
100.3554 -	float					sinTable[FUNCTABLE_SIZE];
100.3555 -	float					squareTable[FUNCTABLE_SIZE];
100.3556 -	float					triangleTable[FUNCTABLE_SIZE];
100.3557 -	float					sawToothTable[FUNCTABLE_SIZE];
100.3558 -	float					inverseSawToothTable[FUNCTABLE_SIZE];
100.3559 -	float					fogTable[FOG_TABLE_SIZE];
100.3560 +	int             numShaders;
100.3561 +	shader_t       *shaders[MAX_SHADERS];
100.3562 +	shader_t       *sortedShaders[MAX_SHADERS];
100.3563 +
100.3564 +	int             numSkins;
100.3565 +	skin_t         *skins[MAX_SKINS];
100.3566 +
100.3567 +	int             numTables;
100.3568 +	shaderTable_t  *shaderTables[MAX_SHADER_TABLES];
100.3569 +
100.3570 +	float           sinTable[FUNCTABLE_SIZE];
100.3571 +	float           squareTable[FUNCTABLE_SIZE];
100.3572 +	float           triangleTable[FUNCTABLE_SIZE];
100.3573 +	float           sawToothTable[FUNCTABLE_SIZE];
100.3574 +	float           inverseSawToothTable[FUNCTABLE_SIZE];
100.3575 +
100.3576 +	int             occlusionQueryObjects[MAX_OCCLUSION_QUERIES];
100.3577  } trGlobals_t;
100.3578  
100.3579 -extern backEndState_t	backEnd;
100.3580 -extern trGlobals_t	tr;
100.3581 -extern glconfig_t	glConfig;		// outside of TR since it shouldn't be cleared during ref re-init
100.3582 -extern glstate_t	glState;		// outside of TR since it shouldn't be cleared during ref re-init
100.3583 +extern const matrix_t quakeToOpenGLMatrix;
100.3584 +extern const matrix_t openGLToQuakeMatrix;
100.3585 +extern int      shadowMapResolutions[5];
100.3586 +
100.3587 +extern backEndState_t backEnd;
100.3588 +extern trGlobals_t tr;
100.3589 +extern glConfig_t glConfig;		// outside of TR since it shouldn't be cleared during ref re-init
100.3590 +extern glstate_t glState;		// outside of TR since it shouldn't be cleared during ref re-init
100.3591 +
100.3592 +extern float    displayAspect;	// FIXME
100.3593  
100.3594  
100.3595  //
100.3596  // cvars
100.3597  //
100.3598 -extern cvar_t	*r_flareSize;
100.3599 -extern cvar_t	*r_flareFade;
100.3600 -// coefficient for the flare intensity falloff function.
100.3601 -#define FLARE_STDCOEFF "150"
100.3602 -extern cvar_t	*r_flareCoeff;
100.3603 -
100.3604 -extern cvar_t	*r_railWidth;
100.3605 -extern cvar_t	*r_railCoreWidth;
100.3606 -extern cvar_t	*r_railSegmentLength;
100.3607 -
100.3608 -extern cvar_t	*r_ignore;				// used for debugging anything
100.3609 -extern cvar_t	*r_verbose;				// used for verbose debug spew
100.3610 -extern cvar_t	*r_ignoreFastPath;		// allows us to ignore our Tess fast paths
100.3611 -
100.3612 -extern cvar_t	*r_znear;				// near Z clip plane
100.3613 -extern cvar_t	*r_zproj;				// z distance of projection plane
100.3614 -extern cvar_t	*r_stereoSeparation;			// separation of cameras for stereo rendering
100.3615 -
100.3616 -extern cvar_t	*r_stencilbits;			// number of desired stencil bits
100.3617 -extern cvar_t	*r_depthbits;			// number of desired depth bits
100.3618 -extern cvar_t	*r_colorbits;			// number of desired color bits, only relevant for fullscreen
100.3619 -extern cvar_t	*r_texturebits;			// number of desired texture bits
100.3620 -										// 0 = use framebuffer depth
100.3621 -										// 16 = use 16-bit textures
100.3622 -										// 32 = use 32-bit textures
100.3623 -										// all else = error
100.3624 -
100.3625 -extern cvar_t	*r_measureOverdraw;		// enables stencil buffer overdraw measurement
100.3626 -
100.3627 -extern cvar_t	*r_lodbias;				// push/pull LOD transitions
100.3628 -extern cvar_t	*r_lodscale;
100.3629 -
100.3630 -extern cvar_t	*r_primitives;			// "0" = based on compiled vertex array existance
100.3631 -										// "1" = glDrawElemet tristrips
100.3632 -										// "2" = glDrawElements triangles
100.3633 -										// "-1" = no drawing
100.3634 -
100.3635 -extern cvar_t	*r_inGameVideo;				// controls whether in game video should be draw
100.3636 -extern cvar_t	*r_fastsky;				// controls whether sky should be cleared or drawn
100.3637 -extern cvar_t	*r_drawSun;				// controls drawing of sun quad
100.3638 -extern cvar_t	*r_dynamiclight;		// dynamic lights enabled/disabled
100.3639 -extern cvar_t	*r_dlightBacks;			// dlight non-facing surfaces for continuity
100.3640 -
100.3641 -extern cvar_t	*r_minEntityLight;		// minimum entity light value
100.3642 -
100.3643 -extern cvar_t	*r_specularLighting;		// extra specular pass for default shader
100.3644 -extern cvar_t	*r_specularLightingExponent;	// specular exponent for extra pass
100.3645 -
100.3646 -extern	cvar_t	*r_norefresh;			// bypasses the ref rendering
100.3647 -extern	cvar_t	*r_drawentities;		// disable/enable entity rendering
100.3648 -extern	cvar_t	*r_drawworld;			// disable/enable world rendering
100.3649 -extern	cvar_t	*r_speeds;				// various levels of information display
100.3650 -extern  cvar_t	*r_detailTextures;		// enables/disables detail texturing stages
100.3651 -extern	cvar_t	*r_novis;				// disable/enable usage of PVS
100.3652 -extern	cvar_t	*r_nocull;
100.3653 -extern	cvar_t	*r_facePlaneCull;		// enables culling of planar surfaces with back side test
100.3654 -extern	cvar_t	*r_nocurves;
100.3655 -extern	cvar_t	*r_showcluster;
100.3656 -
100.3657 -extern cvar_t	*r_width;
100.3658 -extern cvar_t	*r_height;
100.3659 -extern cvar_t	*r_pixelAspect;
100.3660 -
100.3661 -// compatibility
100.3662 -extern cvar_t   *r_mode;
100.3663 -extern cvar_t	*r_customwidth;
100.3664 -extern cvar_t	*r_customheight;
100.3665 -extern cvar_t	*r_custompixelAspect;
100.3666 -
100.3667 -extern cvar_t	*r_fullscreen;
100.3668 -extern cvar_t	*r_minimize;
100.3669 -extern cvar_t	*r_gamma;
100.3670 -extern cvar_t	*r_displayRefresh;		// optional display refresh option
100.3671 -extern cvar_t	*r_ignorehwgamma;		// overrides hardware gamma capabilities
100.3672 -
100.3673 -extern cvar_t	*r_allowExtensions;				// global enable/disable of OpenGL extensions
100.3674 -extern cvar_t	*r_ext_compressed_textures;		// these control use of specific extensions
100.3675 -extern cvar_t	*r_ext_multitexture;
100.3676 -extern cvar_t	*r_ext_compiled_vertex_array;
100.3677 -extern cvar_t	*r_ext_texture_env_add;
100.3678 -
100.3679 -extern cvar_t	*r_ext_texture_filter_anisotropic;
100.3680 -extern cvar_t	*r_ext_max_anisotropy;
100.3681 -
100.3682 -extern	cvar_t	*r_nobind;						// turns off binding to appropriate textures
100.3683 -extern	cvar_t	*r_singleShader;				// make most world faces use default shader
100.3684 -extern	cvar_t	*r_roundImagesDown;
100.3685 -extern	cvar_t	*r_colorMipLevels;				// development aid to see texture mip usage
100.3686 -extern	cvar_t	*r_picmip;						// controls picmip values
100.3687 -extern	cvar_t	*r_finish;
100.3688 -extern	cvar_t	*r_drawBuffer;
100.3689 -extern  cvar_t  *r_glDriver;
100.3690 -extern	cvar_t	*r_swapInterval;
100.3691 -extern	cvar_t	*r_textureMode;
100.3692 -extern	cvar_t	*r_offsetFactor;
100.3693 -extern	cvar_t	*r_offsetUnits;
100.3694 -
100.3695 -extern	cvar_t	*r_fullbright;					// avoid lightmap pass
100.3696 -extern	cvar_t	*r_lightmap;					// render lightmaps only
100.3697 -extern	cvar_t	*r_vertexLight;					// vertex lighting mode for better performance
100.3698 -extern	cvar_t	*r_uiFullScreen;				// ui is running fullscreen
100.3699 -
100.3700 -extern	cvar_t	*r_logFile;						// number of frames to emit GL logs
100.3701 -extern	cvar_t	*r_showtris;					// enables wireframe rendering of the world
100.3702 -extern	cvar_t	*r_showsky;						// forces sky in front of all surfaces
100.3703 -extern	cvar_t	*r_shownormals;					// draws wireframe normals
100.3704 -extern	cvar_t	*r_clear;						// force screen clear every frame
100.3705 -
100.3706 -extern	cvar_t	*r_shadows;						// controls shadows: 0 = none, 1 = blur, 2 = stencil, 3 = black planar projection
100.3707 -extern	cvar_t	*r_flares;						// light flares
100.3708 -
100.3709 -extern	cvar_t	*r_intensity;
100.3710 -
100.3711 -extern	cvar_t	*r_lockpvs;
100.3712 -extern	cvar_t	*r_noportals;
100.3713 -extern	cvar_t	*r_portalOnly;
100.3714 -
100.3715 -extern	cvar_t	*r_subdivisions;
100.3716 -extern	cvar_t	*r_lodCurveError;
100.3717 -extern	cvar_t	*r_smp;
100.3718 -extern	cvar_t	*r_showSmp;
100.3719 -extern	cvar_t	*r_skipBackEnd;
100.3720 -
100.3721 -extern	cvar_t	*r_stereoEnabled;
100.3722 -extern	cvar_t	*r_anaglyphMode;
100.3723 -
100.3724 -extern	cvar_t	*r_greyscale;
100.3725 -
100.3726 -extern	cvar_t	*r_ignoreGLErrors;
100.3727 -
100.3728 -extern	cvar_t	*r_overBrightBits;
100.3729 -extern	cvar_t	*r_mapOverBrightBits;
100.3730 -
100.3731 -extern	cvar_t	*r_debugSurface;
100.3732 -extern	cvar_t	*r_simpleMipMaps;
100.3733 -
100.3734 -extern	cvar_t	*r_showImages;
100.3735 -extern	cvar_t	*r_debugSort;
100.3736 -
100.3737 -extern	cvar_t	*r_printShaders;
100.3738 -extern	cvar_t	*r_saveFontData;
100.3739 -
100.3740 -extern	cvar_t	*r_GLlibCoolDownMsec;
100.3741 -
100.3742 -extern	cvar_t	*r_celshadalgo;					// Cell shading, chooses method: 0 = disabled, 1 = kuwahara, 2 = whiteTexture
100.3743 -extern	cvar_t	*r_celoutline;						//. cel outline. 1 on, 0 off. (maybe other options later)
100.3744 +extern cvar_t  *r_flares;		// light flares
100.3745 +extern cvar_t  *r_flareSize;
100.3746 +extern cvar_t  *r_flareFade;
100.3747 +
100.3748 +extern cvar_t  *r_railWidth;
100.3749 +extern cvar_t  *r_railCoreWidth;
100.3750 +extern cvar_t  *r_railSegmentLength;
100.3751 +
100.3752 +extern cvar_t  *r_ignore;		// used for debugging anything
100.3753 +extern cvar_t  *r_verbose;		// used for verbose debug spew
100.3754 +
100.3755 +extern cvar_t  *r_znear;		// near Z clip plane
100.3756 +extern cvar_t  *r_zfar;
100.3757 +
100.3758 +extern cvar_t  *r_stencilbits;	// number of desired stencil bits
100.3759 +extern cvar_t  *r_depthbits;	// number of desired depth bits
100.3760 +extern cvar_t  *r_colorbits;	// number of desired color bits, only relevant for fullscreen
100.3761 +extern cvar_t  *r_stereo;		// desired pixelformat stereo flag
100.3762 +
100.3763 +extern cvar_t  *r_measureOverdraw;	// enables stencil buffer overdraw measurement
100.3764 +
100.3765 +extern cvar_t  *r_lodbias;		// push/pull LOD transitions
100.3766 +extern cvar_t  *r_lodscale;
100.3767 +
100.3768 +extern cvar_t  *r_forceFog;
100.3769 +extern cvar_t  *r_noFog;
100.3770 +
100.3771 +extern cvar_t  *r_forceAmbient;
100.3772 +extern cvar_t  *r_ambientScale;
100.3773 +extern cvar_t  *r_lightScale;
100.3774 +extern cvar_t  *r_debugLight;
100.3775 +
100.3776 +extern cvar_t  *r_inGameVideo;	// controls whether in game video should be draw
100.3777 +extern cvar_t  *r_fastsky;		// controls whether sky should be cleared or drawn
100.3778 +extern cvar_t  *r_drawSun;		// controls drawing of sun quad
100.3779 +extern cvar_t  *r_noDynamicLighting;	// dynamic lights enabled/disabled
100.3780 +extern cvar_t  *r_noStaticLighting;	// dynamic lights enabled/disabled
100.3781 +extern cvar_t  *r_dynamicLightsCastShadows;
100.3782 +extern cvar_t  *r_precomputedLighting;
100.3783 +extern cvar_t  *r_vertexLighting;
100.3784 +extern cvar_t  *r_heatHazeFix;
100.3785 +extern cvar_t  *r_atiFlippedImageFix;
100.3786 +extern cvar_t  *r_noMarksOnTrisurfs;
100.3787 +
100.3788 +extern cvar_t  *r_norefresh;	// bypasses the ref rendering
100.3789 +extern cvar_t  *r_drawentities;	// disable/enable entity rendering
100.3790 +extern cvar_t  *r_drawworld;	// disable/enable world rendering
100.3791 +extern cvar_t  *r_speeds;		// various levels of information display
100.3792 +extern cvar_t  *r_novis;		// disable/enable usage of PVS
100.3793 +extern cvar_t  *r_nocull;
100.3794 +extern cvar_t  *r_facePlaneCull;	// enables culling of planar surfaces with back side test
100.3795 +extern cvar_t  *r_nocurves;
100.3796 +extern cvar_t  *r_nobatching;
100.3797 +extern cvar_t  *r_noLightScissors;
100.3798 +extern cvar_t  *r_noLightVisCull;
100.3799 +extern cvar_t  *r_noInteractionSort;
100.3800 +extern cvar_t  *r_showcluster;
100.3801 +
100.3802 +extern cvar_t  *r_mode;			// video mode
100.3803 +extern cvar_t  *r_fullscreen;
100.3804 +extern cvar_t  *r_gamma;
100.3805 +extern cvar_t  *r_displayRefresh;	// optional display refresh option
100.3806 +extern cvar_t  *r_ignorehwgamma;	// overrides hardware gamma capabilities
100.3807 +
100.3808 +extern cvar_t  *r_ext_texture_compression;	// these control use of specific extensions
100.3809 +extern cvar_t  *r_ext_occlusion_query;
100.3810 +extern cvar_t  *r_ext_texture_non_power_of_two;
100.3811 +extern cvar_t  *r_ext_draw_buffers;
100.3812 +extern cvar_t  *r_ext_vertex_array_object;
100.3813 +extern cvar_t  *r_ext_half_float_pixel;
100.3814 +extern cvar_t  *r_ext_texture_float;
100.3815 +extern cvar_t  *r_ext_stencil_wrap;
100.3816 +extern cvar_t  *r_ext_texture_filter_anisotropic;
100.3817 +extern cvar_t  *r_ext_stencil_two_side;
100.3818 +extern cvar_t  *r_ext_separate_stencil;
100.3819 +extern cvar_t  *r_ext_depth_bounds_test;
100.3820 +extern cvar_t  *r_ext_framebuffer_object;
100.3821 +extern cvar_t  *r_ext_packed_depth_stencil;
100.3822 +extern cvar_t  *r_ext_framebuffer_blit;
100.3823 +extern cvar_t  *r_extx_framebuffer_mixed_formats;
100.3824 +extern cvar_t  *r_ext_generate_mipmap;
100.3825 +
100.3826 +extern cvar_t  *r_nobind;		// turns off binding to appropriate textures
100.3827 +extern cvar_t  *r_collapseStages;
100.3828 +extern cvar_t  *r_singleShader;	// make most world faces use default shader
100.3829 +extern cvar_t  *r_roundImagesDown;
100.3830 +extern cvar_t  *r_colorMipLevels;	// development aid to see texture mip usage
100.3831 +extern cvar_t  *r_picmip;		// controls picmip values
100.3832 +extern cvar_t  *r_finish;
100.3833 +extern cvar_t  *r_drawBuffer;
100.3834 +extern cvar_t  *r_swapInterval;
100.3835 +extern cvar_t  *r_textureMode;
100.3836 +extern cvar_t  *r_offsetFactor;
100.3837 +extern cvar_t  *r_offsetUnits;
100.3838 +extern cvar_t  *r_forceSpecular;
100.3839 +extern cvar_t  *r_specularExponent;
100.3840 +extern cvar_t  *r_specularScale;
100.3841 +extern cvar_t  *r_normalScale;
100.3842 +extern cvar_t  *r_normalMapping;
100.3843 +
100.3844 +extern cvar_t  *r_uiFullScreen;	// ui is running fullscreen
100.3845 +
100.3846 +extern cvar_t  *r_logFile;		// number of frames to emit GL logs
100.3847 +
100.3848 +extern cvar_t  *r_clear;		// force screen clear every frame
100.3849 +
100.3850 +extern cvar_t  *r_shadows;		// controls shadows: 0 = none, 1 = blur, 2 = black planar projection,
100.3851 +
100.3852 +								// 3 = stencil shadow volumes
100.3853 +								// 4 = shadow mapping
100.3854 +extern cvar_t  *r_softShadows;
100.3855 +extern cvar_t  *r_shadowBlur;
100.3856 +extern cvar_t  *r_shadowMapQuality;
100.3857 +extern cvar_t  *r_shadowMapSizeUltra;
100.3858 +extern cvar_t  *r_shadowMapSizeVery;
100.3859 +extern cvar_t  *r_shadowMapSizeHigh;
100.3860 +extern cvar_t  *r_shadowMapSizeMedium;
100.3861 +extern cvar_t  *r_shadowMapSizeLow;
100.3862 +extern cvar_t  *r_shadowOffsetFactor;
100.3863 +extern cvar_t  *r_shadowOffsetUnits;
100.3864 +extern cvar_t  *r_shadowLodBias;
100.3865 +extern cvar_t  *r_shadowLodScale;
100.3866 +extern cvar_t  *r_noShadowPyramids;
100.3867 +extern cvar_t  *r_cullShadowPyramidFaces;
100.3868 +extern cvar_t  *r_cullShadowPyramidCurves;
100.3869 +extern cvar_t  *r_cullShadowPyramidTriangles;
100.3870 +extern cvar_t  *r_debugShadowMaps;
100.3871 +extern cvar_t  *r_noShadowFrustums;
100.3872 +extern cvar_t  *r_noLightFrustums;
100.3873 +extern cvar_t  *r_shadowMapLuminanceAlpha;
100.3874 +extern cvar_t  *r_shadowMapLinearFilter;
100.3875 +extern cvar_t  *r_lightBleedReduction;
100.3876 +extern cvar_t  *r_overDarkeningFactor;
100.3877 +extern cvar_t  *r_shadowMapDepthScale;
100.3878 +
100.3879 +extern cvar_t  *r_intensity;
100.3880 +
100.3881 +extern cvar_t  *r_lockpvs;
100.3882 +extern cvar_t  *r_noportals;
100.3883 +extern cvar_t  *r_portalOnly;
100.3884 +
100.3885 +extern cvar_t  *r_subdivisions;
100.3886 +extern cvar_t  *r_stitchCurves;
100.3887 +
100.3888 +extern cvar_t  *r_smp;
100.3889 +extern cvar_t  *r_showSmp;
100.3890 +extern cvar_t  *r_skipBackEnd;
100.3891 +
100.3892 +extern cvar_t  *r_ignoreGLErrors;
100.3893 +
100.3894 +extern cvar_t  *r_overBrightBits;
100.3895 +extern cvar_t  *r_mapOverBrightBits;
100.3896 +
100.3897 +extern cvar_t  *r_debugSurface;
100.3898 +extern cvar_t  *r_simpleMipMaps;
100.3899 +
100.3900 +extern cvar_t  *r_showImages;
100.3901 +extern cvar_t  *r_debugSort;
100.3902 +
100.3903 +extern cvar_t  *r_printShaders;
100.3904 +
100.3905 +extern cvar_t  *r_maxPolys;
100.3906 +extern cvar_t  *r_maxPolyVerts;
100.3907 +
100.3908 +extern cvar_t  *r_showTris;		// enables wireframe rendering of the world
100.3909 +extern cvar_t  *r_showSky;		// forces sky in front of all surfaces
100.3910 +extern cvar_t  *r_showShadowVolumes;
100.3911 +extern cvar_t  *r_showShadowLod;
100.3912 +extern cvar_t  *r_showSkeleton;
100.3913 +extern cvar_t  *r_showEntityTransforms;
100.3914 +extern cvar_t  *r_showLightTransforms;
100.3915 +extern cvar_t  *r_showLightInteractions;
100.3916 +extern cvar_t  *r_showLightScissors;
100.3917 +extern cvar_t  *r_showLightBatches;
100.3918 +extern cvar_t  *r_showOcclusionQueries;
100.3919 +extern cvar_t  *r_showBatches;
100.3920 +extern cvar_t  *r_showLightMaps;	// render lightmaps only
100.3921 +extern cvar_t  *r_showDeluxeMaps;
100.3922 +extern cvar_t  *r_showAreaPortals;
100.3923 +extern cvar_t  *r_showCubeProbes;
100.3924 +
100.3925 +extern cvar_t  *r_showDeferredDiffuse;
100.3926 +extern cvar_t  *r_showDeferredNormal;
100.3927 +extern cvar_t  *r_showDeferredSpecular;
100.3928 +extern cvar_t  *r_showDeferredPosition;
100.3929 +extern cvar_t  *r_showDeferredRender;
100.3930 +
100.3931 +extern cvar_t  *r_vboFaces;
100.3932 +extern cvar_t  *r_vboCurves;
100.3933 +extern cvar_t  *r_vboTriangles;
100.3934 +extern cvar_t  *r_vboShadows;
100.3935 +extern cvar_t  *r_vboLighting;
100.3936 +extern cvar_t  *r_vboDynamicLighting;
100.3937 +extern cvar_t  *r_vboModels;
100.3938 +extern cvar_t  *r_vboWorld;
100.3939 +extern cvar_t  *r_vboOptimizeVertices;
100.3940 +extern cvar_t  *r_vboVertexSkinning;
100.3941 +extern cvar_t  *r_vboSmoothNormals;
100.3942 +
100.3943 +extern cvar_t  *r_precacheLightIndexes;
100.3944 +extern cvar_t  *r_precacheShadowIndexes;
100.3945