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(®isteredFont[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