summaryrefslogtreecommitdiff
path: root/src/rend2
diff options
context:
space:
mode:
Diffstat (limited to 'src/rend2')
-rw-r--r--src/rend2/glsl/bokeh_fp.glsl70
-rw-r--r--src/rend2/glsl/bokeh_vp.glsl13
-rw-r--r--src/rend2/glsl/calclevels4x_fp.glsl55
-rw-r--r--src/rend2/glsl/calclevels4x_vp.glsl13
-rw-r--r--src/rend2/glsl/depthblur_fp.glsl58
-rw-r--r--src/rend2/glsl/depthblur_vp.glsl12
-rw-r--r--src/rend2/glsl/dlight_fp.glsl12
-rw-r--r--src/rend2/glsl/dlight_vp.glsl92
-rw-r--r--src/rend2/glsl/down4x_fp.glsl34
-rw-r--r--src/rend2/glsl/down4x_vp.glsl13
-rw-r--r--src/rend2/glsl/fogpass_fp.glsl9
-rw-r--r--src/rend2/glsl/fogpass_vp.glsl117
-rw-r--r--src/rend2/glsl/generic_fp.glsl43
-rw-r--r--src/rend2/glsl/generic_vp.glsl251
-rw-r--r--src/rend2/glsl/lightall_fp.glsl383
-rw-r--r--src/rend2/glsl/lightall_vp.glsl219
-rw-r--r--src/rend2/glsl/pshadow_fp.glsl98
-rw-r--r--src/rend2/glsl/pshadow_vp.glsl17
-rw-r--r--src/rend2/glsl/shadowfill_fp.glsl41
-rw-r--r--src/rend2/glsl/shadowfill_vp.glsl89
-rw-r--r--src/rend2/glsl/shadowmask_fp.glsl127
-rw-r--r--src/rend2/glsl/shadowmask_vp.glsl18
-rw-r--r--src/rend2/glsl/ssao_fp.glsl86
-rw-r--r--src/rend2/glsl/ssao_vp.glsl12
-rw-r--r--src/rend2/glsl/texturecolor_fp.glsl12
-rw-r--r--src/rend2/glsl/texturecolor_vp.glsl15
-rw-r--r--src/rend2/glsl/tonemap_fp.glsl48
-rw-r--r--src/rend2/glsl/tonemap_vp.glsl13
-rw-r--r--src/rend2/qgl.h755
-rw-r--r--src/rend2/tr_animation.c658
-rw-r--r--src/rend2/tr_backend.c1843
-rw-r--r--src/rend2/tr_bsp.c3370
-rw-r--r--src/rend2/tr_cmds.c668
-rw-r--r--src/rend2/tr_curve.c806
-rw-r--r--src/rend2/tr_extensions.c667
-rw-r--r--src/rend2/tr_extramath.c233
-rw-r--r--src/rend2/tr_extramath.h101
-rw-r--r--src/rend2/tr_extratypes.h43
-rw-r--r--src/rend2/tr_fbo.c861
-rw-r--r--src/rend2/tr_fbo.h64
-rw-r--r--src/rend2/tr_flares.c532
-rw-r--r--src/rend2/tr_font.c554
-rw-r--r--src/rend2/tr_glsl.c1932
-rw-r--r--src/rend2/tr_image.c3462
-rw-r--r--src/rend2/tr_image_bmp.c243
-rw-r--r--src/rend2/tr_image_jpg.c441
-rw-r--r--src/rend2/tr_image_pcx.c179
-rw-r--r--src/rend2/tr_image_png.c2490
-rw-r--r--src/rend2/tr_image_tga.c324
-rw-r--r--src/rend2/tr_init.c1480
-rw-r--r--src/rend2/tr_light.c447
-rw-r--r--src/rend2/tr_local.h2856
-rw-r--r--src/rend2/tr_main.c2882
-rw-r--r--src/rend2/tr_marks.c466
-rw-r--r--src/rend2/tr_mesh.c405
-rw-r--r--src/rend2/tr_model.c1583
-rw-r--r--src/rend2/tr_model_iqm.c1058
-rw-r--r--src/rend2/tr_noise.c93
-rw-r--r--src/rend2/tr_postprocess.c488
-rw-r--r--src/rend2/tr_postprocess.h33
-rw-r--r--src/rend2/tr_scene.c520
-rw-r--r--src/rend2/tr_shade.c1866
-rw-r--r--src/rend2/tr_shade_calc.c1339
-rw-r--r--src/rend2/tr_shader.c3741
-rw-r--r--src/rend2/tr_shadows.c343
-rw-r--r--src/rend2/tr_sky.c916
-rw-r--r--src/rend2/tr_subs.c48
-rw-r--r--src/rend2/tr_surface.c1698
-rw-r--r--src/rend2/tr_vbo.c928
-rw-r--r--src/rend2/tr_world.c850
70 files changed, 0 insertions, 46236 deletions
diff --git a/src/rend2/glsl/bokeh_fp.glsl b/src/rend2/glsl/bokeh_fp.glsl
deleted file mode 100644
index d08816ae..00000000
--- a/src/rend2/glsl/bokeh_fp.glsl
+++ /dev/null
@@ -1,70 +0,0 @@
-uniform sampler2D u_TextureMap;
-
-uniform vec4 u_Color;
-
-uniform vec2 u_InvTexRes;
-varying vec2 var_TexCoords;
-
-void main()
-{
- vec4 color;
- vec2 tc;
-
-#if 0
- float c[7] = float[7](1.0, 0.9659258263, 0.8660254038, 0.7071067812, 0.5, 0.2588190451, 0.0);
-
- tc = var_TexCoords + u_InvTexRes * vec2( c[0], c[6]); color = texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[1], c[5]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[2], c[4]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[3], c[3]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[4], c[2]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[5], c[1]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[6], c[0]); color += texture2D(u_TextureMap, tc);
-
- tc = var_TexCoords + u_InvTexRes * vec2( c[1], -c[5]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[2], -c[4]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[3], -c[3]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[4], -c[2]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[5], -c[1]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[6], -c[0]); color += texture2D(u_TextureMap, tc);
-
- tc = var_TexCoords + u_InvTexRes * vec2( -c[0], c[6]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( -c[1], c[5]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( -c[2], c[4]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( -c[3], c[3]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( -c[4], c[2]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( -c[5], c[1]); color += texture2D(u_TextureMap, tc);
-
- tc = var_TexCoords + u_InvTexRes * vec2( -c[1], -c[5]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( -c[2], -c[4]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( -c[3], -c[3]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( -c[4], -c[2]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( -c[5], -c[1]); color += texture2D(u_TextureMap, tc);
-
- gl_FragColor = color * 0.04166667 * u_Color;
-#endif
-
- float c[5] = float[5](1.0, 0.9238795325, 0.7071067812, 0.3826834324, 0.0);
-
- tc = var_TexCoords + u_InvTexRes * vec2( c[0], c[4]); color = texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[1], c[3]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[2], c[2]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[3], c[1]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[4], c[0]); color += texture2D(u_TextureMap, tc);
-
- tc = var_TexCoords + u_InvTexRes * vec2( c[1], -c[3]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[2], -c[2]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[3], -c[1]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( c[4], -c[0]); color += texture2D(u_TextureMap, tc);
-
- tc = var_TexCoords + u_InvTexRes * vec2( -c[0], c[4]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( -c[1], c[3]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( -c[2], c[2]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( -c[3], c[1]); color += texture2D(u_TextureMap, tc);
-
- tc = var_TexCoords + u_InvTexRes * vec2( -c[1], -c[3]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( -c[2], -c[2]); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( -c[3], -c[1]); color += texture2D(u_TextureMap, tc);
-
- gl_FragColor = color * 0.0625 * u_Color;
-}
diff --git a/src/rend2/glsl/bokeh_vp.glsl b/src/rend2/glsl/bokeh_vp.glsl
deleted file mode 100644
index 5ca41600..00000000
--- a/src/rend2/glsl/bokeh_vp.glsl
+++ /dev/null
@@ -1,13 +0,0 @@
-attribute vec4 attr_Position;
-attribute vec4 attr_TexCoord0;
-
-uniform mat4 u_ModelViewProjectionMatrix;
-
-varying vec2 var_TexCoords;
-
-
-void main()
-{
- gl_Position = u_ModelViewProjectionMatrix * attr_Position;
- var_TexCoords = attr_TexCoord0.st;
-}
diff --git a/src/rend2/glsl/calclevels4x_fp.glsl b/src/rend2/glsl/calclevels4x_fp.glsl
deleted file mode 100644
index c8cf06c7..00000000
--- a/src/rend2/glsl/calclevels4x_fp.glsl
+++ /dev/null
@@ -1,55 +0,0 @@
-uniform sampler2D u_TextureMap;
-
-uniform vec4 u_Color;
-
-uniform vec2 u_InvTexRes;
-varying vec2 var_TexCoords;
-
-const vec3 LUMINANCE_VECTOR = vec3(0.2125, 0.7154, 0.0721); //vec3(0.299, 0.587, 0.114);
-
-vec3 GetValues(vec2 offset, vec3 current)
-{
- vec3 minAvgMax;
- vec2 tc = var_TexCoords + u_InvTexRes * offset; minAvgMax = texture2D(u_TextureMap, tc).rgb;
-
-#ifdef FIRST_PASS
- float lumi = max(dot(LUMINANCE_VECTOR, minAvgMax), 0.000001);
- float loglumi = clamp(log2(lumi), -10.0, 10.0);
- minAvgMax = vec3(loglumi * 0.05 + 0.5);
-#endif
-
- return vec3(min(current.x, minAvgMax.x), current.y + minAvgMax.y, max(current.z, minAvgMax.z));
-}
-
-void main()
-{
- vec3 current = vec3(1.0, 0.0, 0.0);
-
-#ifdef FIRST_PASS
- current = GetValues(vec2( 0.0, 0.0), current);
-#else
- current = GetValues(vec2(-1.5, -1.5), current);
- current = GetValues(vec2(-0.5, -1.5), current);
- current = GetValues(vec2( 0.5, -1.5), current);
- current = GetValues(vec2( 1.5, -1.5), current);
-
- current = GetValues(vec2(-1.5, -0.5), current);
- current = GetValues(vec2(-0.5, -0.5), current);
- current = GetValues(vec2( 0.5, -0.5), current);
- current = GetValues(vec2( 1.5, -0.5), current);
-
- current = GetValues(vec2(-1.5, 0.5), current);
- current = GetValues(vec2(-0.5, 0.5), current);
- current = GetValues(vec2( 0.5, 0.5), current);
- current = GetValues(vec2( 1.5, 0.5), current);
-
- current = GetValues(vec2(-1.5, 1.5), current);
- current = GetValues(vec2(-0.5, 1.5), current);
- current = GetValues(vec2( 0.5, 1.5), current);
- current = GetValues(vec2( 1.5, 1.5), current);
-
- current.y *= 0.0625;
-#endif
-
- gl_FragColor = vec4(current, 1.0f);
-}
diff --git a/src/rend2/glsl/calclevels4x_vp.glsl b/src/rend2/glsl/calclevels4x_vp.glsl
deleted file mode 100644
index 5ca41600..00000000
--- a/src/rend2/glsl/calclevels4x_vp.glsl
+++ /dev/null
@@ -1,13 +0,0 @@
-attribute vec4 attr_Position;
-attribute vec4 attr_TexCoord0;
-
-uniform mat4 u_ModelViewProjectionMatrix;
-
-varying vec2 var_TexCoords;
-
-
-void main()
-{
- gl_Position = u_ModelViewProjectionMatrix * attr_Position;
- var_TexCoords = attr_TexCoord0.st;
-}
diff --git a/src/rend2/glsl/depthblur_fp.glsl b/src/rend2/glsl/depthblur_fp.glsl
deleted file mode 100644
index 93895b4e..00000000
--- a/src/rend2/glsl/depthblur_fp.glsl
+++ /dev/null
@@ -1,58 +0,0 @@
-uniform sampler2D u_ScreenImageMap;
-uniform sampler2D u_ScreenDepthMap;
-
-uniform vec4 u_ViewInfo; // zfar / znear, zfar
-varying vec2 var_ScreenTex;
-
-//float gauss[5] = float[5](0.30, 0.23, 0.097, 0.024, 0.0033);
-float gauss[4] = float[4](0.40, 0.24, 0.054, 0.0044);
-//float gauss[3] = float[3](0.60, 0.19, 0.0066);
-#define GAUSS_SIZE 4
-
-float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNear)
-{
- float sampleZDivW = texture2D(depthMap, tex).r;
- return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);
-}
-
-vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFarDivZNear, float zFar)
-{
- float scale = 1.0 / 256.0;
-
-#if defined(USE_HORIZONTAL_BLUR)
- vec2 direction = vec2(1.0, 0.0) * scale;
-#else // if defined(USE_VERTICAL_BLUR)
- vec2 direction = vec2(0.0, 1.0) * scale;
-#endif
-
- float depthCenter = zFar * getLinearDepth(depthMap, tex, zFarDivZNear);
- vec2 centerSlope = vec2(dFdx(depthCenter), dFdy(depthCenter)) / vec2(dFdx(tex.x), dFdy(tex.y));
-
- vec4 result = texture2D(imageMap, tex) * gauss[0];
- float total = gauss[0];
-
- int i, j;
- for (i = 0; i < 2; i++)
- {
- for (j = 1; j < GAUSS_SIZE; j++)
- {
- vec2 offset = direction * j;
- float depthSample = zFar * getLinearDepth(depthMap, tex + offset, zFarDivZNear);
- float depthExpected = depthCenter + dot(centerSlope, offset);
- if(abs(depthSample - depthExpected) < 5.0)
- {
- result += texture2D(imageMap, tex + offset) * gauss[j];
- total += gauss[j];
- }
- }
-
- direction = -direction;
- }
-
- return result / total;
-}
-
-void main()
-{
- gl_FragColor = depthGaussian1D(u_ScreenImageMap, u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y);
-}
diff --git a/src/rend2/glsl/depthblur_vp.glsl b/src/rend2/glsl/depthblur_vp.glsl
deleted file mode 100644
index 9c46a79f..00000000
--- a/src/rend2/glsl/depthblur_vp.glsl
+++ /dev/null
@@ -1,12 +0,0 @@
-attribute vec4 attr_Position;
-attribute vec4 attr_TexCoord0;
-
-varying vec2 var_ScreenTex;
-
-void main()
-{
- gl_Position = attr_Position;
- var_ScreenTex = attr_TexCoord0.xy;
- //vec2 screenCoords = gl_Position.xy / gl_Position.w;
- //var_ScreenTex = screenCoords * 0.5 + 0.5;
-}
diff --git a/src/rend2/glsl/dlight_fp.glsl b/src/rend2/glsl/dlight_fp.glsl
deleted file mode 100644
index 8ffca5b9..00000000
--- a/src/rend2/glsl/dlight_fp.glsl
+++ /dev/null
@@ -1,12 +0,0 @@
-uniform sampler2D u_DiffuseMap;
-
-varying vec2 var_Tex1;
-varying vec4 var_Color;
-
-
-void main()
-{
- vec4 color = texture2D(u_DiffuseMap, var_Tex1);
-
- gl_FragColor = color * var_Color;
-}
diff --git a/src/rend2/glsl/dlight_vp.glsl b/src/rend2/glsl/dlight_vp.glsl
deleted file mode 100644
index d9fd71d0..00000000
--- a/src/rend2/glsl/dlight_vp.glsl
+++ /dev/null
@@ -1,92 +0,0 @@
-attribute vec4 attr_Position;
-attribute vec4 attr_TexCoord0;
-attribute vec3 attr_Normal;
-
-uniform vec4 u_DlightInfo;
-
-#if defined(USE_DEFORM_VERTEXES)
-uniform int u_DeformGen;
-uniform float u_DeformParams[5];
-uniform float u_Time;
-#endif
-
-uniform vec4 u_Color;
-uniform mat4 u_ModelViewProjectionMatrix;
-
-varying vec2 var_Tex1;
-varying vec4 var_Color;
-
-#if defined(USE_DEFORM_VERTEXES)
-vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
-{
- if (u_DeformGen == 0)
- {
- return pos;
- }
-
- float base = u_DeformParams[0];
- float amplitude = u_DeformParams[1];
- float phase = u_DeformParams[2];
- float frequency = u_DeformParams[3];
- float spread = u_DeformParams[4];
-
- if (u_DeformGen == DGEN_BULGE)
- {
- phase *= M_PI * 0.25 * st.x;
- }
- else // if (u_DeformGen <= DGEN_WAVE_INVERSE_SAWTOOTH)
- {
- phase += dot(pos.xyz, vec3(spread));
- }
-
- float value = phase + (u_Time * frequency);
- float func;
-
- if (u_DeformGen == DGEN_WAVE_SIN)
- {
- func = sin(value * 2.0 * M_PI);
- }
- else if (u_DeformGen == DGEN_WAVE_SQUARE)
- {
- func = sign(sin(value * 2.0 * M_PI));
- }
- else if (u_DeformGen == DGEN_WAVE_TRIANGLE)
- {
- func = abs(fract(value + 0.75) - 0.5) * 4.0 - 1.0;
- }
- else if (u_DeformGen == DGEN_WAVE_SAWTOOTH)
- {
- func = fract(value);
- }
- else if (u_DeformGen == DGEN_WAVE_INVERSE_SAWTOOTH)
- {
- func = (1.0 - fract(value));
- }
- else if (u_DeformGen == DGEN_BULGE)
- {
- func = sin(value);
- }
-
- return pos + normal * (base + func * amplitude);
-}
-#endif
-
-void main()
-{
- vec4 position = attr_Position;
- vec3 normal = attr_Normal;
-
-#if defined(USE_DEFORM_VERTEXES)
- position.xyz = DeformPosition(position.xyz, normal, attr_TexCoord0.st);
-#endif
-
- gl_Position = u_ModelViewProjectionMatrix * position;
-
- vec3 dist = u_DlightInfo.xyz - position.xyz;
-
- var_Tex1 = dist.xy * u_DlightInfo.a + vec2(0.5);
- float dlightmod = step(0.0, dot(dist, normal));
- dlightmod *= clamp(2.0 * (1.0 - abs(dist.z) * u_DlightInfo.a), 0.0, 1.0);
-
- var_Color = u_Color * dlightmod;
-}
diff --git a/src/rend2/glsl/down4x_fp.glsl b/src/rend2/glsl/down4x_fp.glsl
deleted file mode 100644
index 0f88fb2e..00000000
--- a/src/rend2/glsl/down4x_fp.glsl
+++ /dev/null
@@ -1,34 +0,0 @@
-uniform sampler2D u_TextureMap;
-
-uniform vec2 u_InvTexRes;
-varying vec2 var_TexCoords;
-
-void main()
-{
- vec4 color;
- vec2 tc;
-
- tc = var_TexCoords + u_InvTexRes * vec2(-1.5, -1.5); color = texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2(-0.5, -1.5); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( 0.5, -1.5); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( 1.5, -1.5); color += texture2D(u_TextureMap, tc);
-
- tc = var_TexCoords + u_InvTexRes * vec2(-1.5, -0.5); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2(-0.5, -0.5); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( 0.5, -0.5); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( 1.5, -0.5); color += texture2D(u_TextureMap, tc);
-
- tc = var_TexCoords + u_InvTexRes * vec2(-1.5, 0.5); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2(-0.5, 0.5); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( 0.5, 0.5); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( 1.5, 0.5); color += texture2D(u_TextureMap, tc);
-
- tc = var_TexCoords + u_InvTexRes * vec2(-1.5, 1.5); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2(-0.5, 1.5); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( 0.5, 1.5); color += texture2D(u_TextureMap, tc);
- tc = var_TexCoords + u_InvTexRes * vec2( 1.5, 1.5); color += texture2D(u_TextureMap, tc);
-
- color *= 0.0625;
-
- gl_FragColor = color;
-}
diff --git a/src/rend2/glsl/down4x_vp.glsl b/src/rend2/glsl/down4x_vp.glsl
deleted file mode 100644
index 5ca41600..00000000
--- a/src/rend2/glsl/down4x_vp.glsl
+++ /dev/null
@@ -1,13 +0,0 @@
-attribute vec4 attr_Position;
-attribute vec4 attr_TexCoord0;
-
-uniform mat4 u_ModelViewProjectionMatrix;
-
-varying vec2 var_TexCoords;
-
-
-void main()
-{
- gl_Position = u_ModelViewProjectionMatrix * attr_Position;
- var_TexCoords = attr_TexCoord0.st;
-}
diff --git a/src/rend2/glsl/fogpass_fp.glsl b/src/rend2/glsl/fogpass_fp.glsl
deleted file mode 100644
index 91884304..00000000
--- a/src/rend2/glsl/fogpass_fp.glsl
+++ /dev/null
@@ -1,9 +0,0 @@
-uniform vec4 u_Color;
-
-varying float var_Scale;
-
-void main()
-{
- gl_FragColor = u_Color;
- gl_FragColor.a *= sqrt(clamp(var_Scale, 0.0, 1.0));
-}
diff --git a/src/rend2/glsl/fogpass_vp.glsl b/src/rend2/glsl/fogpass_vp.glsl
deleted file mode 100644
index f18bc707..00000000
--- a/src/rend2/glsl/fogpass_vp.glsl
+++ /dev/null
@@ -1,117 +0,0 @@
-attribute vec4 attr_Position;
-attribute vec3 attr_Normal;
-attribute vec4 attr_TexCoord0;
-
-//#if defined(USE_VERTEX_ANIMATION)
-attribute vec4 attr_Position2;
-attribute vec3 attr_Normal2;
-//#endif
-
-uniform vec4 u_FogDistance;
-uniform vec4 u_FogDepth;
-uniform float u_FogEyeT;
-
-//#if defined(USE_DEFORM_VERTEXES)
-uniform int u_DeformGen;
-uniform float u_DeformParams[5];
-//#endif
-
-uniform float u_Time;
-uniform mat4 u_ModelViewProjectionMatrix;
-
-//#if defined(USE_VERTEX_ANIMATION)
-uniform float u_VertexLerp;
-//#endif
-
-varying float var_Scale;
-
-#if defined(USE_DEFORM_VERTEXES)
-vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
-{
- if (u_DeformGen == 0)
- {
- return pos;
- }
-
- float base = u_DeformParams[0];
- float amplitude = u_DeformParams[1];
- float phase = u_DeformParams[2];
- float frequency = u_DeformParams[3];
- float spread = u_DeformParams[4];
-
- if (u_DeformGen == DGEN_BULGE)
- {
- phase *= M_PI * 0.25 * st.x;
- }
- else // if (u_DeformGen <= DGEN_WAVE_INVERSE_SAWTOOTH)
- {
- phase += dot(pos.xyz, vec3(spread));
- }
-
- float value = phase + (u_Time * frequency);
- float func;
-
- if (u_DeformGen == DGEN_WAVE_SIN)
- {
- func = sin(value * 2.0 * M_PI);
- }
- else if (u_DeformGen == DGEN_WAVE_SQUARE)
- {
- func = sign(sin(value * 2.0 * M_PI));
- }
- else if (u_DeformGen == DGEN_WAVE_TRIANGLE)
- {
- func = abs(fract(value + 0.75) - 0.5) * 4.0 - 1.0;
- }
- else if (u_DeformGen == DGEN_WAVE_SAWTOOTH)
- {
- func = fract(value);
- }
- else if (u_DeformGen == DGEN_WAVE_INVERSE_SAWTOOTH)
- {
- func = (1.0 - fract(value));
- }
- else if (u_DeformGen == DGEN_BULGE)
- {
- func = sin(value);
- }
-
- return pos + normal * (base + func * amplitude);
-}
-#endif
-
-float CalcFog(vec4 position)
-{
- float s = dot(position, u_FogDistance) * 8.0;
- float t = dot(position, u_FogDepth);
-
- if (t < 1.0)
- {
- t = step(step(0.0, -u_FogEyeT), t);
- }
- else
- {
- t /= t - min(u_FogEyeT, 0.0);
- }
-
- return s * t;
-}
-
-void main()
-{
-#if defined(USE_VERTEX_ANIMATION)
- vec4 position = mix(attr_Position, attr_Position2, u_VertexLerp);
- vec3 normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp));
-#else
- vec4 position = attr_Position;
- vec3 normal = attr_Normal;
-#endif
-
-#if defined(USE_DEFORM_VERTEXES)
- position.xyz = DeformPosition(position.xyz, normal, attr_TexCoord0.st);
-#endif
-
- gl_Position = u_ModelViewProjectionMatrix * position;
-
- var_Scale = CalcFog(position);
-}
diff --git a/src/rend2/glsl/generic_fp.glsl b/src/rend2/glsl/generic_fp.glsl
deleted file mode 100644
index dea52e06..00000000
--- a/src/rend2/glsl/generic_fp.glsl
+++ /dev/null
@@ -1,43 +0,0 @@
-uniform sampler2D u_DiffuseMap;
-
-#if defined(USE_LIGHTMAP)
-uniform sampler2D u_LightMap;
-
-uniform int u_Texture1Env;
-#endif
-
-varying vec2 var_DiffuseTex;
-
-#if defined(USE_LIGHTMAP)
-varying vec2 var_LightTex;
-#endif
-
-varying vec4 var_Color;
-
-
-void main()
-{
- vec4 color = texture2D(u_DiffuseMap, var_DiffuseTex);
-#if defined(USE_LIGHTMAP)
- vec4 color2 = texture2D(u_LightMap, var_LightTex);
- #if defined(RGBE_LIGHTMAP)
- color2.rgb *= exp2(color2.a * 255.0 - 128.0);
- color2.a = 1.0;
- #endif
-
- if (u_Texture1Env == TEXENV_MODULATE)
- {
- color *= color2;
- }
- else if (u_Texture1Env == TEXENV_ADD)
- {
- color += color2;
- }
- else if (u_Texture1Env == TEXENV_REPLACE)
- {
- color = color2;
- }
-#endif
-
- gl_FragColor = color * var_Color;
-}
diff --git a/src/rend2/glsl/generic_vp.glsl b/src/rend2/glsl/generic_vp.glsl
deleted file mode 100644
index 67360b1b..00000000
--- a/src/rend2/glsl/generic_vp.glsl
+++ /dev/null
@@ -1,251 +0,0 @@
-attribute vec4 attr_Position;
-attribute vec3 attr_Normal;
-
-#if defined(USE_VERTEX_ANIMATION)
-attribute vec4 attr_Position2;
-attribute vec3 attr_Normal2;
-#endif
-
-attribute vec4 attr_Color;
-attribute vec4 attr_TexCoord0;
-
-#if defined(USE_LIGHTMAP) || defined(USE_TCGEN)
-attribute vec4 attr_TexCoord1;
-#endif
-
-uniform vec4 u_DiffuseTexMatrix;
-uniform vec4 u_DiffuseTexOffTurb;
-
-#if defined(USE_TCGEN) || defined(USE_RGBAGEN)
-uniform vec3 u_ViewOrigin;
-#endif
-
-#if defined(USE_TCGEN)
-uniform int u_TCGen0;
-uniform vec3 u_TCGen0Vector0;
-uniform vec3 u_TCGen0Vector1;
-#endif
-
-#if defined(USE_FOG)
-uniform vec4 u_FogDistance;
-uniform vec4 u_FogDepth;
-uniform float u_FogEyeT;
-uniform vec4 u_FogColorMask;
-#endif
-
-#if defined(USE_DEFORM_VERTEXES)
-uniform int u_DeformGen;
-uniform float u_DeformParams[5];
-uniform float u_Time;
-#endif
-
-uniform mat4 u_ModelViewProjectionMatrix;
-uniform vec4 u_BaseColor;
-uniform vec4 u_VertColor;
-
-#if defined(USE_RGBAGEN)
-uniform int u_ColorGen;
-uniform int u_AlphaGen;
-uniform vec3 u_AmbientLight;
-uniform vec3 u_DirectedLight;
-uniform vec4 u_LightOrigin;
-uniform float u_PortalRange;
-#endif
-
-#if defined(USE_VERTEX_ANIMATION)
-uniform float u_VertexLerp;
-#endif
-
-varying vec2 var_DiffuseTex;
-#if defined(USE_LIGHTMAP)
-varying vec2 var_LightTex;
-#endif
-varying vec4 var_Color;
-
-#if defined(USE_DEFORM_VERTEXES)
-vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
-{
- float base = u_DeformParams[0];
- float amplitude = u_DeformParams[1];
- float phase = u_DeformParams[2];
- float frequency = u_DeformParams[3];
- float spread = u_DeformParams[4];
-
- if (u_DeformGen == DGEN_BULGE)
- {
- phase *= M_PI * 0.25 * st.x;
- }
- else // if (u_DeformGen <= DGEN_WAVE_INVERSE_SAWTOOTH)
- {
- phase += dot(pos.xyz, vec3(spread));
- }
-
- float value = phase + (u_Time * frequency);
- float func;
-
- if (u_DeformGen == DGEN_WAVE_SIN)
- {
- func = sin(value * 2.0 * M_PI);
- }
- else if (u_DeformGen == DGEN_WAVE_SQUARE)
- {
- func = sign(sin(value * 2.0 * M_PI));
- }
- else if (u_DeformGen == DGEN_WAVE_TRIANGLE)
- {
- func = abs(fract(value + 0.75) - 0.5) * 4.0 - 1.0;
- }
- else if (u_DeformGen == DGEN_WAVE_SAWTOOTH)
- {
- func = fract(value);
- }
- else if (u_DeformGen == DGEN_WAVE_INVERSE_SAWTOOTH)
- {
- func = (1.0 - fract(value));
- }
- else if (u_DeformGen == DGEN_BULGE)
- {
- func = sin(value);
- }
-
- return pos + normal * (base + func * amplitude);
-}
-#endif
-
-#if defined(USE_TCGEN)
-vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3 TCGenVector1)
-{
- vec2 tex = attr_TexCoord0.st;
-
- if (TCGen == TCGEN_LIGHTMAP)
- {
- tex = attr_TexCoord1.st;
- }
- else if (TCGen == TCGEN_ENVIRONMENT_MAPPED)
- {
- vec3 viewer = normalize(u_ViewOrigin - position);
- tex = -reflect(viewer, normal).yz * vec2(0.5, -0.5) + 0.5;
- }
- else if (TCGen == TCGEN_VECTOR)
- {
- tex = vec2(dot(position, TCGenVector0), dot(position, TCGenVector1));
- }
-
- return tex;
-}
-#endif
-
-#if defined(USE_TCMOD)
-vec2 ModTexCoords(vec2 st, vec3 position, vec4 texMatrix, vec4 offTurb)
-{
- float amplitude = offTurb.z;
- float phase = offTurb.w;
- vec2 st2 = vec2(dot(st, texMatrix.xz), dot(st, texMatrix.yw)) + offTurb.xy;
-
- vec3 offsetPos = position / 1024.0;
- offsetPos.x += offsetPos.z;
-
- vec2 texOffset = sin((offsetPos.xy + vec2(phase)) * 2.0 * M_PI);
-
- return st2 + texOffset * amplitude;
-}
-#endif
-
-#if defined(USE_RGBAGEN)
-vec4 CalcColor(vec3 position, vec3 normal)
-{
- vec4 color = u_VertColor * attr_Color + u_BaseColor;
-
- if (u_ColorGen == CGEN_LIGHTING_DIFFUSE)
- {
- float incoming = clamp(dot(normal, u_LightOrigin.xyz), 0.0, 1.0);
-
- color.rgb = clamp(u_DirectedLight * incoming + u_AmbientLight, 0.0, 1.0);
- }
-
- vec3 toView = u_ViewOrigin - position;
- vec3 viewer = normalize(u_ViewOrigin - position);
-
- if (u_AlphaGen == AGEN_LIGHTING_SPECULAR)
- {
- vec3 lightDir = normalize(vec3(-960.0, -1980.0, 96.0) - position.xyz);
- vec3 halfangle = normalize(lightDir + viewer);
-
- color.a = pow(max(dot(normal, halfangle), 0.0), 8.0);
- }
- else if (u_AlphaGen == AGEN_PORTAL)
- {
- float alpha = length(toView) / u_PortalRange;
-
- color.a = clamp(alpha, 0.0, 1.0);
- }
- else if (u_AlphaGen == AGEN_FRESNEL)
- {
- color.a = 0.10 + 0.90 * pow(1.0 - dot(normal, viewer), 5);
- }
-
- return color;
-}
-#endif
-
-#if defined(USE_FOG)
-float CalcFog(vec4 position)
-{
- float s = dot(position, u_FogDistance) * 8.0;
- float t = dot(position, u_FogDepth);
-
- if (t < 1.0)
- {
- t = step(step(0.0, -u_FogEyeT), t);
- }
- else
- {
- t /= t - min(u_FogEyeT, 0.0);
- }
-
- return s * t;
-}
-#endif
-
-void main()
-{
-#if defined(USE_VERTEX_ANIMATION)
- vec4 position = mix(attr_Position, attr_Position2, u_VertexLerp);
- vec3 normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp));
-#else
- vec4 position = attr_Position;
- vec3 normal = attr_Normal;
-#endif
-
-#if defined(USE_DEFORM_VERTEXES)
- position.xyz = DeformPosition(position.xyz, normal, attr_TexCoord0.st);
-#endif
-
- gl_Position = u_ModelViewProjectionMatrix * position;
-
-#if defined(USE_TCGEN)
- vec2 tex = GenTexCoords(u_TCGen0, position.xyz, normal, u_TCGen0Vector0, u_TCGen0Vector1);
-#else
- vec2 tex = attr_TexCoord0.st;
-#endif
-
-#if defined(USE_TCMOD)
- var_DiffuseTex = ModTexCoords(tex, position.xyz, u_DiffuseTexMatrix, u_DiffuseTexOffTurb);
-#else
- var_DiffuseTex = tex;
-#endif
-
-#if defined(USE_LIGHTMAP)
- var_LightTex = attr_TexCoord1.st;
-#endif
-
-#if defined(USE_RGBAGEN)
- var_Color = CalcColor(position.xyz, normal);
-#else
- var_Color = u_VertColor * attr_Color + u_BaseColor;
-#endif
-
-#if defined(USE_FOG)
- var_Color *= vec4(1.0) - u_FogColorMask * sqrt(clamp(CalcFog(position), 0.0, 1.0));
-#endif
-}
diff --git a/src/rend2/glsl/lightall_fp.glsl b/src/rend2/glsl/lightall_fp.glsl
deleted file mode 100644
index ec9bb2dc..00000000
--- a/src/rend2/glsl/lightall_fp.glsl
+++ /dev/null
@@ -1,383 +0,0 @@
-uniform sampler2D u_DiffuseMap;
-
-#if defined(USE_LIGHTMAP)
-uniform sampler2D u_LightMap;
-#endif
-
-#if defined(USE_NORMALMAP)
-uniform sampler2D u_NormalMap;
-#endif
-
-#if defined(USE_DELUXEMAP)
-uniform sampler2D u_DeluxeMap;
-#endif
-
-#if defined(USE_SPECULARMAP)
-uniform sampler2D u_SpecularMap;
-#endif
-
-#if defined(USE_SHADOWMAP)
-uniform sampler2D u_ShadowMap;
-#endif
-
-uniform vec3 u_ViewOrigin;
-
-#if defined(USE_TCGEN)
-uniform int u_TCGen0;
-#endif
-
-#if defined(USE_LIGHT_VECTOR)
-uniform vec3 u_DirectedLight;
-uniform vec3 u_AmbientLight;
-uniform float u_LightRadius;
-#endif
-
-#if defined(USE_LIGHT)
-uniform vec2 u_MaterialInfo;
-#endif
-
-varying vec2 var_DiffuseTex;
-#if defined(USE_LIGHTMAP)
-varying vec2 var_LightTex;
-#endif
-varying vec4 var_Color;
-
-#if defined(USE_NORMALMAP) && !defined(USE_VERT_TANGENT_SPACE)
-varying vec3 var_Position;
-#endif
-
-#if defined(USE_TCGEN) || defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
-varying vec3 var_SampleToView;
-#endif
-
-#if !defined(USE_FAST_LIGHT)
-varying vec3 var_Normal;
-#endif
-
-#if defined(USE_VERT_TANGENT_SPACE)
-varying vec3 var_Tangent;
-varying vec3 var_Bitangent;
-#endif
-
-varying vec3 var_VertLight;
-
-#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP)
-varying vec3 var_WorldLight;
-#endif
-
-#define EPSILON 0.00000001
-
-#if defined(USE_PARALLAXMAP)
-float SampleHeight(sampler2D normalMap, vec2 t)
-{
- #if defined(SWIZZLE_NORMALMAP)
- return texture2D(normalMap, t).r;
- #else
- return texture2D(normalMap, t).a;
- #endif
-}
-
-float RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap)
-{
- const int linearSearchSteps = 16;
- const int binarySearchSteps = 6;
-
- float depthStep = 1.0 / float(linearSearchSteps);
-
- // current size of search window
- float size = depthStep;
-
- // current depth position
- float depth = 0.0;
-
- // best match found (starts with last position 1.0)
- float bestDepth = 1.0;
-
- // search front to back for first point inside object
- for(int i = 0; i < linearSearchSteps - 1; ++i)
- {
- depth += size;
-
- float t = 1.0 - SampleHeight(normalMap, dp + ds * depth);
-
- if(bestDepth > 0.996) // if no depth found yet
- if(depth >= t)
- bestDepth = depth; // store best depth
- }
-
- depth = bestDepth;
-
- // recurse around first point (depth) for closest match
- for(int i = 0; i < binarySearchSteps; ++i)
- {
- size *= 0.5;
-
- float t = 1.0 - SampleHeight(normalMap, dp + ds * depth);
-
- if(depth >= t)
- {
- bestDepth = depth;
- depth -= 2.0 * size;
- }
-
- depth += size;
- }
-
- return bestDepth;
-}
-#endif
-
-float CalcDiffuse(vec3 N, vec3 L, vec3 E, float NE, float NL, float fzero, float shininess)
-{
- #if defined(USE_OREN_NAYAR) || defined(USE_TRIACE_OREN_NAYAR)
- float gamma = dot(E, L) - NE * NL;
- float B = 2.22222 + 0.1 * shininess;
-
- #if defined(USE_OREN_NAYAR)
- float A = 1.0 - 1.0 / (2.0 + 0.33 * shininess);
- gamma = clamp(gamma, 0.0, 1.0);
- #endif
-
- #if defined(USE_TRIACE_OREN_NAYAR)
- float A = 1.0 - 1.0 / (2.0 + 0.65 * shininess);
-
- if (gamma >= 0.0)
- #endif
- {
- B *= max(max(NL, NE), EPSILON);
- }
-
- return (A + gamma / B) * (1.0 - fzero);
- #else
- return 1.0 - fzero;
- #endif
-}
-
-#if defined(USE_SPECULARMAP)
-float CalcSpecular(float NH, float NL, float NE, float EH, float fzero, float shininess)
-{
- #if defined(USE_BLINN) || defined(USE_TRIACE) || defined(USE_TORRANCE_SPARROW)
- float blinn = pow(NH, shininess);
- #endif
-
- #if defined(USE_BLINN)
- return blinn;
- #endif
-
- #if defined(USE_COOK_TORRANCE) || defined (USE_TRIACE) || defined (USE_TORRANCE_SPARROW)
- float fresnel = fzero + (1.0 - fzero) * pow(1.0 - EH, 5);
- #endif
-
- #if defined(USE_COOK_TORRANCE) || defined(USE_TORRANCE_SPARROW)
- float geo = 2.0 * NH * min(NE, NL);
- geo /= max(EH, geo);
- #endif
-
- #if defined(USE_COOK_TORRANCE)
- float m_sq = 2.0 / max(shininess, EPSILON);
- float NH_sq = NH * NH;
- float m_NH_sq = m_sq * NH_sq;
- float beckmann = exp((NH_sq - 1.0) / max(m_NH_sq, EPSILON)) / max(4.0 * m_NH_sq * NH_sq, EPSILON);
-
- return fresnel * geo * beckmann / max(NE, EPSILON);
- #endif
-
- #if defined(USE_TRIACE)
- float scale = 0.1248582 * shininess + 0.2691817;
-
- return fresnel * scale * blinn / max(max(NL, NE), EPSILON);
- #endif
-
- #if defined(USE_TORRANCE_SPARROW)
- float scale = 0.125 * shininess + 1.0;
-
- return fresnel * geo * scale * blinn / max(NE, EPSILON);
- #endif
-}
-#endif
-
-void main()
-{
-#if !defined(USE_FAST_LIGHT) && (defined(USE_LIGHT) || defined(USE_NORMALMAP))
- vec3 surfNormal = normalize(var_Normal);
-#endif
-
-#if defined(USE_DELUXEMAP)
- vec3 worldLight = 2.0 * texture2D(u_DeluxeMap, var_LightTex).xyz - vec3(1.0);
- //worldLight += var_WorldLight * 0.0001;
-#elif defined(USE_LIGHT)
- vec3 worldLight = var_WorldLight;
-#endif
-
-#if defined(USE_LIGHTMAP)
- vec4 lightSample = texture2D(u_LightMap, var_LightTex).rgba;
- #if defined(RGBE_LIGHTMAP)
- lightSample.rgb *= exp2(lightSample.a * 255.0 - 128.0);
- #endif
- vec3 directedLight = lightSample.rgb;
-#elif defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT)
- #if defined(USE_INVSQRLIGHT)
- float intensity = 1.0 / dot(worldLight, worldLight);
- #else
- float intensity = clamp((1.0 - dot(worldLight, worldLight) / (u_LightRadius * u_LightRadius)) * 1.07, 0.0, 1.0);
- #endif
-
- vec3 directedLight = u_DirectedLight * intensity;
- vec3 ambientLight = u_AmbientLight;
-
- #if defined(USE_SHADOWMAP)
- vec2 shadowTex = gl_FragCoord.xy * r_FBufScale;
- directedLight *= texture2D(u_ShadowMap, shadowTex).r;
- #endif
-#elif defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
- vec3 directedLight = var_VertLight;
-#endif
-
-#if defined(USE_TCGEN) || defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
- vec3 SampleToView = normalize(var_SampleToView);
-#endif
- vec2 tex = var_DiffuseTex;
-
- float ambientDiff = 1.0;
-
-#if defined(USE_NORMALMAP)
- #if defined(USE_VERT_TANGENT_SPACE)
- vec3 tangent = var_Tangent;
- vec3 bitangent = var_Bitangent;
- #else
- vec3 q0 = dFdx(var_Position);
- vec3 q1 = dFdy(var_Position);
- vec2 st0 = dFdx(tex);
- vec2 st1 = dFdy(tex);
- float dir = sign(st1.t * st0.s - st0.t * st1.s);
-
- vec3 tangent = normalize( q0 * st1.t - q1 * st0.t) * dir;
- vec3 bitangent = -normalize( q0 * st1.s - q1 * st0.s) * dir;
- #endif
-
- mat3 tangentToWorld = mat3(tangent, bitangent, var_Normal);
-
- #if defined(USE_PARALLAXMAP)
- vec3 offsetDir = normalize(SampleToView * tangentToWorld);
- #if 0
- float height = SampleHeight(u_NormalMap, tex);
- float pdist = 0.05 * height - (0.05 / 2.0);
- #else
- offsetDir.xy *= -0.05 / offsetDir.z;
- float pdist = RayIntersectDisplaceMap(tex, offsetDir.xy, u_NormalMap);
- #endif
- tex += offsetDir.xy * pdist;
- #endif
- #if defined(SWIZZLE_NORMALMAP)
- vec3 normal = 2.0 * texture2D(u_NormalMap, tex).agb - 1.0;
- #else
- vec3 normal = 2.0 * texture2D(u_NormalMap, tex).rgb - 1.0;
- #endif
- normal.z = sqrt(clamp(1.0 - dot(normal.xy, normal.xy), 0.0, 1.0));
- vec3 worldNormal = tangentToWorld * normal;
- #if defined(r_normalAmbient)
- ambientDiff = 0.781341 * normal.z + 0.218659;
- #endif
-#elif defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
- vec3 worldNormal = surfNormal;
-#endif
-
-#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) || (defined(USE_TCGEN) && defined(USE_NORMALMAP))
- worldNormal = normalize(worldNormal);
-#endif
-
-#if defined(USE_TCGEN) && defined(USE_NORMALMAP)
- if (u_TCGen0 == TCGEN_ENVIRONMENT_MAPPED)
- {
- tex = -reflect(normalize(SampleToView), worldNormal).yz * vec2(0.5, -0.5) + 0.5;
- }
-#endif
-
- vec4 diffuse = texture2D(u_DiffuseMap, tex);
-
-#if defined(USE_LIGHT) && defined(USE_FAST_LIGHT)
- #if defined(USE_LIGHTMAP)
- diffuse.rgb *= directedLight;
- #endif
-#elif defined(USE_LIGHT)
- worldLight = normalize(worldLight);
-
- float surfNL = clamp(dot(surfNormal, worldLight), 0.0, 1.0);
-
- #if defined(USE_LIGHTMAP) || defined(USE_LIGHT_VERTEX)
- #if defined(USE_STANDARD_DELUXEMAP)
- // Standard deluxe mapping treats the light sample as fully directed
- // and doesn't compensate for light angle attenuation.
- vec3 ambientLight = vec3(0.0);
- #else
- // Separate the light sample into directed and ambient parts.
- //
- // ambientMax - if the cosine of the angle between the surface
- // normal and the light is below this value, the light
- // is fully ambient.
- // directedMax - if the cosine of the angle between the surface
- // normal and the light is above this value, the light
- // is fully directed.
- const float ambientMax = 0.25;
- const float directedMax = 0.5;
-
- float directedScale = clamp((surfNL - ambientMax) / (directedMax - ambientMax), 0.0, 1.0);
-
- // Scale the directed portion to compensate for the baked-in
- // light angle attenuation.
- directedScale /= max(surfNL, ambientMax);
-
- #if defined(r_normalAmbient)
- directedScale *= 1.0 - r_normalAmbient;
- #endif
-
- // Recover any unused light as ambient
- vec3 ambientLight = directedLight;
- directedLight *= directedScale;
- ambientLight -= directedLight * surfNL;
- #endif
- #endif
-
- float NL = clamp(dot(worldNormal, worldLight), 0.0, 1.0);
- float NE = clamp(dot(worldNormal, SampleToView), 0.0, 1.0);
-
- float fzero = u_MaterialInfo.x;
- float shininess = u_MaterialInfo.y;
-
- #if defined(USE_SPECULARMAP)
- vec4 specular = texture2D(u_SpecularMap, tex);
- //specular.rgb = clamp(specular.rgb - diffuse.rgb, 0.0, 1.0);
- shininess *= specular.a;
- #endif
-
- float directedDiff = NL * CalcDiffuse(worldNormal, worldLight, SampleToView, NE, NL, fzero, shininess);
- diffuse.rgb *= directedLight * directedDiff + ambientDiff * ambientLight;
-
- #if defined(USE_SPECULARMAP)
- vec3 halfAngle = normalize(worldLight + SampleToView);
-
- float EH = clamp(dot(SampleToView, halfAngle), 0.0, 1.0);
- float NH = clamp(dot(worldNormal, halfAngle), 0.0, 1.0);
-
- float directedSpec = NL * CalcSpecular(NH, NL, NE, EH, fzero, shininess);
-
- #if defined(r_normalAmbient)
- vec3 ambientHalf = normalize(surfNormal + SampleToView);
- float ambientSpec = max(dot(ambientHalf, worldNormal) + 0.5, 0.0);
- ambientSpec *= ambientSpec * 0.44;
- ambientSpec = pow(ambientSpec, shininess) * fzero;
- specular.rgb *= directedSpec * directedLight + ambientSpec * ambientLight;
- #else
- specular.rgb *= directedSpec * directedLight;
- #endif
- #endif
-#endif
-
- gl_FragColor = diffuse;
-
-#if defined(USE_SPECULARMAP) && defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
- gl_FragColor.rgb += specular.rgb;
-#endif
-
- gl_FragColor *= var_Color;
-}
diff --git a/src/rend2/glsl/lightall_vp.glsl b/src/rend2/glsl/lightall_vp.glsl
deleted file mode 100644
index 05a41f4d..00000000
--- a/src/rend2/glsl/lightall_vp.glsl
+++ /dev/null
@@ -1,219 +0,0 @@
-attribute vec4 attr_TexCoord0;
-#if defined(USE_LIGHTMAP)
-attribute vec4 attr_TexCoord1;
-#endif
-attribute vec4 attr_Color;
-
-attribute vec4 attr_Position;
-attribute vec3 attr_Normal;
-
-#if defined(USE_VERT_TANGENT_SPACE)
-attribute vec3 attr_Tangent;
-attribute vec3 attr_Bitangent;
-#endif
-
-#if defined(USE_VERTEX_ANIMATION)
-attribute vec4 attr_Position2;
-attribute vec3 attr_Normal2;
- #if defined(USE_VERT_TANGENT_SPACE)
-attribute vec3 attr_Tangent2;
-attribute vec3 attr_Bitangent2;
- #endif
-#endif
-
-#if defined(USE_LIGHT) && !defined(USE_LIGHT_VECTOR)
-attribute vec3 attr_LightDirection;
-#endif
-
-#if defined(USE_TCGEN) || defined(USE_NORMALMAP) || defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
-uniform vec3 u_ViewOrigin;
-#endif
-
-#if defined(USE_TCGEN)
-uniform int u_TCGen0;
-#endif
-
-#if defined(USE_TCMOD)
-uniform vec4 u_DiffuseTexMatrix;
-uniform vec4 u_DiffuseTexOffTurb;
-#endif
-
-uniform mat4 u_ModelViewProjectionMatrix;
-uniform vec4 u_BaseColor;
-uniform vec4 u_VertColor;
-
-#if defined(USE_MODELMATRIX)
-uniform mat4 u_ModelMatrix;
-#endif
-
-#if defined(USE_VERTEX_ANIMATION)
-uniform float u_VertexLerp;
-#endif
-
-#if defined(USE_LIGHT_VECTOR)
-uniform vec4 u_LightOrigin;
- #if defined(USE_FAST_LIGHT)
-uniform vec3 u_DirectedLight;
-uniform vec3 u_AmbientLight;
-uniform float u_LightRadius;
- #endif
-#endif
-
-varying vec2 var_DiffuseTex;
-
-#if defined(USE_LIGHTMAP)
-varying vec2 var_LightTex;
-#endif
-
-#if defined(USE_TCGEN) || defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
-varying vec3 var_SampleToView;
-#endif
-
-varying vec4 var_Color;
-
-#if defined(USE_NORMALMAP) && !defined(USE_VERT_TANGENT_SPACE)
-varying vec3 var_Position;
-#endif
-
-
-#if !defined(USE_FAST_LIGHT)
-varying vec3 var_Normal;
- #if defined(USE_VERT_TANGENT_SPACE)
-varying vec3 var_Tangent;
-varying vec3 var_Bitangent;
- #endif
-#endif
-
-#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
-varying vec3 var_VertLight;
-#endif
-
-#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT)
-varying vec3 var_WorldLight;
-#endif
-
-#if defined(USE_TCMOD)
-vec2 ModTexCoords(vec2 st, vec3 position, vec4 texMatrix, vec4 offTurb)
-{
- float amplitude = offTurb.z;
- float phase = offTurb.w;
- vec2 st2 = vec2(dot(st, texMatrix.xz), dot(st, texMatrix.yw)) + offTurb.xy;
-
- vec3 offsetPos = position / 1024.0;
- offsetPos.x += offsetPos.z;
-
- vec2 texOffset = sin((offsetPos.xy + vec2(phase)) * 2.0 * M_PI);
-
- return st2 + texOffset * amplitude;
-}
-#endif
-
-
-void main()
-{
-#if defined(USE_VERTEX_ANIMATION)
- vec4 position = mix(attr_Position, attr_Position2, u_VertexLerp);
- vec3 normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp));
- #if defined(USE_VERT_TANGENT_SPACE)
- vec3 tangent = normalize(mix(attr_Tangent, attr_Tangent2, u_VertexLerp));
- vec3 bitangent = normalize(mix(attr_Bitangent, attr_Bitangent2, u_VertexLerp));
- #endif
-#else
- vec4 position = attr_Position;
- vec3 normal = attr_Normal;
- #if defined(USE_VERT_TANGENT_SPACE)
- vec3 tangent = attr_Tangent;
- vec3 bitangent = attr_Bitangent;
- #endif
-#endif
-
- gl_Position = u_ModelViewProjectionMatrix * position;
-
-#if (defined(USE_LIGHTMAP) || defined(USE_LIGHT_VERTEX)) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT)
- vec3 worldLight = attr_LightDirection;
-#endif
-
-#if defined(USE_MODELMATRIX)
- position = u_ModelMatrix * position;
- normal = (u_ModelMatrix * vec4(normal, 0.0)).xyz;
- #if defined(USE_VERT_TANGENT_SPACE)
- tangent = (u_ModelMatrix * vec4(tangent, 0.0)).xyz;
- bitangent = (u_ModelMatrix * vec4(bitangent, 0.0)).xyz;
- #endif
-
- #if defined(USE_LIGHTMAP) && !defined(USE_DELUXEMAP) && !defined(USE_FAST_LIGHT)
- worldLight = (u_ModelMatrix * vec4(worldLight, 0.0)).xyz;
- #endif
-#endif
-
-#if defined(USE_NORMALMAP) && !defined(USE_VERT_TANGENT_SPACE)
- var_Position = position.xyz;
-#endif
-
-#if defined(USE_TCGEN) || defined(USE_NORMALMAP) || defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)
- vec3 SampleToView = u_ViewOrigin - position.xyz;
-#endif
-
-#if defined(USE_TCGEN) || defined(USE_NORMALMAP) || (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT))
- var_SampleToView = SampleToView;
-#endif
-
- vec2 tex;
-
-#if defined(USE_TCGEN)
- if (u_TCGen0 == TCGEN_ENVIRONMENT_MAPPED)
- {
- tex = -reflect(normalize(SampleToView), normal).yz * vec2(0.5, -0.5) + 0.5;
- }
- else
-#endif
- {
- tex = attr_TexCoord0.st;
- }
-
-#if defined(USE_TCMOD)
- var_DiffuseTex = ModTexCoords(tex, position.xyz, u_DiffuseTexMatrix, u_DiffuseTexOffTurb);
-#else
- var_DiffuseTex = tex;
-#endif
-
-#if defined(USE_LIGHTMAP)
- var_LightTex = attr_TexCoord1.st;
-#endif
-
-#if !defined(USE_FAST_LIGHT)
- var_Normal = normal;
- #if defined(USE_VERT_TANGENT_SPACE)
- var_Tangent = tangent;
- var_Bitangent = bitangent;
- #endif
-#endif
-
-#if defined(USE_LIGHT) && !defined(USE_DELUXEMAP)
- #if defined(USE_LIGHT_VECTOR)
- vec3 worldLight = u_LightOrigin.xyz - (position.xyz * u_LightOrigin.w);
- #endif
- #if !defined(USE_FAST_LIGHT)
- var_WorldLight = worldLight;
- #endif
-#endif
-
-#if defined(USE_LIGHT_VERTEX) && !defined(USE_FAST_LIGHT)
- var_VertLight = u_VertColor.rgb * attr_Color.rgb;
- var_Color.rgb = vec3(1.0);
- var_Color.a = u_VertColor.a * attr_Color.a + u_BaseColor.a;
-#else
- var_Color = u_VertColor * attr_Color + u_BaseColor;
-#endif
-
-#if defined(USE_LIGHT_VECTOR) && defined(USE_FAST_LIGHT)
- #if defined(USE_INVSQRLIGHT)
- float intensity = 1.0 / dot(worldLight, worldLight);
- #else
- float intensity = clamp((1.0 - dot(worldLight, worldLight) / (u_LightRadius * u_LightRadius)) * 1.07, 0.0, 1.0);
- #endif
- float NL = clamp(dot(normal, normalize(worldLight)), 0.0, 1.0);
-
- var_Color.rgb *= u_DirectedLight * intensity * NL + u_AmbientLight;
-#endif
-}
diff --git a/src/rend2/glsl/pshadow_fp.glsl b/src/rend2/glsl/pshadow_fp.glsl
deleted file mode 100644
index b152971a..00000000
--- a/src/rend2/glsl/pshadow_fp.glsl
+++ /dev/null
@@ -1,98 +0,0 @@
-uniform sampler2D u_ShadowMap;
-
-uniform vec3 u_LightForward;
-uniform vec3 u_LightUp;
-uniform vec3 u_LightRight;
-uniform vec4 u_LightOrigin;
-uniform float u_LightRadius;
-varying vec3 var_Position;
-varying vec3 var_Normal;
-
-float sampleDistMap(sampler2D texMap, vec2 uv, float scale)
-{
- vec3 distv = texture2D(texMap, uv).xyz;
- return dot(distv, vec3(1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0)) * scale;
-}
-
-void main()
-{
- vec3 lightToPos = var_Position - u_LightOrigin.xyz;
- vec2 st = vec2(-dot(u_LightRight, lightToPos), dot(u_LightUp, lightToPos));
-
- float fade = length(st);
-
-#if defined(USE_DISCARD)
- if (fade >= 1.0)
- {
- discard;
- }
-#endif
-
- fade = clamp(8.0 - fade * 8.0, 0.0, 1.0);
-
- st = st * 0.5 + vec2(0.5);
-
-#if defined(USE_SOLID_PSHADOWS)
- float intensity = max(sign(u_LightRadius - length(lightToPos)), 0.0);
-#else
- float intensity = clamp((1.0 - dot(lightToPos, lightToPos) / (u_LightRadius * u_LightRadius)) * 2.0, 0.0, 1.0);
-#endif
-
- float lightDist = length(lightToPos);
- float dist;
-
-#if defined(USE_DISCARD)
- if (dot(u_LightForward, lightToPos) <= 0.0)
- {
- discard;
- }
-
- if (dot(var_Normal, lightToPos) > 0.0)
- {
- discard;
- }
-#else
- intensity *= max(sign(dot(u_LightForward, lightToPos)), 0.0);
- intensity *= max(sign(-dot(var_Normal, lightToPos)), 0.0);
-#endif
-
- intensity *= fade;
-#if defined(USE_PCF)
- float part;
-
- dist = sampleDistMap(u_ShadowMap, st + vec2(-1.0/512.0, -1.0/512.0), u_LightRadius);
- part = max(sign(lightDist - dist), 0.0);
-
- dist = sampleDistMap(u_ShadowMap, st + vec2( 1.0/512.0, -1.0/512.0), u_LightRadius);
- part += max(sign(lightDist - dist), 0.0);
-
- dist = sampleDistMap(u_ShadowMap, st + vec2(-1.0/512.0, 1.0/512.0), u_LightRadius);
- part += max(sign(lightDist - dist), 0.0);
-
- dist = sampleDistMap(u_ShadowMap, st + vec2( 1.0/512.0, 1.0/512.0), u_LightRadius);
- part += max(sign(lightDist - dist), 0.0);
-
- #if defined(USE_DISCARD)
- if (part <= 0.0)
- {
- discard;
- }
- #endif
-
- intensity *= part * 0.25;
-#else
- dist = sampleDistMap(u_ShadowMap, st, u_LightRadius);
-
- #if defined(USE_DISCARD)
- if (lightDist - dist <= 0.0)
- {
- discard;
- }
- #endif
-
- intensity *= max(sign(lightDist - dist), 0.0);
-#endif
-
- gl_FragColor.rgb = vec3(0);
- gl_FragColor.a = clamp(intensity, 0.0, 0.75);
-}
diff --git a/src/rend2/glsl/pshadow_vp.glsl b/src/rend2/glsl/pshadow_vp.glsl
deleted file mode 100644
index 0e0e3b3d..00000000
--- a/src/rend2/glsl/pshadow_vp.glsl
+++ /dev/null
@@ -1,17 +0,0 @@
-attribute vec4 attr_Position;
-attribute vec3 attr_Normal;
-
-uniform mat4 u_ModelViewProjectionMatrix;
-varying vec3 var_Position;
-varying vec3 var_Normal;
-
-
-void main()
-{
- vec4 position = attr_Position;
-
- gl_Position = u_ModelViewProjectionMatrix * position;
-
- var_Position = position.xyz;
- var_Normal = attr_Normal;
-}
diff --git a/src/rend2/glsl/shadowfill_fp.glsl b/src/rend2/glsl/shadowfill_fp.glsl
deleted file mode 100644
index 150f3d12..00000000
--- a/src/rend2/glsl/shadowfill_fp.glsl
+++ /dev/null
@@ -1,41 +0,0 @@
-uniform vec4 u_LightOrigin;
-uniform float u_LightRadius;
-
-varying vec3 var_Position;
-
-void main()
-{
-#if defined(USE_DEPTH)
- float depth = length(u_LightOrigin.xyz - var_Position) / u_LightRadius;
- #if 0
- // 32 bit precision
- const vec4 bitSh = vec4( 256 * 256 * 256, 256 * 256, 256, 1);
- const vec4 bitMsk = vec4( 0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
-
- vec4 comp;
- comp = depth * bitSh;
- comp.xyz = fract(comp.xyz);
- comp -= comp.xxyz * bitMsk;
- gl_FragColor = comp;
- #endif
-
- #if 1
- // 24 bit precision
- const vec3 bitSh = vec3( 256 * 256, 256, 1);
- const vec3 bitMsk = vec3( 0, 1.0 / 256.0, 1.0 / 256.0);
-
- vec3 comp;
- comp = depth * bitSh;
- comp.xy = fract(comp.xy);
- comp -= comp.xxy * bitMsk;
- gl_FragColor = vec4(comp, 1.0);
- #endif
-
- #if 0
- // 8 bit precision
- gl_FragColor = vec4(depth, depth, depth, 1);
- #endif
-#else
- gl_FragColor = vec4(0, 0, 0, 1);
-#endif
-}
diff --git a/src/rend2/glsl/shadowfill_vp.glsl b/src/rend2/glsl/shadowfill_vp.glsl
deleted file mode 100644
index 10802eca..00000000
--- a/src/rend2/glsl/shadowfill_vp.glsl
+++ /dev/null
@@ -1,89 +0,0 @@
-attribute vec4 attr_Position;
-attribute vec3 attr_Normal;
-attribute vec4 attr_TexCoord0;
-
-//#if defined(USE_VERTEX_ANIMATION)
-attribute vec4 attr_Position2;
-attribute vec3 attr_Normal2;
-//#endif
-
-//#if defined(USE_DEFORM_VERTEXES)
-uniform int u_DeformGen;
-uniform float u_DeformParams[5];
-//#endif
-
-uniform float u_Time;
-uniform mat4 u_ModelViewProjectionMatrix;
-
-uniform mat4 u_ModelMatrix;
-
-//#if defined(USE_VERTEX_ANIMATION)
-uniform float u_VertexLerp;
-//#endif
-
-varying vec3 var_Position;
-
-vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st)
-{
- if (u_DeformGen == 0)
- {
- return pos;
- }
-
- float base = u_DeformParams[0];
- float amplitude = u_DeformParams[1];
- float phase = u_DeformParams[2];
- float frequency = u_DeformParams[3];
- float spread = u_DeformParams[4];
-
- if (u_DeformGen == DGEN_BULGE)
- {
- phase *= M_PI * 0.25 * st.x;
- }
- else // if (u_DeformGen <= DGEN_WAVE_INVERSE_SAWTOOTH)
- {
- phase += dot(pos.xyz, vec3(spread));
- }
-
- float value = phase + (u_Time * frequency);
- float func;
-
- if (u_DeformGen == DGEN_WAVE_SIN)
- {
- func = sin(value * 2.0 * M_PI);
- }
- else if (u_DeformGen == DGEN_WAVE_SQUARE)
- {
- func = sign(sin(value * 2.0 * M_PI));
- }
- else if (u_DeformGen == DGEN_WAVE_TRIANGLE)
- {
- func = abs(fract(value + 0.75) - 0.5) * 4.0 - 1.0;
- }
- else if (u_DeformGen == DGEN_WAVE_SAWTOOTH)
- {
- func = fract(value);
- }
- else if (u_DeformGen == DGEN_WAVE_INVERSE_SAWTOOTH)
- {
- func = (1.0 - fract(value));
- }
- else if (u_DeformGen == DGEN_BULGE)
- {
- func = sin(value);
- }
-
- return pos + normal * (base + func * amplitude);
-}
-
-void main()
-{
- vec4 position = mix(attr_Position, attr_Position2, u_VertexLerp);
- vec3 normal = normalize(mix(attr_Normal, attr_Normal2, u_VertexLerp));
-
- position.xyz = DeformPosition(position.xyz, normal, attr_TexCoord0.st);
-
- gl_Position = u_ModelViewProjectionMatrix * position;
-
- var_Position = (u_ModelMatrix * position).xyz;
-}
diff --git a/src/rend2/glsl/shadowmask_fp.glsl b/src/rend2/glsl/shadowmask_fp.glsl
deleted file mode 100644
index b3a698c8..00000000
--- a/src/rend2/glsl/shadowmask_fp.glsl
+++ /dev/null
@@ -1,127 +0,0 @@
-uniform sampler2D u_ScreenDepthMap;
-
-uniform sampler2D u_ShadowMap;
-#if defined(USE_SHADOW_CASCADE)
-uniform sampler2D u_ShadowMap2;
-uniform sampler2D u_ShadowMap3;
-#endif
-
-uniform mat4 u_ShadowMvp;
-#if defined(USE_SHADOW_CASCADE)
-uniform mat4 u_ShadowMvp2;
-uniform mat4 u_ShadowMvp3;
-#endif
-
-uniform vec3 u_ViewOrigin;
-uniform vec4 u_ViewInfo; // zfar / znear, zfar
-
-varying vec2 var_DepthTex;
-varying vec3 var_ViewDir;
-
-// Input: It uses texture coords as the random number seed.
-// Output: Random number: [0,1), that is between 0.0 and 0.999999... inclusive.
-// Author: Michael Pohoreski
-// Copyright: Copyleft 2012 :-)
-// Source: http://stackoverflow.com/questions/5149544/can-i-generate-a-random-number-inside-a-pixel-shader
-
-float random( const vec2 p )
-{
- // We need irrationals for pseudo randomness.
- // Most (all?) known transcendental numbers will (generally) work.
- const vec2 r = vec2(
- 23.1406926327792690, // e^pi (Gelfond's constant)
- 2.6651441426902251); // 2^sqrt(2) (Gelfond-Schneider constant)
- //return fract( cos( mod( 123456789., 1e-7 + 256. * dot(p,r) ) ) );
- return mod( 123456789., 1e-7 + 256. * dot(p,r) );
-}
-
-float PCF(const sampler2D shadowmap, const vec2 st, const float dist)
-{
- float mult;
- float scale = 2.0 / r_shadowMapSize;
-
-#if defined(USE_SHADOW_FILTER)
- float r = random(var_DepthTex.xy);
- float sinr = sin(r) * scale;
- float cosr = cos(r) * scale;
- mat2 rmat = mat2(cosr, sinr, -sinr, cosr);
-
- mult = step(dist, texture2D(shadowmap, st + rmat * vec2(-0.7055767, 0.196515)).r);
- mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.3524343, -0.7791386)).r);
- mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.2391056, 0.9189604)).r);
- #if defined(USE_SHADOW_FILTER2)
- mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.07580382, -0.09224417)).r);
- mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.5784913, -0.002528916)).r);
- mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.192888, 0.4064181)).r);
- mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.6335801, -0.5247476)).r);
- mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.5579782, 0.7491854)).r);
- mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.7320465, 0.6317794)).r);
-
- mult *= 0.11111;
- #else
- mult *= 0.33333;
- #endif
-#else
- mult = step(dist, texture2D(shadowmap, st).r);
-#endif
-
- return mult;
-}
-
-float getLinearDepth(sampler2D depthMap, vec2 tex, float zFarDivZNear)
-{
- float sampleZDivW = texture2D(depthMap, tex).r;
- return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);
-}
-
-void main()
-{
- float result;
-
- float depth = getLinearDepth(u_ScreenDepthMap, var_DepthTex, u_ViewInfo.x);
- float sampleZ = u_ViewInfo.y * depth;
-
- vec4 biasPos = vec4(u_ViewOrigin + var_ViewDir * depth * 0.99, 1.0);
-
- vec4 shadowpos = u_ShadowMvp * biasPos;
-
-#if defined(USE_SHADOW_CASCADE)
- const float fadeTo = 0.5;
- result = fadeTo;
-#else
- result = 0.0;
-#endif
-
- if (all(lessThanEqual(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))
- {
- shadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5;
- result = PCF(u_ShadowMap, shadowpos.xy, shadowpos.z);
- }
-#if defined(USE_SHADOW_CASCADE)
- else
- {
- shadowpos = u_ShadowMvp2 * biasPos;
-
- if (all(lessThanEqual(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))
- {
- shadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5;
- result = PCF(u_ShadowMap2, shadowpos.xy, shadowpos.z);
- }
- else
- {
- shadowpos = u_ShadowMvp3 * biasPos;
-
- if (all(lessThanEqual(abs(shadowpos.xyz), vec3(abs(shadowpos.w)))))
- {
- shadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5;
- result = PCF(u_ShadowMap3, shadowpos.xy, shadowpos.z);
-
- float fade = clamp(sampleZ / r_shadowCascadeZFar * 10.0 - 9.0, 0.0, 1.0);
- result = mix(result, fadeTo, fade);
- }
- }
- }
-#endif
-
- gl_FragColor = vec4(vec3(result), 1.0);
-}
diff --git a/src/rend2/glsl/shadowmask_vp.glsl b/src/rend2/glsl/shadowmask_vp.glsl
deleted file mode 100644
index 13166a24..00000000
--- a/src/rend2/glsl/shadowmask_vp.glsl
+++ /dev/null
@@ -1,18 +0,0 @@
-attribute vec4 attr_Position;
-attribute vec4 attr_TexCoord0;
-
-uniform vec3 u_ViewForward;
-uniform vec3 u_ViewLeft;
-uniform vec3 u_ViewUp;
-uniform vec4 u_ViewInfo; // zfar / znear
-
-varying vec2 var_DepthTex;
-varying vec3 var_ViewDir;
-
-void main()
-{
- gl_Position = attr_Position;
- vec2 screenCoords = gl_Position.xy / gl_Position.w;
- var_DepthTex = attr_TexCoord0.xy;
- var_ViewDir = u_ViewForward + u_ViewLeft * -screenCoords.x + u_ViewUp * screenCoords.y;
-}
diff --git a/src/rend2/glsl/ssao_fp.glsl b/src/rend2/glsl/ssao_fp.glsl
deleted file mode 100644
index 6263284c..00000000
--- a/src/rend2/glsl/ssao_fp.glsl
+++ /dev/null
@@ -1,86 +0,0 @@
-uniform sampler2D u_ScreenDepthMap;
-
-uniform vec4 u_ViewInfo; // zfar / znear, zfar
-
-varying vec2 var_ScreenTex;
-
-vec2 poissonDisc[9] = vec2[9](
-vec2(-0.7055767, 0.196515), vec2(0.3524343, -0.7791386),
-vec2(0.2391056, 0.9189604), vec2(-0.07580382, -0.09224417),
-vec2(0.5784913, -0.002528916), vec2(0.192888, 0.4064181),
-vec2(-0.6335801, -0.5247476), vec2(-0.5579782, 0.7491854),
-vec2(0.7320465, 0.6317794)
-);
-
-// Input: It uses texture coords as the random number seed.
-// Output: Random number: [0,1), that is between 0.0 and 0.999999... inclusive.
-// Author: Michael Pohoreski
-// Copyright: Copyleft 2012 :-)
-// Source: http://stackoverflow.com/questions/5149544/can-i-generate-a-random-number-inside-a-pixel-shader
-
-float random( const vec2 p )
-{
- // We need irrationals for pseudo randomness.
- // Most (all?) known transcendental numbers will (generally) work.
- const vec2 r = vec2(
- 23.1406926327792690, // e^pi (Gelfond's constant)
- 2.6651441426902251); // 2^sqrt(2) (Gelfond-Schneider constant)
- //return fract( cos( mod( 123456789., 1e-7 + 256. * dot(p,r) ) ) );
- return mod( 123456789., 1e-7 + 256. * dot(p,r) );
-}
-
-mat2 randomRotation( const vec2 p )
-{
- float r = random(p);
- float sinr = sin(r);
- float cosr = cos(r);
- return mat2(cosr, sinr, -sinr, cosr);
-}
-
-float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNear)
-{
- float sampleZDivW = texture2D(depthMap, tex).r;
- return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW);
-}
-
-float ambientOcclusion(sampler2D depthMap, const vec2 tex, const float zFarDivZNear, const float zFar)
-{
- float result = 0;
-
- float sampleZ = zFar * getLinearDepth(depthMap, tex, zFarDivZNear);
-
- vec2 expectedSlope = vec2(dFdx(sampleZ), dFdy(sampleZ)) / vec2(dFdx(tex.x), dFdy(tex.y));
-
- if (length(expectedSlope) > 5000.0)
- return 1.0;
-
- vec2 offsetScale = vec2(3.0 / sampleZ);
-
- mat2 rmat = randomRotation(tex);
-
- int i;
- for (i = 0; i < 3; i++)
- {
- vec2 offset = rmat * poissonDisc[i] * offsetScale;
- float sampleZ2 = zFar * getLinearDepth(depthMap, tex + offset, zFarDivZNear);
-
- if (abs(sampleZ - sampleZ2) > 20.0)
- result += 1.0;
- else
- {
- float expectedZ = sampleZ + dot(expectedSlope, offset);
- result += step(expectedZ - 1.0, sampleZ2);
- }
- }
-
- result *= 0.33333;
-
- return result;
-}
-
-void main()
-{
- float result = ambientOcclusion(u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y);
-
- gl_FragColor = vec4(vec3(result), 1.0);
-}
diff --git a/src/rend2/glsl/ssao_vp.glsl b/src/rend2/glsl/ssao_vp.glsl
deleted file mode 100644
index 9c46a79f..00000000
--- a/src/rend2/glsl/ssao_vp.glsl
+++ /dev/null
@@ -1,12 +0,0 @@
-attribute vec4 attr_Position;
-attribute vec4 attr_TexCoord0;
-
-varying vec2 var_ScreenTex;
-
-void main()
-{
- gl_Position = attr_Position;
- var_ScreenTex = attr_TexCoord0.xy;
- //vec2 screenCoords = gl_Position.xy / gl_Position.w;
- //var_ScreenTex = screenCoords * 0.5 + 0.5;
-}
diff --git a/src/rend2/glsl/texturecolor_fp.glsl b/src/rend2/glsl/texturecolor_fp.glsl
deleted file mode 100644
index 5646b511..00000000
--- a/src/rend2/glsl/texturecolor_fp.glsl
+++ /dev/null
@@ -1,12 +0,0 @@
-#version 120
-
-uniform sampler2D u_DiffuseMap;
-uniform vec4 u_Color;
-
-varying vec2 var_Tex1;
-
-
-void main()
-{
- gl_FragColor = texture2D(u_DiffuseMap, var_Tex1) * u_Color;
-}
diff --git a/src/rend2/glsl/texturecolor_vp.glsl b/src/rend2/glsl/texturecolor_vp.glsl
deleted file mode 100644
index ae26a18e..00000000
--- a/src/rend2/glsl/texturecolor_vp.glsl
+++ /dev/null
@@ -1,15 +0,0 @@
-#version 120
-
-attribute vec4 attr_Position;
-attribute vec4 attr_TexCoord0;
-
-uniform mat4 u_ModelViewProjectionMatrix;
-
-varying vec2 var_Tex1;
-
-
-void main()
-{
- gl_Position = u_ModelViewProjectionMatrix * attr_Position;
- var_Tex1 = attr_TexCoord0.st;
-}
diff --git a/src/rend2/glsl/tonemap_fp.glsl b/src/rend2/glsl/tonemap_fp.glsl
deleted file mode 100644
index 9b18de8a..00000000
--- a/src/rend2/glsl/tonemap_fp.glsl
+++ /dev/null
@@ -1,48 +0,0 @@
-uniform sampler2D u_TextureMap;
-uniform sampler2D u_LevelsMap;
-
-uniform vec4 u_Color;
-
-uniform vec2 u_AutoExposureMinMax;
-uniform vec3 u_ToneMinAvgMaxLinear;
-
-varying vec2 var_TexCoords;
-
-const vec3 LUMINANCE_VECTOR = vec3(0.2125, 0.7154, 0.0721); //vec3(0.299, 0.587, 0.114);
-
-vec3 FilmicTonemap(vec3 x)
-{
- const float SS = 0.22; // Shoulder Strength
- const float LS = 0.30; // Linear Strength
- const float LA = 0.10; // Linear Angle
- const float TS = 0.20; // Toe Strength
- const float TAN = 0.01; // Toe Angle Numerator
- const float TAD = 0.30; // Toe Angle Denominator
-
- vec3 SSxx = SS * x * x;
- vec3 LSx = LS * x;
- vec3 LALSx = LSx * LA;
-
- return ((SSxx + LALSx + TS * TAN) / (SSxx + LSx + TS * TAD)) - TAN / TAD;
-
- //return ((x*(SS*x+LA*LS)+TS*TAN)/(x*(SS*x+LS)+TS*TAD)) - TAN/TAD;
-
-}
-
-void main()
-{
- vec4 color = texture2D(u_TextureMap, var_TexCoords) * u_Color;
- vec3 minAvgMax = texture2D(u_LevelsMap, var_TexCoords).rgb;
- vec3 logMinAvgMaxLum = clamp(minAvgMax * 20.0 - 10.0, -u_AutoExposureMinMax.y, -u_AutoExposureMinMax.x);
-
- float avgLum = exp2(logMinAvgMaxLum.y);
- //float maxLum = exp2(logMinAvgMaxLum.z);
-
- color.rgb *= u_ToneMinAvgMaxLinear.y / avgLum;
- color.rgb = max(vec3(0.0), color.rgb - vec3(u_ToneMinAvgMaxLinear.x));
-
- vec3 fWhite = 1.0 / FilmicTonemap(vec3(u_ToneMinAvgMaxLinear.z - u_ToneMinAvgMaxLinear.x));
- color.rgb = FilmicTonemap(color.rgb) * fWhite;
-
- gl_FragColor = clamp(color, 0.0, 1.0);
-}
diff --git a/src/rend2/glsl/tonemap_vp.glsl b/src/rend2/glsl/tonemap_vp.glsl
deleted file mode 100644
index 5ca41600..00000000
--- a/src/rend2/glsl/tonemap_vp.glsl
+++ /dev/null
@@ -1,13 +0,0 @@
-attribute vec4 attr_Position;
-attribute vec4 attr_TexCoord0;
-
-uniform mat4 u_ModelViewProjectionMatrix;
-
-varying vec2 var_TexCoords;
-
-
-void main()
-{
- gl_Position = u_ModelViewProjectionMatrix * attr_Position;
- var_TexCoords = attr_TexCoord0.st;
-}
diff --git a/src/rend2/qgl.h b/src/rend2/qgl.h
deleted file mode 100644
index 6013a87c..00000000
--- a/src/rend2/qgl.h
+++ /dev/null
@@ -1,755 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-/*
-** QGL.H
-*/
-
-#ifndef __QGL_H__
-#define __QGL_H__
-
-#ifdef USE_LOCAL_HEADERS
-# include "SDL_opengl.h"
-#else
-# include <SDL_opengl.h>
-#endif
-
-extern void (APIENTRYP qglActiveTextureARB) (GLenum texture);
-extern void (APIENTRYP qglClientActiveTextureARB) (GLenum texture);
-extern void (APIENTRYP qglMultiTexCoord2fARB) (GLenum target, GLfloat s, GLfloat t);
-
-extern void (APIENTRYP qglLockArraysEXT) (GLint first, GLsizei count);
-extern void (APIENTRYP qglUnlockArraysEXT) (void);
-
-// GL_EXT_draw_range_elements
-extern void (APIENTRY * qglDrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
-
-// GL_EXT_multi_draw_arrays
-extern void (APIENTRY * qglMultiDrawArraysEXT) (GLenum, GLint *, GLsizei *, GLsizei);
-extern void (APIENTRY * qglMultiDrawElementsEXT) (GLenum, const GLsizei *, GLenum, const GLvoid **, GLsizei);
-
-// GL_ARB_shading_language_100
-#ifndef GL_ARB_shading_language_100
-#define GL_ARB_shading_language_100
-#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
-#endif
-
-// GL_ARB_vertex_program
-extern void (APIENTRY * qglVertexAttrib4fARB) (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
-extern void (APIENTRY * qglVertexAttrib4fvARB) (GLuint, const GLfloat *);
-extern void (APIENTRY * qglVertexAttribPointerARB) (GLuint index, GLint size, GLenum type, GLboolean normalized,
- GLsizei stride, const GLvoid * pointer);
-extern void (APIENTRY * qglEnableVertexAttribArrayARB) (GLuint index);
-extern void (APIENTRY * qglDisableVertexAttribArrayARB) (GLuint index);
-
-// GL_ARB_vertex_buffer_object
-extern void (APIENTRY * qglBindBufferARB) (GLenum target, GLuint buffer);
-extern void (APIENTRY * qglDeleteBuffersARB) (GLsizei n, const GLuint * buffers);
-extern void (APIENTRY * qglGenBuffersARB) (GLsizei n, GLuint * buffers);
-extern GLboolean(APIENTRY * qglIsBufferARB) (GLuint buffer);
-extern void (APIENTRY * qglBufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage);
-extern void (APIENTRY * qglBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data);
-extern void (APIENTRY * qglGetBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data);
-extern void (APIENTRY * qglGetBufferParameterivARB) (GLenum target, GLenum pname, GLint * params);
-extern void (APIENTRY * qglGetBufferPointervARB) (GLenum target, GLenum pname, GLvoid * *params);
-
-// GL_ARB_shader_objects
-extern void (APIENTRY * qglDeleteObjectARB) (GLhandleARB obj);
-extern GLhandleARB(APIENTRY * qglGetHandleARB) (GLenum pname);
-extern void (APIENTRY * qglDetachObjectARB) (GLhandleARB containerObj, GLhandleARB attachedObj);
-extern GLhandleARB(APIENTRY * qglCreateShaderObjectARB) (GLenum shaderType);
-extern void (APIENTRY * qglShaderSourceARB) (GLhandleARB shaderObj, GLsizei count, const GLcharARB * *string,
- const GLint * length);
-extern void (APIENTRY * qglCompileShaderARB) (GLhandleARB shaderObj);
-extern GLhandleARB(APIENTRY * qglCreateProgramObjectARB) (void);
-extern void (APIENTRY * qglAttachObjectARB) (GLhandleARB containerObj, GLhandleARB obj);
-extern void (APIENTRY * qglLinkProgramARB) (GLhandleARB programObj);
-extern void (APIENTRY * qglUseProgramObjectARB) (GLhandleARB programObj);
-extern void (APIENTRY * qglValidateProgramARB) (GLhandleARB programObj);
-extern void (APIENTRY * qglUniform1fARB) (GLint location, GLfloat v0);
-extern void (APIENTRY * qglUniform2fARB) (GLint location, GLfloat v0, GLfloat v1);
-extern void (APIENTRY * qglUniform3fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
-extern void (APIENTRY * qglUniform4fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
-extern void (APIENTRY * qglUniform1iARB) (GLint location, GLint v0);
-extern void (APIENTRY * qglUniform2iARB) (GLint location, GLint v0, GLint v1);
-extern void (APIENTRY * qglUniform3iARB) (GLint location, GLint v0, GLint v1, GLint v2);
-extern void (APIENTRY * qglUniform4iARB) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
-extern void (APIENTRY * qglUniform1fvARB) (GLint location, GLsizei count, const GLfloat * value);
-extern void (APIENTRY * qglUniform2fvARB) (GLint location, GLsizei count, const GLfloat * value);
-extern void (APIENTRY * qglUniform3fvARB) (GLint location, GLsizei count, const GLfloat * value);
-extern void (APIENTRY * qglUniform4fvARB) (GLint location, GLsizei count, const GLfloat * value);
-extern void (APIENTRY * qglUniform2ivARB) (GLint location, GLsizei count, const GLint * value);
-extern void (APIENTRY * qglUniform3ivARB) (GLint location, GLsizei count, const GLint * value);
-extern void (APIENTRY * qglUniform4ivARB) (GLint location, GLsizei count, const GLint * value);
-extern void (APIENTRY * qglUniformMatrix2fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-extern void (APIENTRY * qglUniformMatrix3fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-extern void (APIENTRY * qglUniformMatrix4fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-extern void (APIENTRY * qglGetObjectParameterfvARB) (GLhandleARB obj, GLenum pname, GLfloat * params);
-extern void (APIENTRY * qglGetObjectParameterivARB) (GLhandleARB obj, GLenum pname, GLint * params);
-extern void (APIENTRY * qglGetInfoLogARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog);
-extern void (APIENTRY * qglGetAttachedObjectsARB) (GLhandleARB containerObj, GLsizei maxCount, GLsizei * count,
- GLhandleARB * obj);
-extern GLint(APIENTRY * qglGetUniformLocationARB) (GLhandleARB programObj, const GLcharARB * name);
-extern void (APIENTRY * qglGetActiveUniformARB) (GLhandleARB programObj, GLuint index, GLsizei maxIndex, GLsizei * length,
- GLint * size, GLenum * type, GLcharARB * name);
-extern void (APIENTRY * qglGetUniformfvARB) (GLhandleARB programObj, GLint location, GLfloat * params);
-extern void (APIENTRY * qglGetUniformivARB) (GLhandleARB programObj, GLint location, GLint * params);
-extern void (APIENTRY * qglGetShaderSourceARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * source);
-
-// GL_ARB_vertex_shader
-extern void (APIENTRY * qglBindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB * name);
-extern void (APIENTRY * qglGetActiveAttribARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length,
- GLint * size, GLenum * type, GLcharARB * name);
-extern GLint(APIENTRY * qglGetAttribLocationARB) (GLhandleARB programObj, const GLcharARB * name);
-
-// GL_ARB_texture_compression
-extern void (APIENTRY * qglCompressedTexImage3DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
- GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
-extern void (APIENTRY * qglCompressedTexImage2DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
- GLint border, GLsizei imageSize, const GLvoid *data);
-extern void (APIENTRY * qglCompressedTexImage1DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border,
- GLsizei imageSize, const GLvoid *data);
-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);
-extern void (APIENTRY * qglCompressedTexSubImage2DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
- GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
-extern void (APIENTRY * qglCompressedTexSubImage1DARB)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format,
- GLsizei imageSize, const GLvoid *data);
-extern void (APIENTRY * qglGetCompressedTexImageARB)(GLenum target, GLint lod,
- GLvoid *img);
-
-// GL_NVX_gpu_memory_info
-#ifndef GL_NVX_gpu_memory_info
-#define GL_NVX_gpu_memory_info
-#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047
-#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048
-#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
-#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A
-#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B
-#endif
-
-// GL_ATI_meminfo
-#ifndef GL_ATI_meminfo
-#define GL_ATI_meminfo
-#define GL_VBO_FREE_MEMORY_ATI 0x87FB
-#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
-#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
-#endif
-
-// GL_ARB_texture_float
-#ifndef GL_ARB_texture_float
-#define GL_ARB_texture_float
-#define GL_TEXTURE_RED_TYPE_ARB 0x8C10
-#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11
-#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12
-#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13
-#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14
-#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15
-#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16
-#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17
-#define GL_RGBA32F_ARB 0x8814
-#define GL_RGB32F_ARB 0x8815
-#define GL_ALPHA32F_ARB 0x8816
-#define GL_INTENSITY32F_ARB 0x8817
-#define GL_LUMINANCE32F_ARB 0x8818
-#define GL_LUMINANCE_ALPHA32F_ARB 0x8819
-#define GL_RGBA16F_ARB 0x881A
-#define GL_RGB16F_ARB 0x881B
-#define GL_ALPHA16F_ARB 0x881C
-#define GL_INTENSITY16F_ARB 0x881D
-#define GL_LUMINANCE16F_ARB 0x881E
-#define GL_LUMINANCE_ALPHA16F_ARB 0x881F
-#endif
-
-#ifndef GL_ARB_half_float_pixel
-#define GL_ARB_half_float_pixel
-#define GL_HALF_FLOAT_ARB 0x140B
-#endif
-
-// GL_EXT_framebuffer_object
-extern GLboolean (APIENTRY * qglIsRenderbufferEXT)(GLuint renderbuffer);
-extern void (APIENTRY * qglBindRenderbufferEXT)(GLenum target, GLuint renderbuffer);
-extern void (APIENTRY * qglDeleteRenderbuffersEXT)(GLsizei n, const GLuint *renderbuffers);
-extern void (APIENTRY * qglGenRenderbuffersEXT)(GLsizei n, GLuint *renderbuffers);
-extern void (APIENTRY * qglRenderbufferStorageEXT)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-extern void (APIENTRY * qglGetRenderbufferParameterivEXT)(GLenum target, GLenum pname, GLint *params);
-extern GLboolean (APIENTRY * qglIsFramebufferEXT)(GLuint framebuffer);
-extern void (APIENTRY * qglBindFramebufferEXT)(GLenum target, GLuint framebuffer);
-extern void (APIENTRY * qglDeleteFramebuffersEXT)(GLsizei n, const GLuint *framebuffers);
-extern void (APIENTRY * qglGenFramebuffersEXT)(GLsizei n, GLuint *framebuffers);
-extern GLenum (APIENTRY * qglCheckFramebufferStatusEXT)(GLenum target);
-extern void (APIENTRY * qglFramebufferTexture1DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
- GLint level);
-extern void (APIENTRY * qglFramebufferTexture2DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
- GLint level);
-extern void (APIENTRY * qglFramebufferTexture3DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
- GLint level, GLint zoffset);
-extern void (APIENTRY * qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachment, GLenum renderbuffertarget,
- GLuint renderbuffer);
-extern void (APIENTRY * qglGetFramebufferAttachmentParameterivEXT)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
-extern void (APIENTRY * qglGenerateMipmapEXT)(GLenum target);
-
-#ifndef GL_EXT_framebuffer_object
-#define GL_EXT_framebuffer_object
-#define GL_FRAMEBUFFER_EXT 0x8D40
-#define GL_RENDERBUFFER_EXT 0x8D41
-#define GL_STENCIL_INDEX1_EXT 0x8D46
-#define GL_STENCIL_INDEX4_EXT 0x8D47
-#define GL_STENCIL_INDEX8_EXT 0x8D48
-#define GL_STENCIL_INDEX16_EXT 0x8D49
-#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
-#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
-#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
-#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
-#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
-#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
-#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
-#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
-#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
-#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
-#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
-#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
-#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
-#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
-#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
-#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
-#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
-#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
-#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
-#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
-#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
-#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
-#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
-#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
-#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
-#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
-#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
-#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
-#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
-#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
-#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
-#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
-#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
-#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
-#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
-#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
-#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
-#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
-#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
-#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
-#endif
-
-// GL_EXT_packed_depth_stencil
-#ifndef GL_EXT_packed_depth_stencil
-#define GL_EXT_packed_depth_stencil
-#define GL_DEPTH_STENCIL_EXT 0x84F9
-#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
-#define GL_DEPTH24_STENCIL8_EXT 0x88F0
-#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
-#endif
-
-// GL_ARB_occlusion_query
-extern void (APIENTRY * qglGenQueriesARB)(GLsizei n, GLuint *ids);
-extern void (APIENTRY * qglDeleteQueriesARB)(GLsizei n, const GLuint *ids);
-extern GLboolean (APIENTRY * qglIsQueryARB)(GLuint id);
-extern void (APIENTRY * qglBeginQueryARB)(GLenum target, GLuint id);
-extern void (APIENTRY * qglEndQueryARB)(GLenum target);
-extern void (APIENTRY * qglGetQueryivARB)(GLenum target, GLenum pname, GLint *params);
-extern void (APIENTRY * qglGetQueryObjectivARB)(GLuint id, GLenum pname, GLint *params);
-extern void (APIENTRY * qglGetQueryObjectuivARB)(GLuint id, GLenum pname, GLuint *params);
-
-#ifndef GL_ARB_occlusion_query
-#define GL_ARB_occlusion_query
-#define GL_SAMPLES_PASSED_ARB 0x8914
-#define GL_QUERY_COUNTER_BITS_ARB 0x8864
-#define GL_CURRENT_QUERY_ARB 0x8865
-#define GL_QUERY_RESULT_ARB 0x8866
-#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867
-#endif
-
-// GL_EXT_framebuffer_blit
-extern void (APIENTRY * qglBlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter);
-
-#ifndef GL_EXT_framebuffer_blit
-#define GL_EXT_framebuffer_blit
-#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
-#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
-#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
-#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
-#endif
-
-// GL_EXT_framebuffer_multisample
-extern void (APIENTRY * qglRenderbufferStorageMultisampleEXT)(GLenum target, GLsizei samples,
- GLenum internalformat, GLsizei width, GLsizei height);
-
-#ifndef GL_EXT_framebuffer_multisample
-#define GL_EXT_framebuffer_multisample
-#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
-#define GL_MAX_SAMPLES_EXT 0x8D57
-#endif
-
-#ifndef GL_EXT_texture_sRGB
-#define GL_EXT_texture_sRGB
-#define GL_SRGB_EXT 0x8C40
-#define GL_SRGB8_EXT 0x8C41
-#define GL_SRGB_ALPHA_EXT 0x8C42
-#define GL_SRGB8_ALPHA8_EXT 0x8C43
-#define GL_SLUMINANCE_ALPHA_EXT 0x8C44
-#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45
-#define GL_SLUMINANCE_EXT 0x8C46
-#define GL_SLUMINANCE8_EXT 0x8C47
-#define GL_COMPRESSED_SRGB_EXT 0x8C48
-#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49
-#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A
-#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B
-#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
-#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
-#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
-#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
-#endif
-
-#ifndef GL_EXT_framebuffer_sRGB
-#define GL_EXT_framebuffer_sRGB
-#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
-#endif
-
-#ifndef GL_EXT_texture_compression_latc
-#define GL_EXT_texture_compression_latc
-#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
-#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71
-#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
-#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73
-#endif
-
-#ifndef GL_ARB_texture_compression_bptc
-#define GL_ARB_texture_compression_bptc
-#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
-#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
-#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
-#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
-#endif
-
-// GL_ARB_draw_buffers
-extern void (APIENTRY * qglDrawBuffersARB)(GLsizei n, const GLenum *bufs);
-#ifndef GL_ARB_draw_buffers
-#define GL_ARB_draw_buffers
-#define GL_MAX_DRAW_BUFFERS_ARB 0x8824
-#define GL_DRAW_BUFFER0_ARB 0x8825
-#define GL_DRAW_BUFFER1_ARB 0x8826
-#define GL_DRAW_BUFFER2_ARB 0x8827
-#define GL_DRAW_BUFFER3_ARB 0x8828
-#define GL_DRAW_BUFFER4_ARB 0x8829
-#define GL_DRAW_BUFFER5_ARB 0x882A
-#define GL_DRAW_BUFFER6_ARB 0x882B
-#define GL_DRAW_BUFFER7_ARB 0x882C
-#define GL_DRAW_BUFFER8_ARB 0x882D
-#define GL_DRAW_BUFFER9_ARB 0x882E
-#define GL_DRAW_BUFFER10_ARB 0x882F
-#define GL_DRAW_BUFFER11_ARB 0x8830
-#define GL_DRAW_BUFFER12_ARB 0x8831
-#define GL_DRAW_BUFFER13_ARB 0x8832
-#define GL_DRAW_BUFFER14_ARB 0x8833
-#define GL_DRAW_BUFFER15_ARB 0x8834
-#endif
-
-#ifndef GL_ARB_depth_clamp
-#define GL_ARB_depth_clamp
-#define GL_DEPTH_CLAMP 0x864F
-#endif
-
-#if defined(WIN32)
-// WGL_ARB_create_context
-#ifndef WGL_ARB_create_context
-#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
-#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
-#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
-#define WGL_CONTEXT_FLAGS_ARB 0x2094
-#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
-#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
-#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
-#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
-#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
-#define ERROR_INVALID_VERSION_ARB 0x2095
-#define ERROR_INVALID_PROFILE_ARB 0x2096
-#endif
-
-extern HGLRC(APIENTRY * qwglCreateContextAttribsARB) (HDC hdC, HGLRC hShareContext, const int *attribList);
-#endif
-
-#if 0 //defined(__linux__)
-// GLX_ARB_create_context
-#ifndef GLX_ARB_create_context
-#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
-#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
-#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
-#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
-#define GLX_CONTEXT_FLAGS_ARB 0x2094
-#endif
-
-extern GLXContext (APIENTRY * qglXCreateContextAttribsARB) (Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
-#endif
-
-//===========================================================================
-
-#define qglAccum glAccum
-#define qglAlphaFunc glAlphaFunc
-#define qglAreTexturesResident glAreTexturesResident
-#define qglArrayElement glArrayElement
-#define qglBegin glBegin
-#define qglBindTexture glBindTexture
-#define qglBitmap glBitmap
-#define qglBlendFunc glBlendFunc
-#define qglCallList glCallList
-#define qglCallLists glCallLists
-#define qglClear glClear
-#define qglClearAccum glClearAccum
-#define qglClearColor glClearColor
-#define qglClearDepth glClearDepth
-#define qglClearIndex glClearIndex
-#define qglClearStencil glClearStencil
-#define qglClipPlane glClipPlane
-#define qglColor3b glColor3b
-#define qglColor3bv glColor3bv
-#define qglColor3d glColor3d
-#define qglColor3dv glColor3dv
-#define qglColor3f glColor3f
-#define qglColor3fv glColor3fv
-#define qglColor3i glColor3i
-#define qglColor3iv glColor3iv
-#define qglColor3s glColor3s
-#define qglColor3sv glColor3sv
-#define qglColor3ub glColor3ub
-#define qglColor3ubv glColor3ubv
-#define qglColor3ui glColor3ui
-#define qglColor3uiv glColor3uiv
-#define qglColor3us glColor3us
-#define qglColor3usv glColor3usv
-#define qglColor4b glColor4b
-#define qglColor4bv glColor4bv
-#define qglColor4d glColor4d
-#define qglColor4dv glColor4dv
-#define qglColor4f glColor4f
-#define qglColor4fv glColor4fv
-#define qglColor4i glColor4i
-#define qglColor4iv glColor4iv
-#define qglColor4s glColor4s
-#define qglColor4sv glColor4sv
-#define qglColor4ub glColor4ub
-#define qglColor4ubv glColor4ubv
-#define qglColor4ui glColor4ui
-#define qglColor4uiv glColor4uiv
-#define qglColor4us glColor4us
-#define qglColor4usv glColor4usv
-#define qglColorMask glColorMask
-#define qglColorMaterial glColorMaterial
-#define qglColorPointer glColorPointer
-#define qglCopyPixels glCopyPixels
-#define qglCopyTexImage1D glCopyTexImage1D
-#define qglCopyTexImage2D glCopyTexImage2D
-#define qglCopyTexSubImage1D glCopyTexSubImage1D
-#define qglCopyTexSubImage2D glCopyTexSubImage2D
-#define qglCullFace glCullFace
-#define qglDeleteLists glDeleteLists
-#define qglDeleteTextures glDeleteTextures
-#define qglDepthFunc glDepthFunc
-#define qglDepthMask glDepthMask
-#define qglDepthRange glDepthRange
-#define qglDisable glDisable
-#define qglDisableClientState glDisableClientState
-#define qglDrawArrays glDrawArrays
-#define qglDrawBuffer glDrawBuffer
-#define qglDrawElements glDrawElements
-#define qglDrawPixels glDrawPixels
-#define qglEdgeFlag glEdgeFlag
-#define qglEdgeFlagPointer glEdgeFlagPointer
-#define qglEdgeFlagv glEdgeFlagv
-#define qglEnable glEnable
-#define qglEnableClientState glEnableClientState
-#define qglEnd glEnd
-#define qglEndList glEndList
-#define qglEvalCoord1d glEvalCoord1d
-#define qglEvalCoord1dv glEvalCoord1dv
-#define qglEvalCoord1f glEvalCoord1f
-#define qglEvalCoord1fv glEvalCoord1fv
-#define qglEvalCoord2d glEvalCoord2d
-#define qglEvalCoord2dv glEvalCoord2dv
-#define qglEvalCoord2f glEvalCoord2f
-#define qglEvalCoord2fv glEvalCoord2fv
-#define qglEvalMesh1 glEvalMesh1
-#define qglEvalMesh2 glEvalMesh2
-#define qglEvalPoint1 glEvalPoint1
-#define qglEvalPoint2 glEvalPoint2
-#define qglFeedbackBuffer glFeedbackBuffer
-#define qglFinish glFinish
-#define qglFlush glFlush
-#define qglFogf glFogf
-#define qglFogfv glFogfv
-#define qglFogi glFogi
-#define qglFogiv glFogiv
-#define qglFrontFace glFrontFace
-#define qglFrustum glFrustum
-#define qglGenLists glGenLists
-#define qglGenTextures glGenTextures
-#define qglGetBooleanv glGetBooleanv
-#define qglGetClipPlane glGetClipPlane
-#define qglGetDoublev glGetDoublev
-#define qglGetError glGetError
-#define qglGetFloatv glGetFloatv
-#define qglGetIntegerv glGetIntegerv
-#define qglGetLightfv glGetLightfv
-#define qglGetLightiv glGetLightiv
-#define qglGetMapdv glGetMapdv
-#define qglGetMapfv glGetMapfv
-#define qglGetMapiv glGetMapiv
-#define qglGetMaterialfv glGetMaterialfv
-#define qglGetMaterialiv glGetMaterialiv
-#define qglGetPixelMapfv glGetPixelMapfv
-#define qglGetPixelMapuiv glGetPixelMapuiv
-#define qglGetPixelMapusv glGetPixelMapusv
-#define qglGetPointerv glGetPointerv
-#define qglGetPolygonStipple glGetPolygonStipple
-#define qglGetString glGetString
-#define qglGetTexGendv glGetTexGendv
-#define qglGetTexGenfv glGetTexGenfv
-#define qglGetTexGeniv glGetTexGeniv
-#define qglGetTexImage glGetTexImage
-#define qglGetTexLevelParameterfv glGetTexLevelParameterfv
-#define qglGetTexLevelParameteriv glGetTexLevelParameteriv
-#define qglGetTexParameterfv glGetTexParameterfv
-#define qglGetTexParameteriv glGetTexParameteriv
-#define qglHint glHint
-#define qglIndexMask glIndexMask
-#define qglIndexPointer glIndexPointer
-#define qglIndexd glIndexd
-#define qglIndexdv glIndexdv
-#define qglIndexf glIndexf
-#define qglIndexfv glIndexfv
-#define qglIndexi glIndexi
-#define qglIndexiv glIndexiv
-#define qglIndexs glIndexs
-#define qglIndexsv glIndexsv
-#define qglIndexub glIndexub
-#define qglIndexubv glIndexubv
-#define qglInitNames glInitNames
-#define qglInterleavedArrays glInterleavedArrays
-#define qglIsEnabled glIsEnabled
-#define qglIsList glIsList
-#define qglIsTexture glIsTexture
-#define qglLightModelf glLightModelf
-#define qglLightModelfv glLightModelfv
-#define qglLightModeli glLightModeli
-#define qglLightModeliv glLightModeliv
-#define qglLightf glLightf
-#define qglLightfv glLightfv
-#define qglLighti glLighti
-#define qglLightiv glLightiv
-#define qglLineStipple glLineStipple
-#define qglLineWidth glLineWidth
-#define qglListBase glListBase
-#define qglLoadIdentity glLoadIdentity
-#define qglLoadMatrixd glLoadMatrixd
-#define qglLoadMatrixf glLoadMatrixf
-#define qglLoadName glLoadName
-#define qglLogicOp glLogicOp
-#define qglMap1d glMap1d
-#define qglMap1f glMap1f
-#define qglMap2d glMap2d
-#define qglMap2f glMap2f
-#define qglMapGrid1d glMapGrid1d
-#define qglMapGrid1f glMapGrid1f
-#define qglMapGrid2d glMapGrid2d
-#define qglMapGrid2f glMapGrid2f
-#define qglMaterialf glMaterialf
-#define qglMaterialfv glMaterialfv
-#define qglMateriali glMateriali
-#define qglMaterialiv glMaterialiv
-#define qglMatrixMode glMatrixMode
-#define qglMultMatrixd glMultMatrixd
-#define qglMultMatrixf glMultMatrixf
-#define qglNewList glNewList
-#define qglNormal3b glNormal3b
-#define qglNormal3bv glNormal3bv
-#define qglNormal3d glNormal3d
-#define qglNormal3dv glNormal3dv
-#define qglNormal3f glNormal3f
-#define qglNormal3fv glNormal3fv
-#define qglNormal3i glNormal3i
-#define qglNormal3iv glNormal3iv
-#define qglNormal3s glNormal3s
-#define qglNormal3sv glNormal3sv
-#define qglNormalPointer glNormalPointer
-#define qglOrtho glOrtho
-#define qglPassThrough glPassThrough
-#define qglPixelMapfv glPixelMapfv
-#define qglPixelMapuiv glPixelMapuiv
-#define qglPixelMapusv glPixelMapusv
-#define qglPixelStoref glPixelStoref
-#define qglPixelStorei glPixelStorei
-#define qglPixelTransferf glPixelTransferf
-#define qglPixelTransferi glPixelTransferi
-#define qglPixelZoom glPixelZoom
-#define qglPointSize glPointSize
-#define qglPolygonMode glPolygonMode
-#define qglPolygonOffset glPolygonOffset
-#define qglPolygonStipple glPolygonStipple
-#define qglPopAttrib glPopAttrib
-#define qglPopClientAttrib glPopClientAttrib
-#define qglPopMatrix glPopMatrix
-#define qglPopName glPopName
-#define qglPrioritizeTextures glPrioritizeTextures
-#define qglPushAttrib glPushAttrib
-#define qglPushClientAttrib glPushClientAttrib
-#define qglPushMatrix glPushMatrix
-#define qglPushName glPushName
-#define qglRasterPos2d glRasterPos2d
-#define qglRasterPos2dv glRasterPos2dv
-#define qglRasterPos2f glRasterPos2f
-#define qglRasterPos2fv glRasterPos2fv
-#define qglRasterPos2i glRasterPos2i
-#define qglRasterPos2iv glRasterPos2iv
-#define qglRasterPos2s glRasterPos2s
-#define qglRasterPos2sv glRasterPos2sv
-#define qglRasterPos3d glRasterPos3d
-#define qglRasterPos3dv glRasterPos3dv
-#define qglRasterPos3f glRasterPos3f
-#define qglRasterPos3fv glRasterPos3fv
-#define qglRasterPos3i glRasterPos3i
-#define qglRasterPos3iv glRasterPos3iv
-#define qglRasterPos3s glRasterPos3s
-#define qglRasterPos3sv glRasterPos3sv
-#define qglRasterPos4d glRasterPos4d
-#define qglRasterPos4dv glRasterPos4dv
-#define qglRasterPos4f glRasterPos4f
-#define qglRasterPos4fv glRasterPos4fv
-#define qglRasterPos4i glRasterPos4i
-#define qglRasterPos4iv glRasterPos4iv
-#define qglRasterPos4s glRasterPos4s
-#define qglRasterPos4sv glRasterPos4sv
-#define qglReadBuffer glReadBuffer
-#define qglReadPixels glReadPixels
-#define qglRectd glRectd
-#define qglRectdv glRectdv
-#define qglRectf glRectf
-#define qglRectfv glRectfv
-#define qglRecti glRecti
-#define qglRectiv glRectiv
-#define qglRects glRects
-#define qglRectsv glRectsv
-#define qglRenderMode glRenderMode
-#define qglRotated glRotated
-#define qglRotatef glRotatef
-#define qglScaled glScaled
-#define qglScalef glScalef
-#define qglScissor glScissor
-#define qglSelectBuffer glSelectBuffer
-#define qglShadeModel glShadeModel
-#define qglStencilFunc glStencilFunc
-#define qglStencilMask glStencilMask
-#define qglStencilOp glStencilOp
-#define qglTexCoord1d glTexCoord1d
-#define qglTexCoord1dv glTexCoord1dv
-#define qglTexCoord1f glTexCoord1f
-#define qglTexCoord1fv glTexCoord1fv
-#define qglTexCoord1i glTexCoord1i
-#define qglTexCoord1iv glTexCoord1iv
-#define qglTexCoord1s glTexCoord1s
-#define qglTexCoord1sv glTexCoord1sv
-#define qglTexCoord2d glTexCoord2d
-#define qglTexCoord2dv glTexCoord2dv
-#define qglTexCoord2f glTexCoord2f
-#define qglTexCoord2fv glTexCoord2fv
-#define qglTexCoord2i glTexCoord2i
-#define qglTexCoord2iv glTexCoord2iv
-#define qglTexCoord2s glTexCoord2s
-#define qglTexCoord2sv glTexCoord2sv
-#define qglTexCoord3d glTexCoord3d
-#define qglTexCoord3dv glTexCoord3dv
-#define qglTexCoord3f glTexCoord3f
-#define qglTexCoord3fv glTexCoord3fv
-#define qglTexCoord3i glTexCoord3i
-#define qglTexCoord3iv glTexCoord3iv
-#define qglTexCoord3s glTexCoord3s
-#define qglTexCoord3sv glTexCoord3sv
-#define qglTexCoord4d glTexCoord4d
-#define qglTexCoord4dv glTexCoord4dv
-#define qglTexCoord4f glTexCoord4f
-#define qglTexCoord4fv glTexCoord4fv
-#define qglTexCoord4i glTexCoord4i
-#define qglTexCoord4iv glTexCoord4iv
-#define qglTexCoord4s glTexCoord4s
-#define qglTexCoord4sv glTexCoord4sv
-#define qglTexCoordPointer glTexCoordPointer
-#define qglTexEnvf glTexEnvf
-#define qglTexEnvfv glTexEnvfv
-#define qglTexEnvi glTexEnvi
-#define qglTexEnviv glTexEnviv
-#define qglTexGend glTexGend
-#define qglTexGendv glTexGendv
-#define qglTexGenf glTexGenf
-#define qglTexGenfv glTexGenfv
-#define qglTexGeni glTexGeni
-#define qglTexGeniv glTexGeniv
-#define qglTexImage1D glTexImage1D
-#define qglTexImage2D glTexImage2D
-#define qglTexParameterf glTexParameterf
-#define qglTexParameterfv glTexParameterfv
-#define qglTexParameteri glTexParameteri
-#define qglTexParameteriv glTexParameteriv
-#define qglTexSubImage1D glTexSubImage1D
-#define qglTexSubImage2D glTexSubImage2D
-#define qglTranslated glTranslated
-#define qglTranslatef glTranslatef
-#define qglVertex2d glVertex2d
-#define qglVertex2dv glVertex2dv
-#define qglVertex2f glVertex2f
-#define qglVertex2fv glVertex2fv
-#define qglVertex2i glVertex2i
-#define qglVertex2iv glVertex2iv
-#define qglVertex2s glVertex2s
-#define qglVertex2sv glVertex2sv
-#define qglVertex3d glVertex3d
-#define qglVertex3dv glVertex3dv
-#define qglVertex3f glVertex3f
-#define qglVertex3fv glVertex3fv
-#define qglVertex3i glVertex3i
-#define qglVertex3iv glVertex3iv
-#define qglVertex3s glVertex3s
-#define qglVertex3sv glVertex3sv
-#define qglVertex4d glVertex4d
-#define qglVertex4dv glVertex4dv
-#define qglVertex4f glVertex4f
-#define qglVertex4fv glVertex4fv
-#define qglVertex4i glVertex4i
-#define qglVertex4iv glVertex4iv
-#define qglVertex4s glVertex4s
-#define qglVertex4sv glVertex4sv
-#define qglVertexPointer glVertexPointer
-#define qglViewport glViewport
-
-#endif
diff --git a/src/rend2/tr_animation.c b/src/rend2/tr_animation.c
deleted file mode 100644
index 794111c6..00000000
--- a/src/rend2/tr_animation.c
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-#include "tr_local.h"
-
-/*
-
-All bones should be an identity orientation to display the mesh exactly
-as it is specified.
-
-For all other frames, the bones represent the transformation from the
-orientation of the bone in the base frame to the orientation in this
-frame.
-
-*/
-
-/*
-==============
-R_AddAnimSurfaces
-==============
-*/
-void R_AddAnimSurfaces( trRefEntity_t *ent ) {
- md4Header_t *header;
- md4Surface_t *surface;
- md4LOD_t *lod;
- shader_t *shader;
- int i;
-
- header = (md4Header_t *) tr.currentModel->modelData;
- lod = (md4LOD_t *)( (byte *)header + header->ofsLODs );
-
- surface = (md4Surface_t *)( (byte *)lod + lod->ofsSurfaces );
- for ( i = 0 ; i < lod->numSurfaces ; i++ ) {
- shader = R_GetShaderByHandle( surface->shaderIndex );
- R_AddDrawSurf( (void *)surface, shader, 0 /*fogNum*/, qfalse, qfalse );
- surface = (md4Surface_t *)( (byte *)surface + surface->ofsEnd );
- }
-}
-
-/*
-==============
-RB_SurfaceAnim
-==============
-*/
-void RB_SurfaceAnim( md4Surface_t *surface ) {
- int i, j, k;
- float frontlerp, backlerp;
- int *triangles;
- int indexes;
- int baseIndex, baseVertex;
- int numVerts;
- md4Vertex_t *v;
- md4Bone_t bones[MD4_MAX_BONES];
- md4Bone_t *bonePtr, *bone;
- md4Header_t *header;
- md4Frame_t *frame;
- md4Frame_t *oldFrame;
- int frameSize;
-
-
- if ( backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) {
- backlerp = 0;
- frontlerp = 1;
- } else {
- backlerp = backEnd.currentEntity->e.backlerp;
- frontlerp = 1.0f - backlerp;
- }
- header = (md4Header_t *)((byte *)surface + surface->ofsHeader);
-
- frameSize = (size_t)( &((md4Frame_t *)0)->bones[ header->numBones ] );
-
- frame = (md4Frame_t *)((byte *)header + header->ofsFrames +
- backEnd.currentEntity->e.frame * frameSize );
- oldFrame = (md4Frame_t *)((byte *)header + header->ofsFrames +
- backEnd.currentEntity->e.oldframe * frameSize );
-
- RB_CheckOverflow( surface->numVerts, surface->numTriangles * 3 );
-
- triangles = (int *) ((byte *)surface + surface->ofsTriangles);
- indexes = surface->numTriangles * 3;
- baseIndex = tess.numIndexes;
- baseVertex = tess.numVertexes;
- for (j = 0 ; j < indexes ; j++) {
- tess.indexes[baseIndex + j] = baseIndex + triangles[j];
- }
- tess.numIndexes += indexes;
-
- //
- // lerp all the needed bones
- //
- if ( !backlerp ) {
- // no lerping needed
- bonePtr = frame->bones;
- } else {
- bonePtr = bones;
- for ( i = 0 ; i < header->numBones*12 ; i++ ) {
- ((float *)bonePtr)[i] = frontlerp * ((float *)frame->bones)[i]
- + backlerp * ((float *)oldFrame->bones)[i];
- }
- }
-
- //
- // deform the vertexes by the lerped bones
- //
- numVerts = surface->numVerts;
- // FIXME
- // This makes TFC's skeletons work. Shouldn't be necessary anymore, but left
- // in for reference.
- //v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts + 12);
- v = (md4Vertex_t *) ((byte *)surface + surface->ofsVerts);
- for ( j = 0; j < numVerts; j++ ) {
- vec3_t tempVert, tempNormal;
- md4Weight_t *w;
-
- VectorClear( tempVert );
- VectorClear( tempNormal );
- w = v->weights;
- for ( k = 0 ; k < v->numWeights ; k++, w++ ) {
- bone = bonePtr + w->boneIndex;
-
- tempVert[0] += w->boneWeight * ( DotProduct( bone->matrix[0], w->offset ) + bone->matrix[0][3] );
- tempVert[1] += w->boneWeight * ( DotProduct( bone->matrix[1], w->offset ) + bone->matrix[1][3] );
- tempVert[2] += w->boneWeight * ( DotProduct( bone->matrix[2], w->offset ) + bone->matrix[2][3] );
-
- tempNormal[0] += w->boneWeight * DotProduct( bone->matrix[0], v->normal );
- tempNormal[1] += w->boneWeight * DotProduct( bone->matrix[1], v->normal );
- tempNormal[2] += w->boneWeight * DotProduct( bone->matrix[2], v->normal );
- }
-
- tess.xyz[baseVertex + j][0] = tempVert[0];
- tess.xyz[baseVertex + j][1] = tempVert[1];
- tess.xyz[baseVertex + j][2] = tempVert[2];
-
- tess.normal[baseVertex + j][0] = tempNormal[0];
- tess.normal[baseVertex + j][1] = tempNormal[1];
- tess.normal[baseVertex + j][2] = tempNormal[2];
-
- tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
- tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];
-
- // FIXME
- // This makes TFC's skeletons work. Shouldn't be necessary anymore, but left
- // in for reference.
- //v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 );
- v = (md4Vertex_t *)&v->weights[v->numWeights];
- }
-
- tess.numVertexes += surface->numVerts;
-}
-
-
-#ifdef RAVENMD4
-
-// copied and adapted from tr_mesh.c
-
-/*
-=============
-R_MDRCullModel
-=============
-*/
-
-static int R_MDRCullModel( mdrHeader_t *header, trRefEntity_t *ent ) {
- vec3_t bounds[2];
- mdrFrame_t *oldFrame, *newFrame;
- int i, frameSize;
-
- frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] );
-
- // compute frame pointers
- newFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame);
- oldFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.oldframe);
-
- // cull bounding sphere ONLY if this is not an upscaled entity
- if ( !ent->e.nonNormalizedAxes )
- {
- if ( ent->e.frame == ent->e.oldframe )
- {
- switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) )
- {
- // Ummm... yeah yeah I know we don't really have an md3 here.. but we pretend
- // we do. After all, the purpose of md4s are not that different, are they?
-
- case CULL_OUT:
- tr.pc.c_sphere_cull_md3_out++;
- return CULL_OUT;
-
- case CULL_IN:
- tr.pc.c_sphere_cull_md3_in++;
- return CULL_IN;
-
- case CULL_CLIP:
- tr.pc.c_sphere_cull_md3_clip++;
- break;
- }
- }
- else
- {
- int sphereCull, sphereCullB;
-
- sphereCull = R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius );
- if ( newFrame == oldFrame ) {
- sphereCullB = sphereCull;
- } else {
- sphereCullB = R_CullLocalPointAndRadius( oldFrame->localOrigin, oldFrame->radius );
- }
-
- if ( sphereCull == sphereCullB )
- {
- if ( sphereCull == CULL_OUT )
- {
- tr.pc.c_sphere_cull_md3_out++;
- return CULL_OUT;
- }
- else if ( sphereCull == CULL_IN )
- {
- tr.pc.c_sphere_cull_md3_in++;
- return CULL_IN;
- }
- else
- {
- tr.pc.c_sphere_cull_md3_clip++;
- }
- }
- }
- }
-
- // calculate a bounding box in the current coordinate system
- for (i = 0 ; i < 3 ; i++) {
- bounds[0][i] = oldFrame->bounds[0][i] < newFrame->bounds[0][i] ? oldFrame->bounds[0][i] : newFrame->bounds[0][i];
- bounds[1][i] = oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i];
- }
-
- switch ( R_CullLocalBox( bounds ) )
- {
- case CULL_IN:
- tr.pc.c_box_cull_md3_in++;
- return CULL_IN;
- case CULL_CLIP:
- tr.pc.c_box_cull_md3_clip++;
- return CULL_CLIP;
- case CULL_OUT:
- default:
- tr.pc.c_box_cull_md3_out++;
- return CULL_OUT;
- }
-}
-
-/*
-=================
-R_MDRComputeFogNum
-
-=================
-*/
-
-int R_MDRComputeFogNum( mdrHeader_t *header, trRefEntity_t *ent ) {
- int i, j;
- fog_t *fog;
- mdrFrame_t *mdrFrame;
- vec3_t localOrigin;
- int frameSize;
-
- if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
- return 0;
- }
-
- frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] );
-
- // FIXME: non-normalized axis issues
- mdrFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame);
- VectorAdd( ent->e.origin, mdrFrame->localOrigin, localOrigin );
- for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
- fog = &tr.world->fogs[i];
- for ( j = 0 ; j < 3 ; j++ ) {
- if ( localOrigin[j] - mdrFrame->radius >= fog->bounds[1][j] ) {
- break;
- }
- if ( localOrigin[j] + mdrFrame->radius <= fog->bounds[0][j] ) {
- break;
- }
- }
- if ( j == 3 ) {
- return i;
- }
- }
-
- return 0;
-}
-
-
-/*
-==============
-R_MDRAddAnimSurfaces
-==============
-*/
-
-// much stuff in there is just copied from R_AddMd3Surfaces in tr_mesh.c
-
-void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
- mdrHeader_t *header;
- mdrSurface_t *surface;
- mdrLOD_t *lod;
- shader_t *shader;
- skin_t *skin;
- int i, j;
- int lodnum = 0;
- int fogNum = 0;
- int cull;
- qboolean personalModel;
-
- header = (mdrHeader_t *) tr.currentModel->modelData;
-
- personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal;
-
- if ( ent->e.renderfx & RF_WRAP_FRAMES )
- {
- ent->e.frame %= header->numFrames;
- ent->e.oldframe %= header->numFrames;
- }
-
- //
- // Validate the frames so there is no chance of a crash.
- // This will write directly into the entity structure, so
- // when the surfaces are rendered, they don't need to be
- // range checked again.
- //
- if ((ent->e.frame >= header->numFrames)
- || (ent->e.frame < 0)
- || (ent->e.oldframe >= header->numFrames)
- || (ent->e.oldframe < 0) )
- {
- ri.Printf( PRINT_DEVELOPER, "R_MDRAddAnimSurfaces: no such frame %d to %d for '%s'\n",
- ent->e.oldframe, ent->e.frame, tr.currentModel->name );
- ent->e.frame = 0;
- ent->e.oldframe = 0;
- }
-
- //
- // cull the entire model if merged bounding box of both frames
- // is outside the view frustum.
- //
- cull = R_MDRCullModel (header, ent);
- if ( cull == CULL_OUT ) {
- return;
- }
-
- // figure out the current LOD of the model we're rendering, and set the lod pointer respectively.
- lodnum = R_ComputeLOD(ent);
- // check whether this model has as that many LODs at all. If not, try the closest thing we got.
- if(header->numLODs <= 0)
- return;
- if(header->numLODs <= lodnum)
- lodnum = header->numLODs - 1;
-
- lod = (mdrLOD_t *)( (byte *)header + header->ofsLODs);
- for(i = 0; i < lodnum; i++)
- {
- lod = (mdrLOD_t *) ((byte *) lod + lod->ofsEnd);
- }
-
- // set up lighting
- if ( !personalModel || r_shadows->integer > 1 )
- {
- R_SetupEntityLighting( &tr.refdef, ent );
- }
-
- // fogNum?
- fogNum = R_MDRComputeFogNum( header, ent );
-
- surface = (mdrSurface_t *)( (byte *)lod + lod->ofsSurfaces );
-
- for ( i = 0 ; i < lod->numSurfaces ; i++ )
- {
-
- if(ent->e.customShader)
- shader = R_GetShaderByHandle(ent->e.customShader);
- else if(ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins)
- {
- skin = R_GetSkinByHandle(ent->e.customSkin);
- shader = tr.defaultShader;
-
- for(j = 0; j < skin->numSurfaces; j++)
- {
- if (!strcmp(skin->surfaces[j]->name, surface->name))
- {
- shader = skin->surfaces[j]->shader;
- break;
- }
- }
- }
- else if(surface->shaderIndex > 0)
- shader = R_GetShaderByHandle( surface->shaderIndex );
- else
- shader = tr.defaultShader;
-
- // we will add shadows even if the main object isn't visible in the view
-
- // stencil shadows can't do personal models unless I polyhedron clip
- if ( !personalModel
- && r_shadows->integer == 2
- && fogNum == 0
- && !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )
- && shader->sort == SS_OPAQUE )
- {
- R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse, qfalse );
- }
-
- // projection shadows work fine with personal models
- if ( r_shadows->integer == 3
- && fogNum == 0
- && (ent->e.renderfx & RF_SHADOW_PLANE )
- && shader->sort == SS_OPAQUE )
- {
- R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, qfalse );
- }
-
- if (!personalModel)
- R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse, qfalse );
-
- surface = (mdrSurface_t *)( (byte *)surface + surface->ofsEnd );
- }
-}
-
-/*
-==============
-RB_MDRSurfaceAnim
-==============
-*/
-void RB_MDRSurfaceAnim( md4Surface_t *surface )
-{
- int i, j, k;
- float frontlerp, backlerp;
- int *triangles;
- int indexes;
- int baseIndex, baseVertex;
- int numVerts;
- mdrVertex_t *v;
- mdrHeader_t *header;
- mdrFrame_t *frame;
- mdrFrame_t *oldFrame;
- mdrBone_t bones[MD4_MAX_BONES], *bonePtr, *bone;
-
- int frameSize;
-
- // don't lerp if lerping off, or this is the only frame, or the last frame...
- //
- if (backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame)
- {
- backlerp = 0; // if backlerp is 0, lerping is off and frontlerp is never used
- frontlerp = 1;
- }
- else
- {
- backlerp = backEnd.currentEntity->e.backlerp;
- frontlerp = 1.0f - backlerp;
- }
-
- header = (mdrHeader_t *)((byte *)surface + surface->ofsHeader);
-
- frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] );
-
- frame = (mdrFrame_t *)((byte *)header + header->ofsFrames +
- backEnd.currentEntity->e.frame * frameSize );
- oldFrame = (mdrFrame_t *)((byte *)header + header->ofsFrames +
- backEnd.currentEntity->e.oldframe * frameSize );
-
- RB_CheckOverflow( surface->numVerts, surface->numTriangles );
-
- triangles = (int *) ((byte *)surface + surface->ofsTriangles);
- indexes = surface->numTriangles * 3;
- baseIndex = tess.numIndexes;
- baseVertex = tess.numVertexes;
-
- // Set up all triangles.
- for (j = 0 ; j < indexes ; j++)
- {
- tess.indexes[baseIndex + j] = baseVertex + triangles[j];
- }
- tess.numIndexes += indexes;
-
- //
- // lerp all the needed bones
- //
- if ( !backlerp )
- {
- // no lerping needed
- bonePtr = frame->bones;
- }
- else
- {
- bonePtr = bones;
-
- for ( i = 0 ; i < header->numBones*12 ; i++ )
- {
- ((float *)bonePtr)[i] = frontlerp * ((float *)frame->bones)[i] + backlerp * ((float *)oldFrame->bones)[i];
- }
- }
-
- //
- // deform the vertexes by the lerped bones
- //
- numVerts = surface->numVerts;
- v = (mdrVertex_t *) ((byte *)surface + surface->ofsVerts);
- for ( j = 0; j < numVerts; j++ )
- {
- vec3_t tempVert, tempNormal;
- mdrWeight_t *w;
-
- VectorClear( tempVert );
- VectorClear( tempNormal );
- w = v->weights;
- for ( k = 0 ; k < v->numWeights ; k++, w++ )
- {
- bone = bonePtr + w->boneIndex;
-
- tempVert[0] += w->boneWeight * ( DotProduct( bone->matrix[0], w->offset ) + bone->matrix[0][3] );
- tempVert[1] += w->boneWeight * ( DotProduct( bone->matrix[1], w->offset ) + bone->matrix[1][3] );
- tempVert[2] += w->boneWeight * ( DotProduct( bone->matrix[2], w->offset ) + bone->matrix[2][3] );
-
- tempNormal[0] += w->boneWeight * DotProduct( bone->matrix[0], v->normal );
- tempNormal[1] += w->boneWeight * DotProduct( bone->matrix[1], v->normal );
- tempNormal[2] += w->boneWeight * DotProduct( bone->matrix[2], v->normal );
- }
-
- tess.xyz[baseVertex + j][0] = tempVert[0];
- tess.xyz[baseVertex + j][1] = tempVert[1];
- tess.xyz[baseVertex + j][2] = tempVert[2];
-
- tess.normal[baseVertex + j][0] = tempNormal[0];
- tess.normal[baseVertex + j][1] = tempNormal[1];
- tess.normal[baseVertex + j][2] = tempNormal[2];
-
- tess.texCoords[baseVertex + j][0][0] = v->texCoords[0];
- tess.texCoords[baseVertex + j][0][1] = v->texCoords[1];
-
- v = (mdrVertex_t *)&v->weights[v->numWeights];
- }
-
- tess.numVertexes += surface->numVerts;
-}
-
-
-#define MC_MASK_X ((1<<(MC_BITS_X))-1)
-#define MC_MASK_Y ((1<<(MC_BITS_Y))-1)
-#define MC_MASK_Z ((1<<(MC_BITS_Z))-1)
-#define MC_MASK_VECT ((1<<(MC_BITS_VECT))-1)
-
-#define MC_SCALE_VECT (1.0f/(float)((1<<(MC_BITS_VECT-1))-2))
-
-#define MC_POS_X (0)
-#define MC_SHIFT_X (0)
-
-#define MC_POS_Y ((((MC_BITS_X))/8))
-#define MC_SHIFT_Y ((((MC_BITS_X)%8)))
-
-#define MC_POS_Z ((((MC_BITS_X+MC_BITS_Y))/8))
-#define MC_SHIFT_Z ((((MC_BITS_X+MC_BITS_Y)%8)))
-
-#define MC_POS_V11 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z))/8))
-#define MC_SHIFT_V11 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z)%8)))
-
-#define MC_POS_V12 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT))/8))
-#define MC_SHIFT_V12 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT)%8)))
-
-#define MC_POS_V13 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*2))/8))
-#define MC_SHIFT_V13 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*2)%8)))
-
-#define MC_POS_V21 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*3))/8))
-#define MC_SHIFT_V21 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*3)%8)))
-
-#define MC_POS_V22 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*4))/8))
-#define MC_SHIFT_V22 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*4)%8)))
-
-#define MC_POS_V23 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*5))/8))
-#define MC_SHIFT_V23 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*5)%8)))
-
-#define MC_POS_V31 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*6))/8))
-#define MC_SHIFT_V31 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*6)%8)))
-
-#define MC_POS_V32 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*7))/8))
-#define MC_SHIFT_V32 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*7)%8)))
-
-#define MC_POS_V33 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*8))/8))
-#define MC_SHIFT_V33 ((((MC_BITS_X+MC_BITS_Y+MC_BITS_Z+MC_BITS_VECT*8)%8)))
-
-void MC_UnCompress(float mat[3][4],const unsigned char * comp)
-{
- int val;
-
- val=(int)((unsigned short *)(comp))[0];
- val-=1<<(MC_BITS_X-1);
- mat[0][3]=((float)(val))*MC_SCALE_X;
-
- val=(int)((unsigned short *)(comp))[1];
- val-=1<<(MC_BITS_Y-1);
- mat[1][3]=((float)(val))*MC_SCALE_Y;
-
- val=(int)((unsigned short *)(comp))[2];
- val-=1<<(MC_BITS_Z-1);
- mat[2][3]=((float)(val))*MC_SCALE_Z;
-
- val=(int)((unsigned short *)(comp))[3];
- val-=1<<(MC_BITS_VECT-1);
- mat[0][0]=((float)(val))*MC_SCALE_VECT;
-
- val=(int)((unsigned short *)(comp))[4];
- val-=1<<(MC_BITS_VECT-1);
- mat[0][1]=((float)(val))*MC_SCALE_VECT;
-
- val=(int)((unsigned short *)(comp))[5];
- val-=1<<(MC_BITS_VECT-1);
- mat[0][2]=((float)(val))*MC_SCALE_VECT;
-
-
- val=(int)((unsigned short *)(comp))[6];
- val-=1<<(MC_BITS_VECT-1);
- mat[1][0]=((float)(val))*MC_SCALE_VECT;
-
- val=(int)((unsigned short *)(comp))[7];
- val-=1<<(MC_BITS_VECT-1);
- mat[1][1]=((float)(val))*MC_SCALE_VECT;
-
- val=(int)((unsigned short *)(comp))[8];
- val-=1<<(MC_BITS_VECT-1);
- mat[1][2]=((float)(val))*MC_SCALE_VECT;
-
-
- val=(int)((unsigned short *)(comp))[9];
- val-=1<<(MC_BITS_VECT-1);
- mat[2][0]=((float)(val))*MC_SCALE_VECT;
-
- val=(int)((unsigned short *)(comp))[10];
- val-=1<<(MC_BITS_VECT-1);
- mat[2][1]=((float)(val))*MC_SCALE_VECT;
-
- val=(int)((unsigned short *)(comp))[11];
- val-=1<<(MC_BITS_VECT-1);
- mat[2][2]=((float)(val))*MC_SCALE_VECT;
-}
-#endif
diff --git a/src/rend2/tr_backend.c b/src/rend2/tr_backend.c
deleted file mode 100644
index fd61ee76..00000000
--- a/src/rend2/tr_backend.c
+++ /dev/null
@@ -1,1843 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-#include "tr_local.h"
-
-backEndData_t *backEndData;
-backEndState_t backEnd;
-
-
-static float s_flipMatrix[16] = {
- // convert from our coordinate system (looking down X)
- // to OpenGL's coordinate system (looking down -Z)
- 0, 0, -1, 0,
- -1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 0, 1
-};
-
-
-/*
-** GL_Bind2
-*/
-void GL_Bind2( image_t *image, GLenum type ) {
- int texnum;
-
- if ( !image ) {
- ri.Printf( PRINT_WARNING, "GL_Bind2: NULL image\n" );
- texnum = tr.defaultImage->texnum;
- } else {
- texnum = image->texnum;
- }
-
- if ( r_nobind->integer && tr.dlightImage ) { // performance evaluation option
- texnum = tr.dlightImage->texnum;
- }
-
- if ( glState.currenttextures[glState.currenttmu] != texnum ) {
- image->frameUsed = tr.frameCount;
- glState.currenttextures[glState.currenttmu] = texnum;
- qglBindTexture (type, texnum);
- }
-}
-
-/*
-** GL_Bind2
-*/
-void GL_Bind( image_t *image )
-{
- GL_Bind2( image, GL_TEXTURE_2D );
-}
-
-/*
-** GL_BindCubemap
-*/
-void GL_BindCubemap( image_t *image )
-{
- GL_Bind2( image, GL_TEXTURE_CUBE_MAP );
-}
-
-/*
-** GL_SelectTexture
-*/
-void GL_SelectTexture( int unit )
-{
- if ( glState.currenttmu == unit )
- {
- return;
- }
-
- if (!(unit >= 0 && unit <= 31))
- ri.Error( ERR_DROP, "GL_SelectTexture: unit = %i", unit );
-
- qglActiveTextureARB( GL_TEXTURE0_ARB + unit );
-
- glState.currenttmu = unit;
-}
-
-
-/*
-** GL_BindMultitexture
-*/
-void GL_BindMultitexture( image_t *image0, GLuint env0, image_t *image1, GLuint env1 ) {
- int texnum0, texnum1;
-
- texnum0 = image0->texnum;
- texnum1 = image1->texnum;
-
- if ( r_nobind->integer && tr.dlightImage ) { // performance evaluation option
- texnum0 = texnum1 = tr.dlightImage->texnum;
- }
-
- if ( glState.currenttextures[1] != texnum1 ) {
- GL_SelectTexture( 1 );
- image1->frameUsed = tr.frameCount;
- glState.currenttextures[1] = texnum1;
- qglBindTexture( GL_TEXTURE_2D, texnum1 );
- }
- if ( glState.currenttextures[0] != texnum0 ) {
- GL_SelectTexture( 0 );
- image0->frameUsed = tr.frameCount;
- glState.currenttextures[0] = texnum0;
- qglBindTexture( GL_TEXTURE_2D, texnum0 );
- }
-}
-
-/*
-** GL_BindToTMU
-*/
-void GL_BindToTMU( image_t *image, int tmu )
-{
- int texnum;
- int oldtmu = glState.currenttmu;
-
- if (!image)
- texnum = 0;
- else
- texnum = image->texnum;
-
- if ( glState.currenttextures[tmu] != texnum ) {
- GL_SelectTexture( tmu );
- if (image)
- image->frameUsed = tr.frameCount;
- glState.currenttextures[tmu] = texnum;
- qglBindTexture( GL_TEXTURE_2D, texnum );
- GL_SelectTexture( oldtmu );
- }
-}
-
-
-/*
-** GL_Cull
-*/
-void GL_Cull( int cullType ) {
- if ( glState.faceCulling == cullType ) {
- return;
- }
-
- glState.faceCulling = cullType;
-
- if ( cullType == CT_TWO_SIDED )
- {
- qglDisable( GL_CULL_FACE );
- }
- else
- {
- qboolean cullFront;
- qglEnable( GL_CULL_FACE );
-
- cullFront = (cullType == CT_FRONT_SIDED);
- if ( backEnd.viewParms.isMirror )
- {
- cullFront = !cullFront;
- }
-
- if ( backEnd.currentEntity && backEnd.currentEntity->mirrored )
- {
- cullFront = !cullFront;
- }
-
- qglCullFace( cullFront ? GL_FRONT : GL_BACK );
- }
-}
-
-/*
-** GL_TexEnv
-*/
-void GL_TexEnv( int env )
-{
- if ( env == glState.texEnv[glState.currenttmu] )
- {
- return;
- }
-
- glState.texEnv[glState.currenttmu] = env;
-
-
- switch ( env )
- {
- case GL_MODULATE:
- qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
- break;
- case GL_REPLACE:
- qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
- break;
- case GL_DECAL:
- qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
- break;
- case GL_ADD:
- qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD );
- break;
- default:
- ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed", env );
- break;
- }
-}
-
-/*
-** GL_State
-**
-** This routine is responsible for setting the most commonly changed state
-** in Q3.
-*/
-void GL_State( unsigned long stateBits )
-{
- unsigned long diff = stateBits ^ glState.glStateBits;
-
- if ( !diff )
- {
- return;
- }
-
- //
- // check depthFunc bits
- //
- if ( diff & GLS_DEPTHFUNC_BITS )
- {
- if ( stateBits & GLS_DEPTHFUNC_EQUAL )
- {
- qglDepthFunc( GL_EQUAL );
- }
- else if ( stateBits & GLS_DEPTHFUNC_GREATER)
- {
- qglDepthFunc( GL_GREATER );
- }
- else
- {
- qglDepthFunc( GL_LEQUAL );
- }
- }
-
- //
- // check blend bits
- //
- if ( diff & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) )
- {
- GLenum srcFactor, dstFactor;
-
- if ( stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) )
- {
- switch ( stateBits & GLS_SRCBLEND_BITS )
- {
- case GLS_SRCBLEND_ZERO:
- srcFactor = GL_ZERO;
- break;
- case GLS_SRCBLEND_ONE:
- srcFactor = GL_ONE;
- break;
- case GLS_SRCBLEND_DST_COLOR:
- srcFactor = GL_DST_COLOR;
- break;
- case GLS_SRCBLEND_ONE_MINUS_DST_COLOR:
- srcFactor = GL_ONE_MINUS_DST_COLOR;
- break;
- case GLS_SRCBLEND_SRC_ALPHA:
- srcFactor = GL_SRC_ALPHA;
- break;
- case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA:
- srcFactor = GL_ONE_MINUS_SRC_ALPHA;
- break;
- case GLS_SRCBLEND_DST_ALPHA:
- srcFactor = GL_DST_ALPHA;
- break;
- case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA:
- srcFactor = GL_ONE_MINUS_DST_ALPHA;
- break;
- case GLS_SRCBLEND_ALPHA_SATURATE:
- srcFactor = GL_SRC_ALPHA_SATURATE;
- break;
- default:
- srcFactor = GL_ONE; // to get warning to shut up
- ri.Error( ERR_DROP, "GL_State: invalid src blend state bits" );
- break;
- }
-
- switch ( stateBits & GLS_DSTBLEND_BITS )
- {
- case GLS_DSTBLEND_ZERO:
- dstFactor = GL_ZERO;
- break;
- case GLS_DSTBLEND_ONE:
- dstFactor = GL_ONE;
- break;
- case GLS_DSTBLEND_SRC_COLOR:
- dstFactor = GL_SRC_COLOR;
- break;
- case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR:
- dstFactor = GL_ONE_MINUS_SRC_COLOR;
- break;
- case GLS_DSTBLEND_SRC_ALPHA:
- dstFactor = GL_SRC_ALPHA;
- break;
- case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA:
- dstFactor = GL_ONE_MINUS_SRC_ALPHA;
- break;
- case GLS_DSTBLEND_DST_ALPHA:
- dstFactor = GL_DST_ALPHA;
- break;
- case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA:
- dstFactor = GL_ONE_MINUS_DST_ALPHA;
- break;
- default:
- dstFactor = GL_ONE; // to get warning to shut up
- ri.Error( ERR_DROP, "GL_State: invalid dst blend state bits" );
- break;
- }
-
- qglEnable( GL_BLEND );
- qglBlendFunc( srcFactor, dstFactor );
- }
- else
- {
- qglDisable( GL_BLEND );
- }
- }
-
- //
- // check depthmask
- //
- if ( diff & GLS_DEPTHMASK_TRUE )
- {
- if ( stateBits & GLS_DEPTHMASK_TRUE )
- {
- qglDepthMask( GL_TRUE );
- }
- else
- {
- qglDepthMask( GL_FALSE );
- }
- }
-
- //
- // fill/line mode
- //
- if ( diff & GLS_POLYMODE_LINE )
- {
- if ( stateBits & GLS_POLYMODE_LINE )
- {
- qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
- }
- else
- {
- qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
- }
- }
-
- //
- // depthtest
- //
- if ( diff & GLS_DEPTHTEST_DISABLE )
- {
- if ( stateBits & GLS_DEPTHTEST_DISABLE )
- {
- qglDisable( GL_DEPTH_TEST );
- }
- else
- {
- qglEnable( GL_DEPTH_TEST );
- }
- }
-
- //
- // alpha test
- //
- if ( diff & GLS_ATEST_BITS )
- {
- switch ( stateBits & GLS_ATEST_BITS )
- {
- case 0:
- qglDisable( GL_ALPHA_TEST );
- break;
- case GLS_ATEST_GT_0:
- qglEnable( GL_ALPHA_TEST );
- qglAlphaFunc( GL_GREATER, 0.0f );
- break;
- case GLS_ATEST_LT_80:
- qglEnable( GL_ALPHA_TEST );
- qglAlphaFunc( GL_LESS, 0.5f );
- break;
- case GLS_ATEST_GE_80:
- qglEnable( GL_ALPHA_TEST );
- qglAlphaFunc( GL_GEQUAL, 0.5f );
- break;
- default:
- assert( 0 );
- break;
- }
- }
-
- glState.glStateBits = stateBits;
-}
-
-
-void GL_SetProjectionMatrix(matrix_t matrix)
-{
- Matrix16Copy(matrix, glState.projection);
- Matrix16Multiply(glState.projection, glState.modelview, glState.modelviewProjection);
-}
-
-
-void GL_SetModelviewMatrix(matrix_t matrix)
-{
- Matrix16Copy(matrix, glState.modelview);
- Matrix16Multiply(glState.projection, glState.modelview, glState.modelviewProjection);
-}
-
-
-/*
-================
-RB_Hyperspace
-
-A player has predicted a teleport, but hasn't arrived yet
-================
-*/
-static void RB_Hyperspace( void ) {
- float c;
-
- if ( !backEnd.isHyperspace ) {
- // do initialization shit
- }
-
- c = ( backEnd.refdef.time & 255 ) / 255.0f;
- qglClearColor( c, c, c, 1 );
- qglClear( GL_COLOR_BUFFER_BIT );
-
- backEnd.isHyperspace = qtrue;
-}
-
-
-static void SetViewportAndScissor( void ) {
- GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix );
-
- // set the window clipping
- qglViewport( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
- backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight );
- qglScissor( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY,
- backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight );
-}
-
-/*
-=================
-RB_BeginDrawingView
-
-Any mirrored or portaled views have already been drawn, so prepare
-to actually render the visible surfaces for this view
-=================
-*/
-void RB_BeginDrawingView (void) {
- int clearBits = 0;
-
- // sync with gl if needed
- if ( r_finish->integer == 1 && !glState.finishCalled ) {
- qglFinish ();
- glState.finishCalled = qtrue;
- }
- if ( r_finish->integer == 0 ) {
- glState.finishCalled = qtrue;
- }
-
- // we will need to change the projection matrix before drawing
- // 2D images again
- backEnd.projection2D = qfalse;
-
- if (glRefConfig.framebufferObject)
- {
- // FIXME: HUGE HACK: render to the screen fbo if we've already postprocessed the frame and aren't drawing more world
- // drawing more world check is in case of double renders, such as skyportals
- if (backEnd.viewParms.targetFbo == NULL)
- {
- if (!tr.renderFbo || (backEnd.framePostProcessed && (backEnd.refdef.rdflags & RDF_NOWORLDMODEL)))
- {
- FBO_Bind(tr.screenScratchFbo);
- }
- else
- {
- FBO_Bind(tr.renderFbo);
- }
- }
- else
- {
- FBO_Bind(backEnd.viewParms.targetFbo);
- }
- }
-
- //
- // set the modelview matrix for the viewer
- //
- SetViewportAndScissor();
-
- // ensures that depth writes are enabled for the depth clear
- GL_State( GLS_DEFAULT );
- // clear relevant buffers
- clearBits = GL_DEPTH_BUFFER_BIT;
-
- if ( r_measureOverdraw->integer || r_shadows->integer == 2 )
- {
- clearBits |= GL_STENCIL_BUFFER_BIT;
- }
- if ( r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) )
- {
- clearBits |= GL_COLOR_BUFFER_BIT; // FIXME: only if sky shaders have been used
-#ifdef _DEBUG
- qglClearColor( 0.8f, 0.7f, 0.4f, 1.0f ); // FIXME: get color of sky
-#else
- qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // FIXME: get color of sky
-#endif
- }
-
- // clear to white for shadow maps
- if (backEnd.viewParms.flags & VPF_SHADOWMAP)
- {
- clearBits |= GL_COLOR_BUFFER_BIT;
- qglClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
- }
-
- qglClear( clearBits );
-
- if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) )
- {
- RB_Hyperspace();
- return;
- }
- else
- {
- backEnd.isHyperspace = qfalse;
- }
-
- glState.faceCulling = -1; // force face culling to set next time
-
- // we will only draw a sun if there was sky rendered in this view
- backEnd.skyRenderedThisView = qfalse;
-
- // clip to the plane of the portal
- if ( backEnd.viewParms.isPortal ) {
-#if 0
- float plane[4];
- double plane2[4];
-
- plane[0] = backEnd.viewParms.portalPlane.normal[0];
- plane[1] = backEnd.viewParms.portalPlane.normal[1];
- plane[2] = backEnd.viewParms.portalPlane.normal[2];
- plane[3] = backEnd.viewParms.portalPlane.dist;
-
- plane2[0] = DotProduct (backEnd.viewParms.or.axis[0], plane);
- plane2[1] = DotProduct (backEnd.viewParms.or.axis[1], plane);
- plane2[2] = DotProduct (backEnd.viewParms.or.axis[2], plane);
- plane2[3] = DotProduct (plane, backEnd.viewParms.or.origin) - plane[3];
-#endif
- GL_SetModelviewMatrix( s_flipMatrix );
- }
-}
-
-
-#define MAC_EVENT_PUMP_MSEC 5
-
-/*
-==================
-RB_RenderDrawSurfList
-==================
-*/
-void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
- shader_t *shader, *oldShader;
- int fogNum, oldFogNum;
- int entityNum, oldEntityNum;
- int dlighted, oldDlighted;
- int pshadowed, oldPshadowed;
- qboolean depthRange, oldDepthRange, isCrosshair, wasCrosshair;
- int i;
- drawSurf_t *drawSurf;
- int oldSort;
- float originalTime;
- FBO_t* fbo = NULL;
- qboolean inQuery = qfalse;
-
- float depth[2];
-
-
- // save original time for entity shader offsets
- originalTime = backEnd.refdef.floatTime;
-
- fbo = glState.currentFBO;
-
- // draw everything
- oldEntityNum = -1;
- backEnd.currentEntity = &tr.worldEntity;
- oldShader = NULL;
- oldFogNum = -1;
- oldDepthRange = qfalse;
- wasCrosshair = qfalse;
- oldDlighted = qfalse;
- oldPshadowed = qfalse;
- oldSort = -1;
- depthRange = qfalse;
-
- depth[0] = 0.f;
- depth[1] = 1.f;
-
- backEnd.pc.c_surfaces += numDrawSurfs;
-
- for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) {
- if ( drawSurf->sort == oldSort ) {
- if (backEnd.depthFill && shader && shader->sort != SS_OPAQUE)
- continue;
-
- // fast path, same as previous sort
- rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
- continue;
- }
- oldSort = drawSurf->sort;
- R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed );
-
- //
- // change the tess parameters if needed
- // a "entityMergable" shader is a shader that can have surfaces from seperate
- // entities merged into a single batch, like smoke and blood puff sprites
- if (shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted || pshadowed != oldPshadowed
- || ( entityNum != oldEntityNum && !shader->entityMergable ) ) {
- if (oldShader != NULL) {
- RB_EndSurface();
- }
- RB_BeginSurface( shader, fogNum );
- backEnd.pc.c_surfBatches++;
- oldShader = shader;
- oldFogNum = fogNum;
- oldDlighted = dlighted;
- oldPshadowed = pshadowed;
- }
-
- if (backEnd.depthFill && shader && shader->sort != SS_OPAQUE)
- continue;
-
- //
- // change the modelview matrix if needed
- //
- if ( entityNum != oldEntityNum ) {
- qboolean sunflare = qfalse;
- depthRange = isCrosshair = qfalse;
-
- if ( entityNum != REFENTITYNUM_WORLD ) {
- backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
- backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
- // we have to reset the shaderTime as well otherwise image animations start
- // from the wrong frame
- tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
-
- // set up the transformation matrix
- R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.or );
-
- // set up the dynamic lighting if needed
- if ( backEnd.currentEntity->needDlights ) {
- R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
- }
-
- if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK)
- {
- // hack the depth range to prevent view model from poking into walls
- depthRange = qtrue;
-
- if(backEnd.currentEntity->e.renderfx & RF_CROSSHAIR)
- isCrosshair = qtrue;
- }
- } else {
- backEnd.currentEntity = &tr.worldEntity;
- backEnd.refdef.floatTime = originalTime;
- backEnd.or = backEnd.viewParms.world;
- // we have to reset the shaderTime as well otherwise image animations on
- // the world (like water) continue with the wrong frame
- tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
- R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
- }
-
- GL_SetModelviewMatrix( backEnd.or.modelMatrix );
-
- //
- // change depthrange. Also change projection matrix so first person weapon does not look like coming
- // out of the screen.
- //
- if (oldDepthRange != depthRange || wasCrosshair != isCrosshair)
- {
- if (depthRange)
- {
- if(backEnd.viewParms.stereoFrame != STEREO_CENTER)
- {
- if(isCrosshair)
- {
- if(oldDepthRange)
- {
- // was not a crosshair but now is, change back proj matrix
- GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix );
- }
- }
- else
- {
- viewParms_t temp = backEnd.viewParms;
-
- R_SetupProjection(&temp, r_znear->value, 0, qfalse);
-
- GL_SetProjectionMatrix( temp.projectionMatrix );
- }
- }
-
- if(!oldDepthRange)
- {
- depth[0] = 0;
- depth[1] = 0.3f;
- qglDepthRange (depth[0], depth[1]);
- }
- }
- else
- {
- if(!wasCrosshair && backEnd.viewParms.stereoFrame != STEREO_CENTER)
- {
- GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix );
- }
-
- if (!sunflare)
- qglDepthRange (0, 1);
-
- depth[0] = 0;
- depth[1] = 1;
- }
-
- oldDepthRange = depthRange;
- wasCrosshair = isCrosshair;
- }
-
- oldEntityNum = entityNum;
- }
-
- // add the triangles for this surface
- rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
- }
-
- backEnd.refdef.floatTime = originalTime;
-
- // draw the contents of the last shader batch
- if (oldShader != NULL) {
- RB_EndSurface();
- }
-
- if (inQuery) {
- inQuery = qfalse;
- qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
- }
-
- if (glRefConfig.framebufferObject)
- FBO_Bind(fbo);
-
- // go back to the world modelview matrix
-
- GL_SetModelviewMatrix( backEnd.viewParms.world.modelMatrix );
-
- qglDepthRange (0, 1);
-}
-
-
-/*
-============================================================================
-
-RENDER BACK END FUNCTIONS
-
-============================================================================
-*/
-
-/*
-================
-RB_SetGL2D
-
-================
-*/
-void RB_SetGL2D (void) {
- matrix_t matrix;
- int width, height;
-
- if (backEnd.projection2D && backEnd.last2DFBO == glState.currentFBO)
- return;
-
- backEnd.projection2D = qtrue;
- backEnd.last2DFBO = glState.currentFBO;
-
- if (glState.currentFBO)
- {
- width = glState.currentFBO->width;
- height = glState.currentFBO->height;
- }
- else
- {
- width = glConfig.vidWidth;
- height = glConfig.vidHeight;
- }
-
- // set 2D virtual screen size
- qglViewport( 0, 0, width, height );
- qglScissor( 0, 0, width, height );
-
- Matrix16Ortho(0, width, height, 0, 0, 1, matrix);
- GL_SetProjectionMatrix(matrix);
- Matrix16Identity(matrix);
- GL_SetModelviewMatrix(matrix);
-
- GL_State( GLS_DEPTHTEST_DISABLE |
- GLS_SRCBLEND_SRC_ALPHA |
- GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
-
- qglDisable( GL_CULL_FACE );
- qglDisable( GL_CLIP_PLANE0 );
-
- // set time for 2D shaders
- backEnd.refdef.time = ri.Milliseconds();
- backEnd.refdef.floatTime = backEnd.refdef.time * 0.001f;
-
- // reset color scaling
- backEnd.refdef.colorScale = 1.0f;
-}
-
-
-/*
-=============
-RE_StretchRaw
-
-FIXME: not exactly backend
-Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle.
-Used for cinematics.
-=============
-*/
-void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
- int i, j;
- int start, end;
- shaderProgram_t *sp = &tr.textureColorShader;
- vec4_t color;
-
- if ( !tr.registered ) {
- return;
- }
- R_IssuePendingRenderCommands();
-
- // we definately want to sync every frame for the cinematics
- qglFinish();
-
- start = 0;
- if ( r_speeds->integer ) {
- start = ri.Milliseconds();
- }
-
- // make sure rows and cols are powers of 2
- for ( i = 0 ; ( 1 << i ) < cols ; i++ ) {
- }
- for ( j = 0 ; ( 1 << j ) < rows ; j++ ) {
- }
- if ( ( 1 << i ) != cols || ( 1 << j ) != rows) {
- ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
- }
-
- GL_Bind( tr.scratchImage[client] );
-
- // if the scratchImage isn't in the format we want, specify it as a new texture
- if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
- tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
- tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
- qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
- qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
- qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
- } else {
- if (dirty) {
- // otherwise, just subimage upload it so that drivers can tell we are going to be changing
- // it and don't try and do a texture compression
- qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
- }
- }
-
- if ( r_speeds->integer ) {
- end = ri.Milliseconds();
- ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start );
- }
-
- // FIXME: HUGE hack
- if (glRefConfig.framebufferObject)
- {
- if (!tr.renderFbo || backEnd.framePostProcessed)
- {
- FBO_Bind(tr.screenScratchFbo);
- }
- else
- {
- FBO_Bind(tr.renderFbo);
- }
- }
-
- RB_SetGL2D();
-
- tess.numIndexes = 0;
- tess.numVertexes = 0;
- tess.firstIndex = 0;
- tess.minIndex = 0;
- tess.maxIndex = 0;
-
- tess.xyz[tess.numVertexes][0] = x;
- tess.xyz[tess.numVertexes][1] = y;
- tess.xyz[tess.numVertexes][2] = 0;
- tess.xyz[tess.numVertexes][3] = 1;
- tess.texCoords[tess.numVertexes][0][0] = 0.5f / cols;
- tess.texCoords[tess.numVertexes][0][1] = 0.5f / rows;
- tess.texCoords[tess.numVertexes][1][0] = 0;
- tess.texCoords[tess.numVertexes][1][1] = 1;
- tess.numVertexes++;
-
- tess.xyz[tess.numVertexes][0] = x + w;
- tess.xyz[tess.numVertexes][1] = y;
- tess.xyz[tess.numVertexes][2] = 0;
- tess.xyz[tess.numVertexes][3] = 1;
- tess.texCoords[tess.numVertexes][0][0] = (cols - 0.5f) / cols;
- tess.texCoords[tess.numVertexes][0][1] = 0.5f / rows;
- tess.texCoords[tess.numVertexes][1][0] = 0;
- tess.texCoords[tess.numVertexes][1][1] = 1;
- tess.numVertexes++;
-
- tess.xyz[tess.numVertexes][0] = x + w;
- tess.xyz[tess.numVertexes][1] = y + h;
- tess.xyz[tess.numVertexes][2] = 0;
- tess.xyz[tess.numVertexes][3] = 1;
- tess.texCoords[tess.numVertexes][0][0] = (cols - 0.5f) / cols;
- tess.texCoords[tess.numVertexes][0][1] = (rows - 0.5f) / rows;
- tess.texCoords[tess.numVertexes][1][0] = 0;
- tess.texCoords[tess.numVertexes][1][1] = 1;
- tess.numVertexes++;
-
- tess.xyz[tess.numVertexes][0] = x;
- tess.xyz[tess.numVertexes][1] = y + h;
- tess.xyz[tess.numVertexes][2] = 0;
- tess.xyz[tess.numVertexes][3] = 1;
- tess.texCoords[tess.numVertexes][0][0] = 0.5f / cols;
- tess.texCoords[tess.numVertexes][0][1] = (rows - 0.5f) / rows;
- tess.texCoords[tess.numVertexes][1][0] = 0;
- tess.texCoords[tess.numVertexes][1][1] = 1;
- tess.numVertexes++;
-
- tess.indexes[tess.numIndexes++] = 0;
- tess.indexes[tess.numIndexes++] = 1;
- tess.indexes[tess.numIndexes++] = 2;
- tess.indexes[tess.numIndexes++] = 0;
- tess.indexes[tess.numIndexes++] = 2;
- tess.indexes[tess.numIndexes++] = 3;
- tess.minIndex = 0;
- tess.maxIndex = 3;
-
- // FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function
- RB_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD);
-
- sp = &tr.textureColorShader;
-
- GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD);
-
- GLSL_BindProgram(sp);
-
- GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
- VectorSet4(color, 1, 1, 1, 1);
- GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color);
-
- R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);
-
- //R_BindNullVBO();
- //R_BindNullIBO();
-
- tess.numIndexes = 0;
- tess.numVertexes = 0;
- tess.firstIndex = 0;
- tess.minIndex = 0;
- tess.maxIndex = 0;
-}
-
-void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
-
- GL_Bind( tr.scratchImage[client] );
-
- // if the scratchImage isn't in the format we want, specify it as a new texture
- if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
- tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
- tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
- qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
- qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
- qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
- } else {
- if (dirty) {
- // otherwise, just subimage upload it so that drivers can tell we are going to be changing
- // it and don't try and do a texture compression
- qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
- }
- }
-}
-
-
-/*
-=============
-RB_SetColor
-
-=============
-*/
-const void *RB_SetColor( const void *data ) {
- const setColorCommand_t *cmd;
-
- cmd = (const setColorCommand_t *)data;
-
- backEnd.color2D[0] = cmd->color[0] * 255;
- backEnd.color2D[1] = cmd->color[1] * 255;
- backEnd.color2D[2] = cmd->color[2] * 255;
- backEnd.color2D[3] = cmd->color[3] * 255;
-
- return (const void *)(cmd + 1);
-}
-
-/*
-=============
-RB_StretchPic
-=============
-*/
-const void *RB_StretchPic ( const void *data ) {
- const stretchPicCommand_t *cmd;
- shader_t *shader;
- int numVerts, numIndexes;
-
- cmd = (const stretchPicCommand_t *)data;
-
- // FIXME: HUGE hack
- if (glRefConfig.framebufferObject)
- {
- if (!tr.renderFbo || backEnd.framePostProcessed)
- {
- FBO_Bind(tr.screenScratchFbo);
- }
- else
- {
- FBO_Bind(tr.renderFbo);
- }
- }
-
- RB_SetGL2D();
-
- shader = cmd->shader;
- if ( shader != tess.shader ) {
- if ( tess.numIndexes ) {
- RB_EndSurface();
- }
- backEnd.currentEntity = &backEnd.entity2D;
- RB_BeginSurface( shader, 0 );
- }
-
- RB_CHECKOVERFLOW( 4, 6 );
- numVerts = tess.numVertexes;
- numIndexes = tess.numIndexes;
-
- tess.numVertexes += 4;
- tess.numIndexes += 6;
-
- tess.indexes[ numIndexes ] = numVerts + 3;
- tess.indexes[ numIndexes + 1 ] = numVerts + 0;
- tess.indexes[ numIndexes + 2 ] = numVerts + 2;
- tess.indexes[ numIndexes + 3 ] = numVerts + 2;
- tess.indexes[ numIndexes + 4 ] = numVerts + 0;
- tess.indexes[ numIndexes + 5 ] = numVerts + 1;
-
- {
- vec4_t color;
-
- VectorScale4(backEnd.color2D, 1.0f / 255.0f, color);
-
- VectorCopy4(color, tess.vertexColors[ numVerts ]);
- VectorCopy4(color, tess.vertexColors[ numVerts + 1]);
- VectorCopy4(color, tess.vertexColors[ numVerts + 2]);
- VectorCopy4(color, tess.vertexColors[ numVerts + 3 ]);
- }
-
- tess.xyz[ numVerts ][0] = cmd->x;
- tess.xyz[ numVerts ][1] = cmd->y;
- tess.xyz[ numVerts ][2] = 0;
-
- tess.texCoords[ numVerts ][0][0] = cmd->s1;
- tess.texCoords[ numVerts ][0][1] = cmd->t1;
-
- tess.xyz[ numVerts + 1 ][0] = cmd->x + cmd->w;
- tess.xyz[ numVerts + 1 ][1] = cmd->y;
- tess.xyz[ numVerts + 1 ][2] = 0;
-
- tess.texCoords[ numVerts + 1 ][0][0] = cmd->s2;
- tess.texCoords[ numVerts + 1 ][0][1] = cmd->t1;
-
- tess.xyz[ numVerts + 2 ][0] = cmd->x + cmd->w;
- tess.xyz[ numVerts + 2 ][1] = cmd->y + cmd->h;
- tess.xyz[ numVerts + 2 ][2] = 0;
-
- tess.texCoords[ numVerts + 2 ][0][0] = cmd->s2;
- tess.texCoords[ numVerts + 2 ][0][1] = cmd->t2;
-
- tess.xyz[ numVerts + 3 ][0] = cmd->x;
- tess.xyz[ numVerts + 3 ][1] = cmd->y + cmd->h;
- tess.xyz[ numVerts + 3 ][2] = 0;
-
- tess.texCoords[ numVerts + 3 ][0][0] = cmd->s1;
- tess.texCoords[ numVerts + 3 ][0][1] = cmd->t2;
-
- return (const void *)(cmd + 1);
-}
-
-
-/*
-=============
-RB_DrawSurfs
-
-=============
-*/
-const void *RB_DrawSurfs( const void *data ) {
- const drawSurfsCommand_t *cmd;
-
- // finish any 2D drawing if needed
- if ( tess.numIndexes ) {
- RB_EndSurface();
- }
-
- cmd = (const drawSurfsCommand_t *)data;
-
- backEnd.refdef = cmd->refdef;
- backEnd.viewParms = cmd->viewParms;
-
- // clear the z buffer, set the modelview, etc
- RB_BeginDrawingView ();
-
- if (glRefConfig.framebufferObject && (backEnd.viewParms.flags & VPF_DEPTHCLAMP) && glRefConfig.depthClamp)
- {
- qglEnable(GL_DEPTH_CLAMP);
- }
-
- if (glRefConfig.framebufferObject && !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL) && (r_depthPrepass->integer || (backEnd.viewParms.flags & VPF_DEPTHSHADOW)))
- {
- FBO_t *oldFbo = glState.currentFBO;
-
- backEnd.depthFill = qtrue;
- qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs );
- qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]);
- backEnd.depthFill = qfalse;
-
- if (tr.msaaResolveFbo)
- {
- // If we're using multisampling, resolve the depth first
- FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
- }
- else if (tr.renderFbo == NULL)
- {
- // If we're rendering directly to the screen, copy the depth to a texture
- GL_BindToTMU(tr.renderDepthImage, 0);
- qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, glConfig.vidWidth, glConfig.vidHeight, 0);
- }
-
- if (r_ssao->integer)
- {
- // need the depth in a texture we can do GL_LINEAR sampling on, so copy it to an HDR image
- FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, tr.hdrDepthFbo, NULL, NULL, NULL, 0);
- }
-
- if (backEnd.viewParms.flags & VPF_USESUNLIGHT)
- {
- vec4_t quadVerts[4];
- vec2_t texCoords[4];
- vec4_t box;
-
- FBO_Bind(tr.screenShadowFbo);
-
- box[0] = (backEnd.refdef.x ) * tr.screenShadowFbo->width / (float)glConfig.vidWidth;
- box[1] = (backEnd.refdef.y ) * tr.screenShadowFbo->height / (float)glConfig.vidHeight;
- box[2] = (backEnd.refdef.width ) * tr.screenShadowFbo->width / (float)glConfig.vidWidth;
- box[3] = (backEnd.refdef.height) * tr.screenShadowFbo->height / (float)glConfig.vidHeight;
-
- qglViewport(box[0], box[1], box[2], box[3]);
- qglScissor(box[0], box[1], box[2], box[3]);
-
- box[0] = (backEnd.refdef.x ) / (float)glConfig.vidWidth;
- box[1] = (backEnd.refdef.y ) / (float)glConfig.vidHeight;
- box[2] = (backEnd.refdef.x + backEnd.refdef.width ) / (float)glConfig.vidWidth;
- box[3] = (backEnd.refdef.y + backEnd.refdef.height) / (float)glConfig.vidHeight;
-
- texCoords[0][0] = box[0]; texCoords[0][1] = box[3];
- texCoords[1][0] = box[2]; texCoords[1][1] = box[3];
- texCoords[2][0] = box[2]; texCoords[2][1] = box[1];
- texCoords[3][0] = box[0]; texCoords[3][1] = box[1];
-
- box[0] = -1.0f;
- box[1] = -1.0f;
- box[2] = 1.0f;
- box[3] = 1.0f;
-
- VectorSet4(quadVerts[0], box[0], box[3], 0, 1);
- VectorSet4(quadVerts[1], box[2], box[3], 0, 1);
- VectorSet4(quadVerts[2], box[2], box[1], 0, 1);
- VectorSet4(quadVerts[3], box[0], box[1], 0, 1);
-
- GL_State( GLS_DEPTHTEST_DISABLE );
-
- GLSL_BindProgram(&tr.shadowmaskShader);
-
- GL_BindToTMU(tr.renderDepthImage, TB_COLORMAP);
- GL_BindToTMU(tr.sunShadowDepthImage[0], TB_SHADOWMAP);
- GL_BindToTMU(tr.sunShadowDepthImage[1], TB_SHADOWMAP2);
- GL_BindToTMU(tr.sunShadowDepthImage[2], TB_SHADOWMAP3);
-
- GLSL_SetUniformMatrix16(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[0]);
- GLSL_SetUniformMatrix16(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]);
- GLSL_SetUniformMatrix16(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]);
-
- GLSL_SetUniformVec3(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWORIGIN, backEnd.refdef.vieworg);
- {
- vec4_t viewInfo;
- vec3_t viewVector;
-
- float zmax = backEnd.viewParms.zFar;
- float ymax = zmax * tan(backEnd.viewParms.fovY * M_PI / 360.0f);
- float xmax = zmax * tan(backEnd.viewParms.fovX * M_PI / 360.0f);
-
- float zmin = r_znear->value;
-
- VectorScale(backEnd.refdef.viewaxis[0], zmax, viewVector);
- GLSL_SetUniformVec3(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWFORWARD, viewVector);
- VectorScale(backEnd.refdef.viewaxis[1], xmax, viewVector);
- GLSL_SetUniformVec3(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWLEFT, viewVector);
- VectorScale(backEnd.refdef.viewaxis[2], ymax, viewVector);
- GLSL_SetUniformVec3(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWUP, viewVector);
-
- VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0);
-
- GLSL_SetUniformVec4(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWINFO, viewInfo);
- }
-
-
- RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes);
- }
-
- if (r_ssao->integer)
- {
- vec4_t quadVerts[4];
- vec2_t texCoords[4];
-
- FBO_Bind(tr.quarterFbo[0]);
-
- qglViewport(0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height);
- qglScissor(0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height);
-
- VectorSet4(quadVerts[0], -1, 1, 0, 1);
- VectorSet4(quadVerts[1], 1, 1, 0, 1);
- VectorSet4(quadVerts[2], 1, -1, 0, 1);
- VectorSet4(quadVerts[3], -1, -1, 0, 1);
-
- texCoords[0][0] = 0; texCoords[0][1] = 1;
- texCoords[1][0] = 1; texCoords[1][1] = 1;
- texCoords[2][0] = 1; texCoords[2][1] = 0;
- texCoords[3][0] = 0; texCoords[3][1] = 0;
-
- GL_State( GLS_DEPTHTEST_DISABLE );
-
- GLSL_BindProgram(&tr.ssaoShader);
-
- GL_BindToTMU(tr.hdrDepthImage, TB_COLORMAP);
-
- {
- vec4_t viewInfo;
-
- float zmax = backEnd.viewParms.zFar;
- float zmin = r_znear->value;
-
- VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0);
-
- GLSL_SetUniformVec4(&tr.ssaoShader, SSAO_UNIFORM_VIEWINFO, viewInfo);
- }
-
- RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes);
-
-
- FBO_Bind(tr.quarterFbo[1]);
-
- qglViewport(0, 0, tr.quarterFbo[1]->width, tr.quarterFbo[1]->height);
- qglScissor(0, 0, tr.quarterFbo[1]->width, tr.quarterFbo[1]->height);
-
- GLSL_BindProgram(&tr.depthBlurShader[0]);
-
- GL_BindToTMU(tr.quarterImage[0], TB_COLORMAP);
- GL_BindToTMU(tr.hdrDepthImage, TB_LIGHTMAP);
-
- {
- vec4_t viewInfo;
-
- float zmax = backEnd.viewParms.zFar;
- float zmin = r_znear->value;
-
- VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0);
-
- GLSL_SetUniformVec4(&tr.depthBlurShader[0], DEPTHBLUR_UNIFORM_VIEWINFO, viewInfo);
- }
-
- RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes);
-
-
- FBO_Bind(tr.screenSsaoFbo);
-
- qglViewport(0, 0, tr.screenSsaoFbo->width, tr.screenSsaoFbo->height);
- qglScissor(0, 0, tr.screenSsaoFbo->width, tr.screenSsaoFbo->height);
-
- GLSL_BindProgram(&tr.depthBlurShader[1]);
-
- GL_BindToTMU(tr.quarterImage[1], TB_COLORMAP);
- GL_BindToTMU(tr.hdrDepthImage, TB_LIGHTMAP);
-
- {
- vec4_t viewInfo;
-
- float zmax = backEnd.viewParms.zFar;
- float zmin = r_znear->value;
-
- VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0);
-
- GLSL_SetUniformVec4(&tr.depthBlurShader[1], DEPTHBLUR_UNIFORM_VIEWINFO, viewInfo);
- }
-
-
- RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes);
- }
-
- // reset viewport and scissor
- FBO_Bind(oldFbo);
- SetViewportAndScissor();
- }
-
- if (glRefConfig.framebufferObject && (backEnd.viewParms.flags & VPF_DEPTHCLAMP) && glRefConfig.depthClamp)
- {
- qglDisable(GL_DEPTH_CLAMP);
- }
-
- if (!(backEnd.viewParms.flags & VPF_DEPTHSHADOW))
- {
- RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs );
-
- if (r_drawSun->integer)
- {
- RB_DrawSun(0.1, tr.sunShader);
- }
-
- if (r_drawSunRays->integer)
- {
- FBO_t *oldFbo = glState.currentFBO;
- FBO_Bind(tr.sunRaysFbo);
-
- qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
- qglClear( GL_COLOR_BUFFER_BIT );
-
- if (glRefConfig.occlusionQuery)
- {
- tr.sunFlareQueryActive[tr.sunFlareQueryIndex] = qtrue;
- qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, tr.sunFlareQuery[tr.sunFlareQueryIndex]);
- }
-
- RB_DrawSun(0.3, tr.sunFlareShader);
-
- if (glRefConfig.occlusionQuery)
- {
- qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
- }
-
- FBO_Bind(oldFbo);
- }
-
- // darken down any stencil shadows
- RB_ShadowFinish();
-
- // add light flares on lights that aren't obscured
- RB_RenderFlares();
- }
-
- //if (glRefConfig.framebufferObject)
- //FBO_Bind(NULL);
-
- return (const void *)(cmd + 1);
-}
-
-
-/*
-=============
-RB_DrawBuffer
-
-=============
-*/
-const void *RB_DrawBuffer( const void *data ) {
- const drawBufferCommand_t *cmd;
-
- cmd = (const drawBufferCommand_t *)data;
-
- // finish any 2D drawing if needed
- if(tess.numIndexes)
- RB_EndSurface();
-
- if (glRefConfig.framebufferObject)
- FBO_Bind(NULL);
-
- qglDrawBuffer( cmd->buffer );
-
- // clear screen for debugging
- if ( r_clear->integer ) {
- qglClearColor( 1, 0, 0.5, 1 );
- qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
- }
-
- return (const void *)(cmd + 1);
-}
-
-/*
-===============
-RB_ShowImages
-
-Draw all the images to the screen, on top of whatever
-was there. This is used to test for texture thrashing.
-
-Also called by RE_EndRegistration
-===============
-*/
-void RB_ShowImages( void ) {
- int i;
- image_t *image;
- float x, y, w, h;
- int start, end;
-
- RB_SetGL2D();
-
- qglClear( GL_COLOR_BUFFER_BIT );
-
- qglFinish();
-
- start = ri.Milliseconds();
-
- for ( i=0 ; i<tr.numImages ; i++ ) {
- image = tr.images[i];
-
- w = glConfig.vidWidth / 20;
- h = glConfig.vidHeight / 15;
- x = i % 20 * w;
- y = i / 20 * h;
-
- // show in proportional size in mode 2
- if ( r_showImages->integer == 2 ) {
- w *= image->uploadWidth / 512.0f;
- h *= image->uploadHeight / 512.0f;
- }
-
- {
- vec4_t quadVerts[4];
-
- GL_Bind(image);
-
- VectorSet4(quadVerts[0], x, y, 0, 1);
- VectorSet4(quadVerts[1], x + w, y, 0, 1);
- VectorSet4(quadVerts[2], x + w, y + h, 0, 1);
- VectorSet4(quadVerts[3], x, y + h, 0, 1);
-
- RB_InstantQuad(quadVerts);
- }
- }
-
- qglFinish();
-
- end = ri.Milliseconds();
- ri.Printf( PRINT_ALL, "%i msec to draw all images\n", end - start );
-
-}
-
-/*
-=============
-RB_ColorMask
-
-=============
-*/
-const void *RB_ColorMask(const void *data)
-{
- const colorMaskCommand_t *cmd = data;
-
- // finish any 2D drawing if needed
- if(tess.numIndexes)
- RB_EndSurface();
-
- if (glRefConfig.framebufferObject)
- {
- // reverse color mask, so 0 0 0 0 is the default
- backEnd.colorMask[0] = !cmd->rgba[0];
- backEnd.colorMask[1] = !cmd->rgba[1];
- backEnd.colorMask[2] = !cmd->rgba[2];
- backEnd.colorMask[3] = !cmd->rgba[3];
- }
-
- qglColorMask(cmd->rgba[0], cmd->rgba[1], cmd->rgba[2], cmd->rgba[3]);
-
- return (const void *)(cmd + 1);
-}
-
-/*
-=============
-RB_ClearDepth
-
-=============
-*/
-const void *RB_ClearDepth(const void *data)
-{
- const clearDepthCommand_t *cmd = data;
-
- // finish any 2D drawing if needed
- if(tess.numIndexes)
- RB_EndSurface();
-
- // texture swapping test
- if (r_showImages->integer)
- RB_ShowImages();
-
- if (glRefConfig.framebufferObject)
- {
- if (!tr.renderFbo || backEnd.framePostProcessed)
- {
- FBO_Bind(tr.screenScratchFbo);
- }
- else
- {
- FBO_Bind(tr.renderFbo);
- }
- }
-
- qglClear(GL_DEPTH_BUFFER_BIT);
-
- // if we're doing MSAA, clear the depth texture for the resolve buffer
- if (tr.msaaResolveFbo)
- {
- FBO_Bind(tr.msaaResolveFbo);
- qglClear(GL_DEPTH_BUFFER_BIT);
- }
-
-
- return (const void *)(cmd + 1);
-}
-
-/*
-=============
-RB_SwapBuffers
-
-=============
-*/
-const void *RB_SwapBuffers( const void *data ) {
- const swapBuffersCommand_t *cmd;
-
- // finish any 2D drawing if needed
- if ( tess.numIndexes ) {
- RB_EndSurface();
- }
-
- // texture swapping test
- if ( r_showImages->integer ) {
- RB_ShowImages();
- }
-
- cmd = (const swapBuffersCommand_t *)data;
-
- // we measure overdraw by reading back the stencil buffer and
- // counting up the number of increments that have happened
- if ( r_measureOverdraw->integer ) {
- int i;
- long sum = 0;
- unsigned char *stencilReadback;
-
- stencilReadback = ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight );
- qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback );
-
- for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ ) {
- sum += stencilReadback[i];
- }
-
- backEnd.pc.c_overDraw += sum;
- ri.Hunk_FreeTempMemory( stencilReadback );
- }
-
- if (glRefConfig.framebufferObject)
- {
- if (!backEnd.framePostProcessed)
- {
- if (tr.msaaResolveFbo && r_hdr->integer)
- {
- // Resolving an RGB16F MSAA FBO to the screen messes with the brightness, so resolve to an RGB16F FBO first
- FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
- FBO_FastBlit(tr.msaaResolveFbo, NULL, tr.screenScratchFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
- }
- else if (tr.renderFbo)
- {
- FBO_FastBlit(tr.renderFbo, NULL, tr.screenScratchFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
- }
- }
-
- if (tr.screenScratchFbo)
- {
- vec4_t color;
-
- color[0] =
- color[1] =
- color[2] = pow(2, tr.overbrightBits); //exp2(tr.overbrightBits);
- color[3] = 1.0f;
-
- // turn off colormask when copying final image
- if (backEnd.colorMask[0] || backEnd.colorMask[1] || backEnd.colorMask[2] || backEnd.colorMask[3])
- qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-
- FBO_Blit(tr.screenScratchFbo, NULL, NULL, NULL, NULL, NULL, color, 0);
-
- if (backEnd.colorMask[0] || backEnd.colorMask[1] || backEnd.colorMask[2] || backEnd.colorMask[3])
- qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]);
- }
- }
-
- if ( !glState.finishCalled ) {
- qglFinish();
- }
-
- GLimp_LogComment( "***************** RB_SwapBuffers *****************\n\n\n" );
-
- GLimp_EndFrame();
-
- backEnd.framePostProcessed = qfalse;
- backEnd.projection2D = qfalse;
-
- return (const void *)(cmd + 1);
-}
-
-/*
-=============
-RB_CapShadowMap
-
-=============
-*/
-const void *RB_CapShadowMap(const void *data)
-{
- const capShadowmapCommand_t *cmd = data;
-
- // finish any 2D drawing if needed
- if(tess.numIndexes)
- RB_EndSurface();
-
- if (cmd->map != -1)
- {
- GL_SelectTexture(0);
- if (cmd->cubeSide != -1)
- {
- GL_BindCubemap(tr.shadowCubemaps[cmd->map]);
- qglCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cmd->cubeSide, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0);
- }
- else
- {
- GL_Bind(tr.pshadowMaps[cmd->map]);
- qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0);
- }
- }
-
- return (const void *)(cmd + 1);
-}
-
-
-
-/*
-=============
-RB_PostProcess
-
-=============
-*/
-const void *RB_PostProcess(const void *data)
-{
- const postProcessCommand_t *cmd = data;
- FBO_t *srcFbo;
- qboolean autoExposure;
-
- // finish any 2D drawing if needed
- if(tess.numIndexes)
- RB_EndSurface();
-
- if (!glRefConfig.framebufferObject || !r_postProcess->integer)
- {
- // do nothing
- return (const void *)(cmd + 1);
- }
-
- srcFbo = tr.renderFbo;
- if (tr.msaaResolveFbo)
- {
- // Resolve the MSAA before anything else
- FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
- srcFbo = tr.msaaResolveFbo;
- }
-
- if (r_ssao->integer)
- {
- FBO_BlitFromTexture(tr.screenSsaoImage, NULL, NULL, srcFbo, NULL, NULL, NULL, GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO);
- }
-
- if (srcFbo)
- {
- if (r_hdr->integer && (r_toneMap->integer || r_forceToneMap->integer))
- {
- autoExposure = r_autoExposure->integer || r_forceAutoExposure->integer;
- RB_ToneMap(srcFbo, autoExposure);
- }
- else if (r_cameraExposure->value == 0.0f)
- {
- FBO_FastBlit(srcFbo, NULL, tr.screenScratchFbo, NULL, GL_COLOR_BUFFER_BIT, GL_NEAREST);
- }
- else
- {
- vec4_t color;
-
- color[0] =
- color[1] =
- color[2] = pow(2, r_cameraExposure->value); //exp2(r_cameraExposure->value);
- color[3] = 1.0f;
-
- FBO_Blit(srcFbo, NULL, NULL, tr.screenScratchFbo, NULL, NULL, color, 0);
- }
- }
-
- if (r_drawSunRays->integer)
- RB_SunRays();
-
- if (1)
- RB_BokehBlur(backEnd.refdef.blurFactor);
- else
- RB_GaussianBlur(backEnd.refdef.blurFactor);
-
- if (0)
- {
- vec4i_t dstBox;
- VectorSet4(dstBox, 0, 0, 128, 128);
- FBO_BlitFromTexture(tr.sunShadowDepthImage[0], NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
- VectorSet4(dstBox, 128, 0, 128, 128);
- FBO_BlitFromTexture(tr.sunShadowDepthImage[1], NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
- VectorSet4(dstBox, 256, 0, 128, 128);
- FBO_BlitFromTexture(tr.sunShadowDepthImage[2], NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
- }
-
- if (0)
- {
- vec4i_t dstBox;
- VectorSet4(dstBox, 256, glConfig.vidHeight - 256, 256, 256);
- FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
- VectorSet4(dstBox, 512, glConfig.vidHeight - 256, 256, 256);
- FBO_BlitFromTexture(tr.screenShadowImage, NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
- }
-
- if (0)
- {
- vec4i_t dstBox;
- VectorSet4(dstBox, 256, glConfig.vidHeight - 256, 256, 256);
- FBO_BlitFromTexture(tr.sunRaysImage, NULL, NULL, tr.screenScratchFbo, dstBox, NULL, NULL, 0);
- }
-
- backEnd.framePostProcessed = qtrue;
-
- return (const void *)(cmd + 1);
-}
-
-/*
-====================
-RB_ExecuteRenderCommands
-====================
-*/
-void RB_ExecuteRenderCommands( const void *data ) {
- int t1, t2;
-
- t1 = ri.Milliseconds ();
-
- while ( 1 ) {
- data = PADP(data, sizeof(void *));
-
- switch ( *(const int *)data ) {
- case RC_SET_COLOR:
- data = RB_SetColor( data );
- break;
- case RC_STRETCH_PIC:
- data = RB_StretchPic( data );
- break;
- case RC_DRAW_SURFS:
- data = RB_DrawSurfs( data );
- break;
- case RC_DRAW_BUFFER:
- data = RB_DrawBuffer( data );
- break;
- case RC_SWAP_BUFFERS:
- data = RB_SwapBuffers( data );
- break;
- case RC_SCREENSHOT:
- data = RB_TakeScreenshotCmd( data );
- break;
- case RC_VIDEOFRAME:
- data = RB_TakeVideoFrameCmd( data );
- break;
- case RC_COLORMASK:
- data = RB_ColorMask(data);
- break;
- case RC_CLEARDEPTH:
- data = RB_ClearDepth(data);
- break;
- case RC_CAPSHADOWMAP:
- data = RB_CapShadowMap(data);
- break;
- case RC_POSTPROCESS:
- data = RB_PostProcess(data);
- break;
- case RC_END_OF_LIST:
- default:
- // finish any 2D drawing if needed
- if(tess.numIndexes)
- RB_EndSurface();
-
- // stop rendering
- t2 = ri.Milliseconds ();
- backEnd.pc.msec = t2 - t1;
- return;
- }
- }
-
-}
diff --git a/src/rend2/tr_bsp.c b/src/rend2/tr_bsp.c
deleted file mode 100644
index c14245b8..00000000
--- a/src/rend2/tr_bsp.c
+++ /dev/null
@@ -1,3370 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_map.c
-
-#include "tr_local.h"
-
-/*
-
-Loads and prepares a map file for scene rendering.
-
-A single entry point:
-
-void RE_LoadWorldMap( const char *name );
-
-*/
-
-static world_t s_worldData;
-static byte *fileBase;
-
-int c_subdivisions;
-int c_gridVerts;
-
-//===============================================================================
-
-static void HSVtoRGB( float h, float s, float v, float rgb[3] )
-{
- int i;
- float f;
- float p, q, t;
-
- h *= 5;
-
- i = floor( h );
- f = h - i;
-
- p = v * ( 1 - s );
- q = v * ( 1 - s * f );
- t = v * ( 1 - s * ( 1 - f ) );
-
- switch ( i )
- {
- case 0:
- rgb[0] = v;
- rgb[1] = t;
- rgb[2] = p;
- break;
- case 1:
- rgb[0] = q;
- rgb[1] = v;
- rgb[2] = p;
- break;
- case 2:
- rgb[0] = p;
- rgb[1] = v;
- rgb[2] = t;
- break;
- case 3:
- rgb[0] = p;
- rgb[1] = q;
- rgb[2] = v;
- break;
- case 4:
- rgb[0] = t;
- rgb[1] = p;
- rgb[2] = v;
- break;
- case 5:
- rgb[0] = v;
- rgb[1] = p;
- rgb[2] = q;
- break;
- }
-}
-
-/*
-===============
-R_ColorShiftLightingBytes
-
-===============
-*/
-static void R_ColorShiftLightingBytes( byte in[4], byte out[4] ) {
- int shift, r, g, b;
-
- // shift the color data based on overbright range
- shift = r_mapOverBrightBits->integer - tr.overbrightBits;
-
- // shift the data based on overbright range
- r = in[0] << shift;
- g = in[1] << shift;
- b = in[2] << shift;
-
- // normalize by color instead of saturating to white
- if ( ( r | g | b ) > 255 ) {
- int max;
-
- max = r > g ? r : g;
- max = max > b ? max : b;
- r = r * 255 / max;
- g = g * 255 / max;
- b = b * 255 / max;
- }
-
- out[0] = r;
- out[1] = g;
- out[2] = b;
- out[3] = in[3];
-}
-
-
-/*
-===============
-R_ColorShiftLightingBytes
-
-===============
-*/
-static void R_ColorShiftLightingFloats(float in[4], float out[4], float scale )
-{
- scale *= pow(2.0f, r_mapOverBrightBits->integer - tr.overbrightBits);
-
- out[0] = in[0] * scale;
- out[1] = in[1] * scale;
- out[2] = in[2] * scale;
- out[3] = in[3];
-}
-
-
-void ColorToRGBE(const vec3_t color, unsigned char rgbe[4])
-{
- vec3_t sample;
- float maxComponent;
- int e;
-
- VectorCopy(color, sample);
-
- maxComponent = sample[0];
- if(sample[1] > maxComponent)
- maxComponent = sample[1];
- if(sample[2] > maxComponent)
- maxComponent = sample[2];
-
- if(maxComponent < 1e-32)
- {
- rgbe[0] = 0;
- rgbe[1] = 0;
- rgbe[2] = 0;
- rgbe[3] = 0;
- }
- else
- {
-#if 0
- maxComponent = frexp(maxComponent, &e) * 255.0 / maxComponent;
- rgbe[0] = (unsigned char) (sample[0] * maxComponent);
- rgbe[1] = (unsigned char) (sample[1] * maxComponent);
- rgbe[2] = (unsigned char) (sample[2] * maxComponent);
- rgbe[3] = (unsigned char) (e + 128);
-#else
- e = ceil(log(maxComponent) / log(2.0f));//ceil(log2(maxComponent));
- VectorScale(sample, 1.0 / pow(2.0f, e)/*exp2(e)*/, sample);
-
- rgbe[0] = (unsigned char) (sample[0] * 255);
- rgbe[1] = (unsigned char) (sample[1] * 255);
- rgbe[2] = (unsigned char) (sample[2] * 255);
- rgbe[3] = (unsigned char) (e + 128);
-#endif
- }
-}
-
-
-void ColorToRGBA16F(const vec3_t color, unsigned short rgba16f[4])
-{
- rgba16f[0] = FloatToHalf(color[0]);
- rgba16f[1] = FloatToHalf(color[1]);
- rgba16f[2] = FloatToHalf(color[2]);
- rgba16f[3] = FloatToHalf(1.0f);
-}
-
-
-/*
-===============
-R_LoadLightmaps
-
-===============
-*/
-#define DEFAULT_LIGHTMAP_SIZE 128
-#define MAX_LIGHTMAP_PAGES 2
-static void R_LoadLightmaps( lump_t *l, lump_t *surfs ) {
- byte *buf, *buf_p;
- dsurface_t *surf;
- int len;
- byte *image;
- int i, j, numLightmaps, textureInternalFormat = 0;
- float maxIntensity = 0;
- double sumIntensity = 0;
-
- len = l->filelen;
- if ( !len ) {
- return;
- }
- buf = fileBase + l->fileofs;
-
- // we are about to upload textures
- R_IssuePendingRenderCommands();
-
- tr.lightmapSize = DEFAULT_LIGHTMAP_SIZE;
- numLightmaps = len / (tr.lightmapSize * tr.lightmapSize * 3);
-
- // check for deluxe mapping
- if (numLightmaps <= 1)
- {
- tr.worldDeluxeMapping = qfalse;
- }
- else
- {
- tr.worldDeluxeMapping = qtrue;
- for( i = 0, surf = (dsurface_t *)(fileBase + surfs->fileofs);
- i < surfs->filelen / sizeof(dsurface_t); i++, surf++ ) {
- int lightmapNum = LittleLong( surf->lightmapNum );
-
- if ( lightmapNum >= 0 && (lightmapNum & 1) != 0 ) {
- tr.worldDeluxeMapping = qfalse;
- break;
- }
- }
- }
-
- image = ri.Malloc(tr.lightmapSize * tr.lightmapSize * 4 * 2);
-
- if (tr.worldDeluxeMapping)
- numLightmaps >>= 1;
-
- if(numLightmaps == 1)
- {
- //FIXME: HACK: maps with only one lightmap turn up fullbright for some reason.
- //this avoids this, but isn't the correct solution.
- numLightmaps++;
- }
- else if (r_mergeLightmaps->integer && numLightmaps >= 1024 )
- {
- // FIXME: fat light maps don't support more than 1024 light maps
- ri.Printf(PRINT_WARNING, "WARNING: number of lightmaps > 1024\n");
- numLightmaps = 1024;
- }
-
- // use fat lightmaps of an appropriate size
- if (r_mergeLightmaps->integer)
- {
- tr.fatLightmapSize = 512;
- tr.fatLightmapStep = tr.fatLightmapSize / tr.lightmapSize;
-
- // at most MAX_LIGHTMAP_PAGES
- while (tr.fatLightmapStep * tr.fatLightmapStep * MAX_LIGHTMAP_PAGES < numLightmaps && tr.fatLightmapSize != glConfig.maxTextureSize )
- {
- tr.fatLightmapSize <<= 1;
- tr.fatLightmapStep = tr.fatLightmapSize / tr.lightmapSize;
- }
-
- tr.numLightmaps = numLightmaps / (tr.fatLightmapStep * tr.fatLightmapStep);
-
- if (numLightmaps % (tr.fatLightmapStep * tr.fatLightmapStep) != 0)
- tr.numLightmaps++;
- }
- else
- {
- tr.numLightmaps = numLightmaps;
- }
-
- tr.lightmaps = ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low );
-
- if (tr.worldDeluxeMapping)
- {
- tr.deluxemaps = ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low );
- }
-
- if (r_hdr->integer && glRefConfig.textureFloat && glRefConfig.halfFloatPixel)
- textureInternalFormat = GL_RGBA16F_ARB;
-
- if (r_mergeLightmaps->integer)
- {
- for (i = 0; i < tr.numLightmaps; i++)
- {
- tr.lightmaps[i] = R_CreateImage(va("_fatlightmap%d", i), NULL, tr.fatLightmapSize, tr.fatLightmapSize, IMGTYPE_COLORALPHA, IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, textureInternalFormat );
-
- if (tr.worldDeluxeMapping)
- {
- tr.deluxemaps[i] = R_CreateImage(va("_fatdeluxemap%d", i), NULL, tr.fatLightmapSize, tr.fatLightmapSize, IMGTYPE_DELUXE, IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, 0 );
- }
- }
- }
-
- for(i = 0; i < numLightmaps; i++)
- {
- int xoff = 0, yoff = 0;
- int lightmapnum = i;
- // expand the 24 bit on-disk to 32 bit
-
- if (r_mergeLightmaps->integer)
- {
- int lightmaponpage = i % (tr.fatLightmapStep * tr.fatLightmapStep);
- xoff = (lightmaponpage % tr.fatLightmapStep) * tr.lightmapSize;
- yoff = (lightmaponpage / tr.fatLightmapStep) * tr.lightmapSize;
-
- lightmapnum /= (tr.fatLightmapStep * tr.fatLightmapStep);
- }
-
- // if (tr.worldLightmapping)
- {
- char filename[MAX_QPATH];
- byte *hdrLightmap = NULL;
- float lightScale = 1.0f;
- int size = 0;
-
- // look for hdr lightmaps
- if (r_hdr->integer)
- {
- Com_sprintf( filename, sizeof( filename ), "maps/%s/lm_%04d.hdr", s_worldData.baseName, i * (tr.worldDeluxeMapping ? 2 : 1) );
- //ri.Printf(PRINT_ALL, "looking for %s\n", filename);
-
- size = ri.FS_ReadFile(filename, (void **)&hdrLightmap);
- }
-
- if (hdrLightmap)
- {
- byte *p = hdrLightmap;
- //ri.Printf(PRINT_ALL, "found!\n");
-
- /* FIXME: don't just skip over this header and actually parse it */
- while (size && !(*p == '\n' && *(p+1) == '\n'))
- {
- size--;
- p++;
- }
-
- if (!size)
- ri.Error(ERR_DROP, "Bad header for %s!\n", filename);
-
- size -= 2;
- p += 2;
-
- while (size && !(*p == '\n'))
- {
- size--;
- p++;
- }
-
- size--;
- p++;
-
- buf_p = (byte *)p;
-
-#if 0 // HDRFILE_RGBE
- if (size != tr.lightmapSize * tr.lightmapSize * 4)
- ri.Error(ERR_DROP, "Bad size for %s (%i)!\n", filename, size);
-#else // HDRFILE_FLOAT
- if (size != tr.lightmapSize * tr.lightmapSize * 12)
- ri.Error(ERR_DROP, "Bad size for %s (%i)!\n", filename, size);
-#endif
- }
- else
- {
- if (tr.worldDeluxeMapping)
- buf_p = buf + (i * 2) * tr.lightmapSize * tr.lightmapSize * 3;
- else
- buf_p = buf + i * tr.lightmapSize * tr.lightmapSize * 3;
- }
-
- lightScale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits - 8); //exp2(r_mapOverBrightBits->integer - tr.overbrightBits - 8);
-
- for ( j = 0 ; j < tr.lightmapSize * tr.lightmapSize; j++ )
- {
- if (r_hdr->integer)
- {
- float color[3];
-
- if (hdrLightmap)
- {
-#if 0 // HDRFILE_RGBE
- float exponent = exp2(buf_p[j*4+3] - 128);
-
- color[0] = buf_p[j*4+0] * exponent;
- color[1] = buf_p[j*4+1] * exponent;
- color[2] = buf_p[j*4+2] * exponent;
-#else // HDRFILE_FLOAT
- memcpy(color, &buf_p[j*12], 12);
-
- color[0] = LittleFloat(color[0]);
- color[1] = LittleFloat(color[1]);
- color[2] = LittleFloat(color[2]);
-#endif
- }
- else
- {
- //hack: convert LDR lightmap to HDR one
- color[0] = (buf_p[j*3+0] + 1.0f);
- color[1] = (buf_p[j*3+1] + 1.0f);
- color[2] = (buf_p[j*3+2] + 1.0f);
-
- // if under an arbitrary value (say 12) grey it out
- // this prevents weird splotches in dimly lit areas
- if (color[0] + color[1] + color[2] < 12.0f)
- {
- float avg = (color[0] + color[1] + color[2]) * 0.3333f;
- color[0] = avg;
- color[1] = avg;
- color[2] = avg;
- }
- }
-
- VectorScale(color, lightScale, color);
-
- if (glRefConfig.textureFloat && glRefConfig.halfFloatPixel)
- ColorToRGBA16F(color, (unsigned short *)(&image[j*8]));
- else
- ColorToRGBE(color, &image[j*4]);
- }
- else
- {
- if ( r_lightmap->integer == 2 )
- { // color code by intensity as development tool (FIXME: check range)
- float r = buf_p[j*3+0];
- float g = buf_p[j*3+1];
- float b = buf_p[j*3+2];
- float intensity;
- float out[3] = {0.0, 0.0, 0.0};
-
- intensity = 0.33f * r + 0.685f * g + 0.063f * b;
-
- if ( intensity > 255 )
- intensity = 1.0f;
- else
- intensity /= 255.0f;
-
- if ( intensity > maxIntensity )
- maxIntensity = intensity;
-
- HSVtoRGB( intensity, 1.00, 0.50, out );
-
- image[j*4+0] = out[0] * 255;
- image[j*4+1] = out[1] * 255;
- image[j*4+2] = out[2] * 255;
- image[j*4+3] = 255;
-
- sumIntensity += intensity;
- }
- else
- {
- R_ColorShiftLightingBytes( &buf_p[j*3], &image[j*4] );
- image[j*4+3] = 255;
- }
- }
- }
-
- if (r_mergeLightmaps->integer)
- R_UpdateSubImage(tr.lightmaps[lightmapnum], image, xoff, yoff, tr.lightmapSize, tr.lightmapSize);
- else
- tr.lightmaps[i] = R_CreateImage(va("*lightmap%d", i), image, tr.lightmapSize, tr.lightmapSize, IMGTYPE_COLORALPHA, IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, textureInternalFormat );
-
- if (hdrLightmap)
- ri.FS_FreeFile(hdrLightmap);
- }
-
- if (tr.worldDeluxeMapping)
- {
- buf_p = buf + (i * 2 + 1) * tr.lightmapSize * tr.lightmapSize * 3;
-
- for ( j = 0 ; j < tr.lightmapSize * tr.lightmapSize; j++ ) {
- image[j*4+0] = buf_p[j*3+0];
- image[j*4+1] = buf_p[j*3+1];
- image[j*4+2] = buf_p[j*3+2];
-
- // make 0,0,0 into 127,127,127
- if ((image[j*4+0] == 0) && (image[j*4+0] == 0) && (image[j*4+2] == 0))
- {
- image[j*4+0] =
- image[j*4+1] =
- image[j*4+2] = 127;
- }
-
- image[j*4+3] = 255;
- }
-
- if (r_mergeLightmaps->integer)
- {
- R_UpdateSubImage(tr.deluxemaps[lightmapnum], image, xoff, yoff, tr.lightmapSize, tr.lightmapSize );
- }
- else
- {
- tr.deluxemaps[i] = R_CreateImage(va("*deluxemap%d", i), image, tr.lightmapSize, tr.lightmapSize, IMGTYPE_DELUXE, IMGFLAG_NOLIGHTSCALE | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, 0 );
- }
- }
- }
-
- if ( r_lightmap->integer == 2 ) {
- ri.Printf( PRINT_ALL, "Brightest lightmap value: %d\n", ( int ) ( maxIntensity * 255 ) );
- }
-
- ri.Free(image);
-}
-
-
-static float FatPackU(float input, int lightmapnum)
-{
- if (lightmapnum < 0)
- return input;
-
- if (tr.worldDeluxeMapping)
- lightmapnum >>= 1;
-
- lightmapnum %= (tr.fatLightmapStep * tr.fatLightmapStep);
-
- if(tr.fatLightmapSize > 0)
- {
- int x = lightmapnum % tr.fatLightmapStep;
-
- return (input / ((float)tr.fatLightmapStep)) + ((1.0 / ((float)tr.fatLightmapStep)) * (float)x);
- }
-
- return input;
-}
-
-static float FatPackV(float input, int lightmapnum)
-{
- if (lightmapnum < 0)
- return input;
-
- if (tr.worldDeluxeMapping)
- lightmapnum >>= 1;
-
- lightmapnum %= (tr.fatLightmapStep * tr.fatLightmapStep);
-
- if(tr.fatLightmapSize > 0)
- {
- int y = lightmapnum / tr.fatLightmapStep;
-
- return (input / ((float)tr.fatLightmapStep)) + ((1.0 / ((float)tr.fatLightmapStep)) * (float)y);
- }
-
- return input;
-}
-
-
-static int FatLightmap(int lightmapnum)
-{
- if (lightmapnum < 0)
- return lightmapnum;
-
- if (tr.worldDeluxeMapping)
- lightmapnum >>= 1;
-
- if (tr.fatLightmapSize > 0)
- {
- return lightmapnum / (tr.fatLightmapStep * tr.fatLightmapStep);
- }
-
- return lightmapnum;
-}
-
-/*
-=================
-RE_SetWorldVisData
-
-This is called by the clipmodel subsystem so we can share the 1.8 megs of
-space in big maps...
-=================
-*/
-void RE_SetWorldVisData( const byte *vis ) {
- tr.externalVisData = vis;
-}
-
-
-/*
-=================
-R_LoadVisibility
-=================
-*/
-static void R_LoadVisibility( lump_t *l ) {
- int len;
- byte *buf;
-
- len = ( s_worldData.numClusters + 63 ) & ~63;
- s_worldData.novis = ri.Hunk_Alloc( len, h_low );
- Com_Memset( s_worldData.novis, 0xff, len );
-
- len = l->filelen;
- if ( !len ) {
- return;
- }
- buf = fileBase + l->fileofs;
-
- s_worldData.numClusters = LittleLong( ((int *)buf)[0] );
- s_worldData.clusterBytes = LittleLong( ((int *)buf)[1] );
-
- // CM_Load should have given us the vis data to share, so
- // we don't need to allocate another copy
- if ( tr.externalVisData ) {
- s_worldData.vis = tr.externalVisData;
- } else {
- byte *dest;
-
- dest = ri.Hunk_Alloc( len - 8, h_low );
- Com_Memcpy( dest, buf + 8, len - 8 );
- s_worldData.vis = dest;
- }
-}
-
-//===============================================================================
-
-
-/*
-===============
-ShaderForShaderNum
-===============
-*/
-static shader_t *ShaderForShaderNum( int shaderNum, int lightmapNum ) {
- shader_t *shader;
- dshader_t *dsh;
-
- int _shaderNum = LittleLong( shaderNum );
- if ( _shaderNum < 0 || _shaderNum >= s_worldData.numShaders ) {
- ri.Error( ERR_DROP, "ShaderForShaderNum: bad num %i", _shaderNum );
- }
- dsh = &s_worldData.shaders[ _shaderNum ];
-
- if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) {
- lightmapNum = LIGHTMAP_BY_VERTEX;
- }
-
- if ( r_fullbright->integer ) {
- lightmapNum = LIGHTMAP_WHITEIMAGE;
- }
-
- shader = R_FindShader( dsh->shader, lightmapNum, qtrue );
-
- // if the shader had errors, just use default shader
- if ( shader->defaultShader ) {
- return tr.defaultShader;
- }
-
- return shader;
-}
-
-/*
-===============
-ParseFace
-===============
-*/
-static void ParseFace( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf, int *indexes ) {
- int i, j;
- srfSurfaceFace_t *cv;
- srfTriangle_t *tri;
- int numVerts, numTriangles, badTriangles;
- int realLightmapNum;
-
- realLightmapNum = LittleLong( ds->lightmapNum );
-
- // get fog volume
- surf->fogIndex = LittleLong( ds->fogNum ) + 1;
-
- // get shader value
- surf->shader = ShaderForShaderNum( ds->shaderNum, FatLightmap(realLightmapNum) );
- if ( r_singleShader->integer && !surf->shader->isSky ) {
- surf->shader = tr.defaultShader;
- }
-
- numVerts = LittleLong(ds->numVerts);
- if (numVerts > MAX_FACE_POINTS) {
- ri.Printf( PRINT_WARNING, "WARNING: MAX_FACE_POINTS exceeded: %i\n", numVerts);
- numVerts = MAX_FACE_POINTS;
- surf->shader = tr.defaultShader;
- }
-
- numTriangles = LittleLong(ds->numIndexes) / 3;
-
- //cv = ri.Hunk_Alloc(sizeof(*cv), h_low);
- cv = (void *)surf->data;
- cv->surfaceType = SF_FACE;
-
- cv->numTriangles = numTriangles;
- cv->triangles = ri.Hunk_Alloc(numTriangles * sizeof(cv->triangles[0]), h_low);
-
- cv->numVerts = numVerts;
- cv->verts = ri.Hunk_Alloc(numVerts * sizeof(cv->verts[0]), h_low);
-
- // copy vertexes
- surf->cullinfo.type = CULLINFO_PLANE | CULLINFO_BOX;
- ClearBounds(surf->cullinfo.bounds[0], surf->cullinfo.bounds[1]);
- verts += LittleLong(ds->firstVert);
- for(i = 0; i < numVerts; i++)
- {
- vec4_t color;
-
- for(j = 0; j < 3; j++)
- {
- cv->verts[i].xyz[j] = LittleFloat(verts[i].xyz[j]);
- cv->verts[i].normal[j] = LittleFloat(verts[i].normal[j]);
- }
- AddPointToBounds(cv->verts[i].xyz, surf->cullinfo.bounds[0], surf->cullinfo.bounds[1]);
- for(j = 0; j < 2; j++)
- {
- cv->verts[i].st[j] = LittleFloat(verts[i].st[j]);
- //cv->verts[i].lightmap[j] = LittleFloat(verts[i].lightmap[j]);
- }
- cv->verts[i].lightmap[0] = FatPackU(LittleFloat(verts[i].lightmap[0]), realLightmapNum);
- cv->verts[i].lightmap[1] = FatPackV(LittleFloat(verts[i].lightmap[1]), realLightmapNum);
-
- if (hdrVertColors)
- {
- color[0] = hdrVertColors[(ds->firstVert + i) * 3 ];
- color[1] = hdrVertColors[(ds->firstVert + i) * 3 + 1];
- color[2] = hdrVertColors[(ds->firstVert + i) * 3 + 2];
- }
- else
- {
- //hack: convert LDR vertex colors to HDR
- if (r_hdr->integer)
- {
- color[0] = verts[i].color[0] + 1.0f;
- color[1] = verts[i].color[1] + 1.0f;
- color[2] = verts[i].color[2] + 1.0f;
- }
- else
- {
- color[0] = verts[i].color[0];
- color[1] = verts[i].color[1];
- color[2] = verts[i].color[2];
- }
-
- }
- color[3] = verts[i].color[3] / 255.0f;
-
- R_ColorShiftLightingFloats( color, cv->verts[i].vertexColors, 1.0f / 255.0f );
- }
-
- // copy triangles
- badTriangles = 0;
- indexes += LittleLong(ds->firstIndex);
- for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
- {
- for(j = 0; j < 3; j++)
- {
- tri->indexes[j] = LittleLong(indexes[i * 3 + j]);
-
- if(tri->indexes[j] < 0 || tri->indexes[j] >= numVerts)
- {
- ri.Error(ERR_DROP, "Bad index in face surface");
- }
- }
-
- if ((tri->indexes[0] == tri->indexes[1]) || (tri->indexes[1] == tri->indexes[2]) || (tri->indexes[0] == tri->indexes[2]))
- {
- tri--;
- badTriangles++;
- }
- }
-
- if (badTriangles)
- {
- ri.Printf(PRINT_WARNING, "Face has bad triangles, originally shader %s %d tris %d verts, now %d tris\n", surf->shader->name, numTriangles, numVerts, numTriangles - badTriangles);
- cv->numTriangles -= badTriangles;
- }
-
- // take the plane information from the lightmap vector
- for ( i = 0 ; i < 3 ; i++ ) {
- cv->plane.normal[i] = LittleFloat( ds->lightmapVecs[2][i] );
- }
- cv->plane.dist = DotProduct( cv->verts[0].xyz, cv->plane.normal );
- SetPlaneSignbits( &cv->plane );
- cv->plane.type = PlaneTypeForNormal( cv->plane.normal );
- surf->cullinfo.plane = cv->plane;
-
- surf->data = (surfaceType_t *)cv;
-
-#ifdef USE_VERT_TANGENT_SPACE
- // Tr3B - calc tangent spaces
- {
- srfVert_t *dv[3];
-
- for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
- {
- dv[0] = &cv->verts[tri->indexes[0]];
- dv[1] = &cv->verts[tri->indexes[1]];
- dv[2] = &cv->verts[tri->indexes[2]];
-
- R_CalcTangentVectors(dv);
- }
- }
-#endif
-}
-
-
-/*
-===============
-ParseMesh
-===============
-*/
-static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf ) {
- srfGridMesh_t *grid;
- int i, j;
- int width, height, numPoints;
- srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE];
- vec3_t bounds[2];
- vec3_t tmpVec;
- static surfaceType_t skipData = SF_SKIP;
- int realLightmapNum;
-
- realLightmapNum = LittleLong( ds->lightmapNum );
-
- // get fog volume
- surf->fogIndex = LittleLong( ds->fogNum ) + 1;
-
- // get shader value
- surf->shader = ShaderForShaderNum( ds->shaderNum, FatLightmap(realLightmapNum) );
- if ( r_singleShader->integer && !surf->shader->isSky ) {
- surf->shader = tr.defaultShader;
- }
-
- // we may have a nodraw surface, because they might still need to
- // be around for movement clipping
- if ( s_worldData.shaders[ LittleLong( ds->shaderNum ) ].surfaceFlags & SURF_NODRAW ) {
- surf->data = &skipData;
- return;
- }
-
- width = LittleLong( ds->patchWidth );
- height = LittleLong( ds->patchHeight );
-
- if(width < 0 || width > MAX_PATCH_SIZE || height < 0 || height > MAX_PATCH_SIZE)
- ri.Error(ERR_DROP, "ParseMesh: bad size");
-
- verts += LittleLong( ds->firstVert );
- numPoints = width * height;
- for(i = 0; i < numPoints; i++)
- {
- vec4_t color;
-
- for(j = 0; j < 3; j++)
- {
- points[i].xyz[j] = LittleFloat(verts[i].xyz[j]);
- points[i].normal[j] = LittleFloat(verts[i].normal[j]);
- }
-
- for(j = 0; j < 2; j++)
- {
- points[i].st[j] = LittleFloat(verts[i].st[j]);
- //points[i].lightmap[j] = LittleFloat(verts[i].lightmap[j]);
- }
- points[i].lightmap[0] = FatPackU(LittleFloat(verts[i].lightmap[0]), realLightmapNum);
- points[i].lightmap[1] = FatPackV(LittleFloat(verts[i].lightmap[1]), realLightmapNum);
-
- if (hdrVertColors)
- {
- color[0] = hdrVertColors[(ds->firstVert + i) * 3 ];
- color[1] = hdrVertColors[(ds->firstVert + i) * 3 + 1];
- color[2] = hdrVertColors[(ds->firstVert + i) * 3 + 2];
- }
- else
- {
- //hack: convert LDR vertex colors to HDR
- if (r_hdr->integer)
- {
- color[0] = verts[i].color[0] + 1.0f;
- color[1] = verts[i].color[1] + 1.0f;
- color[2] = verts[i].color[2] + 1.0f;
- }
- else
- {
- color[0] = verts[i].color[0];
- color[1] = verts[i].color[1];
- color[2] = verts[i].color[2];
- }
- }
- color[3] = verts[i].color[3] / 255.0f;
-
- R_ColorShiftLightingFloats( color, points[i].vertexColors, 1.0f / 255.0f );
- }
-
- // pre-tesseleate
- grid = R_SubdividePatchToGrid( width, height, points );
- surf->data = (surfaceType_t *)grid;
-
- // copy the level of detail origin, which is the center
- // of the group of all curves that must subdivide the same
- // to avoid cracking
- for ( i = 0 ; i < 3 ; i++ ) {
- bounds[0][i] = LittleFloat( ds->lightmapVecs[0][i] );
- bounds[1][i] = LittleFloat( ds->lightmapVecs[1][i] );
- }
- VectorAdd( bounds[0], bounds[1], bounds[1] );
- VectorScale( bounds[1], 0.5f, grid->lodOrigin );
- VectorSubtract( bounds[0], grid->lodOrigin, tmpVec );
- grid->lodRadius = VectorLength( tmpVec );
-}
-
-/*
-===============
-ParseTriSurf
-===============
-*/
-static void ParseTriSurf( dsurface_t *ds, drawVert_t *verts, float *hdrVertColors, msurface_t *surf, int *indexes ) {
- srfTriangles_t *cv;
- srfTriangle_t *tri;
- int i, j;
- int numVerts, numTriangles, badTriangles;
-
- // get fog volume
- surf->fogIndex = LittleLong( ds->fogNum ) + 1;
-
- // get shader
- surf->shader = ShaderForShaderNum( ds->shaderNum, LIGHTMAP_BY_VERTEX );
- if ( r_singleShader->integer && !surf->shader->isSky ) {
- surf->shader = tr.defaultShader;
- }
-
- numVerts = LittleLong(ds->numVerts);
- numTriangles = LittleLong(ds->numIndexes) / 3;
-
- //cv = ri.Hunk_Alloc(sizeof(*cv), h_low);
- cv = (void *)surf->data;
- cv->surfaceType = SF_TRIANGLES;
-
- cv->numTriangles = numTriangles;
- cv->triangles = ri.Hunk_Alloc(numTriangles * sizeof(cv->triangles[0]), h_low);
-
- cv->numVerts = numVerts;
- cv->verts = ri.Hunk_Alloc(numVerts * sizeof(cv->verts[0]), h_low);
-
- surf->data = (surfaceType_t *) cv;
-
- // copy vertexes
- surf->cullinfo.type = CULLINFO_BOX;
- ClearBounds(surf->cullinfo.bounds[0], surf->cullinfo.bounds[1]);
- verts += LittleLong(ds->firstVert);
- for(i = 0; i < numVerts; i++)
- {
- vec4_t color;
-
- for(j = 0; j < 3; j++)
- {
- cv->verts[i].xyz[j] = LittleFloat(verts[i].xyz[j]);
- cv->verts[i].normal[j] = LittleFloat(verts[i].normal[j]);
- }
-
- AddPointToBounds( cv->verts[i].xyz, surf->cullinfo.bounds[0], surf->cullinfo.bounds[1] );
-
- for(j = 0; j < 2; j++)
- {
- cv->verts[i].st[j] = LittleFloat(verts[i].st[j]);
- cv->verts[i].lightmap[j] = LittleFloat(verts[i].lightmap[j]);
- }
-
- if (hdrVertColors)
- {
- color[0] = hdrVertColors[(ds->firstVert + i) * 3 ];
- color[1] = hdrVertColors[(ds->firstVert + i) * 3 + 1];
- color[2] = hdrVertColors[(ds->firstVert + i) * 3 + 2];
- }
- else
- {
- //hack: convert LDR vertex colors to HDR
- if (r_hdr->integer)
- {
- color[0] = verts[i].color[0] + 1.0f;
- color[1] = verts[i].color[1] + 1.0f;
- color[2] = verts[i].color[2] + 1.0f;
- }
- else
- {
- color[0] = verts[i].color[0];
- color[1] = verts[i].color[1];
- color[2] = verts[i].color[2];
- }
- }
- color[3] = verts[i].color[3] / 255.0f;
-
- R_ColorShiftLightingFloats( color, cv->verts[i].vertexColors, 1.0f / 255.0f );
- }
-
- // copy triangles
- badTriangles = 0;
- indexes += LittleLong(ds->firstIndex);
- for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
- {
- for(j = 0; j < 3; j++)
- {
- tri->indexes[j] = LittleLong(indexes[i * 3 + j]);
-
- if(tri->indexes[j] < 0 || tri->indexes[j] >= numVerts)
- {
- ri.Error(ERR_DROP, "Bad index in face surface");
- }
- }
-
- if ((tri->indexes[0] == tri->indexes[1]) || (tri->indexes[1] == tri->indexes[2]) || (tri->indexes[0] == tri->indexes[2]))
- {
- tri--;
- badTriangles++;
- }
- }
-
- if (badTriangles)
- {
- ri.Printf(PRINT_WARNING, "Trisurf has bad triangles, originally shader %s %d tris %d verts, now %d tris\n", surf->shader->name, numTriangles, numVerts, numTriangles - badTriangles);
- cv->numTriangles -= badTriangles;
- }
-
-#ifdef USE_VERT_TANGENT_SPACE
- // Tr3B - calc tangent spaces
- {
- srfVert_t *dv[3];
-
- for(i = 0, tri = cv->triangles; i < numTriangles; i++, tri++)
- {
- dv[0] = &cv->verts[tri->indexes[0]];
- dv[1] = &cv->verts[tri->indexes[1]];
- dv[2] = &cv->verts[tri->indexes[2]];
-
- R_CalcTangentVectors(dv);
- }
- }
-#endif
-}
-
-/*
-===============
-ParseFlare
-===============
-*/
-static void ParseFlare( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int *indexes ) {
- srfFlare_t *flare;
- int i;
-
- // get fog volume
- surf->fogIndex = LittleLong( ds->fogNum ) + 1;
-
- // get shader
- surf->shader = ShaderForShaderNum( ds->shaderNum, LIGHTMAP_BY_VERTEX );
- if ( r_singleShader->integer && !surf->shader->isSky ) {
- surf->shader = tr.defaultShader;
- }
-
- //flare = ri.Hunk_Alloc( sizeof( *flare ), h_low );
- flare = (void *)surf->data;
- flare->surfaceType = SF_FLARE;
-
- surf->data = (surfaceType_t *)flare;
-
- for ( i = 0 ; i < 3 ; i++ ) {
- flare->origin[i] = LittleFloat( ds->lightmapOrigin[i] );
- flare->color[i] = LittleFloat( ds->lightmapVecs[0][i] );
- flare->normal[i] = LittleFloat( ds->lightmapVecs[2][i] );
- }
-}
-
-
-/*
-=================
-R_MergedWidthPoints
-
-returns true if there are grid points merged on a width edge
-=================
-*/
-int R_MergedWidthPoints(srfGridMesh_t *grid, int offset) {
- int i, j;
-
- for (i = 1; i < grid->width-1; i++) {
- for (j = i + 1; j < grid->width-1; j++) {
- if ( fabs(grid->verts[i + offset].xyz[0] - grid->verts[j + offset].xyz[0]) > .1) continue;
- if ( fabs(grid->verts[i + offset].xyz[1] - grid->verts[j + offset].xyz[1]) > .1) continue;
- if ( fabs(grid->verts[i + offset].xyz[2] - grid->verts[j + offset].xyz[2]) > .1) continue;
- return qtrue;
- }
- }
- return qfalse;
-}
-
-/*
-=================
-R_MergedHeightPoints
-
-returns true if there are grid points merged on a height edge
-=================
-*/
-int R_MergedHeightPoints(srfGridMesh_t *grid, int offset) {
- int i, j;
-
- for (i = 1; i < grid->height-1; i++) {
- for (j = i + 1; j < grid->height-1; j++) {
- if ( fabs(grid->verts[grid->width * i + offset].xyz[0] - grid->verts[grid->width * j + offset].xyz[0]) > .1) continue;
- if ( fabs(grid->verts[grid->width * i + offset].xyz[1] - grid->verts[grid->width * j + offset].xyz[1]) > .1) continue;
- if ( fabs(grid->verts[grid->width * i + offset].xyz[2] - grid->verts[grid->width * j + offset].xyz[2]) > .1) continue;
- return qtrue;
- }
- }
- return qfalse;
-}
-
-/*
-=================
-R_FixSharedVertexLodError_r
-
-NOTE: never sync LoD through grid edges with merged points!
-
-FIXME: write generalized version that also avoids cracks between a patch and one that meets half way?
-=================
-*/
-void R_FixSharedVertexLodError_r( int start, srfGridMesh_t *grid1 ) {
- int j, k, l, m, n, offset1, offset2, touch;
- srfGridMesh_t *grid2;
-
- for ( j = start; j < s_worldData.numsurfaces; j++ ) {
- //
- grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data;
- // if this surface is not a grid
- if ( grid2->surfaceType != SF_GRID ) continue;
- // if the LOD errors are already fixed for this patch
- if ( grid2->lodFixed == 2 ) continue;
- // grids in the same LOD group should have the exact same lod radius
- if ( grid1->lodRadius != grid2->lodRadius ) continue;
- // grids in the same LOD group should have the exact same lod origin
- if ( grid1->lodOrigin[0] != grid2->lodOrigin[0] ) continue;
- if ( grid1->lodOrigin[1] != grid2->lodOrigin[1] ) continue;
- if ( grid1->lodOrigin[2] != grid2->lodOrigin[2] ) continue;
- //
- touch = qfalse;
- for (n = 0; n < 2; n++) {
- //
- if (n) offset1 = (grid1->height-1) * grid1->width;
- else offset1 = 0;
- if (R_MergedWidthPoints(grid1, offset1)) continue;
- for (k = 1; k < grid1->width-1; k++) {
- for (m = 0; m < 2; m++) {
-
- if (m) offset2 = (grid2->height-1) * grid2->width;
- else offset2 = 0;
- if (R_MergedWidthPoints(grid2, offset2)) continue;
- for ( l = 1; l < grid2->width-1; l++) {
- //
- if ( fabs(grid1->verts[k + offset1].xyz[0] - grid2->verts[l + offset2].xyz[0]) > .1) continue;
- if ( fabs(grid1->verts[k + offset1].xyz[1] - grid2->verts[l + offset2].xyz[1]) > .1) continue;
- if ( fabs(grid1->verts[k + offset1].xyz[2] - grid2->verts[l + offset2].xyz[2]) > .1) continue;
- // ok the points are equal and should have the same lod error
- grid2->widthLodError[l] = grid1->widthLodError[k];
- touch = qtrue;
- }
- }
- for (m = 0; m < 2; m++) {
-
- if (m) offset2 = grid2->width-1;
- else offset2 = 0;
- if (R_MergedHeightPoints(grid2, offset2)) continue;
- for ( l = 1; l < grid2->height-1; l++) {
- //
- if ( fabs(grid1->verts[k + offset1].xyz[0] - grid2->verts[grid2->width * l + offset2].xyz[0]) > .1) continue;
- if ( fabs(grid1->verts[k + offset1].xyz[1] - grid2->verts[grid2->width * l + offset2].xyz[1]) > .1) continue;
- if ( fabs(grid1->verts[k + offset1].xyz[2] - grid2->verts[grid2->width * l + offset2].xyz[2]) > .1) continue;
- // ok the points are equal and should have the same lod error
- grid2->heightLodError[l] = grid1->widthLodError[k];
- touch = qtrue;
- }
- }
- }
- }
- for (n = 0; n < 2; n++) {
- //
- if (n) offset1 = grid1->width-1;
- else offset1 = 0;
- if (R_MergedHeightPoints(grid1, offset1)) continue;
- for (k = 1; k < grid1->height-1; k++) {
- for (m = 0; m < 2; m++) {
-
- if (m) offset2 = (grid2->height-1) * grid2->width;
- else offset2 = 0;
- if (R_MergedWidthPoints(grid2, offset2)) continue;
- for ( l = 1; l < grid2->width-1; l++) {
- //
- if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[0] - grid2->verts[l + offset2].xyz[0]) > .1) continue;
- if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[1] - grid2->verts[l + offset2].xyz[1]) > .1) continue;
- if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[2] - grid2->verts[l + offset2].xyz[2]) > .1) continue;
- // ok the points are equal and should have the same lod error
- grid2->widthLodError[l] = grid1->heightLodError[k];
- touch = qtrue;
- }
- }
- for (m = 0; m < 2; m++) {
-
- if (m) offset2 = grid2->width-1;
- else offset2 = 0;
- if (R_MergedHeightPoints(grid2, offset2)) continue;
- for ( l = 1; l < grid2->height-1; l++) {
- //
- if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[0] - grid2->verts[grid2->width * l + offset2].xyz[0]) > .1) continue;
- if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[1] - grid2->verts[grid2->width * l + offset2].xyz[1]) > .1) continue;
- if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[2] - grid2->verts[grid2->width * l + offset2].xyz[2]) > .1) continue;
- // ok the points are equal and should have the same lod error
- grid2->heightLodError[l] = grid1->heightLodError[k];
- touch = qtrue;
- }
- }
- }
- }
- if (touch) {
- grid2->lodFixed = 2;
- R_FixSharedVertexLodError_r ( start, grid2 );
- //NOTE: this would be correct but makes things really slow
- //grid2->lodFixed = 1;
- }
- }
-}
-
-/*
-=================
-R_FixSharedVertexLodError
-
-This function assumes that all patches in one group are nicely stitched together for the highest LoD.
-If this is not the case this function will still do its job but won't fix the highest LoD cracks.
-=================
-*/
-void R_FixSharedVertexLodError( void ) {
- int i;
- srfGridMesh_t *grid1;
-
- for ( i = 0; i < s_worldData.numsurfaces; i++ ) {
- //
- grid1 = (srfGridMesh_t *) s_worldData.surfaces[i].data;
- // if this surface is not a grid
- if ( grid1->surfaceType != SF_GRID )
- continue;
- //
- if ( grid1->lodFixed )
- continue;
- //
- grid1->lodFixed = 2;
- // recursively fix other patches in the same LOD group
- R_FixSharedVertexLodError_r( i + 1, grid1);
- }
-}
-
-
-/*
-===============
-R_StitchPatches
-===============
-*/
-int R_StitchPatches( int grid1num, int grid2num ) {
- float *v1, *v2;
- srfGridMesh_t *grid1, *grid2;
- int k, l, m, n, offset1, offset2, row, column;
-
- grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data;
- grid2 = (srfGridMesh_t *) s_worldData.surfaces[grid2num].data;
- for (n = 0; n < 2; n++) {
- //
- if (n) offset1 = (grid1->height-1) * grid1->width;
- else offset1 = 0;
- if (R_MergedWidthPoints(grid1, offset1))
- continue;
- for (k = 0; k < grid1->width-2; k += 2) {
-
- for (m = 0; m < 2; m++) {
-
- if ( grid2->width >= MAX_GRID_SIZE )
- break;
- if (m) offset2 = (grid2->height-1) * grid2->width;
- else offset2 = 0;
- for ( l = 0; l < grid2->width-1; l++) {
- //
- v1 = grid1->verts[k + offset1].xyz;
- v2 = grid2->verts[l + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
-
- v1 = grid1->verts[k + 2 + offset1].xyz;
- v2 = grid2->verts[l + 1 + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
- //
- v1 = grid2->verts[l + offset2].xyz;
- v2 = grid2->verts[l + 1 + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) < .01 &&
- fabs(v1[1] - v2[1]) < .01 &&
- fabs(v1[2] - v2[2]) < .01)
- continue;
- //
- //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
- // insert column into grid2 right after after column l
- if (m) row = grid2->height-1;
- else row = 0;
- grid2 = R_GridInsertColumn( grid2, l+1, row,
- grid1->verts[k + 1 + offset1].xyz, grid1->widthLodError[k+1]);
- grid2->lodStitched = qfalse;
- s_worldData.surfaces[grid2num].data = (void *) grid2;
- return qtrue;
- }
- }
- for (m = 0; m < 2; m++) {
-
- if (grid2->height >= MAX_GRID_SIZE)
- break;
- if (m) offset2 = grid2->width-1;
- else offset2 = 0;
- for ( l = 0; l < grid2->height-1; l++) {
- //
- v1 = grid1->verts[k + offset1].xyz;
- v2 = grid2->verts[grid2->width * l + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
-
- v1 = grid1->verts[k + 2 + offset1].xyz;
- v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
- //
- v1 = grid2->verts[grid2->width * l + offset2].xyz;
- v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) < .01 &&
- fabs(v1[1] - v2[1]) < .01 &&
- fabs(v1[2] - v2[2]) < .01)
- continue;
- //
- //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
- // insert row into grid2 right after after row l
- if (m) column = grid2->width-1;
- else column = 0;
- grid2 = R_GridInsertRow( grid2, l+1, column,
- grid1->verts[k + 1 + offset1].xyz, grid1->widthLodError[k+1]);
- grid2->lodStitched = qfalse;
- s_worldData.surfaces[grid2num].data = (void *) grid2;
- return qtrue;
- }
- }
- }
- }
- for (n = 0; n < 2; n++) {
- //
- if (n) offset1 = grid1->width-1;
- else offset1 = 0;
- if (R_MergedHeightPoints(grid1, offset1))
- continue;
- for (k = 0; k < grid1->height-2; k += 2) {
- for (m = 0; m < 2; m++) {
-
- if ( grid2->width >= MAX_GRID_SIZE )
- break;
- if (m) offset2 = (grid2->height-1) * grid2->width;
- else offset2 = 0;
- for ( l = 0; l < grid2->width-1; l++) {
- //
- v1 = grid1->verts[grid1->width * k + offset1].xyz;
- v2 = grid2->verts[l + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
-
- v1 = grid1->verts[grid1->width * (k + 2) + offset1].xyz;
- v2 = grid2->verts[l + 1 + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
- //
- v1 = grid2->verts[l + offset2].xyz;
- v2 = grid2->verts[(l + 1) + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) < .01 &&
- fabs(v1[1] - v2[1]) < .01 &&
- fabs(v1[2] - v2[2]) < .01)
- continue;
- //
- //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
- // insert column into grid2 right after after column l
- if (m) row = grid2->height-1;
- else row = 0;
- grid2 = R_GridInsertColumn( grid2, l+1, row,
- grid1->verts[grid1->width * (k + 1) + offset1].xyz, grid1->heightLodError[k+1]);
- grid2->lodStitched = qfalse;
- s_worldData.surfaces[grid2num].data = (void *) grid2;
- return qtrue;
- }
- }
- for (m = 0; m < 2; m++) {
-
- if (grid2->height >= MAX_GRID_SIZE)
- break;
- if (m) offset2 = grid2->width-1;
- else offset2 = 0;
- for ( l = 0; l < grid2->height-1; l++) {
- //
- v1 = grid1->verts[grid1->width * k + offset1].xyz;
- v2 = grid2->verts[grid2->width * l + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
-
- v1 = grid1->verts[grid1->width * (k + 2) + offset1].xyz;
- v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
- //
- v1 = grid2->verts[grid2->width * l + offset2].xyz;
- v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) < .01 &&
- fabs(v1[1] - v2[1]) < .01 &&
- fabs(v1[2] - v2[2]) < .01)
- continue;
- //
- //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
- // insert row into grid2 right after after row l
- if (m) column = grid2->width-1;
- else column = 0;
- grid2 = R_GridInsertRow( grid2, l+1, column,
- grid1->verts[grid1->width * (k + 1) + offset1].xyz, grid1->heightLodError[k+1]);
- grid2->lodStitched = qfalse;
- s_worldData.surfaces[grid2num].data = (void *) grid2;
- return qtrue;
- }
- }
- }
- }
- for (n = 0; n < 2; n++) {
- //
- if (n) offset1 = (grid1->height-1) * grid1->width;
- else offset1 = 0;
- if (R_MergedWidthPoints(grid1, offset1))
- continue;
- for (k = grid1->width-1; k > 1; k -= 2) {
-
- for (m = 0; m < 2; m++) {
-
- if ( grid2->width >= MAX_GRID_SIZE )
- break;
- if (m) offset2 = (grid2->height-1) * grid2->width;
- else offset2 = 0;
- for ( l = 0; l < grid2->width-1; l++) {
- //
- v1 = grid1->verts[k + offset1].xyz;
- v2 = grid2->verts[l + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
-
- v1 = grid1->verts[k - 2 + offset1].xyz;
- v2 = grid2->verts[l + 1 + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
- //
- v1 = grid2->verts[l + offset2].xyz;
- v2 = grid2->verts[(l + 1) + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) < .01 &&
- fabs(v1[1] - v2[1]) < .01 &&
- fabs(v1[2] - v2[2]) < .01)
- continue;
- //
- //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
- // insert column into grid2 right after after column l
- if (m) row = grid2->height-1;
- else row = 0;
- grid2 = R_GridInsertColumn( grid2, l+1, row,
- grid1->verts[k - 1 + offset1].xyz, grid1->widthLodError[k+1]);
- grid2->lodStitched = qfalse;
- s_worldData.surfaces[grid2num].data = (void *) grid2;
- return qtrue;
- }
- }
- for (m = 0; m < 2; m++) {
-
- if (grid2->height >= MAX_GRID_SIZE)
- break;
- if (m) offset2 = grid2->width-1;
- else offset2 = 0;
- for ( l = 0; l < grid2->height-1; l++) {
- //
- v1 = grid1->verts[k + offset1].xyz;
- v2 = grid2->verts[grid2->width * l + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
-
- v1 = grid1->verts[k - 2 + offset1].xyz;
- v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
- //
- v1 = grid2->verts[grid2->width * l + offset2].xyz;
- v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) < .01 &&
- fabs(v1[1] - v2[1]) < .01 &&
- fabs(v1[2] - v2[2]) < .01)
- continue;
- //
- //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
- // insert row into grid2 right after after row l
- if (m) column = grid2->width-1;
- else column = 0;
- grid2 = R_GridInsertRow( grid2, l+1, column,
- grid1->verts[k - 1 + offset1].xyz, grid1->widthLodError[k+1]);
- if (!grid2)
- break;
- grid2->lodStitched = qfalse;
- s_worldData.surfaces[grid2num].data = (void *) grid2;
- return qtrue;
- }
- }
- }
- }
- for (n = 0; n < 2; n++) {
- //
- if (n) offset1 = grid1->width-1;
- else offset1 = 0;
- if (R_MergedHeightPoints(grid1, offset1))
- continue;
- for (k = grid1->height-1; k > 1; k -= 2) {
- for (m = 0; m < 2; m++) {
-
- if ( grid2->width >= MAX_GRID_SIZE )
- break;
- if (m) offset2 = (grid2->height-1) * grid2->width;
- else offset2 = 0;
- for ( l = 0; l < grid2->width-1; l++) {
- //
- v1 = grid1->verts[grid1->width * k + offset1].xyz;
- v2 = grid2->verts[l + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
-
- v1 = grid1->verts[grid1->width * (k - 2) + offset1].xyz;
- v2 = grid2->verts[l + 1 + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
- //
- v1 = grid2->verts[l + offset2].xyz;
- v2 = grid2->verts[(l + 1) + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) < .01 &&
- fabs(v1[1] - v2[1]) < .01 &&
- fabs(v1[2] - v2[2]) < .01)
- continue;
- //
- //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
- // insert column into grid2 right after after column l
- if (m) row = grid2->height-1;
- else row = 0;
- grid2 = R_GridInsertColumn( grid2, l+1, row,
- grid1->verts[grid1->width * (k - 1) + offset1].xyz, grid1->heightLodError[k+1]);
- grid2->lodStitched = qfalse;
- s_worldData.surfaces[grid2num].data = (void *) grid2;
- return qtrue;
- }
- }
- for (m = 0; m < 2; m++) {
-
- if (grid2->height >= MAX_GRID_SIZE)
- break;
- if (m) offset2 = grid2->width-1;
- else offset2 = 0;
- for ( l = 0; l < grid2->height-1; l++) {
- //
- v1 = grid1->verts[grid1->width * k + offset1].xyz;
- v2 = grid2->verts[grid2->width * l + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
-
- v1 = grid1->verts[grid1->width * (k - 2) + offset1].xyz;
- v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) > .1)
- continue;
- if ( fabs(v1[1] - v2[1]) > .1)
- continue;
- if ( fabs(v1[2] - v2[2]) > .1)
- continue;
- //
- v1 = grid2->verts[grid2->width * l + offset2].xyz;
- v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
- if ( fabs(v1[0] - v2[0]) < .01 &&
- fabs(v1[1] - v2[1]) < .01 &&
- fabs(v1[2] - v2[2]) < .01)
- continue;
- //
- //ri.Printf( PRINT_ALL, "found highest LoD crack between two patches\n" );
- // insert row into grid2 right after after row l
- if (m) column = grid2->width-1;
- else column = 0;
- grid2 = R_GridInsertRow( grid2, l+1, column,
- grid1->verts[grid1->width * (k - 1) + offset1].xyz, grid1->heightLodError[k+1]);
- grid2->lodStitched = qfalse;
- s_worldData.surfaces[grid2num].data = (void *) grid2;
- return qtrue;
- }
- }
- }
- }
- return qfalse;
-}
-
-/*
-===============
-R_TryStitchPatch
-
-This function will try to stitch patches in the same LoD group together for the highest LoD.
-
-Only single missing vertice cracks will be fixed.
-
-Vertices will be joined at the patch side a crack is first found, at the other side
-of the patch (on the same row or column) the vertices will not be joined and cracks
-might still appear at that side.
-===============
-*/
-int R_TryStitchingPatch( int grid1num ) {
- int j, numstitches;
- srfGridMesh_t *grid1, *grid2;
-
- numstitches = 0;
- grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data;
- for ( j = 0; j < s_worldData.numsurfaces; j++ ) {
- //
- grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data;
- // if this surface is not a grid
- if ( grid2->surfaceType != SF_GRID ) continue;
- // grids in the same LOD group should have the exact same lod radius
- if ( grid1->lodRadius != grid2->lodRadius ) continue;
- // grids in the same LOD group should have the exact same lod origin
- if ( grid1->lodOrigin[0] != grid2->lodOrigin[0] ) continue;
- if ( grid1->lodOrigin[1] != grid2->lodOrigin[1] ) continue;
- if ( grid1->lodOrigin[2] != grid2->lodOrigin[2] ) continue;
- //
- while (R_StitchPatches(grid1num, j))
- {
- numstitches++;
- }
- }
- return numstitches;
-}
-
-/*
-===============
-R_StitchAllPatches
-===============
-*/
-void R_StitchAllPatches( void ) {
- int i, stitched, numstitches;
- srfGridMesh_t *grid1;
-
- numstitches = 0;
- do
- {
- stitched = qfalse;
- for ( i = 0; i < s_worldData.numsurfaces; i++ ) {
- //
- grid1 = (srfGridMesh_t *) s_worldData.surfaces[i].data;
- // if this surface is not a grid
- if ( grid1->surfaceType != SF_GRID )
- continue;
- //
- if ( grid1->lodStitched )
- continue;
- //
- grid1->lodStitched = qtrue;
- stitched = qtrue;
- //
- numstitches += R_TryStitchingPatch( i );
- }
- }
- while (stitched);
- ri.Printf( PRINT_ALL, "stitched %d LoD cracks\n", numstitches );
-}
-
-/*
-===============
-R_MovePatchSurfacesToHunk
-===============
-*/
-void R_MovePatchSurfacesToHunk(void) {
- int i, size;
- srfGridMesh_t *grid, *hunkgrid;
-
- for ( i = 0; i < s_worldData.numsurfaces; i++ ) {
- //
- grid = (srfGridMesh_t *) s_worldData.surfaces[i].data;
- // if this surface is not a grid
- if ( grid->surfaceType != SF_GRID )
- continue;
- //
- size = sizeof(*grid);
- hunkgrid = ri.Hunk_Alloc(size, h_low);
- Com_Memcpy(hunkgrid, grid, size);
-
- hunkgrid->widthLodError = ri.Hunk_Alloc( grid->width * 4, h_low );
- Com_Memcpy( hunkgrid->widthLodError, grid->widthLodError, grid->width * 4 );
-
- hunkgrid->heightLodError = ri.Hunk_Alloc( grid->height * 4, h_low );
- Com_Memcpy( hunkgrid->heightLodError, grid->heightLodError, grid->height * 4 );
-
- hunkgrid->numTriangles = grid->numTriangles;
- hunkgrid->triangles = ri.Hunk_Alloc(grid->numTriangles * sizeof(srfTriangle_t), h_low);
- Com_Memcpy(hunkgrid->triangles, grid->triangles, grid->numTriangles * sizeof(srfTriangle_t));
-
- hunkgrid->numVerts = grid->numVerts;
- hunkgrid->verts = ri.Hunk_Alloc(grid->numVerts * sizeof(srfVert_t), h_low);
- Com_Memcpy(hunkgrid->verts, grid->verts, grid->numVerts * sizeof(srfVert_t));
-
- R_FreeSurfaceGridMesh( grid );
-
- s_worldData.surfaces[i].data = (void *) hunkgrid;
- }
-}
-
-
-/*
-=================
-BSPSurfaceCompare
-compare function for qsort()
-=================
-*/
-static int BSPSurfaceCompare(const void *a, const void *b)
-{
- msurface_t *aa, *bb;
-
- aa = *(msurface_t **) a;
- bb = *(msurface_t **) b;
-
- // shader first
- if(aa->shader->sortedIndex < bb->shader->sortedIndex)
- return -1;
-
- else if(aa->shader->sortedIndex > bb->shader->sortedIndex)
- return 1;
-
- // by fogIndex
- if(aa->fogIndex < bb->fogIndex)
- return -1;
-
- else if(aa->fogIndex > bb->fogIndex)
- return 1;
-
- return 0;
-}
-
-
-static void CopyVert(const srfVert_t * in, srfVert_t * out)
-{
- int j;
-
- for(j = 0; j < 3; j++)
- {
- out->xyz[j] = in->xyz[j];
-#ifdef USE_VERT_TANGENT_SPACE
- out->tangent[j] = in->tangent[j];
- out->bitangent[j] = in->bitangent[j];
-#endif
- out->normal[j] = in->normal[j];
- out->lightdir[j] = in->lightdir[j];
- }
-
- for(j = 0; j < 2; j++)
- {
- out->st[j] = in->st[j];
- out->lightmap[j] = in->lightmap[j];
- }
-
- for(j = 0; j < 4; j++)
- {
- out->vertexColors[j] = in->vertexColors[j];
- }
-}
-
-
-/*
-===============
-R_CreateWorldVBO
-===============
-*/
-static void R_CreateWorldVBO(void)
-{
- int i, j, k;
-
- int numVerts;
- srfVert_t *verts;
-
- int numTriangles;
- srfTriangle_t *triangles;
-
- int numSurfaces;
- msurface_t *surface;
- msurface_t **surfacesSorted;
-
- int startTime, endTime;
-
- startTime = ri.Milliseconds();
-
- numVerts = 0;
- numTriangles = 0;
- numSurfaces = 0;
- for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numsurfaces /* s_worldData.numWorldSurfaces */; k++, surface++)
- {
- if(*surface->data == SF_FACE)
- {
- srfSurfaceFace_t *face = (srfSurfaceFace_t *) surface->data;
-
- if(face->numVerts)
- numVerts += face->numVerts;
-
- if(face->numTriangles)
- numTriangles += face->numTriangles;
-
- numSurfaces++;
- }
- else if(*surface->data == SF_GRID)
- {
- srfGridMesh_t *grid = (srfGridMesh_t *) surface->data;
-
- if(grid->numVerts)
- numVerts += grid->numVerts;
-
- if(grid->numTriangles)
- numTriangles += grid->numTriangles;
-
- numSurfaces++;
- }
- else if(*surface->data == SF_TRIANGLES)
- {
- srfTriangles_t *tri = (srfTriangles_t *) surface->data;
-
- if(tri->numVerts)
- numVerts += tri->numVerts;
-
- if(tri->numTriangles)
- numTriangles += tri->numTriangles;
-
- numSurfaces++;
- }
- }
-
- if(!numVerts || !numTriangles)
- return;
-
- ri.Printf(PRINT_ALL, "...calculating world VBO ( %i verts %i tris )\n", numVerts, numTriangles);
-
- // create arrays
-
- verts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t));
-
- triangles = ri.Hunk_AllocateTempMemory(numTriangles * sizeof(srfTriangle_t));
-
- // presort surfaces
- surfacesSorted = ri.Malloc(numSurfaces * sizeof(*surfacesSorted));
-
- j = 0;
- for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numsurfaces; k++, surface++)
- {
- if(*surface->data == SF_FACE || *surface->data == SF_GRID || *surface->data == SF_TRIANGLES)
- {
- surfacesSorted[j++] = surface;
- }
- }
-
- qsort(surfacesSorted, numSurfaces, sizeof(*surfacesSorted), BSPSurfaceCompare);
-
- // set up triangle indices
- numVerts = 0;
- numTriangles = 0;
- for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k])
- {
- if(*surface->data == SF_FACE)
- {
- srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
-
- srf->firstIndex = numTriangles * 3;
-
- if(srf->numTriangles)
- {
- srfTriangle_t *tri;
-
- srf->minIndex = numVerts + srf->triangles->indexes[0];
- srf->maxIndex = numVerts + srf->triangles->indexes[0];
-
- for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
- {
- for(j = 0; j < 3; j++)
- {
- triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
- srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]);
- srf->maxIndex = MAX(srf->maxIndex, numVerts + tri->indexes[j]);
- }
- }
-
- numTriangles += srf->numTriangles;
- }
-
- if(srf->numVerts)
- numVerts += srf->numVerts;
- }
- else if(*surface->data == SF_GRID)
- {
- srfGridMesh_t *srf = (srfGridMesh_t *) surface->data;
-
- srf->firstIndex = numTriangles * 3;
-
- if(srf->numTriangles)
- {
- srfTriangle_t *tri;
-
- srf->minIndex = numVerts + srf->triangles->indexes[0];
- srf->maxIndex = numVerts + srf->triangles->indexes[0];
-
- for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
- {
- for(j = 0; j < 3; j++)
- {
- triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
- srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]);
- srf->maxIndex = MAX(srf->maxIndex, numVerts + tri->indexes[j]);
- }
- }
-
- numTriangles += srf->numTriangles;
- }
-
- if(srf->numVerts)
- numVerts += srf->numVerts;
- }
- else if(*surface->data == SF_TRIANGLES)
- {
- srfTriangles_t *srf = (srfTriangles_t *) surface->data;
-
- srf->firstIndex = numTriangles * 3;
-
- if(srf->numTriangles)
- {
- srfTriangle_t *tri;
-
- srf->minIndex = numVerts + srf->triangles->indexes[0];
- srf->maxIndex = numVerts + srf->triangles->indexes[0];
-
- for(i = 0, tri = srf->triangles; i < srf->numTriangles; i++, tri++)
- {
- for(j = 0; j < 3; j++)
- {
- triangles[numTriangles + i].indexes[j] = numVerts + tri->indexes[j];
- srf->minIndex = MIN(srf->minIndex, numVerts + tri->indexes[j]);
- srf->maxIndex = MAX(srf->maxIndex, numVerts + tri->indexes[j]);
- }
- }
-
- numTriangles += srf->numTriangles;
- }
-
- if(srf->numVerts)
- numVerts += srf->numVerts;
- }
- }
-
- // build vertices
- numVerts = 0;
- for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k])
- {
- if(*surface->data == SF_FACE)
- {
- srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
-
- srf->firstVert = numVerts;
-
- if(srf->numVerts)
- {
- for(i = 0; i < srf->numVerts; i++)
- {
- CopyVert(&srf->verts[i], &verts[numVerts + i]);
- }
-
- numVerts += srf->numVerts;
- }
- }
- else if(*surface->data == SF_GRID)
- {
- srfGridMesh_t *srf = (srfGridMesh_t *) surface->data;
-
- srf->firstVert = numVerts;
-
- if(srf->numVerts)
- {
- for(i = 0; i < srf->numVerts; i++)
- {
- CopyVert(&srf->verts[i], &verts[numVerts + i]);
- }
-
- numVerts += srf->numVerts;
- }
- }
- else if(*surface->data == SF_TRIANGLES)
- {
- srfTriangles_t *srf = (srfTriangles_t *) surface->data;
-
- srf->firstVert = numVerts;
-
- if(srf->numVerts)
- {
- for(i = 0; i < srf->numVerts; i++)
- {
- CopyVert(&srf->verts[i], &verts[numVerts + i]);
- }
-
- numVerts += srf->numVerts;
- }
- }
- }
-
-#ifdef USE_VERT_TANGENT_SPACE
- s_worldData.vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", 0), numVerts, verts,
- ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BITANGENT |
- ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC);
-#else
- s_worldData.vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", 0), numVerts, verts,
- ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD |
- ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC);
-#endif
-
- s_worldData.ibo = R_CreateIBO2(va("staticBspModel0_IBO %i", 0), numTriangles, triangles, VBO_USAGE_STATIC);
-
- endTime = ri.Milliseconds();
- ri.Printf(PRINT_ALL, "world VBO calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0);
-
- // point triangle surfaces to world VBO
- for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k])
- {
- if(*surface->data == SF_FACE)
- {
- srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
-
- if( srf->numVerts && srf->numTriangles)
- {
- srf->vbo = s_worldData.vbo;
- srf->ibo = s_worldData.ibo;
- }
- }
- else if(*surface->data == SF_GRID)
- {
- srfGridMesh_t *srf = (srfGridMesh_t *) surface->data;
-
- if( srf->numVerts && srf->numTriangles)
- {
- srf->vbo = s_worldData.vbo;
- srf->ibo = s_worldData.ibo;
- }
- }
- else if(*surface->data == SF_TRIANGLES)
- {
- srfTriangles_t *srf = (srfTriangles_t *) surface->data;
-
- if( srf->numVerts && srf->numTriangles)
- {
- srf->vbo = s_worldData.vbo;
- srf->ibo = s_worldData.ibo;
- }
- }
- }
-
-
- startTime = ri.Milliseconds();
-
- ri.Free(surfacesSorted);
-
- ri.Hunk_FreeTempMemory(triangles);
- ri.Hunk_FreeTempMemory(verts);
-}
-
-/*
-===============
-R_LoadSurfaces
-===============
-*/
-static void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) {
- dsurface_t *in;
- msurface_t *out;
- drawVert_t *dv;
- int *indexes;
- int count;
- int numFaces, numMeshes, numTriSurfs, numFlares;
- int i;
- float *hdrVertColors = NULL;
-
- numFaces = 0;
- numMeshes = 0;
- numTriSurfs = 0;
- numFlares = 0;
-
- in = (void *)(fileBase + surfs->fileofs);
- if (surfs->filelen % sizeof(*in))
- ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
- count = surfs->filelen / sizeof(*in);
-
- dv = (void *)(fileBase + verts->fileofs);
- if (verts->filelen % sizeof(*dv))
- ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
-
- indexes = (void *)(fileBase + indexLump->fileofs);
- if ( indexLump->filelen % sizeof(*indexes))
- ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
-
- out = ri.Hunk_Alloc ( count * sizeof(*out), h_low );
-
- s_worldData.surfaces = out;
- s_worldData.numsurfaces = count;
- s_worldData.surfacesViewCount = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesViewCount), h_low );
- s_worldData.surfacesDlightBits = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesDlightBits), h_low );
- s_worldData.surfacesPshadowBits = ri.Hunk_Alloc ( count * sizeof(*s_worldData.surfacesPshadowBits), h_low );
-
- // load hdr vertex colors
- if (r_hdr->integer)
- {
- char filename[MAX_QPATH];
- int size;
-
- Com_sprintf( filename, sizeof( filename ), "maps/%s/vertlight.raw", s_worldData.baseName);
- //ri.Printf(PRINT_ALL, "looking for %s\n", filename);
-
- size = ri.FS_ReadFile(filename, (void **)&hdrVertColors);
-
- if (hdrVertColors)
- {
- //ri.Printf(PRINT_ALL, "Found!\n");
- if (size != sizeof(float) * 3 * (verts->filelen / sizeof(*dv)))
- ri.Error(ERR_DROP, "Bad size for %s (%i, expected %i)!\n", filename, size, (int)((sizeof(float)) * 3 * (verts->filelen / sizeof(*dv))));
- }
- }
-
-
- // Two passes, allocate surfaces first, then load them full of data
- // This ensures surfaces are close together to reduce L2 cache misses when using VBOs,
- // which don't actually use the verts and tris
- in = (void *)(fileBase + surfs->fileofs);
- out = s_worldData.surfaces;
- for ( i = 0 ; i < count ; i++, in++, out++ ) {
- switch ( LittleLong( in->surfaceType ) ) {
- case MST_PATCH:
- // FIXME: do this
- break;
- case MST_TRIANGLE_SOUP:
- out->data = ri.Hunk_Alloc( sizeof(srfTriangles_t), h_low);
- break;
- case MST_PLANAR:
- out->data = ri.Hunk_Alloc( sizeof(srfSurfaceFace_t), h_low);
- break;
- case MST_FLARE:
- out->data = ri.Hunk_Alloc( sizeof(srfFlare_t), h_low);
- break;
- default:
- break;
- }
- }
-
- in = (void *)(fileBase + surfs->fileofs);
- out = s_worldData.surfaces;
- for ( i = 0 ; i < count ; i++, in++, out++ ) {
- switch ( LittleLong( in->surfaceType ) ) {
- case MST_PATCH:
- ParseMesh ( in, dv, hdrVertColors, out );
- {
- srfGridMesh_t *surface = (srfGridMesh_t *)out->data;
-
- out->cullinfo.type = CULLINFO_BOX | CULLINFO_SPHERE;
- VectorCopy(surface->meshBounds[0], out->cullinfo.bounds[0]);
- VectorCopy(surface->meshBounds[1], out->cullinfo.bounds[1]);
- VectorCopy(surface->localOrigin, out->cullinfo.localOrigin);
- out->cullinfo.radius = surface->meshRadius;
- }
- numMeshes++;
- break;
- case MST_TRIANGLE_SOUP:
- ParseTriSurf( in, dv, hdrVertColors, out, indexes );
- numTriSurfs++;
- break;
- case MST_PLANAR:
- ParseFace( in, dv, hdrVertColors, out, indexes );
- numFaces++;
- break;
- case MST_FLARE:
- ParseFlare( in, dv, out, indexes );
- {
- out->cullinfo.type = CULLINFO_NONE;
- }
- numFlares++;
- break;
- default:
- ri.Error( ERR_DROP, "Bad surfaceType" );
- }
- }
-
- if (hdrVertColors)
- {
- ri.FS_FreeFile(hdrVertColors);
- }
-
-#ifdef PATCH_STITCHING
- R_StitchAllPatches();
-#endif
-
- R_FixSharedVertexLodError();
-
-#ifdef PATCH_STITCHING
- R_MovePatchSurfacesToHunk();
-#endif
-
- ri.Printf( PRINT_ALL, "...loaded %d faces, %i meshes, %i trisurfs, %i flares\n",
- numFaces, numMeshes, numTriSurfs, numFlares );
-}
-
-
-
-/*
-=================
-R_LoadSubmodels
-=================
-*/
-static void R_LoadSubmodels( lump_t *l ) {
- dmodel_t *in;
- bmodel_t *out;
- int i, j, count;
-
- in = (void *)(fileBase + l->fileofs);
- if (l->filelen % sizeof(*in))
- ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
- count = l->filelen / sizeof(*in);
-
- s_worldData.numBModels = count;
- s_worldData.bmodels = out = ri.Hunk_Alloc( count * sizeof(*out), h_low );
-
- for ( i=0 ; i<count ; i++, in++, out++ ) {
- model_t *model;
-
- model = R_AllocModel();
-
- assert( model != NULL ); // this should never happen
- if ( model == NULL ) {
- ri.Error(ERR_DROP, "R_LoadSubmodels: R_AllocModel() failed");
- }
-
- model->type = MOD_BRUSH;
- model->bmodel = out;
- Com_sprintf( model->name, sizeof( model->name ), "*%d", i );
-
- for (j=0 ; j<3 ; j++) {
- out->bounds[0][j] = LittleFloat (in->mins[j]);
- out->bounds[1][j] = LittleFloat (in->maxs[j]);
- }
-
- out->firstSurface = LittleLong( in->firstSurface );
- out->numSurfaces = LittleLong( in->numSurfaces );
-
- if(i == 0)
- {
- // Tr3B: add this for limiting VBO surface creation
- s_worldData.numWorldSurfaces = out->numSurfaces;
- }
- }
-}
-
-
-
-//==================================================================
-
-/*
-=================
-R_SetParent
-=================
-*/
-static void R_SetParent (mnode_t *node, mnode_t *parent)
-{
- node->parent = parent;
- if (node->contents != -1)
- return;
- R_SetParent (node->children[0], node);
- R_SetParent (node->children[1], node);
-}
-
-/*
-=================
-R_LoadNodesAndLeafs
-=================
-*/
-static void R_LoadNodesAndLeafs (lump_t *nodeLump, lump_t *leafLump) {
- int i, j, p;
- dnode_t *in;
- dleaf_t *inLeaf;
- mnode_t *out;
- int numNodes, numLeafs;
-
- in = (void *)(fileBase + nodeLump->fileofs);
- if (nodeLump->filelen % sizeof(dnode_t) ||
- leafLump->filelen % sizeof(dleaf_t) ) {
- ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
- }
- numNodes = nodeLump->filelen / sizeof(dnode_t);
- numLeafs = leafLump->filelen / sizeof(dleaf_t);
-
- out = ri.Hunk_Alloc ( (numNodes + numLeafs) * sizeof(*out), h_low);
-
- s_worldData.nodes = out;
- s_worldData.numnodes = numNodes + numLeafs;
- s_worldData.numDecisionNodes = numNodes;
-
- // load nodes
- for ( i=0 ; i<numNodes; i++, in++, out++)
- {
- for (j=0 ; j<3 ; j++)
- {
- out->mins[j] = LittleLong (in->mins[j]);
- out->maxs[j] = LittleLong (in->maxs[j]);
- }
-
- p = LittleLong(in->planeNum);
- out->plane = s_worldData.planes + p;
-
- out->contents = CONTENTS_NODE; // differentiate from leafs
-
- for (j=0 ; j<2 ; j++)
- {
- p = LittleLong (in->children[j]);
- if (p >= 0)
- out->children[j] = s_worldData.nodes + p;
- else
- out->children[j] = s_worldData.nodes + numNodes + (-1 - p);
- }
- }
-
- // load leafs
- inLeaf = (void *)(fileBase + leafLump->fileofs);
- for ( i=0 ; i<numLeafs ; i++, inLeaf++, out++)
- {
- for (j=0 ; j<3 ; j++)
- {
- out->mins[j] = LittleLong (inLeaf->mins[j]);
- out->maxs[j] = LittleLong (inLeaf->maxs[j]);
- }
-
- out->cluster = LittleLong(inLeaf->cluster);
- out->area = LittleLong(inLeaf->area);
-
- if ( out->cluster >= s_worldData.numClusters ) {
- s_worldData.numClusters = out->cluster + 1;
- }
-
- out->firstmarksurface = LittleLong(inLeaf->firstLeafSurface);
- out->nummarksurfaces = LittleLong(inLeaf->numLeafSurfaces);
- }
-
- // chain decendants
- R_SetParent (s_worldData.nodes, NULL);
-}
-
-//=============================================================================
-
-/*
-=================
-R_LoadShaders
-=================
-*/
-static void R_LoadShaders( lump_t *l ) {
- int i, count;
- dshader_t *in, *out;
-
- in = (void *)(fileBase + l->fileofs);
- if (l->filelen % sizeof(*in))
- ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
- count = l->filelen / sizeof(*in);
- out = ri.Hunk_Alloc ( count*sizeof(*out), h_low );
-
- s_worldData.shaders = out;
- s_worldData.numShaders = count;
-
- Com_Memcpy( out, in, count*sizeof(*out) );
-
- for ( i=0 ; i<count ; i++ ) {
- out[i].surfaceFlags = LittleLong( out[i].surfaceFlags );
- out[i].contentFlags = LittleLong( out[i].contentFlags );
- }
-}
-
-
-/*
-=================
-R_LoadMarksurfaces
-=================
-*/
-static void R_LoadMarksurfaces (lump_t *l)
-{
- int i, j, count;
- int *in;
- int *out;
-
- in = (void *)(fileBase + l->fileofs);
- if (l->filelen % sizeof(*in))
- ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
- count = l->filelen / sizeof(*in);
- out = ri.Hunk_Alloc ( count*sizeof(*out), h_low);
-
- s_worldData.marksurfaces = out;
- s_worldData.nummarksurfaces = count;
-
- for ( i=0 ; i<count ; i++)
- {
- j = LittleLong(in[i]);
- out[i] = j;
- }
-}
-
-
-/*
-=================
-R_LoadPlanes
-=================
-*/
-static void R_LoadPlanes( lump_t *l ) {
- int i, j;
- cplane_t *out;
- dplane_t *in;
- int count;
- int bits;
-
- in = (void *)(fileBase + l->fileofs);
- if (l->filelen % sizeof(*in))
- ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
- count = l->filelen / sizeof(*in);
- out = ri.Hunk_Alloc ( count*2*sizeof(*out), h_low);
-
- s_worldData.planes = out;
- s_worldData.numplanes = count;
-
- for ( i=0 ; i<count ; i++, in++, out++) {
- bits = 0;
- for (j=0 ; j<3 ; j++) {
- out->normal[j] = LittleFloat (in->normal[j]);
- if (out->normal[j] < 0) {
- bits |= 1<<j;
- }
- }
-
- out->dist = LittleFloat (in->dist);
- out->type = PlaneTypeForNormal( out->normal );
- out->signbits = bits;
- }
-}
-
-/*
-=================
-R_LoadFogs
-
-=================
-*/
-static void R_LoadFogs( lump_t *l, lump_t *brushesLump, lump_t *sidesLump ) {
- int i;
- fog_t *out;
- dfog_t *fogs;
- dbrush_t *brushes, *brush;
- dbrushside_t *sides;
- int count, brushesCount, sidesCount;
- int sideNum;
- int planeNum;
- shader_t *shader;
- float d;
- int firstSide;
-
- fogs = (void *)(fileBase + l->fileofs);
- if (l->filelen % sizeof(*fogs)) {
- ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
- }
- count = l->filelen / sizeof(*fogs);
-
- // create fog strucutres for them
- s_worldData.numfogs = count + 1;
- s_worldData.fogs = ri.Hunk_Alloc ( s_worldData.numfogs*sizeof(*out), h_low);
- out = s_worldData.fogs + 1;
-
- if ( !count ) {
- return;
- }
-
- brushes = (void *)(fileBase + brushesLump->fileofs);
- if (brushesLump->filelen % sizeof(*brushes)) {
- ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
- }
- brushesCount = brushesLump->filelen / sizeof(*brushes);
-
- sides = (void *)(fileBase + sidesLump->fileofs);
- if (sidesLump->filelen % sizeof(*sides)) {
- ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name);
- }
- sidesCount = sidesLump->filelen / sizeof(*sides);
-
- for ( i=0 ; i<count ; i++, fogs++) {
- out->originalBrushNumber = LittleLong( fogs->brushNum );
-
- if ( (unsigned)out->originalBrushNumber >= brushesCount ) {
- ri.Error( ERR_DROP, "fog brushNumber out of range" );
- }
- brush = brushes + out->originalBrushNumber;
-
- firstSide = LittleLong( brush->firstSide );
-
- if ( (unsigned)firstSide > sidesCount - 6 ) {
- ri.Error( ERR_DROP, "fog brush sideNumber out of range" );
- }
-
- // brushes are always sorted with the axial sides first
- sideNum = firstSide + 0;
- planeNum = LittleLong( sides[ sideNum ].planeNum );
- out->bounds[0][0] = -s_worldData.planes[ planeNum ].dist;
-
- sideNum = firstSide + 1;
- planeNum = LittleLong( sides[ sideNum ].planeNum );
- out->bounds[1][0] = s_worldData.planes[ planeNum ].dist;
-
- sideNum = firstSide + 2;
- planeNum = LittleLong( sides[ sideNum ].planeNum );
- out->bounds[0][1] = -s_worldData.planes[ planeNum ].dist;
-
- sideNum = firstSide + 3;
- planeNum = LittleLong( sides[ sideNum ].planeNum );
- out->bounds[1][1] = s_worldData.planes[ planeNum ].dist;
-
- sideNum = firstSide + 4;
- planeNum = LittleLong( sides[ sideNum ].planeNum );
- out->bounds[0][2] = -s_worldData.planes[ planeNum ].dist;
-
- sideNum = firstSide + 5;
- planeNum = LittleLong( sides[ sideNum ].planeNum );
- out->bounds[1][2] = s_worldData.planes[ planeNum ].dist;
-
- // get information from the shader for fog parameters
- shader = R_FindShader( fogs->shader, LIGHTMAP_NONE, qtrue );
-
- out->parms = shader->fogParms;
-
- out->colorInt = ColorBytes4 ( shader->fogParms.color[0] * tr.identityLight,
- shader->fogParms.color[1] * tr.identityLight,
- shader->fogParms.color[2] * tr.identityLight, 1.0 );
-
- d = shader->fogParms.depthForOpaque < 1 ? 1 : shader->fogParms.depthForOpaque;
- out->tcScale = 1.0f / ( d * 8 );
-
- // set the gradient vector
- sideNum = LittleLong( fogs->visibleSide );
-
- if ( sideNum == -1 ) {
- out->hasSurface = qfalse;
- } else {
- out->hasSurface = qtrue;
- planeNum = LittleLong( sides[ firstSide + sideNum ].planeNum );
- VectorSubtract( vec3_origin, s_worldData.planes[ planeNum ].normal, out->surface );
- out->surface[3] = -s_worldData.planes[ planeNum ].dist;
- }
-
- out++;
- }
-
-}
-
-
-/*
-================
-R_LoadLightGrid
-
-================
-*/
-void R_LoadLightGrid( lump_t *l ) {
- int i;
- vec3_t maxs;
- int numGridPoints;
- world_t *w;
- float *wMins, *wMaxs;
-
- w = &s_worldData;
-
- w->lightGridInverseSize[0] = 1.0f / w->lightGridSize[0];
- w->lightGridInverseSize[1] = 1.0f / w->lightGridSize[1];
- w->lightGridInverseSize[2] = 1.0f / w->lightGridSize[2];
-
- wMins = w->bmodels[0].bounds[0];
- wMaxs = w->bmodels[0].bounds[1];
-
- for ( i = 0 ; i < 3 ; i++ ) {
- w->lightGridOrigin[i] = w->lightGridSize[i] * ceil( wMins[i] / w->lightGridSize[i] );
- maxs[i] = w->lightGridSize[i] * floor( wMaxs[i] / w->lightGridSize[i] );
- w->lightGridBounds[i] = (maxs[i] - w->lightGridOrigin[i])/w->lightGridSize[i] + 1;
- }
-
- numGridPoints = w->lightGridBounds[0] * w->lightGridBounds[1] * w->lightGridBounds[2];
-
- if ( l->filelen != numGridPoints * 8 ) {
- ri.Printf( PRINT_WARNING, "WARNING: light grid mismatch\n" );
- w->lightGridData = NULL;
- return;
- }
-
- w->lightGridData = ri.Hunk_Alloc( l->filelen, h_low );
- Com_Memcpy( w->lightGridData, (void *)(fileBase + l->fileofs), l->filelen );
-
- // deal with overbright bits
- for ( i = 0 ; i < numGridPoints ; i++ ) {
- R_ColorShiftLightingBytes( &w->lightGridData[i*8], &w->lightGridData[i*8] );
- R_ColorShiftLightingBytes( &w->lightGridData[i*8+3], &w->lightGridData[i*8+3] );
- }
-
- // load hdr lightgrid
- if (r_hdr->integer)
- {
- char filename[MAX_QPATH];
- float *hdrLightGrid;
- int size;
-
- Com_sprintf( filename, sizeof( filename ), "maps/%s/lightgrid.raw", s_worldData.baseName);
- //ri.Printf(PRINT_ALL, "looking for %s\n", filename);
-
- size = ri.FS_ReadFile(filename, (void **)&hdrLightGrid);
-
- if (hdrLightGrid)
- {
- float lightScale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits);
-
- //ri.Printf(PRINT_ALL, "found!\n");
-
- if (size != sizeof(float) * 6 * numGridPoints)
- {
- ri.Error(ERR_DROP, "Bad size for %s (%i, expected %i)!\n", filename, size, (int)(sizeof(float)) * 6 * numGridPoints);
- }
-
- w->hdrLightGrid = ri.Hunk_Alloc(size, h_low);
-
- for (i = 0; i < numGridPoints ; i++)
- {
- w->hdrLightGrid[i * 6 ] = hdrLightGrid[i * 6 ] * lightScale;
- w->hdrLightGrid[i * 6 + 1] = hdrLightGrid[i * 6 + 1] * lightScale;
- w->hdrLightGrid[i * 6 + 2] = hdrLightGrid[i * 6 + 2] * lightScale;
- w->hdrLightGrid[i * 6 + 3] = hdrLightGrid[i * 6 + 3] * lightScale;
- w->hdrLightGrid[i * 6 + 4] = hdrLightGrid[i * 6 + 4] * lightScale;
- w->hdrLightGrid[i * 6 + 5] = hdrLightGrid[i * 6 + 5] * lightScale;
- }
- }
-
- if (hdrLightGrid)
- ri.FS_FreeFile(hdrLightGrid);
- }
-}
-
-/*
-================
-R_LoadEntities
-================
-*/
-void R_LoadEntities( lump_t *l ) {
- char *p, *token, *s;
- char keyname[MAX_TOKEN_CHARS];
- char value[MAX_TOKEN_CHARS];
- world_t *w;
-
- w = &s_worldData;
- w->lightGridSize[0] = 64;
- w->lightGridSize[1] = 64;
- w->lightGridSize[2] = 128;
-
- p = (char *)(fileBase + l->fileofs);
-
- // store for reference by the cgame
- w->entityString = ri.Hunk_Alloc( l->filelen + 1, h_low );
- strcpy( w->entityString, p );
- w->entityParsePoint = w->entityString;
-
- token = COM_ParseExt( &p, qtrue );
- if (!*token || *token != '{') {
- return;
- }
-
- // only parse the world spawn
- while ( 1 ) {
- // parse key
- token = COM_ParseExt( &p, qtrue );
-
- if ( !*token || *token == '}' ) {
- break;
- }
- Q_strncpyz(keyname, token, sizeof(keyname));
-
- // parse value
- token = COM_ParseExt( &p, qtrue );
-
- if ( !*token || *token == '}' ) {
- break;
- }
- Q_strncpyz(value, token, sizeof(value));
-
- // check for remapping of shaders for vertex lighting
- s = "vertexremapshader";
- if (!Q_strncmp(keyname, s, strlen(s)) ) {
- s = strchr(value, ';');
- if (!s) {
- ri.Printf( PRINT_WARNING, "WARNING: no semi colon in vertexshaderremap '%s'\n", value );
- break;
- }
- *s++ = 0;
- if (r_vertexLight->integer) {
- R_RemapShader(value, s, "0");
- }
- continue;
- }
- // check for remapping of shaders
- s = "remapshader";
- if (!Q_strncmp(keyname, s, strlen(s)) ) {
- s = strchr(value, ';');
- if (!s) {
- ri.Printf( PRINT_WARNING, "WARNING: no semi colon in shaderremap '%s'\n", value );
- break;
- }
- *s++ = 0;
- R_RemapShader(value, s, "0");
- continue;
- }
- // check for a different grid size
- if (!Q_stricmp(keyname, "gridsize")) {
- sscanf(value, "%f %f %f", &w->lightGridSize[0], &w->lightGridSize[1], &w->lightGridSize[2] );
- continue;
- }
-
- // check for auto exposure
- if (!Q_stricmp(keyname, "autoExposureMinMax")) {
- sscanf(value, "%f %f", &tr.autoExposureMinMax[0], &tr.autoExposureMinMax[1]);
- continue;
- }
- }
-}
-
-/*
-=================
-R_GetEntityToken
-=================
-*/
-qboolean R_GetEntityToken( char *buffer, int size ) {
- const char *s;
-
- s = COM_Parse( &s_worldData.entityParsePoint );
- Q_strncpyz( buffer, s, size );
- if ( !s_worldData.entityParsePoint || !s[0] ) {
- s_worldData.entityParsePoint = s_worldData.entityString;
- return qfalse;
- } else {
- return qtrue;
- }
-}
-
-
-/*
-=================
-R_MergeLeafSurfaces
-
-Merges surfaces that share a common leaf
-=================
-*/
-void R_MergeLeafSurfaces(void)
-{
- int i, j, k;
- int numWorldSurfaces;
- int mergedSurfIndex;
- int numMergedSurfaces;
- int numUnmergedSurfaces;
- IBO_t *ibo;
-
- msurface_t *mergedSurf;
-
- glIndex_t *iboIndexes, *outIboIndexes;
- int numIboIndexes;
-
- int startTime, endTime;
-
- startTime = ri.Milliseconds();
-
- numWorldSurfaces = s_worldData.numWorldSurfaces;
-
- // use viewcount to keep track of mergers
- for (i = 0; i < numWorldSurfaces; i++)
- {
- s_worldData.surfacesViewCount[i] = -1;
- }
-
- // create ibo
- ibo = tr.ibos[tr.numIBOs++] = ri.Hunk_Alloc(sizeof(*ibo), h_low);
- memset(ibo, 0, sizeof(*ibo));
- Q_strncpyz(ibo->name, "staticWorldMesh_IBO_mergedSurfs", sizeof(ibo->name));
-
- // allocate more than we need
- iboIndexes = outIboIndexes = ri.Malloc(s_worldData.ibo->indexesSize);
-
- // mark matching surfaces
- for (i = 0; i < s_worldData.numnodes - s_worldData.numDecisionNodes; i++)
- {
- mnode_t *leaf = s_worldData.nodes + s_worldData.numDecisionNodes + i;
-
- for (j = 0; j < leaf->nummarksurfaces; j++)
- {
- msurface_t *surf1;
- shader_t *shader1;
- int fogIndex1;
- int surfNum1;
-
- surfNum1 = *(s_worldData.marksurfaces + leaf->firstmarksurface + j);
-
- if (s_worldData.surfacesViewCount[surfNum1] != -1)
- continue;
-
- surf1 = s_worldData.surfaces + surfNum1;
-
- if ((*surf1->data != SF_GRID) && (*surf1->data != SF_TRIANGLES) && (*surf1->data != SF_FACE))
- continue;
-
- shader1 = surf1->shader;
-
- if(shader1->isSky)
- continue;
-
- if(shader1->isPortal)
- continue;
-
- if(ShaderRequiresCPUDeforms(shader1))
- continue;
-
- fogIndex1 = surf1->fogIndex;
-
- s_worldData.surfacesViewCount[surfNum1] = surfNum1;
-
- for (k = j + 1; k < leaf->nummarksurfaces; k++)
- {
- msurface_t *surf2;
- shader_t *shader2;
- int fogIndex2;
- int surfNum2;
-
- surfNum2 = *(s_worldData.marksurfaces + leaf->firstmarksurface + k);
-
- if (s_worldData.surfacesViewCount[surfNum2] != -1)
- continue;
-
- surf2 = s_worldData.surfaces + surfNum2;
-
- if ((*surf2->data != SF_GRID) && (*surf2->data != SF_TRIANGLES) && (*surf2->data != SF_FACE))
- continue;
-
- shader2 = surf2->shader;
-
- if (shader1 != shader2)
- continue;
-
- fogIndex2 = surf2->fogIndex;
-
- if (fogIndex1 != fogIndex2)
- continue;
-
- s_worldData.surfacesViewCount[surfNum2] = surfNum1;
- }
- }
- }
-
- // don't add surfaces that don't merge to any others to the merged list
- for (i = 0; i < numWorldSurfaces; i++)
- {
- qboolean merges = qfalse;
-
- if (s_worldData.surfacesViewCount[i] != i)
- continue;
-
- for (j = 0; j < numWorldSurfaces; j++)
- {
- if (j == i)
- continue;
-
- if (s_worldData.surfacesViewCount[j] == i)
- {
- merges = qtrue;
- break;
- }
- }
-
- if (!merges)
- s_worldData.surfacesViewCount[i] = -1;
- }
-
- // count merged/unmerged surfaces
- numMergedSurfaces = 0;
- numUnmergedSurfaces = 0;
- for (i = 0; i < numWorldSurfaces; i++)
- {
- if (s_worldData.surfacesViewCount[i] == i)
- {
- numMergedSurfaces++;
- }
- else if (s_worldData.surfacesViewCount[i] == -1)
- {
- numUnmergedSurfaces++;
- }
- }
-
- // Allocate merged surfaces
- s_worldData.mergedSurfaces = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfaces) * numMergedSurfaces, h_low);
- s_worldData.mergedSurfacesViewCount = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesViewCount) * numMergedSurfaces, h_low);
- s_worldData.mergedSurfacesDlightBits = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesDlightBits) * numMergedSurfaces, h_low);
- s_worldData.mergedSurfacesPshadowBits = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesPshadowBits) * numMergedSurfaces, h_low);
- s_worldData.numMergedSurfaces = numMergedSurfaces;
-
- // view surfaces are like mark surfaces, except negative ones represent merged surfaces
- // -1 represents 0, -2 represents 1, and so on
- s_worldData.viewSurfaces = ri.Hunk_Alloc(sizeof(*s_worldData.viewSurfaces) * s_worldData.nummarksurfaces, h_low);
-
- // copy view surfaces into mark surfaces
- for (i = 0; i < s_worldData.nummarksurfaces; i++)
- {
- s_worldData.viewSurfaces[i] = s_worldData.marksurfaces[i];
- }
-
- // actually merge surfaces
- numIboIndexes = 0;
- mergedSurfIndex = 0;
- mergedSurf = s_worldData.mergedSurfaces;
- for (i = 0; i < numWorldSurfaces; i++)
- {
- msurface_t *surf1;
-
- vec3_t bounds[2];
-
- int numSurfsToMerge;
- int numTriangles;
- int numVerts;
- int firstIndex;
-
- srfVBOMesh_t *vboSurf;
-
- if (s_worldData.surfacesViewCount[i] != i)
- continue;
-
- surf1 = s_worldData.surfaces + i;
-
- // count verts, indexes, and surfaces
- numSurfsToMerge = 0;
- numTriangles = 0;
- numVerts = 0;
- for (j = 0; j < numWorldSurfaces; j++)
- {
- msurface_t *surf2;
-
- if (s_worldData.surfacesViewCount[j] != i)
- continue;
-
- surf2 = s_worldData.surfaces + j;
-
- switch(*surf2->data)
- {
- case SF_FACE:
- {
- srfSurfaceFace_t *face;
-
- face = (srfSurfaceFace_t *) surf2->data;
- numTriangles += face->numTriangles;
- numVerts += face->numVerts;
- }
- break;
-
- case SF_GRID:
- {
- srfGridMesh_t *grid;
-
- grid = (srfGridMesh_t *) surf2->data;
- numTriangles += grid->numTriangles;
- numVerts += grid->numVerts;
- }
- break;
-
- case SF_TRIANGLES:
- {
- srfTriangles_t *tris;
-
- tris = (srfTriangles_t *) surf2->data;
- numTriangles += tris->numTriangles;
- numVerts += tris->numVerts;
- }
- break;
-
- default:
- break;
- }
-
- numSurfsToMerge++;
- }
-
- if (numVerts == 0 || numTriangles == 0 || numSurfsToMerge < 2)
- {
- continue;
- }
-
- // Merge surfaces (indexes) and calculate bounds
- ClearBounds(bounds[0], bounds[1]);
- firstIndex = numIboIndexes;
- for (j = 0; j < numWorldSurfaces; j++)
- {
- msurface_t *surf2;
-
- if (s_worldData.surfacesViewCount[j] != i)
- continue;
-
- surf2 = s_worldData.surfaces + j;
-
- AddPointToBounds(surf2->cullinfo.bounds[0], bounds[0], bounds[1]);
- AddPointToBounds(surf2->cullinfo.bounds[1], bounds[0], bounds[1]);
-
- switch(*surf2->data)
- {
- case SF_FACE:
- {
- srfSurfaceFace_t *face;
-
- face = (srfSurfaceFace_t *) surf2->data;
-
- for (k = 0; k < face->numTriangles; k++)
- {
- *outIboIndexes++ = face->triangles[k].indexes[0] + face->firstVert;
- *outIboIndexes++ = face->triangles[k].indexes[1] + face->firstVert;
- *outIboIndexes++ = face->triangles[k].indexes[2] + face->firstVert;
- numIboIndexes += 3;
- }
- }
- break;
-
- case SF_GRID:
- {
- srfGridMesh_t *grid;
-
- grid = (srfGridMesh_t *) surf2->data;
-
- for (k = 0; k < grid->numTriangles; k++)
- {
- *outIboIndexes++ = grid->triangles[k].indexes[0] + grid->firstVert;
- *outIboIndexes++ = grid->triangles[k].indexes[1] + grid->firstVert;
- *outIboIndexes++ = grid->triangles[k].indexes[2] + grid->firstVert;
- numIboIndexes += 3;
- }
- }
- break;
-
- case SF_TRIANGLES:
- {
- srfTriangles_t *tris;
-
- tris = (srfTriangles_t *) surf2->data;
-
- for (k = 0; k < tris->numTriangles; k++)
- {
- *outIboIndexes++ = tris->triangles[k].indexes[0] + tris->firstVert;
- *outIboIndexes++ = tris->triangles[k].indexes[1] + tris->firstVert;
- *outIboIndexes++ = tris->triangles[k].indexes[2] + tris->firstVert;
- numIboIndexes += 3;
- }
- }
- break;
-
- // never happens, but silences a compile warning
- default:
- break;
- }
- }
-
- vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low);
- memset(vboSurf, 0, sizeof(*vboSurf));
- vboSurf->surfaceType = SF_VBO_MESH;
-
- vboSurf->vbo = s_worldData.vbo;
- vboSurf->ibo = ibo;
-
- vboSurf->numIndexes = numTriangles * 3;
- vboSurf->numVerts = numVerts;
- vboSurf->firstIndex = firstIndex;
-
- vboSurf->minIndex = *(iboIndexes + firstIndex);
- vboSurf->maxIndex = *(iboIndexes + firstIndex);
-
- for (j = 1; j < numTriangles * 3; j++)
- {
- vboSurf->minIndex = MIN(vboSurf->minIndex, *(iboIndexes + firstIndex + j));
- vboSurf->maxIndex = MAX(vboSurf->maxIndex, *(iboIndexes + firstIndex + j));
- }
-
- vboSurf->shader = surf1->shader;
- vboSurf->fogIndex = surf1->fogIndex;
-
- VectorCopy(bounds[0], vboSurf->bounds[0]);
- VectorCopy(bounds[1], vboSurf->bounds[1]);
-
- VectorCopy(bounds[0], mergedSurf->cullinfo.bounds[0]);
- VectorCopy(bounds[1], mergedSurf->cullinfo.bounds[1]);
-
- mergedSurf->cullinfo.type = CULLINFO_BOX;
- mergedSurf->data = (surfaceType_t *)vboSurf;
- mergedSurf->fogIndex = surf1->fogIndex;
- mergedSurf->shader = surf1->shader;
-
- // redirect view surfaces to this surf
- for (j = 0; j < numWorldSurfaces; j++)
- {
- if (s_worldData.surfacesViewCount[j] != i)
- continue;
-
- for (k = 0; k < s_worldData.nummarksurfaces; k++)
- {
- int *mark = s_worldData.marksurfaces + k;
- int *view = s_worldData.viewSurfaces + k;
-
- if (*mark == j)
- *view = -(mergedSurfIndex + 1);
- }
- }
-
- mergedSurfIndex++;
- mergedSurf++;
- }
-
- // finish up the ibo
- R_IssuePendingRenderCommands();
-
- qglGenBuffersARB(1, &ibo->indexesVBO);
-
- R_BindIBO(ibo);
-
- qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, numIboIndexes * sizeof(*iboIndexes), iboIndexes, GL_STATIC_DRAW_ARB);
-
- R_BindNullIBO();
-
- GL_CheckErrors();
-
- ri.Free(iboIndexes);
-
- endTime = ri.Milliseconds();
-
- ri.Printf(PRINT_ALL, "Processed %d surfaces into %d merged, %d unmerged in %5.2f seconds\n",
- numWorldSurfaces, numMergedSurfaces, numUnmergedSurfaces, (endTime - startTime) / 1000.0f);
-
- // reset viewcounts
- for (i = 0; i < numWorldSurfaces; i++)
- {
- s_worldData.surfacesViewCount[i] = -1;
- }
-}
-
-
-void R_CalcVertexLightDirs( void )
-{
- int i, k;
- msurface_t *surface;
-
- for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numsurfaces /* s_worldData.numWorldSurfaces */; k++, surface++)
- {
- if(*surface->data == SF_FACE)
- {
- srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
-
- if(srf->numVerts)
- {
- for(i = 0; i < srf->numVerts; i++)
- {
- R_LightDirForPoint( srf->verts[i].xyz, srf->verts[i].lightdir, srf->verts[i].normal, &s_worldData );
- }
- }
- }
- else if(*surface->data == SF_GRID)
- {
- srfGridMesh_t *srf = (srfGridMesh_t *) surface->data;
-
- if(srf->numVerts)
- {
- for(i = 0; i < srf->numVerts; i++)
- {
- R_LightDirForPoint( srf->verts[i].xyz, srf->verts[i].lightdir, srf->verts[i].normal, &s_worldData );
- }
- }
- }
- else if(*surface->data == SF_TRIANGLES)
- {
- srfTriangles_t *srf = (srfTriangles_t *) surface->data;
-
- if(srf->numVerts)
- {
- for(i = 0; i < srf->numVerts; i++)
- {
- R_LightDirForPoint( srf->verts[i].xyz, srf->verts[i].lightdir, srf->verts[i].normal, &s_worldData );
- }
- }
- }
- }
-}
-
-
-/*
-=================
-RE_LoadWorldMap
-
-Called directly from cgame
-=================
-*/
-void RE_LoadWorldMap( const char *name ) {
- int i;
- dheader_t *header;
- union {
- byte *b;
- void *v;
- } buffer;
- byte *startMarker;
-
- if ( tr.worldMapLoaded ) {
- ri.Error( ERR_DROP, "ERROR: attempted to redundantly load world map" );
- }
-
- // set default map light scale
- tr.mapLightScale = 1.0f;
-
- // set default sun direction to be used if it isn't
- // overridden by a shader
- tr.sunDirection[0] = 0.45f;
- tr.sunDirection[1] = 0.3f;
- tr.sunDirection[2] = 0.9f;
-
- VectorNormalize( tr.sunDirection );
-
- // set default autoexposure settings
- tr.autoExposureMinMax[0] = -2.0f;
- tr.autoExposureMinMax[1] = 2.0f;
-
- // set default tone mapping settings
- tr.toneMinAvgMaxLevel[0] = -8.0f;
- tr.toneMinAvgMaxLevel[1] = -2.0f;
- tr.toneMinAvgMaxLevel[2] = 0.0f;
-
- tr.worldMapLoaded = qtrue;
-
- // load it
- ri.FS_ReadFile( name, &buffer.v );
- if ( !buffer.b ) {
- ri.Error (ERR_DROP, "RE_LoadWorldMap: %s not found", name);
- }
-
- // clear tr.world so if the level fails to load, the next
- // try will not look at the partially loaded version
- tr.world = NULL;
-
- Com_Memset( &s_worldData, 0, sizeof( s_worldData ) );
- Q_strncpyz( s_worldData.name, name, sizeof( s_worldData.name ) );
-
- Q_strncpyz( s_worldData.baseName, COM_SkipPath( s_worldData.name ), sizeof( s_worldData.name ) );
- COM_StripExtension(s_worldData.baseName, s_worldData.baseName, sizeof(s_worldData.baseName));
-
- startMarker = ri.Hunk_Alloc(0, h_low);
- c_gridVerts = 0;
-
- header = (dheader_t *)buffer.b;
- fileBase = (byte *)header;
-
- i = LittleLong (header->version);
- if ( i != BSP_VERSION ) {
- ri.Error (ERR_DROP, "RE_LoadWorldMap: %s has wrong version number (%i should be %i)",
- name, i, BSP_VERSION);
- }
-
- // swap all the lumps
- for (i=0 ; i<sizeof(dheader_t)/4 ; i++) {
- ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
- }
-
- // load into heap
- R_LoadEntities( &header->lumps[LUMP_ENTITIES] );
- R_LoadShaders( &header->lumps[LUMP_SHADERS] );
- R_LoadLightmaps( &header->lumps[LUMP_LIGHTMAPS], &header->lumps[LUMP_SURFACES] );
- R_LoadPlanes (&header->lumps[LUMP_PLANES]);
- R_LoadFogs( &header->lumps[LUMP_FOGS], &header->lumps[LUMP_BRUSHES], &header->lumps[LUMP_BRUSHSIDES] );
- R_LoadSurfaces( &header->lumps[LUMP_SURFACES], &header->lumps[LUMP_DRAWVERTS], &header->lumps[LUMP_DRAWINDEXES] );
- R_LoadMarksurfaces (&header->lumps[LUMP_LEAFSURFACES]);
- R_LoadNodesAndLeafs (&header->lumps[LUMP_NODES], &header->lumps[LUMP_LEAFS]);
- R_LoadSubmodels (&header->lumps[LUMP_MODELS]);
- R_LoadVisibility( &header->lumps[LUMP_VISIBILITY] );
- R_LoadLightGrid( &header->lumps[LUMP_LIGHTGRID] );
-
- // determine vertex light directions
- R_CalcVertexLightDirs();
-
- // create static VBOS from the world
- R_CreateWorldVBO();
- if (r_mergeLeafSurfaces->integer)
- {
- R_MergeLeafSurfaces();
- }
-
- s_worldData.dataSize = (byte *)ri.Hunk_Alloc(0, h_low) - startMarker;
-
- // only set tr.world now that we know the entire level has loaded properly
- tr.world = &s_worldData;
-
- // make sure the VBO glState entries are safe
- R_BindNullVBO();
- R_BindNullIBO();
-
- ri.FS_FreeFile( buffer.v );
-}
diff --git a/src/rend2/tr_cmds.c b/src/rend2/tr_cmds.c
deleted file mode 100644
index 622b401a..00000000
--- a/src/rend2/tr_cmds.c
+++ /dev/null
@@ -1,668 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-#include "tr_local.h"
-
-volatile renderCommandList_t *renderCommandList;
-
-/*
-=====================
-R_PerformanceCounters
-=====================
-*/
-void R_PerformanceCounters( void ) {
- if ( !r_speeds->integer ) {
- // clear the counters even if we aren't printing
- Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );
- Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
- return;
- }
-
- if (r_speeds->integer == 1) {
- ri.Printf (PRINT_ALL, "%i/%i/%i shaders/batches/surfs %i leafs %i verts %i/%i tris %.2f mtex %.2f dc\n",
- backEnd.pc.c_shaders, backEnd.pc.c_surfBatches, backEnd.pc.c_surfaces, tr.pc.c_leafs, backEnd.pc.c_vertexes,
- backEnd.pc.c_indexes/3, backEnd.pc.c_totalIndexes/3,
- R_SumOfUsedImages()/(1000000.0f), backEnd.pc.c_overDraw / (float)(glConfig.vidWidth * glConfig.vidHeight) );
- } else if (r_speeds->integer == 2) {
- ri.Printf (PRINT_ALL, "(patch) %i sin %i sclip %i sout %i bin %i bclip %i bout\n",
- tr.pc.c_sphere_cull_patch_in, tr.pc.c_sphere_cull_patch_clip, tr.pc.c_sphere_cull_patch_out,
- tr.pc.c_box_cull_patch_in, tr.pc.c_box_cull_patch_clip, tr.pc.c_box_cull_patch_out );
- ri.Printf (PRINT_ALL, "(md3) %i sin %i sclip %i sout %i bin %i bclip %i bout\n",
- tr.pc.c_sphere_cull_md3_in, tr.pc.c_sphere_cull_md3_clip, tr.pc.c_sphere_cull_md3_out,
- tr.pc.c_box_cull_md3_in, tr.pc.c_box_cull_md3_clip, tr.pc.c_box_cull_md3_out );
- } else if (r_speeds->integer == 3) {
- ri.Printf (PRINT_ALL, "viewcluster: %i\n", tr.viewCluster );
- } else if (r_speeds->integer == 4) {
- if ( backEnd.pc.c_dlightVertexes ) {
- ri.Printf (PRINT_ALL, "dlight srf:%i culled:%i verts:%i tris:%i\n",
- tr.pc.c_dlightSurfaces, tr.pc.c_dlightSurfacesCulled,
- backEnd.pc.c_dlightVertexes, backEnd.pc.c_dlightIndexes / 3 );
- }
- }
- else if (r_speeds->integer == 5 )
- {
- ri.Printf( PRINT_ALL, "zFar: %.0f\n", tr.viewParms.zFar );
- }
- else if (r_speeds->integer == 6 )
- {
- ri.Printf( PRINT_ALL, "flare adds:%i tests:%i renders:%i\n",
- backEnd.pc.c_flareAdds, backEnd.pc.c_flareTests, backEnd.pc.c_flareRenders );
- }
- else if (r_speeds->integer == 7 )
- {
- ri.Printf( PRINT_ALL, "VBO draws: static %i dynamic %i\nMultidraws: %i merged %i\n",
- backEnd.pc.c_staticVboDraws, backEnd.pc.c_dynamicVboDraws, backEnd.pc.c_multidraws, backEnd.pc.c_multidrawsMerged );
- ri.Printf( PRINT_ALL, "GLSL binds: %i draws: gen %i light %i fog %i dlight %i\n",
- backEnd.pc.c_glslShaderBinds, backEnd.pc.c_genericDraws, backEnd.pc.c_lightallDraws, backEnd.pc.c_fogDraws, backEnd.pc.c_dlightDraws);
- }
-
- Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );
- Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
-}
-
-
-/*
-====================
-R_IssueRenderCommands
-====================
-*/
-void R_IssueRenderCommands( qboolean runPerformanceCounters ) {
- renderCommandList_t *cmdList;
-
- cmdList = &backEndData->commands;
- assert(cmdList);
- // add an end-of-list command
- *(int *)(cmdList->cmds + cmdList->used) = RC_END_OF_LIST;
-
- // clear it out, in case this is a sync and not a buffer flip
- cmdList->used = 0;
-
- if ( runPerformanceCounters ) {
- R_PerformanceCounters();
- }
-
- // actually start the commands going
- if ( !r_skipBackEnd->integer ) {
- // let it start on the new batch
- RB_ExecuteRenderCommands( cmdList->cmds );
- }
-}
-
-
-/*
-====================
-R_IssuePendingRenderCommands
-
-Issue any pending commands and wait for them to complete.
-====================
-*/
-void R_IssuePendingRenderCommands( void ) {
- if ( !tr.registered ) {
- return;
- }
- R_IssueRenderCommands( qfalse );
-}
-
-/*
-============
-R_GetCommandBuffer
-
-make sure there is enough command space
-============
-*/
-void *R_GetCommandBuffer( int bytes ) {
- renderCommandList_t *cmdList;
-
- cmdList = &backEndData->commands;
- bytes = PAD(bytes, sizeof(void *));
-
- // always leave room for the end of list command
- if ( cmdList->used + bytes + 4 > MAX_RENDER_COMMANDS ) {
- if ( bytes > MAX_RENDER_COMMANDS - 4 ) {
- ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes );
- }
- // if we run out of room, just start dropping commands
- return NULL;
- }
-
- cmdList->used += bytes;
-
- return cmdList->cmds + cmdList->used - bytes;
-}
-
-
-/*
-=============
-R_AddDrawSurfCmd
-
-=============
-*/
-void R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs ) {
- drawSurfsCommand_t *cmd;
-
- cmd = R_GetCommandBuffer( sizeof( *cmd ) );
- if ( !cmd ) {
- return;
- }
- cmd->commandId = RC_DRAW_SURFS;
-
- cmd->drawSurfs = drawSurfs;
- cmd->numDrawSurfs = numDrawSurfs;
-
- cmd->refdef = tr.refdef;
- cmd->viewParms = tr.viewParms;
-}
-
-
-/*
-=============
-R_AddCapShadowmapCmd
-
-=============
-*/
-void R_AddCapShadowmapCmd( int map, int cubeSide ) {
- capShadowmapCommand_t *cmd;
-
- cmd = R_GetCommandBuffer( sizeof( *cmd ) );
- if ( !cmd ) {
- return;
- }
- cmd->commandId = RC_CAPSHADOWMAP;
-
- cmd->map = map;
- cmd->cubeSide = cubeSide;
-}
-
-
-/*
-=============
-R_PostProcessingCmd
-
-=============
-*/
-void R_AddPostProcessCmd( ) {
- postProcessCommand_t *cmd;
-
- cmd = R_GetCommandBuffer( sizeof( *cmd ) );
- if ( !cmd ) {
- return;
- }
- cmd->commandId = RC_POSTPROCESS;
-
- cmd->refdef = tr.refdef;
- cmd->viewParms = tr.viewParms;
-}
-
-/*
-=============
-RE_SetColor
-
-Passing NULL will set the color to white
-=============
-*/
-void RE_SetColor( const float *rgba ) {
- setColorCommand_t *cmd;
-
- if ( !tr.registered ) {
- return;
- }
- cmd = R_GetCommandBuffer( sizeof( *cmd ) );
- if ( !cmd ) {
- return;
- }
- cmd->commandId = RC_SET_COLOR;
- if ( !rgba ) {
- static float colorWhite[4] = { 1, 1, 1, 1 };
-
- rgba = colorWhite;
- }
-
- cmd->color[0] = rgba[0];
- cmd->color[1] = rgba[1];
- cmd->color[2] = rgba[2];
- cmd->color[3] = rgba[3];
-}
-
-/*
-=============
-R_ClipRegion
-=============
-*/
-static qboolean R_ClipRegion ( float *x, float *y, float *w, float *h,
- float *s1, float *t1, float *s2, float *t2 ) {
- float left, top, right, bottom;
- float _s1, _t1, _s2, _t2;
- float clipLeft, clipTop, clipRight, clipBottom;
-
- if (tr.clipRegion[2] <= tr.clipRegion[0] ||
- tr.clipRegion[3] <= tr.clipRegion[1] ) {
- return qfalse;
- }
-
- left = *x;
- top = *y;
- right = *x + *w;
- bottom = *y + *h;
-
- _s1 = *s1;
- _t1 = *t1;
- _s2 = *s2;
- _t2 = *t2;
-
- clipLeft = tr.clipRegion[0];
- clipTop = tr.clipRegion[1];
- clipRight = tr.clipRegion[2];
- clipBottom = tr.clipRegion[3];
-
- // Completely clipped away
- if ( right <= clipLeft || left >= clipRight ||
- bottom <= clipTop || top >= clipBottom ) {
- return qtrue;
- }
-
- // Clip left edge
- if ( left < clipLeft ) {
- float f = ( clipLeft - left ) / ( right - left );
- *s1 = ( f * ( _s2 - _s1 ) ) + _s1;
- *x = clipLeft;
- *w -= ( clipLeft - left );
- }
-
- // Clip right edge
- if ( right > clipRight ) {
- float f = ( clipRight - right ) / ( left - right );
- *s2 = ( f * ( _s1 - _s2 ) ) + _s2;
- *w = clipRight - *x;
- }
-
- // Clip top edge
- if ( top < clipTop ) {
- float f = ( clipTop - top ) / ( bottom - top );
- *t1 = ( f * ( _t2 - _t1 ) ) + _t1;
- *y = clipTop;
- *h -= ( clipTop - top );
- }
-
- // Clip bottom edge
- if ( bottom > clipBottom ) {
- float f = ( clipBottom - bottom ) / ( top - bottom );
- *t2 = ( f * ( _t1 - _t2 ) ) + _t2;
- *h = clipBottom - *y;
- }
-
- return qfalse;
-}
-
-/*
-=============
-RE_SetClipRegion
-=============
-*/
-void RE_SetClipRegion( const float *region ) {
- if ( region == NULL ) {
- Com_Memset( tr.clipRegion, 0, sizeof( vec4_t ) );
- } else {
- Vector4Copy( region, tr.clipRegion );
- }
-}
-
-/*
-=============
-RE_StretchPic
-=============
-*/
-void RE_StretchPic ( float x, float y, float w, float h,
- float s1, float t1, float s2, float t2, qhandle_t hShader ) {
- stretchPicCommand_t *cmd;
-
- if (!tr.registered) {
- return;
- }
- if (R_ClipRegion(&x, &y, &w, &h, &s1, &t1, &s2, &t2)) {
- return;
- }
- cmd = R_GetCommandBuffer( sizeof( *cmd ) );
- if ( !cmd ) {
- return;
- }
- cmd->commandId = RC_STRETCH_PIC;
- cmd->shader = R_GetShaderByHandle( hShader );
- cmd->x = x;
- cmd->y = y;
- cmd->w = w;
- cmd->h = h;
- cmd->s1 = s1;
- cmd->t1 = t1;
- cmd->s2 = s2;
- cmd->t2 = t2;
-}
-
-#define MODE_RED_CYAN 1
-#define MODE_RED_BLUE 2
-#define MODE_RED_GREEN 3
-#define MODE_GREEN_MAGENTA 4
-#define MODE_MAX MODE_GREEN_MAGENTA
-
-void R_SetColorMode(GLboolean *rgba, stereoFrame_t stereoFrame, int colormode)
-{
- rgba[0] = rgba[1] = rgba[2] = rgba[3] = GL_TRUE;
-
- if(colormode > MODE_MAX)
- {
- if(stereoFrame == STEREO_LEFT)
- stereoFrame = STEREO_RIGHT;
- else if(stereoFrame == STEREO_RIGHT)
- stereoFrame = STEREO_LEFT;
-
- colormode -= MODE_MAX;
- }
-
- if(colormode == MODE_GREEN_MAGENTA)
- {
- if(stereoFrame == STEREO_LEFT)
- rgba[0] = rgba[2] = GL_FALSE;
- else if(stereoFrame == STEREO_RIGHT)
- rgba[1] = GL_FALSE;
- }
- else
- {
- if(stereoFrame == STEREO_LEFT)
- rgba[1] = rgba[2] = GL_FALSE;
- else if(stereoFrame == STEREO_RIGHT)
- {
- rgba[0] = GL_FALSE;
-
- if(colormode == MODE_RED_BLUE)
- rgba[1] = GL_FALSE;
- else if(colormode == MODE_RED_GREEN)
- rgba[2] = GL_FALSE;
- }
- }
-}
-
-
-/*
-====================
-RE_BeginFrame
-
-If running in stereo, RE_BeginFrame will be called twice
-for each RE_EndFrame
-====================
-*/
-void RE_BeginFrame( stereoFrame_t stereoFrame ) {
- drawBufferCommand_t *cmd = NULL;
- colorMaskCommand_t *colcmd = NULL;
-
- if ( !tr.registered ) {
- return;
- }
- glState.finishCalled = qfalse;
-
- tr.frameCount++;
- tr.frameSceneNum = 0;
-
- //
- // do overdraw measurement
- //
- if ( r_measureOverdraw->integer )
- {
- if ( glConfig.stencilBits < 4 )
- {
- ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits );
- ri.Cvar_Set( "r_measureOverdraw", "0" );
- r_measureOverdraw->modified = qfalse;
- }
- else if ( r_shadows->integer == 2 )
- {
- ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" );
- ri.Cvar_Set( "r_measureOverdraw", "0" );
- r_measureOverdraw->modified = qfalse;
- }
- else
- {
- R_IssuePendingRenderCommands();
- qglEnable( GL_STENCIL_TEST );
- qglStencilMask( ~0U );
- qglClearStencil( 0U );
- qglStencilFunc( GL_ALWAYS, 0U, ~0U );
- qglStencilOp( GL_KEEP, GL_INCR, GL_INCR );
- }
- r_measureOverdraw->modified = qfalse;
- }
- else
- {
- // this is only reached if it was on and is now off
- if ( r_measureOverdraw->modified ) {
- R_IssuePendingRenderCommands();
- qglDisable( GL_STENCIL_TEST );
- }
- r_measureOverdraw->modified = qfalse;
- }
-
- //
- // texturemode stuff
- //
- if ( r_textureMode->modified ) {
- R_IssuePendingRenderCommands();
- GL_TextureMode( r_textureMode->string );
- r_textureMode->modified = qfalse;
- }
-
- //
- // gamma stuff
- //
- if ( r_gamma->modified ) {
- r_gamma->modified = qfalse;
-
- R_IssuePendingRenderCommands();
- R_SetColorMappings();
- }
-
- // check for errors
- if ( !r_ignoreGLErrors->integer )
- {
- int err;
-
- R_IssuePendingRenderCommands();
- if ((err = qglGetError()) != GL_NO_ERROR)
- ri.Error(ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!", err);
- }
-
- if (glConfig.stereoEnabled) {
- if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) )
- return;
-
- cmd->commandId = RC_DRAW_BUFFER;
-
- if ( stereoFrame == STEREO_LEFT ) {
- cmd->buffer = (int)GL_BACK_LEFT;
- } else if ( stereoFrame == STEREO_RIGHT ) {
- cmd->buffer = (int)GL_BACK_RIGHT;
- } else {
- ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame );
- }
- }
- else
- {
- if(r_anaglyphMode->integer)
- {
- if(r_anaglyphMode->modified)
- {
- // clear both, front and backbuffer.
- qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- backEnd.colorMask[0] = GL_FALSE;
- backEnd.colorMask[1] = GL_FALSE;
- backEnd.colorMask[2] = GL_FALSE;
- backEnd.colorMask[3] = GL_FALSE;
- qglClearColor(0.0f, 0.0f, 0.0f, 1.0f);
-
- if (glRefConfig.framebufferObject)
- {
- // clear all framebuffers
- if (tr.msaaResolveFbo)
- {
- FBO_Bind(tr.msaaResolveFbo);
- qglClear(GL_COLOR_BUFFER_BIT);
- }
-
- if (tr.renderFbo)
- {
- FBO_Bind(tr.renderFbo);
- qglClear(GL_COLOR_BUFFER_BIT);
- }
-
- if (tr.screenScratchFbo)
- {
- FBO_Bind(tr.screenScratchFbo);
- qglClear(GL_COLOR_BUFFER_BIT);
- }
-
- FBO_Bind(NULL);
- }
-
- qglDrawBuffer(GL_FRONT);
- qglClear(GL_COLOR_BUFFER_BIT);
- qglDrawBuffer(GL_BACK);
- qglClear(GL_COLOR_BUFFER_BIT);
-
- r_anaglyphMode->modified = qfalse;
- }
-
- if(stereoFrame == STEREO_LEFT)
- {
- if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) )
- return;
-
- if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) )
- return;
- }
- else if(stereoFrame == STEREO_RIGHT)
- {
- clearDepthCommand_t *cldcmd;
-
- if( !(cldcmd = R_GetCommandBuffer(sizeof(*cldcmd))) )
- return;
-
- cldcmd->commandId = RC_CLEARDEPTH;
-
- if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) )
- return;
- }
- else
- ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame );
-
- R_SetColorMode(colcmd->rgba, stereoFrame, r_anaglyphMode->integer);
- colcmd->commandId = RC_COLORMASK;
- }
- else
- {
- if(stereoFrame != STEREO_CENTER)
- ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame );
-
- if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) )
- return;
- }
-
- if(cmd)
- {
- cmd->commandId = RC_DRAW_BUFFER;
-
- if(r_anaglyphMode->modified)
- {
- qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- backEnd.colorMask[0] = 0;
- backEnd.colorMask[1] = 0;
- backEnd.colorMask[2] = 0;
- backEnd.colorMask[3] = 0;
- r_anaglyphMode->modified = qfalse;
- }
-
- if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT"))
- cmd->buffer = (int)GL_FRONT;
- else
- cmd->buffer = (int)GL_BACK;
- }
- }
-
- tr.refdef.stereoFrame = stereoFrame;
-}
-
-
-/*
-=============
-RE_EndFrame
-
-Returns the number of msec spent in the back end
-=============
-*/
-void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {
- swapBuffersCommand_t *cmd;
-
- if ( !tr.registered ) {
- return;
- }
- cmd = R_GetCommandBuffer( sizeof( *cmd ) );
- if ( !cmd ) {
- return;
- }
- cmd->commandId = RC_SWAP_BUFFERS;
-
- R_IssueRenderCommands( qtrue );
-
- R_InitNextFrame();
-
- if ( frontEndMsec ) {
- *frontEndMsec = tr.frontEndMsec;
- }
- tr.frontEndMsec = 0;
- if ( backEndMsec ) {
- *backEndMsec = backEnd.pc.msec;
- }
- backEnd.pc.msec = 0;
-}
-
-/*
-=============
-RE_TakeVideoFrame
-=============
-*/
-void RE_TakeVideoFrame( int width, int height,
- byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg )
-{
- videoFrameCommand_t *cmd;
-
- if( !tr.registered ) {
- return;
- }
-
- cmd = R_GetCommandBuffer( sizeof( *cmd ) );
- if( !cmd ) {
- return;
- }
-
- cmd->commandId = RC_VIDEOFRAME;
-
- cmd->width = width;
- cmd->height = height;
- cmd->captureBuffer = captureBuffer;
- cmd->encodeBuffer = encodeBuffer;
- cmd->motionJpeg = motionJpeg;
-}
diff --git a/src/rend2/tr_curve.c b/src/rend2/tr_curve.c
deleted file mode 100644
index 3d439257..00000000
--- a/src/rend2/tr_curve.c
+++ /dev/null
@@ -1,806 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-#include "tr_local.h"
-
-/*
-
-This file does all of the processing necessary to turn a raw grid of points
-read from the map file into a srfGridMesh_t ready for rendering.
-
-The level of detail solution is direction independent, based only on subdivided
-distance from the true curve.
-
-Only a single entry point:
-
-srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
- srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
-
-*/
-
-
-/*
-============
-LerpDrawVert
-============
-*/
-static void LerpDrawVert( srfVert_t *a, srfVert_t *b, srfVert_t *out ) {
- out->xyz[0] = 0.5f * (a->xyz[0] + b->xyz[0]);
- out->xyz[1] = 0.5f * (a->xyz[1] + b->xyz[1]);
- out->xyz[2] = 0.5f * (a->xyz[2] + b->xyz[2]);
-
- out->st[0] = 0.5f * (a->st[0] + b->st[0]);
- out->st[1] = 0.5f * (a->st[1] + b->st[1]);
-
- out->lightmap[0] = 0.5f * (a->lightmap[0] + b->lightmap[0]);
- out->lightmap[1] = 0.5f * (a->lightmap[1] + b->lightmap[1]);
-
- out->vertexColors[0] = 0.5f * (a->vertexColors[0] + b->vertexColors[0]);
- out->vertexColors[1] = 0.5f * (a->vertexColors[1] + b->vertexColors[1]);
- out->vertexColors[2] = 0.5f * (a->vertexColors[2] + b->vertexColors[2]);
- out->vertexColors[3] = 0.5f * (a->vertexColors[3] + b->vertexColors[3]);
-}
-
-/*
-============
-Transpose
-============
-*/
-static void Transpose( int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
- int i, j;
- srfVert_t temp;
-
- if ( width > height ) {
- for ( i = 0 ; i < height ; i++ ) {
- for ( j = i + 1 ; j < width ; j++ ) {
- if ( j < height ) {
- // swap the value
- temp = ctrl[j][i];
- ctrl[j][i] = ctrl[i][j];
- ctrl[i][j] = temp;
- } else {
- // just copy
- ctrl[j][i] = ctrl[i][j];
- }
- }
- }
- } else {
- for ( i = 0 ; i < width ; i++ ) {
- for ( j = i + 1 ; j < height ; j++ ) {
- if ( j < width ) {
- // swap the value
- temp = ctrl[i][j];
- ctrl[i][j] = ctrl[j][i];
- ctrl[j][i] = temp;
- } else {
- // just copy
- ctrl[i][j] = ctrl[j][i];
- }
- }
- }
- }
-
-}
-
-
-/*
-=================
-MakeMeshNormals
-
-Handles all the complicated wrapping and degenerate cases
-=================
-*/
-static void MakeMeshNormals( int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
- int i, j, k, dist;
- vec3_t normal;
- vec3_t sum;
- int count = 0;
- vec3_t base;
- vec3_t delta;
- int x, y;
- srfVert_t *dv;
- vec3_t around[8], temp;
- qboolean good[8];
- qboolean wrapWidth, wrapHeight;
- float len;
-static int neighbors[8][2] = {
- {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}
- };
-
- wrapWidth = qfalse;
- for ( i = 0 ; i < height ; i++ ) {
- VectorSubtract( ctrl[i][0].xyz, ctrl[i][width-1].xyz, delta );
- len = VectorLengthSquared( delta );
- if ( len > 1.0 ) {
- break;
- }
- }
- if ( i == height ) {
- wrapWidth = qtrue;
- }
-
- wrapHeight = qfalse;
- for ( i = 0 ; i < width ; i++ ) {
- VectorSubtract( ctrl[0][i].xyz, ctrl[height-1][i].xyz, delta );
- len = VectorLengthSquared( delta );
- if ( len > 1.0 ) {
- break;
- }
- }
- if ( i == width) {
- wrapHeight = qtrue;
- }
-
-
- for ( i = 0 ; i < width ; i++ ) {
- for ( j = 0 ; j < height ; j++ ) {
- count = 0;
- dv = &ctrl[j][i];
- VectorCopy( dv->xyz, base );
- for ( k = 0 ; k < 8 ; k++ ) {
- VectorClear( around[k] );
- good[k] = qfalse;
-
- for ( dist = 1 ; dist <= 3 ; dist++ ) {
- x = i + neighbors[k][0] * dist;
- y = j + neighbors[k][1] * dist;
- if ( wrapWidth ) {
- if ( x < 0 ) {
- x = width - 1 + x;
- } else if ( x >= width ) {
- x = 1 + x - width;
- }
- }
- if ( wrapHeight ) {
- if ( y < 0 ) {
- y = height - 1 + y;
- } else if ( y >= height ) {
- y = 1 + y - height;
- }
- }
-
- if ( x < 0 || x >= width || y < 0 || y >= height ) {
- break; // edge of patch
- }
- VectorSubtract( ctrl[y][x].xyz, base, temp );
- if ( VectorNormalize2( temp, temp ) == 0 ) {
- continue; // degenerate edge, get more dist
- } else {
- good[k] = qtrue;
- VectorCopy( temp, around[k] );
- break; // good edge
- }
- }
- }
-
- VectorClear( sum );
- for ( k = 0 ; k < 8 ; k++ ) {
- if ( !good[k] || !good[(k+1)&7] ) {
- continue; // didn't get two points
- }
- CrossProduct( around[(k+1)&7], around[k], normal );
- if ( VectorNormalize2( normal, normal ) == 0 ) {
- continue;
- }
- VectorAdd( normal, sum, sum );
- count++;
- }
- //if ( count == 0 ) {
- // printf("bad normal\n");
- //}
- VectorNormalize2( sum, dv->normal );
- }
- }
-}
-
-#ifdef USE_VERT_TANGENT_SPACE
-static void MakeMeshTangentVectors(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], int numTriangles,
- srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2])
-{
- int i, j;
- srfVert_t *dv[3];
- static srfVert_t ctrl2[MAX_GRID_SIZE * MAX_GRID_SIZE];
- srfTriangle_t *tri;
-
- // FIXME: use more elegant way
- for(i = 0; i < width; i++)
- {
- for(j = 0; j < height; j++)
- {
- dv[0] = &ctrl2[j * width + i];
- *dv[0] = ctrl[j][i];
- }
- }
-
- for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
- {
- dv[0] = &ctrl2[tri->indexes[0]];
- dv[1] = &ctrl2[tri->indexes[1]];
- dv[2] = &ctrl2[tri->indexes[2]];
-
- R_CalcTangentVectors(dv);
- }
-
-#if 0
- for(i = 0; i < (width * height); i++)
- {
- dv0 = &ctrl2[i];
-
- VectorNormalize(dv0->normal);
-#if 0
- VectorNormalize(dv0->tangent);
- VectorNormalize(dv0->bitangent);
-#else
- d = DotProduct(dv0->tangent, dv0->normal);
- VectorMA(dv0->tangent, -d, dv0->normal, dv0->tangent);
- VectorNormalize(dv0->tangent);
-
- d = DotProduct(dv0->bitangent, dv0->normal);
- VectorMA(dv0->bitangent, -d, dv0->normal, dv0->bitangent);
- VectorNormalize(dv0->bitangent);
-#endif
- }
-#endif
-
-
-#if 0
- // do another extra smoothing for normals to avoid flat shading
- for(i = 0; i < (width * height); i++)
- {
- for(j = 0; j < (width * height); j++)
- {
- if(R_CompareVert(&ctrl2[i], &ctrl2[j], qfalse))
- {
- VectorAdd(ctrl2[i].normal, ctrl2[j].normal, ctrl2[i].normal);
- }
- }
-
- VectorNormalize(ctrl2[i].normal);
- }
-#endif
-
- for(i = 0; i < width; i++)
- {
- for(j = 0; j < height; j++)
- {
- dv[0] = &ctrl2[j * width + i];
- dv[1] = &ctrl[j][i];
-
- VectorCopy(dv[0]->tangent, dv[1]->tangent);
- VectorCopy(dv[0]->bitangent, dv[1]->bitangent);
- }
- }
-}
-#endif
-
-
-static int MakeMeshTriangles(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
- srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2])
-{
- int i, j;
- int numTriangles;
- int w, h;
- srfVert_t *dv;
- static srfVert_t ctrl2[MAX_GRID_SIZE * MAX_GRID_SIZE];
-
- h = height - 1;
- w = width - 1;
- numTriangles = 0;
- for(i = 0; i < h; i++)
- {
- for(j = 0; j < w; j++)
- {
- int v1, v2, v3, v4;
-
- // vertex order to be reckognized as tristrips
- v1 = i * width + j + 1;
- v2 = v1 - 1;
- v3 = v2 + width;
- v4 = v3 + 1;
-
- triangles[numTriangles].indexes[0] = v2;
- triangles[numTriangles].indexes[1] = v3;
- triangles[numTriangles].indexes[2] = v1;
- numTriangles++;
-
- triangles[numTriangles].indexes[0] = v1;
- triangles[numTriangles].indexes[1] = v3;
- triangles[numTriangles].indexes[2] = v4;
- numTriangles++;
- }
- }
-
- R_CalcSurfaceTriangleNeighbors(numTriangles, triangles);
-
- // FIXME: use more elegant way
- for(i = 0; i < width; i++)
- {
- for(j = 0; j < height; j++)
- {
- dv = &ctrl2[j * width + i];
- *dv = ctrl[j][i];
- }
- }
-
- R_CalcSurfaceTrianglePlanes(numTriangles, triangles, ctrl2);
-
- return numTriangles;
-}
-
-
-/*
-============
-InvertCtrl
-============
-*/
-static void InvertCtrl( int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
- int i, j;
- srfVert_t temp;
-
- for ( i = 0 ; i < height ; i++ ) {
- for ( j = 0 ; j < width/2 ; j++ ) {
- temp = ctrl[i][j];
- ctrl[i][j] = ctrl[i][width-1-j];
- ctrl[i][width-1-j] = temp;
- }
- }
-}
-
-
-/*
-=================
-InvertErrorTable
-=================
-*/
-static void InvertErrorTable( float errorTable[2][MAX_GRID_SIZE], int width, int height ) {
- int i;
- float copy[2][MAX_GRID_SIZE];
-
- Com_Memcpy( copy, errorTable, sizeof( copy ) );
-
- for ( i = 0 ; i < width ; i++ ) {
- errorTable[1][i] = copy[0][i]; //[width-1-i];
- }
-
- for ( i = 0 ; i < height ; i++ ) {
- errorTable[0][i] = copy[1][height-1-i];
- }
-
-}
-
-/*
-==================
-PutPointsOnCurve
-==================
-*/
-static void PutPointsOnCurve( srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
- int width, int height ) {
- int i, j;
- srfVert_t prev, next;
-
- for ( i = 0 ; i < width ; i++ ) {
- for ( j = 1 ; j < height ; j += 2 ) {
- LerpDrawVert( &ctrl[j][i], &ctrl[j+1][i], &prev );
- LerpDrawVert( &ctrl[j][i], &ctrl[j-1][i], &next );
- LerpDrawVert( &prev, &next, &ctrl[j][i] );
- }
- }
-
-
- for ( j = 0 ; j < height ; j++ ) {
- for ( i = 1 ; i < width ; i += 2 ) {
- LerpDrawVert( &ctrl[j][i], &ctrl[j][i+1], &prev );
- LerpDrawVert( &ctrl[j][i], &ctrl[j][i-1], &next );
- LerpDrawVert( &prev, &next, &ctrl[j][i] );
- }
- }
-}
-
-/*
-=================
-R_CreateSurfaceGridMesh
-=================
-*/
-srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
- srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE],
- int numTriangles, srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2]) {
- int i, j, size;
- srfVert_t *vert;
- vec3_t tmpVec;
- srfGridMesh_t *grid;
-
- // copy the results out to a grid
- size = (width * height - 1) * sizeof( srfVert_t ) + sizeof( *grid );
-
-#ifdef PATCH_STITCHING
- grid = /*ri.Hunk_Alloc*/ ri.Malloc( size );
- Com_Memset(grid, 0, size);
-
- grid->widthLodError = /*ri.Hunk_Alloc*/ ri.Malloc( width * 4 );
- Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 );
-
- grid->heightLodError = /*ri.Hunk_Alloc*/ ri.Malloc( height * 4 );
- Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 );
-
- grid->numTriangles = numTriangles;
- grid->triangles = ri.Malloc(grid->numTriangles * sizeof(srfTriangle_t));
- Com_Memcpy(grid->triangles, triangles, numTriangles * sizeof(srfTriangle_t));
-
- grid->numVerts = (width * height);
- grid->verts = ri.Malloc(grid->numVerts * sizeof(srfVert_t));
-#else
- grid = ri.Hunk_Alloc( size );
- Com_Memset(grid, 0, size);
-
- grid->widthLodError = ri.Hunk_Alloc( width * 4 );
- Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 );
-
- grid->heightLodError = ri.Hunk_Alloc( height * 4 );
- Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 );
-
- grid->numTriangles = numTriangles;
- grid->triangles = ri.Hunk_Alloc(grid->numTriangles * sizeof(srfTriangle_t), h_low);
- Com_Memcpy(grid->triangles, triangles, numTriangles * sizeof(srfTriangle_t));
-
- grid->numVerts = (width * height);
- grid->verts = ri.Hunk_Alloc(grid->numVerts * sizeof(srfVert_t), h_low);
-#endif
-
- grid->width = width;
- grid->height = height;
- grid->surfaceType = SF_GRID;
- ClearBounds( grid->meshBounds[0], grid->meshBounds[1] );
- for ( i = 0 ; i < width ; i++ ) {
- for ( j = 0 ; j < height ; j++ ) {
- vert = &grid->verts[j*width+i];
- *vert = ctrl[j][i];
- AddPointToBounds( vert->xyz, grid->meshBounds[0], grid->meshBounds[1] );
- }
- }
-
- // compute local origin and bounds
- VectorAdd( grid->meshBounds[0], grid->meshBounds[1], grid->localOrigin );
- VectorScale( grid->localOrigin, 0.5f, grid->localOrigin );
- VectorSubtract( grid->meshBounds[0], grid->localOrigin, tmpVec );
- grid->meshRadius = VectorLength( tmpVec );
-
- VectorCopy( grid->localOrigin, grid->lodOrigin );
- grid->lodRadius = grid->meshRadius;
- //
- return grid;
-}
-
-/*
-=================
-R_FreeSurfaceGridMesh
-=================
-*/
-void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) {
- ri.Free(grid->widthLodError);
- ri.Free(grid->heightLodError);
- ri.Free(grid->triangles);
- ri.Free(grid->verts);
- ri.Free(grid);
-}
-
-/*
-=================
-R_SubdividePatchToGrid
-=================
-*/
-srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
- srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
- int i, j, k, l;
- srfVert_t_cleared( prev );
- srfVert_t_cleared( next );
- srfVert_t_cleared( mid );
- float len, maxLen;
- int dir;
- int t;
- srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
- float errorTable[2][MAX_GRID_SIZE];
- int numTriangles;
- static srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2];
- int consecutiveComplete;
-
- for ( i = 0 ; i < width ; i++ ) {
- for ( j = 0 ; j < height ; j++ ) {
- ctrl[j][i] = points[j*width+i];
- }
- }
-
- for ( dir = 0 ; dir < 2 ; dir++ ) {
-
- for ( j = 0 ; j < MAX_GRID_SIZE ; j++ ) {
- errorTable[dir][j] = 0;
- }
-
- consecutiveComplete = 0;
-
- // horizontal subdivisions
- for ( j = 0 ; ; j = (j + 2) % (width - 1) ) {
- // check subdivided midpoints against control points
-
- // FIXME: also check midpoints of adjacent patches against the control points
- // this would basically stitch all patches in the same LOD group together.
-
- maxLen = 0;
- for ( i = 0 ; i < height ; i++ ) {
- vec3_t midxyz;
- vec3_t midxyz2;
- vec3_t dir;
- vec3_t projected;
- float d;
-
- // calculate the point on the curve
- for ( l = 0 ; l < 3 ; l++ ) {
- midxyz[l] = (ctrl[i][j].xyz[l] + ctrl[i][j+1].xyz[l] * 2
- + ctrl[i][j+2].xyz[l] ) * 0.25f;
- }
-
- // see how far off the line it is
- // using dist-from-line will not account for internal
- // texture warping, but it gives a lot less polygons than
- // dist-from-midpoint
- VectorSubtract( midxyz, ctrl[i][j].xyz, midxyz );
- VectorSubtract( ctrl[i][j+2].xyz, ctrl[i][j].xyz, dir );
- VectorNormalize( dir );
-
- d = DotProduct( midxyz, dir );
- VectorScale( dir, d, projected );
- VectorSubtract( midxyz, projected, midxyz2);
- len = VectorLengthSquared( midxyz2 ); // we will do the sqrt later
- if ( len > maxLen ) {
- maxLen = len;
- }
- }
-
- maxLen = sqrt(maxLen);
-
- // if all the points are on the lines, remove the entire columns
- if ( maxLen < 0.1f ) {
- errorTable[dir][j+1] = 999;
- // if we go over the whole grid twice without adding any columns, stop
- if (++consecutiveComplete >= width)
- break;
- continue;
- }
-
- // see if we want to insert subdivided columns
- if ( width + 2 > MAX_GRID_SIZE ) {
- errorTable[dir][j+1] = 1.0f/maxLen;
- break; // can't subdivide any more
- }
-
- if ( maxLen <= r_subdivisions->value ) {
- errorTable[dir][j+1] = 1.0f/maxLen;
- // if we go over the whole grid twice without adding any columns, stop
- if (++consecutiveComplete >= width)
- break;
- continue; // didn't need subdivision
- }
-
- errorTable[dir][j+2] = 1.0f/maxLen;
-
- consecutiveComplete = 0;
-
- // insert two columns and replace the peak
- width += 2;
- for ( i = 0 ; i < height ; i++ ) {
- LerpDrawVert( &ctrl[i][j], &ctrl[i][j+1], &prev );
- LerpDrawVert( &ctrl[i][j+1], &ctrl[i][j+2], &next );
- LerpDrawVert( &prev, &next, &mid );
-
- for ( k = width - 1 ; k > j + 3 ; k-- ) {
- ctrl[i][k] = ctrl[i][k-2];
- }
- ctrl[i][j + 1] = prev;
- ctrl[i][j + 2] = mid;
- ctrl[i][j + 3] = next;
- }
-
- // skip the new one, we'll get it on the next pass
- j += 2;
- }
-
- Transpose( width, height, ctrl );
- t = width;
- width = height;
- height = t;
- }
-
-
- // put all the aproximating points on the curve
- PutPointsOnCurve( ctrl, width, height );
-
- // cull out any rows or columns that are colinear
- for ( i = 1 ; i < width-1 ; i++ ) {
- if ( errorTable[0][i] != 999 ) {
- continue;
- }
- for ( j = i+1 ; j < width ; j++ ) {
- for ( k = 0 ; k < height ; k++ ) {
- ctrl[k][j-1] = ctrl[k][j];
- }
- errorTable[0][j-1] = errorTable[0][j];
- }
- width--;
- }
-
- for ( i = 1 ; i < height-1 ; i++ ) {
- if ( errorTable[1][i] != 999 ) {
- continue;
- }
- for ( j = i+1 ; j < height ; j++ ) {
- for ( k = 0 ; k < width ; k++ ) {
- ctrl[j-1][k] = ctrl[j][k];
- }
- errorTable[1][j-1] = errorTable[1][j];
- }
- height--;
- }
-
-#if 1
- // flip for longest tristrips as an optimization
- // the results should be visually identical with or
- // without this step
- if ( height > width ) {
- Transpose( width, height, ctrl );
- InvertErrorTable( errorTable, width, height );
- t = width;
- width = height;
- height = t;
- InvertCtrl( width, height, ctrl );
- }
-#endif
-
- // calculate triangles
- numTriangles = MakeMeshTriangles(width, height, ctrl, triangles);
-
- // calculate normals
- MakeMeshNormals( width, height, ctrl );
-#ifdef USE_VERT_TANGENT_SPACE
- MakeMeshTangentVectors(width, height, ctrl, numTriangles, triangles);
-#endif
-
- return R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
-}
-
-/*
-===============
-R_GridInsertColumn
-===============
-*/
-srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ) {
- int i, j;
- int width, height, oldwidth;
- srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
- float errorTable[2][MAX_GRID_SIZE];
- float lodRadius;
- vec3_t lodOrigin;
- int numTriangles;
- static srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2];
-
- oldwidth = 0;
- width = grid->width + 1;
- if (width > MAX_GRID_SIZE)
- return NULL;
- height = grid->height;
- for (i = 0; i < width; i++) {
- if (i == column) {
- //insert new column
- for (j = 0; j < grid->height; j++) {
- LerpDrawVert( &grid->verts[j * grid->width + i-1], &grid->verts[j * grid->width + i], &ctrl[j][i] );
- if (j == row)
- VectorCopy(point, ctrl[j][i].xyz);
- }
- errorTable[0][i] = loderror;
- continue;
- }
- errorTable[0][i] = grid->widthLodError[oldwidth];
- for (j = 0; j < grid->height; j++) {
- ctrl[j][i] = grid->verts[j * grid->width + oldwidth];
- }
- oldwidth++;
- }
- for (j = 0; j < grid->height; j++) {
- errorTable[1][j] = grid->heightLodError[j];
- }
- // put all the aproximating points on the curve
- //PutPointsOnCurve( ctrl, width, height );
-
- // calculate triangles
- numTriangles = MakeMeshTriangles(width, height, ctrl, triangles);
-
- // calculate normals
- MakeMeshNormals( width, height, ctrl );
-
- VectorCopy(grid->lodOrigin, lodOrigin);
- lodRadius = grid->lodRadius;
- // free the old grid
- R_FreeSurfaceGridMesh(grid);
- // create a new grid
- grid = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
- grid->lodRadius = lodRadius;
- VectorCopy(lodOrigin, grid->lodOrigin);
- return grid;
-}
-
-/*
-===============
-R_GridInsertRow
-===============
-*/
-srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ) {
- int i, j;
- int width, height, oldheight;
- srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
- float errorTable[2][MAX_GRID_SIZE];
- float lodRadius;
- vec3_t lodOrigin;
- int numTriangles;
- static srfTriangle_t triangles[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2];
-
- oldheight = 0;
- width = grid->width;
- height = grid->height + 1;
- if (height > MAX_GRID_SIZE)
- return NULL;
- for (i = 0; i < height; i++) {
- if (i == row) {
- //insert new row
- for (j = 0; j < grid->width; j++) {
- LerpDrawVert( &grid->verts[(i-1) * grid->width + j], &grid->verts[i * grid->width + j], &ctrl[i][j] );
- if (j == column)
- VectorCopy(point, ctrl[i][j].xyz);
- }
- errorTable[1][i] = loderror;
- continue;
- }
- errorTable[1][i] = grid->heightLodError[oldheight];
- for (j = 0; j < grid->width; j++) {
- ctrl[i][j] = grid->verts[oldheight * grid->width + j];
- }
- oldheight++;
- }
- for (j = 0; j < grid->width; j++) {
- errorTable[0][j] = grid->widthLodError[j];
- }
- // put all the aproximating points on the curve
- //PutPointsOnCurve( ctrl, width, height );
-
- // calculate triangles
- numTriangles = MakeMeshTriangles(width, height, ctrl, triangles);
-
- // calculate normals
- MakeMeshNormals( width, height, ctrl );
-
- VectorCopy(grid->lodOrigin, lodOrigin);
- lodRadius = grid->lodRadius;
- // free the old grid
- R_FreeSurfaceGridMesh(grid);
- // create a new grid
- grid = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
- grid->lodRadius = lodRadius;
- VectorCopy(lodOrigin, grid->lodOrigin);
- return grid;
-}
diff --git a/src/rend2/tr_extensions.c b/src/rend2/tr_extensions.c
deleted file mode 100644
index 0b70d48b..00000000
--- a/src/rend2/tr_extensions.c
+++ /dev/null
@@ -1,667 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 2011 James Canete (use.less01@gmail.com)
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_extensions.c - extensions needed by the renderer not in sdl_glimp.c
-
-#ifdef USE_LOCAL_HEADERS
-# include "SDL.h"
-#else
-# include <SDL.h>
-#endif
-
-#include "tr_local.h"
-
-// GL_EXT_draw_range_elements
-void (APIENTRY * qglDrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
-
-// GL_EXT_multi_draw_arrays
-void (APIENTRY * qglMultiDrawArraysEXT) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
-void (APIENTRY * qglMultiDrawElementsEXT) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount);
-
-// GL_ARB_vertex_shader
-void (APIENTRY * qglBindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB * name);
-void (APIENTRY * qglGetActiveAttribARB) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length,
- GLint * size, GLenum * type, GLcharARB * name);
-GLint(APIENTRY * qglGetAttribLocationARB) (GLhandleARB programObj, const GLcharARB * name);
-
-// GL_ARB_vertex_program
-void (APIENTRY * qglVertexAttrib4fARB) (GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
-void (APIENTRY * qglVertexAttrib4fvARB) (GLuint, const GLfloat *);
-void (APIENTRY * qglVertexAttribPointerARB) (GLuint index, GLint size, GLenum type, GLboolean normalized,
- GLsizei stride, const GLvoid * pointer);
-void (APIENTRY * qglEnableVertexAttribArrayARB) (GLuint index);
-void (APIENTRY * qglDisableVertexAttribArrayARB) (GLuint index);
-
-// GL_ARB_vertex_buffer_object
-void (APIENTRY * qglBindBufferARB) (GLenum target, GLuint buffer);
-void (APIENTRY * qglDeleteBuffersARB) (GLsizei n, const GLuint * buffers);
-void (APIENTRY * qglGenBuffersARB) (GLsizei n, GLuint * buffers);
-
-GLboolean(APIENTRY * qglIsBufferARB) (GLuint buffer);
-void (APIENTRY * qglBufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage);
-void (APIENTRY * qglBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data);
-void (APIENTRY * qglGetBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data);
-
-void (APIENTRY * qglGetBufferParameterivARB) (GLenum target, GLenum pname, GLint * params);
-void (APIENTRY * qglGetBufferPointervARB) (GLenum target, GLenum pname, GLvoid * *params);
-
-// GL_ARB_shader_objects
-void (APIENTRY * qglDeleteObjectARB) (GLhandleARB obj);
-
-GLhandleARB(APIENTRY * qglGetHandleARB) (GLenum pname);
-void (APIENTRY * qglDetachObjectARB) (GLhandleARB containerObj, GLhandleARB attachedObj);
-
-GLhandleARB(APIENTRY * qglCreateShaderObjectARB) (GLenum shaderType);
-void (APIENTRY * qglShaderSourceARB) (GLhandleARB shaderObj, GLsizei count, const GLcharARB * *string,
- const GLint * length);
-void (APIENTRY * qglCompileShaderARB) (GLhandleARB shaderObj);
-
-GLhandleARB(APIENTRY * qglCreateProgramObjectARB) (void);
-void (APIENTRY * qglAttachObjectARB) (GLhandleARB containerObj, GLhandleARB obj);
-void (APIENTRY * qglLinkProgramARB) (GLhandleARB programObj);
-void (APIENTRY * qglUseProgramObjectARB) (GLhandleARB programObj);
-void (APIENTRY * qglValidateProgramARB) (GLhandleARB programObj);
-void (APIENTRY * qglUniform1fARB) (GLint location, GLfloat v0);
-void (APIENTRY * qglUniform2fARB) (GLint location, GLfloat v0, GLfloat v1);
-void (APIENTRY * qglUniform3fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
-void (APIENTRY * qglUniform4fARB) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
-void (APIENTRY * qglUniform1iARB) (GLint location, GLint v0);
-void (APIENTRY * qglUniform2iARB) (GLint location, GLint v0, GLint v1);
-void (APIENTRY * qglUniform3iARB) (GLint location, GLint v0, GLint v1, GLint v2);
-void (APIENTRY * qglUniform4iARB) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
-void (APIENTRY * qglUniform1fvARB) (GLint location, GLsizei count, const GLfloat * value);
-void (APIENTRY * qglUniform2fvARB) (GLint location, GLsizei count, const GLfloat * value);
-void (APIENTRY * qglUniform3fvARB) (GLint location, GLsizei count, const GLfloat * value);
-void (APIENTRY * qglUniform4fvARB) (GLint location, GLsizei count, const GLfloat * value);
-void (APIENTRY * qglUniform2ivARB) (GLint location, GLsizei count, const GLint * value);
-void (APIENTRY * qglUniform3ivARB) (GLint location, GLsizei count, const GLint * value);
-void (APIENTRY * qglUniform4ivARB) (GLint location, GLsizei count, const GLint * value);
-void (APIENTRY * qglUniformMatrix2fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void (APIENTRY * qglUniformMatrix3fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void (APIENTRY * qglUniformMatrix4fvARB) (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void (APIENTRY * qglGetObjectParameterfvARB) (GLhandleARB obj, GLenum pname, GLfloat * params);
-void (APIENTRY * qglGetObjectParameterivARB) (GLhandleARB obj, GLenum pname, GLint * params);
-void (APIENTRY * qglGetInfoLogARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog);
-void (APIENTRY * qglGetAttachedObjectsARB) (GLhandleARB containerObj, GLsizei maxCount, GLsizei * count,
- GLhandleARB * obj);
-GLint(APIENTRY * qglGetUniformLocationARB) (GLhandleARB programObj, const GLcharARB * name);
-void (APIENTRY * qglGetActiveUniformARB) (GLhandleARB programObj, GLuint index, GLsizei maxIndex, GLsizei * length,
- GLint * size, GLenum * type, GLcharARB * name);
-void (APIENTRY * qglGetUniformfvARB) (GLhandleARB programObj, GLint location, GLfloat * params);
-void (APIENTRY * qglGetUniformivARB) (GLhandleARB programObj, GLint location, GLint * params);
-void (APIENTRY * qglGetShaderSourceARB) (GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * source);
-
-// GL_ARB_texture_compression
-void (APIENTRY * qglCompressedTexImage3DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
- GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
-void (APIENTRY * qglCompressedTexImage2DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
- GLint border, GLsizei imageSize, const GLvoid *data);
-void (APIENTRY * qglCompressedTexImage1DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border,
- GLsizei imageSize, const GLvoid *data);
-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);
-void (APIENTRY * qglCompressedTexSubImage2DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
- GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
-void (APIENTRY * qglCompressedTexSubImage1DARB)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format,
- GLsizei imageSize, const GLvoid *data);
-void (APIENTRY * qglGetCompressedTexImageARB)(GLenum target, GLint lod,
- GLvoid *img);
-
-// GL_EXT_framebuffer_object
-GLboolean (APIENTRY * qglIsRenderbufferEXT)(GLuint renderbuffer);
-void (APIENTRY * qglBindRenderbufferEXT)(GLenum target, GLuint renderbuffer);
-void (APIENTRY * qglDeleteRenderbuffersEXT)(GLsizei n, const GLuint *renderbuffers);
-void (APIENTRY * qglGenRenderbuffersEXT)(GLsizei n, GLuint *renderbuffers);
-
-void (APIENTRY * qglRenderbufferStorageEXT)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-
-void (APIENTRY * qglGetRenderbufferParameterivEXT)(GLenum target, GLenum pname, GLint *params);
-
-GLboolean (APIENTRY * qglIsFramebufferEXT)(GLuint framebuffer);
-void (APIENTRY * qglBindFramebufferEXT)(GLenum target, GLuint framebuffer);
-void (APIENTRY * qglDeleteFramebuffersEXT)(GLsizei n, const GLuint *framebuffers);
-void (APIENTRY * qglGenFramebuffersEXT)(GLsizei n, GLuint *framebuffers);
-
-GLenum (APIENTRY * qglCheckFramebufferStatusEXT)(GLenum target);
-
-void (APIENTRY * qglFramebufferTexture1DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
- GLint level);
-void (APIENTRY * qglFramebufferTexture2DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
- GLint level);
-void (APIENTRY * qglFramebufferTexture3DEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
- GLint level, GLint zoffset);
-
-void (APIENTRY * qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachment, GLenum renderbuffertarget,
- GLuint renderbuffer);
-
-void (APIENTRY * qglGetFramebufferAttachmentParameterivEXT)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
-
-void (APIENTRY * qglGenerateMipmapEXT)(GLenum target);
-
-// GL_ARB_occlusion_query
-void (APIENTRY * qglGenQueriesARB)(GLsizei n, GLuint *ids);
-void (APIENTRY * qglDeleteQueriesARB)(GLsizei n, const GLuint *ids);
-GLboolean (APIENTRY * qglIsQueryARB)(GLuint id);
-void (APIENTRY * qglBeginQueryARB)(GLenum target, GLuint id);
-void (APIENTRY * qglEndQueryARB)(GLenum target);
-void (APIENTRY * qglGetQueryivARB)(GLenum target, GLenum pname, GLint *params);
-void (APIENTRY * qglGetQueryObjectivARB)(GLuint id, GLenum pname, GLint *params);
-void (APIENTRY * qglGetQueryObjectuivARB)(GLuint id, GLenum pname, GLuint *params);
-
-// GL_EXT_framebuffer_blit
-void (APIENTRY * qglBlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter);
-
-// GL_EXT_framebuffer_multisample
-void (APIENTRY * qglRenderbufferStorageMultisampleEXT)(GLenum target, GLsizei samples,
- GLenum internalformat, GLsizei width, GLsizei height);
-
-// GL_ARB_draw_buffers
-void (APIENTRY * qglDrawBuffersARB)(GLsizei n, const GLenum *bufs);
-
-static qboolean GLimp_HaveExtension(const char *ext)
-{
- const char *ptr = Q_stristr( glConfig.extensions_string, ext );
- if (ptr == NULL)
- return qfalse;
- ptr += strlen(ext);
- return ((*ptr == ' ') || (*ptr == '\0')); // verify it's complete string.
-}
-
-void GLimp_InitExtraExtensions()
-{
- char *extension;
- const char* result[3] = { "...ignoring %s\n", "...using %s\n", "...%s not found\n" };
-
- // GL_EXT_draw_range_elements
- extension = "GL_EXT_draw_range_elements";
- glRefConfig.drawRangeElements = qfalse;
- qglMultiDrawArraysEXT = NULL;
- qglMultiDrawElementsEXT = NULL;
- if( GLimp_HaveExtension( extension ) )
- {
- qglDrawRangeElementsEXT = (void *) SDL_GL_GetProcAddress("glDrawRangeElementsEXT");
-
- if ( r_ext_draw_range_elements->integer)
- glRefConfig.drawRangeElements = qtrue;
-
- ri.Printf(PRINT_ALL, result[glRefConfig.drawRangeElements], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-
- // GL_EXT_multi_draw_arrays
- extension = "GL_EXT_multi_draw_arrays";
- glRefConfig.multiDrawArrays = qfalse;
- qglMultiDrawArraysEXT = NULL;
- qglMultiDrawElementsEXT = NULL;
- if( GLimp_HaveExtension( extension ) )
- {
- qglMultiDrawArraysEXT = (PFNGLMULTIDRAWARRAYSEXTPROC) SDL_GL_GetProcAddress("glMultiDrawArraysEXT");
- qglMultiDrawElementsEXT = (PFNGLMULTIDRAWELEMENTSEXTPROC) SDL_GL_GetProcAddress("glMultiDrawElementsEXT");
-
- if ( r_ext_multi_draw_arrays->integer )
- glRefConfig.multiDrawArrays = qtrue;
-
- ri.Printf(PRINT_ALL, result[glRefConfig.multiDrawArrays], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-
- // GL_ARB_vertex_program
- //glRefConfig.vertexProgram = qfalse;
- extension = "GL_ARB_vertex_program";
- qglVertexAttrib4fARB = NULL;
- qglVertexAttrib4fvARB = NULL;
- qglVertexAttribPointerARB = NULL;
- qglEnableVertexAttribArrayARB = NULL;
- qglDisableVertexAttribArrayARB = NULL;
- if( GLimp_HaveExtension( extension ) )
- {
- qglVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) SDL_GL_GetProcAddress("glVertexAttrib4fARB");
- qglVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) SDL_GL_GetProcAddress("glVertexAttrib4fvARB");
- qglVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) SDL_GL_GetProcAddress("glVertexAttribPointerARB");
- qglEnableVertexAttribArrayARB =
- (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) SDL_GL_GetProcAddress("glEnableVertexAttribArrayARB");
- qglDisableVertexAttribArrayARB =
- (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) SDL_GL_GetProcAddress("glDisableVertexAttribArrayARB");
-
- ri.Printf(PRINT_ALL, result[1], extension);
- //glRefConfig.vertexProgram = qtrue;
- }
- else
- {
- ri.Error(ERR_FATAL, result[2], extension);
- }
-
- // GL_ARB_vertex_buffer_object
- //glRefConfig.vertexBufferObject = qfalse;
- extension = "GL_ARB_vertex_buffer_object";
- qglBindBufferARB = NULL;
- qglDeleteBuffersARB = NULL;
- qglGenBuffersARB = NULL;
- qglIsBufferARB = NULL;
- qglBufferDataARB = NULL;
- qglBufferSubDataARB = NULL;
- qglGetBufferSubDataARB = NULL;
- qglGetBufferParameterivARB = NULL;
- qglGetBufferPointervARB = NULL;
- if( GLimp_HaveExtension( extension ) )
- {
- qglBindBufferARB = (PFNGLBINDBUFFERARBPROC) SDL_GL_GetProcAddress("glBindBufferARB");
- qglDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) SDL_GL_GetProcAddress("glDeleteBuffersARB");
- qglGenBuffersARB = (PFNGLGENBUFFERSARBPROC) SDL_GL_GetProcAddress("glGenBuffersARB");
- qglIsBufferARB = (PFNGLISBUFFERARBPROC) SDL_GL_GetProcAddress("glIsBufferARB");
- qglBufferDataARB = (PFNGLBUFFERDATAARBPROC) SDL_GL_GetProcAddress("glBufferDataARB");
- qglBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC) SDL_GL_GetProcAddress("glBufferSubDataARB");
- qglGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC) SDL_GL_GetProcAddress("glGetBufferSubDataARB");
- qglGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetBufferParameterivARB");
- qglGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC) SDL_GL_GetProcAddress("glGetBufferPointervARB");
- ri.Printf(PRINT_ALL, result[1], extension);
- //glRefConfig.vertexBufferObject = qtrue;
- }
- else
- {
- ri.Error(ERR_FATAL, result[2], extension);
- }
-
- // GL_ARB_shader_objects
- extension = "GL_ARB_shader_objects";
- //glRefConfig.shaderObjects = qfalse;
- qglDeleteObjectARB = NULL;
- qglGetHandleARB = NULL;
- qglDetachObjectARB = NULL;
- qglCreateShaderObjectARB = NULL;
- qglShaderSourceARB = NULL;
- qglCompileShaderARB = NULL;
- qglCreateProgramObjectARB = NULL;
- qglAttachObjectARB = NULL;
- qglLinkProgramARB = NULL;
- qglUseProgramObjectARB = NULL;
- qglValidateProgramARB = NULL;
- qglUniform1fARB = NULL;
- qglUniform2fARB = NULL;
- qglUniform3fARB = NULL;
- qglUniform4fARB = NULL;
- qglUniform1iARB = NULL;
- qglUniform2iARB = NULL;
- qglUniform3iARB = NULL;
- qglUniform4iARB = NULL;
- qglUniform1fvARB = NULL;
- qglUniform2fvARB = NULL;
- qglUniform3fvARB = NULL;
- qglUniform4fvARB = NULL;
- qglUniform2ivARB = NULL;
- qglUniform3ivARB = NULL;
- qglUniform4ivARB = NULL;
- qglUniformMatrix2fvARB = NULL;
- qglUniformMatrix3fvARB = NULL;
- qglUniformMatrix4fvARB = NULL;
- qglGetObjectParameterfvARB = NULL;
- qglGetObjectParameterivARB = NULL;
- qglGetInfoLogARB = NULL;
- qglGetAttachedObjectsARB = NULL;
- qglGetUniformLocationARB = NULL;
- qglGetActiveUniformARB = NULL;
- qglGetUniformfvARB = NULL;
- qglGetUniformivARB = NULL;
- qglGetShaderSourceARB = NULL;
- if( GLimp_HaveExtension( extension ) )
- {
- qglDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) SDL_GL_GetProcAddress("glDeleteObjectARB");
- qglGetHandleARB = (PFNGLGETHANDLEARBPROC) SDL_GL_GetProcAddress("glGetHandleARB");
- qglDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) SDL_GL_GetProcAddress("glDetachObjectARB");
- qglCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) SDL_GL_GetProcAddress("glCreateShaderObjectARB");
- qglShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glShaderSourceARB");
- qglCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) SDL_GL_GetProcAddress("glCompileShaderARB");
- qglCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glCreateProgramObjectARB");
- qglAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) SDL_GL_GetProcAddress("glAttachObjectARB");
- qglLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) SDL_GL_GetProcAddress("glLinkProgramARB");
- qglUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glUseProgramObjectARB");
- qglValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) SDL_GL_GetProcAddress("glValidateProgramARB");
- qglUniform1fARB = (PFNGLUNIFORM1FARBPROC) SDL_GL_GetProcAddress("glUniform1fARB");
- qglUniform2fARB = (PFNGLUNIFORM2FARBPROC) SDL_GL_GetProcAddress("glUniform2fARB");
- qglUniform3fARB = (PFNGLUNIFORM3FARBPROC) SDL_GL_GetProcAddress("glUniform3fARB");
- qglUniform4fARB = (PFNGLUNIFORM4FARBPROC) SDL_GL_GetProcAddress("glUniform4fARB");
- qglUniform1iARB = (PFNGLUNIFORM1IARBPROC) SDL_GL_GetProcAddress("glUniform1iARB");
- qglUniform2iARB = (PFNGLUNIFORM2IARBPROC) SDL_GL_GetProcAddress("glUniform2iARB");
- qglUniform3iARB = (PFNGLUNIFORM3IARBPROC) SDL_GL_GetProcAddress("glUniform3iARB");
- qglUniform4iARB = (PFNGLUNIFORM4IARBPROC) SDL_GL_GetProcAddress("glUniform4iARB");
- qglUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) SDL_GL_GetProcAddress("glUniform1fvARB");
- qglUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) SDL_GL_GetProcAddress("glUniform2fvARB");
- qglUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) SDL_GL_GetProcAddress("glUniform3fvARB");
- qglUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) SDL_GL_GetProcAddress("glUniform4fvARB");
- qglUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) SDL_GL_GetProcAddress("glUniform2ivARB");
- qglUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) SDL_GL_GetProcAddress("glUniform3ivARB");
- qglUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) SDL_GL_GetProcAddress("glUniform4ivARB");
- qglUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix2fvARB");
- qglUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix3fvARB");
- qglUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) SDL_GL_GetProcAddress("glUniformMatrix4fvARB");
- qglGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterfvARB");
- qglGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterivARB");
- qglGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) SDL_GL_GetProcAddress("glGetInfoLogARB");
- qglGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) SDL_GL_GetProcAddress("glGetAttachedObjectsARB");
- qglGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetUniformLocationARB");
- qglGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) SDL_GL_GetProcAddress("glGetActiveUniformARB");
- qglGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) SDL_GL_GetProcAddress("glGetUniformfvARB");
- qglGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) SDL_GL_GetProcAddress("glGetUniformivARB");
- qglGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glGetShaderSourceARB");
- ri.Printf(PRINT_ALL, result[1], extension);
- //glRefConfig.shaderObjects = qtrue;
- }
- else
- {
- ri.Error(ERR_FATAL, result[2], extension);
- }
-
- // GL_ARB_vertex_shader
- //glRefConfig.vertexShader = qfalse;
- extension = "GL_ARB_vertex_shader";
- qglBindAttribLocationARB = NULL;
- qglGetActiveAttribARB = NULL;
- qglGetAttribLocationARB = NULL;
- if( GLimp_HaveExtension( extension ) )
- {
- //int reservedComponents;
-
- //qglGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &glConfig.maxVertexUniforms);
- //qglGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &glConfig.maxVaryingFloats);
- //qglGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &glConfig.maxVertexAttribs);
-
- //reservedComponents = 16 * 10; // approximation how many uniforms we have besides the bone matrices
-
-#if 0
- if(glConfig.driverType == GLDRV_MESA)
- {
- // HACK
- // restrict to number of vertex uniforms to 512 because of:
- // xreal.x86_64: nv50_program.c:4181: nv50_program_validate_data: Assertion `p->param_nr <= 512' failed
-
- glConfig.maxVertexUniforms = Q_bound(0, glConfig.maxVertexUniforms, 512);
- }
-#endif
-
- //glConfig.maxVertexSkinningBones = (int) Q_bound(0.0, (Q_max(glConfig.maxVertexUniforms - reservedComponents, 0) / 16), MAX_BONES);
- //glConfig.vboVertexSkinningAvailable = r_vboVertexSkinning->integer && ((glConfig.maxVertexSkinningBones >= 12) ? qtrue : qfalse);
-
- qglBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) SDL_GL_GetProcAddress("glBindAttribLocationARB");
- qglGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) SDL_GL_GetProcAddress("glGetActiveAttribARB");
- qglGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetAttribLocationARB");
- ri.Printf(PRINT_ALL, result[1], extension);
- //glRefConfig.vertexShader = qtrue;
- }
- else
- {
- ri.Error(ERR_FATAL, result[2], extension);
- }
-
- // GL_ARB_shading_language_100
- extension = "GL_ARB_shading_language_100";
- glRefConfig.textureFloat = qfalse;
- if( GLimp_HaveExtension( extension ) )
- {
- char version[256];
-
- Q_strncpyz( version, (char *) qglGetString (GL_SHADING_LANGUAGE_VERSION_ARB), sizeof( version ) );
-
- sscanf(version, "%d.%d", &glRefConfig.glslMajorVersion, &glRefConfig.glslMinorVersion);
-
- ri.Printf(PRINT_ALL, "...using GLSL version %s\n", version);
- }
- else
- {
- ri.Error(ERR_FATAL, result[2], extension);
- }
-
- glRefConfig.memInfo = MI_NONE;
-
- if( GLimp_HaveExtension( "GL_NVX_gpu_memory_info" ) )
- {
- glRefConfig.memInfo = MI_NVX;
- }
- else if( GLimp_HaveExtension( "GL_ATI_meminfo" ) )
- {
- glRefConfig.memInfo = MI_ATI;
- }
-
- extension = "GL_ARB_texture_non_power_of_two";
- glRefConfig.textureNonPowerOfTwo = qfalse;
- if( GLimp_HaveExtension( extension ) )
- {
- if(1) //(r_ext_texture_non_power_of_two->integer)
- {
- glRefConfig.textureNonPowerOfTwo = qtrue;
- }
-
- ri.Printf(PRINT_ALL, result[glRefConfig.textureNonPowerOfTwo], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-
- // GL_ARB_texture_float
- extension = "GL_ARB_texture_float";
- glRefConfig.textureFloat = qfalse;
- if( GLimp_HaveExtension( extension ) )
- {
- if( r_ext_texture_float->integer )
- {
- glRefConfig.textureFloat = qtrue;
- }
-
- ri.Printf(PRINT_ALL, result[glRefConfig.textureFloat], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-
- // GL_ARB_half_float_pixel
- extension = "GL_ARB_half_float_pixel";
- glRefConfig.halfFloatPixel = qfalse;
- if( GLimp_HaveExtension( extension ) )
- {
- if( r_arb_half_float_pixel->integer )
- glRefConfig.halfFloatPixel = qtrue;
-
- ri.Printf(PRINT_ALL, result[glRefConfig.halfFloatPixel], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-
- // GL_EXT_framebuffer_object
- extension = "GL_EXT_framebuffer_object";
- glRefConfig.framebufferObject = qfalse;
- if( GLimp_HaveExtension( extension ) )
- {
- glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &glRefConfig.maxRenderbufferSize);
- glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &glRefConfig.maxColorAttachments);
-
- qglIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) SDL_GL_GetProcAddress("glIsRenderbufferEXT");
- qglBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) SDL_GL_GetProcAddress("glBindRenderbufferEXT");
- qglDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) SDL_GL_GetProcAddress("glDeleteRenderbuffersEXT");
- qglGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) SDL_GL_GetProcAddress("glGenRenderbuffersEXT");
- qglRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) SDL_GL_GetProcAddress("glRenderbufferStorageEXT");
- qglGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) SDL_GL_GetProcAddress("glGetRenderbufferParameterivEXT");
- qglIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC) SDL_GL_GetProcAddress("glIsFramebufferEXT");
- qglBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) SDL_GL_GetProcAddress("glBindFramebufferEXT");
- qglDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) SDL_GL_GetProcAddress("glDeleteFramebuffersEXT");
- qglGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) SDL_GL_GetProcAddress("glGenFramebuffersEXT");
- qglCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT");
- qglFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) SDL_GL_GetProcAddress("glFramebufferTexture1DEXT");
- qglFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) SDL_GL_GetProcAddress("glFramebufferTexture2DEXT");
- qglFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) SDL_GL_GetProcAddress("glFramebufferTexture3DEXT");
- qglFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) SDL_GL_GetProcAddress("glFramebufferRenderbufferEXT");
- qglGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) SDL_GL_GetProcAddress("glGetFramebufferAttachmentParameterivEXT");
- qglGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) SDL_GL_GetProcAddress("glGenerateMipmapEXT");
-
- if(r_ext_framebuffer_object->value)
- glRefConfig.framebufferObject = qtrue;
-
- ri.Printf(PRINT_ALL, result[glRefConfig.framebufferObject], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-
- // GL_EXT_packed_depth_stencil
- extension = "GL_EXT_packed_depth_stencil";
- glRefConfig.packedDepthStencil = qfalse;
- if( GLimp_HaveExtension(extension))
- {
- glRefConfig.packedDepthStencil = qtrue;
- ri.Printf(PRINT_ALL, result[glRefConfig.packedDepthStencil], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-
- // GL_ARB_occlusion_query
- extension = "GL_ARB_occlusion_query";
- glRefConfig.occlusionQuery = qfalse;
- if (GLimp_HaveExtension(extension))
- {
- qglGenQueriesARB = (PFNGLGENQUERIESARBPROC) SDL_GL_GetProcAddress("glGenQueriesARB");
- qglDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC) SDL_GL_GetProcAddress("glDeleteQueriesARB");
- qglIsQueryARB = (PFNGLISQUERYARBPROC) SDL_GL_GetProcAddress("glIsQueryARB");
- qglBeginQueryARB = (PFNGLBEGINQUERYARBPROC) SDL_GL_GetProcAddress("glBeginQueryARB");
- qglEndQueryARB = (PFNGLENDQUERYARBPROC) SDL_GL_GetProcAddress("glEndQueryARB");
- qglGetQueryivARB = (PFNGLGETQUERYIVARBPROC) SDL_GL_GetProcAddress("glGetQueryivARB");
- qglGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC) SDL_GL_GetProcAddress("glGetQueryObjectivARB");
- qglGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC) SDL_GL_GetProcAddress("glGetQueryObjectuivARB");
- glRefConfig.occlusionQuery = qtrue;
- ri.Printf(PRINT_ALL, result[glRefConfig.occlusionQuery], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-
- // GL_EXT_framebuffer_blit
- extension = "GL_EXT_framebuffer_blit";
- glRefConfig.framebufferBlit = qfalse;
- if (GLimp_HaveExtension(extension))
- {
- qglBlitFramebufferEXT = (void *)SDL_GL_GetProcAddress("glBlitFramebufferEXT");
- glRefConfig.framebufferBlit = qtrue;
- ri.Printf(PRINT_ALL, result[glRefConfig.framebufferBlit], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-
- // GL_EXT_framebuffer_multisample
- extension = "GL_EXT_framebuffer_multisample";
- glRefConfig.framebufferMultisample = qfalse;
- if (GLimp_HaveExtension(extension))
- {
- qglRenderbufferStorageMultisampleEXT = (void *)SDL_GL_GetProcAddress("glRenderbufferStorageMultisampleEXT");
- glRefConfig.framebufferMultisample = qtrue;
- ri.Printf(PRINT_ALL, result[glRefConfig.framebufferMultisample], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-
- // GL_EXT_texture_sRGB
- extension = "GL_EXT_texture_sRGB";
- glRefConfig.texture_srgb = qfalse;
- if (GLimp_HaveExtension(extension))
- {
- if (r_srgb->integer)
- glRefConfig.texture_srgb = qtrue;
-
- ri.Printf(PRINT_ALL, result[glRefConfig.texture_srgb], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-
- glRefConfig.textureCompression = TCR_NONE;
-
- // GL_EXT_texture_compression_latc
- extension = "GL_EXT_texture_compression_latc";
- if (GLimp_HaveExtension(extension))
- {
- if (r_ext_compressed_textures->integer)
- glRefConfig.textureCompression |= TCR_LATC;
-
- ri.Printf(PRINT_ALL, result[r_ext_compressed_textures->integer ? 1 : 0], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-
- // GL_ARB_texture_compression_bptc
- extension = "GL_ARB_texture_compression_bptc";
- if (GLimp_HaveExtension(extension))
- {
- if (r_ext_compressed_textures->integer >= 2)
- glRefConfig.textureCompression |= TCR_BPTC;
-
- ri.Printf(PRINT_ALL, result[(r_ext_compressed_textures->integer >= 2) ? 1 : 0], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-
- // GL_ARB_draw_buffers
- extension = "GL_ARB_draw_buffers";
- qglDrawBuffersARB = NULL;
- if( GLimp_HaveExtension( extension ) )
- {
- qglDrawBuffersARB = (void *) SDL_GL_GetProcAddress("glDrawBuffersARB");
-
- ri.Printf(PRINT_ALL, result[1], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-
- // GL_ARB_depth_clamp
- extension = "GL_ARB_depth_clamp";
- glRefConfig.depthClamp = qfalse;
- if( GLimp_HaveExtension( extension ) )
- {
- glRefConfig.depthClamp = qtrue;
- ri.Printf(PRINT_ALL, result[1], extension);
- }
- else
- {
- ri.Printf(PRINT_ALL, result[2], extension);
- }
-}
diff --git a/src/rend2/tr_extramath.c b/src/rend2/tr_extramath.c
deleted file mode 100644
index e989c7e9..00000000
--- a/src/rend2/tr_extramath.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 2010 James Canete (use.less01@gmail.com)
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_extramath.c - extra math needed by the renderer not in qmath.c
-
-#include "tr_local.h"
-
-// Some matrix helper functions
-// FIXME: do these already exist in ioq3 and I don't know about them?
-
-void Matrix16Zero( matrix_t out )
-{
- out[ 0] = 0.0f; out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = 0.0f;
- out[ 1] = 0.0f; out[ 5] = 0.0f; out[ 9] = 0.0f; out[13] = 0.0f;
- out[ 2] = 0.0f; out[ 6] = 0.0f; out[10] = 0.0f; out[14] = 0.0f;
- out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 0.0f;
-}
-
-void Matrix16Identity( matrix_t out )
-{
- out[ 0] = 1.0f; out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = 0.0f;
- out[ 1] = 0.0f; out[ 5] = 1.0f; out[ 9] = 0.0f; out[13] = 0.0f;
- out[ 2] = 0.0f; out[ 6] = 0.0f; out[10] = 1.0f; out[14] = 0.0f;
- out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 1.0f;
-}
-
-void Matrix16Copy( const matrix_t in, matrix_t out )
-{
- out[ 0] = in[ 0]; out[ 4] = in[ 4]; out[ 8] = in[ 8]; out[12] = in[12];
- out[ 1] = in[ 1]; out[ 5] = in[ 5]; out[ 9] = in[ 9]; out[13] = in[13];
- out[ 2] = in[ 2]; out[ 6] = in[ 6]; out[10] = in[10]; out[14] = in[14];
- out[ 3] = in[ 3]; out[ 7] = in[ 7]; out[11] = in[11]; out[15] = in[15];
-}
-
-void Matrix16Multiply( const matrix_t in1, const matrix_t in2, matrix_t out )
-{
- out[ 0] = in1[ 0] * in2[ 0] + in1[ 4] * in2[ 1] + in1[ 8] * in2[ 2] + in1[12] * in2[ 3];
- out[ 1] = in1[ 1] * in2[ 0] + in1[ 5] * in2[ 1] + in1[ 9] * in2[ 2] + in1[13] * in2[ 3];
- out[ 2] = in1[ 2] * in2[ 0] + in1[ 6] * in2[ 1] + in1[10] * in2[ 2] + in1[14] * in2[ 3];
- out[ 3] = in1[ 3] * in2[ 0] + in1[ 7] * in2[ 1] + in1[11] * in2[ 2] + in1[15] * in2[ 3];
-
- out[ 4] = in1[ 0] * in2[ 4] + in1[ 4] * in2[ 5] + in1[ 8] * in2[ 6] + in1[12] * in2[ 7];
- out[ 5] = in1[ 1] * in2[ 4] + in1[ 5] * in2[ 5] + in1[ 9] * in2[ 6] + in1[13] * in2[ 7];
- out[ 6] = in1[ 2] * in2[ 4] + in1[ 6] * in2[ 5] + in1[10] * in2[ 6] + in1[14] * in2[ 7];
- out[ 7] = in1[ 3] * in2[ 4] + in1[ 7] * in2[ 5] + in1[11] * in2[ 6] + in1[15] * in2[ 7];
-
- out[ 8] = in1[ 0] * in2[ 8] + in1[ 4] * in2[ 9] + in1[ 8] * in2[10] + in1[12] * in2[11];
- out[ 9] = in1[ 1] * in2[ 8] + in1[ 5] * in2[ 9] + in1[ 9] * in2[10] + in1[13] * in2[11];
- out[10] = in1[ 2] * in2[ 8] + in1[ 6] * in2[ 9] + in1[10] * in2[10] + in1[14] * in2[11];
- out[11] = in1[ 3] * in2[ 8] + in1[ 7] * in2[ 9] + in1[11] * in2[10] + in1[15] * in2[11];
-
- out[12] = in1[ 0] * in2[12] + in1[ 4] * in2[13] + in1[ 8] * in2[14] + in1[12] * in2[15];
- out[13] = in1[ 1] * in2[12] + in1[ 5] * in2[13] + in1[ 9] * in2[14] + in1[13] * in2[15];
- out[14] = in1[ 2] * in2[12] + in1[ 6] * in2[13] + in1[10] * in2[14] + in1[14] * in2[15];
- out[15] = in1[ 3] * in2[12] + in1[ 7] * in2[13] + in1[11] * in2[14] + in1[15] * in2[15];
-}
-
-void Matrix16Transform( const matrix_t in1, const vec4_t in2, vec4_t out )
-{
- out[ 0] = in1[ 0] * in2[ 0] + in1[ 4] * in2[ 1] + in1[ 8] * in2[ 2] + in1[12] * in2[ 3];
- out[ 1] = in1[ 1] * in2[ 0] + in1[ 5] * in2[ 1] + in1[ 9] * in2[ 2] + in1[13] * in2[ 3];
- out[ 2] = in1[ 2] * in2[ 0] + in1[ 6] * in2[ 1] + in1[10] * in2[ 2] + in1[14] * in2[ 3];
- out[ 3] = in1[ 3] * in2[ 0] + in1[ 7] * in2[ 1] + in1[11] * in2[ 2] + in1[15] * in2[ 3];
-}
-
-qboolean Matrix16Compare( const matrix_t a, const matrix_t b )
-{
- return !(a[ 0] != b[ 0] || a[ 4] != b[ 4] || a[ 8] != b[ 8] || a[12] != b[12] ||
- a[ 1] != b[ 1] || a[ 5] != b[ 5] || a[ 9] != b[ 9] || a[13] != b[13] ||
- a[ 2] != b[ 2] || a[ 6] != b[ 6] || a[10] != b[10] || a[14] != b[14] ||
- a[ 3] != b[ 3] || a[ 7] != b[ 7] || a[11] != b[11] || a[15] != b[15]);
-}
-
-void Matrix16Dump( const matrix_t in )
-{
- ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 0], in[ 4], in[ 8], in[12]);
- ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 1], in[ 5], in[ 9], in[13]);
- ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 2], in[ 6], in[10], in[14]);
- ri.Printf(PRINT_ALL, "%3.5f %3.5f %3.5f %3.5f\n", in[ 3], in[ 7], in[11], in[15]);
-}
-
-void Matrix16Translation( vec3_t vec, matrix_t out )
-{
- out[ 0] = 1.0f; out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = vec[0];
- out[ 1] = 0.0f; out[ 5] = 1.0f; out[ 9] = 0.0f; out[13] = vec[1];
- out[ 2] = 0.0f; out[ 6] = 0.0f; out[10] = 1.0f; out[14] = vec[2];
- out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 1.0f;
-}
-
-void Matrix16Ortho( float left, float right, float bottom, float top, float znear, float zfar, matrix_t out )
-{
- out[ 0] = 2.0f / (right - left); out[ 4] = 0.0f; out[ 8] = 0.0f; out[12] = -(right + left) / (right - left);
- out[ 1] = 0.0f; out[ 5] = 2.0f / (top - bottom); out[ 9] = 0.0f; out[13] = -(top + bottom) / (top - bottom);
- out[ 2] = 0.0f; out[ 6] = 0.0f; out[10] = 2.0f / (zfar - znear); out[14] = -(zfar + znear) / (zfar - znear);
- out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 1.0f;
-}
-
-void Matrix16View(vec3_t axes[3], vec3_t origin, matrix_t out)
-{
- out[0] = axes[0][0];
- out[1] = axes[1][0];
- out[2] = axes[2][0];
- out[3] = 0;
-
- out[4] = axes[0][1];
- out[5] = axes[1][1];
- out[6] = axes[2][1];
- out[7] = 0;
-
- out[8] = axes[0][2];
- out[9] = axes[1][2];
- out[10] = axes[2][2];
- out[11] = 0;
-
- out[12] = -DotProduct(origin, axes[0]);
- out[13] = -DotProduct(origin, axes[1]);
- out[14] = -DotProduct(origin, axes[2]);
- out[15] = 1;
-}
-
-void Matrix16SimpleInverse( const matrix_t in, matrix_t out)
-{
- vec3_t v;
- float invSqrLen;
-
- VectorCopy(in + 0, v);
- invSqrLen = 1.0f / DotProduct(v, v); VectorScale(v, invSqrLen, v);
- out[ 0] = v[0]; out[ 4] = v[1]; out[ 8] = v[2]; out[12] = -DotProduct(v, &in[12]);
-
- VectorCopy(in + 4, v);
- invSqrLen = 1.0f / DotProduct(v, v); VectorScale(v, invSqrLen, v);
- out[ 1] = v[0]; out[ 5] = v[1]; out[ 9] = v[2]; out[13] = -DotProduct(v, &in[12]);
-
- VectorCopy(in + 8, v);
- invSqrLen = 1.0f / DotProduct(v, v); VectorScale(v, invSqrLen, v);
- out[ 2] = v[0]; out[ 6] = v[1]; out[10] = v[2]; out[14] = -DotProduct(v, &in[12]);
-
- out[ 3] = 0.0f; out[ 7] = 0.0f; out[11] = 0.0f; out[15] = 1.0f;
-}
-
-qboolean SpheresIntersect(vec3_t origin1, float radius1, vec3_t origin2, float radius2)
-{
- float radiusSum = radius1 + radius2;
- vec3_t diff;
-
- VectorSubtract(origin1, origin2, diff);
-
- if (DotProduct(diff, diff) <= radiusSum * radiusSum)
- {
- return qtrue;
- }
-
- return qfalse;
-}
-
-void BoundingSphereOfSpheres(vec3_t origin1, float radius1, vec3_t origin2, float radius2, vec3_t origin3, float *radius3)
-{
- vec3_t diff;
-
- VectorScale(origin1, 0.5f, origin3);
- VectorMA(origin3, 0.5f, origin2, origin3);
-
- VectorSubtract(origin1, origin2, diff);
- *radius3 = VectorLength(diff) * 0.5f + MAX(radius1, radius2);
-}
-
-int NextPowerOfTwo(int in)
-{
- int out;
-
- for (out = 1; out < in; out <<= 1)
- ;
-
- return out;
-}
-
-unsigned short FloatToHalf(float in)
-{
- unsigned short out;
-
- union
- {
- float f;
- unsigned int i;
- } f32;
-
- int sign, inExponent, inFraction;
- int outExponent, outFraction;
-
- f32.f = in;
-
- sign = (f32.i & 0x80000000) >> 31;
- inExponent = (f32.i & 0x7F800000) >> 23;
- inFraction = f32.i & 0x007FFFFF;
-
- outExponent = CLAMP(inExponent - 127, -15, 16) + 15;
-
- outFraction = 0;
- if (outExponent == 0x1F)
- {
- if (inExponent == 0xFF && inFraction != 0)
- outFraction = 0x3FF;
- }
- else if (outExponent == 0x00)
- {
- if (inExponent == 0x00 && inFraction != 0)
- outFraction = 0x3FF;
- }
- else
- outFraction = inFraction >> 13;
-
- out = (sign << 15) | (outExponent << 10) | outFraction;
-
- return out;
-}
diff --git a/src/rend2/tr_extramath.h b/src/rend2/tr_extramath.h
deleted file mode 100644
index b4ca6f3c..00000000
--- a/src/rend2/tr_extramath.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 2010 James Canete (use.less01@gmail.com)
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_extramath.h
-
-#ifndef __TR_EXTRAMATH_H__
-#define __TR_EXTRAMATH_H__
-
-typedef vec_t matrix_t[16];
-typedef int vec2i_t[2];
-typedef int vec3i_t[3];
-typedef int vec4i_t[4];
-
-void Matrix16Zero( matrix_t out );
-void Matrix16Identity( matrix_t out );
-void Matrix16Copy( const matrix_t in, matrix_t out );
-void Matrix16Multiply( const matrix_t in1, const matrix_t in2, matrix_t out );
-void Matrix16Transform( const matrix_t in1, const vec4_t in2, vec4_t out );
-qboolean Matrix16Compare(const matrix_t a, const matrix_t b);
-void Matrix16Dump( const matrix_t in );
-void Matrix16Translation( vec3_t vec, matrix_t out );
-void Matrix16Ortho( float left, float right, float bottom, float top, float znear, float zfar, matrix_t out );
-void Matrix16View(vec3_t axes[3], vec3_t origin, matrix_t out);
-void Matrix16SimpleInverse( const matrix_t in, matrix_t out);
-
-#define VectorCopy2(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1])
-
-#define VectorCopy4(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
-#define VectorSet4(v,x,y,z,w) ((v)[0]=(x),(v)[1]=(y),(v)[2]=(z),(v)[3]=(w))
-#define DotProduct4(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] + (a)[3]*(b)[3])
-#define VectorScale4(a,b,c) ((c)[0]=(a)[0]*(b),(c)[1]=(a)[1]*(b),(c)[2]=(a)[2]*(b),(c)[3]=(a)[3]*(b))
-
-#define VectorCopy5(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3],(b)[4]=(a)[4])
-
-#define OffsetByteToFloat(a) ((float)(a) * 1.0f/127.5f - 1.0f)
-#define FloatToOffsetByte(a) (byte)(((a) + 1.0f) * 127.5f)
-#define ByteToFloat(a) ((float)(a) * 1.0f/255.0f)
-#define FloatToByte(a) (byte)((a) * 255.0f)
-
-#define RGBtosRGB(a) (((a) < 0.0031308f) ? (12.92f * (a)) : (1.055f * pow((a), 0.41666f) - 0.055f))
-#define sRGBtoRGB(a) (((a) <= 0.04045f) ? ((a) / 12.92f) : (pow((((a) + 0.055f) / 1.055f), 2.4)) )
-
-static ID_INLINE int VectorCompare4(const vec4_t v1, const vec4_t v2)
-{
- if(v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2] || v1[3] != v2[3])
- {
- return 0;
- }
- return 1;
-}
-
-static ID_INLINE int VectorCompare5(const vec5_t v1, const vec5_t v2)
-{
- if(v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2] || v1[3] != v2[3] || v1[4] != v2[4])
- {
- return 0;
- }
- return 1;
-}
-
-qboolean SpheresIntersect(vec3_t origin1, float radius1, vec3_t origin2, float radius2);
-void BoundingSphereOfSpheres(vec3_t origin1, float radius1, vec3_t origin2, float radius2, vec3_t origin3, float *radius3);
-
-#ifndef SGN
-#define SGN(x) (((x) >= 0) ? !!(x) : -1)
-#endif
-
-#ifndef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-#ifndef CLAMP
-#define CLAMP(a,b,c) MIN(MAX((a),(b)),(c))
-#endif
-
-int NextPowerOfTwo(int in);
-unsigned short FloatToHalf(float in);
-
-#endif
diff --git a/src/rend2/tr_extratypes.h b/src/rend2/tr_extratypes.h
deleted file mode 100644
index b84cd5e4..00000000
--- a/src/rend2/tr_extratypes.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 2009-2011 Andrei Drexler, Richard Allen, James Canete
-
-This file is part of Reaction source code.
-
-Reaction source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Reaction source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Reaction source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-#ifndef __TR_EXTRATYPES_H__
-#define __TR_EXTRATYPES_H__
-
-// tr_extratypes.h, for mods that want to extend tr_types.h without losing compatibility with original VMs
-
-// extra renderfx flags start at 0x0400
-#define RF_SUNFLARE 0x0400
-
-// extra refdef flags start at 0x0008
-#define RDF_NOFOG 0x0008 // don't apply fog
-#define RDF_EXTRA 0x0010 // Makro - refdefex_t to follow after refdef_t
-#define RDF_SUNLIGHT 0x0020 // SmileTheory - render sunlight and shadows
-
-typedef struct {
- float blurFactor;
- float sunDir[3];
- float sunCol[3];
- float sunAmbCol[3];
-} refdefex_t;
-
-#endif
diff --git a/src/rend2/tr_fbo.c b/src/rend2/tr_fbo.c
deleted file mode 100644
index 0ad08b20..00000000
--- a/src/rend2/tr_fbo.c
+++ /dev/null
@@ -1,861 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 2006 Kirk Barnes
-Copyright (C) 2006-2008 Robert Beckebans <trebor_7@users.sourceforge.net>
-
-This file is part of XreaL source code.
-
-XreaL source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-XreaL source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with XreaL source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_fbo.c
-#include "tr_local.h"
-
-/*
-=============
-R_CheckFBO
-=============
-*/
-qboolean R_CheckFBO(const FBO_t * fbo)
-{
- int code;
- int id;
-
- qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &id);
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->frameBuffer);
-
- code = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
-
- if(code == GL_FRAMEBUFFER_COMPLETE_EXT)
- {
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
- return qtrue;
- }
-
- // an error occured
- switch (code)
- {
- case GL_FRAMEBUFFER_COMPLETE_EXT:
- break;
-
- case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
- ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Unsupported framebuffer format\n", fbo->name);
- break;
-
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
- ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete attachment\n", fbo->name);
- break;
-
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
- ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing attachment\n", fbo->name);
- break;
-
- //case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
- // ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, duplicate attachment\n", fbo->name);
- // break;
-
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
- ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, attached images must have same dimensions\n",
- fbo->name);
- break;
-
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
- ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, attached images must have same format\n",
- fbo->name);
- break;
-
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
- ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing draw buffer\n", fbo->name);
- break;
-
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
- ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Framebuffer incomplete, missing read buffer\n", fbo->name);
- break;
-
- default:
- ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) unknown error 0x%X\n", fbo->name, code);
- //ri.Error(ERR_FATAL, "R_CheckFBO: (%s) unknown error 0x%X", fbo->name, code);
- //assert(0);
- break;
- }
-
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id);
-
- return qfalse;
-}
-
-/*
-============
-FBO_Create
-============
-*/
-FBO_t *FBO_Create(const char *name, int width, int height)
-{
- FBO_t *fbo;
-
- if(strlen(name) >= MAX_QPATH)
- {
- ri.Error(ERR_DROP, "FBO_Create: \"%s\" is too long\n", name);
- }
-
- if(width <= 0 || width > glRefConfig.maxRenderbufferSize)
- {
- ri.Error(ERR_DROP, "FBO_Create: bad width %i", width);
- }
-
- if(height <= 0 || height > glRefConfig.maxRenderbufferSize)
- {
- ri.Error(ERR_DROP, "FBO_Create: bad height %i", height);
- }
-
- if(tr.numFBOs == MAX_FBOS)
- {
- ri.Error(ERR_DROP, "FBO_Create: MAX_FBOS hit");
- }
-
- fbo = tr.fbos[tr.numFBOs] = ri.Hunk_Alloc(sizeof(*fbo), h_low);
- Q_strncpyz(fbo->name, name, sizeof(fbo->name));
- fbo->index = tr.numFBOs++;
- fbo->width = width;
- fbo->height = height;
-
- qglGenFramebuffersEXT(1, &fbo->frameBuffer);
-
- return fbo;
-}
-
-void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample)
-{
- uint32_t *pRenderBuffer;
- GLenum attachment;
- qboolean absent;
-
- switch(format)
- {
- case GL_RGB:
- case GL_RGBA:
- case GL_RGB8:
- case GL_RGBA8:
- case GL_RGB16F_ARB:
- case GL_RGBA16F_ARB:
- case GL_RGB32F_ARB:
- case GL_RGBA32F_ARB:
- fbo->colorFormat = format;
- pRenderBuffer = &fbo->colorBuffers[index];
- attachment = GL_COLOR_ATTACHMENT0_EXT + index;
- break;
-
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16_ARB:
- case GL_DEPTH_COMPONENT24_ARB:
- case GL_DEPTH_COMPONENT32_ARB:
- fbo->depthFormat = format;
- pRenderBuffer = &fbo->depthBuffer;
- attachment = GL_DEPTH_ATTACHMENT_EXT;
- break;
-
- case GL_STENCIL_INDEX:
- case GL_STENCIL_INDEX1_EXT:
- case GL_STENCIL_INDEX4_EXT:
- case GL_STENCIL_INDEX8_EXT:
- case GL_STENCIL_INDEX16_EXT:
- fbo->stencilFormat = format;
- pRenderBuffer = &fbo->stencilBuffer;
- attachment = GL_STENCIL_ATTACHMENT_EXT;
- break;
-
- case GL_DEPTH_STENCIL_EXT:
- case GL_DEPTH24_STENCIL8_EXT:
- fbo->packedDepthStencilFormat = format;
- pRenderBuffer = &fbo->packedDepthStencilBuffer;
- attachment = 0; // special for stencil and depth
- break;
-
- default:
- ri.Printf(PRINT_WARNING, "FBO_CreateBuffer: invalid format %d\n", format);
- return;
- }
-
- absent = *pRenderBuffer == 0;
- if (absent)
- qglGenRenderbuffersEXT(1, pRenderBuffer);
-
- qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, *pRenderBuffer);
- if (multisample && glRefConfig.framebufferMultisample)
- {
- qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, multisample, format, fbo->width, fbo->height);
- }
- else
- {
- qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, fbo->width, fbo->height);
- }
-
- if(absent)
- {
- if (attachment == 0)
- {
- qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer);
- qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer);
- }
- else
- qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, *pRenderBuffer);
- }
-}
-
-
-/*
-=================
-R_AttachFBOTexture1D
-=================
-*/
-void R_AttachFBOTexture1D(int texId, int index)
-{
- if(index < 0 || index >= glRefConfig.maxColorAttachments)
- {
- ri.Printf(PRINT_WARNING, "R_AttachFBOTexture1D: invalid attachment index %i\n", index);
- return;
- }
-
- qglFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_1D, texId, 0);
-}
-
-/*
-=================
-R_AttachFBOTexture2D
-=================
-*/
-void R_AttachFBOTexture2D(int target, int texId, int index)
-{
- if(target != GL_TEXTURE_2D && (target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB))
- {
- ri.Printf(PRINT_WARNING, "R_AttachFBOTexture2D: invalid target %i\n", target);
- return;
- }
-
- if(index < 0 || index >= glRefConfig.maxColorAttachments)
- {
- ri.Printf(PRINT_WARNING, "R_AttachFBOTexture2D: invalid attachment index %i\n", index);
- return;
- }
-
- qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, target, texId, 0);
-}
-
-/*
-=================
-R_AttachFBOTexture3D
-=================
-*/
-void R_AttachFBOTexture3D(int texId, int index, int zOffset)
-{
- if(index < 0 || index >= glRefConfig.maxColorAttachments)
- {
- ri.Printf(PRINT_WARNING, "R_AttachFBOTexture3D: invalid attachment index %i\n", index);
- return;
- }
-
- qglFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_3D_EXT, texId, 0, zOffset);
-}
-
-/*
-=================
-R_AttachFBOTextureDepth
-=================
-*/
-void R_AttachFBOTextureDepth(int texId)
-{
- qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0);
-}
-
-/*
-=================
-R_AttachFBOTexturePackedDepthStencil
-=================
-*/
-void R_AttachFBOTexturePackedDepthStencil(int texId)
-{
- qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0);
- qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0);
-}
-
-void FBO_AttachTextureImage(image_t *img, int index)
-{
- if (!glState.currentFBO)
- {
- ri.Printf(PRINT_WARNING, "FBO: attempted to attach a texture image with no FBO bound!\n");
- return;
- }
-
- R_AttachFBOTexture2D(GL_TEXTURE_2D, img->texnum, index);
- glState.currentFBO->colorImage[index] = img;
-}
-
-/*
-============
-FBO_Bind
-============
-*/
-void FBO_Bind(FBO_t * fbo)
-{
- if (glState.currentFBO == fbo)
- return;
-
- if (r_logFile->integer)
- {
- // don't just call LogComment, or we will get a call to va() every frame!
- if (fbo)
- GLimp_LogComment(va("--- FBO_Bind( %s ) ---\n", fbo->name));
- else
- GLimp_LogComment("--- FBO_Bind ( NULL ) ---\n");
- }
-
- if (!fbo)
- {
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
- glState.currentFBO = NULL;
-
- return;
- }
-
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->frameBuffer);
-
- /*
- if(fbo->colorBuffers[0])
- {
- qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->colorBuffers[0]);
- }
- */
-
- /*
- if(fbo->depthBuffer)
- {
- qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->depthBuffer);
- qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->depthBuffer);
- }
- */
-
- glState.currentFBO = fbo;
-}
-
-/*
-============
-FBO_Init
-============
-*/
-void FBO_Init(void)
-{
- int i;
- // int width, height, hdrFormat, multisample;
- int hdrFormat, multisample;
-
- ri.Printf(PRINT_ALL, "------- FBO_Init -------\n");
-
- if(!glRefConfig.framebufferObject)
- return;
-
- tr.numFBOs = 0;
-
- GL_CheckErrors();
-
- R_IssuePendingRenderCommands();
-
-/* if(glRefConfig.textureNonPowerOfTwo)
- {
- width = glConfig.vidWidth;
- height = glConfig.vidHeight;
- }
- else
- {
- width = NextPowerOfTwo(glConfig.vidWidth);
- height = NextPowerOfTwo(glConfig.vidHeight);
- } */
-
- hdrFormat = GL_RGBA8;
- if (r_hdr->integer && glRefConfig.framebufferObject && glRefConfig.textureFloat)
- {
- hdrFormat = GL_RGB16F_ARB;
- }
-
- qglGetIntegerv(GL_MAX_SAMPLES_EXT, &multisample);
-
- if (r_ext_framebuffer_multisample->integer < multisample)
- {
- multisample = r_ext_framebuffer_multisample->integer;
- }
-
- if (multisample < 2 || !glRefConfig.framebufferBlit)
- multisample = 0;
-
- if (multisample != r_ext_framebuffer_multisample->integer)
- {
- ri.Cvar_SetValue("r_ext_framebuffer_multisample", (float)multisample);
- }
-
- // only create a render FBO if we need to resolve MSAA or do HDR
- // otherwise just render straight to the screen (tr.renderFbo = NULL)
- if (multisample && glRefConfig.framebufferMultisample)
- {
- tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height);
- FBO_Bind(tr.renderFbo);
-
- FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, multisample);
- FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, multisample);
-
- R_CheckFBO(tr.renderFbo);
-
-
- tr.msaaResolveFbo = FBO_Create("_msaaResolve", tr.renderDepthImage->width, tr.renderDepthImage->height);
- FBO_Bind(tr.msaaResolveFbo);
-
- //FBO_CreateBuffer(tr.msaaResolveFbo, hdrFormat, 0, 0);
- FBO_AttachTextureImage(tr.renderImage, 0);
-
- //FBO_CreateBuffer(tr.msaaResolveFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
- R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);
-
- R_CheckFBO(tr.msaaResolveFbo);
- }
- else if (r_hdr->integer)
- {
- tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height);
- FBO_Bind(tr.renderFbo);
-
- //FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, 0);
- FBO_AttachTextureImage(tr.renderImage, 0);
-
- //FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
- R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);
-
- R_CheckFBO(tr.renderFbo);
- }
-
- // clear render buffer
- // this fixes the corrupt screen bug with r_hdr 1 on older hardware
- if (tr.renderFbo)
- {
- FBO_Bind(tr.renderFbo);
- qglClearColor( 1, 0, 0.5, 1 );
- qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
- FBO_Bind(NULL);
- }
-
- if (r_drawSunRays->integer)
- {
- tr.sunRaysFbo = FBO_Create("_sunRays", tr.renderDepthImage->width, tr.renderDepthImage->height);
- FBO_Bind(tr.sunRaysFbo);
-
- FBO_AttachTextureImage(tr.sunRaysImage, 0);
-
- R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);
-
- R_CheckFBO(tr.sunRaysFbo);
- }
-
- // FIXME: Don't use separate color/depth buffers for a shadow buffer
- for( i = 0; i < MAX_DRAWN_PSHADOWS; i++)
- {
- tr.pshadowFbos[i] = FBO_Create(va("_shadowmap%d", i), tr.pshadowMaps[i]->width, tr.pshadowMaps[i]->height);
- FBO_Bind(tr.pshadowFbos[i]);
-
- //FBO_CreateBuffer(tr.pshadowFbos[i], GL_RGBA8, 0, 0);
- FBO_AttachTextureImage(tr.pshadowMaps[i], 0);
-
- FBO_CreateBuffer(tr.pshadowFbos[i], GL_DEPTH_COMPONENT24_ARB, 0, 0);
- //R_AttachFBOTextureDepth(tr.textureDepthImage->texnum);
-
- R_CheckFBO(tr.pshadowFbos[i]);
- }
-
- for ( i = 0; i < 3; i++)
- {
- tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height);
- FBO_Bind(tr.sunShadowFbo[i]);
-
- //FBO_CreateBuffer(tr.sunShadowFbo[i], GL_RGBA8, 0, 0);
- //FBO_AttachTextureImage(tr.sunShadowImage, 0);
- qglDrawBuffer(GL_NONE);
- qglReadBuffer(GL_NONE);
-
- //FBO_CreateBuffer(tr.sunShadowFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
- R_AttachFBOTextureDepth(tr.sunShadowDepthImage[i]->texnum);
-
- R_CheckFBO(tr.sunShadowFbo[i]);
- }
-
- for (i = 0; i < 2; i++)
- {
- tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height);
- FBO_Bind(tr.textureScratchFbo[i]);
-
- //FBO_CreateBuffer(tr.textureScratchFbo[i], GL_RGBA8, 0, 0);
- FBO_AttachTextureImage(tr.textureScratchImage[i], 0);
-
- R_CheckFBO(tr.textureScratchFbo[i]);
- }
-
- {
- tr.calcLevelsFbo = FBO_Create("_calclevels", tr.calcLevelsImage->width, tr.calcLevelsImage->height);
- FBO_Bind(tr.calcLevelsFbo);
-
- //FBO_CreateBuffer(tr.calcLevelsFbo, hdrFormat, 0, 0);
- FBO_AttachTextureImage(tr.calcLevelsImage, 0);
-
- R_CheckFBO(tr.calcLevelsFbo);
- }
-
- {
- tr.targetLevelsFbo = FBO_Create("_targetlevels", tr.targetLevelsImage->width, tr.targetLevelsImage->height);
- FBO_Bind(tr.targetLevelsFbo);
-
- //FBO_CreateBuffer(tr.targetLevelsFbo, hdrFormat, 0, 0);
- FBO_AttachTextureImage(tr.targetLevelsImage, 0);
-
- R_CheckFBO(tr.targetLevelsFbo);
- }
-
- if (r_softOverbright->integer)
- {
- //tr.screenScratchFbo = FBO_Create("_screenscratch", width, height);
- tr.screenScratchFbo = FBO_Create("_screenscratch", tr.screenScratchImage->width, tr.screenScratchImage->height);
- FBO_Bind(tr.screenScratchFbo);
-
- //FBO_CreateBuffer(tr.screenScratchFbo, format, 0, 0);
- FBO_AttachTextureImage(tr.screenScratchImage, 0);
-
- // FIXME: hack: share zbuffer between render fbo and pre-screen fbo
- //FBO_CreateBuffer(tr.screenScratchFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0);
- R_AttachFBOTextureDepth(tr.renderDepthImage->texnum);
-
- R_CheckFBO(tr.screenScratchFbo);
- }
-
- for (i = 0; i < 2; i++)
- {
- tr.quarterFbo[i] = FBO_Create(va("_quarter%d", i), tr.quarterImage[i]->width, tr.quarterImage[i]->height);
- FBO_Bind(tr.quarterFbo[i]);
-
- //FBO_CreateBuffer(tr.quarterFbo[i], hdrFormat, 0, 0);
- FBO_AttachTextureImage(tr.quarterImage[i], 0);
-
- R_CheckFBO(tr.quarterFbo[i]);
- }
-
- {
- tr.screenShadowFbo = FBO_Create("_screenshadow", tr.screenShadowImage->width, tr.screenShadowImage->height);
- FBO_Bind(tr.screenShadowFbo);
-
- FBO_AttachTextureImage(tr.screenShadowImage, 0);
-
- R_CheckFBO(tr.screenShadowFbo);
- }
-
- if (r_ssao->integer)
- {
- tr.hdrDepthFbo = FBO_Create("_hdrDepth", tr.hdrDepthImage->width, tr.hdrDepthImage->height);
- FBO_Bind(tr.hdrDepthFbo);
-
- FBO_AttachTextureImage(tr.hdrDepthImage, 0);
-
- R_CheckFBO(tr.hdrDepthFbo);
-
- tr.screenSsaoFbo = FBO_Create("_screenssao", tr.screenSsaoImage->width, tr.screenSsaoImage->height);
- FBO_Bind(tr.screenSsaoFbo);
-
- FBO_AttachTextureImage(tr.screenSsaoImage, 0);
-
- R_CheckFBO(tr.screenSsaoFbo);
- }
-
- GL_CheckErrors();
-
- FBO_Bind(NULL);
-}
-
-/*
-============
-FBO_Shutdown
-============
-*/
-void FBO_Shutdown(void)
-{
- int i, j;
- FBO_t *fbo;
-
- ri.Printf(PRINT_ALL, "------- FBO_Shutdown -------\n");
-
- if(!glRefConfig.framebufferObject)
- return;
-
- FBO_Bind(NULL);
-
- for(i = 0; i < tr.numFBOs; i++)
- {
- fbo = tr.fbos[i];
-
- for(j = 0; j < glRefConfig.maxColorAttachments; j++)
- {
- if(fbo->colorBuffers[j])
- qglDeleteRenderbuffersEXT(1, &fbo->colorBuffers[j]);
- }
-
- if(fbo->depthBuffer)
- qglDeleteRenderbuffersEXT(1, &fbo->depthBuffer);
-
- if(fbo->stencilBuffer)
- qglDeleteRenderbuffersEXT(1, &fbo->stencilBuffer);
-
- if(fbo->frameBuffer)
- qglDeleteFramebuffersEXT(1, &fbo->frameBuffer);
- }
-}
-
-/*
-============
-R_FBOList_f
-============
-*/
-void R_FBOList_f(void)
-{
- int i;
- FBO_t *fbo;
-
- if(!glRefConfig.framebufferObject)
- {
- ri.Printf(PRINT_ALL, "GL_EXT_framebuffer_object is not available.\n");
- return;
- }
-
- ri.Printf(PRINT_ALL, " size name\n");
- ri.Printf(PRINT_ALL, "----------------------------------------------------------\n");
-
- for(i = 0; i < tr.numFBOs; i++)
- {
- fbo = tr.fbos[i];
-
- ri.Printf(PRINT_ALL, " %4i: %4i %4i %s\n", i, fbo->width, fbo->height, fbo->name);
- }
-
- ri.Printf(PRINT_ALL, " %i FBOs\n", tr.numFBOs);
-}
-
-// FIXME
-extern void RB_SetGL2D (void);
-
-void FBO_BlitFromTexture(struct image_s *src, vec4i_t inSrcBox, vec2_t inSrcTexScale, FBO_t *dst, vec4i_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend)
-{
- vec4i_t dstBox, srcBox;
- vec2_t srcTexScale;
- vec4_t color;
- vec4_t quadVerts[4];
- vec2_t texCoords[4];
- vec2_t invTexRes;
- FBO_t *oldFbo = glState.currentFBO;
- matrix_t projection;
- int width, height;
-
- if (!src)
- return;
-
- if (inSrcBox)
- {
- VectorSet4(srcBox, inSrcBox[0], inSrcBox[1], inSrcBox[0] + inSrcBox[2], inSrcBox[1] + inSrcBox[3]);
- }
- else
- {
- VectorSet4(srcBox, 0, 0, src->width, src->height);
- }
-
- // framebuffers are 0 bottom, Y up.
- if (inDstBox)
- {
- if (dst)
- {
- dstBox[0] = inDstBox[0];
- dstBox[1] = dst->height - inDstBox[1] - inDstBox[3];
- dstBox[2] = inDstBox[0] + inDstBox[2];
- dstBox[3] = dst->height - inDstBox[1];
- }
- else
- {
- dstBox[0] = inDstBox[0];
- dstBox[1] = glConfig.vidHeight - inDstBox[1] - inDstBox[3];
- dstBox[2] = inDstBox[0] + inDstBox[2];
- dstBox[3] = glConfig.vidHeight - inDstBox[1];
- }
- }
- else if (dst)
- {
- VectorSet4(dstBox, 0, dst->height, dst->width, 0);
- }
- else
- {
- VectorSet4(dstBox, 0, glConfig.vidHeight, glConfig.vidWidth, 0);
- }
-
- if (inSrcTexScale)
- {
- VectorCopy2(inSrcTexScale, srcTexScale);
- }
- else
- {
- srcTexScale[0] = srcTexScale[1] = 1.0f;
- }
-
- if (inColor)
- {
- VectorCopy4(inColor, color);
- }
- else
- {
- color[0] = color[1] = color[2] = color[3] = 1.0f;
- }
-
- if (!shaderProgram)
- {
- shaderProgram = &tr.textureColorShader;
- }
-
- FBO_Bind(dst);
-
- if (glState.currentFBO)
- {
- width = glState.currentFBO->width;
- height = glState.currentFBO->height;
- }
- else
- {
- width = glConfig.vidWidth;
- height = glConfig.vidHeight;
- }
-
- qglViewport( 0, 0, width, height );
- qglScissor( 0, 0, width, height );
-
- Matrix16Ortho(0, width, height, 0, 0, 1, projection);
-
- qglDisable( GL_CULL_FACE );
-
- GL_BindToTMU(src, TB_COLORMAP);
-
- VectorSet4(quadVerts[0], dstBox[0], dstBox[1], 0, 1);
- VectorSet4(quadVerts[1], dstBox[2], dstBox[1], 0, 1);
- VectorSet4(quadVerts[2], dstBox[2], dstBox[3], 0, 1);
- VectorSet4(quadVerts[3], dstBox[0], dstBox[3], 0, 1);
-
- texCoords[0][0] = srcBox[0] / (float)src->width; texCoords[0][1] = 1.0f - srcBox[1] / (float)src->height;
- texCoords[1][0] = srcBox[2] / (float)src->width; texCoords[1][1] = 1.0f - srcBox[1] / (float)src->height;
- texCoords[2][0] = srcBox[2] / (float)src->width; texCoords[2][1] = 1.0f - srcBox[3] / (float)src->height;
- texCoords[3][0] = srcBox[0] / (float)src->width; texCoords[3][1] = 1.0f - srcBox[3] / (float)src->height;
-
- invTexRes[0] = 1.0f / src->width * srcTexScale[0];
- invTexRes[1] = 1.0f / src->height * srcTexScale[1];
-
- GL_State( blend );
-
- GLSL_BindProgram(shaderProgram);
-
- GLSL_SetUniformMatrix16(shaderProgram, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, projection);
- GLSL_SetUniformVec4(shaderProgram, TEXTURECOLOR_UNIFORM_COLOR, color);
- GLSL_SetUniformVec2(shaderProgram, TEXTURECOLOR_UNIFORM_INVTEXRES, invTexRes);
- GLSL_SetUniformVec2(shaderProgram, TEXTURECOLOR_UNIFORM_AUTOEXPOSUREMINMAX, tr.refdef.autoExposureMinMax);
- GLSL_SetUniformVec3(shaderProgram, TEXTURECOLOR_UNIFORM_TONEMINAVGMAXLINEAR, tr.refdef.toneMinAvgMaxLinear);
-
- RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes);
-
- FBO_Bind(oldFbo);
-}
-
-void FBO_Blit(FBO_t *src, vec4i_t inSrcBox, vec2_t srcTexScale, FBO_t *dst, vec4i_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend)
-{
- vec4i_t srcBox;
-
- if (!src)
- return;
-
- // framebuffers are 0 bottom, Y up.
- if (inSrcBox)
- {
- srcBox[0] = inSrcBox[0];
- srcBox[1] = src->height - inSrcBox[1] - inSrcBox[3];
- srcBox[2] = inSrcBox[2];
- srcBox[3] = inSrcBox[3];
- }
- else
- {
- VectorSet4(srcBox, 0, src->height, src->width, -src->height);
- }
-
- FBO_BlitFromTexture(src->colorImage[0], srcBox, srcTexScale, dst, dstBox, shaderProgram, color, blend | GLS_DEPTHTEST_DISABLE);
-}
-
-void FBO_FastBlit(FBO_t *src, vec4i_t srcBox, FBO_t *dst, vec4i_t dstBox, int buffers, int filter)
-{
- vec4i_t srcBoxFinal, dstBoxFinal;
- GLuint srcFb, dstFb;
-
- if (!glRefConfig.framebufferBlit)
- {
- FBO_Blit(src, srcBox, NULL, dst, dstBox, NULL, NULL, 0);
- return;
- }
-
- // get to a neutral state first
- //FBO_Bind(NULL);
-
- srcFb = src ? src->frameBuffer : 0;
- dstFb = dst ? dst->frameBuffer : 0;
-
- if (!srcBox)
- {
- if (src)
- {
- VectorSet4(srcBoxFinal, 0, 0, src->width, src->height);
- }
- else
- {
- VectorSet4(srcBoxFinal, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
- }
- }
- else
- {
- VectorSet4(srcBoxFinal, srcBox[0], srcBox[1], srcBox[0] + srcBox[2], srcBox[1] + srcBox[3]);
- }
-
- if (!dstBox)
- {
- if (dst)
- {
- VectorSet4(dstBoxFinal, 0, 0, dst->width, dst->height);
- }
- else
- {
- VectorSet4(dstBoxFinal, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
- }
- }
- else
- {
- VectorSet4(dstBoxFinal, dstBox[0], dstBox[1], dstBox[0] + dstBox[2], dstBox[1] + dstBox[3]);
- }
-
- qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, srcFb);
- qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dstFb);
- qglBlitFramebufferEXT(srcBoxFinal[0], srcBoxFinal[1], srcBoxFinal[2], srcBoxFinal[3],
- dstBoxFinal[0], dstBoxFinal[1], dstBoxFinal[2], dstBoxFinal[3],
- buffers, filter);
-
- qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- glState.currentFBO = NULL;
-}
diff --git a/src/rend2/tr_fbo.h b/src/rend2/tr_fbo.h
deleted file mode 100644
index f0366251..00000000
--- a/src/rend2/tr_fbo.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 2010 James Canete (use.less01@gmail.com)
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_fbo.h
-
-#ifndef __TR_FBO_H__
-#define __TR_FBO_H__
-
-struct image_s;
-struct shaderProgram_s;
-
-typedef struct FBO_s
-{
- char name[MAX_QPATH];
-
- int index;
-
- uint32_t frameBuffer;
-
- uint32_t colorBuffers[16];
- int colorFormat;
- struct image_s *colorImage[16];
-
- uint32_t depthBuffer;
- int depthFormat;
-
- uint32_t stencilBuffer;
- int stencilFormat;
-
- uint32_t packedDepthStencilBuffer;
- int packedDepthStencilFormat;
-
- int width;
- int height;
-} FBO_t;
-
-void FBO_Bind(FBO_t *fbo);
-void FBO_Init(void);
-void FBO_Shutdown(void);
-
-void FBO_BlitFromTexture(struct image_s *src, vec4i_t srcBox, vec2_t srcTexScale, FBO_t *dst, vec4i_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
-void FBO_Blit(FBO_t *src, vec4i_t srcBox, vec2_t srcTexScale, FBO_t *dst, vec4i_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend);
-void FBO_FastBlit(FBO_t *src, vec4i_t srcBox, FBO_t *dst, vec4i_t dstBox, int buffers, int filter);
-
-
-#endif
diff --git a/src/rend2/tr_flares.c b/src/rend2/tr_flares.c
deleted file mode 100644
index 8e6c321f..00000000
--- a/src/rend2/tr_flares.c
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_flares.c
-
-#include "tr_local.h"
-
-/*
-=============================================================================
-
-LIGHT FLARES
-
-A light flare is an effect that takes place inside the eye when bright light
-sources are visible. The size of the flare reletive to the screen is nearly
-constant, irrespective of distance, but the intensity should be proportional to the
-projected area of the light source.
-
-A surface that has been flagged as having a light flare will calculate the depth
-buffer value that its midpoint should have when the surface is added.
-
-After all opaque surfaces have been rendered, the depth buffer is read back for
-each flare in view. If the point has not been obscured by a closer surface, the
-flare should be drawn.
-
-Surfaces that have a repeated texture should never be flagged as flaring, because
-there will only be a single flare added at the midpoint of the polygon.
-
-To prevent abrupt popping, the intensity of the flare is interpolated up and
-down as it changes visibility. This involves scene to scene state, unlike almost
-all other aspects of the renderer, and is complicated by the fact that a single
-frame may have multiple scenes.
-
-RB_RenderFlares() will be called once per view (twice in a mirrored scene, potentially
-up to five or more times in a frame with 3D status bar icons).
-
-=============================================================================
-*/
-
-
-// flare states maintain visibility over multiple frames for fading
-// layers: view, mirror, menu
-typedef struct flare_s {
- struct flare_s *next; // for active chain
-
- int addedFrame;
-
- qboolean inPortal; // true if in a portal view of the scene
- int frameSceneNum;
- void *surface;
- int fogNum;
-
- int fadeTime;
-
- qboolean visible; // state of last test
- float drawIntensity; // may be non 0 even if !visible due to fading
-
- int windowX, windowY;
- float eyeZ;
-
- vec3_t origin;
- vec3_t color;
-} flare_t;
-
-#define MAX_FLARES 128
-
-flare_t r_flareStructs[MAX_FLARES];
-flare_t *r_activeFlares, *r_inactiveFlares;
-
-int flareCoeff;
-
-/*
-==================
-R_ClearFlares
-==================
-*/
-void R_ClearFlares( void ) {
- int i;
-
- Com_Memset( r_flareStructs, 0, sizeof( r_flareStructs ) );
- r_activeFlares = NULL;
- r_inactiveFlares = NULL;
-
- for ( i = 0 ; i < MAX_FLARES ; i++ ) {
- r_flareStructs[i].next = r_inactiveFlares;
- r_inactiveFlares = &r_flareStructs[i];
- }
-}
-
-
-/*
-==================
-RB_AddFlare
-
-This is called at surface tesselation time
-==================
-*/
-void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, vec3_t normal ) {
- int i;
- flare_t *f;
- vec3_t local;
- float d = 1;
- vec4_t eye, clip, normalized, window;
-
- backEnd.pc.c_flareAdds++;
-
- if(normal && (normal[0] || normal[1] || normal[2]))
- {
- VectorSubtract( backEnd.viewParms.or.origin, point, local );
- VectorNormalizeFast(local);
- d = DotProduct(local, normal);
-
- // If the viewer is behind the flare don't add it.
- if(d < 0)
- return;
- }
-
- // if the point is off the screen, don't bother adding it
- // calculate screen coordinates and depth
- R_TransformModelToClip( point, backEnd.or.modelMatrix,
- backEnd.viewParms.projectionMatrix, eye, clip );
-
- // check to see if the point is completely off screen
- for ( i = 0 ; i < 3 ; i++ ) {
- if ( clip[i] >= clip[3] || clip[i] <= -clip[3] ) {
- return;
- }
- }
-
- R_TransformClipToWindow( clip, &backEnd.viewParms, normalized, window );
-
- if ( window[0] < 0 || window[0] >= backEnd.viewParms.viewportWidth
- || window[1] < 0 || window[1] >= backEnd.viewParms.viewportHeight ) {
- return; // shouldn't happen, since we check the clip[] above, except for FP rounding
- }
-
- // see if a flare with a matching surface, scene, and view exists
- for ( f = r_activeFlares ; f ; f = f->next ) {
- if ( f->surface == surface && f->frameSceneNum == backEnd.viewParms.frameSceneNum
- && f->inPortal == backEnd.viewParms.isPortal ) {
- break;
- }
- }
-
- // allocate a new one
- if (!f ) {
- if ( !r_inactiveFlares ) {
- // the list is completely full
- return;
- }
- f = r_inactiveFlares;
- r_inactiveFlares = r_inactiveFlares->next;
- f->next = r_activeFlares;
- r_activeFlares = f;
-
- f->surface = surface;
- f->frameSceneNum = backEnd.viewParms.frameSceneNum;
- f->inPortal = backEnd.viewParms.isPortal;
- f->addedFrame = -1;
- }
-
- if ( f->addedFrame != backEnd.viewParms.frameCount - 1 ) {
- f->visible = qfalse;
- f->fadeTime = backEnd.refdef.time - 2000;
- }
-
- f->addedFrame = backEnd.viewParms.frameCount;
- f->fogNum = fogNum;
-
- VectorCopy(point, f->origin);
- VectorCopy( color, f->color );
-
- // fade the intensity of the flare down as the
- // light surface turns away from the viewer
- VectorScale( f->color, d, f->color );
-
- // save info needed to test
- f->windowX = backEnd.viewParms.viewportX + window[0];
- f->windowY = backEnd.viewParms.viewportY + window[1];
-
- f->eyeZ = eye[2];
-}
-
-/*
-==================
-RB_AddDlightFlares
-==================
-*/
-void RB_AddDlightFlares( void ) {
- dlight_t *l;
- int i, j, k;
- fog_t *fog = NULL;
-
- if ( !r_flares->integer ) {
- return;
- }
-
- l = backEnd.refdef.dlights;
-
- if(tr.world)
- fog = tr.world->fogs;
-
- for (i=0 ; i<backEnd.refdef.num_dlights ; i++, l++) {
-
- if(fog)
- {
- // find which fog volume the light is in
- for ( j = 1 ; j < tr.world->numfogs ; j++ ) {
- fog = &tr.world->fogs[j];
- for ( k = 0 ; k < 3 ; k++ ) {
- if ( l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k] ) {
- break;
- }
- }
- if ( k == 3 ) {
- break;
- }
- }
- if ( j == tr.world->numfogs ) {
- j = 0;
- }
- }
- else
- j = 0;
-
- RB_AddFlare( (void *)l, j, l->origin, l->color, NULL );
- }
-}
-
-/*
-===============================================================================
-
-FLARE BACK END
-
-===============================================================================
-*/
-
-/*
-==================
-RB_TestFlare
-==================
-*/
-void RB_TestFlare( flare_t *f ) {
- float depth;
- qboolean visible;
- float fade;
- float screenZ;
-
- backEnd.pc.c_flareTests++;
-
- // doing a readpixels is as good as doing a glFinish(), so
- // don't bother with another sync
- glState.finishCalled = qfalse;
-
- // read back the z buffer contents
- qglReadPixels( f->windowX, f->windowY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth );
-
- screenZ = backEnd.viewParms.projectionMatrix[14] /
- ( ( 2*depth - 1 ) * backEnd.viewParms.projectionMatrix[11] - backEnd.viewParms.projectionMatrix[10] );
-
- visible = ( -f->eyeZ - -screenZ ) < 24;
-
- if ( visible ) {
- if ( !f->visible ) {
- f->visible = qtrue;
- f->fadeTime = backEnd.refdef.time - 1;
- }
- fade = ( ( backEnd.refdef.time - f->fadeTime ) /1000.0f ) * r_flareFade->value;
- } else {
- if ( f->visible ) {
- f->visible = qfalse;
- f->fadeTime = backEnd.refdef.time - 1;
- }
- fade = 1.0f - ( ( backEnd.refdef.time - f->fadeTime ) / 1000.0f ) * r_flareFade->value;
- }
-
- if ( fade < 0 ) {
- fade = 0;
- }
- if ( fade > 1 ) {
- fade = 1;
- }
-
- f->drawIntensity = fade;
-}
-
-
-/*
-==================
-RB_RenderFlare
-==================
-*/
-void RB_RenderFlare( flare_t *f ) {
- float size;
- vec3_t color;
- int iColor[3];
- float distance, intensity, factor;
- byte fogFactors[3] = {255, 255, 255};
-
- backEnd.pc.c_flareRenders++;
-
- // We don't want too big values anyways when dividing by distance.
- if(f->eyeZ > -1.0f)
- distance = 1.0f;
- else
- distance = -f->eyeZ;
-
- // calculate the flare size..
- size = backEnd.viewParms.viewportWidth * ( r_flareSize->value/640.0f + 8 / distance );
-
-/*
- * This is an alternative to intensity scaling. It changes the size of the flare on screen instead
- * with growing distance. See in the description at the top why this is not the way to go.
- // size will change ~ 1/r.
- size = backEnd.viewParms.viewportWidth * (r_flareSize->value / (distance * -2.0f));
-*/
-
-/*
- * As flare sizes stay nearly constant with increasing distance we must decrease the intensity
- * to achieve a reasonable visual result. The intensity is ~ (size^2 / distance^2) which can be
- * got by considering the ratio of
- * (flaresurface on screen) : (Surface of sphere defined by flare origin and distance from flare)
- * An important requirement is:
- * intensity <= 1 for all distances.
- *
- * The formula used here to compute the intensity is as follows:
- * intensity = flareCoeff * size^2 / (distance + size*sqrt(flareCoeff))^2
- * As you can see, the intensity will have a max. of 1 when the distance is 0.
- * The coefficient flareCoeff will determine the falloff speed with increasing distance.
- */
-
- factor = distance + size * sqrt(flareCoeff);
-
- intensity = flareCoeff * size * size / (factor * factor);
-
- VectorScale(f->color, f->drawIntensity * intensity, color);
-
-// Calculations for fogging
- if(tr.world && f->fogNum < tr.world->numfogs)
- {
- tess.numVertexes = 1;
- VectorCopy(f->origin, tess.xyz[0]);
- tess.fogNum = f->fogNum;
-
- RB_CalcModulateColorsByFog(fogFactors);
-
- // We don't need to render the flare if colors are 0 anyways.
- if(!(fogFactors[0] || fogFactors[1] || fogFactors[2]))
- return;
- }
-
- iColor[0] = color[0] * fogFactors[0];
- iColor[1] = color[1] * fogFactors[1];
- iColor[2] = color[2] * fogFactors[2];
-
- RB_BeginSurface( tr.flareShader, f->fogNum );
-
- // FIXME: use quadstamp?
- tess.xyz[tess.numVertexes][0] = f->windowX - size;
- tess.xyz[tess.numVertexes][1] = f->windowY - size;
- tess.texCoords[tess.numVertexes][0][0] = 0;
- tess.texCoords[tess.numVertexes][0][1] = 0;
- tess.vertexColors[tess.numVertexes][0] = iColor[0] / 255.0f;
- tess.vertexColors[tess.numVertexes][1] = iColor[1] / 255.0f;
- tess.vertexColors[tess.numVertexes][2] = iColor[2] / 255.0f;
- tess.vertexColors[tess.numVertexes][3] = 1.0f;
- tess.numVertexes++;
-
- tess.xyz[tess.numVertexes][0] = f->windowX - size;
- tess.xyz[tess.numVertexes][1] = f->windowY + size;
- tess.texCoords[tess.numVertexes][0][0] = 0;
- tess.texCoords[tess.numVertexes][0][1] = 1;
- tess.vertexColors[tess.numVertexes][0] = iColor[0] / 255.0f;
- tess.vertexColors[tess.numVertexes][1] = iColor[1] / 255.0f;
- tess.vertexColors[tess.numVertexes][2] = iColor[2] / 255.0f;
- tess.vertexColors[tess.numVertexes][3] = 1.0f;
- tess.numVertexes++;
-
- tess.xyz[tess.numVertexes][0] = f->windowX + size;
- tess.xyz[tess.numVertexes][1] = f->windowY + size;
- tess.texCoords[tess.numVertexes][0][0] = 1;
- tess.texCoords[tess.numVertexes][0][1] = 1;
- tess.vertexColors[tess.numVertexes][0] = iColor[0] / 255.0f;
- tess.vertexColors[tess.numVertexes][1] = iColor[1] / 255.0f;
- tess.vertexColors[tess.numVertexes][2] = iColor[2] / 255.0f;
- tess.vertexColors[tess.numVertexes][3] = 1.0f;
- tess.numVertexes++;
-
- tess.xyz[tess.numVertexes][0] = f->windowX + size;
- tess.xyz[tess.numVertexes][1] = f->windowY - size;
- tess.texCoords[tess.numVertexes][0][0] = 1;
- tess.texCoords[tess.numVertexes][0][1] = 0;
- tess.vertexColors[tess.numVertexes][0] = iColor[0] / 255.0f;
- tess.vertexColors[tess.numVertexes][1] = iColor[1] / 255.0f;
- tess.vertexColors[tess.numVertexes][2] = iColor[2] / 255.0f;
- tess.vertexColors[tess.numVertexes][3] = 1.0f;
- tess.numVertexes++;
-
- tess.indexes[tess.numIndexes++] = 0;
- tess.indexes[tess.numIndexes++] = 1;
- tess.indexes[tess.numIndexes++] = 2;
- tess.indexes[tess.numIndexes++] = 0;
- tess.indexes[tess.numIndexes++] = 2;
- tess.indexes[tess.numIndexes++] = 3;
-
- RB_EndSurface();
-}
-
-/*
-==================
-RB_RenderFlares
-
-Because flares are simulating an occular effect, they should be drawn after
-everything (all views) in the entire frame has been drawn.
-
-Because of the way portals use the depth buffer to mark off areas, the
-needed information would be lost after each view, so we are forced to draw
-flares after each view.
-
-The resulting artifact is that flares in mirrors or portals don't dim properly
-when occluded by something in the main view, and portal flares that should
-extend past the portal edge will be overwritten.
-==================
-*/
-void RB_RenderFlares (void) {
- flare_t *f;
- flare_t **prev;
- qboolean draw;
- matrix_t oldmodelview, oldprojection, matrix;
-
- if ( !r_flares->integer ) {
- return;
- }
-
- if(r_flareCoeff->modified)
- {
- if(r_flareCoeff->value == 0.0f)
- flareCoeff = atof(FLARE_STDCOEFF);
- else
- flareCoeff = r_flareCoeff->value;
-
- r_flareCoeff->modified = qfalse;
- }
-
- // Reset currentEntity to world so that any previously referenced entities
- // don't have influence on the rendering of these flares (i.e. RF_ renderer flags).
- backEnd.currentEntity = &tr.worldEntity;
- backEnd.or = backEnd.viewParms.world;
-
-// RB_AddDlightFlares();
-
- // perform z buffer readback on each flare in this view
- draw = qfalse;
- prev = &r_activeFlares;
- while ( ( f = *prev ) != NULL ) {
- // throw out any flares that weren't added last frame
- if ( f->addedFrame < backEnd.viewParms.frameCount - 1 ) {
- *prev = f->next;
- f->next = r_inactiveFlares;
- r_inactiveFlares = f;
- continue;
- }
-
- // don't draw any here that aren't from this scene / portal
- f->drawIntensity = 0;
- if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum
- && f->inPortal == backEnd.viewParms.isPortal ) {
- RB_TestFlare( f );
- if ( f->drawIntensity ) {
- draw = qtrue;
- } else {
- // this flare has completely faded out, so remove it from the chain
- *prev = f->next;
- f->next = r_inactiveFlares;
- r_inactiveFlares = f;
- continue;
- }
- }
-
- prev = &f->next;
- }
-
- if ( !draw ) {
- return; // none visible
- }
-
- if ( backEnd.viewParms.isPortal ) {
- qglDisable (GL_CLIP_PLANE0);
- }
-
- Matrix16Copy(glState.projection, oldprojection);
- Matrix16Copy(glState.modelview, oldmodelview);
- Matrix16Identity(matrix);
- GL_SetModelviewMatrix(matrix);
- Matrix16Ortho( backEnd.viewParms.viewportX, backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
- backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
- -99999, 99999, matrix );
- GL_SetProjectionMatrix(matrix);
-
- for ( f = r_activeFlares ; f ; f = f->next ) {
- if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum
- && f->inPortal == backEnd.viewParms.isPortal
- && f->drawIntensity ) {
- RB_RenderFlare( f );
- }
- }
-
- GL_SetProjectionMatrix(oldprojection);
- GL_SetModelviewMatrix(oldmodelview);
-}
-
-
-
-
-
diff --git a/src/rend2/tr_font.c b/src/rend2/tr_font.c
deleted file mode 100644
index 21226709..00000000
--- a/src/rend2/tr_font.c
+++ /dev/null
@@ -1,554 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_font.c
-//
-//
-// The font system uses FreeType 2.x to render TrueType fonts for use within the game.
-// As of this writing ( Nov, 2000 ) Team Arena uses these fonts for all of the ui and
-// about 90% of the cgame presentation. A few areas of the CGAME were left uses the old
-// fonts since the code is shared with standard Q3A.
-//
-// If you include this font rendering code in a commercial product you MUST include the
-// following somewhere with your product, see www.freetype.org for specifics or changes.
-// The Freetype code also uses some hinting techniques that MIGHT infringe on patents
-// held by apple so be aware of that also.
-//
-// As of Q3A 1.25+ and Team Arena, we are shipping the game with the font rendering code
-// disabled. This removes any potential patent issues and it keeps us from having to
-// distribute an actual TrueTrype font which is 1. expensive to do and 2. seems to require
-// an act of god to accomplish.
-//
-// What we did was pre-render the fonts using FreeType ( which is why we leave the FreeType
-// credit in the credits ) and then saved off the glyph data and then hand touched up the
-// font bitmaps so they scale a bit better in GL.
-//
-// There are limitations in the way fonts are saved and reloaded in that it is based on
-// point size and not name. So if you pre-render Helvetica in 18 point and Impact in 18 point
-// you will end up with a single 18 point data file and image set. Typically you will want to
-// choose 3 sizes to best approximate the scaling you will be doing in the ui scripting system
-//
-// In the UI Scripting code, a scale of 1.0 is equal to a 48 point font. In Team Arena, we
-// use three or four scales, most of them exactly equaling the specific rendered size. We
-// rendered three sizes in Team Arena, 12, 16, and 20.
-//
-// To generate new font data you need to go through the following steps.
-// 1. delete the fontImage_x_xx.tga files and fontImage_xx.dat files from the fonts path.
-// 2. in a ui script, specificy a font, smallFont, and bigFont keyword with font name and
-// point size. the original TrueType fonts must exist in fonts at this point.
-// 3. run the game, you should see things normally.
-// 4. Exit the game and there will be three dat files and at least three tga files. The
-// tga's are in 256x256 pages so if it takes three images to render a 24 point font you
-// will end up with fontImage_0_24.tga through fontImage_2_24.tga
-// 5. In future runs of the game, the system looks for these images and data files when a s
-// specific point sized font is rendered and loads them for use.
-// 6. Because of the original beta nature of the FreeType code you will probably want to hand
-// touch the font bitmaps.
-//
-// Currently a define in the project turns on or off the FreeType code which is currently
-// defined out. To pre-render new fonts you need enable the define ( BUILD_FREETYPE ) and
-// uncheck the exclude from build check box in the FreeType2 area of the Renderer project.
-
-
-#include "tr_local.h"
-#include "../qcommon/qcommon.h"
-
-#ifdef BUILD_FREETYPE
-#include <ft2build.h>
-#include FT_ERRORS_H
-#include FT_SYSTEM_H
-#include FT_IMAGE_H
-#include FT_FREETYPE_H
-#include FT_OUTLINE_H
-
-#define _FLOOR(x) ((x) & -64)
-#define _CEIL(x) (((x)+63) & -64)
-#define _TRUNC(x) ((x) >> 6)
-
-FT_Library ftLibrary = NULL;
-#endif
-
-#define MAX_FONTS 6
-static int registeredFontCount = 0;
-static fontInfo_t registeredFont[MAX_FONTS];
-
-#ifdef BUILD_FREETYPE
-void R_GetGlyphInfo(FT_GlyphSlot glyph, int *left, int *right, int *width, int *top, int *bottom, int *height, int *pitch) {
- *left = _FLOOR( glyph->metrics.horiBearingX );
- *right = _CEIL( glyph->metrics.horiBearingX + glyph->metrics.width );
- *width = _TRUNC(*right - *left);
-
- *top = _CEIL( glyph->metrics.horiBearingY );
- *bottom = _FLOOR( glyph->metrics.horiBearingY - glyph->metrics.height );
- *height = _TRUNC( *top - *bottom );
- *pitch = ( qtrue ? (*width+3) & -4 : (*width+7) >> 3 );
-}
-
-
-FT_Bitmap *R_RenderGlyph(FT_GlyphSlot glyph, glyphInfo_t* glyphOut) {
- FT_Bitmap *bit2;
- int left, right, width, top, bottom, height, pitch, size;
-
- R_GetGlyphInfo(glyph, &left, &right, &width, &top, &bottom, &height, &pitch);
-
- if ( glyph->format == ft_glyph_format_outline ) {
- size = pitch*height;
-
- bit2 = ri.Malloc(sizeof(FT_Bitmap));
-
- bit2->width = width;
- bit2->rows = height;
- bit2->pitch = pitch;
- bit2->pixel_mode = ft_pixel_mode_grays;
- //bit2->pixel_mode = ft_pixel_mode_mono;
- bit2->buffer = ri.Malloc(pitch*height);
- bit2->num_grays = 256;
-
- Com_Memset( bit2->buffer, 0, size );
-
- FT_Outline_Translate( &glyph->outline, -left, -bottom );
-
- FT_Outline_Get_Bitmap( ftLibrary, &glyph->outline, bit2 );
-
- glyphOut->height = height;
- glyphOut->pitch = pitch;
- glyphOut->top = (glyph->metrics.horiBearingY >> 6) + 1;
- glyphOut->bottom = bottom;
-
- return bit2;
- } else {
- ri.Printf(PRINT_ALL, "Non-outline fonts are not supported\n");
- }
- return NULL;
-}
-
-void WriteTGA (char *filename, byte *data, int width, int height) {
- byte *buffer;
- int i, c;
- int row;
- unsigned char *flip;
- unsigned char *src, *dst;
-
- buffer = ri.Malloc(width*height*4 + 18);
- Com_Memset (buffer, 0, 18);
- buffer[2] = 2; // uncompressed type
- buffer[12] = width&255;
- buffer[13] = width>>8;
- buffer[14] = height&255;
- buffer[15] = height>>8;
- buffer[16] = 32; // pixel size
-
- // swap rgb to bgr
- c = 18 + width * height * 4;
- for (i=18 ; i<c ; i+=4)
- {
- buffer[i] = data[i-18+2]; // blue
- buffer[i+1] = data[i-18+1]; // green
- buffer[i+2] = data[i-18+0]; // red
- buffer[i+3] = data[i-18+3]; // alpha
- }
-
- // flip upside down
- flip = (unsigned char *)ri.Malloc(width*4);
- for(row = 0; row < height/2; row++)
- {
- src = buffer + 18 + row * 4 * width;
- dst = buffer + 18 + (height - row - 1) * 4 * width;
-
- Com_Memcpy(flip, src, width*4);
- Com_Memcpy(src, dst, width*4);
- Com_Memcpy(dst, flip, width*4);
- }
- ri.Free(flip);
-
- ri.FS_WriteFile(filename, buffer, c);
-
- //f = fopen (filename, "wb");
- //fwrite (buffer, 1, c, f);
- //fclose (f);
-
- ri.Free (buffer);
-}
-
-static glyphInfo_t *RE_ConstructGlyphInfo(unsigned char *imageOut, int *xOut, int *yOut, int *maxHeight, FT_Face face, const unsigned char c, qboolean calcHeight) {
- int i;
- static glyphInfo_t glyph;
- unsigned char *src, *dst;
- float scaled_width, scaled_height;
- FT_Bitmap *bitmap = NULL;
-
- Com_Memset(&glyph, 0, sizeof(glyphInfo_t));
- // make sure everything is here
- if (face != NULL) {
- FT_Load_Glyph(face, FT_Get_Char_Index( face, c), FT_LOAD_DEFAULT );
- bitmap = R_RenderGlyph(face->glyph, &glyph);
- if (bitmap) {
- glyph.xSkip = (face->glyph->metrics.horiAdvance >> 6) + 1;
- } else {
- return &glyph;
- }
-
- if (glyph.height > *maxHeight) {
- *maxHeight = glyph.height;
- }
-
- if (calcHeight) {
- ri.Free(bitmap->buffer);
- ri.Free(bitmap);
- return &glyph;
- }
-
-/*
- // need to convert to power of 2 sizes so we do not get
- // any scaling from the gl upload
- for (scaled_width = 1 ; scaled_width < glyph.pitch ; scaled_width<<=1)
- ;
- for (scaled_height = 1 ; scaled_height < glyph.height ; scaled_height<<=1)
- ;
-*/
-
- scaled_width = glyph.pitch;
- scaled_height = glyph.height;
-
- // we need to make sure we fit
- if (*xOut + scaled_width + 1 >= 255) {
- *xOut = 0;
- *yOut += *maxHeight + 1;
- }
-
- if (*yOut + *maxHeight + 1 >= 255) {
- *yOut = -1;
- *xOut = -1;
- ri.Free(bitmap->buffer);
- ri.Free(bitmap);
- return &glyph;
- }
-
-
- src = bitmap->buffer;
- dst = imageOut + (*yOut * 256) + *xOut;
-
- if (bitmap->pixel_mode == ft_pixel_mode_mono) {
- for (i = 0; i < glyph.height; i++) {
- int j;
- unsigned char *_src = src;
- unsigned char *_dst = dst;
- unsigned char mask = 0x80;
- unsigned char val = *_src;
- for (j = 0; j < glyph.pitch; j++) {
- if (mask == 0x80) {
- val = *_src++;
- }
- if (val & mask) {
- *_dst = 0xff;
- }
- mask >>= 1;
-
- if ( mask == 0 ) {
- mask = 0x80;
- }
- _dst++;
- }
-
- src += glyph.pitch;
- dst += 256;
- }
- } else {
- for (i = 0; i < glyph.height; i++) {
- Com_Memcpy(dst, src, glyph.pitch);
- src += glyph.pitch;
- dst += 256;
- }
- }
-
- // we now have an 8 bit per pixel grey scale bitmap
- // that is width wide and pf->ftSize->metrics.y_ppem tall
-
- glyph.imageHeight = scaled_height;
- glyph.imageWidth = scaled_width;
- glyph.s = (float)*xOut / 256;
- glyph.t = (float)*yOut / 256;
- glyph.s2 = glyph.s + (float)scaled_width / 256;
- glyph.t2 = glyph.t + (float)scaled_height / 256;
-
- *xOut += scaled_width + 1;
-
- ri.Free(bitmap->buffer);
- ri.Free(bitmap);
- }
-
- return &glyph;
-}
-#endif
-
-static int fdOffset;
-static byte *fdFile;
-
-int readInt( void ) {
- int i = fdFile[fdOffset]+(fdFile[fdOffset+1]<<8)+(fdFile[fdOffset+2]<<16)+(fdFile[fdOffset+3]<<24);
- fdOffset += 4;
- return i;
-}
-
-typedef union {
- byte fred[4];
- float ffred;
-} poor;
-
-float readFloat( void ) {
- poor me;
-#if defined Q3_BIG_ENDIAN
- me.fred[0] = fdFile[fdOffset+3];
- me.fred[1] = fdFile[fdOffset+2];
- me.fred[2] = fdFile[fdOffset+1];
- me.fred[3] = fdFile[fdOffset+0];
-#elif defined Q3_LITTLE_ENDIAN
- me.fred[0] = fdFile[fdOffset+0];
- me.fred[1] = fdFile[fdOffset+1];
- me.fred[2] = fdFile[fdOffset+2];
- me.fred[3] = fdFile[fdOffset+3];
-#endif
- fdOffset += 4;
- return me.ffred;
-}
-
-void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font) {
-#ifdef BUILD_FREETYPE
- FT_Face face;
- int j, k, xOut, yOut, lastStart, imageNumber;
- int scaledSize, newSize, maxHeight, left;
- unsigned char *out, *imageBuff;
- glyphInfo_t *glyph;
- image_t *image;
- qhandle_t h;
- float max;
- float dpi = 72;
- float glyphScale;
-#endif
- void *faceData;
- int i, len;
- char name[1024];
-
- if (!fontName) {
- ri.Printf(PRINT_ALL, "RE_RegisterFont: called with empty name\n");
- return;
- }
-
- if (pointSize <= 0) {
- pointSize = 12;
- }
-
- R_IssuePendingRenderCommands();
-
- if (registeredFontCount >= MAX_FONTS) {
- ri.Printf(PRINT_WARNING, "RE_RegisterFont: Too many fonts registered already.\n");
- return;
- }
-
- Com_sprintf(name, sizeof(name), "fonts/fontImage_%i.dat",pointSize);
- for (i = 0; i < registeredFontCount; i++) {
- if (Q_stricmp(name, registeredFont[i].name) == 0) {
- Com_Memcpy(font, &registeredFont[i], sizeof(fontInfo_t));
- return;
- }
- }
-
- len = ri.FS_ReadFile(name, NULL);
- if (len == sizeof(fontInfo_t)) {
- ri.FS_ReadFile(name, &faceData);
- fdOffset = 0;
- fdFile = faceData;
- for(i=0; i<GLYPHS_PER_FONT; i++) {
- font->glyphs[i].height = readInt();
- font->glyphs[i].top = readInt();
- font->glyphs[i].bottom = readInt();
- font->glyphs[i].pitch = readInt();
- font->glyphs[i].xSkip = readInt();
- font->glyphs[i].imageWidth = readInt();
- font->glyphs[i].imageHeight = readInt();
- font->glyphs[i].s = readFloat();
- font->glyphs[i].t = readFloat();
- font->glyphs[i].s2 = readFloat();
- font->glyphs[i].t2 = readFloat();
- font->glyphs[i].glyph = readInt();
- Q_strncpyz(font->glyphs[i].shaderName, (const char *)&fdFile[fdOffset], sizeof(font->glyphs[i].shaderName));
- fdOffset += sizeof(font->glyphs[i].shaderName);
- }
- font->glyphScale = readFloat();
- Com_Memcpy(font->name, &fdFile[fdOffset], MAX_QPATH);
-
-// Com_Memcpy(font, faceData, sizeof(fontInfo_t));
- Q_strncpyz(font->name, name, sizeof(font->name));
- for (i = GLYPH_START; i < GLYPH_END; i++) {
- font->glyphs[i].glyph = RE_RegisterShaderNoMip(font->glyphs[i].shaderName);
- }
- Com_Memcpy(&registeredFont[registeredFontCount++], font, sizeof(fontInfo_t));
- return;
- }
-
-#ifndef BUILD_FREETYPE
- ri.Printf(PRINT_WARNING, "RE_RegisterFont: FreeType code not available\n");
-#else
- if (ftLibrary == NULL) {
- ri.Printf(PRINT_WARNING, "RE_RegisterFont: FreeType not initialized.\n");
- return;
- }
-
- len = ri.FS_ReadFile(fontName, &faceData);
- if (len <= 0) {
- ri.Printf(PRINT_WARNING, "RE_RegisterFont: Unable to read font file '%s'\n", fontName);
- return;
- }
-
- // allocate on the stack first in case we fail
- if (FT_New_Memory_Face( ftLibrary, faceData, len, 0, &face )) {
- ri.Printf(PRINT_WARNING, "RE_RegisterFont: FreeType, unable to allocate new face.\n");
- return;
- }
-
-
- if (FT_Set_Char_Size( face, pointSize << 6, pointSize << 6, dpi, dpi)) {
- ri.Printf(PRINT_WARNING, "RE_RegisterFont: FreeType, unable to set face char size.\n");
- return;
- }
-
- //*font = &registeredFonts[registeredFontCount++];
-
- // make a 256x256 image buffer, once it is full, register it, clean it and keep going
- // until all glyphs are rendered
-
- out = ri.Malloc(1024*1024);
- if (out == NULL) {
- ri.Printf(PRINT_WARNING, "RE_RegisterFont: ri.Malloc failure during output image creation.\n");
- return;
- }
- Com_Memset(out, 0, 1024*1024);
-
- maxHeight = 0;
-
- for (i = GLYPH_START; i < GLYPH_END; i++) {
- RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qtrue);
- }
-
- xOut = 0;
- yOut = 0;
- i = GLYPH_START;
- lastStart = i;
- imageNumber = 0;
-
- while ( i <= GLYPH_END ) {
-
- glyph = RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qfalse);
-
- if (xOut == -1 || yOut == -1 || i == GLYPH_END) {
- // ran out of room
- // we need to create an image from the bitmap, set all the handles in the glyphs to this point
- //
-
- scaledSize = 256*256;
- newSize = scaledSize * 4;
- imageBuff = ri.Malloc(newSize);
- left = 0;
- max = 0;
- for ( k = 0; k < (scaledSize) ; k++ ) {
- if (max < out[k]) {
- max = out[k];
- }
- }
-
- if (max > 0) {
- max = 255/max;
- }
-
- for ( k = 0; k < (scaledSize) ; k++ ) {
- imageBuff[left++] = 255;
- imageBuff[left++] = 255;
- imageBuff[left++] = 255;
-
- imageBuff[left++] = ((float)out[k] * max);
- }
-
- Com_sprintf (name, sizeof(name), "fonts/fontImage_%i_%i.tga", imageNumber++, pointSize);
- if (r_saveFontData->integer) {
- WriteTGA(name, imageBuff, 256, 256);
- }
-
- //Com_sprintf (name, sizeof(name), "fonts/fontImage_%i_%i", imageNumber++, pointSize);
- image = R_CreateImage(name, imageBuff, 256, 256, IMGTYPE_COLORALPHA, IMGFLAG_CLAMPTOEDGE, 0 );
- h = RE_RegisterShaderFromImage(name, LIGHTMAP_2D, image, qfalse);
- for (j = lastStart; j < i; j++) {
- font->glyphs[j].glyph = h;
- Q_strncpyz(font->glyphs[j].shaderName, name, sizeof(font->glyphs[j].shaderName));
- }
- lastStart = i;
- Com_Memset(out, 0, 1024*1024);
- xOut = 0;
- yOut = 0;
- ri.Free(imageBuff);
- i++;
- } else {
- Com_Memcpy(&font->glyphs[i], glyph, sizeof(glyphInfo_t));
- i++;
- }
- }
-
- // change the scale to be relative to 1 based on 72 dpi ( so dpi of 144 means a scale of .5 )
- glyphScale = 72.0f / dpi;
-
- // we also need to adjust the scale based on point size relative to 48 points as the ui scaling is based on a 48 point font
- glyphScale *= 48.0f / pointSize;
-
- registeredFont[registeredFontCount].glyphScale = glyphScale;
- font->glyphScale = glyphScale;
- Com_Memcpy(&registeredFont[registeredFontCount++], font, sizeof(fontInfo_t));
-
- if (r_saveFontData->integer) {
- ri.FS_WriteFile(va("fonts/fontImage_%i.dat", pointSize), font, sizeof(fontInfo_t));
- }
-
- ri.Free(out);
-
- ri.FS_FreeFile(faceData);
-#endif
-}
-
-
-
-void R_InitFreeType(void) {
-#ifdef BUILD_FREETYPE
- if (FT_Init_FreeType( &ftLibrary )) {
- ri.Printf(PRINT_WARNING, "R_InitFreeType: Unable to initialize FreeType.\n");
- }
-#endif
- registeredFontCount = 0;
-}
-
-
-void R_DoneFreeType(void) {
-#ifdef BUILD_FREETYPE
- if (ftLibrary) {
- FT_Done_FreeType( ftLibrary );
- ftLibrary = NULL;
- }
-#endif
- registeredFontCount = 0;
-}
-
diff --git a/src/rend2/tr_glsl.c b/src/rend2/tr_glsl.c
deleted file mode 100644
index ccfea909..00000000
--- a/src/rend2/tr_glsl.c
+++ /dev/null
@@ -1,1932 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 2006-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
-
-This file is part of XreaL source code.
-
-XreaL source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-XreaL source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with XreaL source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_glsl.c
-#include "tr_local.h"
-
-void GLSL_BindNullProgram(void);
-
-extern const char *fallbackShader_bokeh_vp;
-extern const char *fallbackShader_bokeh_fp;
-extern const char *fallbackShader_calclevels4x_vp;
-extern const char *fallbackShader_calclevels4x_fp;
-extern const char *fallbackShader_depthblur_vp;
-extern const char *fallbackShader_depthblur_fp;
-extern const char *fallbackShader_dlight_vp;
-extern const char *fallbackShader_dlight_fp;
-extern const char *fallbackShader_down4x_vp;
-extern const char *fallbackShader_down4x_fp;
-extern const char *fallbackShader_fogpass_vp;
-extern const char *fallbackShader_fogpass_fp;
-extern const char *fallbackShader_generic_vp;
-extern const char *fallbackShader_generic_fp;
-extern const char *fallbackShader_lightall_vp;
-extern const char *fallbackShader_lightall_fp;
-extern const char *fallbackShader_pshadow_vp;
-extern const char *fallbackShader_pshadow_fp;
-extern const char *fallbackShader_shadowfill_vp;
-extern const char *fallbackShader_shadowfill_fp;
-extern const char *fallbackShader_shadowmask_vp;
-extern const char *fallbackShader_shadowmask_fp;
-extern const char *fallbackShader_ssao_vp;
-extern const char *fallbackShader_ssao_fp;
-extern const char *fallbackShader_texturecolor_vp;
-extern const char *fallbackShader_texturecolor_fp;
-extern const char *fallbackShader_tonemap_vp;
-extern const char *fallbackShader_tonemap_fp;
-
-static void GLSL_PrintInfoLog(GLhandleARB object, qboolean developerOnly)
-{
- char *msg;
- static char msgPart[1024];
- int maxLength = 0;
- int i;
- int printLevel = developerOnly ? PRINT_DEVELOPER : PRINT_ALL;
-
- qglGetObjectParameterivARB(object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &maxLength);
-
- if (maxLength <= 0)
- {
- ri.Printf(printLevel, "No compile log.\n");
- return;
- }
-
- ri.Printf(printLevel, "compile log:\n");
-
- if (maxLength < 1023)
- {
- qglGetInfoLogARB(object, maxLength, &maxLength, msgPart);
-
- msgPart[maxLength + 1] = '\0';
-
- ri.Printf(printLevel, "%s\n", msgPart);
- }
- else
- {
- msg = ri.Malloc(maxLength);
-
- qglGetInfoLogARB(object, maxLength, &maxLength, msg);
-
- for(i = 0; i < maxLength; i += 1024)
- {
- Q_strncpyz(msgPart, msg + i, sizeof(msgPart));
-
- ri.Printf(printLevel, "%s\n", msgPart);
- }
-
- ri.Free(msg);
- }
-}
-
-static void GLSL_PrintShaderSource(GLhandleARB object)
-{
- char *msg;
- static char msgPart[1024];
- int maxLength = 0;
- int i;
-
- qglGetObjectParameterivARB(object, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB, &maxLength);
-
- msg = ri.Malloc(maxLength);
-
- qglGetShaderSourceARB(object, maxLength, &maxLength, msg);
-
- for(i = 0; i < maxLength; i += 1024)
- {
- Q_strncpyz(msgPart, msg + i, sizeof(msgPart));
- ri.Printf(PRINT_ALL, "%s\n", msgPart);
- }
-
- ri.Free(msg);
-}
-
-static void GLSL_GetShaderHeader( GLenum shaderType, const GLcharARB *extra, char *dest, int size )
-{
- float fbufWidthScale, fbufHeightScale;
-
- dest[0] = '\0';
-
- // HACK: abuse the GLSL preprocessor to turn GLSL 1.20 shaders into 1.30 ones
- if(glRefConfig.glslMajorVersion > 1 || (glRefConfig.glslMajorVersion == 1 && glRefConfig.glslMinorVersion >= 30))
- {
- Q_strcat(dest, size, "#version 130\n");
-
- if(shaderType == GL_VERTEX_SHADER_ARB)
- {
- Q_strcat(dest, size, "#define attribute in\n");
- Q_strcat(dest, size, "#define varying out\n");
- }
- else
- {
- Q_strcat(dest, size, "#define varying in\n");
-
- Q_strcat(dest, size, "out vec4 out_Color;\n");
- Q_strcat(dest, size, "#define gl_FragColor out_Color\n");
- }
- }
- else
- {
- Q_strcat(dest, size, "#version 120\n");
- }
-
- // HACK: add some macros to avoid extra uniforms and save speed and code maintenance
- //Q_strcat(dest, size,
- // va("#ifndef r_SpecularExponent\n#define r_SpecularExponent %f\n#endif\n", r_specularExponent->value));
- //Q_strcat(dest, size,
- // va("#ifndef r_SpecularScale\n#define r_SpecularScale %f\n#endif\n", r_specularScale->value));
- //Q_strcat(dest, size,
- // va("#ifndef r_NormalScale\n#define r_NormalScale %f\n#endif\n", r_normalScale->value));
-
-
- Q_strcat(dest, size, "#ifndef M_PI\n#define M_PI 3.14159265358979323846f\n#endif\n");
-
- //Q_strcat(dest, size, va("#ifndef MAX_SHADOWMAPS\n#define MAX_SHADOWMAPS %i\n#endif\n", MAX_SHADOWMAPS));
-
- Q_strcat(dest, size,
- va("#ifndef deformGen_t\n"
- "#define deformGen_t\n"
- "#define DGEN_WAVE_SIN %i\n"
- "#define DGEN_WAVE_SQUARE %i\n"
- "#define DGEN_WAVE_TRIANGLE %i\n"
- "#define DGEN_WAVE_SAWTOOTH %i\n"
- "#define DGEN_WAVE_INVERSE_SAWTOOTH %i\n"
- "#define DGEN_BULGE %i\n"
- "#define DGEN_MOVE %i\n"
- "#endif\n",
- DGEN_WAVE_SIN,
- DGEN_WAVE_SQUARE,
- DGEN_WAVE_TRIANGLE,
- DGEN_WAVE_SAWTOOTH,
- DGEN_WAVE_INVERSE_SAWTOOTH,
- DGEN_BULGE,
- DGEN_MOVE));
-
- Q_strcat(dest, size,
- va("#ifndef tcGen_t\n"
- "#define tcGen_t\n"
- "#define TCGEN_LIGHTMAP %i\n"
- "#define TCGEN_TEXTURE %i\n"
- "#define TCGEN_ENVIRONMENT_MAPPED %i\n"
- "#define TCGEN_FOG %i\n"
- "#define TCGEN_VECTOR %i\n"
- "#endif\n",
- TCGEN_LIGHTMAP,
- TCGEN_TEXTURE,
- TCGEN_ENVIRONMENT_MAPPED,
- TCGEN_FOG,
- TCGEN_VECTOR));
-
- Q_strcat(dest, size,
- va("#ifndef colorGen_t\n"
- "#define colorGen_t\n"
- "#define CGEN_LIGHTING_DIFFUSE %i\n"
- "#endif\n",
- CGEN_LIGHTING_DIFFUSE));
-
- Q_strcat(dest, size,
- va("#ifndef alphaGen_t\n"
- "#define alphaGen_t\n"
- "#define AGEN_LIGHTING_SPECULAR %i\n"
- "#define AGEN_PORTAL %i\n"
- "#define AGEN_FRESNEL %i\n"
- "#endif\n",
- AGEN_LIGHTING_SPECULAR,
- AGEN_PORTAL,
- AGEN_FRESNEL));
-
- Q_strcat(dest, size,
- va("#ifndef texenv_t\n"
- "#define texenv_t\n"
- "#define TEXENV_MODULATE %i\n"
- "#define TEXENV_ADD %i\n"
- "#define TEXENV_REPLACE %i\n"
- "#endif\n",
- GL_MODULATE,
- GL_ADD,
- GL_REPLACE));
-
- fbufWidthScale = 1.0f / ((float)glConfig.vidWidth);
- fbufHeightScale = 1.0f / ((float)glConfig.vidHeight);
- Q_strcat(dest, size,
- va("#ifndef r_FBufScale\n#define r_FBufScale vec2(%f, %f)\n#endif\n", fbufWidthScale, fbufHeightScale));
-
- if (extra)
- {
- Q_strcat(dest, size, extra);
- }
-
- // OK we added a lot of stuff but if we do something bad in the GLSL shaders then we want the proper line
- // so we have to reset the line counting
- Q_strcat(dest, size, "#line 0\n");
-}
-
-static int GLSL_CompileGPUShader(GLhandleARB program, GLhandleARB *prevShader, const GLcharARB *buffer, int size, GLenum shaderType)
-{
- GLint compiled;
- GLhandleARB shader;
-
- shader = qglCreateShaderObjectARB(shaderType);
-
- qglShaderSourceARB(shader, 1, (const GLcharARB **)&buffer, &size);
-
- // compile shader
- qglCompileShaderARB(shader);
-
- // check if shader compiled
- qglGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled);
- if(!compiled)
- {
- GLSL_PrintShaderSource(shader);
- GLSL_PrintInfoLog(shader, qfalse);
- ri.Error(ERR_DROP, "Couldn't compile shader");
- return 0;
- }
-
- //GLSL_PrintInfoLog(shader, qtrue);
- //GLSL_PrintShaderSource(shader);
-
- if (*prevShader)
- {
- qglDetachObjectARB(program, *prevShader);
- qglDeleteObjectARB(*prevShader);
- }
-
- // attach shader to program
- qglAttachObjectARB(program, shader);
-
- *prevShader = shader;
-
- return 1;
-}
-
-static int GLSL_LoadGPUShaderText(const char *name, const char *fallback,
- GLenum shaderType, char *dest, int destSize)
-{
- char filename[MAX_QPATH];
- GLcharARB *buffer = NULL;
- const GLcharARB *shaderText = NULL;
- int size;
- int result;
-
- if(shaderType == GL_VERTEX_SHADER_ARB)
- {
- Com_sprintf(filename, sizeof(filename), "glsl/%s_vp.glsl", name);
- }
- else
- {
- Com_sprintf(filename, sizeof(filename), "glsl/%s_fp.glsl", name);
- }
-
- ri.Printf(PRINT_DEVELOPER, "...loading '%s'\n", filename);
- size = ri.FS_ReadFile(filename, (void **)&buffer);
- if(!buffer)
- {
- if (fallback)
- {
- ri.Printf(PRINT_DEVELOPER, "couldn't load, using fallback\n");
- shaderText = fallback;
- size = strlen(shaderText);
- }
- else
- {
- ri.Printf(PRINT_DEVELOPER, "couldn't load!\n");
- return 0;
- }
- }
- else
- {
- shaderText = buffer;
- }
-
- if (size > destSize)
- {
- result = 0;
- }
- else
- {
- Q_strncpyz(dest, shaderText, size + 1);
- result = 1;
- }
-
- if (buffer)
- {
- ri.FS_FreeFile(buffer);
- }
-
- return result;
-}
-
-static void GLSL_LinkProgram(GLhandleARB program)
-{
- GLint linked;
-
- qglLinkProgramARB(program);
-
- qglGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &linked);
- if(!linked)
- {
- GLSL_PrintInfoLog(program, qfalse);
- ri.Error(ERR_DROP, "\nshaders failed to link");
- }
-}
-
-static void GLSL_ValidateProgram(GLhandleARB program)
-{
- GLint validated;
-
- qglValidateProgramARB(program);
-
- qglGetObjectParameterivARB(program, GL_OBJECT_VALIDATE_STATUS_ARB, &validated);
- if(!validated)
- {
- GLSL_PrintInfoLog(program, qfalse);
- ri.Error(ERR_DROP, "\nshaders failed to validate");
- }
-}
-
-static void GLSL_ShowProgramUniforms(GLhandleARB program)
-{
- int i, count, size;
- GLenum type;
- char uniformName[1000];
-
- // install the executables in the program object as part of current state.
- qglUseProgramObjectARB(program);
-
- // check for GL Errors
-
- // query the number of active uniforms
- qglGetObjectParameterivARB(program, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &count);
-
- // Loop over each of the active uniforms, and set their value
- for(i = 0; i < count; i++)
- {
- qglGetActiveUniformARB(program, i, sizeof(uniformName), NULL, &size, &type, uniformName);
-
- ri.Printf(PRINT_DEVELOPER, "active uniform: '%s'\n", uniformName);
- }
-
- qglUseProgramObjectARB(0);
-}
-
-static int GLSL_InitGPUShader2(shaderProgram_t * program, const char *name, int attribs, const char *vpCode, const char *fpCode, int numUniforms)
-{
- ri.Printf(PRINT_DEVELOPER, "------- GPU shader -------\n");
-
- if(strlen(name) >= MAX_QPATH)
- {
- ri.Error(ERR_DROP, "GLSL_InitGPUShader2: \"%s\" is too long", name);
- }
-
- Q_strncpyz(program->name, name, sizeof(program->name));
-
- program->program = qglCreateProgramObjectARB();
- program->attribs = attribs;
-
- if (!(GLSL_CompileGPUShader(program->program, &program->vertexShader, vpCode, strlen(vpCode), GL_VERTEX_SHADER_ARB)))
- {
- ri.Printf(PRINT_ALL, "GLSL_InitGPUShader2: Unable to load \"%s\" as GL_VERTEX_SHADER_ARB\n", name);
- qglDeleteObjectARB(program->program);
- return 0;
- }
-
- if(fpCode)
- {
- if(!(GLSL_CompileGPUShader(program->program, &program->fragmentShader, fpCode, strlen(fpCode), GL_FRAGMENT_SHADER_ARB)))
- {
- ri.Printf(PRINT_ALL, "GLSL_InitGPUShader2: Unable to load \"%s\" as GL_FRAGMENT_SHADER_ARB\n", name);
- qglDeleteObjectARB(program->program);
- return 0;
- }
- }
-
- if(attribs & ATTR_POSITION)
- qglBindAttribLocationARB(program->program, ATTR_INDEX_POSITION, "attr_Position");
-
- if(attribs & ATTR_TEXCOORD)
- qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD0, "attr_TexCoord0");
-
- if(attribs & ATTR_LIGHTCOORD)
- qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD1, "attr_TexCoord1");
-
-// if(attribs & ATTR_TEXCOORD2)
-// qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD2, "attr_TexCoord2");
-
-// if(attribs & ATTR_TEXCOORD3)
-// qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD3, "attr_TexCoord3");
-
-#ifdef USE_VERT_TANGENT_SPACE
- if(attribs & ATTR_TANGENT)
- qglBindAttribLocationARB(program->program, ATTR_INDEX_TANGENT, "attr_Tangent");
-
- if(attribs & ATTR_BITANGENT)
- qglBindAttribLocationARB(program->program, ATTR_INDEX_BITANGENT, "attr_Bitangent");
-#endif
-
- if(attribs & ATTR_NORMAL)
- qglBindAttribLocationARB(program->program, ATTR_INDEX_NORMAL, "attr_Normal");
-
- if(attribs & ATTR_COLOR)
- qglBindAttribLocationARB(program->program, ATTR_INDEX_COLOR, "attr_Color");
-
- if(attribs & ATTR_PAINTCOLOR)
- qglBindAttribLocationARB(program->program, ATTR_INDEX_PAINTCOLOR, "attr_PaintColor");
-
- if(attribs & ATTR_LIGHTDIRECTION)
- qglBindAttribLocationARB(program->program, ATTR_INDEX_LIGHTDIRECTION, "attr_LightDirection");
-
- if(attribs & ATTR_POSITION2)
- qglBindAttribLocationARB(program->program, ATTR_INDEX_POSITION2, "attr_Position2");
-
- if(attribs & ATTR_NORMAL2)
- qglBindAttribLocationARB(program->program, ATTR_INDEX_NORMAL2, "attr_Normal2");
-
-#ifdef USE_VERT_TANGENT_SPACE
- if(attribs & ATTR_TANGENT2)
- qglBindAttribLocationARB(program->program, ATTR_INDEX_TANGENT2, "attr_Tangent2");
-
- if(attribs & ATTR_BITANGENT2)
- qglBindAttribLocationARB(program->program, ATTR_INDEX_BITANGENT2, "attr_Bitangent2");
-#endif
-
- GLSL_LinkProgram(program->program);
-
- program->numUniforms = numUniforms;
-
- {
- int i, size;
-
- size = sizeof(*program->uniforms) * numUniforms;
- program->uniforms = ri.Malloc(size);
- for (i = 0; i < numUniforms; i++)
- {
- program->uniforms[i] = -1;
- }
-
- size = sizeof(*program->uniformTypes) * numUniforms;
- program->uniformTypes = ri.Malloc(size);
- memset(program->uniformTypes, 0, size);
-
- size = sizeof(*program->uniformBufferOffsets) * numUniforms;
- program->uniformBufferOffsets = ri.Malloc(size);
- memset(program->uniformBufferOffsets, 0, size);
- }
-
- return 1;
-}
-
-static int GLSL_InitGPUShader(shaderProgram_t * program, const char *name,
- int attribs, qboolean fragmentShader, const GLcharARB *extra, qboolean addHeader,
- const char *fallback_vp, const char *fallback_fp, int numUniforms)
-{
- char vpCode[32000];
- char fpCode[32000];
- char *postHeader;
- int size;
- int result;
-
- size = sizeof(vpCode);
- if (addHeader)
- {
- GLSL_GetShaderHeader(GL_VERTEX_SHADER_ARB, extra, vpCode, size);
- postHeader = &vpCode[strlen(vpCode)];
- size -= strlen(vpCode);
- }
- else
- {
- postHeader = &vpCode[0];
- }
-
- if (!GLSL_LoadGPUShaderText(name, fallback_vp, GL_VERTEX_SHADER_ARB, postHeader, size))
- {
- return 0;
- }
-
- if (fragmentShader)
- {
- size = sizeof(fpCode);
- if (addHeader)
- {
- GLSL_GetShaderHeader(GL_FRAGMENT_SHADER_ARB, extra, fpCode, size);
- postHeader = &fpCode[strlen(fpCode)];
- size -= strlen(fpCode);
- }
- else
- {
- postHeader = &fpCode[0];
- }
-
- if (!GLSL_LoadGPUShaderText(name, fallback_fp, GL_FRAGMENT_SHADER_ARB, postHeader, size))
- {
- return 0;
- }
- }
-
- result = GLSL_InitGPUShader2(program, name, attribs, vpCode, fragmentShader ? fpCode : NULL, numUniforms);
-
- return result;
-}
-
-// intentionally deceiving the user here, not actually setting the names but getting their indexes.
-void GLSL_AddUniform(shaderProgram_t *program, int uniformNum, const char *name, int type)
-{
- GLint *uniforms = program->uniforms;
-
- uniforms[uniformNum] = qglGetUniformLocationARB(program->program, name);
- program->uniformTypes[uniformNum] = type;
-}
-
-void GLSL_EndUniforms(shaderProgram_t *program)
-{
- if (program->numUniforms)
- {
- int i, size;
-
- size = 0;
- for (i = 0; i < program->numUniforms; i++)
- {
- if (program->uniforms[i] != -1)
- {
- program->uniformBufferOffsets[i] = size;
-
- switch(program->uniformTypes[i])
- {
- case GLSL_INT:
- size += sizeof(GLint);
- break;
- case GLSL_FLOAT:
- size += sizeof(GLfloat);
- break;
- case GLSL_FLOAT5:
- size += sizeof(vec_t) * 5;
- break;
- case GLSL_VEC2:
- size += sizeof(vec_t) * 2;
- break;
- case GLSL_VEC3:
- size += sizeof(vec_t) * 3;
- break;
- case GLSL_VEC4:
- size += sizeof(vec_t) * 4;
- break;
- case GLSL_MAT16:
- size += sizeof(vec_t) * 16;
- break;
- default:
- break;
- }
- }
- }
-
- program->uniformBuffer = ri.Malloc(size);
-
- }
-}
-
-void GLSL_FinishGPUShader(shaderProgram_t *program)
-{
- GLSL_ValidateProgram(program->program);
- GLSL_ShowProgramUniforms(program->program);
- GL_CheckErrors();
-}
-
-void GLSL_SetUniformInt(shaderProgram_t *program, int uniformNum, GLint value)
-{
- GLint *uniforms = program->uniforms;
- GLint *compare = (GLint *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
-
- if (uniforms[uniformNum] == -1)
- return;
-
- if (program->uniformTypes[uniformNum] != GLSL_INT)
- {
- ri.Printf( PRINT_WARNING, "GLSL_SetUniformInt: wrong type for uniform %i in program %s\n", uniformNum, program->name);
- return;
- }
-
- if (value == *compare)
- {
- return;
- }
-
- *compare = value;
-
- qglUniform1iARB(uniforms[uniformNum], value);
-}
-
-void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat value)
-{
- GLint *uniforms = program->uniforms;
- GLfloat *compare = (GLfloat *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
-
- if (uniforms[uniformNum] == -1)
- return;
-
- if (program->uniformTypes[uniformNum] != GLSL_FLOAT)
- {
- ri.Printf( PRINT_WARNING, "GLSL_SetUniformFloat: wrong type for uniform %i in program %s\n", uniformNum, program->name);
- return;
- }
-
- if (value == *compare)
- {
- return;
- }
-
- *compare = value;
-
- qglUniform1fARB(uniforms[uniformNum], value);
-}
-
-void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const vec2_t v)
-{
- GLint *uniforms = program->uniforms;
- vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
-
- if (uniforms[uniformNum] == -1)
- return;
-
- if (program->uniformTypes[uniformNum] != GLSL_VEC2)
- {
- ri.Printf( PRINT_WARNING, "GLSL_SetUniformVec2: wrong type for uniform %i in program %s\n", uniformNum, program->name);
- return;
- }
-
- if (v[0] == compare[0] && v[1] == compare[1])
- {
- return;
- }
-
- compare[0] = v[0];
- compare[1] = v[1];
-
- qglUniform2fARB(uniforms[uniformNum], v[0], v[1]);
-}
-
-void GLSL_SetUniformVec3(shaderProgram_t *program, int uniformNum, const vec3_t v)
-{
- GLint *uniforms = program->uniforms;
- vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
-
- if (uniforms[uniformNum] == -1)
- return;
-
- if (program->uniformTypes[uniformNum] != GLSL_VEC3)
- {
- ri.Printf( PRINT_WARNING, "GLSL_SetUniformVec3: wrong type for uniform %i in program %s\n", uniformNum, program->name);
- return;
- }
-
- if (VectorCompare(v, compare))
- {
- return;
- }
-
- VectorCopy(v, compare);
-
- qglUniform3fARB(uniforms[uniformNum], v[0], v[1], v[2]);
-}
-
-void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const vec4_t v)
-{
- GLint *uniforms = program->uniforms;
- vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
-
- if (uniforms[uniformNum] == -1)
- return;
-
- if (program->uniformTypes[uniformNum] != GLSL_VEC4)
- {
- ri.Printf( PRINT_WARNING, "GLSL_SetUniformVec4: wrong type for uniform %i in program %s\n", uniformNum, program->name);
- return;
- }
-
- if (VectorCompare4(v, compare))
- {
- return;
- }
-
- VectorCopy4(v, compare);
-
- qglUniform4fARB(uniforms[uniformNum], v[0], v[1], v[2], v[3]);
-}
-
-void GLSL_SetUniformFloat5(shaderProgram_t *program, int uniformNum, const vec5_t v)
-{
- GLint *uniforms = program->uniforms;
- vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
-
- if (uniforms[uniformNum] == -1)
- return;
-
- if (program->uniformTypes[uniformNum] != GLSL_FLOAT5)
- {
- ri.Printf( PRINT_WARNING, "GLSL_SetUniformFloat5: wrong type for uniform %i in program %s\n", uniformNum, program->name);
- return;
- }
-
- if (VectorCompare5(v, compare))
- {
- return;
- }
-
- VectorCopy5(v, compare);
-
- qglUniform1fvARB(uniforms[uniformNum], 5, v);
-}
-
-void GLSL_SetUniformMatrix16(shaderProgram_t *program, int uniformNum, const matrix_t matrix)
-{
- GLint *uniforms = program->uniforms;
- vec_t *compare = (float *)(program->uniformBuffer + program->uniformBufferOffsets[uniformNum]);
-
- if (uniforms[uniformNum] == -1)
- return;
-
- if (program->uniformTypes[uniformNum] != GLSL_MAT16)
- {
- ri.Printf( PRINT_WARNING, "GLSL_SetUniformMatrix16: wrong type for uniform %i in program %s\n", uniformNum, program->name);
- return;
- }
-
- if (Matrix16Compare(matrix, compare))
- {
- return;
- }
-
- Matrix16Copy(matrix, compare);
-
- qglUniformMatrix4fvARB(uniforms[uniformNum], 1, GL_FALSE, matrix);
-}
-
-void GLSL_DeleteGPUShader(shaderProgram_t *program)
-{
- if(program->program)
- {
- if (program->vertexShader)
- {
- qglDetachObjectARB(program->program, program->vertexShader);
- qglDeleteObjectARB(program->vertexShader);
- }
-
- if (program->fragmentShader)
- {
- qglDetachObjectARB(program->program, program->fragmentShader);
- qglDeleteObjectARB(program->fragmentShader);
- }
-
- qglDeleteObjectARB(program->program);
-
- if (program->uniforms)
- {
- ri.Free(program->uniforms);
- }
-
- if (program->uniformTypes)
- {
- ri.Free(program->uniformTypes);
- }
-
- if (program->uniformBuffer)
- {
- ri.Free(program->uniformBuffer);
- }
-
- if (program->uniformBufferOffsets)
- {
- ri.Free(program->uniformBufferOffsets);
- }
-
- Com_Memset(program, 0, sizeof(*program));
- }
-}
-
-void GLSL_InitGPUShaders(void)
-{
- int startTime, endTime;
- int i;
- char extradefines[1024];
- int attribs;
- int numGenShaders = 0, numLightShaders = 0, numEtcShaders = 0;
-
- ri.Printf(PRINT_ALL, "------- GLSL_InitGPUShaders -------\n");
-
- R_IssuePendingRenderCommands();
-
- startTime = ri.Milliseconds();
-
- for (i = 0; i < GENERICDEF_COUNT; i++)
- {
- attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_NORMAL | ATTR_COLOR;
- extradefines[0] = '\0';
-
- if (i & GENERICDEF_USE_DEFORM_VERTEXES)
- Q_strcat(extradefines, 1024, "#define USE_DEFORM_VERTEXES\n");
-
- if (i & GENERICDEF_USE_TCGEN_AND_TCMOD)
- {
- Q_strcat(extradefines, 1024, "#define USE_TCGEN\n");
- Q_strcat(extradefines, 1024, "#define USE_TCMOD\n");
- }
-
- if (i & GENERICDEF_USE_VERTEX_ANIMATION)
- {
- Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n");
- attribs |= ATTR_POSITION2 | ATTR_NORMAL2;
- }
-
- if (i & GENERICDEF_USE_FOG)
- Q_strcat(extradefines, 1024, "#define USE_FOG\n");
-
- if (i & GENERICDEF_USE_RGBAGEN)
- Q_strcat(extradefines, 1024, "#define USE_RGBAGEN\n");
-
- if (i & GENERICDEF_USE_LIGHTMAP)
- Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n");
-
- if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel))
- Q_strcat(extradefines, 1024, "#define RGBE_LIGHTMAP\n");
-
- if (!GLSL_InitGPUShader(&tr.genericShader[i], "generic", attribs, qtrue, extradefines, qtrue, fallbackShader_generic_vp, fallbackShader_generic_fp, GENERIC_UNIFORM_COUNT))
- {
- ri.Error(ERR_FATAL, "Could not load generic shader!");
- }
-
- // There's actually no need to filter these out, since they'll
- // redirect to -1 if nonexistent, but it's more understandable this way.
-
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
-
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_BASECOLOR, "u_BaseColor", GLSL_VEC4);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_VERTCOLOR, "u_VertColor", GLSL_VEC4);
-
- if (i & GENERICDEF_USE_RGBAGEN)
- {
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_COLORGEN, "u_ColorGen", GLSL_INT);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_ALPHAGEN, "u_AlphaGen", GLSL_INT);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_AMBIENTLIGHT, "u_AmbientLight", GLSL_VEC3);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIRECTEDLIGHT, "u_DirectedLight", GLSL_VEC3);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_LIGHTORIGIN, "u_LightOrigin", GLSL_VEC4);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_PORTALRANGE, "u_PortalRange", GLSL_FLOAT);
- }
-
- if (i & GENERICDEF_USE_TCGEN_AND_TCMOD)
- {
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TCGEN0, "u_TCGen0", GLSL_INT);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TCGEN0VECTOR0, "u_TCGen0Vector0", GLSL_VEC3);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TCGEN0VECTOR1, "u_TCGen0Vector1", GLSL_VEC3);
- }
-
- if (i & GENERICDEF_USE_FOG)
- {
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGCOLORMASK, "u_FogColorMask", GLSL_VEC4);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGDISTANCE, "u_FogDistance", GLSL_VEC4);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGDEPTH, "u_FogDepth", GLSL_VEC4);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_FOGEYET, "u_FogEyeT", GLSL_FLOAT);
- }
-
- if (i & GENERICDEF_USE_DEFORM_VERTEXES)
- {
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DEFORMGEN, "u_DeformGen", GLSL_INT);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DEFORMPARAMS, "u_DeformParams", GLSL_FLOAT5);
- }
-
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TIME, "u_Time", GLSL_FLOAT);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_VIEWORIGIN, "u_ViewOrigin", GLSL_VEC3);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIFFUSETEXMATRIX, "u_DiffuseTexMatrix", GLSL_VEC4);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIFFUSETEXOFFTURB,"u_DiffuseTexOffTurb",GLSL_VEC4);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_TEXTURE1ENV, "u_Texture1Env", GLSL_INT);
-
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_DIFFUSEMAP, "u_DiffuseMap", GLSL_INT);
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_LIGHTMAP, "u_LightMap", GLSL_INT);
-
-
- if (i & GENERICDEF_USE_VERTEX_ANIMATION)
- {
- GLSL_AddUniform(&tr.genericShader[i], GENERIC_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT);
- }
-
- GLSL_EndUniforms(&tr.genericShader[i]);
-
- qglUseProgramObjectARB(tr.genericShader[i].program);
- GLSL_SetUniformInt(&tr.genericShader[i], GENERIC_UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP);
- GLSL_SetUniformInt(&tr.genericShader[i], GENERIC_UNIFORM_LIGHTMAP, TB_LIGHTMAP);
- qglUseProgramObjectARB(0);
-
- GLSL_FinishGPUShader(&tr.genericShader[i]);
-
- numGenShaders++;
- }
-
-
- attribs = ATTR_POSITION | ATTR_TEXCOORD;
-
- if (!GLSL_InitGPUShader(&tr.textureColorShader, "texturecolor", attribs, qtrue, NULL, qfalse, fallbackShader_texturecolor_vp, fallbackShader_texturecolor_fp, TEXTURECOLOR_UNIFORM_COUNT))
- {
- ri.Error(ERR_FATAL, "Could not load texturecolor shader!");
- }
-
- GLSL_AddUniform(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
- GLSL_AddUniform(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_COLOR, "u_Color", GLSL_VEC4);
- GLSL_AddUniform(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_DiffuseMap", GLSL_INT);
-
- GLSL_EndUniforms(&tr.textureColorShader);
-
- qglUseProgramObjectARB(tr.textureColorShader.program);
- GLSL_SetUniformInt(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
- qglUseProgramObjectARB(0);
-
- GLSL_FinishGPUShader(&tr.textureColorShader);
-
- numEtcShaders++;
-
- for (i = 0; i < FOGDEF_COUNT; i++)
- {
- attribs = ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TEXCOORD;
- extradefines[0] = '\0';
-
- if (i & FOGDEF_USE_DEFORM_VERTEXES)
- Q_strcat(extradefines, 1024, "#define USE_DEFORM_VERTEXES\n");
-
- if (i & FOGDEF_USE_VERTEX_ANIMATION)
- Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n");
-
- if (!GLSL_InitGPUShader(&tr.fogShader[i], "fogpass", attribs, qtrue, extradefines, qtrue, fallbackShader_fogpass_vp, fallbackShader_fogpass_fp, FOGPASS_UNIFORM_COUNT))
- {
- ri.Error(ERR_FATAL, "Could not load fogpass shader!");
- }
-
- GLSL_AddUniform(&tr.fogShader[i], FOGPASS_UNIFORM_FOGDISTANCE, "u_FogDistance", GLSL_VEC4);
- GLSL_AddUniform(&tr.fogShader[i], FOGPASS_UNIFORM_FOGDEPTH, "u_FogDepth", GLSL_VEC4);
- GLSL_AddUniform(&tr.fogShader[i], FOGPASS_UNIFORM_FOGEYET, "u_FogEyeT", GLSL_FLOAT);
- GLSL_AddUniform(&tr.fogShader[i], FOGPASS_UNIFORM_DEFORMGEN, "u_DeformGen", GLSL_INT);
- GLSL_AddUniform(&tr.fogShader[i], FOGPASS_UNIFORM_DEFORMPARAMS, "u_DeformParams", GLSL_FLOAT5);
- GLSL_AddUniform(&tr.fogShader[i], FOGPASS_UNIFORM_TIME, "u_Time", GLSL_FLOAT);
- GLSL_AddUniform(&tr.fogShader[i], FOGPASS_UNIFORM_COLOR, "u_Color", GLSL_VEC4);
- GLSL_AddUniform(&tr.fogShader[i], FOGPASS_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
- GLSL_AddUniform(&tr.fogShader[i], FOGPASS_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT);
-
- GLSL_EndUniforms(&tr.fogShader[i]);
- GLSL_FinishGPUShader(&tr.fogShader[i]);
-
- numEtcShaders++;
- }
-
-
- for (i = 0; i < DLIGHTDEF_COUNT; i++)
- {
- attribs = ATTR_POSITION | ATTR_NORMAL | ATTR_TEXCOORD;
- extradefines[0] = '\0';
-
- if (i & DLIGHTDEF_USE_DEFORM_VERTEXES)
- {
- Q_strcat(extradefines, 1024, "#define USE_DEFORM_VERTEXES\n");
- }
-
- if (!GLSL_InitGPUShader(&tr.dlightShader[i], "dlight", attribs, qtrue, extradefines, qtrue, fallbackShader_dlight_vp, fallbackShader_dlight_fp, DLIGHT_UNIFORM_COUNT))
- {
- ri.Error(ERR_FATAL, "Could not load dlight shader!");
- }
-
- GLSL_AddUniform(&tr.dlightShader[i], DLIGHT_UNIFORM_DLIGHTINFO, "u_DlightInfo", GLSL_VEC4);
- GLSL_AddUniform(&tr.dlightShader[i], DLIGHT_UNIFORM_DEFORMGEN, "u_DeformGen", GLSL_INT);
- GLSL_AddUniform(&tr.dlightShader[i], DLIGHT_UNIFORM_DEFORMPARAMS, "u_DeformParams", GLSL_FLOAT5);
- GLSL_AddUniform(&tr.dlightShader[i], DLIGHT_UNIFORM_TIME, "u_Time", GLSL_FLOAT);
- GLSL_AddUniform(&tr.dlightShader[i], DLIGHT_UNIFORM_COLOR, "u_Color", GLSL_VEC4);
- GLSL_AddUniform(&tr.dlightShader[i], DLIGHT_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
-
- GLSL_EndUniforms(&tr.dlightShader[i]);
-
- qglUseProgramObjectARB(tr.dlightShader[i].program);
- GLSL_SetUniformInt(&tr.dlightShader[i], DLIGHT_UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP);
- qglUseProgramObjectARB(0);
-
- GLSL_FinishGPUShader(&tr.dlightShader[i]);
-
- numEtcShaders++;
- }
-
-
- for (i = 0; i < LIGHTDEF_COUNT; i++)
- {
- // skip impossible combos
- if ((i & LIGHTDEF_USE_NORMALMAP) && !r_normalMapping->integer)
- continue;
-
- if ((i & LIGHTDEF_USE_PARALLAXMAP) && !r_parallaxMapping->integer)
- continue;
-
- if ((i & LIGHTDEF_USE_SPECULARMAP) && !r_specularMapping->integer)
- continue;
-
- if ((i & LIGHTDEF_USE_DELUXEMAP) && !r_deluxeMapping->integer)
- continue;
-
- if (!((i & LIGHTDEF_LIGHTTYPE_MASK) == LIGHTDEF_USE_LIGHTMAP) && (i & LIGHTDEF_USE_DELUXEMAP))
- continue;
-
- if (!(i & LIGHTDEF_USE_NORMALMAP) && (i & LIGHTDEF_USE_PARALLAXMAP))
- continue;
-
- if (!((i & LIGHTDEF_LIGHTTYPE_MASK) == LIGHTDEF_USE_LIGHT_VECTOR))
- {
- if (i & LIGHTDEF_USE_SHADOWMAP)
- continue;
- }
-
- attribs = ATTR_POSITION | ATTR_TEXCOORD | ATTR_COLOR | ATTR_NORMAL;
-
- extradefines[0] = '\0';
-
- if (r_normalAmbient->value > 0.003f)
- Q_strcat(extradefines, 1024, va("#define r_normalAmbient %f\n", r_normalAmbient->value));
-
- if (r_dlightMode->integer >= 2)
- Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n");
-
- if (1)
- {
- Q_strcat(extradefines, 1024, "#define SWIZZLE_NORMALMAP\n");
- }
-
- if (r_hdr->integer && !(glRefConfig.textureFloat && glRefConfig.halfFloatPixel))
- Q_strcat(extradefines, 1024, "#define RGBE_LIGHTMAP\n");
-
- if (i & LIGHTDEF_LIGHTTYPE_MASK)
- {
- Q_strcat(extradefines, 1024, "#define USE_LIGHT\n");
-
- if (r_normalMapping->integer == 0 && r_specularMapping->integer == 0)
- Q_strcat(extradefines, 1024, "#define USE_FAST_LIGHT\n");
-
- switch (i & LIGHTDEF_LIGHTTYPE_MASK)
- {
- case LIGHTDEF_USE_LIGHTMAP:
- Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n");
- attribs |= ATTR_LIGHTCOORD | ATTR_LIGHTDIRECTION;
- break;
- case LIGHTDEF_USE_LIGHT_VECTOR:
- Q_strcat(extradefines, 1024, "#define USE_LIGHT_VECTOR\n");
- break;
- case LIGHTDEF_USE_LIGHT_VERTEX:
- Q_strcat(extradefines, 1024, "#define USE_LIGHT_VERTEX\n");
- attribs |= ATTR_LIGHTDIRECTION;
- break;
- default:
- break;
- }
- }
-
- if ((i & LIGHTDEF_USE_NORMALMAP) && r_normalMapping->integer)
- {
- Q_strcat(extradefines, 1024, "#define USE_NORMALMAP\n");
-
- if (r_normalMapping->integer == 2)
- Q_strcat(extradefines, 1024, "#define USE_OREN_NAYAR\n");
-
- if (r_normalMapping->integer == 3)
- Q_strcat(extradefines, 1024, "#define USE_TRIACE_OREN_NAYAR\n");
-
-#ifdef USE_VERT_TANGENT_SPACE
- Q_strcat(extradefines, 1024, "#define USE_VERT_TANGENT_SPACE\n");
- attribs |= ATTR_TANGENT | ATTR_BITANGENT;
-#endif
- }
-
- if ((i & LIGHTDEF_USE_SPECULARMAP) && r_specularMapping->integer)
- {
- Q_strcat(extradefines, 1024, "#define USE_SPECULARMAP\n");
-
- switch (r_specularMapping->integer)
- {
- case 1:
- default:
- Q_strcat(extradefines, 1024, "#define USE_TRIACE\n");
- break;
-
- case 2:
- Q_strcat(extradefines, 1024, "#define USE_BLINN\n");
- break;
-
- case 3:
- Q_strcat(extradefines, 1024, "#define USE_COOK_TORRANCE\n");
- break;
-
- case 4:
- Q_strcat(extradefines, 1024, "#define USE_TORRANCE_SPARROW\n");
- break;
- }
- }
-
- if ((i & LIGHTDEF_USE_DELUXEMAP) && r_deluxeMapping->integer)
- Q_strcat(extradefines, 1024, "#define USE_DELUXEMAP\n");
-
- if ((i & LIGHTDEF_USE_PARALLAXMAP) && !(i & LIGHTDEF_ENTITY) && r_parallaxMapping->integer)
- Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP\n");
-
- if (i & LIGHTDEF_USE_SHADOWMAP)
- Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n");
-
- if (i & LIGHTDEF_USE_TCGEN_AND_TCMOD)
- {
- Q_strcat(extradefines, 1024, "#define USE_TCGEN\n");
- Q_strcat(extradefines, 1024, "#define USE_TCMOD\n");
- }
-
- if (i & LIGHTDEF_ENTITY)
- {
- Q_strcat(extradefines, 1024, "#define USE_VERTEX_ANIMATION\n#define USE_MODELMATRIX\n");
- attribs |= ATTR_POSITION2 | ATTR_NORMAL2;
-
-#ifdef USE_VERT_TANGENT_SPACE
- if (i & LIGHTDEF_USE_NORMALMAP && r_normalMapping->integer)
- {
- attribs |= ATTR_TANGENT2 | ATTR_BITANGENT2;
- }
-#endif
- }
-
- if (!GLSL_InitGPUShader(&tr.lightallShader[i], "lightall", attribs, qtrue, extradefines, qtrue, fallbackShader_lightall_vp, fallbackShader_lightall_fp, GENERIC_UNIFORM_COUNT))
- {
- ri.Error(ERR_FATAL, "Could not load lightall shader!");
- }
-
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_MODELMATRIX, "u_ModelMatrix", GLSL_MAT16);
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DIFFUSETEXMATRIX, "u_DiffuseTexMatrix", GLSL_VEC4);
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DIFFUSETEXOFFTURB, "u_DiffuseTexOffTurb", GLSL_VEC4);
- //GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_NORMALTEXMATRIX, "u_NormalTexMatrix", GLSL_MAT16);
- //GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SPECULARTEXMATRIX, "u_SpecularTexMatrix", GLSL_MAT16);
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VIEWORIGIN, "u_ViewOrigin", GLSL_VEC3);
-
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_TCGEN0, "u_TCGen0", GLSL_INT);
-
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DIFFUSEMAP, "u_DiffuseMap", GLSL_INT);
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_LIGHTMAP, "u_LightMap", GLSL_INT);
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_NORMALMAP, "u_NormalMap", GLSL_INT);
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DELUXEMAP, "u_DeluxeMap", GLSL_INT);
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SPECULARMAP, "u_SpecularMap", GLSL_INT);
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP, "u_ShadowMap", GLSL_INT);
-
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_AMBIENTLIGHT, "u_AmbientLight", GLSL_VEC3);
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_DIRECTEDLIGHT, "u_DirectedLight", GLSL_VEC3);
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_LIGHTORIGIN, "u_LightOrigin", GLSL_VEC4);
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_LIGHTRADIUS, "u_LightRadius", GLSL_FLOAT);
-
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_MATERIALINFO, "u_MaterialInfo", GLSL_VEC2);
-
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_BASECOLOR, "u_BaseColor", GLSL_VEC4);
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VERTCOLOR, "u_VertColor", GLSL_VEC4);
- GLSL_AddUniform(&tr.lightallShader[i], GENERIC_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT);
-
- GLSL_EndUniforms(&tr.lightallShader[i]);
-
- qglUseProgramObjectARB(tr.lightallShader[i].program);
- GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP);
- GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_LIGHTMAP, TB_LIGHTMAP);
- GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_NORMALMAP, TB_NORMALMAP);
- GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_DELUXEMAP, TB_DELUXEMAP);
- GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_SPECULARMAP, TB_SPECULARMAP);
- GLSL_SetUniformInt(&tr.lightallShader[i], GENERIC_UNIFORM_SHADOWMAP, TB_SHADOWMAP);
- qglUseProgramObjectARB(0);
-
- GLSL_FinishGPUShader(&tr.lightallShader[i]);
-
- numLightShaders++;
- }
-
- attribs = ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TEXCOORD;
-
- extradefines[0] = '\0';
-
- if (!GLSL_InitGPUShader(&tr.shadowmapShader, "shadowfill", attribs, qtrue, extradefines, qtrue, fallbackShader_shadowfill_vp, fallbackShader_shadowfill_fp, GENERIC_UNIFORM_COUNT))
- {
- ri.Error(ERR_FATAL, "Could not load shadowfill shader!");
- }
-
- GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_DEFORMGEN, "u_DeformGen", GLSL_INT);
- GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_DEFORMPARAMS, "u_DeformParams", GLSL_FLOAT5);
- GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_TIME, "u_Time", GLSL_FLOAT);
- GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
- GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_MODELMATRIX, "u_ModelMatrix", GLSL_MAT16);
- GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_VERTEXLERP, "u_VertexLerp", GLSL_FLOAT);
-
- GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_LIGHTORIGIN, "u_LightOrigin", GLSL_VEC4);
- GLSL_AddUniform(&tr.shadowmapShader, GENERIC_UNIFORM_LIGHTRADIUS, "u_LightRadius", GLSL_FLOAT);
-
- GLSL_EndUniforms(&tr.shadowmapShader);
- GLSL_FinishGPUShader(&tr.shadowmapShader);
-
- numEtcShaders++;
-
- attribs = ATTR_POSITION | ATTR_NORMAL;
- extradefines[0] = '\0';
-
- Q_strcat(extradefines, 1024, "#define USE_PCF\n#define USE_DISCARD\n");
-
- if (!GLSL_InitGPUShader(&tr.pshadowShader, "pshadow", attribs, qtrue, extradefines, qtrue, fallbackShader_pshadow_vp, fallbackShader_pshadow_fp, PSHADOW_UNIFORM_COUNT))
- {
- ri.Error(ERR_FATAL, "Could not load pshadow shader!");
- }
-
- GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
- GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTFORWARD, "u_LightForward", GLSL_VEC3);
- GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTUP, "u_LightUp", GLSL_VEC3);
- GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTRIGHT, "u_LightRight", GLSL_VEC3);
- GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTORIGIN, "u_LightOrigin", GLSL_VEC4);
- GLSL_AddUniform(&tr.pshadowShader, PSHADOW_UNIFORM_LIGHTRADIUS, "u_LightRadius", GLSL_FLOAT);
-
- GLSL_EndUniforms(&tr.pshadowShader);
-
- qglUseProgramObjectARB(tr.pshadowShader.program);
- GLSL_SetUniformInt(&tr.pshadowShader, PSHADOW_UNIFORM_SHADOWMAP, TB_DIFFUSEMAP);
- qglUseProgramObjectARB(0);
-
- GLSL_FinishGPUShader(&tr.pshadowShader);
-
- numEtcShaders++;
-
-
- attribs = ATTR_POSITION | ATTR_TEXCOORD;
- extradefines[0] = '\0';
-
- if (!GLSL_InitGPUShader(&tr.down4xShader, "down4x", attribs, qtrue, extradefines, qtrue, fallbackShader_down4x_vp, fallbackShader_down4x_fp, TEXTURECOLOR_UNIFORM_COUNT))
- {
- ri.Error(ERR_FATAL, "Could not load down4x shader!");
- }
-
- GLSL_AddUniform(&tr.down4xShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
- GLSL_AddUniform(&tr.down4xShader, TEXTURECOLOR_UNIFORM_INVTEXRES, "u_InvTexRes", GLSL_VEC2);
-
- GLSL_AddUniform(&tr.down4xShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_TextureMap", GLSL_INT);
-
- GLSL_EndUniforms(&tr.down4xShader);
-
- qglUseProgramObjectARB(tr.down4xShader.program);
- GLSL_SetUniformInt(&tr.down4xShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
- qglUseProgramObjectARB(0);
-
- GLSL_FinishGPUShader(&tr.down4xShader);
-
- numEtcShaders++;
-
-
- attribs = ATTR_POSITION | ATTR_TEXCOORD;
- extradefines[0] = '\0';
-
- if (!GLSL_InitGPUShader(&tr.bokehShader, "bokeh", attribs, qtrue, extradefines, qtrue, fallbackShader_bokeh_vp, fallbackShader_bokeh_fp, TEXTURECOLOR_UNIFORM_COUNT))
- {
- ri.Error(ERR_FATAL, "Could not load bokeh shader!");
- }
-
- GLSL_AddUniform(&tr.bokehShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
- GLSL_AddUniform(&tr.bokehShader, TEXTURECOLOR_UNIFORM_INVTEXRES, "u_InvTexRes", GLSL_VEC2);
- GLSL_AddUniform(&tr.bokehShader, TEXTURECOLOR_UNIFORM_COLOR, "u_Color", GLSL_VEC4);
-
- GLSL_AddUniform(&tr.bokehShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_TextureMap", GLSL_INT);
-
- GLSL_EndUniforms(&tr.bokehShader);
-
- qglUseProgramObjectARB(tr.bokehShader.program);
- GLSL_SetUniformInt(&tr.bokehShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
- qglUseProgramObjectARB(0);
-
- GLSL_FinishGPUShader(&tr.bokehShader);
-
- numEtcShaders++;
-
-
- attribs = ATTR_POSITION | ATTR_TEXCOORD;
- extradefines[0] = '\0';
-
- if (!GLSL_InitGPUShader(&tr.tonemapShader, "tonemap", attribs, qtrue, extradefines, qtrue, fallbackShader_tonemap_vp, fallbackShader_tonemap_fp, TEXTURECOLOR_UNIFORM_COUNT))
- {
- ri.Error(ERR_FATAL, "Could not load tonemap shader!");
- }
-
- GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
- GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_INVTEXRES, "u_InvTexRes", GLSL_VEC2);
- GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_COLOR, "u_Color", GLSL_VEC4);
- GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_AUTOEXPOSUREMINMAX, "u_AutoExposureMinMax", GLSL_VEC2);
- GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_TONEMINAVGMAXLINEAR, "u_ToneMinAvgMaxLinear", GLSL_VEC3);
- GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_TextureMap", GLSL_INT);
- GLSL_AddUniform(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_LEVELSMAP, "u_LevelsMap", GLSL_INT);
-
- GLSL_EndUniforms(&tr.tonemapShader);
-
- qglUseProgramObjectARB(tr.tonemapShader.program);
- GLSL_SetUniformInt(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_COLORMAP);
- GLSL_SetUniformInt(&tr.tonemapShader, TEXTURECOLOR_UNIFORM_LEVELSMAP, TB_LEVELSMAP);
- qglUseProgramObjectARB(0);
-
- GLSL_FinishGPUShader(&tr.tonemapShader);
-
- numEtcShaders++;
-
-
- for (i = 0; i < 2; i++)
- {
- attribs = ATTR_POSITION | ATTR_TEXCOORD;
- extradefines[0] = '\0';
-
- if (!i)
- Q_strcat(extradefines, 1024, "#define FIRST_PASS\n");
-
- if (!GLSL_InitGPUShader(&tr.calclevels4xShader[i], "calclevels4x", attribs, qtrue, extradefines, qtrue, fallbackShader_calclevels4x_vp, fallbackShader_calclevels4x_fp, TEXTURECOLOR_UNIFORM_COUNT))
- {
- ri.Error(ERR_FATAL, "Could not load calclevels4x shader!");
- }
-
- GLSL_AddUniform(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, "u_ModelViewProjectionMatrix", GLSL_MAT16);
- GLSL_AddUniform(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_INVTEXRES, "u_InvTexRes", GLSL_VEC2);
- GLSL_AddUniform(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_COLOR, "u_Color", GLSL_VEC4);
-
- GLSL_AddUniform(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_TEXTUREMAP, "u_TextureMap", GLSL_INT);
-
- GLSL_EndUniforms(&tr.calclevels4xShader[i]);
-
- qglUseProgramObjectARB(tr.calclevels4xShader[i].program);
- GLSL_SetUniformInt(&tr.calclevels4xShader[i], TEXTURECOLOR_UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP);
- qglUseProgramObjectARB(0);
-
- GLSL_FinishGPUShader(&tr.calclevels4xShader[i]);
-
- numEtcShaders++;
- }
-
-
- attribs = ATTR_POSITION | ATTR_TEXCOORD;
- extradefines[0] = '\0';
-
- if (r_shadowFilter->integer >= 1)
- Q_strcat(extradefines, 1024, "#define USE_SHADOW_FILTER\n");
-
- if (r_shadowFilter->integer >= 2)
- Q_strcat(extradefines, 1024, "#define USE_SHADOW_FILTER2\n");
-
- Q_strcat(extradefines, 1024, "#define USE_SHADOW_CASCADE\n");
-
- Q_strcat(extradefines, 1024, va("#define r_shadowMapSize %d\n", r_shadowMapSize->integer));
- Q_strcat(extradefines, 1024, va("#define r_shadowCascadeZFar %f\n", r_shadowCascadeZFar->value));
-
-
- if (!GLSL_InitGPUShader(&tr.shadowmaskShader, "shadowmask", attribs, qtrue, extradefines, qtrue, fallbackShader_shadowmask_vp, fallbackShader_shadowmask_fp, SHADOWMASK_UNIFORM_COUNT))
- {
- ri.Error(ERR_FATAL, "Could not load shadowmask shader!");
- }
-
- GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP, "u_ShadowMvp", GLSL_MAT16);
- GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP2, "u_ShadowMvp2", GLSL_MAT16);
- GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMVP3, "u_ShadowMvp3", GLSL_MAT16);
- GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWORIGIN, "u_ViewOrigin", GLSL_VEC3);
- GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWINFO, "u_ViewInfo", GLSL_VEC4);
- GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWFORWARD,"u_ViewForward", GLSL_VEC3);
- GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWLEFT, "u_ViewLeft", GLSL_VEC3);
- GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_VIEWUP, "u_ViewUp", GLSL_VEC3);
-
- GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SCREENDEPTHMAP, "u_ScreenDepthMap", GLSL_INT);
- GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP, "u_ShadowMap", GLSL_INT);
- GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP2, "u_ShadowMap2", GLSL_INT);
- GLSL_AddUniform(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP3, "u_ShadowMap3", GLSL_INT);
-
- GLSL_EndUniforms(&tr.shadowmaskShader);
-
- qglUseProgramObjectARB(tr.shadowmaskShader.program);
- GLSL_SetUniformInt(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SCREENDEPTHMAP, TB_COLORMAP);
- GLSL_SetUniformInt(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP, TB_SHADOWMAP);
- GLSL_SetUniformInt(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP2, TB_SHADOWMAP2);
- GLSL_SetUniformInt(&tr.shadowmaskShader, SHADOWMASK_UNIFORM_SHADOWMAP3, TB_SHADOWMAP3);
- qglUseProgramObjectARB(0);
-
- GLSL_FinishGPUShader(&tr.shadowmaskShader);
-
- numEtcShaders++;
-
-
- attribs = ATTR_POSITION | ATTR_TEXCOORD;
- extradefines[0] = '\0';
-
- if (!GLSL_InitGPUShader(&tr.ssaoShader, "ssao", attribs, qtrue, extradefines, qtrue, fallbackShader_ssao_vp, fallbackShader_ssao_fp, SSAO_UNIFORM_COUNT))
- {
- ri.Error(ERR_FATAL, "Could not load ssao shader!");
- }
-
- GLSL_AddUniform(&tr.ssaoShader, SSAO_UNIFORM_VIEWINFO, "u_ViewInfo", GLSL_VEC4);
-
- GLSL_AddUniform(&tr.ssaoShader, SSAO_UNIFORM_SCREENDEPTHMAP, "u_ScreenDepthMap", GLSL_INT);
-
- GLSL_EndUniforms(&tr.ssaoShader);
-
- qglUseProgramObjectARB(tr.ssaoShader.program);
- GLSL_SetUniformInt(&tr.ssaoShader, SSAO_UNIFORM_SCREENDEPTHMAP, TB_COLORMAP);
- qglUseProgramObjectARB(0);
-
- GLSL_FinishGPUShader(&tr.ssaoShader);
-
- numEtcShaders++;
-
-
- for (i = 0; i < 2; i++)
- {
- attribs = ATTR_POSITION | ATTR_TEXCOORD;
- extradefines[0] = '\0';
-
- if (i & 1)
- Q_strcat(extradefines, 1024, "#define USE_VERTICAL_BLUR\n");
- else
- Q_strcat(extradefines, 1024, "#define USE_HORIZONTAL_BLUR\n");
-
-
- if (!GLSL_InitGPUShader(&tr.depthBlurShader[i], "depthBlur", attribs, qtrue, extradefines, qtrue, fallbackShader_depthblur_vp, fallbackShader_depthblur_fp, DEPTHBLUR_UNIFORM_COUNT))
- {
- ri.Error(ERR_FATAL, "Could not load depthBlur shader!");
- }
-
- GLSL_AddUniform(&tr.depthBlurShader[i], DEPTHBLUR_UNIFORM_VIEWINFO, "u_ViewInfo", GLSL_VEC4);
-
- GLSL_AddUniform(&tr.depthBlurShader[i], DEPTHBLUR_UNIFORM_SCREENIMAGEMAP, "u_ScreenImageMap", GLSL_INT);
- GLSL_AddUniform(&tr.depthBlurShader[i], DEPTHBLUR_UNIFORM_SCREENDEPTHMAP, "u_ScreenDepthMap", GLSL_INT);
-
- GLSL_EndUniforms(&tr.depthBlurShader[i]);
-
- qglUseProgramObjectARB(tr.depthBlurShader[i].program);
- GLSL_SetUniformInt(&tr.depthBlurShader[i], DEPTHBLUR_UNIFORM_SCREENIMAGEMAP, TB_COLORMAP);
- GLSL_SetUniformInt(&tr.depthBlurShader[i], DEPTHBLUR_UNIFORM_SCREENDEPTHMAP, TB_LIGHTMAP);
- qglUseProgramObjectARB(0);
-
- GLSL_FinishGPUShader(&tr.depthBlurShader[i]);
-
- numEtcShaders++;
- }
-
-
- endTime = ri.Milliseconds();
-
- ri.Printf(PRINT_ALL, "loaded %i GLSL shaders (%i gen %i light %i etc) in %5.2f seconds\n",
- numGenShaders + numLightShaders + numEtcShaders, numGenShaders, numLightShaders,
- numEtcShaders, (endTime - startTime) / 1000.0);
-}
-
-void GLSL_ShutdownGPUShaders(void)
-{
- int i;
-
- ri.Printf(PRINT_ALL, "------- GLSL_ShutdownGPUShaders -------\n");
-
- qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD0);
- qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD1);
- qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION);
- qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION2);
- qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL);
-#ifdef USE_VERT_TANGENT_SPACE
- qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT);
- qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT);
-#endif
- qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL2);
-#ifdef USE_VERT_TANGENT_SPACE
- qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT2);
- qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT2);
-#endif
- qglDisableVertexAttribArrayARB(ATTR_INDEX_COLOR);
- qglDisableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION);
- GLSL_BindNullProgram();
-
- for ( i = 0; i < GENERICDEF_COUNT; i++)
- GLSL_DeleteGPUShader(&tr.genericShader[i]);
-
- GLSL_DeleteGPUShader(&tr.textureColorShader);
-
- for ( i = 0; i < FOGDEF_COUNT; i++)
- GLSL_DeleteGPUShader(&tr.fogShader[i]);
-
- for ( i = 0; i < DLIGHTDEF_COUNT; i++)
- GLSL_DeleteGPUShader(&tr.dlightShader[i]);
-
- for ( i = 0; i < LIGHTDEF_COUNT; i++)
- GLSL_DeleteGPUShader(&tr.lightallShader[i]);
-
- GLSL_DeleteGPUShader(&tr.shadowmapShader);
- GLSL_DeleteGPUShader(&tr.pshadowShader);
- GLSL_DeleteGPUShader(&tr.down4xShader);
-
- for ( i = 0; i < 2; i++)
- GLSL_DeleteGPUShader(&tr.calclevels4xShader[i]);
-
- glState.currentProgram = 0;
- qglUseProgramObjectARB(0);
-}
-
-
-void GLSL_BindProgram(shaderProgram_t * program)
-{
- if(!program)
- {
- GLSL_BindNullProgram();
- return;
- }
-
- if(r_logFile->integer)
- {
- // don't just call LogComment, or we will get a call to va() every frame!
- GLimp_LogComment(va("--- GL_BindProgram( %s ) ---\n", program->name));
- }
-
- if(glState.currentProgram != program)
- {
- qglUseProgramObjectARB(program->program);
- glState.currentProgram = program;
- backEnd.pc.c_glslShaderBinds++;
- }
-}
-
-
-void GLSL_BindNullProgram(void)
-{
- if(r_logFile->integer)
- {
- GLimp_LogComment("--- GL_BindNullProgram ---\n");
- }
-
- if(glState.currentProgram)
- {
- qglUseProgramObjectARB(0);
- glState.currentProgram = NULL;
- }
-}
-
-
-void GLSL_VertexAttribsState(uint32_t stateBits)
-{
- uint32_t diff;
-
- GLSL_VertexAttribPointers(stateBits);
-
- diff = stateBits ^ glState.vertexAttribsState;
- if(!diff)
- {
- return;
- }
-
- if(diff & ATTR_POSITION)
- {
- if(stateBits & ATTR_POSITION)
- {
- GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_POSITION )\n");
- qglEnableVertexAttribArrayARB(ATTR_INDEX_POSITION);
- }
- else
- {
- GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_POSITION )\n");
- qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION);
- }
- }
-
- if(diff & ATTR_TEXCOORD)
- {
- if(stateBits & ATTR_TEXCOORD)
- {
- GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TEXCOORD )\n");
- qglEnableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD0);
- }
- else
- {
- GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TEXCOORD )\n");
- qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD0);
- }
- }
-
- if(diff & ATTR_LIGHTCOORD)
- {
- if(stateBits & ATTR_LIGHTCOORD)
- {
- GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_LIGHTCOORD )\n");
- qglEnableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD1);
- }
- else
- {
- GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_LIGHTCOORD )\n");
- qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD1);
- }
- }
-
- if(diff & ATTR_NORMAL)
- {
- if(stateBits & ATTR_NORMAL)
- {
- GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_NORMAL )\n");
- qglEnableVertexAttribArrayARB(ATTR_INDEX_NORMAL);
- }
- else
- {
- GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_NORMAL )\n");
- qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL);
- }
- }
-
-#ifdef USE_VERT_TANGENT_SPACE
- if(diff & ATTR_TANGENT)
- {
- if(stateBits & ATTR_TANGENT)
- {
- GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TANGENT )\n");
- qglEnableVertexAttribArrayARB(ATTR_INDEX_TANGENT);
- }
- else
- {
- GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TANGENT )\n");
- qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT);
- }
- }
-
- if(diff & ATTR_BITANGENT)
- {
- if(stateBits & ATTR_BITANGENT)
- {
- GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_BITANGENT )\n");
- qglEnableVertexAttribArrayARB(ATTR_INDEX_BITANGENT);
- }
- else
- {
- GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_BITANGENT )\n");
- qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT);
- }
- }
-#endif
-
- if(diff & ATTR_COLOR)
- {
- if(stateBits & ATTR_COLOR)
- {
- GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_COLOR )\n");
- qglEnableVertexAttribArrayARB(ATTR_INDEX_COLOR);
- }
- else
- {
- GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_COLOR )\n");
- qglDisableVertexAttribArrayARB(ATTR_INDEX_COLOR);
- }
- }
-
- if(diff & ATTR_LIGHTDIRECTION)
- {
- if(stateBits & ATTR_LIGHTDIRECTION)
- {
- GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_LIGHTDIRECTION )\n");
- qglEnableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION);
- }
- else
- {
- GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_LIGHTDIRECTION )\n");
- qglDisableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION);
- }
- }
-
- if(diff & ATTR_POSITION2)
- {
- if(stateBits & ATTR_POSITION2)
- {
- GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_POSITION2 )\n");
- qglEnableVertexAttribArrayARB(ATTR_INDEX_POSITION2);
- }
- else
- {
- GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_POSITION2 )\n");
- qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION2);
- }
- }
-
- if(diff & ATTR_NORMAL2)
- {
- if(stateBits & ATTR_NORMAL2)
- {
- GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_NORMAL2 )\n");
- qglEnableVertexAttribArrayARB(ATTR_INDEX_NORMAL2);
- }
- else
- {
- GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_NORMAL2 )\n");
- qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL2);
- }
- }
-
-#ifdef USE_VERT_TANGENT_SPACE
- if(diff & ATTR_TANGENT2)
- {
- if(stateBits & ATTR_TANGENT2)
- {
- GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TANGENT2 )\n");
- qglEnableVertexAttribArrayARB(ATTR_INDEX_TANGENT2);
- }
- else
- {
- GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TANGENT2 )\n");
- qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT2);
- }
- }
-
- if(diff & ATTR_BITANGENT2)
- {
- if(stateBits & ATTR_BITANGENT2)
- {
- GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_BITANGENT2 )\n");
- qglEnableVertexAttribArrayARB(ATTR_INDEX_BITANGENT2);
- }
- else
- {
- GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_BITANGENT2 )\n");
- qglDisableVertexAttribArrayARB(ATTR_INDEX_BITANGENT2);
- }
- }
-#endif
-
- glState.vertexAttribsState = stateBits;
-}
-
-void GLSL_VertexAttribPointers(uint32_t attribBits)
-{
- if(!glState.currentVBO)
- {
- ri.Error(ERR_FATAL, "GL_VertexAttribPointers: no VBO bound");
- return;
- }
-
- // don't just call LogComment, or we will get a call to va() every frame!
- GLimp_LogComment(va("--- GL_VertexAttribPointers( %s ) ---\n", glState.currentVBO->name));
-
- if((attribBits & ATTR_POSITION) && !(glState.vertexAttribPointersSet & ATTR_POSITION))
- {
- GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_POSITION )\n");
-
- qglVertexAttribPointerARB(ATTR_INDEX_POSITION, 3, GL_FLOAT, 0, glState.currentVBO->stride_xyz, BUFFER_OFFSET(glState.currentVBO->ofs_xyz + glState.vertexAttribsNewFrame * glState.currentVBO->size_xyz));
- glState.vertexAttribPointersSet |= ATTR_POSITION;
- }
-
- if((attribBits & ATTR_TEXCOORD) && !(glState.vertexAttribPointersSet & ATTR_TEXCOORD))
- {
- GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TEXCOORD )\n");
-
- qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD0, 2, GL_FLOAT, 0, glState.currentVBO->stride_st, BUFFER_OFFSET(glState.currentVBO->ofs_st));
- glState.vertexAttribPointersSet |= ATTR_TEXCOORD;
- }
-
- if((attribBits & ATTR_LIGHTCOORD) && !(glState.vertexAttribPointersSet & ATTR_LIGHTCOORD))
- {
- GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_LIGHTCOORD )\n");
-
- qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD1, 2, GL_FLOAT, 0, glState.currentVBO->stride_lightmap, BUFFER_OFFSET(glState.currentVBO->ofs_lightmap));
- glState.vertexAttribPointersSet |= ATTR_LIGHTCOORD;
- }
-
- if((attribBits & ATTR_NORMAL) && !(glState.vertexAttribPointersSet & ATTR_NORMAL))
- {
- GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_NORMAL )\n");
-
- qglVertexAttribPointerARB(ATTR_INDEX_NORMAL, 3, GL_FLOAT, 0, glState.currentVBO->stride_normal, BUFFER_OFFSET(glState.currentVBO->ofs_normal + glState.vertexAttribsNewFrame * glState.currentVBO->size_normal));
- glState.vertexAttribPointersSet |= ATTR_NORMAL;
- }
-
-#ifdef USE_VERT_TANGENT_SPACE
- if((attribBits & ATTR_TANGENT) && !(glState.vertexAttribPointersSet & ATTR_TANGENT))
- {
- GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TANGENT )\n");
-
- qglVertexAttribPointerARB(ATTR_INDEX_TANGENT, 3, GL_FLOAT, 0, glState.currentVBO->stride_tangent, BUFFER_OFFSET(glState.currentVBO->ofs_tangent + glState.vertexAttribsNewFrame * glState.currentVBO->size_normal)); // FIXME
- glState.vertexAttribPointersSet |= ATTR_TANGENT;
- }
-
- if((attribBits & ATTR_BITANGENT) && !(glState.vertexAttribPointersSet & ATTR_BITANGENT))
- {
- GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_BITANGENT )\n");
-
- qglVertexAttribPointerARB(ATTR_INDEX_BITANGENT, 3, GL_FLOAT, 0, glState.currentVBO->stride_bitangent, BUFFER_OFFSET(glState.currentVBO->ofs_bitangent + glState.vertexAttribsNewFrame * glState.currentVBO->size_normal)); // FIXME
- glState.vertexAttribPointersSet |= ATTR_BITANGENT;
- }
-#endif
-
- if((attribBits & ATTR_COLOR) && !(glState.vertexAttribPointersSet & ATTR_COLOR))
- {
- GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_COLOR )\n");
-
- qglVertexAttribPointerARB(ATTR_INDEX_COLOR, 4, GL_FLOAT, 0, glState.currentVBO->stride_vertexcolor, BUFFER_OFFSET(glState.currentVBO->ofs_vertexcolor));
- glState.vertexAttribPointersSet |= ATTR_COLOR;
- }
-
- if((attribBits & ATTR_LIGHTDIRECTION) && !(glState.vertexAttribPointersSet & ATTR_LIGHTDIRECTION))
- {
- GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_LIGHTDIRECTION )\n");
-
- qglVertexAttribPointerARB(ATTR_INDEX_LIGHTDIRECTION, 3, GL_FLOAT, 0, glState.currentVBO->stride_lightdir, BUFFER_OFFSET(glState.currentVBO->ofs_lightdir));
- glState.vertexAttribPointersSet |= ATTR_LIGHTDIRECTION;
- }
-
- if((attribBits & ATTR_POSITION2) && !(glState.vertexAttribPointersSet & ATTR_POSITION2))
- {
- GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_POSITION2 )\n");
-
- qglVertexAttribPointerARB(ATTR_INDEX_POSITION2, 3, GL_FLOAT, 0, glState.currentVBO->stride_xyz, BUFFER_OFFSET(glState.currentVBO->ofs_xyz + glState.vertexAttribsOldFrame * glState.currentVBO->size_xyz));
- glState.vertexAttribPointersSet |= ATTR_POSITION2;
- }
-
- if((attribBits & ATTR_NORMAL2) && !(glState.vertexAttribPointersSet & ATTR_NORMAL2))
- {
- GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_NORMAL2 )\n");
-
- qglVertexAttribPointerARB(ATTR_INDEX_NORMAL2, 3, GL_FLOAT, 0, glState.currentVBO->stride_normal, BUFFER_OFFSET(glState.currentVBO->ofs_normal + glState.vertexAttribsOldFrame * glState.currentVBO->size_normal));
- glState.vertexAttribPointersSet |= ATTR_NORMAL2;
- }
-
-#ifdef USE_VERT_TANGENT_SPACE
- if((attribBits & ATTR_TANGENT2) && !(glState.vertexAttribPointersSet & ATTR_TANGENT2))
- {
- GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TANGENT2 )\n");
-
- qglVertexAttribPointerARB(ATTR_INDEX_TANGENT2, 3, GL_FLOAT, 0, glState.currentVBO->stride_tangent, BUFFER_OFFSET(glState.currentVBO->ofs_tangent + glState.vertexAttribsOldFrame * glState.currentVBO->size_normal)); // FIXME
- glState.vertexAttribPointersSet |= ATTR_TANGENT2;
- }
-
- if((attribBits & ATTR_BITANGENT2) && !(glState.vertexAttribPointersSet & ATTR_BITANGENT2))
- {
- GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_BITANGENT2 )\n");
-
- qglVertexAttribPointerARB(ATTR_INDEX_BITANGENT2, 3, GL_FLOAT, 0, glState.currentVBO->stride_bitangent, BUFFER_OFFSET(glState.currentVBO->ofs_bitangent + glState.vertexAttribsOldFrame * glState.currentVBO->size_normal)); // FIXME
- glState.vertexAttribPointersSet |= ATTR_BITANGENT2;
- }
-#endif
-
-}
-
-shaderProgram_t *GLSL_GetGenericShaderProgram(int stage)
-{
- shaderStage_t *pStage = tess.xstages[stage];
- int shaderAttribs = 0;
-
- if (tess.fogNum && pStage->adjustColorsForFog)
- {
- shaderAttribs |= GENERICDEF_USE_FOG;
- }
-
- if (pStage->bundle[1].image[0] && tess.shader->multitextureEnv)
- {
- shaderAttribs |= GENERICDEF_USE_LIGHTMAP;
- }
-
- switch (pStage->rgbGen)
- {
- case CGEN_LIGHTING_DIFFUSE:
- shaderAttribs |= GENERICDEF_USE_RGBAGEN;
- break;
- default:
- break;
- }
-
- switch (pStage->alphaGen)
- {
- case AGEN_LIGHTING_SPECULAR:
- case AGEN_PORTAL:
- case AGEN_FRESNEL:
- shaderAttribs |= GENERICDEF_USE_RGBAGEN;
- break;
- default:
- break;
- }
-
- if (pStage->bundle[0].tcGen != TCGEN_TEXTURE)
- {
- shaderAttribs |= GENERICDEF_USE_TCGEN_AND_TCMOD;
- }
-
- if (tess.shader->numDeforms && !ShaderRequiresCPUDeforms(tess.shader))
- {
- shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES;
- }
-
- if (glState.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
- {
- shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION;
- }
-
- if (pStage->bundle[0].numTexMods)
- {
- shaderAttribs |= GENERICDEF_USE_TCGEN_AND_TCMOD;
- }
-
- return &tr.genericShader[shaderAttribs];
-}
diff --git a/src/rend2/tr_image.c b/src/rend2/tr_image.c
deleted file mode 100644
index 8a1f574f..00000000
--- a/src/rend2/tr_image.c
+++ /dev/null
@@ -1,3462 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_image.c
-#include "tr_local.h"
-
-static byte s_intensitytable[256];
-static unsigned char s_gammatable[256];
-
-int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
-int gl_filter_max = GL_LINEAR;
-
-#define FILE_HASH_SIZE 1024
-static image_t* hashTable[FILE_HASH_SIZE];
-
-/*
-** R_GammaCorrect
-*/
-void R_GammaCorrect( byte *buffer, int bufSize ) {
- int i;
-
- for ( i = 0; i < bufSize; i++ ) {
- buffer[i] = s_gammatable[buffer[i]];
- }
-}
-
-typedef struct {
- char *name;
- int minimize, maximize;
-} textureMode_t;
-
-textureMode_t modes[] = {
- {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
- {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
- {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
- {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
- {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
- {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
-};
-
-/*
-================
-return a hash value for the filename
-================
-*/
-static long generateHashValue( const char *fname ) {
- int i;
- long hash;
- char letter;
-
- hash = 0;
- i = 0;
- while (fname[i] != '\0') {
- letter = tolower(fname[i]);
- if (letter =='.') break; // don't include extension
- if (letter =='\\') letter = '/'; // damn path names
- hash+=(long)(letter)*(i+119);
- i++;
- }
- hash &= (FILE_HASH_SIZE-1);
- return hash;
-}
-
-/*
-===============
-GL_TextureMode
-===============
-*/
-void GL_TextureMode( const char *string ) {
- int i;
- image_t *glt;
-
- for ( i=0 ; i< 6 ; i++ ) {
- if ( !Q_stricmp( modes[i].name, string ) ) {
- break;
- }
- }
-
- // hack to prevent trilinear from being set on voodoo,
- // because their driver freaks...
- if ( i == 5 && glConfig.hardwareType == GLHW_3DFX_2D3D ) {
- ri.Printf( PRINT_ALL, "Refusing to set trilinear on a voodoo.\n" );
- i = 3;
- }
-
-
- if ( i == 6 ) {
- ri.Printf (PRINT_ALL, "bad filter name\n");
- return;
- }
-
- gl_filter_min = modes[i].minimize;
- gl_filter_max = modes[i].maximize;
-
- // change all the existing mipmap texture objects
- for ( i = 0 ; i < tr.numImages ; i++ ) {
- glt = tr.images[ i ];
- if ( glt->flags & IMGFLAG_MIPMAP ) {
- GL_Bind (glt);
- qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
- qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
- }
- }
-}
-
-/*
-===============
-R_SumOfUsedImages
-===============
-*/
-int R_SumOfUsedImages( void ) {
- int total;
- int i;
-
- total = 0;
- for ( i = 0; i < tr.numImages; i++ ) {
- if ( tr.images[i]->frameUsed == tr.frameCount ) {
- total += tr.images[i]->uploadWidth * tr.images[i]->uploadHeight;
- }
- }
-
- return total;
-}
-
-/*
-===============
-R_ImageList_f
-===============
-*/
-void R_ImageList_f( void ) {
-#if 1
- int i;
- int estTotalSize = 0;
-
- ri.Printf(PRINT_ALL, "\n -w-- -h-- type -size- --name-------\n");
-
- for ( i = 0 ; i < tr.numImages ; i++ )
- {
- image_t *image = tr.images[i];
- char *format = "???? ";
- char *sizeSuffix;
- int estSize;
- int displaySize;
-
- estSize = image->uploadHeight * image->uploadWidth;
-
- switch(image->internalFormat)
- {
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
- format = "sDXT1";
- // 64 bits per 16 pixels, so 4 bits per pixel
- estSize /= 2;
- break;
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
- format = "sDXT5";
- // 128 bits per 16 pixels, so 1 byte per pixel
- break;
- case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB:
- format = "sBPTC";
- // 128 bits per 16 pixels, so 1 byte per pixel
- break;
- case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
- format = "LATC ";
- // 128 bits per 16 pixels, so 1 byte per pixel
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- format = "DXT1 ";
- // 64 bits per 16 pixels, so 4 bits per pixel
- estSize /= 2;
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- format = "DXT5 ";
- // 128 bits per 16 pixels, so 1 byte per pixel
- break;
- case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
- format = "BPTC ";
- // 128 bits per 16 pixels, so 1 byte per pixel
- break;
- case GL_RGB4_S3TC:
- format = "S3TC ";
- // same as DXT1?
- estSize /= 2;
- break;
- case GL_RGBA4:
- case GL_RGBA8:
- case GL_RGBA:
- format = "RGBA ";
- // 4 bytes per pixel
- estSize *= 4;
- break;
- case GL_LUMINANCE8:
- case GL_LUMINANCE16:
- case GL_LUMINANCE:
- format = "L ";
- // 1 byte per pixel?
- break;
- case GL_RGB5:
- case GL_RGB8:
- case GL_RGB:
- format = "RGB ";
- // 3 bytes per pixel?
- estSize *= 3;
- break;
- case GL_LUMINANCE8_ALPHA8:
- case GL_LUMINANCE16_ALPHA16:
- case GL_LUMINANCE_ALPHA:
- format = "LA ";
- // 2 bytes per pixel?
- estSize *= 2;
- break;
- case GL_SRGB_EXT:
- case GL_SRGB8_EXT:
- format = "sRGB ";
- // 3 bytes per pixel?
- estSize *= 3;
- break;
- case GL_SRGB_ALPHA_EXT:
- case GL_SRGB8_ALPHA8_EXT:
- format = "sRGBA";
- // 4 bytes per pixel?
- estSize *= 4;
- break;
- case GL_SLUMINANCE_EXT:
- case GL_SLUMINANCE8_EXT:
- format = "sL ";
- // 1 byte per pixel?
- break;
- case GL_SLUMINANCE_ALPHA_EXT:
- case GL_SLUMINANCE8_ALPHA8_EXT:
- format = "sLA ";
- // 2 byte per pixel?
- estSize *= 2;
- break;
- }
-
- // mipmap adds about 50%
- if (image->flags & IMGFLAG_MIPMAP)
- estSize += estSize / 2;
-
- sizeSuffix = "b ";
- displaySize = estSize;
-
- if (displaySize > 1024)
- {
- displaySize /= 1024;
- sizeSuffix = "kb";
- }
-
- if (displaySize > 1024)
- {
- displaySize /= 1024;
- sizeSuffix = "Mb";
- }
-
- if (displaySize > 1024)
- {
- displaySize /= 1024;
- sizeSuffix = "Gb";
- }
-
- ri.Printf(PRINT_ALL, "%4i: %4ix%4i %s %4i%s %s\n", i, image->uploadWidth, image->uploadHeight, format, displaySize, sizeSuffix, image->imgName);
- estTotalSize += estSize;
- }
-
- ri.Printf (PRINT_ALL, " ---------\n");
- ri.Printf (PRINT_ALL, " approx %i bytes\n", estTotalSize);
- ri.Printf (PRINT_ALL, " %i total images\n\n", tr.numImages );
-#else
- int i;
- image_t *image;
- int texels;
- const char *yesno[] = {
- "no ", "yes"
- };
-
- ri.Printf (PRINT_ALL, "\n -w-- -h-- -mm- -TMU- -if-- wrap --name-------\n");
- texels = 0;
-
- for ( i = 0 ; i < tr.numImages ; i++ ) {
- image = tr.images[ i ];
-
- texels += image->uploadWidth*image->uploadHeight;
- ri.Printf (PRINT_ALL, "%4i: %4i %4i %s %d ",
- i, image->uploadWidth, image->uploadHeight, yesno[(image->flags & IMGFLAG_MIPMAP) ? 1 : 0], image->TMU );
- switch ( image->internalFormat ) {
- case 1:
- ri.Printf( PRINT_ALL, "I " );
- break;
- case 2:
- ri.Printf( PRINT_ALL, "IA " );
- break;
- case 3:
- ri.Printf( PRINT_ALL, "RGB " );
- break;
- case 4:
- ri.Printf( PRINT_ALL, "RGBA " );
- break;
- case GL_RGBA8:
- ri.Printf( PRINT_ALL, "RGBA8" );
- break;
- case GL_RGB8:
- ri.Printf( PRINT_ALL, "RGB8" );
- break;
- case GL_RGB4_S3TC:
- ri.Printf( PRINT_ALL, "S3TC " );
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- ri.Printf( PRINT_ALL, "DXT1 " );
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- ri.Printf( PRINT_ALL, "DXT5 " );
- break;
- case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
- ri.Printf( PRINT_ALL, "LATC " );
- break;
- case GL_RGBA4:
- ri.Printf( PRINT_ALL, "RGBA4" );
- break;
- case GL_RGB5:
- ri.Printf( PRINT_ALL, "RGB5 " );
- break;
- case GL_SRGB_EXT:
- ri.Printf( PRINT_ALL, "sRGB " );
- break;
- case GL_SRGB8_EXT:
- ri.Printf( PRINT_ALL, "sRGB8" );
- break;
- case GL_SRGB_ALPHA_EXT:
- case GL_SRGB8_ALPHA8_EXT:
- ri.Printf( PRINT_ALL, "sRGBA" );
- break;
- /*
- case GL_SLUMINANCE_EXT:
- break;
- case GL_SLUMINANCE8_EXT:
- break;
- case GL_SLUMINANCE_ALPHA_EXT:
- break;
- case GL_SLUMINANCE8_ALPHA8_EXT:
- break;
- */
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
- ri.Printf( PRINT_ALL, "sDXT1" );
- break;
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
- ri.Printf( PRINT_ALL, "sDXT5" );
- break;
- case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
- ri.Printf( PRINT_ALL, "BPTC " );
- break;
- case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB:
- ri.Printf( PRINT_ALL, "sBPTC" );
- break;
- default:
- ri.Printf( PRINT_ALL, "???? " );
- }
-
- if (image->flags & IMGFLAG_CLAMPTOEDGE)
- ri.Printf( PRINT_ALL, "clmp " );
- else
- ri.Printf( PRINT_ALL, "rept " );
-
- ri.Printf( PRINT_ALL, " %s\n", image->imgName );
- }
- ri.Printf (PRINT_ALL, " ---------\n");
- ri.Printf (PRINT_ALL, " %i total texels (not including mipmaps)\n", texels);
- ri.Printf (PRINT_ALL, " %i total images\n\n", tr.numImages );
-#endif
-}
-
-//=======================================================================
-
-/*
-================
-ResampleTexture
-
-Used to resample images in a more general than quartering fashion.
-
-This will only be filtered properly if the resampled size
-is greater than half the original size.
-
-If a larger shrinking is needed, use the mipmap function
-before or after.
-================
-*/
-static void ResampleTexture( byte *in, int inwidth, int inheight, byte *out,
- int outwidth, int outheight ) {
- int i, j;
- byte *inrow, *inrow2;
- int frac, fracstep;
- int p1[2048], p2[2048];
- byte *pix1, *pix2, *pix3, *pix4;
-
- if (outwidth>2048)
- ri.Error(ERR_DROP, "ResampleTexture: max width");
-
- fracstep = inwidth*0x10000/outwidth;
-
- frac = fracstep>>2;
- for ( i=0 ; i<outwidth ; i++ ) {
- p1[i] = 4*(frac>>16);
- frac += fracstep;
- }
- frac = 3*(fracstep>>2);
- for ( i=0 ; i<outwidth ; i++ ) {
- p2[i] = 4*(frac>>16);
- frac += fracstep;
- }
-
- for (i=0 ; i<outheight ; i++) {
- inrow = in + 4*inwidth*(int)((i+0.25)*inheight/outheight);
- inrow2 = in + 4*inwidth*(int)((i+0.75)*inheight/outheight);
- frac = fracstep >> 1;
- for (j=0 ; j<outwidth ; j++) {
- pix1 = inrow + p1[j];
- pix2 = inrow + p2[j];
- pix3 = inrow2 + p1[j];
- pix4 = inrow2 + p2[j];
- *out++ = (pix1[0] + pix2[0] + pix3[0] + pix4[0])>>2;
- *out++ = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2;
- *out++ = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2;
- *out++ = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2;
- }
- }
-}
-
-static void RGBAtoYCoCgA(const byte *in, byte *out, int width, int height)
-{
- int x, y;
-
- for (y = 0; y < height; y++)
- {
- const byte *inbyte = in + y * width * 4;
- byte *outbyte = out + y * width * 4;
-
- for (x = 0; x < width; x++)
- {
- byte r, g, b, a, rb2;
-
- r = *inbyte++;
- g = *inbyte++;
- b = *inbyte++;
- a = *inbyte++;
- rb2 = (r + b) >> 1;
-
- *outbyte++ = (g + rb2) >> 1; // Y = R/4 + G/2 + B/4
- *outbyte++ = (r - b + 256) >> 1; // Co = R/2 - B/2
- *outbyte++ = (g - rb2 + 256) >> 1; // Cg = -R/4 + G/2 - B/4
- *outbyte++ = a;
- }
- }
-}
-
-static void YCoCgAtoRGBA(const byte *in, byte *out, int width, int height)
-{
- int x, y;
-
- for (y = 0; y < height; y++)
- {
- const byte *inbyte = in + y * width * 4;
- byte *outbyte = out + y * width * 4;
-
- for (x = 0; x < width; x++)
- {
- byte _Y, Co, Cg, a;
-
- _Y = *inbyte++;
- Co = *inbyte++;
- Cg = *inbyte++;
- a = *inbyte++;
-
- *outbyte++ = CLAMP(_Y + Co - Cg, 0, 255); // R = Y + Co - Cg
- *outbyte++ = CLAMP(_Y + Cg - 128, 0, 255); // G = Y + Cg
- *outbyte++ = CLAMP(_Y - Co - Cg + 256, 0, 255); // B = Y - Co - Cg
- *outbyte++ = a;
- }
- }
-}
-
-
-// uses a sobel filter to change a texture to a normal map
-static void RGBAtoNormal(const byte *in, byte *out, int width, int height, qboolean clampToEdge)
-{
- int x, y, max;
-
- // convert to heightmap, storing in alpha
- // same as converting to Y in YCoCg
- max = 1;
- for (y = 0; y < height; y++)
- {
- const byte *inbyte = in + y * width * 4;
- byte *outbyte = out + y * width * 4 + 3;
-
- for (x = 0; x < width; x++)
- {
- *outbyte = (inbyte[0] >> 2) + (inbyte[1] >> 1) + (inbyte[2] >> 2);
- max = MAX(max, *outbyte);
- outbyte += 4;
- inbyte += 4;
- }
- }
-
- // level out heights
- if (max < 255)
- {
- for (y = 0; y < height; y++)
- {
- byte *outbyte = out + y * width * 4 + 3;
-
- for (x = 0; x < width; x++)
- {
- *outbyte = *outbyte + (255 - max);
- outbyte += 4;
- }
- }
- }
-
-
- // now run sobel filter over height values to generate X and Y
- // then normalize
- for (y = 0; y < height; y++)
- {
- byte *outbyte = out + y * width * 4;
-
- for (x = 0; x < width; x++)
- {
- // 0 1 2
- // 3 4 5
- // 6 7 8
-
- byte s[9];
- int x2, y2, i;
- vec3_t normal;
-
- i = 0;
- for (y2 = -1; y2 <= 1; y2++)
- {
- int src_y = y + y2;
-
- if (clampToEdge)
- {
- src_y = CLAMP(src_y, 0, height - 1);
- }
- else
- {
- src_y = (src_y + height) % height;
- }
-
-
- for (x2 = -1; x2 <= 1; x2++)
- {
- int src_x = x + x2;
-
- if (clampToEdge)
- {
- src_x = CLAMP(src_x, 0, height - 1);
- }
- else
- {
- src_x = (src_x + height) % height;
- }
-
- s[i++] = *(out + (src_y * width + src_x) * 4 + 3);
- }
- }
-
- normal[0] = s[0] - s[2]
- + 2 * s[3] - 2 * s[5]
- + s[6] - s[8];
-
- normal[1] = s[0] + 2 * s[1] + s[2]
-
- - s[6] - 2 * s[7] - s[8];
-
- normal[2] = s[4] * 4;
-
- if (!VectorNormalize2(normal, normal))
- {
- VectorSet(normal, 0, 0, 1);
- }
-
- *outbyte++ = FloatToOffsetByte(normal[0]);
- *outbyte++ = FloatToOffsetByte(normal[1]);
- *outbyte++ = FloatToOffsetByte(normal[2]);
- outbyte++;
- }
- }
-}
-
-#define COPYSAMPLE(a,b) *(unsigned int *)(a) = *(unsigned int *)(b)
-
-// based on Fast Curve Based Interpolation
-// from Fast Artifacts-Free Image Interpolation (http://www.andreagiachetti.it/icbi/)
-// assumes data has a 2 pixel thick border of clamped or wrapped data
-// expects data to be a grid with even (0, 0), (2, 0), (0, 2), (2, 2) etc pixels filled
-// only performs FCBI on specified component
-static void DoFCBI(byte *in, byte *out, int width, int height, int component)
-{
- int x, y;
- byte *outbyte, *inbyte;
-
- // copy in to out
- for (y = 2; y < height - 2; y += 2)
- {
- inbyte = in + (y * width + 2) * 4 + component;
- outbyte = out + (y * width + 2) * 4 + component;
-
- for (x = 2; x < width - 2; x += 2)
- {
- *outbyte = *inbyte;
- outbyte += 8;
- inbyte += 8;
- }
- }
-
- for (y = 3; y < height - 3; y += 2)
- {
- // diagonals
- //
- // NWp - northwest interpolated pixel
- // NEp - northeast interpolated pixel
- // NWd - northwest first derivative
- // NEd - northeast first derivative
- // NWdd - northwest second derivative
- // NEdd - northeast second derivative
- //
- // Uses these samples:
- //
- // 0
- // - - a - b - -
- // - - - - - - -
- // c - d - e - f
- // 0 - - - - - - -
- // g - h - i - j
- // - - - - - - -
- // - - k - l - -
- //
- // x+2 uses these samples:
- //
- // 0
- // - - - - a - b - -
- // - - - - - - - - -
- // - - c - d - e - f
- // 0 - - - - - - - - -
- // - - g - h - i - j
- // - - - - - - - - -
- // - - - - k - l - -
- //
- // so we can reuse 8 of them on next iteration
- //
- // a=b, c=d, d=e, e=f, g=h, h=i, i=j, k=l
- //
- // only b, f, j, and l need to be sampled on next iteration
-
- byte sa, sb, sc, sd, se, sf, sg, sh, si, sj, sk, sl;
- byte *line1, *line2, *line3, *line4;
-
- x = 3;
-
- // optimization one
- // SAMPLE2(sa, x-1, y-3);
- //SAMPLE2(sc, x-3, y-1); SAMPLE2(sd, x-1, y-1); SAMPLE2(se, x+1, y-1);
- //SAMPLE2(sg, x-3, y+1); SAMPLE2(sh, x-1, y+1); SAMPLE2(si, x+1, y+1);
- // SAMPLE2(sk, x-1, y+3);
-
- // optimization two
- line1 = in + ((y - 3) * width + (x - 1)) * 4 + component;
- line2 = in + ((y - 1) * width + (x - 3)) * 4 + component;
- line3 = in + ((y + 1) * width + (x - 3)) * 4 + component;
- line4 = in + ((y + 3) * width + (x - 1)) * 4 + component;
-
- // COPYSAMPLE(sa, line1); line1 += 8;
- //COPYSAMPLE(sc, line2); line2 += 8; COPYSAMPLE(sd, line2); line2 += 8; COPYSAMPLE(se, line2); line2 += 8;
- //COPYSAMPLE(sg, line3); line3 += 8; COPYSAMPLE(sh, line3); line3 += 8; COPYSAMPLE(si, line3); line3 += 8;
- // COPYSAMPLE(sk, line4); line4 += 8;
-
- sa = *line1; line1 += 8;
- sc = *line2; line2 += 8; sd = *line2; line2 += 8; se = *line2; line2 += 8;
- sg = *line3; line3 += 8; sh = *line3; line3 += 8; si = *line3; line3 += 8;
- sk = *line4; line4 += 8;
-
- outbyte = out + (y * width + x) * 4 + component;
-
- for ( ; x < width - 3; x += 2)
- {
- int NWd, NEd, NWp, NEp;
-
- // original
- // SAMPLE2(sa, x-1, y-3); SAMPLE2(sb, x+1, y-3);
- //SAMPLE2(sc, x-3, y-1); SAMPLE2(sd, x-1, y-1); SAMPLE2(se, x+1, y-1); SAMPLE2(sf, x+3, y-1);
- //SAMPLE2(sg, x-3, y+1); SAMPLE2(sh, x-1, y+1); SAMPLE2(si, x+1, y+1); SAMPLE2(sj, x+3, y+1);
- // SAMPLE2(sk, x-1, y+3); SAMPLE2(sl, x+1, y+3);
-
- // optimization one
- //SAMPLE2(sb, x+1, y-3);
- //SAMPLE2(sf, x+3, y-1);
- //SAMPLE2(sj, x+3, y+1);
- //SAMPLE2(sl, x+1, y+3);
-
- // optimization two
- //COPYSAMPLE(sb, line1); line1 += 8;
- //COPYSAMPLE(sf, line2); line2 += 8;
- //COPYSAMPLE(sj, line3); line3 += 8;
- //COPYSAMPLE(sl, line4); line4 += 8;
-
- sb = *line1; line1 += 8;
- sf = *line2; line2 += 8;
- sj = *line3; line3 += 8;
- sl = *line4; line4 += 8;
-
- NWp = sd + si;
- NEp = se + sh;
- NWd = abs(sd - si);
- NEd = abs(se - sh);
-
- if (NWd > 100 || NEd > 100 || abs(NWp-NEp) > 200)
- {
- if (NWd < NEd)
- *outbyte = NWp >> 1;
- else
- *outbyte = NEp >> 1;
- }
- else
- {
- int NWdd, NEdd;
-
- //NEdd = abs(sg + sd + sb - 3 * (se + sh) + sk + si + sf);
- //NWdd = abs(sa + se + sj - 3 * (sd + si) + sc + sh + sl);
- NEdd = abs(sg + sb - 3 * NEp + sk + sf + NWp);
- NWdd = abs(sa + sj - 3 * NWp + sc + sl + NEp);
-
- if (NWdd > NEdd)
- *outbyte = NWp >> 1;
- else
- *outbyte = NEp >> 1;
- }
-
- outbyte += 8;
-
- // COPYSAMPLE(sa, sb);
- //COPYSAMPLE(sc, sd); COPYSAMPLE(sd, se); COPYSAMPLE(se, sf);
- //COPYSAMPLE(sg, sh); COPYSAMPLE(sh, si); COPYSAMPLE(si, sj);
- // COPYSAMPLE(sk, sl);
-
- sa = sb;
- sc = sd; sd = se; se = sf;
- sg = sh; sh = si; si = sj;
- sk = sl;
- }
- }
-
- // hack: copy out to in again
- for (y = 3; y < height - 3; y += 2)
- {
- inbyte = out + (y * width + 3) * 4 + component;
- outbyte = in + (y * width + 3) * 4 + component;
-
- for (x = 3; x < width - 3; x += 2)
- {
- *outbyte = *inbyte;
- outbyte += 8;
- inbyte += 8;
- }
- }
-
- for (y = 2; y < height - 3; y++)
- {
- // horizontal & vertical
- //
- // hp - horizontally interpolated pixel
- // vp - vertically interpolated pixel
- // hd - horizontal first derivative
- // vd - vertical first derivative
- // hdd - horizontal second derivative
- // vdd - vertical second derivative
- // Uses these samples:
- //
- // 0
- // - a - b -
- // c - d - e
- // 0 - f - g -
- // h - i - j
- // - k - l -
- //
- // x+2 uses these samples:
- //
- // 0
- // - - - a - b -
- // - - c - d - e
- // 0 - - - f - g -
- // - - h - i - j
- // - - - k - l -
- //
- // so we can reuse 7 of them on next iteration
- //
- // a=b, c=d, d=e, f=g, h=i, i=j, k=l
- //
- // only b, e, g, j, and l need to be sampled on next iteration
-
- byte sa, sb, sc, sd, se, sf, sg, sh, si, sj, sk, sl;
- byte *line1, *line2, *line3, *line4, *line5;
-
- //x = (y + 1) % 2;
- x = (y + 1) % 2 + 2;
-
- // optimization one
- // SAMPLE2(sa, x-1, y-2);
- //SAMPLE2(sc, x-2, y-1); SAMPLE2(sd, x, y-1);
- // SAMPLE2(sf, x-1, y );
- //SAMPLE2(sh, x-2, y+1); SAMPLE2(si, x, y+1);
- // SAMPLE2(sk, x-1, y+2);
-
- line1 = in + ((y - 2) * width + (x - 1)) * 4 + component;
- line2 = in + ((y - 1) * width + (x - 2)) * 4 + component;
- line3 = in + ((y ) * width + (x - 1)) * 4 + component;
- line4 = in + ((y + 1) * width + (x - 2)) * 4 + component;
- line5 = in + ((y + 2) * width + (x - 1)) * 4 + component;
-
- // COPYSAMPLE(sa, line1); line1 += 8;
- //COPYSAMPLE(sc, line2); line2 += 8; COPYSAMPLE(sd, line2); line2 += 8;
- // COPYSAMPLE(sf, line3); line3 += 8;
- //COPYSAMPLE(sh, line4); line4 += 8; COPYSAMPLE(si, line4); line4 += 8;
- // COPYSAMPLE(sk, line5); line5 += 8;
-
- sa = *line1; line1 += 8;
- sc = *line2; line2 += 8; sd = *line2; line2 += 8;
- sf = *line3; line3 += 8;
- sh = *line4; line4 += 8; si = *line4; line4 += 8;
- sk = *line5; line5 += 8;
-
- outbyte = out + (y * width + x) * 4 + component;
-
- for ( ; x < width - 3; x+=2)
- {
- int hd, vd, hp, vp;
-
- // SAMPLE2(sa, x-1, y-2); SAMPLE2(sb, x+1, y-2);
- //SAMPLE2(sc, x-2, y-1); SAMPLE2(sd, x, y-1); SAMPLE2(se, x+2, y-1);
- // SAMPLE2(sf, x-1, y ); SAMPLE2(sg, x+1, y );
- //SAMPLE2(sh, x-2, y+1); SAMPLE2(si, x, y+1); SAMPLE2(sj, x+2, y+1);
- // SAMPLE2(sk, x-1, y+2); SAMPLE2(sl, x+1, y+2);
-
- // optimization one
- //SAMPLE2(sb, x+1, y-2);
- //SAMPLE2(se, x+2, y-1);
- //SAMPLE2(sg, x+1, y );
- //SAMPLE2(sj, x+2, y+1);
- //SAMPLE2(sl, x+1, y+2);
-
- //COPYSAMPLE(sb, line1); line1 += 8;
- //COPYSAMPLE(se, line2); line2 += 8;
- //COPYSAMPLE(sg, line3); line3 += 8;
- //COPYSAMPLE(sj, line4); line4 += 8;
- //COPYSAMPLE(sl, line5); line5 += 8;
-
- sb = *line1; line1 += 8;
- se = *line2; line2 += 8;
- sg = *line3; line3 += 8;
- sj = *line4; line4 += 8;
- sl = *line5; line5 += 8;
-
- hp = sf + sg;
- vp = sd + si;
- hd = abs(sf - sg);
- vd = abs(sd - si);
-
- if (hd > 100 || vd > 100 || abs(hp-vp) > 200)
- {
- if (hd < vd)
- *outbyte = hp >> 1;
- else
- *outbyte = vp >> 1;
- }
- else
- {
- int hdd, vdd;
-
- //hdd = abs(sc[i] + sd[i] + se[i] - 3 * (sf[i] + sg[i]) + sh[i] + si[i] + sj[i]);
- //vdd = abs(sa[i] + sf[i] + sk[i] - 3 * (sd[i] + si[i]) + sb[i] + sg[i] + sl[i]);
-
- hdd = abs(sc + se - 3 * hp + sh + sj + vp);
- vdd = abs(sa + sk - 3 * vp + sb + sl + hp);
-
- if (hdd > vdd)
- *outbyte = hp >> 1;
- else
- *outbyte = vp >> 1;
- }
-
- outbyte += 8;
-
- // COPYSAMPLE(sa, sb);
- //COPYSAMPLE(sc, sd); COPYSAMPLE(sd, se);
- // COPYSAMPLE(sf, sg);
- //COPYSAMPLE(sh, si); COPYSAMPLE(si, sj);
- // COPYSAMPLE(sk, sl);
- sa = sb;
- sc = sd; sd = se;
- sf = sg;
- sh = si; si = sj;
- sk = sl;
- }
- }
-}
-
-// Similar to FCBI, but throws out the second order derivatives for speed
-static void DoFCBIQuick(byte *in, byte *out, int width, int height, int component)
-{
- int x, y;
- byte *outbyte, *inbyte;
-
- // copy in to out
- for (y = 2; y < height - 2; y += 2)
- {
- inbyte = in + (y * width + 2) * 4 + component;
- outbyte = out + (y * width + 2) * 4 + component;
-
- for (x = 2; x < width - 2; x += 2)
- {
- *outbyte = *inbyte;
- outbyte += 8;
- inbyte += 8;
- }
- }
-
- for (y = 3; y < height - 4; y += 2)
- {
- byte sd, se, sh, si;
- byte *line2, *line3;
-
- x = 3;
-
- line2 = in + ((y - 1) * width + (x - 1)) * 4 + component;
- line3 = in + ((y + 1) * width + (x - 1)) * 4 + component;
-
- sd = *line2; line2 += 8;
- sh = *line3; line3 += 8;
-
- outbyte = out + (y * width + x) * 4 + component;
-
- for ( ; x < width - 4; x += 2)
- {
- int NWd, NEd, NWp, NEp;
-
- se = *line2; line2 += 8;
- si = *line3; line3 += 8;
-
- NWp = sd + si;
- NEp = se + sh;
- NWd = abs(sd - si);
- NEd = abs(se - sh);
-
- if (NWd < NEd)
- *outbyte = NWp >> 1;
- else
- *outbyte = NEp >> 1;
-
- outbyte += 8;
-
- sd = se;
- sh = si;
- }
- }
-
- // hack: copy out to in again
- for (y = 3; y < height - 3; y += 2)
- {
- inbyte = out + (y * width + 3) * 4 + component;
- outbyte = in + (y * width + 3) * 4 + component;
-
- for (x = 3; x < width - 3; x += 2)
- {
- *outbyte = *inbyte;
- outbyte += 8;
- inbyte += 8;
- }
- }
-
- for (y = 2; y < height - 3; y++)
- {
- byte sd, sf, sg, si;
- byte *line2, *line3, *line4;
-
- x = (y + 1) % 2 + 2;
-
- line2 = in + ((y - 1) * width + (x )) * 4 + component;
- line3 = in + ((y ) * width + (x - 1)) * 4 + component;
- line4 = in + ((y + 1) * width + (x )) * 4 + component;
-
- outbyte = out + (y * width + x) * 4 + component;
-
- sf = *line3; line3 += 8;
-
- for ( ; x < width - 3; x+=2)
- {
- int hd, vd, hp, vp;
-
- sd = *line2; line2 += 8;
- sg = *line3; line3 += 8;
- si = *line4; line4 += 8;
-
- hp = sf + sg;
- vp = sd + si;
- hd = abs(sf - sg);
- vd = abs(sd - si);
-
- if (hd < vd)
- *outbyte = hp >> 1;
- else
- *outbyte = vp >> 1;
-
- outbyte += 8;
-
- sf = sg;
- }
- }
-}
-
-// Similar to DoFCBIQuick, but just takes the average instead of checking derivatives
-// as well, this operates on all four components
-static void DoLinear(byte *in, byte *out, int width, int height)
-{
- int x, y, i;
- byte *outbyte, *inbyte;
-
- // copy in to out
- for (y = 2; y < height - 2; y += 2)
- {
- x = 2;
-
- inbyte = in + (y * width + x) * 4;
- outbyte = out + (y * width + x) * 4;
-
- for ( ; x < width - 2; x += 2)
- {
- COPYSAMPLE(outbyte, inbyte);
- outbyte += 8;
- inbyte += 8;
- }
- }
-
- for (y = 1; y < height - 1; y += 2)
- {
- byte sd[4], se[4], sh[4], si[4];
- byte *line2, *line3;
-
- x = 1;
-
- line2 = in + ((y - 1) * width + (x - 1)) * 4;
- line3 = in + ((y + 1) * width + (x - 1)) * 4;
-
- COPYSAMPLE(sd, line2); line2 += 8;
- COPYSAMPLE(sh, line3); line3 += 8;
-
- outbyte = out + (y * width + x) * 4;
-
- for ( ; x < width - 1; x += 2)
- {
- COPYSAMPLE(se, line2); line2 += 8;
- COPYSAMPLE(si, line3); line3 += 8;
-
- for (i = 0; i < 4; i++)
- {
- *outbyte++ = (sd[i] + si[i] + se[i] + sh[i]) >> 2;
- }
-
- outbyte += 4;
-
- COPYSAMPLE(sd, se);
- COPYSAMPLE(sh, si);
- }
- }
-
- // hack: copy out to in again
- for (y = 1; y < height - 1; y += 2)
- {
- x = 1;
-
- inbyte = out + (y * width + x) * 4;
- outbyte = in + (y * width + x) * 4;
-
- for ( ; x < width - 1; x += 2)
- {
- COPYSAMPLE(outbyte, inbyte);
- outbyte += 8;
- inbyte += 8;
- }
- }
-
- for (y = 1; y < height - 1; y++)
- {
- byte sd[4], sf[4], sg[4], si[4];
- byte *line2, *line3, *line4;
-
- x = y % 2 + 1;
-
- line2 = in + ((y - 1) * width + (x )) * 4;
- line3 = in + ((y ) * width + (x - 1)) * 4;
- line4 = in + ((y + 1) * width + (x )) * 4;
-
- COPYSAMPLE(sf, line3); line3 += 8;
-
- outbyte = out + (y * width + x) * 4;
-
- for ( ; x < width - 1; x += 2)
- {
- COPYSAMPLE(sd, line2); line2 += 8;
- COPYSAMPLE(sg, line3); line3 += 8;
- COPYSAMPLE(si, line4); line4 += 8;
-
- for (i = 0; i < 4; i++)
- {
- *outbyte++ = (sf[i] + sg[i] + sd[i] + si[i]) >> 2;
- }
-
- outbyte += 4;
-
- COPYSAMPLE(sf, sg);
- }
- }
-}
-
-
-static void ExpandHalfTextureToGrid( byte *data, int width, int height)
-{
- int x, y;
-
- for (y = height / 2; y > 0; y--)
- {
- byte *outbyte = data + ((y * 2 - 1) * (width) - 2) * 4;
- byte *inbyte = data + (y * (width / 2) - 1) * 4;
-
- for (x = width / 2; x > 0; x--)
- {
- COPYSAMPLE(outbyte, inbyte);
-
- outbyte -= 8;
- inbyte -= 4;
- }
- }
-}
-
-static void FillInNormalizedZ(const byte *in, byte *out, int width, int height)
-{
- int x, y;
-
- for (y = 0; y < height; y++)
- {
- const byte *inbyte = in + y * width * 4;
- byte *outbyte = out + y * width * 4;
-
- for (x = 0; x < width; x++)
- {
- byte nx, ny, nz, h;
- float fnx, fny, fll, fnz;
-
- nx = *inbyte++;
- ny = *inbyte++;
- inbyte++;
- h = *inbyte++;
-
- fnx = OffsetByteToFloat(nx);
- fny = OffsetByteToFloat(ny);
- fll = 1.0f - fnx * fnx - fny * fny;
- if (fll >= 0.0f)
- fnz = (float)sqrt(fll);
- else
- fnz = 0.0f;
-
- nz = FloatToOffsetByte(fnz);
-
- *outbyte++ = nx;
- *outbyte++ = ny;
- *outbyte++ = nz;
- *outbyte++ = h;
- }
- }
-}
-
-
-// size must be even
-#define WORKBLOCK_SIZE 128
-#define WORKBLOCK_BORDER 4
-#define WORKBLOCK_REALSIZE (WORKBLOCK_SIZE + WORKBLOCK_BORDER * 2)
-
-// assumes that data has already been expanded into a 2x2 grid
-static void FCBIByBlock(byte *data, int width, int height, qboolean clampToEdge, qboolean normalized)
-{
- byte workdata[WORKBLOCK_REALSIZE * WORKBLOCK_REALSIZE * 4];
- byte outdata[WORKBLOCK_REALSIZE * WORKBLOCK_REALSIZE * 4];
- byte *inbyte, *outbyte;
- int x, y;
- int srcx, srcy;
-
- ExpandHalfTextureToGrid(data, width, height);
-
- for (y = 0; y < height; y += WORKBLOCK_SIZE)
- {
- for (x = 0; x < width; x += WORKBLOCK_SIZE)
- {
- int x2, y2;
- int workwidth, workheight, fullworkwidth, fullworkheight;
-
- workwidth = MIN(WORKBLOCK_SIZE, width - x);
- workheight = MIN(WORKBLOCK_SIZE, height - y);
-
- fullworkwidth = workwidth + WORKBLOCK_BORDER * 2;
- fullworkheight = workheight + WORKBLOCK_BORDER * 2;
-
- //memset(workdata, 0, WORKBLOCK_REALSIZE * WORKBLOCK_REALSIZE * 4);
-
- // fill in work block
- for (y2 = 0; y2 < fullworkheight; y2 += 2)
- {
- srcy = y + y2 - WORKBLOCK_BORDER;
-
- if (clampToEdge)
- {
- srcy = CLAMP(srcy, 0, height - 2);
- }
- else
- {
- srcy = (srcy + height) % height;
- }
-
- outbyte = workdata + y2 * fullworkwidth * 4;
- inbyte = data + srcy * width * 4;
-
- for (x2 = 0; x2 < fullworkwidth; x2 += 2)
- {
- srcx = x + x2 - WORKBLOCK_BORDER;
-
- if (clampToEdge)
- {
- srcx = CLAMP(srcx, 0, width - 2);
- }
- else
- {
- srcx = (srcx + width) % width;
- }
-
- COPYSAMPLE(outbyte, inbyte + srcx * 4);
- outbyte += 8;
- }
- }
-
- // submit work block
- DoLinear(workdata, outdata, fullworkwidth, fullworkheight);
-
- if (!normalized)
- {
- switch (r_imageUpsampleType->integer)
- {
- case 0:
- break;
- case 1:
- DoFCBIQuick(workdata, outdata, fullworkwidth, fullworkheight, 0);
- break;
- case 2:
- default:
- DoFCBI(workdata, outdata, fullworkwidth, fullworkheight, 0);
- break;
- }
- }
- else
- {
- switch (r_imageUpsampleType->integer)
- {
- case 0:
- break;
- case 1:
- DoFCBIQuick(workdata, outdata, fullworkwidth, fullworkheight, 0);
- DoFCBIQuick(workdata, outdata, fullworkwidth, fullworkheight, 1);
- break;
- case 2:
- default:
- DoFCBI(workdata, outdata, fullworkwidth, fullworkheight, 0);
- DoFCBI(workdata, outdata, fullworkwidth, fullworkheight, 1);
- break;
- }
- }
-
- // copy back work block
- for (y2 = 0; y2 < workheight; y2++)
- {
- inbyte = outdata + ((y2 + WORKBLOCK_BORDER) * fullworkwidth + WORKBLOCK_BORDER) * 4;
- outbyte = data + ((y + y2) * width + x) * 4;
- for (x2 = 0; x2 < workwidth; x2++)
- {
- COPYSAMPLE(outbyte, inbyte);
- outbyte += 4;
- inbyte += 4;
- }
- }
- }
- }
-}
-#undef COPYSAMPLE
-
-/*
-================
-R_LightScaleTexture
-
-Scale up the pixel values in a texture to increase the
-lighting range
-================
-*/
-void R_LightScaleTexture (byte *in, int inwidth, int inheight, qboolean only_gamma )
-{
- if ( only_gamma )
- {
- if ( !glConfig.deviceSupportsGamma )
- {
- int i, c;
- byte *p;
-
- p = in;
-
- c = inwidth*inheight;
- for (i=0 ; i<c ; i++, p+=4)
- {
- p[0] = s_gammatable[p[0]];
- p[1] = s_gammatable[p[1]];
- p[2] = s_gammatable[p[2]];
- }
- }
- }
- else
- {
- int i, c;
- byte *p;
-
- p = in;
-
- c = inwidth*inheight;
-
- if ( glConfig.deviceSupportsGamma )
- {
- for (i=0 ; i<c ; i++, p+=4)
- {
- p[0] = s_intensitytable[p[0]];
- p[1] = s_intensitytable[p[1]];
- p[2] = s_intensitytable[p[2]];
- }
- }
- else
- {
- for (i=0 ; i<c ; i++, p+=4)
- {
- p[0] = s_gammatable[s_intensitytable[p[0]]];
- p[1] = s_gammatable[s_intensitytable[p[1]]];
- p[2] = s_gammatable[s_intensitytable[p[2]]];
- }
- }
- }
-}
-
-
-/*
-================
-R_MipMap2
-
-Operates in place, quartering the size of the texture
-Proper linear filter
-================
-*/
-static void R_MipMap2( byte *in, int inWidth, int inHeight ) {
- int i, j, k;
- byte *outpix;
- int inWidthMask, inHeightMask;
- int total;
- int outWidth, outHeight;
- unsigned *temp;
-
- outWidth = inWidth >> 1;
- outHeight = inHeight >> 1;
- temp = ri.Hunk_AllocateTempMemory( outWidth * outHeight * 4 );
-
- inWidthMask = inWidth - 1;
- inHeightMask = inHeight - 1;
-
- for ( i = 0 ; i < outHeight ; i++ ) {
- for ( j = 0 ; j < outWidth ; j++ ) {
- outpix = (byte *) ( temp + i * outWidth + j );
- for ( k = 0 ; k < 4 ; k++ ) {
- total =
- 1 * (&in[ 4*(((i*2-1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask)) ])[k] +
- 2 * (&in[ 4*(((i*2-1)&inHeightMask)*inWidth + ((j*2 )&inWidthMask)) ])[k] +
- 2 * (&in[ 4*(((i*2-1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask)) ])[k] +
- 1 * (&in[ 4*(((i*2-1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask)) ])[k] +
-
- 2 * (&in[ 4*(((i*2 )&inHeightMask)*inWidth + ((j*2-1)&inWidthMask)) ])[k] +
- 4 * (&in[ 4*(((i*2 )&inHeightMask)*inWidth + ((j*2 )&inWidthMask)) ])[k] +
- 4 * (&in[ 4*(((i*2 )&inHeightMask)*inWidth + ((j*2+1)&inWidthMask)) ])[k] +
- 2 * (&in[ 4*(((i*2 )&inHeightMask)*inWidth + ((j*2+2)&inWidthMask)) ])[k] +
-
- 2 * (&in[ 4*(((i*2+1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask)) ])[k] +
- 4 * (&in[ 4*(((i*2+1)&inHeightMask)*inWidth + ((j*2 )&inWidthMask)) ])[k] +
- 4 * (&in[ 4*(((i*2+1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask)) ])[k] +
- 2 * (&in[ 4*(((i*2+1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask)) ])[k] +
-
- 1 * (&in[ 4*(((i*2+2)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask)) ])[k] +
- 2 * (&in[ 4*(((i*2+2)&inHeightMask)*inWidth + ((j*2 )&inWidthMask)) ])[k] +
- 2 * (&in[ 4*(((i*2+2)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask)) ])[k] +
- 1 * (&in[ 4*(((i*2+2)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask)) ])[k];
- outpix[k] = total / 36;
- }
- }
- }
-
- Com_Memcpy( in, temp, outWidth * outHeight * 4 );
- ri.Hunk_FreeTempMemory( temp );
-}
-
-
-static void R_MipMapsRGB( byte *in, int inWidth, int inHeight)
-{
- int i, j, k;
- int outWidth, outHeight;
- byte *temp;
-
- outWidth = inWidth >> 1;
- outHeight = inHeight >> 1;
- temp = ri.Hunk_AllocateTempMemory( outWidth * outHeight * 4 );
-
- for ( i = 0 ; i < outHeight ; i++ ) {
- byte *outbyte = temp + ( i * outWidth ) * 4;
- byte *inbyte1 = in + ( i * 2 * inWidth ) * 4;
- byte *inbyte2 = in + ( (i * 2 + 1) * inWidth ) * 4;
- for ( j = 0 ; j < outWidth ; j++ ) {
- for ( k = 0 ; k < 3 ; k++ ) {
- float total, current;
-
- current = ByteToFloat(inbyte1[0]); total = sRGBtoRGB(current);
- current = ByteToFloat(inbyte1[4]); total += sRGBtoRGB(current);
- current = ByteToFloat(inbyte2[0]); total += sRGBtoRGB(current);
- current = ByteToFloat(inbyte2[4]); total += sRGBtoRGB(current);
-
- total *= 0.25f;
-
- inbyte1++;
- inbyte2++;
-
- current = RGBtosRGB(total);
- *outbyte++ = FloatToByte(current);
- }
- *outbyte++ = (inbyte1[0] + inbyte1[4] + inbyte2[0] + inbyte2[4]) >> 2;
- inbyte1 += 5;
- inbyte2 += 5;
- }
- }
-
- Com_Memcpy( in, temp, outWidth * outHeight * 4 );
- ri.Hunk_FreeTempMemory( temp );
-}
-
-/*
-================
-R_MipMap
-
-Operates in place, quartering the size of the texture
-================
-*/
-static void R_MipMap (byte *in, int width, int height) {
- int i, j;
- byte *out;
- int row;
-
- if ( !r_simpleMipMaps->integer ) {
- R_MipMap2( in, width, height );
- return;
- }
-
- if ( width == 1 && height == 1 ) {
- return;
- }
-
- row = width * 4;
- out = in;
- width >>= 1;
- height >>= 1;
-
- if ( width == 0 || height == 0 ) {
- width += height; // get largest
- for (i=0 ; i<width ; i++, out+=4, in+=8 ) {
- out[0] = ( in[0] + in[4] )>>1;
- out[1] = ( in[1] + in[5] )>>1;
- out[2] = ( in[2] + in[6] )>>1;
- out[3] = ( in[3] + in[7] )>>1;
- }
- return;
- }
-
- for (i=0 ; i<height ; i++, in+=row) {
- for (j=0 ; j<width ; j++, out+=4, in+=8) {
- out[0] = (in[0] + in[4] + in[row+0] + in[row+4])>>2;
- out[1] = (in[1] + in[5] + in[row+1] + in[row+5])>>2;
- out[2] = (in[2] + in[6] + in[row+2] + in[row+6])>>2;
- out[3] = (in[3] + in[7] + in[row+3] + in[row+7])>>2;
- }
- }
-}
-
-
-static void R_MipMapLuminanceAlpha (const byte *in, byte *out, int width, int height)
-{
- int i, j, row;
-
- if ( width == 1 && height == 1 ) {
- return;
- }
-
- row = width * 4;
- width >>= 1;
- height >>= 1;
-
- if ( width == 0 || height == 0 ) {
- width += height; // get largest
- for (i=0 ; i<width ; i++, out+=4, in+=8 ) {
- out[0] =
- out[1] =
- out[2] = (in[0] + in[4]) >> 1;
- out[3] = (in[3] + in[7]) >> 1;
- }
- return;
- }
-
- for (i=0 ; i<height ; i++, in+=row) {
- for (j=0 ; j<width ; j++, out+=4, in+=8) {
- out[0] =
- out[1] =
- out[2] = (in[0] + in[4] + in[row ] + in[row+4]) >> 2;
- out[3] = (in[3] + in[7] + in[row+3] + in[row+7]) >> 2;
- }
- }
-
-}
-
-
-static void R_MipMapNormalHeight (const byte *in, byte *out, int width, int height, qboolean swizzle)
-{
- int i, j;
- int row;
- int sx = swizzle ? 3 : 0;
- int sa = swizzle ? 0 : 3;
-
- if ( width == 1 && height == 1 ) {
- return;
- }
-
- row = width * 4;
- width >>= 1;
- height >>= 1;
-
- for (i=0 ; i<height ; i++, in+=row) {
- for (j=0 ; j<width ; j++, out+=4, in+=8) {
- vec3_t v;
-
- v[0] = OffsetByteToFloat(in[sx ]);
- v[1] = OffsetByteToFloat(in[ 1]);
- v[2] = OffsetByteToFloat(in[ 2]);
-
- v[0] += OffsetByteToFloat(in[sx +4]);
- v[1] += OffsetByteToFloat(in[ 5]);
- v[2] += OffsetByteToFloat(in[ 6]);
-
- v[0] += OffsetByteToFloat(in[sx+row ]);
- v[1] += OffsetByteToFloat(in[ row+1]);
- v[2] += OffsetByteToFloat(in[ row+2]);
-
- v[0] += OffsetByteToFloat(in[sx+row+4]);
- v[1] += OffsetByteToFloat(in[ row+5]);
- v[2] += OffsetByteToFloat(in[ row+6]);
-
- VectorNormalizeFast(v);
-
- //v[0] *= 0.25f;
- //v[1] *= 0.25f;
- //v[2] = 1.0f - v[0] * v[0] - v[1] * v[1];
- //v[2] = sqrt(MAX(v[2], 0.0f));
-
- out[sx] = FloatToOffsetByte(v[0]);
- out[1 ] = FloatToOffsetByte(v[1]);
- out[2 ] = FloatToOffsetByte(v[2]);
- out[sa] = MAX(MAX(in[sa], in[sa+4]), MAX(in[sa+row], in[sa+row+4]));
- }
- }
-}
-
-
-/*
-==================
-R_BlendOverTexture
-
-Apply a color blend over a set of pixels
-==================
-*/
-static void R_BlendOverTexture( byte *data, int pixelCount, byte blend[4] ) {
- int i;
- int inverseAlpha;
- int premult[3];
-
- inverseAlpha = 255 - blend[3];
- premult[0] = blend[0] * blend[3];
- premult[1] = blend[1] * blend[3];
- premult[2] = blend[2] * blend[3];
-
- for ( i = 0 ; i < pixelCount ; i++, data+=4 ) {
- data[0] = ( data[0] * inverseAlpha + premult[0] ) >> 9;
- data[1] = ( data[1] * inverseAlpha + premult[1] ) >> 9;
- data[2] = ( data[2] * inverseAlpha + premult[2] ) >> 9;
- }
-}
-
-byte mipBlendColors[16][4] = {
- {0,0,0,0},
- {255,0,0,128},
- {0,255,0,128},
- {0,0,255,128},
- {255,0,0,128},
- {0,255,0,128},
- {0,0,255,128},
- {255,0,0,128},
- {0,255,0,128},
- {0,0,255,128},
- {255,0,0,128},
- {0,255,0,128},
- {0,0,255,128},
- {255,0,0,128},
- {0,255,0,128},
- {0,0,255,128},
-};
-
-static void RawImage_SwizzleRA( byte *data, int width, int height )
-{
- int i;
- byte *ptr = data, swap;
-
- for (i=0; i<width*height; i++, ptr+=4)
- {
- // swap red and alpha
- swap = ptr[0];
- ptr[0] = ptr[3];
- ptr[3] = swap;
- }
-}
-
-
-/*
-===============
-RawImage_ScaleToPower2
-
-===============
-*/
-static void RawImage_ScaleToPower2( byte **data, int *inout_width, int *inout_height, int *inout_scaled_width, int *inout_scaled_height, imgType_t type, imgFlags_t flags, byte **resampledBuffer)
-{
- int width = *inout_width;
- int height = *inout_height;
- int scaled_width = *inout_scaled_width;
- int scaled_height = *inout_scaled_height;
- qboolean picmip = flags & IMGFLAG_PICMIP;
- qboolean mipmap = flags & IMGFLAG_MIPMAP;
- qboolean clampToEdge = flags & IMGFLAG_CLAMPTOEDGE;
-
- //
- // convert to exact power of 2 sizes
- //
- if (glRefConfig.textureNonPowerOfTwo && !mipmap)
- {
- scaled_width = width;
- scaled_height = height;
- }
- else
- {
- scaled_width = NextPowerOfTwo(width);
- scaled_height = NextPowerOfTwo(height);
- }
-
- if ( r_roundImagesDown->integer && scaled_width > width )
- scaled_width >>= 1;
- if ( r_roundImagesDown->integer && scaled_height > height )
- scaled_height >>= 1;
-
- if ( picmip && data && resampledBuffer && r_imageUpsample->integer &&
- scaled_width < r_imageUpsampleMaxSize->integer && scaled_height < r_imageUpsampleMaxSize->integer)
- {
- int finalwidth, finalheight;
- //int startTime, endTime;
-
- //startTime = ri.Milliseconds();
-
- finalwidth = scaled_width << r_imageUpsample->integer;
- finalheight = scaled_height << r_imageUpsample->integer;
-
- while ( finalwidth > r_imageUpsampleMaxSize->integer
- || finalheight > r_imageUpsampleMaxSize->integer ) {
- finalwidth >>= 1;
- finalheight >>= 1;
- }
-
- while ( finalwidth > glConfig.maxTextureSize
- || finalheight > glConfig.maxTextureSize ) {
- finalwidth >>= 1;
- finalheight >>= 1;
- }
-
- *resampledBuffer = ri.Hunk_AllocateTempMemory( finalwidth * finalheight * 4 );
-
- if (scaled_width != width || scaled_height != height)
- {
- ResampleTexture (*data, width, height, *resampledBuffer, scaled_width, scaled_height);
- }
- else
- {
- byte *inbyte, *outbyte;
- int i;
-
- inbyte = *data;
- outbyte = *resampledBuffer;
-
- for (i = width * height * 4; i > 0; i--)
- {
- *outbyte++ = *inbyte++;
- }
- }
-
- if (type == IMGTYPE_COLORALPHA)
- RGBAtoYCoCgA(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height);
-
- while (scaled_width < finalwidth || scaled_height < finalheight)
- {
- scaled_width <<= 1;
- scaled_height <<= 1;
-
- FCBIByBlock(*resampledBuffer, scaled_width, scaled_height, clampToEdge, (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT));
- }
-
- if (type == IMGTYPE_COLORALPHA)
- {
- YCoCgAtoRGBA(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height);
- }
- else if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT)
- {
- FillInNormalizedZ(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height);
- }
-
-
- //endTime = ri.Milliseconds();
-
- //ri.Printf(PRINT_ALL, "upsampled %dx%d to %dx%d in %dms\n", width, height, scaled_width, scaled_height, endTime - startTime);
-
- *data = *resampledBuffer;
- width = scaled_width;
- height = scaled_height;
- }
- else if ( scaled_width != width || scaled_height != height ) {
- if (data && resampledBuffer)
- {
- *resampledBuffer = ri.Hunk_AllocateTempMemory( scaled_width * scaled_height * 4 );
- ResampleTexture (*data, width, height, *resampledBuffer, scaled_width, scaled_height);
- *data = *resampledBuffer;
- }
- width = scaled_width;
- height = scaled_height;
- }
-
- //
- // perform optional picmip operation
- //
- if ( picmip ) {
- scaled_width >>= r_picmip->integer;
- scaled_height >>= r_picmip->integer;
- }
-
- //
- // clamp to minimum size
- //
- if (scaled_width < 1) {
- scaled_width = 1;
- }
- if (scaled_height < 1) {
- scaled_height = 1;
- }
-
- //
- // clamp to the current upper OpenGL limit
- // scale both axis down equally so we don't have to
- // deal with a half mip resampling
- //
- while ( scaled_width > glConfig.maxTextureSize
- || scaled_height > glConfig.maxTextureSize ) {
- scaled_width >>= 1;
- scaled_height >>= 1;
- }
-
- *inout_width = width;
- *inout_height = height;
- *inout_scaled_width = scaled_width;
- *inout_scaled_height = scaled_height;
-}
-
-
-static qboolean RawImage_HasAlpha(const byte *scan, int numPixels)
-{
- int i;
-
- if (!scan)
- return qtrue;
-
- for ( i = 0; i < numPixels; i++ )
- {
- if ( scan[i*4 + 3] != 255 )
- {
- return qtrue;
- }
- }
-
- return qfalse;
-}
-
-static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean lightMap, imgType_t type, imgFlags_t flags)
-{
- int samples = 3;
- GLenum internalFormat = GL_RGB;
- qboolean forceNoCompression = (flags & IMGFLAG_NO_COMPRESSION);
- qboolean normalmap = (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT);
-
- if(normalmap)
- {
- if ((!RawImage_HasAlpha(data, numPixels) || (type == IMGTYPE_NORMAL)) && !forceNoCompression && (glRefConfig.textureCompression & TCR_LATC))
- {
- internalFormat = GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
- }
- else
- {
- if ( !forceNoCompression && glConfig.textureCompression == TC_S3TC_ARB )
- {
- internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
- }
- else if ( r_texturebits->integer == 16 )
- {
- internalFormat = GL_RGBA4;
- }
- else if ( r_texturebits->integer == 32 )
- {
- internalFormat = GL_RGBA8;
- }
- else
- {
- internalFormat = GL_RGBA;
- }
- }
- }
- else if(lightMap)
- {
- samples = 4;
- if(r_greyscale->integer)
- internalFormat = GL_LUMINANCE;
- else
- internalFormat = GL_RGBA;
- }
- else
- {
- if (RawImage_HasAlpha(data, numPixels))
- {
- samples = 4;
- }
-
- // select proper internal format
- if ( samples == 3 )
- {
- if(r_greyscale->integer)
- {
- if(r_texturebits->integer == 16)
- internalFormat = GL_LUMINANCE8;
- else if(r_texturebits->integer == 32)
- internalFormat = GL_LUMINANCE16;
- else
- internalFormat = GL_LUMINANCE;
- }
- else
- {
- if ( !forceNoCompression && (glRefConfig.textureCompression & TCR_BPTC) )
- {
- internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
- }
- else if ( !forceNoCompression && glConfig.textureCompression == TC_S3TC_ARB )
- {
- internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
- }
- else if ( !forceNoCompression && glConfig.textureCompression == TC_S3TC )
- {
- internalFormat = GL_RGB4_S3TC;
- }
- else if ( r_texturebits->integer == 16 )
- {
- internalFormat = GL_RGB5;
- }
- else if ( r_texturebits->integer == 32 )
- {
- internalFormat = GL_RGB8;
- }
- else
- {
- internalFormat = GL_RGB;
- }
- }
- }
- else if ( samples == 4 )
- {
- if(r_greyscale->integer)
- {
- if(r_texturebits->integer == 16)
- internalFormat = GL_LUMINANCE8_ALPHA8;
- else if(r_texturebits->integer == 32)
- internalFormat = GL_LUMINANCE16_ALPHA16;
- else
- internalFormat = GL_LUMINANCE_ALPHA;
- }
- else
- {
- if ( !forceNoCompression && (glRefConfig.textureCompression & TCR_BPTC) )
- {
- internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
- }
- else if ( !forceNoCompression && glConfig.textureCompression == TC_S3TC_ARB )
- {
- internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
- }
- else if ( r_texturebits->integer == 16 )
- {
- internalFormat = GL_RGBA4;
- }
- else if ( r_texturebits->integer == 32 )
- {
- internalFormat = GL_RGBA8;
- }
- else
- {
- internalFormat = GL_RGBA;
- }
- }
- }
-
- if (glRefConfig.texture_srgb && (flags & IMGFLAG_SRGB))
- {
- switch(internalFormat)
- {
- case GL_RGB:
- internalFormat = GL_SRGB_EXT;
- break;
-
- case GL_RGB4:
- case GL_RGB5:
- case GL_RGB8:
- internalFormat = GL_SRGB8_EXT;
- break;
-
- case GL_RGBA:
- internalFormat = GL_SRGB_ALPHA_EXT;
- break;
-
- case GL_RGBA4:
- case GL_RGBA8:
- internalFormat = GL_SRGB8_ALPHA8_EXT;
- break;
-
- case GL_LUMINANCE:
- internalFormat = GL_SLUMINANCE_EXT;
- break;
-
- case GL_LUMINANCE8:
- case GL_LUMINANCE16:
- internalFormat = GL_SLUMINANCE8_EXT;
- break;
-
- case GL_LUMINANCE_ALPHA:
- internalFormat = GL_SLUMINANCE_ALPHA_EXT;
- break;
-
- case GL_LUMINANCE8_ALPHA8:
- case GL_LUMINANCE16_ALPHA16:
- internalFormat = GL_SLUMINANCE8_ALPHA8_EXT;
- break;
-
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
- break;
-
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
- break;
-
- case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
- internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB;
- break;
- }
- }
- }
-
- return internalFormat;
-}
-
-
-static void RawImage_UploadTexture( byte *data, int x, int y, int width, int height, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture )
-{
- int dataFormat, dataType;
-
- switch(internalFormat)
- {
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16_ARB:
- case GL_DEPTH_COMPONENT24_ARB:
- case GL_DEPTH_COMPONENT32_ARB:
- dataFormat = GL_DEPTH_COMPONENT;
- dataType = GL_UNSIGNED_BYTE;
- break;
- case GL_RGBA16F_ARB:
- dataFormat = GL_RGBA;
- dataType = GL_HALF_FLOAT_ARB;
- break;
- default:
- dataFormat = GL_RGBA;
- dataType = GL_UNSIGNED_BYTE;
- break;
- }
-
- if ( subtexture )
- qglTexSubImage2D( GL_TEXTURE_2D, 0, x, y, width, height, dataFormat, dataType, data );
- else
- qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, width, height, 0, dataFormat, dataType, data );
-
- if (flags & IMGFLAG_MIPMAP)
- {
- int miplevel;
-
- miplevel = 0;
- while (width > 1 || height > 1)
- {
- if (data)
- {
- if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT)
- {
- if (internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT)
- {
- R_MipMapLuminanceAlpha( data, data, width, height );
- }
- else
- {
- R_MipMapNormalHeight( data, data, width, height, qtrue);
- }
- }
- else if (flags & IMGFLAG_SRGB)
- {
- R_MipMapsRGB( data, width, height );
- }
- else
- {
- R_MipMap( data, width, height );
- }
- }
-
- width >>= 1;
- height >>= 1;
- if (width < 1)
- width = 1;
- if (height < 1)
- height = 1;
- miplevel++;
-
- if ( data && r_colorMipLevels->integer )
- R_BlendOverTexture( (byte *)data, width * height, mipBlendColors[miplevel] );
-
- if ( subtexture )
- {
- x >>= 1;
- y >>= 1;
- qglTexSubImage2D( GL_TEXTURE_2D, miplevel, x, y, width, height, dataFormat, dataType, data );
- }
- else
- {
- qglTexImage2D (GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, dataFormat, dataType, data );
- }
- }
- }
-}
-
-
-/*
-===============
-Upload32
-
-===============
-*/
-extern qboolean charSet;
-static void Upload32( byte *data, int width, int height, imgType_t type, imgFlags_t flags,
- qboolean lightMap, GLenum internalFormat, int *pUploadWidth, int *pUploadHeight)
-{
- byte *scaledBuffer = NULL;
- byte *resampledBuffer = NULL;
- int scaled_width, scaled_height;
- int i, c;
- byte *scan;
-
- RawImage_ScaleToPower2(&data, &width, &height, &scaled_width, &scaled_height, type, flags, &resampledBuffer);
-
- scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height );
-
- //
- // scan the texture for each channel's max values
- // and verify if the alpha channel is being used or not
- //
- c = width*height;
- scan = data;
-
- if( r_greyscale->integer )
- {
- for ( i = 0; i < c; i++ )
- {
- byte luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]);
- scan[i*4] = luma;
- scan[i*4 + 1] = luma;
- scan[i*4 + 2] = luma;
- }
- }
- else if( r_greyscale->value )
- {
- for ( i = 0; i < c; i++ )
- {
- float luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]);
- scan[i*4] = LERP(scan[i*4], luma, r_greyscale->value);
- scan[i*4 + 1] = LERP(scan[i*4 + 1], luma, r_greyscale->value);
- scan[i*4 + 2] = LERP(scan[i*4 + 2], luma, r_greyscale->value);
- }
- }
-
- // Convert to RGB if sRGB textures aren't supported in hardware
- if (!glRefConfig.texture_srgb && (flags & IMGFLAG_SRGB))
- {
- byte *in = data;
- int c = width * height;
- while (c--)
- {
- for (i = 0; i < 3; i++)
- {
- float x = ByteToFloat(in[i]);
- x = sRGBtoRGB(x);
- in[i] = FloatToByte(x);
- }
- in += 4;
- }
-
- // FIXME: Probably should mark the image as non-sRGB as well
- flags &= ~IMGFLAG_SRGB;
- }
-
- // normals are always swizzled
- if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT)
- {
- RawImage_SwizzleRA(data, width, height);
- }
-
- // LATC2 is only used for normals
- if (internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT)
- {
- byte *in = data;
- int c = width * height;
- while (c--)
- {
- in[0] = in[1];
- in[2] = in[1];
- in += 4;
- }
- }
-
- // copy or resample data as appropriate for first MIP level
- if ( ( scaled_width == width ) &&
- ( scaled_height == height ) ) {
- if (!(flags & IMGFLAG_MIPMAP))
- {
- RawImage_UploadTexture( data, 0, 0, scaled_width, scaled_height, internalFormat, type, flags, qfalse );
- //qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
- *pUploadWidth = scaled_width;
- *pUploadHeight = scaled_height;
-
- goto done;
- }
- Com_Memcpy (scaledBuffer, data, width*height*4);
- }
- else
- {
- // use the normal mip-mapping function to go down from here
- while ( width > scaled_width || height > scaled_height ) {
-
- if (flags & IMGFLAG_SRGB)
- {
- R_MipMapsRGB( (byte *)data, width, height );
- }
- else
- {
- R_MipMap( (byte *)data, width, height );
- }
-
- width >>= 1;
- height >>= 1;
- if ( width < 1 ) {
- width = 1;
- }
- if ( height < 1 ) {
- height = 1;
- }
- }
- Com_Memcpy( scaledBuffer, data, width * height * 4 );
- }
-
- if (!(flags & IMGFLAG_NOLIGHTSCALE))
- R_LightScaleTexture (scaledBuffer, scaled_width, scaled_height, !(flags & IMGFLAG_MIPMAP) );
-
- *pUploadWidth = scaled_width;
- *pUploadHeight = scaled_height;
-
- RawImage_UploadTexture(scaledBuffer, 0, 0, scaled_width, scaled_height, internalFormat, type, flags, qfalse);
-
-done:
-
- if (flags & IMGFLAG_MIPMAP)
- {
- if ( textureFilterAnisotropic )
- qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
- (GLint)Com_Clamp( 1, maxAnisotropy, r_ext_max_anisotropy->integer ) );
-
- qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
- qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
- }
- else
- {
- if ( textureFilterAnisotropic )
- qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 );
-
- qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- }
-
- GL_CheckErrors();
-
- if ( scaledBuffer != 0 )
- ri.Hunk_FreeTempMemory( scaledBuffer );
- if ( resampledBuffer != 0 )
- ri.Hunk_FreeTempMemory( resampledBuffer );
-}
-
-
-static void EmptyTexture( int width, int height, imgType_t type, imgFlags_t flags,
- qboolean lightMap, GLenum internalFormat, int *pUploadWidth, int *pUploadHeight )
-{
- int scaled_width, scaled_height;
-
- RawImage_ScaleToPower2(NULL, &width, &height, &scaled_width, &scaled_height, type, flags, NULL);
-
- *pUploadWidth = scaled_width;
- *pUploadHeight = scaled_height;
-
- RawImage_UploadTexture(NULL, 0, 0, scaled_width, scaled_height, internalFormat, type, flags, qfalse);
-
- if (flags & IMGFLAG_MIPMAP)
- {
- if ( textureFilterAnisotropic )
- qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
- (GLint)Com_Clamp( 1, maxAnisotropy, r_ext_max_anisotropy->integer ) );
-
- qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
- qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
- }
- else
- {
- if ( textureFilterAnisotropic )
- qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 );
-
- qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- }
-
- // Fix for sampling depth buffer on old nVidia cards
- // from http://www.idevgames.com/forums/thread-4141-post-34844.html#pid34844
- switch(internalFormat)
- {
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16_ARB:
- case GL_DEPTH_COMPONENT24_ARB:
- case GL_DEPTH_COMPONENT32_ARB:
- qglTexParameterf(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE );
- qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
- qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
- break;
- default:
- break;
- }
-
- GL_CheckErrors();
-}
-
-
-/*
-================
-R_CreateImage
-
-This is the only way any image_t are created
-================
-*/
-image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat ) {
- image_t *image;
- qboolean isLightmap = qfalse;
- long hash;
- int glWrapClampMode;
-
- if (strlen(name) >= MAX_QPATH ) {
- ri.Error (ERR_DROP, "R_CreateImage: \"%s\" is too long", name);
- }
- if ( !strncmp( name, "*lightmap", 9 ) ) {
- isLightmap = qtrue;
- }
-
- if ( tr.numImages == MAX_DRAWIMAGES ) {
- ri.Error( ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit");
- }
-
- image = tr.images[tr.numImages] = ri.Hunk_Alloc( sizeof( image_t ), h_low );
- image->texnum = 1024 + tr.numImages;
- tr.numImages++;
-
- image->type = type;
- image->flags = flags;
-
- strcpy (image->imgName, name);
-
- image->width = width;
- image->height = height;
- if (flags & IMGFLAG_CLAMPTOEDGE)
- glWrapClampMode = GL_CLAMP_TO_EDGE;
- else
- glWrapClampMode = GL_REPEAT;
-
- if (!internalFormat)
- {
- if (image->flags & IMGFLAG_CUBEMAP)
- internalFormat = GL_RGBA8;
- else
- internalFormat = RawImage_GetFormat(pic, width * height, isLightmap, image->type, image->flags);
- }
-
- image->internalFormat = internalFormat;
-
-
- // lightmaps are always allocated on TMU 1
- if ( qglActiveTextureARB && isLightmap ) {
- image->TMU = 1;
- } else {
- image->TMU = 0;
- }
-
- if ( qglActiveTextureARB ) {
- GL_SelectTexture( image->TMU );
- }
-
- if (image->flags & IMGFLAG_CUBEMAP)
- {
- GL_BindCubemap(image);
- qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
- qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-
- qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
- qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
- qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
- qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
- qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
- qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
-
- image->uploadWidth = width;
- image->uploadHeight = height;
- }
- else
- {
- GL_Bind(image);
-
- if (pic)
- {
- Upload32( pic, image->width, image->height, image->type, image->flags,
- isLightmap, image->internalFormat, &image->uploadWidth,
- &image->uploadHeight );
- }
- else
- {
- EmptyTexture(image->width, image->height, image->type, image->flags,
- isLightmap, image->internalFormat, &image->uploadWidth,
- &image->uploadHeight );
- }
-
- qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode );
- qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode );
- }
-
- GL_SelectTexture( 0 );
-
- hash = generateHashValue(name);
- image->next = hashTable[hash];
- hashTable[hash] = image;
-
- return image;
-}
-
-void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height )
-{
- byte *scaledBuffer = NULL;
- byte *resampledBuffer = NULL;
- int scaled_width, scaled_height, scaled_x, scaled_y;
- byte *data = pic;
-
- // normals are always swizzled
- if (image->type == IMGTYPE_NORMAL || image->type == IMGTYPE_NORMALHEIGHT)
- {
- RawImage_SwizzleRA(pic, width, height);
- }
-
- // LATC2 is only used for normals
- if (image->internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT)
- {
- byte *in = data;
- int c = width * height;
- while (c--)
- {
- in[0] = in[1];
- in[2] = in[1];
- in += 4;
- }
- }
-
-
- RawImage_ScaleToPower2(&pic, &width, &height, &scaled_width, &scaled_height, image->type, image->flags, &resampledBuffer);
-
- scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height );
-
- if ( qglActiveTextureARB ) {
- GL_SelectTexture( image->TMU );
- }
-
- GL_Bind(image);
-
- // copy or resample data as appropriate for first MIP level
- if ( ( scaled_width == width ) &&
- ( scaled_height == height ) ) {
- if (!(image->flags & IMGFLAG_MIPMAP))
- {
- scaled_x = x * scaled_width / width;
- scaled_y = y * scaled_height / height;
- RawImage_UploadTexture( data, scaled_x, scaled_y, scaled_width, scaled_height, image->internalFormat, image->type, image->flags, qtrue );
- //qglTexSubImage2D( GL_TEXTURE_2D, 0, scaled_x, scaled_y, scaled_width, scaled_height, GL_RGBA, GL_UNSIGNED_BYTE, data );
-
- GL_CheckErrors();
- goto done;
- }
- Com_Memcpy (scaledBuffer, data, width*height*4);
- }
- else
- {
- // use the normal mip-mapping function to go down from here
- while ( width > scaled_width || height > scaled_height ) {
-
- if (image->flags & IMGFLAG_SRGB)
- {
- R_MipMapsRGB( (byte *)data, width, height );
- }
- else
- {
- R_MipMap( (byte *)data, width, height );
- }
-
- width >>= 1;
- height >>= 1;
- x >>= 1;
- y >>= 1;
- if ( width < 1 ) {
- width = 1;
- }
- if ( height < 1 ) {
- height = 1;
- }
- }
- Com_Memcpy( scaledBuffer, data, width * height * 4 );
- }
-
- if (!(image->flags & IMGFLAG_NOLIGHTSCALE))
- R_LightScaleTexture (scaledBuffer, scaled_width, scaled_height, !(image->flags & IMGFLAG_MIPMAP) );
-
- scaled_x = x * scaled_width / width;
- scaled_y = y * scaled_height / height;
- RawImage_UploadTexture( (byte *)data, scaled_x, scaled_y, scaled_width, scaled_height, image->internalFormat, image->type, image->flags, qtrue );
-
-done:
-
- GL_SelectTexture( 0 );
-
- GL_CheckErrors();
-
- if ( scaledBuffer != 0 )
- ri.Hunk_FreeTempMemory( scaledBuffer );
- if ( resampledBuffer != 0 )
- ri.Hunk_FreeTempMemory( resampledBuffer );
-}
-
-//===================================================================
-
-typedef struct
-{
- char *ext;
- void (*ImageLoader)( const char *, unsigned char **, int *, int * );
-} imageExtToLoaderMap_t;
-
-// Note that the ordering indicates the order of preference used
-// when there are multiple images of different formats available
-static imageExtToLoaderMap_t imageLoaders[ ] =
-{
- { "tga", R_LoadTGA },
- { "jpg", R_LoadJPG },
- { "jpeg", R_LoadJPG },
- { "png", R_LoadPNG },
- { "pcx", R_LoadPCX },
- { "bmp", R_LoadBMP }
-};
-
-static int numImageLoaders = ARRAY_LEN( imageLoaders );
-
-/*
-=================
-R_LoadImage
-
-Loads any of the supported image types into a cannonical
-32 bit format.
-=================
-*/
-void R_LoadImage( const char *name, byte **pic, int *width, int *height )
-{
- qboolean orgNameFailed = qfalse;
- int orgLoader = -1;
- int i;
- char localName[ MAX_QPATH ];
- const char *ext;
- char *altName;
-
- *pic = NULL;
- *width = 0;
- *height = 0;
-
- Q_strncpyz( localName, name, MAX_QPATH );
-
- ext = COM_GetExtension( localName );
-
- if( *ext )
- {
- // Look for the correct loader and use it
- for( i = 0; i < numImageLoaders; i++ )
- {
- if( !Q_stricmp( ext, imageLoaders[ i ].ext ) )
- {
- // Load
- imageLoaders[ i ].ImageLoader( localName, pic, width, height );
- break;
- }
- }
-
- // A loader was found
- if( i < numImageLoaders )
- {
- if( *pic == NULL )
- {
- // Loader failed, most likely because the file isn't there;
- // try again without the extension
- orgNameFailed = qtrue;
- orgLoader = i;
- COM_StripExtension( name, localName, MAX_QPATH );
- }
- else
- {
- // Something loaded
- return;
- }
- }
- }
-
- // Try and find a suitable match using all
- // the image formats supported
- for( i = 0; i < numImageLoaders; i++ )
- {
- if (i == orgLoader)
- continue;
-
- altName = va( "%s.%s", localName, imageLoaders[ i ].ext );
-
- // Load
- imageLoaders[ i ].ImageLoader( altName, pic, width, height );
-
- if( *pic )
- {
- if( orgNameFailed )
- {
- ri.Printf( PRINT_DEVELOPER, "WARNING: %s not present, using %s instead\n",
- name, altName );
- }
-
- break;
- }
- }
-}
-
-
-/*
-===============
-R_FindImageFile
-
-Finds or loads the given image.
-Returns NULL if it fails, not a default image.
-==============
-*/
-image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags )
-{
- image_t *image;
- int width, height;
- byte *pic;
- long hash;
-
- if (!name) {
- return NULL;
- }
-
- hash = generateHashValue(name);
-
- //
- // see if the image is already loaded
- //
- for (image=hashTable[hash]; image; image=image->next) {
- if ( !strcmp( name, image->imgName ) ) {
- // the white image can be used with any set of parms, but other mismatches are errors
- if ( strcmp( name, "*white" ) ) {
- if ( image->flags != flags ) {
- ri.Printf( PRINT_DEVELOPER, "WARNING: reused image %s with mixed flags (%i vs %i)\n", name, image->flags, flags );
- }
- }
- return image;
- }
- }
-
- //
- // load the pic from disk
- //
- R_LoadImage( name, &pic, &width, &height );
- if ( pic == NULL ) {
- return NULL;
- }
-
- if (r_normalMapping->integer && !(type == IMGTYPE_NORMAL) && (flags & IMGFLAG_PICMIP) && (flags & IMGFLAG_MIPMAP) && (flags & IMGFLAG_GENNORMALMAP))
- {
- char normalName[MAX_QPATH];
- image_t *normalImage;
- int normalWidth, normalHeight;
- imgFlags_t normalFlags;
-
- normalFlags = (flags & ~(IMGFLAG_GENNORMALMAP | IMGFLAG_SRGB)) | IMGFLAG_NOLIGHTSCALE;
-
- COM_StripExtension(name, normalName, MAX_QPATH);
- Q_strcat(normalName, MAX_QPATH, "_n");
-
- // find normalmap in case it's there
- normalImage = R_FindImageFile(normalName, IMGTYPE_NORMAL, normalFlags);
-
- // if not, generate it
- if (normalImage == NULL)
- {
- byte *normalPic;
- int x, y;
-
- normalWidth = width;
- normalHeight = height;
- normalPic = ri.Malloc(width * height * 4);
- RGBAtoNormal(pic, normalPic, width, height, flags & IMGFLAG_CLAMPTOEDGE);
-
- // Brighten up the original image to work with the normal map
- RGBAtoYCoCgA(pic, pic, width, height);
- for (y = 0; y < height; y++)
- {
- byte *picbyte = pic + y * width * 4;
- byte *normbyte = normalPic + y * width * 4;
- for (x = 0; x < width; x++)
- {
- int div = MAX(normbyte[2] - 127, 16);
- picbyte[0] = CLAMP(picbyte[0] * 128 / div, 0, 255);
- picbyte += 4;
- normbyte += 4;
- }
- }
- YCoCgAtoRGBA(pic, pic, width, height);
-
- R_CreateImage( normalName, normalPic, normalWidth, normalHeight, IMGTYPE_NORMAL, normalFlags, 0 );
- ri.Free( normalPic );
- }
- }
-
- image = R_CreateImage( ( char * ) name, pic, width, height, type, flags, 0 );
- ri.Free( pic );
- return image;
-}
-
-
-/*
-================
-R_CreateDlightImage
-================
-*/
-#define DLIGHT_SIZE 16
-static void R_CreateDlightImage( void ) {
- int x,y;
- byte data[DLIGHT_SIZE][DLIGHT_SIZE][4];
- int b;
-
- // make a centered inverse-square falloff blob for dynamic lighting
- for (x=0 ; x<DLIGHT_SIZE ; x++) {
- for (y=0 ; y<DLIGHT_SIZE ; y++) {
- float d;
-
- d = ( DLIGHT_SIZE/2 - 0.5f - x ) * ( DLIGHT_SIZE/2 - 0.5f - x ) +
- ( DLIGHT_SIZE/2 - 0.5f - y ) * ( DLIGHT_SIZE/2 - 0.5f - y );
- b = 4000 / d;
- if (b > 255) {
- b = 255;
- } else if ( b < 75 ) {
- b = 0;
- }
- data[y][x][0] =
- data[y][x][1] =
- data[y][x][2] = b;
- data[y][x][3] = 255;
- }
- }
- tr.dlightImage = R_CreateImage("*dlight", (byte *)data, DLIGHT_SIZE, DLIGHT_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_CLAMPTOEDGE, 0 );
-}
-
-
-/*
-=================
-R_InitFogTable
-=================
-*/
-void R_InitFogTable( void ) {
- int i;
- float d;
- float exp;
-
- exp = 0.5;
-
- for ( i = 0 ; i < FOG_TABLE_SIZE ; i++ ) {
- d = pow ( (float)i/(FOG_TABLE_SIZE-1), exp );
-
- tr.fogTable[i] = d;
- }
-}
-
-/*
-================
-R_FogFactor
-
-Returns a 0.0 to 1.0 fog density value
-This is called for each texel of the fog texture on startup
-and for each vertex of transparent shaders in fog dynamically
-================
-*/
-float R_FogFactor( float s, float t ) {
- float d;
-
- s -= 1.0/512;
- if ( s < 0 ) {
- return 0;
- }
- if ( t < 1.0/32 ) {
- return 0;
- }
- if ( t < 31.0/32 ) {
- s *= (t - 1.0f/32.0f) / (30.0f/32.0f);
- }
-
- // we need to leave a lot of clamp range
- s *= 8;
-
- if ( s > 1.0 ) {
- s = 1.0;
- }
-
- d = tr.fogTable[ (int)(s * (FOG_TABLE_SIZE-1)) ];
-
- return d;
-}
-
-/*
-================
-R_CreateFogImage
-================
-*/
-#define FOG_S 256
-#define FOG_T 32
-static void R_CreateFogImage( void ) {
- int x,y;
- byte *data;
- float d;
- float borderColor[4];
-
- data = ri.Hunk_AllocateTempMemory( FOG_S * FOG_T * 4 );
-
- // S is distance, T is depth
- for (x=0 ; x<FOG_S ; x++) {
- for (y=0 ; y<FOG_T ; y++) {
- d = R_FogFactor( ( x + 0.5f ) / FOG_S, ( y + 0.5f ) / FOG_T );
-
- data[(y*FOG_S+x)*4+0] =
- data[(y*FOG_S+x)*4+1] =
- data[(y*FOG_S+x)*4+2] = 255;
- data[(y*FOG_S+x)*4+3] = 255*d;
- }
- }
- // standard openGL clamping doesn't really do what we want -- it includes
- // the border color at the edges. OpenGL 1.2 has clamp-to-edge, which does
- // what we want.
- tr.fogImage = R_CreateImage("*fog", (byte *)data, FOG_S, FOG_T, IMGTYPE_COLORALPHA, IMGFLAG_CLAMPTOEDGE, 0 );
- ri.Hunk_FreeTempMemory( data );
-
- borderColor[0] = 1.0;
- borderColor[1] = 1.0;
- borderColor[2] = 1.0;
- borderColor[3] = 1;
-
- qglTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor );
-}
-
-/*
-==================
-R_CreateDefaultImage
-==================
-*/
-#define DEFAULT_SIZE 16
-static void R_CreateDefaultImage( void ) {
- int x;
- byte data[DEFAULT_SIZE][DEFAULT_SIZE][4];
-
- // the default image will be a box, to allow you to see the mapping coordinates
- Com_Memset( data, 32, sizeof( data ) );
- for ( x = 0 ; x < DEFAULT_SIZE ; x++ ) {
- data[0][x][0] =
- data[0][x][1] =
- data[0][x][2] =
- data[0][x][3] = 255;
-
- data[x][0][0] =
- data[x][0][1] =
- data[x][0][2] =
- data[x][0][3] = 255;
-
- data[DEFAULT_SIZE-1][x][0] =
- data[DEFAULT_SIZE-1][x][1] =
- data[DEFAULT_SIZE-1][x][2] =
- data[DEFAULT_SIZE-1][x][3] = 255;
-
- data[x][DEFAULT_SIZE-1][0] =
- data[x][DEFAULT_SIZE-1][1] =
- data[x][DEFAULT_SIZE-1][2] =
- data[x][DEFAULT_SIZE-1][3] = 255;
- }
- tr.defaultImage = R_CreateImage("*default", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_MIPMAP, 0);
-}
-
-/*
-==================
-R_CreateBuiltinImages
-==================
-*/
-void R_CreateBuiltinImages( void ) {
- int x,y;
- byte data[DEFAULT_SIZE][DEFAULT_SIZE][4];
-
- R_CreateDefaultImage();
-
- // we use a solid white image instead of disabling texturing
- Com_Memset( data, 255, sizeof( data ) );
- tr.whiteImage = R_CreateImage("*white", (byte *)data, 8, 8, IMGTYPE_COLORALPHA, IMGFLAG_NONE, 0);
-
- if (r_dlightMode->integer >= 2)
- {
- for( x = 0; x < MAX_DLIGHTS; x++)
- {
- tr.shadowCubemaps[x] = R_CreateImage(va("*shadowcubemap%i", x), (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_CLAMPTOEDGE | IMGFLAG_CUBEMAP, 0);
- }
- }
-
- // with overbright bits active, we need an image which is some fraction of full color,
- // for default lightmaps, etc
- for (x=0 ; x<DEFAULT_SIZE ; x++) {
- for (y=0 ; y<DEFAULT_SIZE ; y++) {
- data[y][x][0] =
- data[y][x][1] =
- data[y][x][2] = tr.identityLightByte;
- data[y][x][3] = 255;
- }
- }
-
- tr.identityLightImage = R_CreateImage("*identityLight", (byte *)data, 8, 8, IMGTYPE_COLORALPHA, IMGFLAG_NONE, 0);
-
-
- for(x=0;x<32;x++) {
- // scratchimage is usually used for cinematic drawing
- tr.scratchImage[x] = R_CreateImage("*scratch", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_PICMIP | IMGFLAG_CLAMPTOEDGE, 0);
- }
-
- R_CreateDlightImage();
- R_CreateFogImage();
-
- if (glRefConfig.framebufferObject)
- {
- int width, height, hdrFormat;
-
- if(glRefConfig.textureNonPowerOfTwo)
- {
- width = glConfig.vidWidth;
- height = glConfig.vidHeight;
- }
- else
- {
- width = NextPowerOfTwo(glConfig.vidWidth);
- height = NextPowerOfTwo(glConfig.vidHeight);
- }
-
- hdrFormat = GL_RGBA8;
- if (r_hdr->integer && glRefConfig.framebufferObject && glRefConfig.textureFloat)
- hdrFormat = GL_RGB16F_ARB;
-
- tr.renderImage = R_CreateImage("_render", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat);
-
- if (r_drawSunRays->integer)
- tr.sunRaysImage = R_CreateImage("*sunRays", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
-
- if (r_softOverbright->integer)
- {
- int format;
-
- format = GL_RGBA8;
-
- tr.screenScratchImage = R_CreateImage("*screenScratch", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, format);
- }
-
- if (glRefConfig.framebufferObject)
- {
- tr.renderDepthImage = R_CreateImage("*renderdepth", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB);
- tr.textureDepthImage = R_CreateImage("*texturedepth", NULL, PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB);
- }
-
- {
- unsigned short sdata[4];
- void *p;
-
- if (hdrFormat == GL_RGB16F_ARB)
- {
- sdata[0] = FloatToHalf(0.0f);
- sdata[1] = FloatToHalf(0.45f);
- sdata[2] = FloatToHalf(1.0f);
- sdata[3] = FloatToHalf(1.0f);
- p = &sdata[0];
- }
- else
- {
- data[0][0][0] = 0;
- data[0][0][1] = 0.45f * 255;
- data[0][0][2] = 255;
- data[0][0][3] = 255;
- p = data;
- }
-
- tr.calcLevelsImage = R_CreateImage("*calcLevels", p, 1, 1, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat);
- tr.targetLevelsImage = R_CreateImage("*targetLevels", p, 1, 1, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat);
- tr.fixedLevelsImage = R_CreateImage("*fixedLevels", p, 1, 1, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat);
- }
-
- for (x = 0; x < 2; x++)
- {
- tr.textureScratchImage[x] = R_CreateImage(va("*textureScratch%d", x), NULL, 256, 256, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
- }
- for (x = 0; x < 2; x++)
- {
- tr.quarterImage[x] = R_CreateImage(va("*quarter%d", x), NULL, width / 2, height / 2, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
- }
-
- tr.screenShadowImage = R_CreateImage("*screenShadow", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
-
- if (r_ssao->integer)
- {
- tr.screenSsaoImage = R_CreateImage("*screenSsao", NULL, width / 2, height / 2, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
- tr.hdrDepthImage = R_CreateImage("*hdrDepth", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_INTENSITY32F_ARB);
- }
-
- for( x = 0; x < MAX_DRAWN_PSHADOWS; x++)
- {
- tr.pshadowMaps[x] = R_CreateImage(va("*shadowmap%i", x), NULL, PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8);
- }
-
- for ( x = 0; x < 3; x++)
- {
- tr.sunShadowDepthImage[x] = R_CreateImage(va("*sunshadowdepth%i", x), NULL, r_shadowMapSize->integer, r_shadowMapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB);
- }
- }
-}
-
-
-/*
-===============
-R_SetColorMappings
-===============
-*/
-void R_SetColorMappings( void ) {
- int i, j;
- float g;
- int inf;
- int shift;
-
- // setup the overbright lighting
- tr.overbrightBits = r_overBrightBits->integer;
- if ( !glConfig.deviceSupportsGamma ) {
- tr.overbrightBits = 0; // need hardware gamma for overbright
- }
-
- // never overbright in windowed mode without soft overbright
- if ( !glConfig.isFullscreen && !r_softOverbright->integer )
- {
- tr.overbrightBits = 0;
- }
-
- // never overbright with tonemapping
- if ( r_toneMap->integer && r_hdr->integer )
- {
- tr.overbrightBits = 0;
- }
-
- // allow 2 overbright bits in 24 bit, but only 1 in 16 bit
- if ( glConfig.colorBits > 16 ) {
- if ( tr.overbrightBits > 2 ) {
- tr.overbrightBits = 2;
- }
- } else {
- if ( tr.overbrightBits > 1 ) {
- tr.overbrightBits = 1;
- }
- }
- if ( tr.overbrightBits < 0 ) {
- tr.overbrightBits = 0;
- }
-
- tr.identityLight = 1.0f / ( 1 << tr.overbrightBits );
- tr.identityLightByte = 255 * tr.identityLight;
-
-
- if ( r_intensity->value <= 1 ) {
- ri.Cvar_Set( "r_intensity", "1" );
- }
-
- if ( r_gamma->value < 0.5f ) {
- ri.Cvar_Set( "r_gamma", "0.5" );
- } else if ( r_gamma->value > 3.0f ) {
- ri.Cvar_Set( "r_gamma", "3.0" );
- }
-
- g = r_gamma->value;
-
- shift = tr.overbrightBits;
-
- // no shift with soft overbright
- if (r_softOverbright->integer)
- {
- shift = 0;
- }
-
- for ( i = 0; i < 256; i++ ) {
- int i2;
-
- if (r_srgb->integer)
- {
- i2 = 255 * RGBtosRGB(i/255.0f) + 0.5f;
- }
- else
- {
- i2 = i;
- }
-
- if ( g == 1 ) {
- inf = i2;
- } else {
- inf = 255 * pow ( i2/255.0f, 1.0f / g ) + 0.5f;
- }
- inf <<= shift;
- if (inf < 0) {
- inf = 0;
- }
- if (inf > 255) {
- inf = 255;
- }
- s_gammatable[i] = inf;
- }
-
- for (i=0 ; i<256 ; i++) {
- j = i * r_intensity->value;
- if (j > 255) {
- j = 255;
- }
- s_intensitytable[i] = j;
- }
-
- if ( glConfig.deviceSupportsGamma )
- {
- GLimp_SetGamma( s_gammatable, s_gammatable, s_gammatable );
- }
-}
-
-/*
-===============
-R_InitImages
-===============
-*/
-void R_InitImages( void ) {
- Com_Memset(hashTable, 0, sizeof(hashTable));
- // build brightness translation tables
- R_SetColorMappings();
-
- // create default texture and white texture
- R_CreateBuiltinImages();
-}
-
-/*
-===============
-R_DeleteTextures
-===============
-*/
-void R_DeleteTextures( void ) {
- int i;
-
- for ( i=0; i<tr.numImages ; i++ ) {
- qglDeleteTextures( 1, &tr.images[i]->texnum );
- }
- Com_Memset( tr.images, 0, sizeof( tr.images ) );
-
- tr.numImages = 0;
-
- Com_Memset( glState.currenttextures, 0, sizeof( glState.currenttextures ) );
- if ( qglActiveTextureARB ) {
- GL_SelectTexture( 1 );
- qglBindTexture( GL_TEXTURE_2D, 0 );
- GL_SelectTexture( 0 );
- qglBindTexture( GL_TEXTURE_2D, 0 );
- } else {
- qglBindTexture( GL_TEXTURE_2D, 0 );
- }
-}
-
-/*
-============================================================================
-
-SKINS
-
-============================================================================
-*/
-
-/*
-==================
-CommaParse
-
-This is unfortunate, but the skin files aren't
-compatable with our normal parsing rules.
-==================
-*/
-static char *CommaParse( char **data_p ) {
- int c = 0, len;
- char *data;
- static char com_token[MAX_TOKEN_CHARS];
-
- data = *data_p;
- len = 0;
- com_token[0] = 0;
-
- // make sure incoming data is valid
- if ( !data ) {
- *data_p = NULL;
- return com_token;
- }
-
- while ( 1 ) {
- // skip whitespace
- while( (c = *data) <= ' ') {
- if( !c ) {
- break;
- }
- data++;
- }
-
-
- c = *data;
-
- // skip double slash comments
- if ( c == '/' && data[1] == '/' )
- {
- while (*data && *data != '\n')
- data++;
- }
- // skip /* */ comments
- else if ( c=='/' && data[1] == '*' )
- {
- while ( *data && ( *data != '*' || data[1] != '/' ) )
- {
- data++;
- }
- if ( *data )
- {
- data += 2;
- }
- }
- else
- {
- break;
- }
- }
-
- if ( c == 0 ) {
- return "";
- }
-
- // handle quoted strings
- if (c == '\"')
- {
- data++;
- while (1)
- {
- c = *data++;
- if (c=='\"' || !c)
- {
- com_token[len] = 0;
- *data_p = ( char * ) data;
- return com_token;
- }
- if (len < MAX_TOKEN_CHARS)
- {
- com_token[len] = c;
- len++;
- }
- }
- }
-
- // parse a regular word
- do
- {
- if (len < MAX_TOKEN_CHARS)
- {
- com_token[len] = c;
- len++;
- }
- data++;
- c = *data;
- } while (c>32 && c != ',' );
-
- if (len == MAX_TOKEN_CHARS)
- {
-// ri.Printf (PRINT_DEVELOPER, "Token exceeded %i chars, discarded.\n", MAX_TOKEN_CHARS);
- len = 0;
- }
- com_token[len] = 0;
-
- *data_p = ( char * ) data;
- return com_token;
-}
-
-
-/*
-===============
-RE_RegisterSkin
-
-===============
-*/
-qhandle_t RE_RegisterSkin( const char *name ) {
- qhandle_t hSkin;
- skin_t *skin;
- skinSurface_t *surf;
- union {
- char *c;
- void *v;
- } text;
- char *text_p;
- char *token;
- char surfName[MAX_QPATH];
-
- if ( !name || !name[0] ) {
- ri.Printf( PRINT_DEVELOPER, "Empty name passed to RE_RegisterSkin\n" );
- return 0;
- }
-
- if ( strlen( name ) >= MAX_QPATH ) {
- ri.Printf( PRINT_DEVELOPER, "Skin name exceeds MAX_QPATH\n" );
- return 0;
- }
-
-
- // see if the skin is already loaded
- for ( hSkin = 1; hSkin < tr.numSkins ; hSkin++ ) {
- skin = tr.skins[hSkin];
- if ( !Q_stricmp( skin->name, name ) ) {
- if( skin->numSurfaces == 0 ) {
- return 0; // default skin
- }
- return hSkin;
- }
- }
-
- // allocate a new skin
- if ( tr.numSkins == MAX_SKINS ) {
- ri.Printf( PRINT_WARNING, "WARNING: RE_RegisterSkin( '%s' ) MAX_SKINS hit\n", name );
- return 0;
- }
- tr.numSkins++;
- skin = ri.Hunk_Alloc( sizeof( skin_t ), h_low );
- tr.skins[hSkin] = skin;
- Q_strncpyz( skin->name, name, sizeof( skin->name ) );
- skin->numSurfaces = 0;
-
- R_IssuePendingRenderCommands();
-
- // If not a .skin file, load as a single shader
- if ( strcmp( name + strlen( name ) - 5, ".skin" ) ) {
- skin->numSurfaces = 1;
- skin->surfaces[0] = ri.Hunk_Alloc( sizeof(skin->surfaces[0]), h_low );
- skin->surfaces[0]->shader = R_FindShader( name, LIGHTMAP_NONE, qtrue );
- return hSkin;
- }
-
- // load and parse the skin file
- ri.FS_ReadFile( name, &text.v );
- if ( !text.c ) {
- return 0;
- }
-
- text_p = text.c;
- while ( text_p && *text_p ) {
- // get surface name
- token = CommaParse( &text_p );
- Q_strncpyz( surfName, token, sizeof( surfName ) );
-
- if ( !token[0] ) {
- break;
- }
- // lowercase the surface name so skin compares are faster
- Q_strlwr( surfName );
-
- if ( *text_p == ',' ) {
- text_p++;
- }
-
- if ( strstr( token, "tag_" ) ) {
- continue;
- }
-
- // parse the shader name
- token = CommaParse( &text_p );
-
- surf = skin->surfaces[ skin->numSurfaces ] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low );
- Q_strncpyz( surf->name, surfName, sizeof( surf->name ) );
- surf->shader = R_FindShader( token, LIGHTMAP_NONE, qtrue );
- skin->numSurfaces++;
- }
-
- ri.FS_FreeFile( text.v );
-
-
- // never let a skin have 0 shaders
- if ( skin->numSurfaces == 0 ) {
- return 0; // use default skin
- }
-
- return hSkin;
-}
-
-
-/*
-===============
-R_InitSkins
-===============
-*/
-void R_InitSkins( void ) {
- skin_t *skin;
-
- tr.numSkins = 1;
-
- // make the default skin have all default shaders
- skin = tr.skins[0] = ri.Hunk_Alloc( sizeof( skin_t ), h_low );
- Q_strncpyz( skin->name, "<default skin>", sizeof( skin->name ) );
- skin->numSurfaces = 1;
- skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces ), h_low );
- skin->surfaces[0]->shader = tr.defaultShader;
-}
-
-/*
-===============
-R_GetSkinByHandle
-===============
-*/
-skin_t *R_GetSkinByHandle( qhandle_t hSkin ) {
- if ( hSkin < 1 || hSkin >= tr.numSkins ) {
- return tr.skins[0];
- }
- return tr.skins[ hSkin ];
-}
-
-/*
-===============
-R_SkinList_f
-===============
-*/
-void R_SkinList_f( void ) {
- int i, j;
- skin_t *skin;
-
- ri.Printf (PRINT_ALL, "------------------\n");
-
- for ( i = 0 ; i < tr.numSkins ; i++ ) {
- skin = tr.skins[i];
-
- ri.Printf( PRINT_ALL, "%3i:%s\n", i, skin->name );
- for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
- ri.Printf( PRINT_ALL, " %s = %s\n",
- skin->surfaces[j]->name, skin->surfaces[j]->shader->name );
- }
- }
- ri.Printf (PRINT_ALL, "------------------\n");
-}
-
-
diff --git a/src/rend2/tr_image_bmp.c b/src/rend2/tr_image_bmp.c
deleted file mode 100644
index 707bee3b..00000000
--- a/src/rend2/tr_image_bmp.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-#include "../qcommon/q_shared.h"
-#include "../qcommon/qfiles.h"
-#include "../qcommon/qcommon.h"
-#include "../renderer/tr_public.h"
-extern refimport_t ri;
-
-typedef struct
-{
- char id[2];
- unsigned fileSize;
- unsigned reserved0;
- unsigned bitmapDataOffset;
- unsigned bitmapHeaderSize;
- unsigned width;
- unsigned height;
- unsigned short planes;
- unsigned short bitsPerPixel;
- unsigned compression;
- unsigned bitmapDataSize;
- unsigned hRes;
- unsigned vRes;
- unsigned colors;
- unsigned importantColors;
- unsigned char palette[256][4];
-} BMPHeader_t;
-
-void R_LoadBMP( const char *name, byte **pic, int *width, int *height )
-{
- int columns, rows;
- unsigned numPixels;
- byte *pixbuf;
- int row, column;
- byte *buf_p;
- byte *end;
- union {
- byte *b;
- void *v;
- } buffer;
- int length;
- BMPHeader_t bmpHeader;
- byte *bmpRGBA;
-
- *pic = NULL;
-
- if(width)
- *width = 0;
-
- if(height)
- *height = 0;
-
- //
- // load the file
- //
- length = ri.FS_ReadFile( ( char * ) name, &buffer.v);
- if (!buffer.b || length < 0) {
- return;
- }
-
- if (length < 54)
- {
- ri.Error( ERR_DROP, "LoadBMP: header too short (%s)", name );
- }
-
- buf_p = buffer.b;
- end = buffer.b + length;
-
- bmpHeader.id[0] = *buf_p++;
- bmpHeader.id[1] = *buf_p++;
- bmpHeader.fileSize = LittleLong( * ( int * ) buf_p );
- buf_p += 4;
- bmpHeader.reserved0 = LittleLong( * ( int * ) buf_p );
- buf_p += 4;
- bmpHeader.bitmapDataOffset = LittleLong( * ( int * ) buf_p );
- buf_p += 4;
- bmpHeader.bitmapHeaderSize = LittleLong( * ( int * ) buf_p );
- buf_p += 4;
- bmpHeader.width = LittleLong( * ( int * ) buf_p );
- buf_p += 4;
- bmpHeader.height = LittleLong( * ( int * ) buf_p );
- buf_p += 4;
- bmpHeader.planes = LittleShort( * ( short * ) buf_p );
- buf_p += 2;
- bmpHeader.bitsPerPixel = LittleShort( * ( short * ) buf_p );
- buf_p += 2;
- bmpHeader.compression = LittleLong( * ( int * ) buf_p );
- buf_p += 4;
- bmpHeader.bitmapDataSize = LittleLong( * ( int * ) buf_p );
- buf_p += 4;
- bmpHeader.hRes = LittleLong( * ( int * ) buf_p );
- buf_p += 4;
- bmpHeader.vRes = LittleLong( * ( int * ) buf_p );
- buf_p += 4;
- bmpHeader.colors = LittleLong( * ( int * ) buf_p );
- buf_p += 4;
- bmpHeader.importantColors = LittleLong( * ( int * ) buf_p );
- buf_p += 4;
-
- if ( bmpHeader.bitsPerPixel == 8 )
- {
- if (buf_p + sizeof(bmpHeader.palette) > end)
- ri.Error( ERR_DROP, "LoadBMP: header too short (%s)", name );
-
- Com_Memcpy( bmpHeader.palette, buf_p, sizeof( bmpHeader.palette ) );
- buf_p += sizeof(bmpHeader.palette);
- }
-
- if (buffer.b + bmpHeader.bitmapDataOffset > end)
- {
- ri.Error( ERR_DROP, "LoadBMP: invalid offset value in header (%s)", name );
- }
-
- buf_p = buffer.b + bmpHeader.bitmapDataOffset;
-
- if ( bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M' )
- {
- ri.Error( ERR_DROP, "LoadBMP: only Windows-style BMP files supported (%s)", name );
- }
- if ( bmpHeader.fileSize != length )
- {
- ri.Error( ERR_DROP, "LoadBMP: header size does not match file size (%u vs. %u) (%s)", bmpHeader.fileSize, length, name );
- }
- if ( bmpHeader.compression != 0 )
- {
- ri.Error( ERR_DROP, "LoadBMP: only uncompressed BMP files supported (%s)", name );
- }
- if ( bmpHeader.bitsPerPixel < 8 )
- {
- ri.Error( ERR_DROP, "LoadBMP: monochrome and 4-bit BMP files not supported (%s)", name );
- }
-
- switch ( bmpHeader.bitsPerPixel )
- {
- case 8:
- case 16:
- case 24:
- case 32:
- break;
- default:
- ri.Error( ERR_DROP, "LoadBMP: illegal pixel_size '%hu' in file '%s'", bmpHeader.bitsPerPixel, name );
- break;
- }
-
- columns = bmpHeader.width;
- rows = bmpHeader.height;
- if ( rows < 0 )
- rows = -rows;
- numPixels = columns * rows;
-
- if(columns <= 0 || !rows || numPixels > 0x1FFFFFFF // 4*1FFFFFFF == 0x7FFFFFFC < 0x7FFFFFFF
- || ((numPixels * 4) / columns) / 4 != rows)
- {
- ri.Error (ERR_DROP, "LoadBMP: %s has an invalid image size", name);
- }
- if(buf_p + numPixels*bmpHeader.bitsPerPixel/8 > end)
- {
- ri.Error (ERR_DROP, "LoadBMP: file truncated (%s)", name);
- }
-
- if ( width )
- *width = columns;
- if ( height )
- *height = rows;
-
- bmpRGBA = ri.Malloc( numPixels * 4 );
- *pic = bmpRGBA;
-
-
- for ( row = rows-1; row >= 0; row-- )
- {
- pixbuf = bmpRGBA + row*columns*4;
-
- for ( column = 0; column < columns; column++ )
- {
- unsigned char red, green, blue, alpha;
- int palIndex;
- unsigned short shortPixel;
-
- switch ( bmpHeader.bitsPerPixel )
- {
- case 8:
- palIndex = *buf_p++;
- *pixbuf++ = bmpHeader.palette[palIndex][2];
- *pixbuf++ = bmpHeader.palette[palIndex][1];
- *pixbuf++ = bmpHeader.palette[palIndex][0];
- *pixbuf++ = 0xff;
- break;
- case 16:
- shortPixel = * ( unsigned short * ) pixbuf;
- pixbuf += 2;
- *pixbuf++ = ( shortPixel & ( 31 << 10 ) ) >> 7;
- *pixbuf++ = ( shortPixel & ( 31 << 5 ) ) >> 2;
- *pixbuf++ = ( shortPixel & ( 31 ) ) << 3;
- *pixbuf++ = 0xff;
- break;
-
- case 24:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = 255;
- break;
- case 32:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- alpha = *buf_p++;
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = alpha;
- break;
- }
- }
- }
-
- ri.FS_FreeFile( buffer.v );
-
-}
diff --git a/src/rend2/tr_image_jpg.c b/src/rend2/tr_image_jpg.c
deleted file mode 100644
index 494b4a28..00000000
--- a/src/rend2/tr_image_jpg.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-#include "../qcommon/q_shared.h"
-#include "../qcommon/qfiles.h"
-#include "../qcommon/qcommon.h"
-#include "../renderer/tr_public.h"
-extern refimport_t ri;
-
-/*
- * Include file for users of JPEG library.
- * You will need to have included system headers that define at least
- * the typedefs FILE and size_t before you can include jpeglib.h.
- * (stdio.h is sufficient on ANSI-conforming systems.)
- * You may also wish to include "jerror.h".
- */
-
-#ifdef USE_INTERNAL_JPEG
-# define JPEG_INTERNALS
-#endif
-
-#include <jpeglib.h>
-
-#ifndef USE_INTERNAL_JPEG
-# if JPEG_LIB_VERSION < 80
-# error Need system libjpeg >= 80
-# endif
-#endif
-
-static void R_JPGErrorExit(j_common_ptr cinfo)
-{
- char buffer[JMSG_LENGTH_MAX];
-
- (*cinfo->err->format_message) (cinfo, buffer);
-
- /* Let the memory manager delete any temp files before we die */
- jpeg_destroy(cinfo);
-
- ri.Error(ERR_FATAL, "%s", buffer);
-}
-
-static void R_JPGOutputMessage(j_common_ptr cinfo)
-{
- char buffer[JMSG_LENGTH_MAX];
-
- /* Create the message */
- (*cinfo->err->format_message) (cinfo, buffer);
-
- /* Send it to stderr, adding a newline */
- ri.Printf(PRINT_ALL, "%s\n", buffer);
-}
-
-void R_LoadJPG(const char *filename, unsigned char **pic, int *width, int *height)
-{
- /* This struct contains the JPEG decompression parameters and pointers to
- * working space (which is allocated as needed by the JPEG library).
- */
- struct jpeg_decompress_struct cinfo = {NULL};
- /* We use our private extension JPEG error handler.
- * Note that this struct must live as long as the main JPEG parameter
- * struct, to avoid dangling-pointer problems.
- */
- /* This struct represents a JPEG error handler. It is declared separately
- * because applications often want to supply a specialized error handler
- * (see the second half of this file for an example). But here we just
- * take the easy way out and use the standard error handler, which will
- * print a message on stderr and call exit() if compression fails.
- * Note that this struct must live as long as the main JPEG parameter
- * struct, to avoid dangling-pointer problems.
- */
- struct jpeg_error_mgr jerr;
- /* More stuff */
- JSAMPARRAY buffer; /* Output row buffer */
- unsigned int row_stride; /* physical row width in output buffer */
- unsigned int pixelcount, memcount;
- unsigned int sindex, dindex;
- byte *out;
- int len;
- union {
- byte *b;
- void *v;
- } fbuffer;
- byte *buf;
-
- /* In this example we want to open the input file before doing anything else,
- * so that the setjmp() error recovery below can assume the file is open.
- * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
- * requires it in order to read binary files.
- */
-
- len = ri.FS_ReadFile ( ( char * ) filename, &fbuffer.v);
- if (!fbuffer.b || len < 0) {
- return;
- }
-
- /* Step 1: allocate and initialize JPEG decompression object */
-
- /* We have to set up the error handler first, in case the initialization
- * step fails. (Unlikely, but it could happen if you are out of memory.)
- * This routine fills in the contents of struct jerr, and returns jerr's
- * address which we place into the link field in cinfo.
- */
- cinfo.err = jpeg_std_error(&jerr);
- cinfo.err->error_exit = R_JPGErrorExit;
- cinfo.err->output_message = R_JPGOutputMessage;
-
- /* Now we can initialize the JPEG decompression object. */
- jpeg_create_decompress(&cinfo);
-
- /* Step 2: specify data source (eg, a file) */
-
- jpeg_mem_src(&cinfo, fbuffer.b, len);
-
- /* Step 3: read file parameters with jpeg_read_header() */
-
- (void) jpeg_read_header(&cinfo, TRUE);
- /* We can ignore the return value from jpeg_read_header since
- * (a) suspension is not possible with the stdio data source, and
- * (b) we passed TRUE to reject a tables-only JPEG file as an error.
- * See libjpeg.doc for more info.
- */
-
- /* Step 4: set parameters for decompression */
-
- /*
- * Make sure it always converts images to RGB color space. This will
- * automatically convert 8-bit greyscale images to RGB as well.
- */
- cinfo.out_color_space = JCS_RGB;
-
- /* Step 5: Start decompressor */
-
- (void) jpeg_start_decompress(&cinfo);
- /* We can ignore the return value since suspension is not possible
- * with the stdio data source.
- */
-
- /* We may need to do some setup of our own at this point before reading
- * the data. After jpeg_start_decompress() we have the correct scaled
- * output image dimensions available, as well as the output colormap
- * if we asked for color quantization.
- * In this example, we need to make an output work buffer of the right size.
- */
- /* JSAMPLEs per row in output buffer */
-
- pixelcount = cinfo.output_width * cinfo.output_height;
-
- if(!cinfo.output_width || !cinfo.output_height
- || ((pixelcount * 4) / cinfo.output_width) / 4 != cinfo.output_height
- || pixelcount > 0x1FFFFFFF || cinfo.output_components != 3
- )
- {
- // Free the memory to make sure we don't leak memory
- ri.FS_FreeFile (fbuffer.v);
- jpeg_destroy_decompress(&cinfo);
-
- ri.Error(ERR_DROP, "LoadJPG: %s has an invalid image format: %dx%d*4=%d, components: %d", filename,
- cinfo.output_width, cinfo.output_height, pixelcount * 4, cinfo.output_components);
- }
-
- memcount = pixelcount * 4;
- row_stride = cinfo.output_width * cinfo.output_components;
-
- out = ri.Malloc(memcount);
-
- *width = cinfo.output_width;
- *height = cinfo.output_height;
-
- /* Step 6: while (scan lines remain to be read) */
- /* jpeg_read_scanlines(...); */
-
- /* Here we use the library's state variable cinfo.output_scanline as the
- * loop counter, so that we don't have to keep track ourselves.
- */
- while (cinfo.output_scanline < cinfo.output_height) {
- /* jpeg_read_scanlines expects an array of pointers to scanlines.
- * Here the array is only one element long, but you could ask for
- * more than one scanline at a time if that's more convenient.
- */
- buf = ((out+(row_stride*cinfo.output_scanline)));
- buffer = &buf;
- (void) jpeg_read_scanlines(&cinfo, buffer, 1);
- }
-
- buf = out;
-
- // Expand from RGB to RGBA
- sindex = pixelcount * cinfo.output_components;
- dindex = memcount;
-
- do
- {
- buf[--dindex] = 255;
- buf[--dindex] = buf[--sindex];
- buf[--dindex] = buf[--sindex];
- buf[--dindex] = buf[--sindex];
- } while(sindex);
-
- *pic = out;
-
- /* Step 7: Finish decompression */
-
- jpeg_finish_decompress(&cinfo);
- /* We can ignore the return value since suspension is not possible
- * with the stdio data source.
- */
-
- /* Step 8: Release JPEG decompression object */
-
- /* This is an important step since it will release a good deal of memory. */
- jpeg_destroy_decompress(&cinfo);
-
- /* After finish_decompress, we can close the input file.
- * Here we postpone it until after no more JPEG errors are possible,
- * so as to simplify the setjmp error logic above. (Actually, I don't
- * think that jpeg_destroy can do an error exit, but why assume anything...)
- */
- ri.FS_FreeFile (fbuffer.v);
-
- /* At this point you may want to check to see whether any corrupt-data
- * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
- */
-
- /* And we're done! */
-}
-
-
-/* Expanded data destination object for stdio output */
-
-typedef struct {
- struct jpeg_destination_mgr pub; /* public fields */
-
- byte* outfile; /* target stream */
- int size;
-} my_destination_mgr;
-
-typedef my_destination_mgr * my_dest_ptr;
-
-
-/*
- * Initialize destination --- called by jpeg_start_compress
- * before any data is actually written.
- */
-
-static void
-init_destination (j_compress_ptr cinfo)
-{
- my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
-
- dest->pub.next_output_byte = dest->outfile;
- dest->pub.free_in_buffer = dest->size;
-}
-
-
-/*
- * Empty the output buffer --- called whenever buffer fills up.
- *
- * In typical applications, this should write the entire output buffer
- * (ignoring the current state of next_output_byte & free_in_buffer),
- * reset the pointer & count to the start of the buffer, and return TRUE
- * indicating that the buffer has been dumped.
- *
- * In applications that need to be able to suspend compression due to output
- * overrun, a FALSE return indicates that the buffer cannot be emptied now.
- * In this situation, the compressor will return to its caller (possibly with
- * an indication that it has not accepted all the supplied scanlines). The
- * application should resume compression after it has made more room in the
- * output buffer. Note that there are substantial restrictions on the use of
- * suspension --- see the documentation.
- *
- * When suspending, the compressor will back up to a convenient restart point
- * (typically the start of the current MCU). next_output_byte & free_in_buffer
- * indicate where the restart point will be if the current call returns FALSE.
- * Data beyond this point will be regenerated after resumption, so do not
- * write it out when emptying the buffer externally.
- */
-
-static boolean
-empty_output_buffer (j_compress_ptr cinfo)
-{
- my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
-
- jpeg_destroy_compress(cinfo);
-
- // Make crash fatal or we would probably leak memory.
- ri.Error(ERR_FATAL, "Output buffer for encoded JPEG image has insufficient size of %d bytes",
- dest->size);
-
- return FALSE;
-}
-
-/*
- * Terminate destination --- called by jpeg_finish_compress
- * after all data has been written. Usually needs to flush buffer.
- *
- * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
- * application must deal with any cleanup that should happen even
- * for error exit.
- */
-
-static void term_destination(j_compress_ptr cinfo)
-{
-}
-
-
-/*
- * Prepare for output to a stdio stream.
- * The caller must have already opened the stream, and is responsible
- * for closing it after finishing compression.
- */
-
-static void
-jpegDest (j_compress_ptr cinfo, byte* outfile, int size)
-{
- my_dest_ptr dest;
-
- /* The destination object is made permanent so that multiple JPEG images
- * can be written to the same file without re-executing jpeg_stdio_dest.
- * This makes it dangerous to use this manager and a different destination
- * manager serially with the same JPEG object, because their private object
- * sizes may be different. Caveat programmer.
- */
- if (cinfo->dest == NULL) { /* first time for this JPEG object? */
- cinfo->dest = (struct jpeg_destination_mgr *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
- sizeof(my_destination_mgr));
- }
-
- dest = (my_dest_ptr) cinfo->dest;
- dest->pub.init_destination = init_destination;
- dest->pub.empty_output_buffer = empty_output_buffer;
- dest->pub.term_destination = term_destination;
- dest->outfile = outfile;
- dest->size = size;
-}
-
-/*
-=================
-SaveJPGToBuffer
-
-Encodes JPEG from image in image_buffer and writes to buffer.
-Expects RGB input data
-=================
-*/
-size_t RE_SaveJPGToBuffer(byte *buffer, size_t bufSize, int quality,
- int image_width, int image_height, byte *image_buffer, int padding)
-{
- struct jpeg_compress_struct cinfo;
- struct jpeg_error_mgr jerr;
- JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
- my_dest_ptr dest;
- int row_stride; /* physical row width in image buffer */
- size_t outcount;
-
- /* Step 1: allocate and initialize JPEG compression object */
- cinfo.err = jpeg_std_error(&jerr);
- cinfo.err->error_exit = R_JPGErrorExit;
- cinfo.err->output_message = R_JPGOutputMessage;
-
- /* Now we can initialize the JPEG compression object. */
- jpeg_create_compress(&cinfo);
-
- /* Step 2: specify data destination (eg, a file) */
- /* Note: steps 2 and 3 can be done in either order. */
- jpegDest(&cinfo, buffer, bufSize);
-
- /* Step 3: set parameters for compression */
- cinfo.image_width = image_width; /* image width and height, in pixels */
- cinfo.image_height = image_height;
- cinfo.input_components = 3; /* # of color components per pixel */
- cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
-
- jpeg_set_defaults(&cinfo);
- jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
- /* If quality is set high, disable chroma subsampling */
- if (quality >= 85) {
- cinfo.comp_info[0].h_samp_factor = 1;
- cinfo.comp_info[0].v_samp_factor = 1;
- }
-
- /* Step 4: Start compressor */
- jpeg_start_compress(&cinfo, TRUE);
-
- /* Step 5: while (scan lines remain to be written) */
- /* jpeg_write_scanlines(...); */
- row_stride = image_width * cinfo.input_components + padding; /* JSAMPLEs per row in image_buffer */
-
- while (cinfo.next_scanline < cinfo.image_height) {
- /* jpeg_write_scanlines expects an array of pointers to scanlines.
- * Here the array is only one element long, but you could pass
- * more than one scanline at a time if that's more convenient.
- */
- row_pointer[0] = &image_buffer[((cinfo.image_height-1)*row_stride)-cinfo.next_scanline * row_stride];
- (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
- }
-
- /* Step 6: Finish compression */
- jpeg_finish_compress(&cinfo);
-
- dest = (my_dest_ptr) cinfo.dest;
- outcount = dest->size - dest->pub.free_in_buffer;
-
- /* Step 7: release JPEG compression object */
- jpeg_destroy_compress(&cinfo);
-
- /* And we're done! */
- return outcount;
-}
-
-void RE_SaveJPG(char * filename, int quality, int image_width, int image_height, byte *image_buffer, int padding)
-{
- byte *out;
- size_t bufSize;
-
- bufSize = image_width * image_height * 3;
- out = ri.Hunk_AllocateTempMemory(bufSize);
-
- bufSize = RE_SaveJPGToBuffer(out, bufSize, quality, image_width, image_height, image_buffer, padding);
- ri.FS_WriteFile(filename, out, bufSize);
-
- ri.Hunk_FreeTempMemory(out);
-}
diff --git a/src/rend2/tr_image_pcx.c b/src/rend2/tr_image_pcx.c
deleted file mode 100644
index d4dd575d..00000000
--- a/src/rend2/tr_image_pcx.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
- 2008 Ludwig Nussel
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-#include "../qcommon/q_shared.h"
-#include "../qcommon/qfiles.h"
-#include "../qcommon/qcommon.h"
-#include "../renderer/tr_public.h"
-extern refimport_t ri;
-
-/*
-========================================================================
-
-PCX files are used for 8 bit images
-
-========================================================================
-*/
-
-typedef struct {
- char manufacturer;
- char version;
- char encoding;
- char bits_per_pixel;
- unsigned short xmin,ymin,xmax,ymax;
- unsigned short hres,vres;
- unsigned char palette[48];
- char reserved;
- char color_planes;
- unsigned short bytes_per_line;
- unsigned short palette_type;
- unsigned short hscreensize, vscreensize;
- char filler[54];
- unsigned char data[];
-} pcx_t;
-
-void R_LoadPCX ( const char *filename, byte **pic, int *width, int *height)
-{
- union {
- byte *b;
- void *v;
- } raw;
- byte *end;
- pcx_t *pcx;
- int len;
- unsigned char dataByte = 0, runLength = 0;
- byte *out, *pix;
- unsigned short w, h;
- byte *pic8;
- byte *palette;
- int i;
- unsigned size = 0;
-
- if (width)
- *width = 0;
- if (height)
- *height = 0;
- *pic = NULL;
-
- //
- // load the file
- //
- len = ri.FS_ReadFile( ( char * ) filename, &raw.v);
- if (!raw.b || len < 0) {
- return;
- }
-
- if((unsigned)len < sizeof(pcx_t))
- {
- ri.Printf (PRINT_ALL, "PCX truncated: %s\n", filename);
- ri.FS_FreeFile (raw.v);
- return;
- }
-
- //
- // parse the PCX file
- //
- pcx = (pcx_t *)raw.b;
- end = raw.b+len;
-
- w = LittleShort(pcx->xmax)+1;
- h = LittleShort(pcx->ymax)+1;
- size = w*h;
-
- if (pcx->manufacturer != 0x0a
- || pcx->version != 5
- || pcx->encoding != 1
- || pcx->color_planes != 1
- || pcx->bits_per_pixel != 8
- || w >= 1024
- || h >= 1024)
- {
- ri.Printf (PRINT_ALL, "Bad or unsupported pcx file %s (%dx%d@%d)\n", filename, w, h, pcx->bits_per_pixel);
- return;
- }
-
- pix = pic8 = ri.Malloc ( size );
-
- raw.b = pcx->data;
- // FIXME: should use bytes_per_line but original q3 didn't do that either
- while(pix < pic8+size)
- {
- if(runLength > 0) {
- *pix++ = dataByte;
- --runLength;
- continue;
- }
-
- if(raw.b+1 > end)
- break;
- dataByte = *raw.b++;
-
- if((dataByte & 0xC0) == 0xC0)
- {
- if(raw.b+1 > end)
- break;
- runLength = dataByte & 0x3F;
- dataByte = *raw.b++;
- }
- else
- runLength = 1;
- }
-
- if(pix < pic8+size)
- {
- ri.Printf (PRINT_ALL, "PCX file truncated: %s\n", filename);
- ri.FS_FreeFile (pcx);
- ri.Free (pic8);
- }
-
- if (raw.b-(byte*)pcx >= end - (byte*)769 || end[-769] != 0x0c)
- {
- ri.Printf (PRINT_ALL, "PCX missing palette: %s\n", filename);
- ri.FS_FreeFile (pcx);
- ri.Free (pic8);
- return;
- }
-
- palette = end-768;
-
- pix = out = ri.Malloc(4 * size );
- for (i = 0 ; i < size ; i++)
- {
- unsigned char p = pic8[i];
- pix[0] = palette[p*3];
- pix[1] = palette[p*3 + 1];
- pix[2] = palette[p*3 + 2];
- pix[3] = 255;
- pix += 4;
- }
-
- if (width)
- *width = w;
- if (height)
- *height = h;
-
- *pic = out;
-
- ri.FS_FreeFile (pcx);
- ri.Free (pic8);
-}
diff --git a/src/rend2/tr_image_png.c b/src/rend2/tr_image_png.c
deleted file mode 100644
index ee37aa75..00000000
--- a/src/rend2/tr_image_png.c
+++ /dev/null
@@ -1,2490 +0,0 @@
-/*
-===========================================================================
-ioquake3 png decoder
-Copyright (C) 2007,2008 Joerg Dietrich
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-===========================================================================
-*/
-
-#include "../qcommon/q_shared.h"
-#include "../qcommon/qfiles.h"
-#include "../qcommon/qcommon.h"
-#include "../renderer/tr_public.h"
-extern refimport_t ri;
-
-#include "../qcommon/puff.h"
-
-// we could limit the png size to a lower value here
-#ifndef INT_MAX
-#define INT_MAX 0x1fffffff
-#endif
-
-/*
-=================
-PNG LOADING
-=================
-*/
-
-/*
- * Quake 3 image format : RGBA
- */
-
-#define Q3IMAGE_BYTESPERPIXEL (4)
-
-/*
- * PNG specifications
- */
-
-/*
- * The first 8 Bytes of every PNG-File are a fixed signature
- * to identify the file as a PNG.
- */
-
-#define PNG_Signature "\x89\x50\x4E\x47\xD\xA\x1A\xA"
-#define PNG_Signature_Size (8)
-
-/*
- * After the signature diverse chunks follow.
- * A chunk consists of a header and if Length
- * is bigger than 0 a body and a CRC of the body follow.
- */
-
-struct PNG_ChunkHeader
-{
- uint32_t Length;
- uint32_t Type;
-};
-
-#define PNG_ChunkHeader_Size (8)
-
-typedef uint32_t PNG_ChunkCRC;
-
-#define PNG_ChunkCRC_Size (4)
-
-/*
- * We use the following ChunkTypes.
- * All others are ignored.
- */
-
-#define MAKE_CHUNKTYPE(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | ((d)))
-
-#define PNG_ChunkType_IHDR MAKE_CHUNKTYPE('I', 'H', 'D', 'R')
-#define PNG_ChunkType_PLTE MAKE_CHUNKTYPE('P', 'L', 'T', 'E')
-#define PNG_ChunkType_IDAT MAKE_CHUNKTYPE('I', 'D', 'A', 'T')
-#define PNG_ChunkType_IEND MAKE_CHUNKTYPE('I', 'E', 'N', 'D')
-#define PNG_ChunkType_tRNS MAKE_CHUNKTYPE('t', 'R', 'N', 'S')
-
-/*
- * Per specification the first chunk after the signature SHALL be IHDR.
- */
-
-struct PNG_Chunk_IHDR
-{
- uint32_t Width;
- uint32_t Height;
- uint8_t BitDepth;
- uint8_t ColourType;
- uint8_t CompressionMethod;
- uint8_t FilterMethod;
- uint8_t InterlaceMethod;
-};
-
-#define PNG_Chunk_IHDR_Size (13)
-
-/*
- * ColourTypes
- */
-
-#define PNG_ColourType_Grey (0)
-#define PNG_ColourType_True (2)
-#define PNG_ColourType_Indexed (3)
-#define PNG_ColourType_GreyAlpha (4)
-#define PNG_ColourType_TrueAlpha (6)
-
-/*
- * number of colour components
- *
- * Grey : 1 grey
- * True : 1 R, 1 G, 1 B
- * Indexed : 1 index
- * GreyAlpha : 1 grey, 1 alpha
- * TrueAlpha : 1 R, 1 G, 1 B, 1 alpha
- */
-
-#define PNG_NumColourComponents_Grey (1)
-#define PNG_NumColourComponents_True (3)
-#define PNG_NumColourComponents_Indexed (1)
-#define PNG_NumColourComponents_GreyAlpha (2)
-#define PNG_NumColourComponents_TrueAlpha (4)
-
-/*
- * For the different ColourTypes
- * different BitDepths are specified.
- */
-
-#define PNG_BitDepth_1 ( 1)
-#define PNG_BitDepth_2 ( 2)
-#define PNG_BitDepth_4 ( 4)
-#define PNG_BitDepth_8 ( 8)
-#define PNG_BitDepth_16 (16)
-
-/*
- * Only one valid CompressionMethod is standardized.
- */
-
-#define PNG_CompressionMethod_0 (0)
-
-/*
- * Only one valid FilterMethod is currently standardized.
- */
-
-#define PNG_FilterMethod_0 (0)
-
-/*
- * This FilterMethod defines 5 FilterTypes
- */
-
-#define PNG_FilterType_None (0)
-#define PNG_FilterType_Sub (1)
-#define PNG_FilterType_Up (2)
-#define PNG_FilterType_Average (3)
-#define PNG_FilterType_Paeth (4)
-
-/*
- * Two InterlaceMethods are standardized :
- * 0 - NonInterlaced
- * 1 - Interlaced
- */
-
-#define PNG_InterlaceMethod_NonInterlaced (0)
-#define PNG_InterlaceMethod_Interlaced (1)
-
-/*
- * The Adam7 interlace method uses 7 passes.
- */
-
-#define PNG_Adam7_NumPasses (7)
-
-/*
- * The compressed data starts with a header ...
- */
-
-struct PNG_ZlibHeader
-{
- uint8_t CompressionMethod;
- uint8_t Flags;
-};
-
-#define PNG_ZlibHeader_Size (2)
-
-/*
- * ... and is followed by a check value
- */
-
-#define PNG_ZlibCheckValue_Size (4)
-
-/*
- * Some support functions for buffered files follow.
- */
-
-/*
- * buffered file representation
- */
-
-struct BufferedFile
-{
- byte *Buffer;
- int Length;
- byte *Ptr;
- int BytesLeft;
-};
-
-/*
- * Read a file into a buffer.
- */
-
-static struct BufferedFile *ReadBufferedFile(const char *name)
-{
- struct BufferedFile *BF;
- union {
- byte *b;
- void *v;
- } buffer;
-
- /*
- * input verification
- */
-
- if(!name)
- {
- return(NULL);
- }
-
- /*
- * Allocate control struct.
- */
-
- BF = ri.Malloc(sizeof(struct BufferedFile));
- if(!BF)
- {
- return(NULL);
- }
-
- /*
- * Initialize the structs components.
- */
-
- BF->Length = 0;
- BF->Buffer = NULL;
- BF->Ptr = NULL;
- BF->BytesLeft = 0;
-
- /*
- * Read the file.
- */
-
- BF->Length = ri.FS_ReadFile((char *) name, &buffer.v);
- BF->Buffer = buffer.b;
-
- /*
- * Did we get it? Is it big enough?
- */
-
- if(!(BF->Buffer && (BF->Length > 0)))
- {
- ri.Free(BF);
-
- return(NULL);
- }
-
- /*
- * Set the pointers and counters.
- */
-
- BF->Ptr = BF->Buffer;
- BF->BytesLeft = BF->Length;
-
- return(BF);
-}
-
-/*
- * Close a buffered file.
- */
-
-static void CloseBufferedFile(struct BufferedFile *BF)
-{
- if(BF)
- {
- if(BF->Buffer)
- {
- ri.FS_FreeFile(BF->Buffer);
- }
-
- ri.Free(BF);
- }
-}
-
-/*
- * Get a pointer to the requested bytes.
- */
-
-static void *BufferedFileRead(struct BufferedFile *BF, unsigned Length)
-{
- void *RetVal;
-
- /*
- * input verification
- */
-
- if(!(BF && Length))
- {
- return(NULL);
- }
-
- /*
- * not enough bytes left
- */
-
- if(Length > BF->BytesLeft)
- {
- return(NULL);
- }
-
- /*
- * the pointer to the requested data
- */
-
- RetVal = BF->Ptr;
-
- /*
- * Raise the pointer and counter.
- */
-
- BF->Ptr += Length;
- BF->BytesLeft -= Length;
-
- return(RetVal);
-}
-
-/*
- * Rewind the buffer.
- */
-
-static qboolean BufferedFileRewind(struct BufferedFile *BF, unsigned Offset)
-{
- unsigned BytesRead;
-
- /*
- * input verification
- */
-
- if(!BF)
- {
- return(qfalse);
- }
-
- /*
- * special trick to rewind to the beginning of the buffer
- */
-
- if(Offset == (unsigned)-1)
- {
- BF->Ptr = BF->Buffer;
- BF->BytesLeft = BF->Length;
-
- return(qtrue);
- }
-
- /*
- * How many bytes do we have already read?
- */
-
- BytesRead = BF->Ptr - BF->Buffer;
-
- /*
- * We can only rewind to the beginning of the BufferedFile.
- */
-
- if(Offset > BytesRead)
- {
- return(qfalse);
- }
-
- /*
- * lower the pointer and counter.
- */
-
- BF->Ptr -= Offset;
- BF->BytesLeft += Offset;
-
- return(qtrue);
-}
-
-/*
- * Skip some bytes.
- */
-
-static qboolean BufferedFileSkip(struct BufferedFile *BF, unsigned Offset)
-{
- /*
- * input verification
- */
-
- if(!BF)
- {
- return(qfalse);
- }
-
- /*
- * We can only skip to the end of the BufferedFile.
- */
-
- if(Offset > BF->BytesLeft)
- {
- return(qfalse);
- }
-
- /*
- * lower the pointer and counter.
- */
-
- BF->Ptr += Offset;
- BF->BytesLeft -= Offset;
-
- return(qtrue);
-}
-
-/*
- * Find a chunk
- */
-
-static qboolean FindChunk(struct BufferedFile *BF, uint32_t ChunkType)
-{
- struct PNG_ChunkHeader *CH;
-
- uint32_t Length;
- uint32_t Type;
-
- /*
- * input verification
- */
-
- if(!BF)
- {
- return(qfalse);
- }
-
- /*
- * cycle trough the chunks
- */
-
- while(qtrue)
- {
- /*
- * Read the chunk-header.
- */
-
- CH = BufferedFileRead(BF, PNG_ChunkHeader_Size);
- if(!CH)
- {
- return(qfalse);
- }
-
- /*
- * Do not swap the original types
- * they might be needed later.
- */
-
- Length = BigLong(CH->Length);
- Type = BigLong(CH->Type);
-
- /*
- * We found it!
- */
-
- if(Type == ChunkType)
- {
- /*
- * Rewind to the start of the chunk.
- */
-
- BufferedFileRewind(BF, PNG_ChunkHeader_Size);
-
- break;
- }
- else
- {
- /*
- * Skip the rest of the chunk.
- */
-
- if(Length)
- {
- if(!BufferedFileSkip(BF, Length + PNG_ChunkCRC_Size))
- {
- return(qfalse);
- }
- }
- }
- }
-
- return(qtrue);
-}
-
-/*
- * Decompress all IDATs
- */
-
-static uint32_t DecompressIDATs(struct BufferedFile *BF, uint8_t **Buffer)
-{
- uint8_t *DecompressedData;
- uint32_t DecompressedDataLength;
-
- uint8_t *CompressedData;
- uint8_t *CompressedDataPtr;
- uint32_t CompressedDataLength;
-
- struct PNG_ChunkHeader *CH;
-
- uint32_t Length;
- uint32_t Type;
-
- int BytesToRewind;
-
- int32_t puffResult;
- uint8_t *puffDest;
- uint32_t puffDestLen;
- uint8_t *puffSrc;
- uint32_t puffSrcLen;
-
- /*
- * input verification
- */
-
- if(!(BF && Buffer))
- {
- return(-1);
- }
-
- /*
- * some zeroing
- */
-
- DecompressedData = NULL;
- DecompressedDataLength = 0;
- *Buffer = DecompressedData;
-
- CompressedData = NULL;
- CompressedDataLength = 0;
-
- BytesToRewind = 0;
-
- /*
- * Find the first IDAT chunk.
- */
-
- if(!FindChunk(BF, PNG_ChunkType_IDAT))
- {
- return(-1);
- }
-
- /*
- * Count the size of the uncompressed data
- */
-
- while(qtrue)
- {
- /*
- * Read chunk header
- */
-
- CH = BufferedFileRead(BF, PNG_ChunkHeader_Size);
- if(!CH)
- {
- /*
- * Rewind to the start of this adventure
- * and return unsuccessfull
- */
-
- BufferedFileRewind(BF, BytesToRewind);
-
- return(-1);
- }
-
- /*
- * Length and Type of chunk
- */
-
- Length = BigLong(CH->Length);
- Type = BigLong(CH->Type);
-
- /*
- * We have reached the end of the IDAT chunks
- */
-
- if(!(Type == PNG_ChunkType_IDAT))
- {
- BufferedFileRewind(BF, PNG_ChunkHeader_Size);
-
- break;
- }
-
- /*
- * Add chunk header to count.
- */
-
- BytesToRewind += PNG_ChunkHeader_Size;
-
- /*
- * Skip to next chunk
- */
-
- if(Length)
- {
- if(!BufferedFileSkip(BF, Length + PNG_ChunkCRC_Size))
- {
- BufferedFileRewind(BF, BytesToRewind);
-
- return(-1);
- }
-
- BytesToRewind += Length + PNG_ChunkCRC_Size;
- CompressedDataLength += Length;
- }
- }
-
- BufferedFileRewind(BF, BytesToRewind);
-
- CompressedData = ri.Malloc(CompressedDataLength);
- if(!CompressedData)
- {
- return(-1);
- }
-
- CompressedDataPtr = CompressedData;
-
- /*
- * Collect the compressed Data
- */
-
- while(qtrue)
- {
- /*
- * Read chunk header
- */
-
- CH = BufferedFileRead(BF, PNG_ChunkHeader_Size);
- if(!CH)
- {
- ri.Free(CompressedData);
-
- return(-1);
- }
-
- /*
- * Length and Type of chunk
- */
-
- Length = BigLong(CH->Length);
- Type = BigLong(CH->Type);
-
- /*
- * We have reached the end of the IDAT chunks
- */
-
- if(!(Type == PNG_ChunkType_IDAT))
- {
- BufferedFileRewind(BF, PNG_ChunkHeader_Size);
-
- break;
- }
-
- /*
- * Copy the Data
- */
-
- if(Length)
- {
- uint8_t *OrigCompressedData;
-
- OrigCompressedData = BufferedFileRead(BF, Length);
- if(!OrigCompressedData)
- {
- ri.Free(CompressedData);
-
- return(-1);
- }
-
- if(!BufferedFileSkip(BF, PNG_ChunkCRC_Size))
- {
- ri.Free(CompressedData);
-
- return(-1);
- }
-
- memcpy(CompressedDataPtr, OrigCompressedData, Length);
- CompressedDataPtr += Length;
- }
- }
-
- /*
- * Let puff() calculate the decompressed data length.
- */
-
- puffDest = NULL;
- puffDestLen = 0;
-
- /*
- * The zlib header and checkvalue don't belong to the compressed data.
- */
-
- puffSrc = CompressedData + PNG_ZlibHeader_Size;
- puffSrcLen = CompressedDataLength - PNG_ZlibHeader_Size - PNG_ZlibCheckValue_Size;
-
- /*
- * first puff() to calculate the size of the uncompressed data
- */
-
- puffResult = puff(puffDest, &puffDestLen, puffSrc, &puffSrcLen);
- if(!((puffResult == 0) && (puffDestLen > 0)))
- {
- ri.Free(CompressedData);
-
- return(-1);
- }
-
- /*
- * Allocate the buffer for the uncompressed data.
- */
-
- DecompressedData = ri.Malloc(puffDestLen);
- if(!DecompressedData)
- {
- ri.Free(CompressedData);
-
- return(-1);
- }
-
- /*
- * Set the input again in case something was changed by the last puff() .
- */
-
- puffDest = DecompressedData;
- puffSrc = CompressedData + PNG_ZlibHeader_Size;
- puffSrcLen = CompressedDataLength - PNG_ZlibHeader_Size - PNG_ZlibCheckValue_Size;
-
- /*
- * decompression puff()
- */
-
- puffResult = puff(puffDest, &puffDestLen, puffSrc, &puffSrcLen);
-
- /*
- * The compressed data is not needed anymore.
- */
-
- ri.Free(CompressedData);
-
- /*
- * Check if the last puff() was successfull.
- */
-
- if(!((puffResult == 0) && (puffDestLen > 0)))
- {
- ri.Free(DecompressedData);
-
- return(-1);
- }
-
- /*
- * Set the output of this function.
- */
-
- DecompressedDataLength = puffDestLen;
- *Buffer = DecompressedData;
-
- return(DecompressedDataLength);
-}
-
-/*
- * the Paeth predictor
- */
-
-static uint8_t PredictPaeth(uint8_t a, uint8_t b, uint8_t c)
-{
- /*
- * a == Left
- * b == Up
- * c == UpLeft
- */
-
- uint8_t Pr;
- int p;
- int pa, pb, pc;
-
- p = ((int) a) + ((int) b) - ((int) c);
- pa = abs(p - ((int) a));
- pb = abs(p - ((int) b));
- pc = abs(p - ((int) c));
-
- if((pa <= pb) && (pa <= pc))
- {
- Pr = a;
- }
- else if(pb <= pc)
- {
- Pr = b;
- }
- else
- {
- Pr = c;
- }
-
- return(Pr);
-
-}
-
-/*
- * Reverse the filters.
- */
-
-static qboolean UnfilterImage(uint8_t *DecompressedData,
- uint32_t ImageHeight,
- uint32_t BytesPerScanline,
- uint32_t BytesPerPixel)
-{
- uint8_t *DecompPtr;
- uint8_t FilterType;
- uint8_t *PixelLeft, *PixelUp, *PixelUpLeft;
- uint32_t w, h, p;
-
- /*
- * some zeros for the filters
- */
-
- uint8_t Zeros[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-
- /*
- * input verification
- */
-
- if(!(DecompressedData && BytesPerPixel))
- {
- return(qfalse);
- }
-
- /*
- * ImageHeight and BytesPerScanline can be zero in small interlaced images.
- */
-
- if((!ImageHeight) || (!BytesPerScanline))
- {
- return(qtrue);
- }
-
- /*
- * Set the pointer to the start of the decompressed Data.
- */
-
- DecompPtr = DecompressedData;
-
- /*
- * Un-filtering is done in place.
- */
-
- /*
- * Go trough all scanlines.
- */
-
- for(h = 0; h < ImageHeight; h++)
- {
- /*
- * Every scanline starts with a FilterType byte.
- */
-
- FilterType = *DecompPtr;
- DecompPtr++;
-
- /*
- * Left pixel of the first byte in a scanline is zero.
- */
-
- PixelLeft = Zeros;
-
- /*
- * Set PixelUp to previous line only if we are on the second line or above.
- *
- * Plus one byte for the FilterType
- */
-
- if(h > 0)
- {
- PixelUp = DecompPtr - (BytesPerScanline + 1);
- }
- else
- {
- PixelUp = Zeros;
- }
-
- /*
- * The pixel left to the first pixel of the previous scanline is zero too.
- */
-
- PixelUpLeft = Zeros;
-
- /*
- * Cycle trough all pixels of the scanline.
- */
-
- for(w = 0; w < (BytesPerScanline / BytesPerPixel); w++)
- {
- /*
- * Cycle trough the bytes of the pixel.
- */
-
- for(p = 0; p < BytesPerPixel; p++)
- {
- switch(FilterType)
- {
- case PNG_FilterType_None :
- {
- /*
- * The byte is unfiltered.
- */
-
- break;
- }
-
- case PNG_FilterType_Sub :
- {
- DecompPtr[p] += PixelLeft[p];
-
- break;
- }
-
- case PNG_FilterType_Up :
- {
- DecompPtr[p] += PixelUp[p];
-
- break;
- }
-
- case PNG_FilterType_Average :
- {
- DecompPtr[p] += ((uint8_t) ((((uint16_t) PixelLeft[p]) + ((uint16_t) PixelUp[p])) / 2));
-
- break;
- }
-
- case PNG_FilterType_Paeth :
- {
- DecompPtr[p] += PredictPaeth(PixelLeft[p], PixelUp[p], PixelUpLeft[p]);
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
- }
-
- PixelLeft = DecompPtr;
-
- /*
- * We only have an upleft pixel if we are on the second line or above.
- */
-
- if(h > 0)
- {
- PixelUpLeft = DecompPtr - (BytesPerScanline + 1);
- }
-
- /*
- * Skip to the next pixel.
- */
-
- DecompPtr += BytesPerPixel;
-
- /*
- * We only have a previous line if we are on the second line and above.
- */
-
- if(h > 0)
- {
- PixelUp = DecompPtr - (BytesPerScanline + 1);
- }
- }
- }
-
- return(qtrue);
-}
-
-/*
- * Convert a raw input pixel to Quake 3 RGA format.
- */
-
-static qboolean ConvertPixel(struct PNG_Chunk_IHDR *IHDR,
- byte *OutPtr,
- uint8_t *DecompPtr,
- qboolean HasTransparentColour,
- uint8_t *TransparentColour,
- uint8_t *OutPal)
-{
- /*
- * input verification
- */
-
- if(!(IHDR && OutPtr && DecompPtr && TransparentColour && OutPal))
- {
- return(qfalse);
- }
-
- switch(IHDR->ColourType)
- {
- case PNG_ColourType_Grey :
- {
- switch(IHDR->BitDepth)
- {
- case PNG_BitDepth_1 :
- case PNG_BitDepth_2 :
- case PNG_BitDepth_4 :
- {
- uint8_t Step;
- uint8_t GreyValue;
-
- Step = 0xFF / ((1 << IHDR->BitDepth) - 1);
-
- GreyValue = DecompPtr[0] * Step;
-
- OutPtr[0] = GreyValue;
- OutPtr[1] = GreyValue;
- OutPtr[2] = GreyValue;
- OutPtr[3] = 0xFF;
-
- /*
- * Grey supports full transparency for one specified colour
- */
-
- if(HasTransparentColour)
- {
- if(TransparentColour[1] == DecompPtr[0])
- {
- OutPtr[3] = 0x00;
- }
- }
-
-
- break;
- }
-
- case PNG_BitDepth_8 :
- case PNG_BitDepth_16 :
- {
- OutPtr[0] = DecompPtr[0];
- OutPtr[1] = DecompPtr[0];
- OutPtr[2] = DecompPtr[0];
- OutPtr[3] = 0xFF;
-
- /*
- * Grey supports full transparency for one specified colour
- */
-
- if(HasTransparentColour)
- {
- if(IHDR->BitDepth == PNG_BitDepth_8)
- {
- if(TransparentColour[1] == DecompPtr[0])
- {
- OutPtr[3] = 0x00;
- }
- }
- else
- {
- if((TransparentColour[0] == DecompPtr[0]) && (TransparentColour[1] == DecompPtr[1]))
- {
- OutPtr[3] = 0x00;
- }
- }
- }
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- break;
- }
-
- case PNG_ColourType_True :
- {
- switch(IHDR->BitDepth)
- {
- case PNG_BitDepth_8 :
- {
- OutPtr[0] = DecompPtr[0];
- OutPtr[1] = DecompPtr[1];
- OutPtr[2] = DecompPtr[2];
- OutPtr[3] = 0xFF;
-
- /*
- * True supports full transparency for one specified colour
- */
-
- if(HasTransparentColour)
- {
- if((TransparentColour[1] == DecompPtr[0]) &&
- (TransparentColour[3] == DecompPtr[1]) &&
- (TransparentColour[5] == DecompPtr[2]))
- {
- OutPtr[3] = 0x00;
- }
- }
-
- break;
- }
-
- case PNG_BitDepth_16 :
- {
- /*
- * We use only the upper byte.
- */
-
- OutPtr[0] = DecompPtr[0];
- OutPtr[1] = DecompPtr[2];
- OutPtr[2] = DecompPtr[4];
- OutPtr[3] = 0xFF;
-
- /*
- * True supports full transparency for one specified colour
- */
-
- if(HasTransparentColour)
- {
- if((TransparentColour[0] == DecompPtr[0]) && (TransparentColour[1] == DecompPtr[1]) &&
- (TransparentColour[2] == DecompPtr[2]) && (TransparentColour[3] == DecompPtr[3]) &&
- (TransparentColour[4] == DecompPtr[4]) && (TransparentColour[5] == DecompPtr[5]))
- {
- OutPtr[3] = 0x00;
- }
- }
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- break;
- }
-
- case PNG_ColourType_Indexed :
- {
- OutPtr[0] = OutPal[DecompPtr[0] * Q3IMAGE_BYTESPERPIXEL + 0];
- OutPtr[1] = OutPal[DecompPtr[0] * Q3IMAGE_BYTESPERPIXEL + 1];
- OutPtr[2] = OutPal[DecompPtr[0] * Q3IMAGE_BYTESPERPIXEL + 2];
- OutPtr[3] = OutPal[DecompPtr[0] * Q3IMAGE_BYTESPERPIXEL + 3];
-
- break;
- }
-
- case PNG_ColourType_GreyAlpha :
- {
- switch(IHDR->BitDepth)
- {
- case PNG_BitDepth_8 :
- {
- OutPtr[0] = DecompPtr[0];
- OutPtr[1] = DecompPtr[0];
- OutPtr[2] = DecompPtr[0];
- OutPtr[3] = DecompPtr[1];
-
- break;
- }
-
- case PNG_BitDepth_16 :
- {
- /*
- * We use only the upper byte.
- */
-
- OutPtr[0] = DecompPtr[0];
- OutPtr[1] = DecompPtr[0];
- OutPtr[2] = DecompPtr[0];
- OutPtr[3] = DecompPtr[2];
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- break;
- }
-
- case PNG_ColourType_TrueAlpha :
- {
- switch(IHDR->BitDepth)
- {
- case PNG_BitDepth_8 :
- {
- OutPtr[0] = DecompPtr[0];
- OutPtr[1] = DecompPtr[1];
- OutPtr[2] = DecompPtr[2];
- OutPtr[3] = DecompPtr[3];
-
- break;
- }
-
- case PNG_BitDepth_16 :
- {
- /*
- * We use only the upper byte.
- */
-
- OutPtr[0] = DecompPtr[0];
- OutPtr[1] = DecompPtr[2];
- OutPtr[2] = DecompPtr[4];
- OutPtr[3] = DecompPtr[6];
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- return(qtrue);
-}
-
-
-/*
- * Decode a non-interlaced image.
- */
-
-static qboolean DecodeImageNonInterlaced(struct PNG_Chunk_IHDR *IHDR,
- byte *OutBuffer,
- uint8_t *DecompressedData,
- uint32_t DecompressedDataLength,
- qboolean HasTransparentColour,
- uint8_t *TransparentColour,
- uint8_t *OutPal)
-{
- uint32_t IHDR_Width;
- uint32_t IHDR_Height;
- uint32_t BytesPerScanline, BytesPerPixel, PixelsPerByte;
- uint32_t w, h, p;
- byte *OutPtr;
- uint8_t *DecompPtr;
-
- /*
- * input verification
- */
-
- if(!(IHDR && OutBuffer && DecompressedData && DecompressedDataLength && TransparentColour && OutPal))
- {
- return(qfalse);
- }
-
- /*
- * byte swapping
- */
-
- IHDR_Width = BigLong(IHDR->Width);
- IHDR_Height = BigLong(IHDR->Height);
-
- /*
- * information for un-filtering
- */
-
- switch(IHDR->ColourType)
- {
- case PNG_ColourType_Grey :
- {
- switch(IHDR->BitDepth)
- {
- case PNG_BitDepth_1 :
- case PNG_BitDepth_2 :
- case PNG_BitDepth_4 :
- {
- BytesPerPixel = 1;
- PixelsPerByte = 8 / IHDR->BitDepth;
-
- break;
- }
-
- case PNG_BitDepth_8 :
- case PNG_BitDepth_16 :
- {
- BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_Grey;
- PixelsPerByte = 1;
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- break;
- }
-
- case PNG_ColourType_True :
- {
- switch(IHDR->BitDepth)
- {
- case PNG_BitDepth_8 :
- case PNG_BitDepth_16 :
- {
- BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_True;
- PixelsPerByte = 1;
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- break;
- }
-
- case PNG_ColourType_Indexed :
- {
- switch(IHDR->BitDepth)
- {
- case PNG_BitDepth_1 :
- case PNG_BitDepth_2 :
- case PNG_BitDepth_4 :
- {
- BytesPerPixel = 1;
- PixelsPerByte = 8 / IHDR->BitDepth;
-
- break;
- }
-
- case PNG_BitDepth_8 :
- {
- BytesPerPixel = PNG_NumColourComponents_Indexed;
- PixelsPerByte = 1;
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- break;
- }
-
- case PNG_ColourType_GreyAlpha :
- {
- switch(IHDR->BitDepth)
- {
- case PNG_BitDepth_8 :
- case PNG_BitDepth_16 :
- {
- BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_GreyAlpha;
- PixelsPerByte = 1;
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- break;
- }
-
- case PNG_ColourType_TrueAlpha :
- {
- switch(IHDR->BitDepth)
- {
- case PNG_BitDepth_8 :
- case PNG_BitDepth_16 :
- {
- BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_TrueAlpha;
- PixelsPerByte = 1;
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- /*
- * Calculate the size of one scanline
- */
-
- BytesPerScanline = (IHDR_Width * BytesPerPixel + (PixelsPerByte - 1)) / PixelsPerByte;
-
- /*
- * Check if we have enough data for the whole image.
- */
-
- if(!(DecompressedDataLength == ((BytesPerScanline + 1) * IHDR_Height)))
- {
- return(qfalse);
- }
-
- /*
- * Unfilter the image.
- */
-
- if(!UnfilterImage(DecompressedData, IHDR_Height, BytesPerScanline, BytesPerPixel))
- {
- return(qfalse);
- }
-
- /*
- * Set the working pointers to the beginning of the buffers.
- */
-
- OutPtr = OutBuffer;
- DecompPtr = DecompressedData;
-
- /*
- * Create the output image.
- */
-
- for(h = 0; h < IHDR_Height; h++)
- {
- /*
- * Count the pixels on the scanline for those multipixel bytes
- */
-
- uint32_t CurrPixel;
-
- /*
- * skip FilterType
- */
-
- DecompPtr++;
-
- /*
- * Reset the pixel count.
- */
-
- CurrPixel = 0;
-
- for(w = 0; w < (BytesPerScanline / BytesPerPixel); w++)
- {
- if(PixelsPerByte > 1)
- {
- uint8_t Mask;
- uint32_t Shift;
- uint8_t SinglePixel;
-
- for(p = 0; p < PixelsPerByte; p++)
- {
- if(CurrPixel < IHDR_Width)
- {
- Mask = (1 << IHDR->BitDepth) - 1;
- Shift = (PixelsPerByte - 1 - p) * IHDR->BitDepth;
-
- SinglePixel = ((DecompPtr[0] & (Mask << Shift)) >> Shift);
-
- if(!ConvertPixel(IHDR, OutPtr, &SinglePixel, HasTransparentColour, TransparentColour, OutPal))
- {
- return(qfalse);
- }
-
- OutPtr += Q3IMAGE_BYTESPERPIXEL;
- CurrPixel++;
- }
- }
-
- }
- else
- {
- if(!ConvertPixel(IHDR, OutPtr, DecompPtr, HasTransparentColour, TransparentColour, OutPal))
- {
- return(qfalse);
- }
-
-
- OutPtr += Q3IMAGE_BYTESPERPIXEL;
- }
-
- DecompPtr += BytesPerPixel;
- }
- }
-
- return(qtrue);
-}
-
-/*
- * Decode an interlaced image.
- */
-
-static qboolean DecodeImageInterlaced(struct PNG_Chunk_IHDR *IHDR,
- byte *OutBuffer,
- uint8_t *DecompressedData,
- uint32_t DecompressedDataLength,
- qboolean HasTransparentColour,
- uint8_t *TransparentColour,
- uint8_t *OutPal)
-{
- uint32_t IHDR_Width;
- uint32_t IHDR_Height;
- uint32_t BytesPerScanline[PNG_Adam7_NumPasses], BytesPerPixel, PixelsPerByte;
- uint32_t PassWidth[PNG_Adam7_NumPasses], PassHeight[PNG_Adam7_NumPasses];
- uint32_t WSkip[PNG_Adam7_NumPasses], WOffset[PNG_Adam7_NumPasses], HSkip[PNG_Adam7_NumPasses], HOffset[PNG_Adam7_NumPasses];
- uint32_t w, h, p, a;
- byte *OutPtr;
- uint8_t *DecompPtr;
- uint32_t TargetLength;
-
- /*
- * input verification
- */
-
- if(!(IHDR && OutBuffer && DecompressedData && DecompressedDataLength && TransparentColour && OutPal))
- {
- return(qfalse);
- }
-
- /*
- * byte swapping
- */
-
- IHDR_Width = BigLong(IHDR->Width);
- IHDR_Height = BigLong(IHDR->Height);
-
- /*
- * Skip and Offset for the passes.
- */
-
- WSkip[0] = 8;
- WOffset[0] = 0;
- HSkip[0] = 8;
- HOffset[0] = 0;
-
- WSkip[1] = 8;
- WOffset[1] = 4;
- HSkip[1] = 8;
- HOffset[1] = 0;
-
- WSkip[2] = 4;
- WOffset[2] = 0;
- HSkip[2] = 8;
- HOffset[2] = 4;
-
- WSkip[3] = 4;
- WOffset[3] = 2;
- HSkip[3] = 4;
- HOffset[3] = 0;
-
- WSkip[4] = 2;
- WOffset[4] = 0;
- HSkip[4] = 4;
- HOffset[4] = 2;
-
- WSkip[5] = 2;
- WOffset[5] = 1;
- HSkip[5] = 2;
- HOffset[5] = 0;
-
- WSkip[6] = 1;
- WOffset[6] = 0;
- HSkip[6] = 2;
- HOffset[6] = 1;
-
- /*
- * Calculate the sizes of the passes.
- */
-
- PassWidth[0] = (IHDR_Width + 7) / 8;
- PassHeight[0] = (IHDR_Height + 7) / 8;
-
- PassWidth[1] = (IHDR_Width + 3) / 8;
- PassHeight[1] = (IHDR_Height + 7) / 8;
-
- PassWidth[2] = (IHDR_Width + 3) / 4;
- PassHeight[2] = (IHDR_Height + 3) / 8;
-
- PassWidth[3] = (IHDR_Width + 1) / 4;
- PassHeight[3] = (IHDR_Height + 3) / 4;
-
- PassWidth[4] = (IHDR_Width + 1) / 2;
- PassHeight[4] = (IHDR_Height + 1) / 4;
-
- PassWidth[5] = (IHDR_Width + 0) / 2;
- PassHeight[5] = (IHDR_Height + 1) / 2;
-
- PassWidth[6] = (IHDR_Width + 0) / 1;
- PassHeight[6] = (IHDR_Height + 0) / 2;
-
- /*
- * information for un-filtering
- */
-
- switch(IHDR->ColourType)
- {
- case PNG_ColourType_Grey :
- {
- switch(IHDR->BitDepth)
- {
- case PNG_BitDepth_1 :
- case PNG_BitDepth_2 :
- case PNG_BitDepth_4 :
- {
- BytesPerPixel = 1;
- PixelsPerByte = 8 / IHDR->BitDepth;
-
- break;
- }
-
- case PNG_BitDepth_8 :
- case PNG_BitDepth_16 :
- {
- BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_Grey;
- PixelsPerByte = 1;
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- break;
- }
-
- case PNG_ColourType_True :
- {
- switch(IHDR->BitDepth)
- {
- case PNG_BitDepth_8 :
- case PNG_BitDepth_16 :
- {
- BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_True;
- PixelsPerByte = 1;
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- break;
- }
-
- case PNG_ColourType_Indexed :
- {
- switch(IHDR->BitDepth)
- {
- case PNG_BitDepth_1 :
- case PNG_BitDepth_2 :
- case PNG_BitDepth_4 :
- {
- BytesPerPixel = 1;
- PixelsPerByte = 8 / IHDR->BitDepth;
-
- break;
- }
-
- case PNG_BitDepth_8 :
- {
- BytesPerPixel = PNG_NumColourComponents_Indexed;
- PixelsPerByte = 1;
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- break;
- }
-
- case PNG_ColourType_GreyAlpha :
- {
- switch(IHDR->BitDepth)
- {
- case PNG_BitDepth_8 :
- case PNG_BitDepth_16 :
- {
- BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_GreyAlpha;
- PixelsPerByte = 1;
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- break;
- }
-
- case PNG_ColourType_TrueAlpha :
- {
- switch(IHDR->BitDepth)
- {
- case PNG_BitDepth_8 :
- case PNG_BitDepth_16 :
- {
- BytesPerPixel = (IHDR->BitDepth / 8) * PNG_NumColourComponents_TrueAlpha;
- PixelsPerByte = 1;
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- break;
- }
-
- default :
- {
- return(qfalse);
- }
- }
-
- /*
- * Calculate the size of the scanlines per pass
- */
-
- for(a = 0; a < PNG_Adam7_NumPasses; a++)
- {
- BytesPerScanline[a] = (PassWidth[a] * BytesPerPixel + (PixelsPerByte - 1)) / PixelsPerByte;
- }
-
- /*
- * Calculate the size of all passes
- */
-
- TargetLength = 0;
-
- for(a = 0; a < PNG_Adam7_NumPasses; a++)
- {
- TargetLength += ((BytesPerScanline[a] + (BytesPerScanline[a] ? 1 : 0)) * PassHeight[a]);
- }
-
- /*
- * Check if we have enough data for the whole image.
- */
-
- if(!(DecompressedDataLength == TargetLength))
- {
- return(qfalse);
- }
-
- /*
- * Unfilter the image.
- */
-
- DecompPtr = DecompressedData;
-
- for(a = 0; a < PNG_Adam7_NumPasses; a++)
- {
- if(!UnfilterImage(DecompPtr, PassHeight[a], BytesPerScanline[a], BytesPerPixel))
- {
- return(qfalse);
- }
-
- DecompPtr += ((BytesPerScanline[a] + (BytesPerScanline[a] ? 1 : 0)) * PassHeight[a]);
- }
-
- /*
- * Set the working pointers to the beginning of the buffers.
- */
-
- DecompPtr = DecompressedData;
-
- /*
- * Create the output image.
- */
-
- for(a = 0; a < PNG_Adam7_NumPasses; a++)
- {
- for(h = 0; h < PassHeight[a]; h++)
- {
- /*
- * Count the pixels on the scanline for those multipixel bytes
- */
-
- uint32_t CurrPixel;
-
- /*
- * skip FilterType
- * but only when the pass has a width bigger than zero
- */
-
- if(BytesPerScanline[a])
- {
- DecompPtr++;
- }
-
- /*
- * Reset the pixel count.
- */
-
- CurrPixel = 0;
-
- for(w = 0; w < (BytesPerScanline[a] / BytesPerPixel); w++)
- {
- if(PixelsPerByte > 1)
- {
- uint8_t Mask;
- uint32_t Shift;
- uint8_t SinglePixel;
-
- for(p = 0; p < PixelsPerByte; p++)
- {
- if(CurrPixel < PassWidth[a])
- {
- Mask = (1 << IHDR->BitDepth) - 1;
- Shift = (PixelsPerByte - 1 - p) * IHDR->BitDepth;
-
- SinglePixel = ((DecompPtr[0] & (Mask << Shift)) >> Shift);
-
- OutPtr = OutBuffer + (((((h * HSkip[a]) + HOffset[a]) * IHDR_Width) + ((CurrPixel * WSkip[a]) + WOffset[a])) * Q3IMAGE_BYTESPERPIXEL);
-
- if(!ConvertPixel(IHDR, OutPtr, &SinglePixel, HasTransparentColour, TransparentColour, OutPal))
- {
- return(qfalse);
- }
-
- CurrPixel++;
- }
- }
-
- }
- else
- {
- OutPtr = OutBuffer + (((((h * HSkip[a]) + HOffset[a]) * IHDR_Width) + ((w * WSkip[a]) + WOffset[a])) * Q3IMAGE_BYTESPERPIXEL);
-
- if(!ConvertPixel(IHDR, OutPtr, DecompPtr, HasTransparentColour, TransparentColour, OutPal))
- {
- return(qfalse);
- }
- }
-
- DecompPtr += BytesPerPixel;
- }
- }
- }
-
- return(qtrue);
-}
-
-/*
- * The PNG loader
- */
-
-void R_LoadPNG(const char *name, byte **pic, int *width, int *height)
-{
- struct BufferedFile *ThePNG;
- byte *OutBuffer;
- uint8_t *Signature;
- struct PNG_ChunkHeader *CH;
- uint32_t ChunkHeaderLength;
- uint32_t ChunkHeaderType;
- struct PNG_Chunk_IHDR *IHDR;
- uint32_t IHDR_Width;
- uint32_t IHDR_Height;
- PNG_ChunkCRC *CRC;
- uint8_t *InPal;
- uint8_t *DecompressedData;
- uint32_t DecompressedDataLength;
- uint32_t i;
-
- /*
- * palette with 256 RGBA entries
- */
-
- uint8_t OutPal[1024];
-
- /*
- * transparent colour from the tRNS chunk
- */
-
- qboolean HasTransparentColour = qfalse;
- uint8_t TransparentColour[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-
- /*
- * input verification
- */
-
- if(!(name && pic))
- {
- return;
- }
-
- /*
- * Zero out return values.
- */
-
- *pic = NULL;
-
- if(width)
- {
- *width = 0;
- }
-
- if(height)
- {
- *height = 0;
- }
-
- /*
- * Read the file.
- */
-
- ThePNG = ReadBufferedFile(name);
- if(!ThePNG)
- {
- return;
- }
-
- /*
- * Read the siganture of the file.
- */
-
- Signature = BufferedFileRead(ThePNG, PNG_Signature_Size);
- if(!Signature)
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Is it a PNG?
- */
-
- if(memcmp(Signature, PNG_Signature, PNG_Signature_Size))
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Read the first chunk-header.
- */
-
- CH = BufferedFileRead(ThePNG, PNG_ChunkHeader_Size);
- if(!CH)
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * PNG multi-byte types are in Big Endian
- */
-
- ChunkHeaderLength = BigLong(CH->Length);
- ChunkHeaderType = BigLong(CH->Type);
-
- /*
- * Check if the first chunk is an IHDR.
- */
-
- if(!((ChunkHeaderType == PNG_ChunkType_IHDR) && (ChunkHeaderLength == PNG_Chunk_IHDR_Size)))
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Read the IHDR.
- */
-
- IHDR = BufferedFileRead(ThePNG, PNG_Chunk_IHDR_Size);
- if(!IHDR)
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Read the CRC for IHDR
- */
-
- CRC = BufferedFileRead(ThePNG, PNG_ChunkCRC_Size);
- if(!CRC)
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Here we could check the CRC if we wanted to.
- */
-
- /*
- * multi-byte type swapping
- */
-
- IHDR_Width = BigLong(IHDR->Width);
- IHDR_Height = BigLong(IHDR->Height);
-
- /*
- * Check if Width and Height are valid.
- */
-
- if(!((IHDR_Width > 0) && (IHDR_Height > 0))
- || IHDR_Width > INT_MAX / Q3IMAGE_BYTESPERPIXEL / IHDR_Height)
- {
- CloseBufferedFile(ThePNG);
-
- ri.Printf( PRINT_WARNING, "%s: invalid image size\n", name );
-
- return;
- }
-
- /*
- * Do we need to check if the dimensions of the image are valid for Quake3?
- */
-
- /*
- * Check if CompressionMethod and FilterMethod are valid.
- */
-
- if(!((IHDR->CompressionMethod == PNG_CompressionMethod_0) && (IHDR->FilterMethod == PNG_FilterMethod_0)))
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Check if InterlaceMethod is valid.
- */
-
- if(!((IHDR->InterlaceMethod == PNG_InterlaceMethod_NonInterlaced) || (IHDR->InterlaceMethod == PNG_InterlaceMethod_Interlaced)))
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Read palette for an indexed image.
- */
-
- if(IHDR->ColourType == PNG_ColourType_Indexed)
- {
- /*
- * We need the palette first.
- */
-
- if(!FindChunk(ThePNG, PNG_ChunkType_PLTE))
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Read the chunk-header.
- */
-
- CH = BufferedFileRead(ThePNG, PNG_ChunkHeader_Size);
- if(!CH)
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * PNG multi-byte types are in Big Endian
- */
-
- ChunkHeaderLength = BigLong(CH->Length);
- ChunkHeaderType = BigLong(CH->Type);
-
- /*
- * Check if the chunk is a PLTE.
- */
-
- if(!(ChunkHeaderType == PNG_ChunkType_PLTE))
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Check if Length is divisible by 3
- */
-
- if(ChunkHeaderLength % 3)
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Read the raw palette data
- */
-
- InPal = BufferedFileRead(ThePNG, ChunkHeaderLength);
- if(!InPal)
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Read the CRC for the palette
- */
-
- CRC = BufferedFileRead(ThePNG, PNG_ChunkCRC_Size);
- if(!CRC)
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Set some default values.
- */
-
- for(i = 0; i < 256; i++)
- {
- OutPal[i * Q3IMAGE_BYTESPERPIXEL + 0] = 0x00;
- OutPal[i * Q3IMAGE_BYTESPERPIXEL + 1] = 0x00;
- OutPal[i * Q3IMAGE_BYTESPERPIXEL + 2] = 0x00;
- OutPal[i * Q3IMAGE_BYTESPERPIXEL + 3] = 0xFF;
- }
-
- /*
- * Convert to the Quake3 RGBA-format.
- */
-
- for(i = 0; i < (ChunkHeaderLength / 3); i++)
- {
- OutPal[i * Q3IMAGE_BYTESPERPIXEL + 0] = InPal[i*3+0];
- OutPal[i * Q3IMAGE_BYTESPERPIXEL + 1] = InPal[i*3+1];
- OutPal[i * Q3IMAGE_BYTESPERPIXEL + 2] = InPal[i*3+2];
- OutPal[i * Q3IMAGE_BYTESPERPIXEL + 3] = 0xFF;
- }
- }
-
- /*
- * transparency information is sometimes stored in a tRNS chunk
- */
-
- /*
- * Let's see if there is a tRNS chunk
- */
-
- if(FindChunk(ThePNG, PNG_ChunkType_tRNS))
- {
- uint8_t *Trans;
-
- /*
- * Read the chunk-header.
- */
-
- CH = BufferedFileRead(ThePNG, PNG_ChunkHeader_Size);
- if(!CH)
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * PNG multi-byte types are in Big Endian
- */
-
- ChunkHeaderLength = BigLong(CH->Length);
- ChunkHeaderType = BigLong(CH->Type);
-
- /*
- * Check if the chunk is a tRNS.
- */
-
- if(!(ChunkHeaderType == PNG_ChunkType_tRNS))
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Read the transparency information.
- */
-
- Trans = BufferedFileRead(ThePNG, ChunkHeaderLength);
- if(!Trans)
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Read the CRC.
- */
-
- CRC = BufferedFileRead(ThePNG, PNG_ChunkCRC_Size);
- if(!CRC)
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Only for Grey, True and Indexed ColourType should tRNS exist.
- */
-
- switch(IHDR->ColourType)
- {
- case PNG_ColourType_Grey :
- {
- if(!ChunkHeaderLength == 2)
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- HasTransparentColour = qtrue;
-
- /*
- * Grey can have one colour which is completely transparent.
- * This colour is always stored in 16 bits.
- */
-
- TransparentColour[0] = Trans[0];
- TransparentColour[1] = Trans[1];
-
- break;
- }
-
- case PNG_ColourType_True :
- {
- if(!ChunkHeaderLength == 6)
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- HasTransparentColour = qtrue;
-
- /*
- * True can have one colour which is completely transparent.
- * This colour is always stored in 16 bits.
- */
-
- TransparentColour[0] = Trans[0];
- TransparentColour[1] = Trans[1];
- TransparentColour[2] = Trans[2];
- TransparentColour[3] = Trans[3];
- TransparentColour[4] = Trans[4];
- TransparentColour[5] = Trans[5];
-
- break;
- }
-
- case PNG_ColourType_Indexed :
- {
- /*
- * Maximum of 256 one byte transparency entries.
- */
-
- if(ChunkHeaderLength > 256)
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- HasTransparentColour = qtrue;
-
- /*
- * alpha values for palette entries
- */
-
- for(i = 0; i < ChunkHeaderLength; i++)
- {
- OutPal[i * Q3IMAGE_BYTESPERPIXEL + 3] = Trans[i];
- }
-
- break;
- }
-
- /*
- * All other ColourTypes should not have tRNS chunks
- */
-
- default :
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
- }
- }
-
- /*
- * Rewind to the start of the file.
- */
-
- if(!BufferedFileRewind(ThePNG, -1))
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Skip the signature
- */
-
- if(!BufferedFileSkip(ThePNG, PNG_Signature_Size))
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Decompress all IDAT chunks
- */
-
- DecompressedDataLength = DecompressIDATs(ThePNG, &DecompressedData);
- if(!(DecompressedDataLength && DecompressedData))
- {
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Allocate output buffer.
- */
-
- OutBuffer = ri.Malloc(IHDR_Width * IHDR_Height * Q3IMAGE_BYTESPERPIXEL);
- if(!OutBuffer)
- {
- ri.Free(DecompressedData);
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- /*
- * Interlaced and Non-interlaced images need to be handled differently.
- */
-
- switch(IHDR->InterlaceMethod)
- {
- case PNG_InterlaceMethod_NonInterlaced :
- {
- if(!DecodeImageNonInterlaced(IHDR, OutBuffer, DecompressedData, DecompressedDataLength, HasTransparentColour, TransparentColour, OutPal))
- {
- ri.Free(OutBuffer);
- ri.Free(DecompressedData);
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- break;
- }
-
- case PNG_InterlaceMethod_Interlaced :
- {
- if(!DecodeImageInterlaced(IHDR, OutBuffer, DecompressedData, DecompressedDataLength, HasTransparentColour, TransparentColour, OutPal))
- {
- ri.Free(OutBuffer);
- ri.Free(DecompressedData);
- CloseBufferedFile(ThePNG);
-
- return;
- }
-
- break;
- }
-
- default :
- {
- ri.Free(OutBuffer);
- ri.Free(DecompressedData);
- CloseBufferedFile(ThePNG);
-
- return;
- }
- }
-
- /*
- * update the pointer to the image data
- */
-
- *pic = OutBuffer;
-
- /*
- * Fill width and height.
- */
-
- if(width)
- {
- *width = IHDR_Width;
- }
-
- if(height)
- {
- *height = IHDR_Height;
- }
-
- /*
- * DecompressedData is not needed anymore.
- */
-
- ri.Free(DecompressedData);
-
- /*
- * We have all data, so close the file.
- */
-
- CloseBufferedFile(ThePNG);
-}
diff --git a/src/rend2/tr_image_tga.c b/src/rend2/tr_image_tga.c
deleted file mode 100644
index 27ca0d7b..00000000
--- a/src/rend2/tr_image_tga.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-#include "../qcommon/q_shared.h"
-#include "../qcommon/qfiles.h"
-#include "../qcommon/qcommon.h"
-#include "../renderer/tr_public.h"
-extern refimport_t ri;
-
-/*
-========================================================================
-
-TGA files are used for 24/32 bit images
-
-========================================================================
-*/
-
-typedef struct _TargaHeader {
- unsigned char id_length, colormap_type, image_type;
- unsigned short colormap_index, colormap_length;
- unsigned char colormap_size;
- unsigned short x_origin, y_origin, width, height;
- unsigned char pixel_size, attributes;
-} TargaHeader;
-
-void R_LoadTGA ( const char *name, byte **pic, int *width, int *height)
-{
- unsigned columns, rows, numPixels;
- byte *pixbuf;
- int row, column;
- byte *buf_p;
- byte *end;
- union {
- byte *b;
- void *v;
- } buffer;
- TargaHeader targa_header;
- byte *targa_rgba;
- int length;
-
- *pic = NULL;
-
- if(width)
- *width = 0;
- if(height)
- *height = 0;
-
- //
- // load the file
- //
- length = ri.FS_ReadFile ( ( char * ) name, &buffer.v);
- if (!buffer.b || length < 0) {
- return;
- }
-
- if(length < 18)
- {
- ri.Error( ERR_DROP, "LoadTGA: header too short (%s)", name );
- }
-
- buf_p = buffer.b;
- end = buffer.b + length;
-
- targa_header.id_length = buf_p[0];
- targa_header.colormap_type = buf_p[1];
- targa_header.image_type = buf_p[2];
-
- memcpy(&targa_header.colormap_index, &buf_p[3], 2);
- memcpy(&targa_header.colormap_length, &buf_p[5], 2);
- targa_header.colormap_size = buf_p[7];
- memcpy(&targa_header.x_origin, &buf_p[8], 2);
- memcpy(&targa_header.y_origin, &buf_p[10], 2);
- memcpy(&targa_header.width, &buf_p[12], 2);
- memcpy(&targa_header.height, &buf_p[14], 2);
- targa_header.pixel_size = buf_p[16];
- targa_header.attributes = buf_p[17];
-
- targa_header.colormap_index = LittleShort(targa_header.colormap_index);
- targa_header.colormap_length = LittleShort(targa_header.colormap_length);
- targa_header.x_origin = LittleShort(targa_header.x_origin);
- targa_header.y_origin = LittleShort(targa_header.y_origin);
- targa_header.width = LittleShort(targa_header.width);
- targa_header.height = LittleShort(targa_header.height);
-
- buf_p += 18;
-
- if (targa_header.image_type!=2
- && targa_header.image_type!=10
- && targa_header.image_type != 3 )
- {
- ri.Error (ERR_DROP, "LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported");
- }
-
- if ( targa_header.colormap_type != 0 )
- {
- ri.Error( ERR_DROP, "LoadTGA: colormaps not supported" );
- }
-
- if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 )
- {
- ri.Error (ERR_DROP, "LoadTGA: Only 32 or 24 bit images supported (no colormaps)");
- }
-
- columns = targa_header.width;
- rows = targa_header.height;
- numPixels = columns * rows * 4;
-
- if(!columns || !rows || numPixels > 0x7FFFFFFF || numPixels / columns / 4 != rows)
- {
- ri.Error (ERR_DROP, "LoadTGA: %s has an invalid image size", name);
- }
-
-
- targa_rgba = ri.Malloc (numPixels);
-
- if (targa_header.id_length != 0)
- {
- if (buf_p + targa_header.id_length > end)
- ri.Error( ERR_DROP, "LoadTGA: header too short (%s)", name );
-
- buf_p += targa_header.id_length; // skip TARGA image comment
- }
-
- if ( targa_header.image_type==2 || targa_header.image_type == 3 )
- {
- if(buf_p + columns*rows*targa_header.pixel_size/8 > end)
- {
- ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)", name);
- }
-
- // Uncompressed RGB or gray scale image
- for(row=rows-1; row>=0; row--)
- {
- pixbuf = targa_rgba + row*columns*4;
- for(column=0; column<columns; column++)
- {
- unsigned char red,green,blue,alphabyte;
- switch (targa_header.pixel_size)
- {
-
- case 8:
- blue = *buf_p++;
- green = blue;
- red = blue;
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = 255;
- break;
-
- case 24:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = 255;
- break;
- case 32:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- alphabyte = *buf_p++;
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = alphabyte;
- break;
- default:
- ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'", targa_header.pixel_size, name );
- break;
- }
- }
- }
- }
- else if (targa_header.image_type==10) { // Runlength encoded RGB images
- unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
-
- red = 0;
- green = 0;
- blue = 0;
- alphabyte = 0xff;
-
- for(row=rows-1; row>=0; row--) {
- pixbuf = targa_rgba + row*columns*4;
- for(column=0; column<columns; ) {
- if(buf_p + 1 > end)
- ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)", name);
- packetHeader= *buf_p++;
- packetSize = 1 + (packetHeader & 0x7f);
- if (packetHeader & 0x80) { // run-length packet
- if(buf_p + targa_header.pixel_size/8 > end)
- ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)", name);
- switch (targa_header.pixel_size) {
- case 24:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- alphabyte = 255;
- break;
- case 32:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- alphabyte = *buf_p++;
- break;
- default:
- ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'", targa_header.pixel_size, name );
- break;
- }
-
- for(j=0;j<packetSize;j++) {
- *pixbuf++=red;
- *pixbuf++=green;
- *pixbuf++=blue;
- *pixbuf++=alphabyte;
- column++;
- if (column==columns) { // run spans across rows
- column=0;
- if (row>0)
- row--;
- else
- goto breakOut;
- pixbuf = targa_rgba + row*columns*4;
- }
- }
- }
- else { // non run-length packet
-
- if(buf_p + targa_header.pixel_size/8*packetSize > end)
- ri.Error (ERR_DROP, "LoadTGA: file truncated (%s)", name);
- for(j=0;j<packetSize;j++) {
- switch (targa_header.pixel_size) {
- case 24:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = 255;
- break;
- case 32:
- blue = *buf_p++;
- green = *buf_p++;
- red = *buf_p++;
- alphabyte = *buf_p++;
- *pixbuf++ = red;
- *pixbuf++ = green;
- *pixbuf++ = blue;
- *pixbuf++ = alphabyte;
- break;
- default:
- ri.Error( ERR_DROP, "LoadTGA: illegal pixel_size '%d' in file '%s'", targa_header.pixel_size, name );
- break;
- }
- column++;
- if (column==columns) { // pixel packet run spans across rows
- column=0;
- if (row>0)
- row--;
- else
- goto breakOut;
- pixbuf = targa_rgba + row*columns*4;
- }
- }
- }
- }
- breakOut:;
- }
- }
-
-#if 0
- // TTimo: this is the chunk of code to ensure a behavior that meets TGA specs
- // bit 5 set => top-down
- if (targa_header.attributes & 0x20) {
- unsigned char *flip = (unsigned char*)malloc (columns*4);
- unsigned char *src, *dst;
-
- for (row = 0; row < rows/2; row++) {
- src = targa_rgba + row * 4 * columns;
- dst = targa_rgba + (rows - row - 1) * 4 * columns;
-
- memcpy (flip, src, columns*4);
- memcpy (src, dst, columns*4);
- memcpy (dst, flip, columns*4);
- }
- free (flip);
- }
-#endif
- // instead we just print a warning
- if (targa_header.attributes & 0x20) {
- ri.Printf( PRINT_WARNING, "WARNING: '%s' TGA file header declares top-down image, ignoring\n", name);
- }
-
- if (width)
- *width = columns;
- if (height)
- *height = rows;
-
- *pic = targa_rgba;
-
- ri.FS_FreeFile (buffer.v);
-}
diff --git a/src/rend2/tr_init.c b/src/rend2/tr_init.c
deleted file mode 100644
index 7228d01b..00000000
--- a/src/rend2/tr_init.c
+++ /dev/null
@@ -1,1480 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_init.c -- functions that are not called every frame
-
-#include "tr_local.h"
-
-glconfig_t glConfig;
-glRefConfig_t glRefConfig;
-qboolean textureFilterAnisotropic = qfalse;
-int maxAnisotropy = 0;
-float displayAspect = 0.0f;
-
-glstate_t glState;
-
-static void GfxInfo_f( void );
-static void GfxMemInfo_f( void );
-
-#ifdef USE_RENDERER_DLOPEN
-cvar_t *com_altivec;
-#endif
-
-cvar_t *r_flareSize;
-cvar_t *r_flareFade;
-cvar_t *r_flareCoeff;
-
-cvar_t *r_railWidth;
-cvar_t *r_railCoreWidth;
-cvar_t *r_railSegmentLength;
-
-cvar_t *r_verbose;
-cvar_t *r_ignore;
-
-cvar_t *r_detailTextures;
-
-cvar_t *r_znear;
-cvar_t *r_zproj;
-cvar_t *r_stereoSeparation;
-
-cvar_t *r_skipBackEnd;
-
-cvar_t *r_stereoEnabled;
-cvar_t *r_anaglyphMode;
-
-cvar_t *r_greyscale;
-
-cvar_t *r_ignorehwgamma;
-cvar_t *r_measureOverdraw;
-
-cvar_t *r_inGameVideo;
-cvar_t *r_fastsky;
-cvar_t *r_drawSun;
-cvar_t *r_dynamiclight;
-cvar_t *r_dlightBacks;
-
-cvar_t *r_lodbias;
-cvar_t *r_lodscale;
-
-cvar_t *r_norefresh;
-cvar_t *r_drawentities;
-cvar_t *r_drawworld;
-cvar_t *r_speeds;
-cvar_t *r_fullbright;
-cvar_t *r_novis;
-cvar_t *r_nocull;
-cvar_t *r_facePlaneCull;
-cvar_t *r_showcluster;
-cvar_t *r_nocurves;
-
-cvar_t *r_allowExtensions;
-
-cvar_t *r_ext_compressed_textures;
-cvar_t *r_ext_multitexture;
-cvar_t *r_ext_compiled_vertex_array;
-cvar_t *r_ext_texture_env_add;
-cvar_t *r_ext_texture_filter_anisotropic;
-cvar_t *r_ext_max_anisotropy;
-
-cvar_t *r_ext_draw_range_elements;
-cvar_t *r_ext_multi_draw_arrays;
-cvar_t *r_ext_framebuffer_object;
-cvar_t *r_ext_texture_float;
-cvar_t *r_arb_half_float_pixel;
-cvar_t *r_ext_framebuffer_multisample;
-
-cvar_t *r_mergeMultidraws;
-cvar_t *r_mergeLeafSurfaces;
-
-cvar_t *r_cameraExposure;
-
-cvar_t *r_softOverbright;
-
-cvar_t *r_hdr;
-cvar_t *r_postProcess;
-
-cvar_t *r_toneMap;
-cvar_t *r_forceToneMap;
-cvar_t *r_forceToneMapMin;
-cvar_t *r_forceToneMapAvg;
-cvar_t *r_forceToneMapMax;
-
-cvar_t *r_autoExposure;
-cvar_t *r_forceAutoExposure;
-cvar_t *r_forceAutoExposureMin;
-cvar_t *r_forceAutoExposureMax;
-
-cvar_t *r_srgb;
-
-cvar_t *r_depthPrepass;
-cvar_t *r_ssao;
-
-cvar_t *r_normalMapping;
-cvar_t *r_specularMapping;
-cvar_t *r_deluxeMapping;
-cvar_t *r_parallaxMapping;
-cvar_t *r_normalAmbient;
-cvar_t *r_recalcMD3Normals;
-cvar_t *r_mergeLightmaps;
-cvar_t *r_dlightMode;
-cvar_t *r_pshadowDist;
-cvar_t *r_imageUpsample;
-cvar_t *r_imageUpsampleMaxSize;
-cvar_t *r_imageUpsampleType;
-cvar_t *r_genNormalMaps;
-cvar_t *r_forceSun;
-cvar_t *r_forceSunMapLightScale;
-cvar_t *r_forceSunLightScale;
-cvar_t *r_forceSunAmbientScale;
-cvar_t *r_drawSunRays;
-cvar_t *r_sunShadows;
-cvar_t *r_shadowFilter;
-cvar_t *r_shadowMapSize;
-cvar_t *r_shadowCascadeZNear;
-cvar_t *r_shadowCascadeZFar;
-cvar_t *r_shadowCascadeZBias;
-
-cvar_t *r_ignoreGLErrors;
-cvar_t *r_logFile;
-
-cvar_t *r_stencilbits;
-cvar_t *r_depthbits;
-cvar_t *r_colorbits;
-cvar_t *r_texturebits;
-cvar_t *r_ext_multisample;
-
-cvar_t *r_drawBuffer;
-cvar_t *r_lightmap;
-cvar_t *r_vertexLight;
-cvar_t *r_uiFullScreen;
-cvar_t *r_shadows;
-cvar_t *r_flares;
-cvar_t *r_mode;
-cvar_t *r_nobind;
-cvar_t *r_singleShader;
-cvar_t *r_roundImagesDown;
-cvar_t *r_colorMipLevels;
-cvar_t *r_picmip;
-cvar_t *r_showtris;
-cvar_t *r_showsky;
-cvar_t *r_shownormals;
-cvar_t *r_finish;
-cvar_t *r_clear;
-cvar_t *r_swapInterval;
-cvar_t *r_textureMode;
-cvar_t *r_offsetFactor;
-cvar_t *r_offsetUnits;
-cvar_t *r_gamma;
-cvar_t *r_intensity;
-cvar_t *r_lockpvs;
-cvar_t *r_noportals;
-cvar_t *r_portalOnly;
-
-cvar_t *r_subdivisions;
-cvar_t *r_lodCurveError;
-
-cvar_t *r_fullscreen;
-cvar_t *r_noborder;
-
-cvar_t *r_width;
-cvar_t *r_height;
-cvar_t *r_pixelAspect;
-
-cvar_t *r_overBrightBits;
-cvar_t *r_mapOverBrightBits;
-
-cvar_t *r_debugSurface;
-cvar_t *r_simpleMipMaps;
-
-cvar_t *r_showImages;
-
-cvar_t *r_ambientScale;
-cvar_t *r_directedScale;
-cvar_t *r_debugLight;
-cvar_t *r_debugSort;
-cvar_t *r_printShaders;
-cvar_t *r_saveFontData;
-
-cvar_t *r_marksOnTriangleMeshes;
-
-cvar_t *r_aviMotionJpegQuality;
-cvar_t *r_screenshotJpegQuality;
-
-cvar_t *r_maxpolys;
-int max_polys;
-cvar_t *r_maxpolyverts;
-int max_polyverts;
-
-/*
-** InitOpenGL
-**
-** This function is responsible for initializing a valid OpenGL subsystem. This
-** is done by calling GLimp_Init (which gives us a working OGL subsystem) then
-** setting variables, checking GL constants, and reporting the gfx system config
-** to the user.
-*/
-static void InitOpenGL( void )
-{
- char renderer_buffer[1024];
-
- //
- // initialize OS specific portions of the renderer
- //
- // GLimp_Init directly or indirectly references the following cvars:
- // - r_fullscreen
- // - r_mode
- // - r_(color|depth|stencil)bits
- // - r_ignorehwgamma
- // - r_gamma
- //
-
- if ( glConfig.vidWidth == 0 )
- {
- GLint temp;
-
- GLimp_Init();
- GLimp_InitExtraExtensions();
-
- strcpy( renderer_buffer, glConfig.renderer_string );
- Q_strlwr( renderer_buffer );
-
- // OpenGL driver constants
- qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp );
- glConfig.maxTextureSize = temp;
-
- // stubbed or broken drivers may have reported 0...
- if ( glConfig.maxTextureSize <= 0 )
- {
- glConfig.maxTextureSize = 0;
- }
- }
-
- // set default state
- GL_SetDefaultState();
-}
-
-/*
-==================
-GL_CheckErrors
-==================
-*/
-void GL_CheckErrs( char *file, int line ) {
- int err;
- char s[64];
-
- err = qglGetError();
- if ( err == GL_NO_ERROR ) {
- return;
- }
- if ( r_ignoreGLErrors->integer ) {
- return;
- }
- switch( err ) {
- case GL_INVALID_ENUM:
- strcpy( s, "GL_INVALID_ENUM" );
- break;
- case GL_INVALID_VALUE:
- strcpy( s, "GL_INVALID_VALUE" );
- break;
- case GL_INVALID_OPERATION:
- strcpy( s, "GL_INVALID_OPERATION" );
- break;
- case GL_STACK_OVERFLOW:
- strcpy( s, "GL_STACK_OVERFLOW" );
- break;
- case GL_STACK_UNDERFLOW:
- strcpy( s, "GL_STACK_UNDERFLOW" );
- break;
- case GL_OUT_OF_MEMORY:
- strcpy( s, "GL_OUT_OF_MEMORY" );
- break;
- default:
- Com_sprintf( s, sizeof(s), "%i", err);
- break;
- }
-
- ri.Error( ERR_FATAL, "GL_CheckErrors: %s in %s at line %d", s , file, line);
-}
-
-
-/*
-==============================================================================
-
- SCREEN SHOTS
-
-NOTE TTimo
-some thoughts about the screenshots system:
-screenshots get written in fs_homepath + fs_gamedir
-vanilla q3 .. baseq3/screenshots/ *.tga
-team arena .. missionpack/screenshots/ *.tga
-
-two commands: "screenshot" and "screenshotJPEG"
-we use statics to store a count and start writing the first screenshot/screenshot????.tga (.jpg) available
-(with FS_FileExists / FS_FOpenFileWrite calls)
-FIXME: the statics don't get a reinit between fs_game changes
-
-==============================================================================
-*/
-
-/*
-==================
-RB_ReadPixels
-
-Reads an image but takes care of alignment issues for reading RGB images.
-
-Reads a minimum offset for where the RGB data starts in the image from
-integer stored at pointer offset. When the function has returned the actual
-offset was written back to address offset. This address will always have an
-alignment of packAlign to ensure efficient copying.
-
-Stores the length of padding after a line of pixels to address padlen
-
-Return value must be freed with ri.Hunk_FreeTempMemory()
-==================
-*/
-
-byte *RB_ReadPixels(int x, int y, int width, int height, size_t *offset, int *padlen)
-{
- byte *buffer, *bufstart;
- int padwidth, linelen;
- GLint packAlign;
-
- qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign);
-
- linelen = width * 3;
- padwidth = PAD(linelen, packAlign);
-
- // Allocate a few more bytes so that we can choose an alignment we like
- buffer = ri.Hunk_AllocateTempMemory(padwidth * height + *offset + packAlign - 1);
-
- bufstart = PADP((intptr_t) buffer + *offset, packAlign);
- qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, bufstart);
-
- *offset = bufstart - buffer;
- *padlen = padwidth - linelen;
-
- return buffer;
-}
-
-/*
-==================
-RB_TakeScreenshot
-==================
-*/
-void RB_TakeScreenshot(int x, int y, int width, int height, char *fileName)
-{
- byte *allbuf, *buffer;
- byte *srcptr, *destptr;
- byte *endline, *endmem;
- byte temp;
-
- int linelen, padlen;
- size_t offset = 18, memcount;
-
- allbuf = RB_ReadPixels(x, y, width, height, &offset, &padlen);
- buffer = allbuf + offset - 18;
-
- Com_Memset (buffer, 0, 18);
- buffer[2] = 2; // uncompressed type
- buffer[12] = width & 255;
- buffer[13] = width >> 8;
- buffer[14] = height & 255;
- buffer[15] = height >> 8;
- buffer[16] = 24; // pixel size
-
- // swap rgb to bgr and remove padding from line endings
- linelen = width * 3;
-
- srcptr = destptr = allbuf + offset;
- endmem = srcptr + (linelen + padlen) * height;
-
- while(srcptr < endmem)
- {
- endline = srcptr + linelen;
-
- while(srcptr < endline)
- {
- temp = srcptr[0];
- *destptr++ = srcptr[2];
- *destptr++ = srcptr[1];
- *destptr++ = temp;
-
- srcptr += 3;
- }
-
- // Skip the pad
- srcptr += padlen;
- }
-
- memcount = linelen * height;
-
- // gamma correct
- if(glConfig.deviceSupportsGamma)
- R_GammaCorrect(allbuf + offset, memcount);
-
- ri.FS_WriteFile(fileName, buffer, memcount + 18);
-
- ri.Hunk_FreeTempMemory(allbuf);
-}
-
-/*
-==================
-RB_TakeScreenshotJPEG
-==================
-*/
-
-void RB_TakeScreenshotJPEG(int x, int y, int width, int height, char *fileName)
-{
- byte *buffer;
- size_t offset = 0, memcount;
- int padlen;
-
- buffer = RB_ReadPixels(x, y, width, height, &offset, &padlen);
- memcount = (width * 3 + padlen) * height;
-
- // gamma correct
- if(glConfig.deviceSupportsGamma)
- R_GammaCorrect(buffer + offset, memcount);
-
- RE_SaveJPG(fileName, r_screenshotJpegQuality->integer, width, height, buffer + offset, padlen);
- ri.Hunk_FreeTempMemory(buffer);
-}
-
-/*
-==================
-RB_TakeScreenshotCmd
-==================
-*/
-const void *RB_TakeScreenshotCmd( const void *data ) {
- const screenshotCommand_t *cmd;
-
- cmd = (const screenshotCommand_t *)data;
-
- // finish any 2D drawing if needed
- if(tess.numIndexes)
- RB_EndSurface();
-
- if (cmd->jpeg)
- RB_TakeScreenshotJPEG( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
- else
- RB_TakeScreenshot( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName);
-
- return (const void *)(cmd + 1);
-}
-
-/*
-==================
-R_TakeScreenshot
-==================
-*/
-void R_TakeScreenshot( int x, int y, int width, int height, char *name, qboolean jpeg ) {
- static char fileName[MAX_OSPATH]; // bad things if two screenshots per frame?
- screenshotCommand_t *cmd;
-
- cmd = R_GetCommandBuffer( sizeof( *cmd ) );
- if ( !cmd ) {
- return;
- }
- cmd->commandId = RC_SCREENSHOT;
-
- cmd->x = x;
- cmd->y = y;
- cmd->width = width;
- cmd->height = height;
- Q_strncpyz( fileName, name, sizeof(fileName) );
- cmd->fileName = fileName;
- cmd->jpeg = jpeg;
-}
-
-/*
-==================
-R_ScreenshotFilename
-==================
-*/
-void R_ScreenshotFilename( int lastNumber, char *fileName ) {
- int a,b,c,d;
-
- if ( lastNumber < 0 || lastNumber > 9999 ) {
- Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.tga" );
- return;
- }
-
- a = lastNumber / 1000;
- lastNumber -= a*1000;
- b = lastNumber / 100;
- lastNumber -= b*100;
- c = lastNumber / 10;
- lastNumber -= c*10;
- d = lastNumber;
-
- Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.tga"
- , a, b, c, d );
-}
-
-/*
-==================
-R_ScreenshotFilename
-==================
-*/
-void R_ScreenshotFilenameJPEG( int lastNumber, char *fileName ) {
- int a,b,c,d;
-
- if ( lastNumber < 0 || lastNumber > 9999 ) {
- Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot9999.jpg" );
- return;
- }
-
- a = lastNumber / 1000;
- lastNumber -= a*1000;
- b = lastNumber / 100;
- lastNumber -= b*100;
- c = lastNumber / 10;
- lastNumber -= c*10;
- d = lastNumber;
-
- Com_sprintf( fileName, MAX_OSPATH, "screenshots/shot%i%i%i%i.jpg"
- , a, b, c, d );
-}
-
-/*
-====================
-R_LevelShot
-
-levelshots are specialized 128*128 thumbnails for
-the menu system, sampled down from full screen distorted images
-====================
-*/
-void R_LevelShot( void ) {
- char checkname[MAX_OSPATH];
- byte *buffer;
- byte *source, *allsource;
- byte *src, *dst;
- size_t offset = 0;
- int padlen;
- int x, y;
- int r, g, b;
- float xScale, yScale;
- int xx, yy;
-
- Com_sprintf(checkname, sizeof(checkname), "levelshots/%s.tga", tr.world->baseName);
-
- allsource = RB_ReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, &offset, &padlen);
- source = allsource + offset;
-
- buffer = ri.Hunk_AllocateTempMemory(128 * 128*3 + 18);
- Com_Memset (buffer, 0, 18);
- buffer[2] = 2; // uncompressed type
- buffer[12] = 128;
- buffer[14] = 128;
- buffer[16] = 24; // pixel size
-
- // resample from source
- xScale = glConfig.vidWidth / 512.0f;
- yScale = glConfig.vidHeight / 384.0f;
- for ( y = 0 ; y < 128 ; y++ ) {
- for ( x = 0 ; x < 128 ; x++ ) {
- r = g = b = 0;
- for ( yy = 0 ; yy < 3 ; yy++ ) {
- for ( xx = 0 ; xx < 4 ; xx++ ) {
- src = source + (3 * glConfig.vidWidth + padlen) * (int)((y*3 + yy) * yScale) +
- 3 * (int) ((x*4 + xx) * xScale);
- r += src[0];
- g += src[1];
- b += src[2];
- }
- }
- dst = buffer + 18 + 3 * ( y * 128 + x );
- dst[0] = b / 12;
- dst[1] = g / 12;
- dst[2] = r / 12;
- }
- }
-
- // gamma correct
- if ( glConfig.deviceSupportsGamma ) {
- R_GammaCorrect( buffer + 18, 128 * 128 * 3 );
- }
-
- ri.FS_WriteFile( checkname, buffer, 128 * 128*3 + 18 );
-
- ri.Hunk_FreeTempMemory(buffer);
- ri.Hunk_FreeTempMemory(allsource);
-
- ri.Printf( PRINT_ALL, "Wrote %s\n", checkname );
-}
-
-/*
-==================
-R_ScreenShot_f
-
-screenshot
-screenshot [silent]
-screenshot [levelshot]
-screenshot [filename]
-
-Doesn't print the pacifier message if there is a second arg
-==================
-*/
-void R_ScreenShot_f (void) {
- char checkname[MAX_OSPATH];
- static int lastNumber = -1;
- qboolean silent;
-
- if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
- R_LevelShot();
- return;
- }
-
- if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) {
- silent = qtrue;
- } else {
- silent = qfalse;
- }
-
- if ( ri.Cmd_Argc() == 2 && !silent ) {
- // explicit filename
- Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.tga", ri.Cmd_Argv( 1 ) );
- } else {
- // scan for a free filename
-
- // if we have saved a previous screenshot, don't scan
- // again, because recording demo avis can involve
- // thousands of shots
- if ( lastNumber == -1 ) {
- lastNumber = 0;
- }
- // scan for a free number
- for ( ; lastNumber <= 9999 ; lastNumber++ ) {
- R_ScreenshotFilename( lastNumber, checkname );
-
- if (!ri.FS_FileExists( checkname ))
- {
- break; // file doesn't exist
- }
- }
-
- if ( lastNumber >= 9999 ) {
- ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n");
- return;
- }
-
- lastNumber++;
- }
-
- R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qfalse );
-
- if ( !silent ) {
- ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
- }
-}
-
-void R_ScreenShotJPEG_f (void) {
- char checkname[MAX_OSPATH];
- static int lastNumber = -1;
- qboolean silent;
-
- if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) {
- R_LevelShot();
- return;
- }
-
- if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) {
- silent = qtrue;
- } else {
- silent = qfalse;
- }
-
- if ( ri.Cmd_Argc() == 2 && !silent ) {
- // explicit filename
- Com_sprintf( checkname, MAX_OSPATH, "screenshots/%s.jpg", ri.Cmd_Argv( 1 ) );
- } else {
- // scan for a free filename
-
- // if we have saved a previous screenshot, don't scan
- // again, because recording demo avis can involve
- // thousands of shots
- if ( lastNumber == -1 ) {
- lastNumber = 0;
- }
- // scan for a free number
- for ( ; lastNumber <= 9999 ; lastNumber++ ) {
- R_ScreenshotFilenameJPEG( lastNumber, checkname );
-
- if (!ri.FS_FileExists( checkname ))
- {
- break; // file doesn't exist
- }
- }
-
- if ( lastNumber == 10000 ) {
- ri.Printf (PRINT_ALL, "ScreenShot: Couldn't create a file\n");
- return;
- }
-
- lastNumber++;
- }
-
- R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, qtrue );
-
- if ( !silent ) {
- ri.Printf (PRINT_ALL, "Wrote %s\n", checkname);
- }
-}
-
-//============================================================================
-
-/*
-==================
-RB_TakeVideoFrameCmd
-==================
-*/
-const void *RB_TakeVideoFrameCmd( const void *data )
-{
- const videoFrameCommand_t *cmd;
- byte *cBuf;
- size_t memcount, linelen;
- int padwidth, avipadwidth, padlen, avipadlen;
- GLint packAlign;
-
- // finish any 2D drawing if needed
- if(tess.numIndexes)
- RB_EndSurface();
-
- cmd = (const videoFrameCommand_t *)data;
-
- qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign);
-
- linelen = cmd->width * 3;
-
- // Alignment stuff for glReadPixels
- padwidth = PAD(linelen, packAlign);
- padlen = padwidth - linelen;
- // AVI line padding
- avipadwidth = PAD(linelen, AVI_LINE_PADDING);
- avipadlen = avipadwidth - linelen;
-
- cBuf = PADP(cmd->captureBuffer, packAlign);
-
- qglReadPixels(0, 0, cmd->width, cmd->height, GL_RGB,
- GL_UNSIGNED_BYTE, cBuf);
-
- memcount = padwidth * cmd->height;
-
- // gamma correct
- if(glConfig.deviceSupportsGamma)
- R_GammaCorrect(cBuf, memcount);
-
- if(cmd->motionJpeg)
- {
- memcount = RE_SaveJPGToBuffer(cmd->encodeBuffer, linelen * cmd->height,
- r_aviMotionJpegQuality->integer,
- cmd->width, cmd->height, cBuf, padlen);
- ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, memcount);
- }
- else
- {
- byte *lineend, *memend;
- byte *srcptr, *destptr;
-
- srcptr = cBuf;
- destptr = cmd->encodeBuffer;
- memend = srcptr + memcount;
-
- // swap R and B and remove line paddings
- while(srcptr < memend)
- {
- lineend = srcptr + linelen;
- while(srcptr < lineend)
- {
- *destptr++ = srcptr[2];
- *destptr++ = srcptr[1];
- *destptr++ = srcptr[0];
- srcptr += 3;
- }
-
- Com_Memset(destptr, '\0', avipadlen);
- destptr += avipadlen;
-
- srcptr += padlen;
- }
-
- ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, avipadwidth * cmd->height);
- }
-
- return (const void *)(cmd + 1);
-}
-
-//============================================================================
-
-/*
-** GL_SetDefaultState
-*/
-void GL_SetDefaultState( void )
-{
- qglClearDepth( 1.0f );
-
- qglCullFace(GL_FRONT);
-
- qglColor4f (1,1,1,1);
-
- // initialize downstream texture unit if we're running
- // in a multitexture environment
- if ( qglActiveTextureARB ) {
- GL_SelectTexture( 1 );
- GL_TextureMode( r_textureMode->string );
- GL_TexEnv( GL_MODULATE );
- qglDisable( GL_TEXTURE_2D );
- GL_SelectTexture( 0 );
- }
-
- qglEnable(GL_TEXTURE_2D);
- GL_TextureMode( r_textureMode->string );
- GL_TexEnv( GL_MODULATE );
-
- //qglShadeModel( GL_SMOOTH );
- qglDepthFunc( GL_LEQUAL );
-
- //
- // make sure our GL state vector is set correctly
- //
- glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE;
-
- glState.vertexAttribsState = 0;
- glState.vertexAttribPointersSet = 0;
- glState.currentProgram = 0;
- qglUseProgramObjectARB(0);
-
- qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
- glState.currentVBO = NULL;
- glState.currentIBO = NULL;
-
- qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
- qglDepthMask( GL_TRUE );
- qglDisable( GL_DEPTH_TEST );
- qglEnable( GL_SCISSOR_TEST );
- qglDisable( GL_CULL_FACE );
- qglDisable( GL_BLEND );
-}
-
-/*
-================
-R_PrintLongString
-
-Workaround for ri.Printf's 1024 characters buffer limit.
-================
-*/
-void R_PrintLongString(const char *string) {
- char buffer[1024];
- const char *p;
- int size = strlen(string);
-
- p = string;
- while(size > 0)
- {
- Q_strncpyz(buffer, p, sizeof (buffer) );
- ri.Printf( PRINT_ALL, "%s", buffer );
- p += 1023;
- size -= 1023;
- }
-}
-
-/*
-================
-GfxInfo_f
-================
-*/
-void GfxInfo_f( void )
-{
- const char *enablestrings[] =
- {
- "disabled",
- "enabled"
- };
- const char *fsstrings[] =
- {
- "windowed",
- "fullscreen"
- };
-
- ri.Printf( PRINT_ALL, "\nGL_VENDOR: %s\n", glConfig.vendor_string );
- ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glConfig.renderer_string );
- ri.Printf( PRINT_ALL, "GL_VERSION: %s\n", glConfig.version_string );
- ri.Printf( PRINT_ALL, "GL_EXTENSIONS: " );
- R_PrintLongString( glConfig.extensions_string );
- ri.Printf( PRINT_ALL, "\n" );
- ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize );
- ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_UNITS_ARB: %d\n", glConfig.numTextureUnits );
- ri.Printf( PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits );
- ri.Printf( PRINT_ALL, "MODE: %d, %d x %d %s hz:", r_mode->integer, glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen->integer == 1] );
- if ( glConfig.displayFrequency )
- {
- ri.Printf( PRINT_ALL, "%d\n", glConfig.displayFrequency );
- }
- else
- {
- ri.Printf( PRINT_ALL, "N/A\n" );
- }
- if ( glConfig.deviceSupportsGamma )
- {
- ri.Printf( PRINT_ALL, "GAMMA: hardware w/ %d overbright bits\n", tr.overbrightBits );
- }
- else
- {
- ri.Printf( PRINT_ALL, "GAMMA: software w/ %d overbright bits\n", tr.overbrightBits );
- }
-
- ri.Printf( PRINT_ALL, "texturemode: %s\n", r_textureMode->string );
- ri.Printf( PRINT_ALL, "picmip: %d\n", r_picmip->integer );
- ri.Printf( PRINT_ALL, "texture bits: %d\n", r_texturebits->integer );
- ri.Printf( PRINT_ALL, "multitexture: %s\n", enablestrings[qglActiveTextureARB != 0] );
- ri.Printf( PRINT_ALL, "compiled vertex arrays: %s\n", enablestrings[qglLockArraysEXT != 0 ] );
- ri.Printf( PRINT_ALL, "texenv add: %s\n", enablestrings[glConfig.textureEnvAddAvailable != 0] );
- ri.Printf( PRINT_ALL, "compressed textures: %s\n", enablestrings[glConfig.textureCompression!=TC_NONE] );
- if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 )
- {
- ri.Printf( PRINT_ALL, "HACK: using vertex lightmap approximation\n" );
- }
- if ( glConfig.hardwareType == GLHW_RAGEPRO )
- {
- ri.Printf( PRINT_ALL, "HACK: ragePro approximations\n" );
- }
- if ( glConfig.hardwareType == GLHW_RIVA128 )
- {
- ri.Printf( PRINT_ALL, "HACK: riva128 approximations\n" );
- }
- if ( r_finish->integer ) {
- ri.Printf( PRINT_ALL, "Forcing glFinish\n" );
- }
-}
-
-/*
-================
-GfxMemInfo_f
-================
-*/
-void GfxMemInfo_f( void )
-{
- switch (glRefConfig.memInfo)
- {
- case MI_NONE:
- {
- ri.Printf(PRINT_ALL, "No extension found for GPU memory info.\n");
- }
- break;
- case MI_NVX:
- {
- int value;
-
- qglGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &value);
- ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX: %ikb\n", value);
-
- qglGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &value);
- ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX: %ikb\n", value);
-
- qglGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &value);
- ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX: %ikb\n", value);
-
- qglGetIntegerv(GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX, &value);
- ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_EVICTION_COUNT_NVX: %i\n", value);
-
- qglGetIntegerv(GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX, &value);
- ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_EVICTED_MEMORY_NVX: %ikb\n", value);
- }
- break;
- case MI_ATI:
- {
- // GL_ATI_meminfo
- int value[4];
-
- qglGetIntegerv(GL_VBO_FREE_MEMORY_ATI, &value[0]);
- ri.Printf(PRINT_ALL, "VBO_FREE_MEMORY_ATI: %ikb total %ikb largest aux: %ikb total %ikb largest\n", value[0], value[1], value[2], value[3]);
-
- qglGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, &value[0]);
- ri.Printf(PRINT_ALL, "TEXTURE_FREE_MEMORY_ATI: %ikb total %ikb largest aux: %ikb total %ikb largest\n", value[0], value[1], value[2], value[3]);
-
- qglGetIntegerv(GL_RENDERBUFFER_FREE_MEMORY_ATI, &value[0]);
- ri.Printf(PRINT_ALL, "RENDERBUFFER_FREE_MEMORY_ATI: %ikb total %ikb largest aux: %ikb total %ikb largest\n", value[0], value[1], value[2], value[3]);
- }
- break;
- }
-}
-
-/*
-===============
-R_Register
-===============
-*/
-void R_Register( void )
-{
- #ifdef USE_RENDERER_DLOPEN
- com_altivec = ri.Cvar_Get("com_altivec", "1", CVAR_ARCHIVE);
- #endif
-
- //
- // latched and archived variables
- //
- r_allowExtensions = ri.Cvar_Get( "r_allowExtensions", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_ext_compressed_textures = ri.Cvar_Get( "r_ext_compressed_textures", "0", CVAR_ARCHIVE | CVAR_LATCH );
- r_ext_multitexture = ri.Cvar_Get( "r_ext_multitexture", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_ext_compiled_vertex_array = ri.Cvar_Get( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE | CVAR_LATCH);
- r_ext_texture_env_add = ri.Cvar_Get( "r_ext_texture_env_add", "1", CVAR_ARCHIVE | CVAR_LATCH);
-
- r_ext_draw_range_elements = ri.Cvar_Get( "r_ext_draw_range_elements", "1", CVAR_ARCHIVE | CVAR_LATCH);
- r_ext_multi_draw_arrays = ri.Cvar_Get( "r_ext_multi_draw_arrays", "1", CVAR_ARCHIVE | CVAR_LATCH);
- r_ext_framebuffer_object = ri.Cvar_Get( "r_ext_framebuffer_object", "1", CVAR_ARCHIVE | CVAR_LATCH);
- r_ext_texture_float = ri.Cvar_Get( "r_ext_texture_float", "1", CVAR_ARCHIVE | CVAR_LATCH);
- r_arb_half_float_pixel = ri.Cvar_Get( "r_arb_half_float_pixel", "1", CVAR_ARCHIVE | CVAR_LATCH);
- r_ext_framebuffer_multisample = ri.Cvar_Get( "r_ext_framebuffer_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH);
-
- r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic",
- "0", CVAR_ARCHIVE | CVAR_LATCH );
- r_ext_max_anisotropy = ri.Cvar_Get( "r_ext_max_anisotropy", "2", CVAR_ARCHIVE | CVAR_LATCH );
-
- r_picmip = ri.Cvar_Get ("r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_roundImagesDown = ri.Cvar_Get ("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_colorMipLevels = ri.Cvar_Get ("r_colorMipLevels", "0", CVAR_LATCH );
- ri.Cvar_CheckRange( r_picmip, 0, 16, qtrue );
- r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_texturebits = ri.Cvar_Get( "r_texturebits", "0", CVAR_ARCHIVE | CVAR_LATCH );
- r_colorbits = ri.Cvar_Get( "r_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
- r_stencilbits = ri.Cvar_Get( "r_stencilbits", "8", CVAR_ARCHIVE | CVAR_LATCH );
- r_depthbits = ri.Cvar_Get( "r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH );
- r_ext_multisample = ri.Cvar_Get( "r_ext_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH );
- ri.Cvar_CheckRange( r_ext_multisample, 0, 4, qtrue );
- r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE | CVAR_LATCH);
- r_mode = ri.Cvar_Get( "r_mode", "-2", CVAR_ARCHIVE | CVAR_LATCH );
- r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE );
- r_noborder = ri.Cvar_Get("r_noborder", "0", CVAR_ARCHIVE);
- r_width = ri.Cvar_Get( "r_width", "640", CVAR_ARCHIVE | CVAR_LATCH );
- r_height = ri.Cvar_Get( "r_height", "480", CVAR_ARCHIVE | CVAR_LATCH );
- r_pixelAspect = ri.Cvar_Get( "r_pixelAspect", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_simpleMipMaps = ri.Cvar_Get( "r_simpleMipMaps", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_vertexLight = ri.Cvar_Get( "r_vertexLight", "0", CVAR_ARCHIVE | CVAR_LATCH );
- r_uiFullScreen = ri.Cvar_Get( "r_uifullscreen", "0", 0);
- r_subdivisions = ri.Cvar_Get ("r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH);
- r_stereoEnabled = ri.Cvar_Get( "r_stereoEnabled", "0", CVAR_ARCHIVE | CVAR_LATCH);
- r_greyscale = ri.Cvar_Get("r_greyscale", "0", CVAR_ARCHIVE | CVAR_LATCH);
- ri.Cvar_CheckRange(r_greyscale, 0, 1, qfalse);
-
- r_softOverbright = ri.Cvar_Get( "r_softOverbright", "1", CVAR_ARCHIVE | CVAR_LATCH );
-
- r_hdr = ri.Cvar_Get( "r_hdr", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE );
-
- r_toneMap = ri.Cvar_Get( "r_toneMap", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_forceToneMap = ri.Cvar_Get( "r_forceToneMap", "0", CVAR_CHEAT );
- r_forceToneMapMin = ri.Cvar_Get( "r_forceToneMapMin", "-8.0", CVAR_CHEAT );
- r_forceToneMapAvg = ri.Cvar_Get( "r_forceToneMapAvg", "-2.0", CVAR_CHEAT );
- r_forceToneMapMax = ri.Cvar_Get( "r_forceToneMapMax", "0.0", CVAR_CHEAT );
-
- r_autoExposure = ri.Cvar_Get( "r_autoExposure", "1", CVAR_ARCHIVE );
- r_forceAutoExposure = ri.Cvar_Get( "r_forceAutoExposure", "0", CVAR_CHEAT );
- r_forceAutoExposureMin = ri.Cvar_Get( "r_forceAutoExposureMin", "-2.0", CVAR_CHEAT );
- r_forceAutoExposureMax = ri.Cvar_Get( "r_forceAutoExposureMax", "2.0", CVAR_CHEAT );
-
- r_cameraExposure = ri.Cvar_Get( "r_cameraExposure", "0", CVAR_CHEAT );
-
- r_srgb = ri.Cvar_Get( "r_srgb", "0", CVAR_ARCHIVE | CVAR_LATCH );
-
- r_depthPrepass = ri.Cvar_Get( "r_depthPrepass", "1", CVAR_ARCHIVE );
- r_ssao = ri.Cvar_Get( "r_ssao", "0", CVAR_LATCH | CVAR_ARCHIVE );
-
- r_normalMapping = ri.Cvar_Get( "r_normalMapping", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_specularMapping = ri.Cvar_Get( "r_specularMapping", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
- r_normalAmbient = ri.Cvar_Get( "r_normalAmbient", "0", CVAR_ARCHIVE | CVAR_LATCH );
- r_dlightMode = ri.Cvar_Get( "r_dlightMode", "0", CVAR_ARCHIVE | CVAR_LATCH );
- r_pshadowDist = ri.Cvar_Get( "r_pshadowDist", "128", CVAR_ARCHIVE );
- r_recalcMD3Normals = ri.Cvar_Get( "r_recalcMD3Normals", "0", CVAR_ARCHIVE | CVAR_LATCH );
- r_mergeLightmaps = ri.Cvar_Get( "r_mergeLightmaps", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_imageUpsample = ri.Cvar_Get( "r_imageUpsample", "0", CVAR_ARCHIVE | CVAR_LATCH );
- r_imageUpsampleMaxSize = ri.Cvar_Get( "r_imageUpsampleMaxSize", "1024", CVAR_ARCHIVE | CVAR_LATCH );
- r_imageUpsampleType = ri.Cvar_Get( "r_imageUpsampleType", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_genNormalMaps = ri.Cvar_Get( "r_genNormalMaps", "0", CVAR_ARCHIVE | CVAR_LATCH );
-
- r_forceSun = ri.Cvar_Get( "r_forceSun", "0", CVAR_CHEAT );
- r_forceSunMapLightScale = ri.Cvar_Get( "r_forceSunMapLightScale", "0.5", CVAR_CHEAT );
- r_forceSunLightScale = ri.Cvar_Get( "r_forceSunLightScale", "0.5", CVAR_CHEAT );
- r_forceSunAmbientScale = ri.Cvar_Get( "r_forceSunAmbientScale", "0.2", CVAR_CHEAT );
- r_drawSunRays = ri.Cvar_Get( "r_drawSunRays", "0", CVAR_ARCHIVE | CVAR_LATCH );
-
- r_sunShadows = ri.Cvar_Get( "r_sunShadows", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_shadowFilter = ri.Cvar_Get( "r_shadowFilter", "1", CVAR_ARCHIVE | CVAR_LATCH );
- r_shadowMapSize = ri.Cvar_Get( "r_shadowMapSize", "1024", CVAR_ARCHIVE | CVAR_LATCH );
- r_shadowCascadeZNear = ri.Cvar_Get( "r_shadowCascadeZNear", "4", CVAR_ARCHIVE | CVAR_LATCH );
- r_shadowCascadeZFar = ri.Cvar_Get( "r_shadowCascadeZFar", "3072", CVAR_ARCHIVE | CVAR_LATCH );
- r_shadowCascadeZBias = ri.Cvar_Get( "r_shadowCascadeZBias", "-320", CVAR_ARCHIVE | CVAR_LATCH );
-
- //
- // temporary latched variables that can only change over a restart
- //
- r_fullbright = ri.Cvar_Get ("r_fullbright", "0", CVAR_LATCH|CVAR_CHEAT );
- r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "2", CVAR_LATCH );
- r_intensity = ri.Cvar_Get ("r_intensity", "1", CVAR_LATCH );
- r_singleShader = ri.Cvar_Get ("r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH );
-
- //
- // archived variables that can change at any time
- //
- r_lodCurveError = ri.Cvar_Get( "r_lodCurveError", "250", CVAR_ARCHIVE|CVAR_CHEAT );
- r_lodbias = ri.Cvar_Get( "r_lodbias", "0", CVAR_ARCHIVE );
- r_flares = ri.Cvar_Get ("r_flares", "0", CVAR_ARCHIVE );
- r_znear = ri.Cvar_Get( "r_znear", "4", CVAR_CHEAT );
- ri.Cvar_CheckRange( r_znear, 0.001f, 200, qfalse );
- r_zproj = ri.Cvar_Get( "r_zproj", "64", CVAR_ARCHIVE );
- r_stereoSeparation = ri.Cvar_Get( "r_stereoSeparation", "64", CVAR_ARCHIVE );
- r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE );
- r_fastsky = ri.Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE );
- r_inGameVideo = ri.Cvar_Get( "r_inGameVideo", "1", CVAR_ARCHIVE );
- r_drawSun = ri.Cvar_Get( "r_drawSun", "0", CVAR_ARCHIVE );
- r_dynamiclight = ri.Cvar_Get( "r_dynamiclight", "1", CVAR_ARCHIVE );
- r_dlightBacks = ri.Cvar_Get( "r_dlightBacks", "1", CVAR_ARCHIVE );
- r_finish = ri.Cvar_Get ("r_finish", "0", CVAR_ARCHIVE);
- r_textureMode = ri.Cvar_Get( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE );
- r_swapInterval = ri.Cvar_Get( "r_swapInterval", "0",
- CVAR_ARCHIVE | CVAR_LATCH );
- r_gamma = ri.Cvar_Get( "r_gamma", "1", CVAR_ARCHIVE );
- r_facePlaneCull = ri.Cvar_Get ("r_facePlaneCull", "1", CVAR_ARCHIVE );
-
- r_railWidth = ri.Cvar_Get( "r_railWidth", "16", CVAR_ARCHIVE );
- r_railCoreWidth = ri.Cvar_Get( "r_railCoreWidth", "6", CVAR_ARCHIVE );
- r_railSegmentLength = ri.Cvar_Get( "r_railSegmentLength", "32", CVAR_ARCHIVE );
-
- r_ambientScale = ri.Cvar_Get( "r_ambientScale", "0.6", CVAR_CHEAT );
- r_directedScale = ri.Cvar_Get( "r_directedScale", "1", CVAR_CHEAT );
-
- r_anaglyphMode = ri.Cvar_Get("r_anaglyphMode", "0", CVAR_ARCHIVE);
- r_mergeMultidraws = ri.Cvar_Get("r_mergeMultidraws", "1", CVAR_ARCHIVE);
- r_mergeLeafSurfaces = ri.Cvar_Get("r_mergeLeafSurfaces", "1", CVAR_ARCHIVE);
-
- //
- // temporary variables that can change at any time
- //
- r_showImages = ri.Cvar_Get( "r_showImages", "0", CVAR_TEMP );
-
- r_debugLight = ri.Cvar_Get( "r_debuglight", "0", CVAR_TEMP );
- r_debugSort = ri.Cvar_Get( "r_debugSort", "0", CVAR_CHEAT );
- r_printShaders = ri.Cvar_Get( "r_printShaders", "0", 0 );
- r_saveFontData = ri.Cvar_Get( "r_saveFontData", "0", 0 );
-
- r_nocurves = ri.Cvar_Get ("r_nocurves", "0", CVAR_CHEAT );
- r_drawworld = ri.Cvar_Get ("r_drawworld", "1", CVAR_CHEAT );
- r_lightmap = ri.Cvar_Get ("r_lightmap", "0", 0 );
- r_portalOnly = ri.Cvar_Get ("r_portalOnly", "0", CVAR_CHEAT );
-
- r_flareSize = ri.Cvar_Get ("r_flareSize", "40", CVAR_CHEAT);
- r_flareFade = ri.Cvar_Get ("r_flareFade", "7", CVAR_CHEAT);
- r_flareCoeff = ri.Cvar_Get ("r_flareCoeff", FLARE_STDCOEFF, CVAR_CHEAT);
-
- r_skipBackEnd = ri.Cvar_Get ("r_skipBackEnd", "0", CVAR_CHEAT);
-
- r_measureOverdraw = ri.Cvar_Get( "r_measureOverdraw", "0", CVAR_CHEAT );
- r_lodscale = ri.Cvar_Get( "r_lodscale", "5", CVAR_CHEAT );
- r_norefresh = ri.Cvar_Get ("r_norefresh", "0", CVAR_CHEAT);
- r_drawentities = ri.Cvar_Get ("r_drawentities", "1", CVAR_CHEAT );
- r_ignore = ri.Cvar_Get( "r_ignore", "1", CVAR_CHEAT );
- r_nocull = ri.Cvar_Get ("r_nocull", "0", CVAR_CHEAT);
- r_novis = ri.Cvar_Get ("r_novis", "0", CVAR_CHEAT);
- r_showcluster = ri.Cvar_Get ("r_showcluster", "0", CVAR_CHEAT);
- r_speeds = ri.Cvar_Get ("r_speeds", "0", CVAR_CHEAT);
- r_verbose = ri.Cvar_Get( "r_verbose", "0", CVAR_CHEAT );
- r_logFile = ri.Cvar_Get( "r_logFile", "0", CVAR_CHEAT );
- r_debugSurface = ri.Cvar_Get ("r_debugSurface", "0", CVAR_CHEAT);
- r_nobind = ri.Cvar_Get ("r_nobind", "0", CVAR_CHEAT);
- r_showtris = ri.Cvar_Get ("r_showtris", "0", CVAR_CHEAT);
- r_showsky = ri.Cvar_Get ("r_showsky", "0", CVAR_CHEAT);
- r_shownormals = ri.Cvar_Get ("r_shownormals", "0", CVAR_CHEAT);
- r_clear = ri.Cvar_Get ("r_clear", "0", CVAR_CHEAT);
- r_offsetFactor = ri.Cvar_Get( "r_offsetfactor", "-1", CVAR_CHEAT );
- r_offsetUnits = ri.Cvar_Get( "r_offsetunits", "-2", CVAR_CHEAT );
- r_drawBuffer = ri.Cvar_Get( "r_drawBuffer", "GL_BACK", CVAR_CHEAT );
- r_lockpvs = ri.Cvar_Get ("r_lockpvs", "0", CVAR_CHEAT);
- r_noportals = ri.Cvar_Get ("r_noportals", "0", CVAR_CHEAT);
- r_shadows = ri.Cvar_Get( "cg_shadows", "1", 0 );
-
- r_marksOnTriangleMeshes = ri.Cvar_Get("r_marksOnTriangleMeshes", "0", CVAR_ARCHIVE);
-
- r_aviMotionJpegQuality = ri.Cvar_Get("r_aviMotionJpegQuality", "90", CVAR_ARCHIVE);
- r_screenshotJpegQuality = ri.Cvar_Get("r_screenshotJpegQuality", "90", CVAR_ARCHIVE);
-
- r_maxpolys = ri.Cvar_Get( "r_maxpolys", va("%d", MAX_POLYS), 0);
- r_maxpolyverts = ri.Cvar_Get( "r_maxpolyverts", va("%d", MAX_POLYVERTS), 0);
-
- // make sure all the commands added here are also
- // removed in R_Shutdown
- ri.Cmd_AddCommand( "imagelist", R_ImageList_f );
- ri.Cmd_AddCommand( "shaderlist", R_ShaderList_f );
- ri.Cmd_AddCommand( "skinlist", R_SkinList_f );
- ri.Cmd_AddCommand( "modellist", R_Modellist_f );
- ri.Cmd_AddCommand( "screenshot", R_ScreenShot_f );
- ri.Cmd_AddCommand( "screenshotJPEG", R_ScreenShotJPEG_f );
- ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
- ri.Cmd_AddCommand( "minimize", GLimp_Minimize );
- ri.Cmd_AddCommand( "gfxmeminfo", GfxMemInfo_f );
-}
-
-void R_InitQueries(void)
-{
- if (!glRefConfig.occlusionQuery)
- return;
-
- if (r_drawSunRays->integer)
- qglGenQueriesARB(ARRAY_LEN(tr.sunFlareQuery), tr.sunFlareQuery);
-}
-
-void R_ShutDownQueries(void)
-{
- if (!glRefConfig.occlusionQuery)
- return;
-
- if (r_drawSunRays->integer)
- qglDeleteQueriesARB(ARRAY_LEN(tr.sunFlareQuery), tr.sunFlareQuery);
-}
-
-/*
-===============
-R_Init
-===============
-*/
-void R_Init( void ) {
- int err;
- int i;
- byte *ptr;
-
- ri.Printf( PRINT_ALL, "----- R_Init -----\n" );
-
- // clear all our internal state
- Com_Memset( &tr, 0, sizeof( tr ) );
- Com_Memset( &backEnd, 0, sizeof( backEnd ) );
- Com_Memset( &tess, 0, sizeof( tess ) );
-
-// Swap_Init();
-
- if ( (intptr_t)tess.xyz & 15 ) {
- ri.Printf( PRINT_WARNING, "tess.xyz not 16 byte aligned\n" );
- }
- //Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) );
-
- //
- // init function tables
- //
- for ( i = 0; i < FUNCTABLE_SIZE; i++ )
- {
- tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) );
- tr.squareTable[i] = ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f;
- tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE;
- tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i];
-
- if ( i < FUNCTABLE_SIZE / 2 )
- {
- if ( i < FUNCTABLE_SIZE / 4 )
- {
- tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 );
- }
- else
- {
- tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4];
- }
- }
- else
- {
- tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2];
- }
- }
-
- R_InitFogTable();
-
- R_NoiseInit();
-
- R_Register();
-
- max_polys = r_maxpolys->integer;
- if (max_polys < MAX_POLYS)
- max_polys = MAX_POLYS;
-
- max_polyverts = r_maxpolyverts->integer;
- if (max_polyverts < MAX_POLYVERTS)
- max_polyverts = MAX_POLYVERTS;
-
- ptr = ri.Hunk_Alloc( sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low);
- backEndData = (backEndData_t *) ptr;
- backEndData->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData ));
- backEndData->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys);
- R_InitNextFrame();
-
- InitOpenGL();
-
- R_InitImages();
-
- if (glRefConfig.framebufferObject)
- FBO_Init();
-
- GLSL_InitGPUShaders();
-
- R_InitVBOs();
-
- R_InitShaders();
-
- R_InitSkins();
-
- R_ModelInit();
-
- R_InitFreeType();
-
- R_InitQueries();
-
-
- err = qglGetError();
- if ( err != GL_NO_ERROR )
- ri.Printf (PRINT_ALL, "glGetError() = 0x%x\n", err);
-
- // print info
- GfxInfo_f();
- ri.Printf( PRINT_ALL, "----- finished R_Init -----\n" );
-}
-
-/*
-===============
-RE_Shutdown
-===============
-*/
-void RE_Shutdown( qboolean destroyWindow ) {
-
- ri.Printf( PRINT_ALL, "RE_Shutdown( %i )\n", destroyWindow );
-
- ri.Cmd_RemoveCommand ("modellist");
- ri.Cmd_RemoveCommand ("screenshotJPEG");
- ri.Cmd_RemoveCommand ("screenshot");
- ri.Cmd_RemoveCommand ("imagelist");
- ri.Cmd_RemoveCommand ("shaderlist");
- ri.Cmd_RemoveCommand ("skinlist");
- ri.Cmd_RemoveCommand ("gfxinfo");
- ri.Cmd_RemoveCommand("minimize");
- ri.Cmd_RemoveCommand( "shaderstate" );
- ri.Cmd_RemoveCommand( "gfxmeminfo" );
-
-
- if ( tr.registered ) {
- R_IssuePendingRenderCommands();
- R_ShutDownQueries();
- if (glRefConfig.framebufferObject)
- FBO_Shutdown();
- R_DeleteTextures();
- R_ShutdownVBOs();
- GLSL_ShutdownGPUShaders();
- }
-
- R_DoneFreeType();
-
- // shut down platform specific OpenGL stuff
- if ( destroyWindow ) {
- GLimp_Shutdown();
- }
-
- tr.registered = qfalse;
-}
-
-
-/*
-=============
-RE_EndRegistration
-
-Touch all images to make sure they are resident
-=============
-*/
-void RE_EndRegistration( void ) {
- R_IssuePendingRenderCommands();
- if (!ri.Sys_LowPhysicalMemory()) {
- RB_ShowImages();
- }
-}
-
-
-/*
-@@@@@@@@@@@@@@@@@@@@@
-GetRefAPI
-
-@@@@@@@@@@@@@@@@@@@@@
-*/
-#ifdef USE_RENDERER_DLOPEN
-Q_EXPORT refexport_t* QDECL GetRefAPI ( int apiVersion, refimport_t *rimp ) {
-#else
-refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) {
-#endif
-
- static refexport_t re;
-
- ri = *rimp;
-
- Com_Memset( &re, 0, sizeof( re ) );
-
- if ( apiVersion != REF_API_VERSION ) {
- ri.Printf(PRINT_ALL, "Mismatched REF_API_VERSION: expected %i, got %i\n",
- REF_API_VERSION, apiVersion );
- return NULL;
- }
-
- // the RE_ functions are Renderer Entry points
-
- re.Shutdown = RE_Shutdown;
-
- re.BeginRegistration = RE_BeginRegistration;
- re.RegisterModel = RE_RegisterModel;
- re.RegisterSkin = RE_RegisterSkin;
- re.RegisterShader = RE_RegisterShader;
- re.RegisterShaderNoMip = RE_RegisterShaderNoMip;
- re.LoadWorld = RE_LoadWorldMap;
- re.SetWorldVisData = RE_SetWorldVisData;
- re.EndRegistration = RE_EndRegistration;
-
- re.BeginFrame = RE_BeginFrame;
- re.EndFrame = RE_EndFrame;
-
- re.MarkFragments = R_MarkFragments;
- re.LerpTag = R_LerpTag;
- re.ModelBounds = R_ModelBounds;
-
- re.ClearScene = RE_ClearScene;
- re.AddRefEntityToScene = RE_AddRefEntityToScene;
- re.AddPolyToScene = RE_AddPolyToScene;
- re.LightForPoint = R_LightForPoint;
- re.AddLightToScene = RE_AddLightToScene;
- re.AddAdditiveLightToScene = RE_AddAdditiveLightToScene;
- re.RenderScene = RE_RenderScene;
-
- re.SetColor = RE_SetColor;
- re.SetClipRegion = RE_SetClipRegion;
- re.DrawStretchPic = RE_StretchPic;
- re.DrawStretchRaw = RE_StretchRaw;
- re.UploadCinematic = RE_UploadCinematic;
-
- re.RegisterFont = RE_RegisterFont;
- re.RemapShader = R_RemapShader;
- re.GetEntityToken = R_GetEntityToken;
- re.inPVS = R_inPVS;
-
- re.TakeVideoFrame = RE_TakeVideoFrame;
-
- return &re;
-}
diff --git a/src/rend2/tr_light.c b/src/rend2/tr_light.c
deleted file mode 100644
index 4e90ce20..00000000
--- a/src/rend2/tr_light.c
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_light.c
-
-#include "tr_local.h"
-
-#define DLIGHT_AT_RADIUS 16
-// at the edge of a dlight's influence, this amount of light will be added
-
-#define DLIGHT_MINIMUM_RADIUS 16
-// never calculate a range less than this to prevent huge light numbers
-
-
-/*
-===============
-R_TransformDlights
-
-Transforms the origins of an array of dlights.
-Used by both the front end (for DlightBmodel) and
-the back end (before doing the lighting calculation)
-===============
-*/
-void R_TransformDlights( int count, dlight_t *dl, orientationr_t *or) {
- int i;
- vec3_t temp;
-
- for ( i = 0 ; i < count ; i++, dl++ ) {
- VectorSubtract( dl->origin, or->origin, temp );
- dl->transformed[0] = DotProduct( temp, or->axis[0] );
- dl->transformed[1] = DotProduct( temp, or->axis[1] );
- dl->transformed[2] = DotProduct( temp, or->axis[2] );
- }
-}
-
-/*
-=============
-R_DlightBmodel
-
-Determine which dynamic lights may effect this bmodel
-=============
-*/
-void R_DlightBmodel( bmodel_t *bmodel ) {
- int i, j;
- dlight_t *dl;
- int mask;
- msurface_t *surf;
-
- // transform all the lights
- R_TransformDlights( tr.refdef.num_dlights, tr.refdef.dlights, &tr.or );
-
- mask = 0;
- for ( i=0 ; i<tr.refdef.num_dlights ; i++ ) {
- dl = &tr.refdef.dlights[i];
-
- // see if the point is close enough to the bounds to matter
- for ( j = 0 ; j < 3 ; j++ ) {
- if ( dl->transformed[j] - bmodel->bounds[1][j] > dl->radius ) {
- break;
- }
- if ( bmodel->bounds[0][j] - dl->transformed[j] > dl->radius ) {
- break;
- }
- }
- if ( j < 3 ) {
- continue;
- }
-
- // we need to check this light
- mask |= 1 << i;
- }
-
- tr.currentEntity->needDlights = (mask != 0);
-
- // set the dlight bits in all the surfaces
- for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) {
- surf = tr.world->surfaces + bmodel->firstSurface + i;
-
- if ( *surf->data == SF_FACE ) {
- ((srfSurfaceFace_t *)surf->data)->dlightBits = mask;
- } else if ( *surf->data == SF_GRID ) {
- ((srfGridMesh_t *)surf->data)->dlightBits = mask;
- } else if ( *surf->data == SF_TRIANGLES ) {
- ((srfTriangles_t *)surf->data)->dlightBits = mask;
- }
- }
-}
-
-
-/*
-=============================================================================
-
-LIGHT SAMPLING
-
-=============================================================================
-*/
-
-extern cvar_t *r_ambientScale;
-extern cvar_t *r_directedScale;
-extern cvar_t *r_debugLight;
-
-/*
-=================
-R_SetupEntityLightingGrid
-
-=================
-*/
-static void R_SetupEntityLightingGrid( trRefEntity_t *ent, world_t *world ) {
- vec3_t lightOrigin;
- int pos[3];
- int i, j;
- byte *gridData;
- float frac[3];
- int gridStep[3];
- vec3_t direction;
- float totalFactor;
-
- if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
- // seperate lightOrigins are needed so an object that is
- // sinking into the ground can still be lit, and so
- // multi-part models can be lit identically
- VectorCopy( ent->e.lightingOrigin, lightOrigin );
- } else {
- VectorCopy( ent->e.origin, lightOrigin );
- }
-
- VectorSubtract( lightOrigin, world->lightGridOrigin, lightOrigin );
- for ( i = 0 ; i < 3 ; i++ ) {
- float v;
-
- v = lightOrigin[i]*world->lightGridInverseSize[i];
- pos[i] = floor( v );
- frac[i] = v - pos[i];
- if ( pos[i] < 0 ) {
- pos[i] = 0;
- } else if ( pos[i] >= world->lightGridBounds[i] - 1 ) {
- pos[i] = world->lightGridBounds[i] - 1;
- }
- }
-
- VectorClear( ent->ambientLight );
- VectorClear( ent->directedLight );
- VectorClear( direction );
-
- assert( world->lightGridData ); // NULL with -nolight maps
-
- // trilerp the light value
- gridStep[0] = 8;
- gridStep[1] = 8 * world->lightGridBounds[0];
- gridStep[2] = 8 * world->lightGridBounds[0] * world->lightGridBounds[1];
- gridData = world->lightGridData + pos[0] * gridStep[0]
- + pos[1] * gridStep[1] + pos[2] * gridStep[2];
-
- totalFactor = 0;
- for ( i = 0 ; i < 8 ; i++ ) {
- float factor;
- byte *data;
- int lat, lng;
- vec3_t normal;
- qboolean ignore;
- #if idppc
- float d0, d1, d2, d3, d4, d5;
- #endif
- factor = 1.0;
- data = gridData;
- ignore = qfalse;
- for ( j = 0 ; j < 3 ; j++ ) {
- if ( i & (1<<j) ) {
- if ((pos[j] + 1) >= world->lightGridBounds[j] - 1)
- {
- ignore = qtrue; // ignore values outside lightgrid
- }
- factor *= frac[j];
- data += gridStep[j];
- } else {
- factor *= (1.0f - frac[j]);
- }
- }
-
- if ( ignore )
- continue;
-
- if (world->hdrLightGrid)
- {
- float *hdrData = world->hdrLightGrid + (int)(data - world->lightGridData) / 8 * 6;
- if (!(hdrData[0]+hdrData[1]+hdrData[2]+hdrData[3]+hdrData[4]+hdrData[5]) ) {
- continue; // ignore samples in walls
- }
- }
- else
- {
- if (!(data[0]+data[1]+data[2]+data[3]+data[4]+data[5]) ) {
- continue; // ignore samples in walls
- }
- }
- totalFactor += factor;
- #if idppc
- d0 = data[0]; d1 = data[1]; d2 = data[2];
- d3 = data[3]; d4 = data[4]; d5 = data[5];
-
- ent->ambientLight[0] += factor * d0;
- ent->ambientLight[1] += factor * d1;
- ent->ambientLight[2] += factor * d2;
-
- ent->directedLight[0] += factor * d3;
- ent->directedLight[1] += factor * d4;
- ent->directedLight[2] += factor * d5;
- #else
- if (world->hdrLightGrid)
- {
- // FIXME: this is hideous
- float *hdrData = world->hdrLightGrid + (int)(data - world->lightGridData) / 8 * 6;
-
- ent->ambientLight[0] += factor * hdrData[0];
- ent->ambientLight[1] += factor * hdrData[1];
- ent->ambientLight[2] += factor * hdrData[2];
-
- ent->directedLight[0] += factor * hdrData[3];
- ent->directedLight[1] += factor * hdrData[4];
- ent->directedLight[2] += factor * hdrData[5];
- }
- else
- {
- ent->ambientLight[0] += factor * data[0];
- ent->ambientLight[1] += factor * data[1];
- ent->ambientLight[2] += factor * data[2];
-
- ent->directedLight[0] += factor * data[3];
- ent->directedLight[1] += factor * data[4];
- ent->directedLight[2] += factor * data[5];
- }
- #endif
- lat = data[7];
- lng = data[6];
- lat *= (FUNCTABLE_SIZE/256);
- lng *= (FUNCTABLE_SIZE/256);
-
- // decode X as cos( lat ) * sin( long )
- // decode Y as sin( lat ) * sin( long )
- // decode Z as cos( long )
-
- normal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
- normal[1] = tr.sinTable[lat] * tr.sinTable[lng];
- normal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
-
- VectorMA( direction, factor, normal, direction );
- }
-
- if ( totalFactor > 0 && totalFactor < 0.99 ) {
- totalFactor = 1.0f / totalFactor;
- VectorScale( ent->ambientLight, totalFactor, ent->ambientLight );
- VectorScale( ent->directedLight, totalFactor, ent->directedLight );
- }
-
- VectorScale( ent->ambientLight, r_ambientScale->value, ent->ambientLight );
- VectorScale( ent->directedLight, r_directedScale->value, ent->directedLight );
-
- VectorNormalize2( direction, ent->lightDir );
-}
-
-
-/*
-===============
-LogLight
-===============
-*/
-static void LogLight( trRefEntity_t *ent ) {
- int max1, max2;
-
- if ( !(ent->e.renderfx & RF_FIRST_PERSON ) ) {
- return;
- }
-
- max1 = ent->ambientLight[0];
- if ( ent->ambientLight[1] > max1 ) {
- max1 = ent->ambientLight[1];
- } else if ( ent->ambientLight[2] > max1 ) {
- max1 = ent->ambientLight[2];
- }
-
- max2 = ent->directedLight[0];
- if ( ent->directedLight[1] > max2 ) {
- max2 = ent->directedLight[1];
- } else if ( ent->directedLight[2] > max2 ) {
- max2 = ent->directedLight[2];
- }
-
- ri.Printf( PRINT_ALL, "amb:%i dir:%i\n", max1, max2 );
-}
-
-/*
-=================
-R_SetupEntityLighting
-
-Calculates all the lighting values that will be used
-by the Calc_* functions
-=================
-*/
-void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) {
- int i;
- dlight_t *dl;
- float power;
- vec3_t dir;
- float d;
- vec3_t lightDir;
- vec3_t lightOrigin;
-
- // lighting calculations
- if ( ent->lightingCalculated ) {
- return;
- }
- ent->lightingCalculated = qtrue;
-
- //
- // trace a sample point down to find ambient light
- //
- if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) {
- // seperate lightOrigins are needed so an object that is
- // sinking into the ground can still be lit, and so
- // multi-part models can be lit identically
- VectorCopy( ent->e.lightingOrigin, lightOrigin );
- } else {
- VectorCopy( ent->e.origin, lightOrigin );
- }
-
- // if NOWORLDMODEL, only use dynamic lights (menu system, etc)
- if ( !(refdef->rdflags & RDF_NOWORLDMODEL )
- && tr.world->lightGridData ) {
- R_SetupEntityLightingGrid( ent, tr.world );
- } else {
- ent->ambientLight[0] = ent->ambientLight[1] =
- ent->ambientLight[2] = tr.identityLight * 150;
- ent->directedLight[0] = ent->directedLight[1] =
- ent->directedLight[2] = tr.identityLight * 150;
- VectorCopy( tr.sunDirection, ent->lightDir );
- }
-
- // bonus items and view weapons have a fixed minimum add
- if ( !r_hdr->integer /* ent->e.renderfx & RF_MINLIGHT */ ) {
- // give everything a minimum light add
- ent->ambientLight[0] += tr.identityLight * 32;
- ent->ambientLight[1] += tr.identityLight * 32;
- ent->ambientLight[2] += tr.identityLight * 32;
- }
-
- //
- // modify the light by dynamic lights
- //
- d = VectorLength( ent->directedLight );
- VectorScale( ent->lightDir, d, lightDir );
-
- for ( i = 0 ; i < refdef->num_dlights ; i++ ) {
- dl = &refdef->dlights[i];
- VectorSubtract( dl->origin, lightOrigin, dir );
- d = VectorNormalize( dir );
-
- power = DLIGHT_AT_RADIUS * ( dl->radius * dl->radius );
- if ( d < DLIGHT_MINIMUM_RADIUS ) {
- d = DLIGHT_MINIMUM_RADIUS;
- }
- d = power / ( d * d );
-
- VectorMA( ent->directedLight, d, dl->color, ent->directedLight );
- VectorMA( lightDir, d, dir, lightDir );
- }
-
- // clamp ambient
- if ( !r_hdr->integer )
- {
- for ( i = 0 ; i < 3 ; i++ ) {
- if ( ent->ambientLight[i] > tr.identityLightByte ) {
- ent->ambientLight[i] = tr.identityLightByte;
- }
- }
- }
-
- if ( r_debugLight->integer ) {
- LogLight( ent );
- }
-
- // save out the byte packet version
- ((byte *)&ent->ambientLightInt)[0] = ri.ftol(ent->ambientLight[0]);
- ((byte *)&ent->ambientLightInt)[1] = ri.ftol(ent->ambientLight[1]);
- ((byte *)&ent->ambientLightInt)[2] = ri.ftol(ent->ambientLight[2]);
- ((byte *)&ent->ambientLightInt)[3] = 0xff;
-
- // transform the direction to local space
- // no need to do this if using lightentity glsl shader
- VectorNormalize( lightDir );
- VectorCopy(lightDir, ent->lightDir);
-}
-
-/*
-=================
-R_LightForPoint
-=================
-*/
-int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir )
-{
- trRefEntity_t ent;
-
- if ( tr.world->lightGridData == NULL )
- return qfalse;
-
- Com_Memset(&ent, 0, sizeof(ent));
- VectorCopy( point, ent.e.origin );
- R_SetupEntityLightingGrid( &ent, tr.world );
- VectorCopy(ent.ambientLight, ambientLight);
- VectorCopy(ent.directedLight, directedLight);
- VectorCopy(ent.lightDir, lightDir);
-
- return qtrue;
-}
-
-
-int R_LightDirForPoint( vec3_t point, vec3_t lightDir, vec3_t normal, world_t *world )
-{
- trRefEntity_t ent;
-
- if ( world->lightGridData == NULL )
- return qfalse;
-
- Com_Memset(&ent, 0, sizeof(ent));
- VectorCopy( point, ent.e.origin );
- R_SetupEntityLightingGrid( &ent, world );
- VectorCopy(ent.lightDir, lightDir);
-
- return qtrue;
-}
diff --git a/src/rend2/tr_local.h b/src/rend2/tr_local.h
deleted file mode 100644
index a5d57d35..00000000
--- a/src/rend2/tr_local.h
+++ /dev/null
@@ -1,2856 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-
-#ifndef TR_LOCAL_H
-#define TR_LOCAL_H
-
-#include "../qcommon/q_shared.h"
-#include "../qcommon/qfiles.h"
-#include "../qcommon/qcommon.h"
-#include "../renderer/tr_public.h"
-#include "tr_extratypes.h"
-#include "tr_extramath.h"
-#include "tr_fbo.h"
-#include "tr_postprocess.h"
-#include "qgl.h"
-#include "../renderer/iqm.h"
-
-#define GL_INDEX_TYPE GL_UNSIGNED_INT
-typedef unsigned int glIndex_t;
-
-#define BUFFER_OFFSET(i) ((char *)NULL + (i))
-
-// 14 bits
-// can't be increased without changing bit packing for drawsurfs
-// see QSORT_SHADERNUM_SHIFT
-#define SHADERNUM_BITS 14
-#define MAX_SHADERS (1<<SHADERNUM_BITS)
-
-//#define MAX_SHADER_STATES 2048
-#define MAX_STATES_PER_SHADER 32
-#define MAX_STATE_NAME 32
-
-#define MAX_FBOS 64
-#define MAX_VISCOUNTS 5
-#define MAX_VBOS 4096
-#define MAX_IBOS 4096
-
-#define MAX_CALC_PSHADOWS 64
-#define MAX_DRAWN_PSHADOWS 16 // do not increase past 32, because bit flags are used on surfaces
-#define PSHADOW_MAP_SIZE 512
-
-#define USE_VERT_TANGENT_SPACE
-
-typedef struct dlight_s {
- vec3_t origin;
- vec3_t color; // range from 0.0 to 1.0, should be color normalized
- float radius;
-
- vec3_t transformed; // origin in local coordinate system
- int additive; // texture detail is lost tho when the lightmap is dark
-} dlight_t;
-
-
-// a trRefEntity_t has all the information passed in by
-// the client game, as well as some locally derived info
-typedef struct {
- refEntity_t e;
-
- float axisLength; // compensate for non-normalized axis
-
- qboolean needDlights; // true for bmodels that touch a dlight
- qboolean lightingCalculated;
- // JBravo: Mirrored models
- qboolean mirrored; // mirrored matrix, needs reversed culling
- vec3_t lightDir; // normalized direction towards light
- vec3_t ambientLight; // color normalized to 0-255
- int ambientLightInt; // 32 bit rgba packed
- vec3_t directedLight;
-} trRefEntity_t;
-
-
-typedef struct {
- vec3_t origin; // in world coordinates
- vec3_t axis[3]; // orientation in world
- vec3_t viewOrigin; // viewParms->or.origin in local coordinates
- float modelMatrix[16];
- float transformMatrix[16];
-} orientationr_t;
-
-typedef enum
-{
- IMGTYPE_COLORALPHA, // for color, lightmap, diffuse, and specular
- IMGTYPE_NORMAL,
- IMGTYPE_NORMALHEIGHT,
- IMGTYPE_DELUXE, // normals are swizzled, deluxe are not
-} imgType_t;
-
-typedef enum
-{
- IMGFLAG_NONE = 0x0000,
- IMGFLAG_MIPMAP = 0x0001,
- IMGFLAG_PICMIP = 0x0002,
- IMGFLAG_CUBEMAP = 0x0004,
- IMGFLAG_NO_COMPRESSION = 0x0010,
- IMGFLAG_NOLIGHTSCALE = 0x0020,
- IMGFLAG_CLAMPTOEDGE = 0x0040,
- IMGFLAG_SRGB = 0x0080,
- IMGFLAG_GENNORMALMAP = 0x0100,
-} imgFlags_t;
-
-typedef struct image_s {
- char imgName[MAX_QPATH]; // game path, including extension
- int width, height; // source image
- int uploadWidth, uploadHeight; // after power of two and picmip but not including clamp to MAX_TEXTURE_SIZE
- GLuint texnum; // gl texture binding
-
- int frameUsed; // for texture usage in frame statistics
-
- int internalFormat;
- int TMU; // only needed for voodoo2
-
- imgType_t type;
- imgFlags_t flags;
-
- struct image_s* next;
-} image_t;
-
-typedef enum
-{
- VBO_USAGE_STATIC,
- VBO_USAGE_DYNAMIC
-} vboUsage_t;
-
-typedef struct VBO_s
-{
- char name[MAX_QPATH];
-
- uint32_t vertexesVBO;
- int vertexesSize; // amount of memory data allocated for all vertices in bytes
- uint32_t ofs_xyz;
- uint32_t ofs_normal;
- uint32_t ofs_st;
- uint32_t ofs_lightmap;
- uint32_t ofs_vertexcolor;
- uint32_t ofs_lightdir;
-#ifdef USE_VERT_TANGENT_SPACE
- uint32_t ofs_tangent;
- uint32_t ofs_bitangent;
-#endif
- uint32_t stride_xyz;
- uint32_t stride_normal;
- uint32_t stride_st;
- uint32_t stride_lightmap;
- uint32_t stride_vertexcolor;
- uint32_t stride_lightdir;
-#ifdef USE_VERT_TANGENT_SPACE
- uint32_t stride_tangent;
- uint32_t stride_bitangent;
-#endif
- uint32_t size_xyz;
- uint32_t size_normal;
-
- int attribs;
-} VBO_t;
-
-typedef struct IBO_s
-{
- char name[MAX_QPATH];
-
- uint32_t indexesVBO;
- int indexesSize; // amount of memory data allocated for all triangles in bytes
-// uint32_t ofsIndexes;
-} IBO_t;
-
-//===============================================================================
-
-typedef enum {
- SS_BAD,
- SS_PORTAL, // mirrors, portals, viewscreens
- SS_ENVIRONMENT, // sky box
- SS_OPAQUE, // opaque
-
- SS_DECAL, // scorch marks, etc.
- SS_SEE_THROUGH, // ladders, grates, grills that may have small blended edges
- // in addition to alpha test
- SS_BANNER,
-
- SS_FOG,
-
- SS_UNDERWATER, // for items that should be drawn in front of the water plane
-
- SS_BLEND0, // regular transparency and filters
- SS_BLEND1, // generally only used for additive type effects
- SS_BLEND2,
- SS_BLEND3,
-
- SS_BLEND6,
- SS_STENCIL_SHADOW,
- SS_ALMOST_NEAREST, // gun smoke puffs
-
- SS_NEAREST // blood blobs
-} shaderSort_t;
-
-
-#define MAX_SHADER_STAGES 8
-
-typedef enum {
- GF_NONE,
-
- GF_SIN,
- GF_SQUARE,
- GF_TRIANGLE,
- GF_SAWTOOTH,
- GF_INVERSE_SAWTOOTH,
-
- GF_NOISE
-
-} genFunc_t;
-
-
-typedef enum {
- DEFORM_NONE,
- DEFORM_WAVE,
- DEFORM_NORMALS,
- DEFORM_BULGE,
- DEFORM_MOVE,
- DEFORM_PROJECTION_SHADOW,
- DEFORM_AUTOSPRITE,
- DEFORM_AUTOSPRITE2,
- DEFORM_TEXT0,
- DEFORM_TEXT1,
- DEFORM_TEXT2,
- DEFORM_TEXT3,
- DEFORM_TEXT4,
- DEFORM_TEXT5,
- DEFORM_TEXT6,
- DEFORM_TEXT7
-} deform_t;
-
-// deformVertexes types that can be handled by the GPU
-typedef enum
-{
- // do not edit: same as genFunc_t
-
- DGEN_NONE,
- DGEN_WAVE_SIN,
- DGEN_WAVE_SQUARE,
- DGEN_WAVE_TRIANGLE,
- DGEN_WAVE_SAWTOOTH,
- DGEN_WAVE_INVERSE_SAWTOOTH,
- DGEN_WAVE_NOISE,
-
- // do not edit until this line
-
- DGEN_BULGE,
- DGEN_MOVE
-} deformGen_t;
-
-typedef enum {
- AGEN_IDENTITY,
- AGEN_SKIP,
- AGEN_ENTITY,
- AGEN_ONE_MINUS_ENTITY,
- AGEN_VERTEX,
- AGEN_ONE_MINUS_VERTEX,
- AGEN_LIGHTING_SPECULAR,
- AGEN_WAVEFORM,
- AGEN_PORTAL,
- AGEN_CONST,
- AGEN_FRESNEL
-} alphaGen_t;
-
-typedef enum {
- CGEN_BAD,
- CGEN_IDENTITY_LIGHTING, // tr.identityLight
- CGEN_IDENTITY, // always (1,1,1,1)
- CGEN_ENTITY, // grabbed from entity's modulate field
- CGEN_ONE_MINUS_ENTITY, // grabbed from 1 - entity.modulate
- CGEN_EXACT_VERTEX, // tess.vertexColors
- CGEN_VERTEX, // tess.vertexColors * tr.identityLight
- CGEN_EXACT_VERTEX_LIT, // like CGEN_EXACT_VERTEX but takes a light direction from the lightgrid
- CGEN_VERTEX_LIT, // like CGEN_VERTEX but takes a light direction from the lightgrid
- CGEN_ONE_MINUS_VERTEX,
- CGEN_WAVEFORM, // programmatically generated
- CGEN_LIGHTING_DIFFUSE,
- CGEN_FOG, // standard fog
- CGEN_CONST // fixed color
-} colorGen_t;
-
-typedef enum {
- TCGEN_BAD,
- TCGEN_IDENTITY, // clear to 0,0
- TCGEN_LIGHTMAP,
- TCGEN_TEXTURE,
- TCGEN_ENVIRONMENT_MAPPED,
- TCGEN_FOG,
- TCGEN_VECTOR // S and T from world coordinates
-} texCoordGen_t;
-
-typedef enum {
- ACFF_NONE,
- ACFF_MODULATE_RGB,
- ACFF_MODULATE_RGBA,
- ACFF_MODULATE_ALPHA
-} acff_t;
-
-typedef struct {
- genFunc_t func;
-
- float base;
- float amplitude;
- float phase;
- float frequency;
-} waveForm_t;
-
-#define TR_MAX_TEXMODS 4
-
-typedef enum {
- TMOD_NONE,
- TMOD_TRANSFORM,
- TMOD_TURBULENT,
- TMOD_SCROLL,
- TMOD_SCALE,
- TMOD_STRETCH,
- TMOD_ROTATE,
- TMOD_ENTITY_TRANSLATE
-} texMod_t;
-
-#define MAX_SHADER_DEFORMS 3
-typedef struct {
- deform_t deformation; // vertex coordinate modification type
-
- vec3_t moveVector;
- waveForm_t deformationWave;
- float deformationSpread;
-
- float bulgeWidth;
- float bulgeHeight;
- float bulgeSpeed;
-} deformStage_t;
-
-
-typedef struct {
- texMod_t type;
-
- // used for TMOD_TURBULENT and TMOD_STRETCH
- waveForm_t wave;
-
- // used for TMOD_TRANSFORM
- float matrix[2][2]; // s' = s * m[0][0] + t * m[1][0] + trans[0]
- float translate[2]; // t' = s * m[0][1] + t * m[0][1] + trans[1]
-
- // used for TMOD_SCALE
- float scale[2]; // s *= scale[0]
- // t *= scale[1]
-
- // used for TMOD_SCROLL
- float scroll[2]; // s' = s + scroll[0] * time
- // t' = t + scroll[1] * time
-
- // + = clockwise
- // - = counterclockwise
- float rotateSpeed;
-
-} texModInfo_t;
-
-
-#define MAX_IMAGE_ANIMATIONS 8
-
-typedef struct {
- image_t *image[MAX_IMAGE_ANIMATIONS];
- int numImageAnimations;
- float imageAnimationSpeed;
-
- texCoordGen_t tcGen;
- vec3_t tcGenVectors[2];
-
- int numTexMods;
- texModInfo_t *texMods;
-
- int videoMapHandle;
- qboolean isLightmap;
- qboolean vertexLightmap;
- qboolean isVideoMap;
-} textureBundle_t;
-
-enum
-{
- TB_COLORMAP = 0,
- TB_DIFFUSEMAP = 0,
- TB_LIGHTMAP = 1,
- TB_LEVELSMAP = 1,
- TB_SHADOWMAP = 1,
- TB_NORMALMAP = 2,
- TB_DELUXEMAP = 3,
- TB_SHADOWMAP2 = 3,
- TB_SPECULARMAP = 4,
- TB_SHADOWMAP3 = 5,
- NUM_TEXTURE_BUNDLES = 6
-};
-
-typedef enum
-{
- // material shader stage types
- ST_COLORMAP = 0, // vanilla Q3A style shader treatening
- ST_DIFFUSEMAP = 0, // treat color and diffusemap the same
- ST_NORMALMAP,
- ST_NORMALPARALLAXMAP,
- ST_SPECULARMAP,
- ST_GLSL
-} stageType_t;
-
-typedef struct {
- qboolean active;
-
- textureBundle_t bundle[NUM_TEXTURE_BUNDLES];
-
- waveForm_t rgbWave;
- colorGen_t rgbGen;
-
- waveForm_t alphaWave;
- alphaGen_t alphaGen;
-
- byte constantColor[4]; // for CGEN_CONST and AGEN_CONST
-
- unsigned stateBits; // GLS_xxxx mask
-
- acff_t adjustColorsForFog;
-
- qboolean isDetail;
-
- stageType_t type;
- struct shaderProgram_s *glslShaderGroup;
- int glslShaderIndex;
- vec2_t materialInfo;
-} shaderStage_t;
-
-struct shaderCommands_s;
-
-// any change in the LIGHTMAP_* defines here MUST be reflected in
-// R_FindShader() in tr_bsp.c
-#define LIGHTMAP_2D -4 // shader is for 2D rendering
-#define LIGHTMAP_BY_VERTEX -3 // pre-lit triangle models
-#define LIGHTMAP_WHITEIMAGE -2
-#define LIGHTMAP_NONE -1
-
-typedef enum {
- CT_FRONT_SIDED,
- CT_BACK_SIDED,
- CT_TWO_SIDED
-} cullType_t;
-
-typedef enum {
- FP_NONE, // surface is translucent and will just be adjusted properly
- FP_EQUAL, // surface is opaque but possibly alpha tested
- FP_LE // surface is trnaslucent, but still needs a fog pass (fog surface)
-} fogPass_t;
-
-typedef struct {
- float cloudHeight;
- image_t *outerbox[6], *innerbox[6];
-} skyParms_t;
-
-typedef struct {
- vec3_t color;
- float depthForOpaque;
-} fogParms_t;
-
-
-typedef struct shader_s {
- char name[MAX_QPATH]; // game path, including extension
- int lightmapIndex; // for a shader to match, both name and lightmapIndex must match
-
- int index; // this shader == tr.shaders[index]
- int sortedIndex; // this shader == tr.sortedShaders[sortedIndex]
-
- float sort; // lower numbered shaders draw before higher numbered
-
- qboolean defaultShader; // we want to return index 0 if the shader failed to
- // load for some reason, but R_FindShader should
- // still keep a name allocated for it, so if
- // something calls RE_RegisterShader again with
- // the same name, we don't try looking for it again
-
- qboolean explicitlyDefined; // found in a .shader file
-
- int surfaceFlags; // if explicitlyDefined, this will have SURF_* flags
- int contentFlags;
-
- qboolean entityMergable; // merge across entites optimizable (smoke, blood)
-
- qboolean isSky;
- skyParms_t sky;
- fogParms_t fogParms;
-
- float portalRange; // distance to fog out at
- qboolean isPortal;
-
- int multitextureEnv; // 0, GL_MODULATE, GL_ADD (FIXME: put in stage)
-
- cullType_t cullType; // CT_FRONT_SIDED, CT_BACK_SIDED, or CT_TWO_SIDED
- qboolean polygonOffset; // set for decals and other items that must be offset
- qboolean noMipMaps; // for console fonts, 2D elements, etc.
- qboolean noPicMip; // for images that must always be full resolution
-
- fogPass_t fogPass; // draw a blended pass, possibly with depth test equals
-
- int vertexAttribs; // not all shaders will need all data to be gathered
-
- int numDeforms;
- deformStage_t deforms[MAX_SHADER_DEFORMS];
-
- int numUnfoggedPasses;
- shaderStage_t *stages[MAX_SHADER_STAGES];
-
- void (*optimalStageIteratorFunc)( void );
-
- float clampTime; // time this shader is clamped to
- float timeOffset; // current time offset for this shader
-
- int numStates; // if non-zero this is a state shader
- struct shader_s *currentShader; // current state if this is a state shader
- struct shader_s *parentShader; // current state if this is a state shader
- int currentState; // current state index for cycle purposes
- long expireTime; // time in milliseconds this expires
-
- struct shader_s *remappedShader; // current shader this one is remapped too
-
- int shaderStates[MAX_STATES_PER_SHADER]; // index to valid shader states
-
- struct shader_s *next;
-} shader_t;
-
-static ID_INLINE qboolean ShaderRequiresCPUDeforms(const shader_t * shader)
-{
- if(shader->numDeforms)
- {
- const deformStage_t *ds = &shader->deforms[0];
-
- if (shader->numDeforms > 1)
- return qtrue;
-
- switch (ds->deformation)
- {
- case DEFORM_WAVE:
- case DEFORM_BULGE:
- return qfalse;
-
- default:
- return qtrue;
- }
- }
-
- return qfalse;
-}
-
-typedef struct shaderState_s {
- char shaderName[MAX_QPATH]; // name of shader this state belongs to
- char name[MAX_STATE_NAME]; // name of this state
- char stateShader[MAX_QPATH]; // shader this name invokes
- int cycleTime; // time this cycle lasts, <= 0 is forever
- shader_t *shader;
-} shaderState_t;
-
-enum
-{
- ATTR_INDEX_POSITION = 0,
- ATTR_INDEX_TEXCOORD0 = 1,
- ATTR_INDEX_TEXCOORD1 = 2,
- ATTR_INDEX_TANGENT = 3,
- ATTR_INDEX_BITANGENT = 4,
- ATTR_INDEX_NORMAL = 5,
- ATTR_INDEX_COLOR = 6,
- ATTR_INDEX_PAINTCOLOR = 7,
- ATTR_INDEX_LIGHTDIRECTION = 8,
- ATTR_INDEX_BONE_INDEXES = 9,
- ATTR_INDEX_BONE_WEIGHTS = 10,
-
- // GPU vertex animations
- ATTR_INDEX_POSITION2 = 11,
- ATTR_INDEX_TANGENT2 = 12,
- ATTR_INDEX_BITANGENT2 = 13,
- ATTR_INDEX_NORMAL2 = 14
-};
-
-enum
-{
- GLS_SRCBLEND_ZERO = (1 << 0),
- GLS_SRCBLEND_ONE = (1 << 1),
- GLS_SRCBLEND_DST_COLOR = (1 << 2),
- GLS_SRCBLEND_ONE_MINUS_DST_COLOR = (1 << 3),
- GLS_SRCBLEND_SRC_ALPHA = (1 << 4),
- GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA = (1 << 5),
- GLS_SRCBLEND_DST_ALPHA = (1 << 6),
- GLS_SRCBLEND_ONE_MINUS_DST_ALPHA = (1 << 7),
- GLS_SRCBLEND_ALPHA_SATURATE = (1 << 8),
-
- GLS_SRCBLEND_BITS = GLS_SRCBLEND_ZERO
- | GLS_SRCBLEND_ONE
- | GLS_SRCBLEND_DST_COLOR
- | GLS_SRCBLEND_ONE_MINUS_DST_COLOR
- | GLS_SRCBLEND_SRC_ALPHA
- | GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA
- | GLS_SRCBLEND_DST_ALPHA
- | GLS_SRCBLEND_ONE_MINUS_DST_ALPHA
- | GLS_SRCBLEND_ALPHA_SATURATE,
-
- GLS_DSTBLEND_ZERO = (1 << 9),
- GLS_DSTBLEND_ONE = (1 << 10),
- GLS_DSTBLEND_SRC_COLOR = (1 << 11),
- GLS_DSTBLEND_ONE_MINUS_SRC_COLOR = (1 << 12),
- GLS_DSTBLEND_SRC_ALPHA = (1 << 13),
- GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA = (1 << 14),
- GLS_DSTBLEND_DST_ALPHA = (1 << 15),
- GLS_DSTBLEND_ONE_MINUS_DST_ALPHA = (1 << 16),
-
- GLS_DSTBLEND_BITS = GLS_DSTBLEND_ZERO
- | GLS_DSTBLEND_ONE
- | GLS_DSTBLEND_SRC_COLOR
- | GLS_DSTBLEND_ONE_MINUS_SRC_COLOR
- | GLS_DSTBLEND_SRC_ALPHA
- | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA
- | GLS_DSTBLEND_DST_ALPHA
- | GLS_DSTBLEND_ONE_MINUS_DST_ALPHA,
-
- GLS_DEPTHMASK_TRUE = (1 << 17),
-
- GLS_POLYMODE_LINE = (1 << 18),
-
- GLS_DEPTHTEST_DISABLE = (1 << 19),
-
- GLS_DEPTHFUNC_LESS = (1 << 20),
- GLS_DEPTHFUNC_EQUAL = (1 << 21),
-
- GLS_DEPTHFUNC_BITS = GLS_DEPTHFUNC_LESS
- | GLS_DEPTHFUNC_EQUAL,
-
- GLS_ATEST_GT_0 = (1 << 22),
- GLS_ATEST_LT_128 = (1 << 23),
- GLS_ATEST_GE_128 = (1 << 24),
-// GLS_ATEST_GE_CUSTOM = (1 << 25),
-
- GLS_ATEST_BITS = GLS_ATEST_GT_0
- | GLS_ATEST_LT_128
- | GLS_ATEST_GE_128,
-// | GLS_ATEST_GT_CUSTOM,
-
- GLS_REDMASK_FALSE = (1 << 26),
- GLS_GREENMASK_FALSE = (1 << 27),
- GLS_BLUEMASK_FALSE = (1 << 28),
- GLS_ALPHAMASK_FALSE = (1 << 29),
-
- GLS_COLORMASK_BITS = GLS_REDMASK_FALSE
- | GLS_GREENMASK_FALSE
- | GLS_BLUEMASK_FALSE
- | GLS_ALPHAMASK_FALSE,
-
- GLS_STENCILTEST_ENABLE = (1 << 30),
-
- GLS_DEFAULT = GLS_DEPTHMASK_TRUE
-};
-
-enum
-{
- ATTR_POSITION = 0x0001,
- ATTR_TEXCOORD = 0x0002,
- ATTR_LIGHTCOORD = 0x0004,
- ATTR_TANGENT = 0x0008,
- ATTR_BITANGENT = 0x0010,
- ATTR_NORMAL = 0x0020,
- ATTR_COLOR = 0x0040,
- ATTR_PAINTCOLOR = 0x0080,
- ATTR_LIGHTDIRECTION = 0x0100,
- ATTR_BONE_INDEXES = 0x0200,
- ATTR_BONE_WEIGHTS = 0x0400,
-
- // for .md3 interpolation
- ATTR_POSITION2 = 0x0800,
- ATTR_TANGENT2 = 0x1000,
- ATTR_BITANGENT2 = 0x2000,
- ATTR_NORMAL2 = 0x4000,
-
- ATTR_DEFAULT = ATTR_POSITION,
- ATTR_BITS = ATTR_POSITION |
- ATTR_TEXCOORD |
- ATTR_LIGHTCOORD |
- ATTR_TANGENT |
- ATTR_BITANGENT |
- ATTR_NORMAL |
- ATTR_COLOR |
- ATTR_PAINTCOLOR |
- ATTR_LIGHTDIRECTION |
- ATTR_BONE_INDEXES |
- ATTR_BONE_WEIGHTS |
- ATTR_POSITION2 |
- ATTR_TANGENT2 |
- ATTR_BITANGENT2 |
- ATTR_NORMAL2
-};
-
-enum
-{
- GENERICDEF_USE_DEFORM_VERTEXES = 0x0001,
- GENERICDEF_USE_TCGEN_AND_TCMOD = 0x0002,
- GENERICDEF_USE_VERTEX_ANIMATION = 0x0004,
- GENERICDEF_USE_FOG = 0x0008,
- GENERICDEF_USE_RGBAGEN = 0x0010,
- GENERICDEF_USE_LIGHTMAP = 0x0020,
- GENERICDEF_ALL = 0x003F,
- GENERICDEF_COUNT = 0x0040,
-};
-
-enum
-{
- FOGDEF_USE_DEFORM_VERTEXES = 0x0001,
- FOGDEF_USE_VERTEX_ANIMATION = 0x0002,
- FOGDEF_ALL = 0x0003,
- FOGDEF_COUNT = 0x0004,
-};
-
-enum
-{
- DLIGHTDEF_USE_DEFORM_VERTEXES = 0x0001,
- DLIGHTDEF_ALL = 0x0001,
- DLIGHTDEF_COUNT = 0x0002,
-};
-
-enum
-{
- LIGHTDEF_USE_LIGHTMAP = 0x0001,
- LIGHTDEF_USE_LIGHT_VECTOR = 0x0002,
- LIGHTDEF_USE_LIGHT_VERTEX = 0x0003,
- LIGHTDEF_LIGHTTYPE_MASK = 0x0003,
- LIGHTDEF_ENTITY = 0x0004,
- LIGHTDEF_USE_TCGEN_AND_TCMOD = 0x0008,
- LIGHTDEF_USE_NORMALMAP = 0x0010,
- LIGHTDEF_USE_SPECULARMAP = 0x0020,
- LIGHTDEF_USE_DELUXEMAP = 0x0040,
- LIGHTDEF_USE_PARALLAXMAP = 0x0080,
- LIGHTDEF_USE_SHADOWMAP = 0x0100,
- LIGHTDEF_ALL = 0x01FF,
- LIGHTDEF_COUNT = 0x0200
-};
-
-enum
-{
- GLSL_INT,
- GLSL_FLOAT,
- GLSL_FLOAT5,
- GLSL_VEC2,
- GLSL_VEC3,
- GLSL_VEC4,
- GLSL_MAT16
-};
-
-// Tr3B - shaderProgram_t represents a pair of one
-// GLSL vertex and one GLSL fragment shader
-typedef struct shaderProgram_s
-{
- char name[MAX_QPATH];
-
- GLhandleARB program;
- GLhandleARB vertexShader;
- GLhandleARB fragmentShader;
- uint32_t attribs; // vertex array attributes
-
- // uniform parameters
- int numUniforms;
- GLint *uniforms;
- char *uniformTypes; // max 127 uniform types
- short *uniformBufferOffsets; // max 32767/64=511 uniforms
- char *uniformBuffer;
-} shaderProgram_t;
-
-
-enum
-{
- TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX = 0,
- TEXTURECOLOR_UNIFORM_INVTEXRES,
- TEXTURECOLOR_UNIFORM_AUTOEXPOSUREMINMAX,
- TEXTURECOLOR_UNIFORM_TONEMINAVGMAXLINEAR,
- TEXTURECOLOR_UNIFORM_TEXTUREMAP,
- TEXTURECOLOR_UNIFORM_LEVELSMAP,
- TEXTURECOLOR_UNIFORM_COLOR,
- TEXTURECOLOR_UNIFORM_COUNT
-};
-
-
-enum
-{
- FOGPASS_UNIFORM_FOGDISTANCE = 0,
- FOGPASS_UNIFORM_FOGDEPTH,
- FOGPASS_UNIFORM_FOGEYET,
- FOGPASS_UNIFORM_DEFORMGEN,
- FOGPASS_UNIFORM_DEFORMPARAMS,
- FOGPASS_UNIFORM_TIME,
- FOGPASS_UNIFORM_COLOR,
- FOGPASS_UNIFORM_MODELVIEWPROJECTIONMATRIX,
- FOGPASS_UNIFORM_VERTEXLERP,
- FOGPASS_UNIFORM_COUNT
-};
-
-
-enum
-{
- DLIGHT_UNIFORM_DIFFUSEMAP = 0,
- DLIGHT_UNIFORM_DLIGHTINFO,
- DLIGHT_UNIFORM_DEFORMGEN,
- DLIGHT_UNIFORM_DEFORMPARAMS,
- DLIGHT_UNIFORM_TIME,
- DLIGHT_UNIFORM_COLOR,
- DLIGHT_UNIFORM_MODELVIEWPROJECTIONMATRIX,
- DLIGHT_UNIFORM_VERTEXLERP,
- DLIGHT_UNIFORM_COUNT
-};
-
-
-enum
-{
- PSHADOW_UNIFORM_SHADOWMAP = 0,
- PSHADOW_UNIFORM_MODELVIEWPROJECTIONMATRIX,
- PSHADOW_UNIFORM_LIGHTFORWARD,
- PSHADOW_UNIFORM_LIGHTUP,
- PSHADOW_UNIFORM_LIGHTRIGHT,
- PSHADOW_UNIFORM_LIGHTORIGIN,
- PSHADOW_UNIFORM_LIGHTRADIUS,
- PSHADOW_UNIFORM_COUNT
-};
-
-
-enum
-{
- GENERIC_UNIFORM_DIFFUSEMAP = 0,
- GENERIC_UNIFORM_LIGHTMAP,
- GENERIC_UNIFORM_NORMALMAP,
- GENERIC_UNIFORM_DELUXEMAP,
- GENERIC_UNIFORM_SPECULARMAP,
- GENERIC_UNIFORM_SHADOWMAP,
- GENERIC_UNIFORM_DIFFUSETEXMATRIX,
- GENERIC_UNIFORM_DIFFUSETEXOFFTURB,
- //GENERIC_UNIFORM_NORMALTEXMATRIX,
- //GENERIC_UNIFORM_SPECULARTEXMATRIX,
- GENERIC_UNIFORM_TEXTURE1ENV,
- GENERIC_UNIFORM_VIEWORIGIN,
- GENERIC_UNIFORM_TCGEN0,
- GENERIC_UNIFORM_TCGEN0VECTOR0,
- GENERIC_UNIFORM_TCGEN0VECTOR1,
- GENERIC_UNIFORM_DEFORMGEN,
- GENERIC_UNIFORM_DEFORMPARAMS,
- GENERIC_UNIFORM_COLORGEN,
- GENERIC_UNIFORM_ALPHAGEN,
- GENERIC_UNIFORM_BASECOLOR,
- GENERIC_UNIFORM_VERTCOLOR,
- GENERIC_UNIFORM_AMBIENTLIGHT,
- GENERIC_UNIFORM_DIRECTEDLIGHT,
- GENERIC_UNIFORM_LIGHTORIGIN,
- GENERIC_UNIFORM_LIGHTRADIUS,
- GENERIC_UNIFORM_PORTALRANGE,
- GENERIC_UNIFORM_FOGDISTANCE,
- GENERIC_UNIFORM_FOGDEPTH,
- GENERIC_UNIFORM_FOGEYET,
- GENERIC_UNIFORM_FOGCOLORMASK,
- GENERIC_UNIFORM_MODELMATRIX,
- GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX,
- GENERIC_UNIFORM_TIME,
- GENERIC_UNIFORM_VERTEXLERP,
- GENERIC_UNIFORM_MATERIALINFO,
- GENERIC_UNIFORM_COUNT
-};
-
-enum
-{
- SHADOWMASK_UNIFORM_SCREENDEPTHMAP = 0,
- SHADOWMASK_UNIFORM_SHADOWMAP,
- SHADOWMASK_UNIFORM_SHADOWMAP2,
- SHADOWMASK_UNIFORM_SHADOWMAP3,
- SHADOWMASK_UNIFORM_SHADOWMVP,
- SHADOWMASK_UNIFORM_SHADOWMVP2,
- SHADOWMASK_UNIFORM_SHADOWMVP3,
- SHADOWMASK_UNIFORM_VIEWORIGIN,
- SHADOWMASK_UNIFORM_VIEWINFO, // znear, zfar, width/2, height/2
- SHADOWMASK_UNIFORM_VIEWFORWARD,
- SHADOWMASK_UNIFORM_VIEWLEFT,
- SHADOWMASK_UNIFORM_VIEWUP,
- SHADOWMASK_UNIFORM_COUNT
-};
-
-enum
-{
- SSAO_UNIFORM_SCREENDEPTHMAP = 0,
- SSAO_UNIFORM_VIEWINFO, // znear, zfar, width/2, height/2
- SSAO_UNIFORM_COUNT
-};
-
-enum
-{
- DEPTHBLUR_UNIFORM_SCREENIMAGEMAP = 0,
- DEPTHBLUR_UNIFORM_SCREENDEPTHMAP,
- DEPTHBLUR_UNIFORM_VIEWINFO, // znear, zfar, width/2, height/2
- DEPTHBLUR_UNIFORM_COUNT
-};
-
-//
-// Tr3B: these are fire wall functions to avoid expensive redundant glUniform* calls
-//#define USE_UNIFORM_FIREWALL 1
-//#define LOG_GLSL_UNIFORMS 1
-
-// trRefdef_t holds everything that comes in refdef_t,
-// as well as the locally generated scene information
-typedef struct {
- int x, y, width, height;
- float fov_x, fov_y;
- vec3_t vieworg;
- vec3_t viewaxis[3]; // transformation matrix
-
- stereoFrame_t stereoFrame;
-
- int time; // time in milliseconds for shader effects and other time dependent rendering issues
- int rdflags; // RDF_NOWORLDMODEL, etc
-
- // 1 bits will prevent the associated area from rendering at all
- byte areamask[MAX_MAP_AREA_BYTES];
- qboolean areamaskModified; // qtrue if areamask changed since last scene
-
- float floatTime; // tr.refdef.time / 1000.0
-
- float blurFactor;
-
- // text messages for deform text shaders
- char text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH];
-
- int num_entities;
- trRefEntity_t *entities;
-
- int num_dlights;
- struct dlight_s *dlights;
-
- int numPolys;
- struct srfPoly_s *polys;
-
- int numDrawSurfs;
- struct drawSurf_s *drawSurfs;
-
- unsigned int dlightMask;
- int num_pshadows;
- struct pshadow_s *pshadows;
-
- float sunShadowMvp[3][16];
- float sunDir[4];
- float sunCol[4];
- float sunAmbCol[4];
- float colorScale;
-
- float autoExposureMinMax[2];
- float toneMinAvgMaxLinear[3];
-} trRefdef_t;
-
-
-//=================================================================================
-
-// skins allow models to be retextured without modifying the model file
-typedef struct {
- char name[MAX_QPATH];
- shader_t *shader;
-} skinSurface_t;
-
-typedef struct skin_s {
- char name[MAX_QPATH]; // game path, including extension
- int numSurfaces;
- skinSurface_t *surfaces[MD3_MAX_SURFACES];
-} skin_t;
-
-
-typedef struct {
- int originalBrushNumber;
- vec3_t bounds[2];
-
- unsigned colorInt; // in packed byte format
- float tcScale; // texture coordinate vector scales
- fogParms_t parms;
-
- // for clipping distance in fog when outside
- qboolean hasSurface;
- float surface[4];
-} fog_t;
-
-typedef enum {
- VPF_NONE = 0x00,
- VPF_SHADOWMAP = 0x01,
- VPF_DEPTHSHADOW = 0x02,
- VPF_DEPTHCLAMP = 0x04,
- VPF_ORTHOGRAPHIC = 0x08,
- VPF_USESUNLIGHT = 0x10,
- VPF_FARPLANEFRUSTUM = 0x20
-} viewParmFlags_t;
-
-typedef struct {
- orientationr_t or;
- orientationr_t world;
- vec3_t pvsOrigin; // may be different than or.origin for portals
- qboolean isPortal; // true if this view is through a portal
- qboolean isMirror; // the portal is a mirror, invert the face culling
- viewParmFlags_t flags;
- int frameSceneNum; // copied from tr.frameSceneNum
- int frameCount; // copied from tr.frameCount
- cplane_t portalPlane; // clip anything behind this if mirroring
- int viewportX, viewportY, viewportWidth, viewportHeight;
- FBO_t *targetFbo;
- float fovX, fovY;
- float projectionMatrix[16];
- cplane_t frustum[5];
- vec3_t visBounds[2];
- float zFar;
- float zNear;
- stereoFrame_t stereoFrame;
-} viewParms_t;
-
-
-/*
-==============================================================================
-
-SURFACES
-
-==============================================================================
-*/
-typedef byte color4ub_t[4];
-
-// any changes in surfaceType must be mirrored in rb_surfaceTable[]
-typedef enum {
- SF_BAD,
- SF_SKIP, // ignore
- SF_FACE,
- SF_GRID,
- SF_TRIANGLES,
- SF_POLY,
- SF_MDV,
- SF_MD4,
-#ifdef RAVENMD4
- SF_MDR,
-#endif
- SF_IQM,
- SF_FLARE,
- SF_ENTITY, // beams, rails, lightning, etc that can be determined by entity
- SF_DISPLAY_LIST,
- SF_VBO_MESH,
- SF_VBO_MDVMESH,
-
- SF_NUM_SURFACE_TYPES,
- SF_MAX = 0x7fffffff // ensures that sizeof( surfaceType_t ) == sizeof( int )
-} surfaceType_t;
-
-typedef struct drawSurf_s {
- unsigned sort; // bit combination for fast compares
- surfaceType_t *surface; // any of surface*_t
-} drawSurf_t;
-
-#define MAX_FACE_POINTS 64
-
-#define MAX_PATCH_SIZE 32 // max dimensions of a patch mesh in map file
-#define MAX_GRID_SIZE 65 // max dimensions of a grid mesh in memory
-
-// when cgame directly specifies a polygon, it becomes a srfPoly_t
-// as soon as it is called
-typedef struct srfPoly_s {
- surfaceType_t surfaceType;
- qhandle_t hShader;
- int fogIndex;
- int numVerts;
- polyVert_t *verts;
-} srfPoly_t;
-
-typedef struct srfDisplayList_s {
- surfaceType_t surfaceType;
- int listNum;
-} srfDisplayList_t;
-
-
-typedef struct srfFlare_s {
- surfaceType_t surfaceType;
- vec3_t origin;
- vec3_t normal;
- vec3_t color;
-} srfFlare_t;
-
-typedef struct
-{
- vec3_t xyz;
- vec2_t st;
- vec2_t lightmap;
- vec3_t normal;
-#ifdef USE_VERT_TANGENT_SPACE
- vec3_t tangent;
- vec3_t bitangent;
-#endif
- vec3_t lightdir;
- vec4_t vertexColors;
-
-#if DEBUG_OPTIMIZEVERTICES
- unsigned int id;
-#endif
-} srfVert_t;
-
-#ifdef USE_VERT_TANGENT_SPACE
-#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0, 0}}
-#else
-#define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0, 0}}
-#endif
-
-typedef struct
-{
- int indexes[3];
- int neighbors[3];
- vec4_t plane;
- qboolean facingLight;
- qboolean degenerated;
-} srfTriangle_t;
-
-
-typedef struct srfGridMesh_s
-{
- surfaceType_t surfaceType;
-
- // dynamic lighting information
- int dlightBits;
- int pshadowBits;
-
- // culling information
- vec3_t meshBounds[2];
- vec3_t localOrigin;
- float meshRadius;
-
- // lod information, which may be different
- // than the culling information to allow for
- // groups of curves that LOD as a unit
- vec3_t lodOrigin;
- float lodRadius;
- int lodFixed;
- int lodStitched;
-
- // vertexes
- int width, height;
- float *widthLodError;
- float *heightLodError;
-
- int numTriangles;
- srfTriangle_t *triangles;
-
- int numVerts;
- srfVert_t *verts;
-
- // BSP VBO offsets
- int firstVert;
- int firstIndex;
- glIndex_t minIndex;
- glIndex_t maxIndex;
-
- // static render data
- VBO_t *vbo; // points to bsp model VBO
- IBO_t *ibo;
-} srfGridMesh_t;
-
-
-typedef struct
-{
- surfaceType_t surfaceType;
-
- // dynamic lighting information
- int dlightBits;
- int pshadowBits;
-
- // culling information
- cplane_t plane;
-// vec3_t bounds[2];
-
- // triangle definitions
- int numTriangles;
- srfTriangle_t *triangles;
-
- int numVerts;
- srfVert_t *verts;
-
- // BSP VBO offsets
- int firstVert;
- int firstIndex;
- glIndex_t minIndex;
- glIndex_t maxIndex;
-
- // static render data
- VBO_t *vbo; // points to bsp model VBO
- IBO_t *ibo;
-} srfSurfaceFace_t;
-
-
-// misc_models in maps are turned into direct geometry by xmap
-typedef struct
-{
- surfaceType_t surfaceType;
-
- // dynamic lighting information
- int dlightBits;
- int pshadowBits;
-
- // culling information
-// vec3_t bounds[2];
-
- // triangle definitions
- int numTriangles;
- srfTriangle_t *triangles;
-
- int numVerts;
- srfVert_t *verts;
-
- // BSP VBO offsets
- int firstVert;
- int firstIndex;
- glIndex_t minIndex;
- glIndex_t maxIndex;
-
- // static render data
- VBO_t *vbo; // points to bsp model VBO
- IBO_t *ibo;
-} srfTriangles_t;
-
-// inter-quake-model
-typedef struct {
- int num_vertexes;
- int num_triangles;
- int num_frames;
- int num_surfaces;
- int num_joints;
- struct srfIQModel_s *surfaces;
-
- float *positions;
- float *texcoords;
- float *normals;
- float *tangents;
- byte *blendIndexes;
- byte *blendWeights;
- byte *colors;
- int *triangles;
-
- int *jointParents;
- float *poseMats;
- float *bounds;
- char *names;
-} iqmData_t;
-
-// inter-quake-model surface
-typedef struct srfIQModel_s {
- surfaceType_t surfaceType;
- char name[MAX_QPATH];
- shader_t *shader;
- iqmData_t *data;
- int first_vertex, num_vertexes;
- int first_triangle, num_triangles;
-} srfIQModel_t;
-
-typedef struct srfVBOMesh_s
-{
- surfaceType_t surfaceType;
-
- struct shader_s *shader; // FIXME move this to somewhere else
- int fogIndex;
-
- // dynamic lighting information
- int dlightBits;
- int pshadowBits;
-
- // culling information
- vec3_t bounds[2];
-
- // backEnd stats
- int numIndexes;
- int numVerts;
- int firstIndex;
- glIndex_t minIndex;
- glIndex_t maxIndex;
-
- // static render data
- VBO_t *vbo;
- IBO_t *ibo;
-} srfVBOMesh_t;
-
-typedef struct srfVBOMDVMesh_s
-{
- surfaceType_t surfaceType;
-
- struct mdvModel_s *mdvModel;
- struct mdvSurface_s *mdvSurface;
-
- // backEnd stats
- int numIndexes;
- int numVerts;
- glIndex_t minIndex;
- glIndex_t maxIndex;
-
- // static render data
- VBO_t *vbo;
- IBO_t *ibo;
-} srfVBOMDVMesh_t;
-
-extern void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])(void *);
-
-/*
-==============================================================================
-
-SHADOWS
-
-==============================================================================
-*/
-
-typedef struct pshadow_s
-{
- float sort;
-
- int numEntities;
- int entityNums[8];
- vec3_t entityOrigins[8];
- float entityRadiuses[8];
-
- float viewRadius;
- vec3_t viewOrigin;
-
- vec3_t lightViewAxis[3];
- vec3_t lightOrigin;
- float lightRadius;
- cplane_t cullPlane;
-} pshadow_t;
-
-
-/*
-==============================================================================
-
-BRUSH MODELS
-
-==============================================================================
-*/
-
-
-//
-// in memory representation
-//
-
-#define SIDE_FRONT 0
-#define SIDE_BACK 1
-#define SIDE_ON 2
-
-#define CULLINFO_NONE 0
-#define CULLINFO_BOX 1
-#define CULLINFO_SPHERE 2
-#define CULLINFO_PLANE 4
-
-typedef struct cullinfo_s {
- int type;
- vec3_t bounds[2];
- vec3_t localOrigin;
- float radius;
- cplane_t plane;
-} cullinfo_t;
-
-typedef struct msurface_s {
- //int viewCount; // if == tr.viewCount, already added
- struct shader_s *shader;
- int fogIndex;
- cullinfo_t cullinfo;
-
- surfaceType_t *data; // any of srf*_t
-} msurface_t;
-
-
-#define CONTENTS_NODE -1
-typedef struct mnode_s {
- // common with leaf and node
- int contents; // -1 for nodes, to differentiate from leafs
- int visCounts[MAX_VISCOUNTS]; // node needs to be traversed if current
- vec3_t mins, maxs; // for bounding box culling
- struct mnode_s *parent;
-
- // node specific
- cplane_t *plane;
- struct mnode_s *children[2];
-
- // leaf specific
- int cluster;
- int area;
-
- int firstmarksurface;
- int nummarksurfaces;
-} mnode_t;
-
-typedef struct {
- vec3_t bounds[2]; // for culling
- int firstSurface;
- int numSurfaces;
-} bmodel_t;
-
-typedef struct {
- char name[MAX_QPATH]; // ie: maps/tim_dm2.bsp
- char baseName[MAX_QPATH]; // ie: tim_dm2
-
- int dataSize;
-
- int numShaders;
- dshader_t *shaders;
-
- int numBModels;
- bmodel_t *bmodels;
-
- int numplanes;
- cplane_t *planes;
-
- int numnodes; // includes leafs
- int numDecisionNodes;
- mnode_t *nodes;
-
- VBO_t *vbo;
- IBO_t *ibo;
-
- int numWorldSurfaces;
-
- int numsurfaces;
- msurface_t *surfaces;
- int *surfacesViewCount;
- int *surfacesDlightBits;
- int *surfacesPshadowBits;
-
- int numMergedSurfaces;
- msurface_t *mergedSurfaces;
- int *mergedSurfacesViewCount;
- int *mergedSurfacesDlightBits;
- int *mergedSurfacesPshadowBits;
-
- int nummarksurfaces;
- int *marksurfaces;
- int *viewSurfaces;
-
- int numfogs;
- fog_t *fogs;
-
- vec3_t lightGridOrigin;
- vec3_t lightGridSize;
- vec3_t lightGridInverseSize;
- int lightGridBounds[3];
- byte *lightGridData;
- float *hdrLightGrid;
-
-
- int numClusters;
- int clusterBytes;
- const byte *vis; // may be passed in by CM_LoadMap to save space
-
- byte *novis; // clusterBytes of 0xff
-
- char *entityString;
- char *entityParsePoint;
-} world_t;
-
-
-/*
-==============================================================================
-MDV MODELS - meta format for vertex animation models like .md2, .md3, .mdc
-==============================================================================
-*/
-typedef struct
-{
- float bounds[2][3];
- float localOrigin[3];
- float radius;
-} mdvFrame_t;
-
-typedef struct
-{
- float origin[3];
- float axis[3][3];
-} mdvTag_t;
-
-typedef struct
-{
- char name[MAX_QPATH]; // tag name
-} mdvTagName_t;
-
-typedef struct
-{
- vec3_t xyz;
- vec3_t normal;
-#ifdef USE_VERT_TANGENT_SPACE
- vec3_t tangent;
- vec3_t bitangent;
-#endif
-} mdvVertex_t;
-
-typedef struct
-{
- float st[2];
-} mdvSt_t;
-
-typedef struct mdvSurface_s
-{
- surfaceType_t surfaceType;
-
- char name[MAX_QPATH]; // polyset name
-
- int numShaderIndexes;
- int *shaderIndexes;
-
- int numVerts;
- mdvVertex_t *verts;
- mdvSt_t *st;
-
- int numTriangles;
- srfTriangle_t *triangles;
-
- struct mdvModel_s *model;
-} mdvSurface_t;
-
-typedef struct mdvModel_s
-{
- int numFrames;
- mdvFrame_t *frames;
-
- int numTags;
- mdvTag_t *tags;
- mdvTagName_t *tagNames;
-
- int numSurfaces;
- mdvSurface_t *surfaces;
-
- int numVBOSurfaces;
- srfVBOMDVMesh_t *vboSurfaces;
-
- int numSkins;
-} mdvModel_t;
-
-
-//======================================================================
-
-typedef enum {
- MOD_BAD,
- MOD_BRUSH,
- MOD_MESH,
- MOD_MD4,
-#ifdef RAVENMD4
- MOD_MDR,
-#endif
- MOD_IQM
-} modtype_t;
-
-typedef struct model_s {
- char name[MAX_QPATH];
- modtype_t type;
- int index; // model = tr.models[model->index]
-
- int dataSize; // just for listing purposes
- bmodel_t *bmodel; // only if type == MOD_BRUSH
- mdvModel_t *mdv[MD3_MAX_LODS]; // only if type == MOD_MESH
- void *modelData; // only if type == (MOD_MD4 | MOD_MDR | MOD_IQM)
-
- int numLods;
-} model_t;
-
-
-#define MAX_MOD_KNOWN 1024
-
-void R_ModelInit (void);
-model_t *R_GetModelByHandle( qhandle_t hModel );
-int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame,
- float frac, const char *tagName );
-void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs );
-
-void R_Modellist_f (void);
-
-//====================================================
-extern refimport_t ri;
-
-#define MAX_DRAWIMAGES 2048
-#define MAX_SKINS 1024
-
-
-#define MAX_DRAWSURFS 0x10000
-#define DRAWSURF_MASK (MAX_DRAWSURFS-1)
-
-/*
-
-the drawsurf sort data is packed into a single 32 bit value so it can be
-compared quickly during the qsorting process
-
-the bits are allocated as follows:
-
-0 - 1 : dlightmap index
-//2 : used to be clipped flag REMOVED - 03.21.00 rad
-2 - 6 : fog index
-11 - 20 : entity index
-21 - 31 : sorted shader index
-
- TTimo - 1.32
-0-1 : dlightmap index
-2-6 : fog index
-7-16 : entity index
-17-30 : sorted shader index
-
- SmileTheory - for pshadows
-17-31 : sorted shader index
-7-16 : entity index
-2-6 : fog index
-1 : pshadow flag
-0 : dlight flag
-*/
-#define QSORT_FOGNUM_SHIFT 2
-#define QSORT_REFENTITYNUM_SHIFT 7
-#define QSORT_SHADERNUM_SHIFT (QSORT_REFENTITYNUM_SHIFT+REFENTITYNUM_BITS)
-#if (QSORT_SHADERNUM_SHIFT+SHADERNUM_BITS) > 32
- #error "Need to update sorting, too many bits."
-#endif
-#define QSORT_PSHADOW_SHIFT 1
-
-extern int gl_filter_min, gl_filter_max;
-
-/*
-** performanceCounters_t
-*/
-typedef struct {
- int c_sphere_cull_patch_in, c_sphere_cull_patch_clip, c_sphere_cull_patch_out;
- int c_box_cull_patch_in, c_box_cull_patch_clip, c_box_cull_patch_out;
- int c_sphere_cull_md3_in, c_sphere_cull_md3_clip, c_sphere_cull_md3_out;
- int c_box_cull_md3_in, c_box_cull_md3_clip, c_box_cull_md3_out;
-
- int c_leafs;
- int c_dlightSurfaces;
- int c_dlightSurfacesCulled;
-} frontEndCounters_t;
-
-#define FOG_TABLE_SIZE 256
-#define FUNCTABLE_SIZE 1024
-#define FUNCTABLE_SIZE2 10
-#define FUNCTABLE_MASK (FUNCTABLE_SIZE-1)
-
-
-// the renderer front end should never modify glstate_t
-typedef struct {
- int currenttextures[NUM_TEXTURE_BUNDLES];
- int currenttmu;
- qboolean finishCalled;
- int texEnv[2];
- int faceCulling;
- unsigned long glStateBits;
- uint32_t vertexAttribsState;
- uint32_t vertexAttribPointersSet;
- uint32_t vertexAttribsNewFrame;
- uint32_t vertexAttribsOldFrame;
- float vertexAttribsInterpolation;
- shaderProgram_t *currentProgram;
- FBO_t *currentFBO;
- VBO_t *currentVBO;
- IBO_t *currentIBO;
- matrix_t modelview;
- matrix_t projection;
- matrix_t modelviewProjection;
-} glstate_t;
-
-typedef enum {
- MI_NONE,
- MI_NVX,
- MI_ATI
-} memInfo_t;
-
-typedef enum {
- TCR_NONE = 0x0000,
- TCR_LATC = 0x0001,
- TCR_BPTC = 0x0002,
-} textureCompressionRef_t;
-
-// We can't change glConfig_t without breaking DLL/vms compatibility, so
-// store extensions we have here.
-typedef struct {
- qboolean drawRangeElements;
- qboolean multiDrawArrays;
- qboolean occlusionQuery;
-
- int glslMajorVersion;
- int glslMinorVersion;
-
- memInfo_t memInfo;
-
- qboolean framebufferObject;
- int maxRenderbufferSize;
- int maxColorAttachments;
-
- qboolean textureNonPowerOfTwo;
- qboolean textureFloat;
- qboolean halfFloatPixel;
- qboolean packedDepthStencil;
- textureCompressionRef_t textureCompression;
-
- qboolean framebufferMultisample;
- qboolean framebufferBlit;
-
- qboolean texture_srgb;
-
- qboolean depthClamp;
-} glRefConfig_t;
-
-
-typedef struct {
- int c_surfaces, c_shaders, c_vertexes, c_indexes, c_totalIndexes;
- int c_surfBatches;
- float c_overDraw;
-
- int c_vboVertexBuffers;
- int c_vboIndexBuffers;
- int c_vboVertexes;
- int c_vboIndexes;
-
- int c_staticVboDraws;
- int c_dynamicVboDraws;
-
- int c_multidraws;
- int c_multidrawsMerged;
-
- int c_dlightVertexes;
- int c_dlightIndexes;
-
- int c_flareAdds;
- int c_flareTests;
- int c_flareRenders;
-
- int c_glslShaderBinds;
- int c_genericDraws;
- int c_lightallDraws;
- int c_fogDraws;
- int c_dlightDraws;
-
- int msec; // total msec for backend run
-} backEndCounters_t;
-
-// all state modified by the back end is seperated
-// from the front end state
-typedef struct {
- trRefdef_t refdef;
- viewParms_t viewParms;
- orientationr_t or;
- backEndCounters_t pc;
- qboolean isHyperspace;
- trRefEntity_t *currentEntity;
- qboolean skyRenderedThisView; // flag for drawing sun
-
- qboolean projection2D; // if qtrue, drawstretchpic doesn't need to change modes
- byte color2D[4];
- qboolean vertexes2D; // shader needs to be finished
- trRefEntity_t entity2D; // currentEntity will point at this when doing 2D rendering
-
- FBO_t *last2DFBO;
- qboolean colorMask[4];
- qboolean framePostProcessed;
- qboolean depthFill;
-} backEndState_t;
-
-/*
-** trGlobals_t
-**
-** Most renderer globals are defined here.
-** backend functions should never modify any of these fields,
-** but may read fields that aren't dynamically modified
-** by the frontend.
-*/
-typedef struct {
- qboolean registered; // cleared at shutdown, set at beginRegistration
-
- int visIndex;
- int visClusters[MAX_VISCOUNTS];
- int visCounts[MAX_VISCOUNTS]; // incremented every time a new vis cluster is entered
-
- int frameCount; // incremented every frame
- int sceneCount; // incremented every scene
- int viewCount; // incremented every view (twice a scene if portaled)
- // and every R_MarkFragments call
-
- int frameSceneNum; // zeroed at RE_BeginFrame
-
- qboolean worldMapLoaded;
- qboolean worldDeluxeMapping;
- vec2_t autoExposureMinMax;
- vec3_t toneMinAvgMaxLevel;
- world_t *world;
-
- const byte *externalVisData; // from RE_SetWorldVisData, shared with CM_Load
-
- image_t *defaultImage;
- image_t *scratchImage[32];
- image_t *fogImage;
- image_t *dlightImage; // inverse-quare highlight for projective adding
- image_t *flareImage;
- image_t *whiteImage; // full of 0xff
- image_t *identityLightImage; // full of tr.identityLightByte
-
- image_t *shadowCubemaps[MAX_DLIGHTS];
-
-
- image_t *renderImage;
- image_t *sunRaysImage;
- image_t *renderDepthImage;
- image_t *pshadowMaps[MAX_DRAWN_PSHADOWS];
- image_t *textureScratchImage[2];
- image_t *screenScratchImage;
- image_t *quarterImage[2];
- image_t *calcLevelsImage;
- image_t *targetLevelsImage;
- image_t *fixedLevelsImage;
- image_t *sunShadowDepthImage[3];
- image_t *screenShadowImage;
- image_t *screenSsaoImage;
- image_t *hdrDepthImage;
-
- image_t *textureDepthImage;
-
- FBO_t *renderFbo;
- FBO_t *msaaResolveFbo;
- FBO_t *sunRaysFbo;
- FBO_t *depthFbo;
- FBO_t *pshadowFbos[MAX_DRAWN_PSHADOWS];
- FBO_t *textureScratchFbo[2];
- FBO_t *screenScratchFbo;
- FBO_t *quarterFbo[2];
- FBO_t *calcLevelsFbo;
- FBO_t *targetLevelsFbo;
- FBO_t *sunShadowFbo[3];
- FBO_t *screenShadowFbo;
- FBO_t *screenSsaoFbo;
- FBO_t *hdrDepthFbo;
-
- shader_t *defaultShader;
- shader_t *shadowShader;
- shader_t *projectionShadowShader;
-
- shader_t *flareShader;
- shader_t *sunShader;
- shader_t *sunFlareShader;
-
- int numLightmaps;
- int lightmapSize;
- image_t **lightmaps;
- image_t **deluxemaps;
-
- int fatLightmapSize;
- int fatLightmapStep;
-
- trRefEntity_t *currentEntity;
- trRefEntity_t worldEntity; // point currentEntity at this when rendering world
- int currentEntityNum;
- int shiftedEntityNum; // currentEntityNum << QSORT_REFENTITYNUM_SHIFT
- model_t *currentModel;
-
- //
- // GPU shader programs
- //
- shaderProgram_t genericShader[GENERICDEF_COUNT];
- shaderProgram_t textureColorShader;
- shaderProgram_t fogShader[FOGDEF_COUNT];
- shaderProgram_t dlightShader[DLIGHTDEF_COUNT];
- shaderProgram_t lightallShader[LIGHTDEF_COUNT];
- shaderProgram_t shadowmapShader;
- shaderProgram_t pshadowShader;
- shaderProgram_t down4xShader;
- shaderProgram_t bokehShader;
- shaderProgram_t tonemapShader;
- shaderProgram_t calclevels4xShader[2];
- shaderProgram_t shadowmaskShader;
- shaderProgram_t ssaoShader;
- shaderProgram_t depthBlurShader[2];
-
-
- // -----------------------------------------
-
- viewParms_t viewParms;
-
- float identityLight; // 1.0 / ( 1 << overbrightBits )
- int identityLightByte; // identityLight * 255
- int overbrightBits; // r_overbrightBits->integer, but set to 0 if no hw gamma
-
- orientationr_t or; // for current entity
-
- trRefdef_t refdef;
-
- int viewCluster;
-
- float mapLightScale;
-
- qboolean sunShadows;
- vec3_t sunLight; // from the sky shader for this level
- vec3_t sunAmbient;
- vec3_t sunDirection;
-
- frontEndCounters_t pc;
- int frontEndMsec; // not in pc due to clearing issue
-
- vec4_t clipRegion; // 2D clipping region
-
- //
- // put large tables at the end, so most elements will be
- // within the +/32K indexed range on risc processors
- //
- model_t *models[MAX_MOD_KNOWN];
- int numModels;
-
- int numImages;
- image_t *images[MAX_DRAWIMAGES];
-
- int numFBOs;
- FBO_t *fbos[MAX_FBOS];
-
- int numVBOs;
- VBO_t *vbos[MAX_VBOS];
-
- int numIBOs;
- IBO_t *ibos[MAX_IBOS];
-
- // shader indexes from other modules will be looked up in tr.shaders[]
- // shader indexes from drawsurfs will be looked up in sortedShaders[]
- // lower indexed sortedShaders must be rendered first (opaque surfaces before translucent)
- int numShaders;
- shader_t *shaders[MAX_SHADERS];
- shader_t *sortedShaders[MAX_SHADERS];
-
- int numSkins;
- skin_t *skins[MAX_SKINS];
-
- GLuint sunFlareQuery[2];
- int sunFlareQueryIndex;
- qboolean sunFlareQueryActive[2];
-
- float sinTable[FUNCTABLE_SIZE];
- float squareTable[FUNCTABLE_SIZE];
- float triangleTable[FUNCTABLE_SIZE];
- float sawToothTable[FUNCTABLE_SIZE];
- float inverseSawToothTable[FUNCTABLE_SIZE];
- float fogTable[FOG_TABLE_SIZE];
-} trGlobals_t;
-
-extern backEndState_t backEnd;
-extern trGlobals_t tr;
-extern glconfig_t glConfig; // outside of TR since it shouldn't be cleared during ref re-init
-extern glstate_t glState; // outside of TR since it shouldn't be cleared during ref re-init
-
-// These three variables should live inside glConfig but can't because of compatibility issues to the original ID vms.
-// If you release a stand-alone game and your mod uses tr_types.h from this build you can safely move them to
-// the glconfig_t struct.
-extern qboolean textureFilterAnisotropic;
-extern int maxAnisotropy;
-extern glRefConfig_t glRefConfig;
-extern float displayAspect;
-
-
-//
-// cvars
-//
-extern cvar_t *r_flareSize;
-extern cvar_t *r_flareFade;
-// coefficient for the flare intensity falloff function.
-#define FLARE_STDCOEFF "150"
-extern cvar_t *r_flareCoeff;
-
-extern cvar_t *r_railWidth;
-extern cvar_t *r_railCoreWidth;
-extern cvar_t *r_railSegmentLength;
-
-extern cvar_t *r_ignore; // used for debugging anything
-extern cvar_t *r_verbose; // used for verbose debug spew
-
-extern cvar_t *r_znear; // near Z clip plane
-extern cvar_t *r_zproj; // z distance of projection plane
-extern cvar_t *r_stereoSeparation; // separation of cameras for stereo rendering
-
-extern cvar_t *r_stencilbits; // number of desired stencil bits
-extern cvar_t *r_depthbits; // number of desired depth bits
-extern cvar_t *r_colorbits; // number of desired color bits, only relevant for fullscreen
-extern cvar_t *r_texturebits; // number of desired texture bits
-extern cvar_t *r_ext_multisample;
- // 0 = use framebuffer depth
- // 16 = use 16-bit textures
- // 32 = use 32-bit textures
- // all else = error
-
-extern cvar_t *r_measureOverdraw; // enables stencil buffer overdraw measurement
-
-extern cvar_t *r_lodbias; // push/pull LOD transitions
-extern cvar_t *r_lodscale;
-
-extern cvar_t *r_inGameVideo; // controls whether in game video should be draw
-extern cvar_t *r_fastsky; // controls whether sky should be cleared or drawn
-extern cvar_t *r_drawSun; // controls drawing of sun quad
-extern cvar_t *r_dynamiclight; // dynamic lights enabled/disabled
-extern cvar_t *r_dlightBacks; // dlight non-facing surfaces for continuity
-
-extern cvar_t *r_norefresh; // bypasses the ref rendering
-extern cvar_t *r_drawentities; // disable/enable entity rendering
-extern cvar_t *r_drawworld; // disable/enable world rendering
-extern cvar_t *r_speeds; // various levels of information display
-extern cvar_t *r_detailTextures; // enables/disables detail texturing stages
-extern cvar_t *r_novis; // disable/enable usage of PVS
-extern cvar_t *r_nocull;
-extern cvar_t *r_facePlaneCull; // enables culling of planar surfaces with back side test
-extern cvar_t *r_nocurves;
-extern cvar_t *r_showcluster;
-
-extern cvar_t *r_mode; // video mode
-extern cvar_t *r_fullscreen;
-extern cvar_t *r_noborder;
-extern cvar_t *r_gamma;
-extern cvar_t *r_ignorehwgamma; // overrides hardware gamma capabilities
-
-extern cvar_t *r_allowExtensions; // global enable/disable of OpenGL extensions
-extern cvar_t *r_ext_compressed_textures; // these control use of specific extensions
-extern cvar_t *r_ext_multitexture;
-extern cvar_t *r_ext_compiled_vertex_array;
-extern cvar_t *r_ext_texture_env_add;
-
-extern cvar_t *r_ext_texture_filter_anisotropic;
-extern cvar_t *r_ext_max_anisotropy;
-
-extern cvar_t *r_ext_draw_range_elements;
-extern cvar_t *r_ext_multi_draw_arrays;
-extern cvar_t *r_ext_framebuffer_object;
-extern cvar_t *r_ext_texture_float;
-extern cvar_t *r_arb_half_float_pixel;
-extern cvar_t *r_ext_framebuffer_multisample;
-
-extern cvar_t *r_nobind; // turns off binding to appropriate textures
-extern cvar_t *r_singleShader; // make most world faces use default shader
-extern cvar_t *r_roundImagesDown;
-extern cvar_t *r_colorMipLevels; // development aid to see texture mip usage
-extern cvar_t *r_picmip; // controls picmip values
-extern cvar_t *r_finish;
-extern cvar_t *r_drawBuffer;
-extern cvar_t *r_swapInterval;
-extern cvar_t *r_textureMode;
-extern cvar_t *r_offsetFactor;
-extern cvar_t *r_offsetUnits;
-
-extern cvar_t *r_fullbright; // avoid lightmap pass
-extern cvar_t *r_lightmap; // render lightmaps only
-extern cvar_t *r_vertexLight; // vertex lighting mode for better performance
-extern cvar_t *r_uiFullScreen; // ui is running fullscreen
-
-extern cvar_t *r_logFile; // number of frames to emit GL logs
-extern cvar_t *r_showtris; // enables wireframe rendering of the world
-extern cvar_t *r_showsky; // forces sky in front of all surfaces
-extern cvar_t *r_shownormals; // draws wireframe normals
-extern cvar_t *r_clear; // force screen clear every frame
-
-extern cvar_t *r_shadows; // controls shadows: 0 = none, 1 = blur, 2 = stencil, 3 = black planar projection
-extern cvar_t *r_flares; // light flares
-
-extern cvar_t *r_intensity;
-
-extern cvar_t *r_lockpvs;
-extern cvar_t *r_noportals;
-extern cvar_t *r_portalOnly;
-
-extern cvar_t *r_subdivisions;
-extern cvar_t *r_lodCurveError;
-extern cvar_t *r_skipBackEnd;
-
-extern cvar_t *r_stereoEnabled;
-extern cvar_t *r_anaglyphMode;
-
-extern cvar_t *r_mergeMultidraws;
-extern cvar_t *r_mergeLeafSurfaces;
-
-extern cvar_t *r_softOverbright;
-
-extern cvar_t *r_hdr;
-extern cvar_t *r_postProcess;
-
-extern cvar_t *r_toneMap;
-extern cvar_t *r_forceToneMap;
-extern cvar_t *r_forceToneMapMin;
-extern cvar_t *r_forceToneMapAvg;
-extern cvar_t *r_forceToneMapMax;
-
-extern cvar_t *r_autoExposure;
-extern cvar_t *r_forceAutoExposure;
-extern cvar_t *r_forceAutoExposureMin;
-extern cvar_t *r_forceAutoExposureMax;
-
-extern cvar_t *r_cameraExposure;
-
-extern cvar_t *r_srgb;
-
-extern cvar_t *r_depthPrepass;
-extern cvar_t *r_ssao;
-
-extern cvar_t *r_normalMapping;
-extern cvar_t *r_specularMapping;
-extern cvar_t *r_deluxeMapping;
-extern cvar_t *r_parallaxMapping;
-extern cvar_t *r_normalAmbient;
-extern cvar_t *r_dlightMode;
-extern cvar_t *r_pshadowDist;
-extern cvar_t *r_recalcMD3Normals;
-extern cvar_t *r_mergeLightmaps;
-extern cvar_t *r_imageUpsample;
-extern cvar_t *r_imageUpsampleMaxSize;
-extern cvar_t *r_imageUpsampleType;
-extern cvar_t *r_genNormalMaps;
-extern cvar_t *r_forceSun;
-extern cvar_t *r_forceSunMapLightScale;
-extern cvar_t *r_forceSunLightScale;
-extern cvar_t *r_forceSunAmbientScale;
-extern cvar_t *r_drawSunRays;
-extern cvar_t *r_sunShadows;
-extern cvar_t *r_shadowFilter;
-extern cvar_t *r_shadowMapSize;
-extern cvar_t *r_shadowCascadeZNear;
-extern cvar_t *r_shadowCascadeZFar;
-extern cvar_t *r_shadowCascadeZBias;
-
-extern cvar_t *r_greyscale;
-
-extern cvar_t *r_ignoreGLErrors;
-
-extern cvar_t *r_overBrightBits;
-extern cvar_t *r_mapOverBrightBits;
-
-extern cvar_t *r_debugSurface;
-extern cvar_t *r_simpleMipMaps;
-
-extern cvar_t *r_showImages;
-extern cvar_t *r_debugSort;
-
-extern cvar_t *r_printShaders;
-extern cvar_t *r_saveFontData;
-
-extern cvar_t *r_marksOnTriangleMeshes;
-
-//====================================================================
-
-float R_NoiseGet4f( float x, float y, float z, float t );
-void R_NoiseInit( void );
-
-void R_SwapBuffers( int );
-
-void R_RenderView( viewParms_t *parms );
-void R_RenderDlightCubemaps(const refdef_t *fd);
-void R_RenderPshadowMaps(const refdef_t *fd);
-void R_RenderSunShadowMaps(const refdef_t *fd, int level);
-
-void R_AddMD3Surfaces( trRefEntity_t *e );
-void R_AddNullModelSurfaces( trRefEntity_t *e );
-void R_AddBeamSurfaces( trRefEntity_t *e );
-void R_AddRailSurfaces( trRefEntity_t *e, qboolean isUnderwater );
-void R_AddLightningBoltSurfaces( trRefEntity_t *e );
-
-void R_AddPolygonSurfaces( void );
-
-void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader,
- int *fogNum, int *dlightMap, int *pshadowMap );
-
-void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader,
- int fogIndex, int dlightMap, int pshadowMap );
-
-void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal,
- const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2);
-qboolean R_CalcTangentVectors(srfVert_t * dv[3]);
-void R_CalcSurfaceTriangleNeighbors(int numTriangles, srfTriangle_t * triangles);
-void R_CalcSurfaceTrianglePlanes(int numTriangles, srfTriangle_t * triangles, srfVert_t * verts);
-
-#define CULL_IN 0 // completely unclipped
-#define CULL_CLIP 1 // clipped by one or more planes
-#define CULL_OUT 2 // completely outside the clipping planes
-void R_LocalNormalToWorld (const vec3_t local, vec3_t world);
-void R_LocalPointToWorld (const vec3_t local, vec3_t world);
-int R_CullBox (vec3_t bounds[2]);
-int R_CullLocalBox (vec3_t bounds[2]);
-int R_CullPointAndRadiusEx( const vec3_t origin, float radius, const cplane_t* frustum, int numPlanes );
-int R_CullPointAndRadius( const vec3_t origin, float radius );
-int R_CullLocalPointAndRadius( const vec3_t origin, float radius );
-
-void R_SetupProjection(viewParms_t *dest, float zProj, float zFar, qboolean computeFrustum);
-void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms, orientationr_t *or );
-
-/*
-** GL wrapper/helper functions
-*/
-void GL_Bind( image_t *image );
-void GL_BindCubemap( image_t *image );
-void GL_BindToTMU( image_t *image, int tmu );
-void GL_SetDefaultState (void);
-void GL_SelectTexture( int unit );
-void GL_TextureMode( const char *string );
-void GL_CheckErrs( char *file, int line );
-#define GL_CheckErrors(...) GL_CheckErrs(__FILE__, __LINE__)
-void GL_State( unsigned long stateVector );
-void GL_SetProjectionMatrix(matrix_t matrix);
-void GL_SetModelviewMatrix(matrix_t matrix);
-void GL_TexEnv( int env );
-void GL_Cull( int cullType );
-
-#define GLS_SRCBLEND_ZERO 0x00000001
-#define GLS_SRCBLEND_ONE 0x00000002
-#define GLS_SRCBLEND_DST_COLOR 0x00000003
-#define GLS_SRCBLEND_ONE_MINUS_DST_COLOR 0x00000004
-#define GLS_SRCBLEND_SRC_ALPHA 0x00000005
-#define GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA 0x00000006
-#define GLS_SRCBLEND_DST_ALPHA 0x00000007
-#define GLS_SRCBLEND_ONE_MINUS_DST_ALPHA 0x00000008
-#define GLS_SRCBLEND_ALPHA_SATURATE 0x00000009
-#define GLS_SRCBLEND_BITS 0x0000000f
-
-#define GLS_DSTBLEND_ZERO 0x00000010
-#define GLS_DSTBLEND_ONE 0x00000020
-#define GLS_DSTBLEND_SRC_COLOR 0x00000030
-#define GLS_DSTBLEND_ONE_MINUS_SRC_COLOR 0x00000040
-#define GLS_DSTBLEND_SRC_ALPHA 0x00000050
-#define GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA 0x00000060
-#define GLS_DSTBLEND_DST_ALPHA 0x00000070
-#define GLS_DSTBLEND_ONE_MINUS_DST_ALPHA 0x00000080
-#define GLS_DSTBLEND_BITS 0x000000f0
-
-#define GLS_DEPTHMASK_TRUE 0x00000100
-
-#define GLS_POLYMODE_LINE 0x00001000
-
-#define GLS_DEPTHTEST_DISABLE 0x00010000
-#define GLS_DEPTHFUNC_EQUAL 0x00020000
-#define GLS_DEPTHFUNC_GREATER 0x00040000
-#define GLS_DEPTHFUNC_BITS 0x00060000
-
-#define GLS_ATEST_GT_0 0x10000000
-#define GLS_ATEST_LT_80 0x20000000
-#define GLS_ATEST_GE_80 0x40000000
-#define GLS_ATEST_BITS 0x70000000
-
-#define GLS_DEFAULT GLS_DEPTHMASK_TRUE
-
-void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty);
-void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty);
-
-void RE_BeginFrame( stereoFrame_t stereoFrame );
-void RE_BeginRegistration( glconfig_t *glconfig );
-void RE_LoadWorldMap( const char *mapname );
-void RE_SetWorldVisData( const byte *vis );
-qhandle_t RE_RegisterModel( const char *name );
-qhandle_t RE_RegisterSkin( const char *name );
-void RE_Shutdown( qboolean destroyWindow );
-
-qboolean R_GetEntityToken( char *buffer, int size );
-
-model_t *R_AllocModel( void );
-
-void R_Init( void );
-image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags );
-image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat );
-void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height );
-qboolean R_GetModeInfo( int *width, int *height, float *windowAspect, int mode );
-
-void R_SetColorMappings( void );
-void R_GammaCorrect( byte *buffer, int bufSize );
-
-void R_ImageList_f( void );
-void R_SkinList_f( void );
-// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=516
-const void *RB_TakeScreenshotCmd( const void *data );
-void R_ScreenShot_f( void );
-
-void R_InitFogTable( void );
-float R_FogFactor( float s, float t );
-void R_InitImages( void );
-void R_DeleteTextures( void );
-int R_SumOfUsedImages( void );
-void R_InitSkins( void );
-skin_t *R_GetSkinByHandle( qhandle_t hSkin );
-
-int R_ComputeLOD( trRefEntity_t *ent );
-
-const void *RB_TakeVideoFrameCmd( const void *data );
-
-//
-// tr_shader.c
-//
-qhandle_t RE_RegisterShaderLightMap( const char *name, int lightmapIndex );
-qhandle_t RE_RegisterShader( const char *name );
-qhandle_t RE_RegisterShaderNoMip( const char *name );
-qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage);
-
-shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage );
-shader_t *R_GetShaderByHandle( qhandle_t hShader );
-shader_t *R_GetShaderByState( int index, long *cycleTime );
-shader_t *R_FindShaderByName( const char *name );
-void R_InitShaders( void );
-void R_ShaderList_f( void );
-void R_RemapShader(const char *oldShader, const char *newShader, const char *timeOffset);
-
-/*
-====================================================================
-
-IMPLEMENTATION SPECIFIC FUNCTIONS
-
-====================================================================
-*/
-
-void GLimp_Init( void );
-void GLimp_Shutdown( void );
-void GLimp_EndFrame( void );
-
-void GLimp_LogComment( char *comment );
-void GLimp_Minimize(void);
-
-// NOTE TTimo linux works with float gamma value, not the gamma table
-// the params won't be used, getting the r_gamma cvar directly
-void GLimp_SetGamma( unsigned char red[256],
- unsigned char green[256],
- unsigned char blue[256] );
-
-
-void GLimp_InitExtraExtensions( void );
-/*
-====================================================================
-
-TESSELATOR/SHADER DECLARATIONS
-
-====================================================================
-*/
-
-typedef struct stageVars
-{
- color4ub_t colors[SHADER_MAX_VERTEXES];
- vec2_t texcoords[NUM_TEXTURE_BUNDLES][SHADER_MAX_VERTEXES];
-} stageVars_t;
-
-#define MAX_MULTIDRAW_PRIMITIVES 16384
-
-typedef struct shaderCommands_s
-{
- glIndex_t indexes[SHADER_MAX_INDEXES] QALIGN(16);
- vec4_t xyz[SHADER_MAX_VERTEXES] QALIGN(16);
- vec4_t normal[SHADER_MAX_VERTEXES] QALIGN(16);
-#ifdef USE_VERT_TANGENT_SPACE
- vec4_t tangent[SHADER_MAX_VERTEXES] QALIGN(16);
- vec4_t bitangent[SHADER_MAX_VERTEXES] QALIGN(16);
-#endif
- vec2_t texCoords[SHADER_MAX_VERTEXES][2] QALIGN(16);
- vec4_t vertexColors[SHADER_MAX_VERTEXES] QALIGN(16);
- vec4_t lightdir[SHADER_MAX_VERTEXES] QALIGN(16);
- //int vertexDlightBits[SHADER_MAX_VERTEXES] QALIGN(16);
-
- VBO_t *vbo;
- IBO_t *ibo;
- qboolean useInternalVBO;
-
- stageVars_t svars QALIGN(16);
-
- //color4ub_t constantColor255[SHADER_MAX_VERTEXES] QALIGN(16);
-
- shader_t *shader;
- float shaderTime;
- int fogNum;
-
- int dlightBits; // or together of all vertexDlightBits
- int pshadowBits;
-
- int firstIndex;
- int numIndexes;
- int numVertexes;
- glIndex_t minIndex;
- glIndex_t maxIndex;
-
- int multiDrawPrimitives;
- GLsizei multiDrawNumIndexes[MAX_MULTIDRAW_PRIMITIVES];
- glIndex_t *multiDrawFirstIndex[MAX_MULTIDRAW_PRIMITIVES];
- glIndex_t *multiDrawLastIndex[MAX_MULTIDRAW_PRIMITIVES];
- glIndex_t multiDrawMinIndex[MAX_MULTIDRAW_PRIMITIVES];
- glIndex_t multiDrawMaxIndex[MAX_MULTIDRAW_PRIMITIVES];
-
- // info extracted from current shader
- int numPasses;
- void (*currentStageIteratorFunc)( void );
- shaderStage_t **xstages;
-} shaderCommands_t;
-
-extern shaderCommands_t tess;
-
-void RB_BeginSurface(shader_t *shader, int fogNum );
-void RB_EndSurface(void);
-void RB_CheckOverflow( int verts, int indexes );
-#define RB_CHECKOVERFLOW(v,i) if (tess.numVertexes + (v) >= SHADER_MAX_VERTEXES || tess.numIndexes + (i) >= SHADER_MAX_INDEXES ) {RB_CheckOverflow(v,i);}
-
-void R_DrawElementsVBO( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex, glIndex_t maxIndex );
-void RB_StageIteratorGeneric( void );
-void RB_StageIteratorSky( void );
-void RB_StageIteratorVertexLitTexture( void );
-void RB_StageIteratorLightmappedMultitexture( void );
-
-void RB_AddQuadStamp( vec3_t origin, vec3_t left, vec3_t up, float color[4] );
-void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float color[4], float s1, float t1, float s2, float t2 );
-void RB_InstantQuad( vec4_t quadVerts[4] );
-//void RB_InstantQuad2(vec4_t quadVerts[4], vec2_t texCoords[4], vec4_t color, shaderProgram_t *sp, vec2_t invTexRes);
-void RB_InstantQuad2(vec4_t quadVerts[4], vec2_t texCoords[4]);
-
-void RB_ShowImages( void );
-
-
-/*
-============================================================
-
-WORLD MAP
-
-============================================================
-*/
-
-void R_AddBrushModelSurfaces( trRefEntity_t *e );
-void R_AddWorldSurfaces( void );
-qboolean R_inPVS( const vec3_t p1, const vec3_t p2 );
-
-
-/*
-============================================================
-
-FLARES
-
-============================================================
-*/
-
-void R_ClearFlares( void );
-
-void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, vec3_t normal );
-void RB_AddDlightFlares( void );
-void RB_RenderFlares (void);
-
-/*
-============================================================
-
-LIGHTS
-
-============================================================
-*/
-
-void R_DlightBmodel( bmodel_t *bmodel );
-void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent );
-void R_TransformDlights( int count, dlight_t *dl, orientationr_t *or );
-int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir );
-int R_LightDirForPoint( vec3_t point, vec3_t lightDir, vec3_t normal, world_t *world );
-
-
-/*
-============================================================
-
-SHADOWS
-
-============================================================
-*/
-
-void RB_ShadowTessEnd( void );
-void RB_ShadowFinish( void );
-void RB_ProjectionShadowDeform( void );
-
-/*
-============================================================
-
-SKIES
-
-============================================================
-*/
-
-void R_BuildCloudData( shaderCommands_t *shader );
-void R_InitSkyTexCoords( float cloudLayerHeight );
-void R_DrawSkyBox( shaderCommands_t *shader );
-void RB_DrawSun( float scale, shader_t *shader );
-void RB_ClipSkyPolygons( shaderCommands_t *shader );
-
-/*
-============================================================
-
-CURVE TESSELATION
-
-============================================================
-*/
-
-#define PATCH_STITCHING
-
-srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
- srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] );
-srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror );
-srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror );
-void R_FreeSurfaceGridMesh( srfGridMesh_t *grid );
-
-/*
-============================================================
-
-MARKERS, POLYGON PROJECTION ON WORLD POLYGONS
-
-============================================================
-*/
-
-int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection,
- int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer );
-
-
-/*
-============================================================
-
-VERTEX BUFFER OBJECTS
-
-============================================================
-*/
-VBO_t *R_CreateVBO(const char *name, byte * vertexes, int vertexesSize, vboUsage_t usage);
-VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vertexes, uint32_t stateBits, vboUsage_t usage);
-
-IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage);
-IBO_t *R_CreateIBO2(const char *name, int numTriangles, srfTriangle_t * triangles, vboUsage_t usage);
-
-void R_BindVBO(VBO_t * vbo);
-void R_BindNullVBO(void);
-
-void R_BindIBO(IBO_t * ibo);
-void R_BindNullIBO(void);
-
-void R_InitVBOs(void);
-void R_ShutdownVBOs(void);
-void R_VBOList_f(void);
-
-void RB_UpdateVBOs(unsigned int attribBits);
-
-
-/*
-============================================================
-
-GLSL
-
-============================================================
-*/
-
-void GLSL_InitGPUShaders(void);
-void GLSL_ShutdownGPUShaders(void);
-void GLSL_VertexAttribsState(uint32_t stateBits);
-void GLSL_VertexAttribPointers(uint32_t attribBits);
-void GLSL_BindProgram(shaderProgram_t * program);
-void GLSL_BindNullProgram(void);
-
-void GLSL_SetNumUniforms(shaderProgram_t *program, int numUniforms);
-void GLSL_SetUniformName(shaderProgram_t *program, int uniformNum, const char *name);
-void GLSL_SetUniformInt(shaderProgram_t *program, int uniformNum, GLint value);
-void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat value);
-void GLSL_SetUniformFloat5(shaderProgram_t *program, int uniformNum, const vec5_t v);
-void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const vec2_t v);
-void GLSL_SetUniformVec3(shaderProgram_t *program, int uniformNum, const vec3_t v);
-void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const vec4_t v);
-void GLSL_SetUniformMatrix16(shaderProgram_t *program, int uniformNum, const matrix_t matrix);
-
-shaderProgram_t *GLSL_GetGenericShaderProgram(int stage);
-
-/*
-============================================================
-
-SCENE GENERATION
-
-============================================================
-*/
-
-void R_InitNextFrame( void );
-
-void RE_ClearScene( void );
-void RE_AddRefEntityToScene( const refEntity_t *ent );
-void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int num );
-void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b );
-void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b );
-void RE_RenderScene( const refdef_t *fd );
-
-#ifdef RAVENMD4
-/*
-=============================================================
-
-UNCOMPRESSING BONES
-
-=============================================================
-*/
-
-#define MC_BITS_X (16)
-#define MC_BITS_Y (16)
-#define MC_BITS_Z (16)
-#define MC_BITS_VECT (16)
-
-#define MC_SCALE_X (1.0f/64)
-#define MC_SCALE_Y (1.0f/64)
-#define MC_SCALE_Z (1.0f/64)
-
-void MC_UnCompress(float mat[3][4],const unsigned char * comp);
-#endif
-
-/*
-=============================================================
-
-ANIMATED MODELS
-
-=============================================================
-*/
-
-// void R_MakeAnimModel( model_t *model ); haven't seen this one really, so not needed I guess.
-void R_AddAnimSurfaces( trRefEntity_t *ent );
-void RB_SurfaceAnim( md4Surface_t *surfType );
-#ifdef RAVENMD4
-void R_MDRAddAnimSurfaces( trRefEntity_t *ent );
-void RB_MDRSurfaceAnim( md4Surface_t *surface );
-#endif
-qboolean R_LoadIQM (model_t *mod, void *buffer, int filesize, const char *name );
-void R_AddIQMSurfaces( trRefEntity_t *ent );
-void RB_IQMSurfaceAnim( surfaceType_t *surface );
-int R_IQMLerpTag( orientation_t *tag, iqmData_t *data,
- int startFrame, int endFrame,
- float frac, const char *tagName );
-
-/*
-=============================================================
-
-IMAGE LOADERS
-
-=============================================================
-*/
-
-void R_LoadBMP( const char *name, byte **pic, int *width, int *height );
-void R_LoadJPG( const char *name, byte **pic, int *width, int *height );
-void R_LoadPCX( const char *name, byte **pic, int *width, int *height );
-void R_LoadPNG( const char *name, byte **pic, int *width, int *height );
-void R_LoadTGA( const char *name, byte **pic, int *width, int *height );
-
-/*
-=============================================================
-=============================================================
-*/
-void R_TransformModelToClip( const vec3_t src, const float *modelMatrix, const float *projectionMatrix,
- vec4_t eye, vec4_t dst );
-void R_TransformClipToWindow( const vec4_t clip, const viewParms_t *view, vec4_t normalized, vec4_t window );
-
-void RB_DeformTessGeometry( void );
-
-void RB_CalcEnvironmentTexCoords( float *dstTexCoords );
-void RB_CalcFogTexCoords( float *dstTexCoords );
-void RB_CalcScrollTexCoords( const float scroll[2], float *dstTexCoords );
-void RB_CalcRotateTexCoords( float rotSpeed, float *dstTexCoords );
-void RB_CalcScaleTexCoords( const float scale[2], float *dstTexCoords );
-void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *dstTexCoords );
-void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *dstTexCoords );
-
-void RB_CalcScaleTexMatrix( const float scale[2], float *matrix );
-void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix );
-void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix );
-void RB_CalcTurbulentTexMatrix( const waveForm_t *wf, matrix_t matrix );
-void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix );
-void RB_CalcStretchTexMatrix( const waveForm_t *wf, float *matrix );
-
-void RB_CalcModulateColorsByFog( unsigned char *dstColors );
-void RB_CalcModulateAlphasByFog( unsigned char *dstColors );
-void RB_CalcModulateRGBAsByFog( unsigned char *dstColors );
-void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors );
-float RB_CalcWaveAlphaSingle( const waveForm_t *wf );
-void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors );
-float RB_CalcWaveColorSingle( const waveForm_t *wf );
-void RB_CalcAlphaFromEntity( unsigned char *dstColors );
-void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors );
-void RB_CalcStretchTexCoords( const waveForm_t *wf, float *texCoords );
-void RB_CalcColorFromEntity( unsigned char *dstColors );
-void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors );
-void RB_CalcSpecularAlpha( unsigned char *alphas );
-void RB_CalcDiffuseColor( unsigned char *colors );
-
-/*
-=============================================================
-
-RENDERER BACK END FUNCTIONS
-
-=============================================================
-*/
-
-void RB_ExecuteRenderCommands( const void *data );
-
-/*
-=============================================================
-
-RENDERER BACK END COMMAND QUEUE
-
-=============================================================
-*/
-
-#define MAX_RENDER_COMMANDS 0x40000
-
-typedef struct {
- byte cmds[MAX_RENDER_COMMANDS];
- int used;
-} renderCommandList_t;
-
-typedef struct {
- int commandId;
- float color[4];
-} setColorCommand_t;
-
-typedef struct {
- int commandId;
- int buffer;
-} drawBufferCommand_t;
-
-typedef struct {
- int commandId;
- image_t *image;
- int width;
- int height;
- void *data;
-} subImageCommand_t;
-
-typedef struct {
- int commandId;
-} swapBuffersCommand_t;
-
-typedef struct {
- int commandId;
- int buffer;
-} endFrameCommand_t;
-
-typedef struct {
- int commandId;
- shader_t *shader;
- float x, y;
- float w, h;
- float s1, t1;
- float s2, t2;
-} stretchPicCommand_t;
-
-typedef struct {
- int commandId;
- trRefdef_t refdef;
- viewParms_t viewParms;
- drawSurf_t *drawSurfs;
- int numDrawSurfs;
-} drawSurfsCommand_t;
-
-typedef struct {
- int commandId;
- int x;
- int y;
- int width;
- int height;
- char *fileName;
- qboolean jpeg;
-} screenshotCommand_t;
-
-typedef struct {
- int commandId;
- int width;
- int height;
- byte *captureBuffer;
- byte *encodeBuffer;
- qboolean motionJpeg;
-} videoFrameCommand_t;
-
-typedef struct
-{
- int commandId;
-
- GLboolean rgba[4];
-} colorMaskCommand_t;
-
-typedef struct
-{
- int commandId;
-} clearDepthCommand_t;
-
-typedef struct {
- int commandId;
- int map;
- int cubeSide;
-} capShadowmapCommand_t;
-
-typedef struct {
- int commandId;
- trRefdef_t refdef;
- viewParms_t viewParms;
-} postProcessCommand_t;
-
-typedef enum {
- RC_END_OF_LIST,
- RC_SET_COLOR,
- RC_STRETCH_PIC,
- RC_DRAW_SURFS,
- RC_DRAW_BUFFER,
- RC_SWAP_BUFFERS,
- RC_SCREENSHOT,
- RC_VIDEOFRAME,
- RC_COLORMASK,
- RC_CLEARDEPTH,
- RC_CAPSHADOWMAP,
- RC_POSTPROCESS
-} renderCommand_t;
-
-
-// these are sort of arbitrary limits.
-// the limits apply to the sum of all scenes in a frame --
-// the main view, all the 3D icons, etc
-#define MAX_POLYS 600
-#define MAX_POLYVERTS 3000
-
-// all of the information needed by the back end must be
-// contained in a backEndData_t
-typedef struct {
- drawSurf_t drawSurfs[MAX_DRAWSURFS];
- dlight_t dlights[MAX_DLIGHTS];
- trRefEntity_t entities[MAX_REFENTITIES];
- srfPoly_t *polys;//[MAX_POLYS];
- polyVert_t *polyVerts;//[MAX_POLYVERTS];
- pshadow_t pshadows[MAX_CALC_PSHADOWS];
- renderCommandList_t commands;
-} backEndData_t;
-
-extern int max_polys;
-extern int max_polyverts;
-
-extern backEndData_t *backEndData; // the second one may not be allocated
-
-extern volatile renderCommandList_t *renderCommandList;
-
-
-void *R_GetCommandBuffer( int bytes );
-void RB_ExecuteRenderCommands( const void *data );
-
-void R_IssuePendingRenderCommands( void );
-
-void R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs );
-void R_AddCapShadowmapCmd( int dlight, int cubeSide );
-void R_AddPostProcessCmd (void);
-
-void RE_SetColor( const float *rgba );
-void RE_SetClipRegion( const float *region );
-void RE_StretchPic ( float x, float y, float w, float h,
- float s1, float t1, float s2, float t2, qhandle_t hShader );
-void RE_BeginFrame( stereoFrame_t stereoFrame );
-void RE_EndFrame( int *frontEndMsec, int *backEndMsec );
-void RE_SaveJPG(char * filename, int quality, int image_width, int image_height,
- unsigned char *image_buffer, int padding);
-size_t RE_SaveJPGToBuffer(byte *buffer, size_t bufSize, int quality,
- int image_width, int image_height, byte *image_buffer, int padding);
-void RE_TakeVideoFrame( int width, int height,
- byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg );
-
-// font stuff
-void R_InitFreeType( void );
-void R_DoneFreeType( void );
-void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font);
-
-
-#endif //TR_LOCAL_H
diff --git a/src/rend2/tr_main.c b/src/rend2/tr_main.c
deleted file mode 100644
index 0935dce7..00000000
--- a/src/rend2/tr_main.c
+++ /dev/null
@@ -1,2882 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_main.c -- main control flow for each frame
-
-#include "tr_local.h"
-
-#include <string.h> // memcpy
-
-trGlobals_t tr;
-
-static float s_flipMatrix[16] = {
- // convert from our coordinate system (looking down X)
- // to OpenGL's coordinate system (looking down -Z)
- 0, 0, -1, 0,
- -1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 0, 1
-};
-
-
-refimport_t ri;
-
-// entities that will have procedurally generated surfaces will just
-// point at this for their sorting surface
-surfaceType_t entitySurface = SF_ENTITY;
-
-/*
-================
-R_CompareVert
-================
-*/
-qboolean R_CompareVert(srfVert_t * v1, srfVert_t * v2, qboolean checkST)
-{
- int i;
-
- for(i = 0; i < 3; i++)
- {
- if(floor(v1->xyz[i] + 0.1) != floor(v2->xyz[i] + 0.1))
- {
- return qfalse;
- }
-
- if(checkST && ((v1->st[0] != v2->st[0]) || (v1->st[1] != v2->st[1])))
- {
- return qfalse;
- }
- }
-
- return qtrue;
-}
-
-/*
-=============
-R_CalcNormalForTriangle
-=============
-*/
-void R_CalcNormalForTriangle(vec3_t normal, const vec3_t v0, const vec3_t v1, const vec3_t v2)
-{
- vec3_t udir, vdir;
-
- // compute the face normal based on vertex points
- VectorSubtract(v2, v0, udir);
- VectorSubtract(v1, v0, vdir);
- CrossProduct(udir, vdir, normal);
-
- VectorNormalize(normal);
-}
-
-/*
-=============
-R_CalcTangentsForTriangle
-http://members.rogers.com/deseric/tangentspace.htm
-=============
-*/
-void R_CalcTangentsForTriangle(vec3_t tangent, vec3_t bitangent,
- const vec3_t v0, const vec3_t v1, const vec3_t v2,
- const vec2_t t0, const vec2_t t1, const vec2_t t2)
-{
- int i;
- vec3_t planes[3];
- vec3_t u, v;
-
- for(i = 0; i < 3; i++)
- {
- VectorSet(u, v1[i] - v0[i], t1[0] - t0[0], t1[1] - t0[1]);
- VectorSet(v, v2[i] - v0[i], t2[0] - t0[0], t2[1] - t0[1]);
-
- VectorNormalize(u);
- VectorNormalize(v);
-
- CrossProduct(u, v, planes[i]);
- }
-
- //So your tangent space will be defined by this :
- //Normal = Normal of the triangle or Tangent X Bitangent (careful with the cross product,
- // you have to make sure the normal points in the right direction)
- //Tangent = ( dp(Fx(s,t)) / ds, dp(Fy(s,t)) / ds, dp(Fz(s,t)) / ds ) or ( -Bx/Ax, -By/Ay, - Bz/Az )
- //Bitangent = ( dp(Fx(s,t)) / dt, dp(Fy(s,t)) / dt, dp(Fz(s,t)) / dt ) or ( -Cx/Ax, -Cy/Ay, -Cz/Az )
-
- // tangent...
- tangent[0] = -planes[0][1] / planes[0][0];
- tangent[1] = -planes[1][1] / planes[1][0];
- tangent[2] = -planes[2][1] / planes[2][0];
- VectorNormalize(tangent);
-
- // bitangent...
- bitangent[0] = -planes[0][2] / planes[0][0];
- bitangent[1] = -planes[1][2] / planes[1][0];
- bitangent[2] = -planes[2][2] / planes[2][0];
- VectorNormalize(bitangent);
-}
-
-
-
-
-/*
-=============
-R_CalcTangentSpace
-=============
-*/
-void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal,
- const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2)
-{
- vec3_t cp, u, v;
- vec3_t faceNormal;
-
- VectorSet(u, v1[0] - v0[0], t1[0] - t0[0], t1[1] - t0[1]);
- VectorSet(v, v2[0] - v0[0], t2[0] - t0[0], t2[1] - t0[1]);
-
- CrossProduct(u, v, cp);
- if(fabs(cp[0]) > 10e-6)
- {
- tangent[0] = -cp[1] / cp[0];
- bitangent[0] = -cp[2] / cp[0];
- }
-
- u[0] = v1[1] - v0[1];
- v[0] = v2[1] - v0[1];
-
- CrossProduct(u, v, cp);
- if(fabs(cp[0]) > 10e-6)
- {
- tangent[1] = -cp[1] / cp[0];
- bitangent[1] = -cp[2] / cp[0];
- }
-
- u[0] = v1[2] - v0[2];
- v[0] = v2[2] - v0[2];
-
- CrossProduct(u, v, cp);
- if(fabs(cp[0]) > 10e-6)
- {
- tangent[2] = -cp[1] / cp[0];
- bitangent[2] = -cp[2] / cp[0];
- }
-
- VectorNormalize(tangent);
- VectorNormalize(bitangent);
-
- // compute the face normal based on vertex points
- if ( normal[0] == 0.0f && normal[1] == 0.0f && normal[2] == 0.0f )
- {
- VectorSubtract(v2, v0, u);
- VectorSubtract(v1, v0, v);
- CrossProduct(u, v, faceNormal);
- }
- else
- {
- VectorCopy(normal, faceNormal);
- }
-
- VectorNormalize(faceNormal);
-
-#if 1
- // Gram-Schmidt orthogonalize
- //tangent[a] = (t - n * Dot(n, t)).Normalize();
- VectorMA(tangent, -DotProduct(faceNormal, tangent), faceNormal, tangent);
- VectorNormalize(tangent);
-
- // compute the cross product B=NxT
- //CrossProduct(normal, tangent, bitangent);
-#else
- // normal, compute the cross product N=TxB
- CrossProduct(tangent, bitangent, normal);
- VectorNormalize(normal);
-
- if(DotProduct(normal, faceNormal) < 0)
- {
- //VectorInverse(normal);
- //VectorInverse(tangent);
- //VectorInverse(bitangent);
-
- // compute the cross product T=BxN
- CrossProduct(bitangent, faceNormal, tangent);
-
- // compute the cross product B=NxT
- //CrossProduct(normal, tangent, bitangent);
- }
-#endif
-
- VectorCopy(faceNormal, normal);
-}
-
-void R_CalcTangentSpaceFast(vec3_t tangent, vec3_t bitangent, vec3_t normal,
- const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2)
-{
- vec3_t cp, u, v;
- vec3_t faceNormal;
-
- VectorSet(u, v1[0] - v0[0], t1[0] - t0[0], t1[1] - t0[1]);
- VectorSet(v, v2[0] - v0[0], t2[0] - t0[0], t2[1] - t0[1]);
-
- CrossProduct(u, v, cp);
- if(fabs(cp[0]) > 10e-6)
- {
- tangent[0] = -cp[1] / cp[0];
- bitangent[0] = -cp[2] / cp[0];
- }
-
- u[0] = v1[1] - v0[1];
- v[0] = v2[1] - v0[1];
-
- CrossProduct(u, v, cp);
- if(fabs(cp[0]) > 10e-6)
- {
- tangent[1] = -cp[1] / cp[0];
- bitangent[1] = -cp[2] / cp[0];
- }
-
- u[0] = v1[2] - v0[2];
- v[0] = v2[2] - v0[2];
-
- CrossProduct(u, v, cp);
- if(fabs(cp[0]) > 10e-6)
- {
- tangent[2] = -cp[1] / cp[0];
- bitangent[2] = -cp[2] / cp[0];
- }
-
- VectorNormalizeFast(tangent);
- VectorNormalizeFast(bitangent);
-
- // compute the face normal based on vertex points
- VectorSubtract(v2, v0, u);
- VectorSubtract(v1, v0, v);
- CrossProduct(u, v, faceNormal);
-
- VectorNormalizeFast(faceNormal);
-
-#if 0
- // normal, compute the cross product N=TxB
- CrossProduct(tangent, bitangent, normal);
- VectorNormalizeFast(normal);
-
- if(DotProduct(normal, faceNormal) < 0)
- {
- VectorInverse(normal);
- //VectorInverse(tangent);
- //VectorInverse(bitangent);
-
- CrossProduct(normal, tangent, bitangent);
- }
-
- VectorCopy(faceNormal, normal);
-#else
- // Gram-Schmidt orthogonalize
- //tangent[a] = (t - n * Dot(n, t)).Normalize();
- VectorMA(tangent, -DotProduct(faceNormal, tangent), faceNormal, tangent);
- VectorNormalizeFast(tangent);
-#endif
-
- VectorCopy(faceNormal, normal);
-}
-
-/*
-http://www.terathon.com/code/tangent.html
-*/
-void R_CalcTBN(vec3_t tangent, vec3_t bitangent, vec3_t normal,
- const vec3_t v1, const vec3_t v2, const vec3_t v3, const vec2_t w1, const vec2_t w2, const vec2_t w3)
-{
- vec3_t u, v;
- float x1, x2, y1, y2, z1, z2;
- float s1, s2, t1, t2;
- float r, dot;
-
- x1 = v2[0] - v1[0];
- x2 = v3[0] - v1[0];
- y1 = v2[1] - v1[1];
- y2 = v3[1] - v1[1];
- z1 = v2[2] - v1[2];
- z2 = v3[2] - v1[2];
-
- s1 = w2[0] - w1[0];
- s2 = w3[0] - w1[0];
- t1 = w2[1] - w1[1];
- t2 = w3[1] - w1[1];
-
- r = 1.0f / (s1 * t2 - s2 * t1);
-
- VectorSet(tangent, (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
- VectorSet(bitangent, (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
-
- // compute the face normal based on vertex points
- VectorSubtract(v3, v1, u);
- VectorSubtract(v2, v1, v);
- CrossProduct(u, v, normal);
-
- VectorNormalize(normal);
-
- // Gram-Schmidt orthogonalize
- //tangent[a] = (t - n * Dot(n, t)).Normalize();
- dot = DotProduct(normal, tangent);
- VectorMA(tangent, -dot, normal, tangent);
- VectorNormalize(tangent);
-
- // B=NxT
- //CrossProduct(normal, tangent, bitangent);
-}
-
-void R_CalcTBN2(vec3_t tangent, vec3_t bitangent, vec3_t normal,
- const vec3_t v1, const vec3_t v2, const vec3_t v3, const vec2_t t1, const vec2_t t2, const vec2_t t3)
-{
- vec3_t v2v1;
- vec3_t v3v1;
-
- float c2c1_T;
- float c2c1_B;
-
- float c3c1_T;
- float c3c1_B;
-
- float denominator;
- float scale1, scale2;
-
- vec3_t T, B, N, C;
-
-
- // Calculate the tangent basis for each vertex of the triangle
- // UPDATE: In the 3rd edition of the accompanying article, the for-loop located here has
- // been removed as it was redundant (the entire TBN matrix was calculated three times
- // instead of just one).
- //
- // Please note, that this function relies on the fact that the input geometry are triangles
- // and the tangent basis for each vertex thus is identical!
- //
-
- // Calculate the vectors from the current vertex to the two other vertices in the triangle
- VectorSubtract(v2, v1, v2v1);
- VectorSubtract(v3, v1, v3v1);
-
- // The equation presented in the article states that:
- // c2c1_T = V2.texcoord.x - V1.texcoord.x
- // c2c1_B = V2.texcoord.y - V1.texcoord.y
- // c3c1_T = V3.texcoord.x - V1.texcoord.x
- // c3c1_B = V3.texcoord.y - V1.texcoord.y
-
- // Calculate c2c1_T and c2c1_B
- c2c1_T = t2[0] - t1[0];
- c2c1_B = t2[1] - t2[1];
-
- // Calculate c3c1_T and c3c1_B
- c3c1_T = t3[0] - t1[0];
- c3c1_B = t3[1] - t1[1];
-
- denominator = c2c1_T * c3c1_B - c3c1_T * c2c1_B;
- //if(ROUNDOFF(fDenominator) == 0.0f)
- if(denominator == 0.0f)
- {
- // We won't risk a divide by zero, so set the tangent matrix to the identity matrix
- VectorSet(tangent, 1, 0, 0);
- VectorSet(bitangent, 0, 1, 0);
- VectorSet(normal, 0, 0, 1);
- }
- else
- {
- // Calculate the reciprocal value once and for all (to achieve speed)
- scale1 = 1.0f / denominator;
-
- // T and B are calculated just as the equation in the article states
- VectorSet(T, (c3c1_B * v2v1[0] - c2c1_B * v3v1[0]) * scale1,
- (c3c1_B * v2v1[1] - c2c1_B * v3v1[1]) * scale1,
- (c3c1_B * v2v1[2] - c2c1_B * v3v1[2]) * scale1);
-
- VectorSet(B, (-c3c1_T * v2v1[0] + c2c1_T * v3v1[0]) * scale1,
- (-c3c1_T * v2v1[1] + c2c1_T * v3v1[1]) * scale1,
- (-c3c1_T * v2v1[2] + c2c1_T * v3v1[2]) * scale1);
-
- // The normal N is calculated as the cross product between T and B
- CrossProduct(T, B, N);
-
-#if 0
- VectorCopy(T, tangent);
- VectorCopy(B, bitangent);
- VectorCopy(N, normal);
-#else
- // Calculate the reciprocal value once and for all (to achieve speed)
- scale2 = 1.0f / ((T[0] * B[1] * N[2] - T[2] * B[1] * N[0]) +
- (B[0] * N[1] * T[2] - B[2] * N[1] * T[0]) +
- (N[0] * T[1] * B[2] - N[2] * T[1] * B[0]));
-
- // Calculate the inverse if the TBN matrix using the formula described in the article.
- // We store the basis vectors directly in the provided TBN matrix: pvTBNMatrix
- CrossProduct(B, N, C); tangent[0] = C[0] * scale2;
- CrossProduct(N, T, C); tangent[1] = -C[0] * scale2;
- CrossProduct(T, B, C); tangent[2] = C[0] * scale2;
- VectorNormalize(tangent);
-
- CrossProduct(B, N, C); bitangent[0] = -C[1] * scale2;
- CrossProduct(N, T, C); bitangent[1] = C[1] * scale2;
- CrossProduct(T, B, C); bitangent[2] = -C[1] * scale2;
- VectorNormalize(bitangent);
-
- CrossProduct(B, N, C); normal[0] = C[2] * scale2;
- CrossProduct(N, T, C); normal[1] = -C[2] * scale2;
- CrossProduct(T, B, C); normal[2] = C[2] * scale2;
- VectorNormalize(normal);
-#endif
- }
-}
-
-
-#ifdef USE_VERT_TANGENT_SPACE
-qboolean R_CalcTangentVectors(srfVert_t * dv[3])
-{
- int i;
- float bb, s, t;
- vec3_t bary;
-
-
- /* calculate barycentric basis for the triangle */
- bb = (dv[1]->st[0] - dv[0]->st[0]) * (dv[2]->st[1] - dv[0]->st[1]) - (dv[2]->st[0] - dv[0]->st[0]) * (dv[1]->st[1] - dv[0]->st[1]);
- if(fabs(bb) < 0.00000001f)
- return qfalse;
-
- /* do each vertex */
- for(i = 0; i < 3; i++)
- {
- // calculate s tangent vector
- s = dv[i]->st[0] + 10.0f;
- t = dv[i]->st[1];
- bary[0] = ((dv[1]->st[0] - s) * (dv[2]->st[1] - t) - (dv[2]->st[0] - s) * (dv[1]->st[1] - t)) / bb;
- bary[1] = ((dv[2]->st[0] - s) * (dv[0]->st[1] - t) - (dv[0]->st[0] - s) * (dv[2]->st[1] - t)) / bb;
- bary[2] = ((dv[0]->st[0] - s) * (dv[1]->st[1] - t) - (dv[1]->st[0] - s) * (dv[0]->st[1] - t)) / bb;
-
- dv[i]->tangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
- dv[i]->tangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
- dv[i]->tangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
-
- VectorSubtract(dv[i]->tangent, dv[i]->xyz, dv[i]->tangent);
- VectorNormalize(dv[i]->tangent);
-
- // calculate t tangent vector
- s = dv[i]->st[0];
- t = dv[i]->st[1] + 10.0f;
- bary[0] = ((dv[1]->st[0] - s) * (dv[2]->st[1] - t) - (dv[2]->st[0] - s) * (dv[1]->st[1] - t)) / bb;
- bary[1] = ((dv[2]->st[0] - s) * (dv[0]->st[1] - t) - (dv[0]->st[0] - s) * (dv[2]->st[1] - t)) / bb;
- bary[2] = ((dv[0]->st[0] - s) * (dv[1]->st[1] - t) - (dv[1]->st[0] - s) * (dv[0]->st[1] - t)) / bb;
-
- dv[i]->bitangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
- dv[i]->bitangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
- dv[i]->bitangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
-
- VectorSubtract(dv[i]->bitangent, dv[i]->xyz, dv[i]->bitangent);
- VectorNormalize(dv[i]->bitangent);
-
- // debug code
- //% Sys_FPrintf( SYS_VRB, "%d S: (%f %f %f) T: (%f %f %f)\n", i,
- //% stv[ i ][ 0 ], stv[ i ][ 1 ], stv[ i ][ 2 ], ttv[ i ][ 0 ], ttv[ i ][ 1 ], ttv[ i ][ 2 ] );
- }
-
- return qtrue;
-}
-#endif
-
-
-/*
-=================
-R_FindSurfaceTriangleWithEdge
-Tr3B - recoded from Q2E
-=================
-*/
-static int R_FindSurfaceTriangleWithEdge(int numTriangles, srfTriangle_t * triangles, int start, int end, int ignore)
-{
- srfTriangle_t *tri;
- int count, match;
- int i;
-
- count = 0;
- match = -1;
-
- for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
- {
- if((tri->indexes[0] == start && tri->indexes[1] == end) ||
- (tri->indexes[1] == start && tri->indexes[2] == end) || (tri->indexes[2] == start && tri->indexes[0] == end))
- {
- if(i != ignore)
- {
- match = i;
- }
-
- count++;
- }
- else if((tri->indexes[1] == start && tri->indexes[0] == end) ||
- (tri->indexes[2] == start && tri->indexes[1] == end) || (tri->indexes[0] == start && tri->indexes[2] == end))
- {
- count++;
- }
- }
-
- // detect edges shared by three triangles and make them seams
- if(count > 2)
- {
- match = -1;
- }
-
- return match;
-}
-
-
-/*
-=================
-R_CalcSurfaceTriangleNeighbors
-Tr3B - recoded from Q2E
-=================
-*/
-void R_CalcSurfaceTriangleNeighbors(int numTriangles, srfTriangle_t * triangles)
-{
- int i;
- srfTriangle_t *tri;
-
- for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
- {
- tri->neighbors[0] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[1], tri->indexes[0], i);
- tri->neighbors[1] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[2], tri->indexes[1], i);
- tri->neighbors[2] = R_FindSurfaceTriangleWithEdge(numTriangles, triangles, tri->indexes[0], tri->indexes[2], i);
- }
-}
-
-/*
-=================
-R_CalcSurfaceTrianglePlanes
-=================
-*/
-void R_CalcSurfaceTrianglePlanes(int numTriangles, srfTriangle_t * triangles, srfVert_t * verts)
-{
- int i;
- srfTriangle_t *tri;
-
- for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
- {
- float *v1, *v2, *v3;
- vec3_t d1, d2;
-
- v1 = verts[tri->indexes[0]].xyz;
- v2 = verts[tri->indexes[1]].xyz;
- v3 = verts[tri->indexes[2]].xyz;
-
- VectorSubtract(v2, v1, d1);
- VectorSubtract(v3, v1, d2);
-
- CrossProduct(d2, d1, tri->plane);
- tri->plane[3] = DotProduct(tri->plane, v1);
- }
-}
-
-
-/*
-=================
-R_CullLocalBox
-
-Returns CULL_IN, CULL_CLIP, or CULL_OUT
-=================
-*/
-int R_CullLocalBox(vec3_t localBounds[2]) {
-#if 0
- int i, j;
- vec3_t transformed[8];
- float dists[8];
- vec3_t v;
- cplane_t *frust;
- int anyBack;
- int front, back;
-
- if ( r_nocull->integer ) {
- return CULL_CLIP;
- }
-
- // transform into world space
- for (i = 0 ; i < 8 ; i++) {
- v[0] = bounds[i&1][0];
- v[1] = bounds[(i>>1)&1][1];
- v[2] = bounds[(i>>2)&1][2];
-
- VectorCopy( tr.or.origin, transformed[i] );
- VectorMA( transformed[i], v[0], tr.or.axis[0], transformed[i] );
- VectorMA( transformed[i], v[1], tr.or.axis[1], transformed[i] );
- VectorMA( transformed[i], v[2], tr.or.axis[2], transformed[i] );
- }
-
- // check against frustum planes
- anyBack = 0;
- for (i = 0 ; i < 4 ; i++) {
- frust = &tr.viewParms.frustum[i];
-
- front = back = 0;
- for (j = 0 ; j < 8 ; j++) {
- dists[j] = DotProduct(transformed[j], frust->normal);
- if ( dists[j] > frust->dist ) {
- front = 1;
- if ( back ) {
- break; // a point is in front
- }
- } else {
- back = 1;
- }
- }
- if ( !front ) {
- // all points were behind one of the planes
- return CULL_OUT;
- }
- anyBack |= back;
- }
-
- if ( !anyBack ) {
- return CULL_IN; // completely inside frustum
- }
-
- return CULL_CLIP; // partially clipped
-#else
- int j;
- vec3_t transformed;
- vec3_t v;
- vec3_t worldBounds[2];
-
- if(r_nocull->integer)
- {
- return CULL_CLIP;
- }
-
- // transform into world space
- ClearBounds(worldBounds[0], worldBounds[1]);
-
- for(j = 0; j < 8; j++)
- {
- v[0] = localBounds[j & 1][0];
- v[1] = localBounds[(j >> 1) & 1][1];
- v[2] = localBounds[(j >> 2) & 1][2];
-
- R_LocalPointToWorld(v, transformed);
-
- AddPointToBounds(transformed, worldBounds[0], worldBounds[1]);
- }
-
- return R_CullBox(worldBounds);
-#endif
-}
-
-/*
-=================
-R_CullBox
-
-Returns CULL_IN, CULL_CLIP, or CULL_OUT
-=================
-*/
-int R_CullBox(vec3_t worldBounds[2]) {
- int i;
- cplane_t *frust;
- qboolean anyClip;
- int r, numPlanes;
-
- numPlanes = (tr.viewParms.flags & VPF_FARPLANEFRUSTUM) ? 5 : 4;
-
- // check against frustum planes
- anyClip = qfalse;
- for(i = 0; i < numPlanes; i++)
- {
- frust = &tr.viewParms.frustum[i];
-
- r = BoxOnPlaneSide(worldBounds[0], worldBounds[1], frust);
-
- if(r == 2)
- {
- // completely outside frustum
- return CULL_OUT;
- }
- if(r == 3)
- {
- anyClip = qtrue;
- }
- }
-
- if(!anyClip)
- {
- // completely inside frustum
- return CULL_IN;
- }
-
- // partially clipped
- return CULL_CLIP;
-}
-
-/*
-** R_CullLocalPointAndRadius
-*/
-int R_CullLocalPointAndRadius( const vec3_t pt, float radius )
-{
- vec3_t transformed;
-
- R_LocalPointToWorld( pt, transformed );
-
- return R_CullPointAndRadius( transformed, radius );
-}
-
-/*
-** R_CullPointAndRadius
-*/
-int R_CullPointAndRadiusEx( const vec3_t pt, float radius, const cplane_t* frustum, int numPlanes )
-{
- int i;
- float dist;
- const cplane_t *frust;
- qboolean mightBeClipped = qfalse;
-
- if ( r_nocull->integer ) {
- return CULL_CLIP;
- }
-
- // check against frustum planes
- for (i = 0 ; i < numPlanes ; i++)
- {
- frust = &frustum[i];
-
- dist = DotProduct( pt, frust->normal) - frust->dist;
- if ( dist < -radius )
- {
- return CULL_OUT;
- }
- else if ( dist <= radius )
- {
- mightBeClipped = qtrue;
- }
- }
-
- if ( mightBeClipped )
- {
- return CULL_CLIP;
- }
-
- return CULL_IN; // completely inside frustum
-}
-
-/*
-** R_CullPointAndRadius
-*/
-int R_CullPointAndRadius( const vec3_t pt, float radius )
-{
- return R_CullPointAndRadiusEx(pt, radius, tr.viewParms.frustum, (tr.viewParms.flags & VPF_FARPLANEFRUSTUM) ? 5 : 4);
-}
-
-/*
-=================
-R_LocalNormalToWorld
-
-=================
-*/
-void R_LocalNormalToWorld (const vec3_t local, vec3_t world) {
- world[0] = local[0] * tr.or.axis[0][0] + local[1] * tr.or.axis[1][0] + local[2] * tr.or.axis[2][0];
- world[1] = local[0] * tr.or.axis[0][1] + local[1] * tr.or.axis[1][1] + local[2] * tr.or.axis[2][1];
- world[2] = local[0] * tr.or.axis[0][2] + local[1] * tr.or.axis[1][2] + local[2] * tr.or.axis[2][2];
-}
-
-/*
-=================
-R_LocalPointToWorld
-
-=================
-*/
-void R_LocalPointToWorld (const vec3_t local, vec3_t world) {
- world[0] = local[0] * tr.or.axis[0][0] + local[1] * tr.or.axis[1][0] + local[2] * tr.or.axis[2][0] + tr.or.origin[0];
- world[1] = local[0] * tr.or.axis[0][1] + local[1] * tr.or.axis[1][1] + local[2] * tr.or.axis[2][1] + tr.or.origin[1];
- world[2] = local[0] * tr.or.axis[0][2] + local[1] * tr.or.axis[1][2] + local[2] * tr.or.axis[2][2] + tr.or.origin[2];
-}
-
-/*
-=================
-R_WorldToLocal
-
-=================
-*/
-void R_WorldToLocal (const vec3_t world, vec3_t local) {
- local[0] = DotProduct(world, tr.or.axis[0]);
- local[1] = DotProduct(world, tr.or.axis[1]);
- local[2] = DotProduct(world, tr.or.axis[2]);
-}
-
-/*
-==========================
-R_TransformModelToClip
-
-==========================
-*/
-void R_TransformModelToClip( const vec3_t src, const float *modelMatrix, const float *projectionMatrix,
- vec4_t eye, vec4_t dst ) {
- int i;
-
- for ( i = 0 ; i < 4 ; i++ ) {
- eye[i] =
- src[0] * modelMatrix[ i + 0 * 4 ] +
- src[1] * modelMatrix[ i + 1 * 4 ] +
- src[2] * modelMatrix[ i + 2 * 4 ] +
- 1 * modelMatrix[ i + 3 * 4 ];
- }
-
- for ( i = 0 ; i < 4 ; i++ ) {
- dst[i] =
- eye[0] * projectionMatrix[ i + 0 * 4 ] +
- eye[1] * projectionMatrix[ i + 1 * 4 ] +
- eye[2] * projectionMatrix[ i + 2 * 4 ] +
- eye[3] * projectionMatrix[ i + 3 * 4 ];
- }
-}
-
-/*
-==========================
-R_TransformClipToWindow
-
-==========================
-*/
-void R_TransformClipToWindow( const vec4_t clip, const viewParms_t *view, vec4_t normalized, vec4_t window ) {
- normalized[0] = clip[0] / clip[3];
- normalized[1] = clip[1] / clip[3];
- normalized[2] = ( clip[2] + clip[3] ) / ( 2 * clip[3] );
-
- window[0] = 0.5f * ( 1.0f + normalized[0] ) * view->viewportWidth;
- window[1] = 0.5f * ( 1.0f + normalized[1] ) * view->viewportHeight;
- window[2] = normalized[2];
-
- window[0] = (int) ( window[0] + 0.5 );
- window[1] = (int) ( window[1] + 0.5 );
-}
-
-
-/*
-==========================
-myGlMultMatrix
-
-==========================
-*/
-void myGlMultMatrix( const float *a, const float *b, float *out ) {
- int i, j;
-
- for ( i = 0 ; i < 4 ; i++ ) {
- for ( j = 0 ; j < 4 ; j++ ) {
- out[ i * 4 + j ] =
- a [ i * 4 + 0 ] * b [ 0 * 4 + j ]
- + a [ i * 4 + 1 ] * b [ 1 * 4 + j ]
- + a [ i * 4 + 2 ] * b [ 2 * 4 + j ]
- + a [ i * 4 + 3 ] * b [ 3 * 4 + j ];
- }
- }
-}
-
-/*
-=================
-R_RotateForEntity
-
-Generates an orientation for an entity and viewParms
-Does NOT produce any GL calls
-Called by both the front end and the back end
-=================
-*/
-void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms,
- orientationr_t *or ) {
- float glMatrix[16];
- vec3_t delta;
- float axisLength;
-
- if ( ent->e.reType != RT_MODEL ) {
- *or = viewParms->world;
- return;
- }
-
- VectorCopy( ent->e.origin, or->origin );
-
- VectorCopy( ent->e.axis[0], or->axis[0] );
- VectorCopy( ent->e.axis[1], or->axis[1] );
- VectorCopy( ent->e.axis[2], or->axis[2] );
-
- glMatrix[0] = or->axis[0][0];
- glMatrix[4] = or->axis[1][0];
- glMatrix[8] = or->axis[2][0];
- glMatrix[12] = or->origin[0];
-
- glMatrix[1] = or->axis[0][1];
- glMatrix[5] = or->axis[1][1];
- glMatrix[9] = or->axis[2][1];
- glMatrix[13] = or->origin[1];
-
- glMatrix[2] = or->axis[0][2];
- glMatrix[6] = or->axis[1][2];
- glMatrix[10] = or->axis[2][2];
- glMatrix[14] = or->origin[2];
-
- glMatrix[3] = 0;
- glMatrix[7] = 0;
- glMatrix[11] = 0;
- glMatrix[15] = 1;
-
- Matrix16Copy(glMatrix, or->transformMatrix);
- myGlMultMatrix( glMatrix, viewParms->world.modelMatrix, or->modelMatrix );
-
- // calculate the viewer origin in the model's space
- // needed for fog, specular, and environment mapping
- VectorSubtract( viewParms->or.origin, or->origin, delta );
-
- // compensate for scale in the axes if necessary
- if ( ent->e.nonNormalizedAxes ) {
- axisLength = VectorLength( ent->e.axis[0] );
- if ( !axisLength ) {
- axisLength = 0;
- } else {
- axisLength = 1.0f / axisLength;
- }
- } else {
- axisLength = 1.0f;
- }
-
- or->viewOrigin[0] = DotProduct( delta, or->axis[0] ) * axisLength;
- or->viewOrigin[1] = DotProduct( delta, or->axis[1] ) * axisLength;
- or->viewOrigin[2] = DotProduct( delta, or->axis[2] ) * axisLength;
-}
-
-/*
-=================
-R_RotateForViewer
-
-Sets up the modelview matrix for a given viewParm
-=================
-*/
-void R_RotateForViewer (void)
-{
- float viewerMatrix[16];
- vec3_t origin;
-
- Com_Memset (&tr.or, 0, sizeof(tr.or));
- tr.or.axis[0][0] = 1;
- tr.or.axis[1][1] = 1;
- tr.or.axis[2][2] = 1;
- VectorCopy (tr.viewParms.or.origin, tr.or.viewOrigin);
-
- // transform by the camera placement
- VectorCopy( tr.viewParms.or.origin, origin );
-
- viewerMatrix[0] = tr.viewParms.or.axis[0][0];
- viewerMatrix[4] = tr.viewParms.or.axis[0][1];
- viewerMatrix[8] = tr.viewParms.or.axis[0][2];
- viewerMatrix[12] = -origin[0] * viewerMatrix[0] + -origin[1] * viewerMatrix[4] + -origin[2] * viewerMatrix[8];
-
- viewerMatrix[1] = tr.viewParms.or.axis[1][0];
- viewerMatrix[5] = tr.viewParms.or.axis[1][1];
- viewerMatrix[9] = tr.viewParms.or.axis[1][2];
- viewerMatrix[13] = -origin[0] * viewerMatrix[1] + -origin[1] * viewerMatrix[5] + -origin[2] * viewerMatrix[9];
-
- viewerMatrix[2] = tr.viewParms.or.axis[2][0];
- viewerMatrix[6] = tr.viewParms.or.axis[2][1];
- viewerMatrix[10] = tr.viewParms.or.axis[2][2];
- viewerMatrix[14] = -origin[0] * viewerMatrix[2] + -origin[1] * viewerMatrix[6] + -origin[2] * viewerMatrix[10];
-
- viewerMatrix[3] = 0;
- viewerMatrix[7] = 0;
- viewerMatrix[11] = 0;
- viewerMatrix[15] = 1;
-
- // convert from our coordinate system (looking down X)
- // to OpenGL's coordinate system (looking down -Z)
- myGlMultMatrix( viewerMatrix, s_flipMatrix, tr.or.modelMatrix );
-
- tr.viewParms.world = tr.or;
-
-}
-
-/*
-** SetFarClip
-*/
-static void R_SetFarClip( void )
-{
- float farthestCornerDistance = 0;
- int i;
-
- // if not rendering the world (icons, menus, etc)
- // set a 2k far clip plane
- if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
- tr.viewParms.zFar = 2048;
- return;
- }
-
- //
- // set far clipping planes dynamically
- //
- farthestCornerDistance = 0;
- for ( i = 0; i < 8; i++ )
- {
- vec3_t v;
- vec3_t vecTo;
- float distance;
-
- if ( i & 1 )
- {
- v[0] = tr.viewParms.visBounds[0][0];
- }
- else
- {
- v[0] = tr.viewParms.visBounds[1][0];
- }
-
- if ( i & 2 )
- {
- v[1] = tr.viewParms.visBounds[0][1];
- }
- else
- {
- v[1] = tr.viewParms.visBounds[1][1];
- }
-
- if ( i & 4 )
- {
- v[2] = tr.viewParms.visBounds[0][2];
- }
- else
- {
- v[2] = tr.viewParms.visBounds[1][2];
- }
-
- VectorSubtract( v, tr.viewParms.or.origin, vecTo );
-
- distance = vecTo[0] * vecTo[0] + vecTo[1] * vecTo[1] + vecTo[2] * vecTo[2];
-
- if ( distance > farthestCornerDistance )
- {
- farthestCornerDistance = distance;
- }
- }
- tr.viewParms.zFar = sqrt( farthestCornerDistance );
-}
-
-/*
-=================
-R_SetupFrustum
-
-Set up the culling frustum planes for the current view using the results we got from computing the first two rows of
-the projection matrix.
-=================
-*/
-void R_SetupFrustum (viewParms_t *dest, float xmin, float xmax, float ymax, float zProj, float zFar, float stereoSep)
-{
- vec3_t ofsorigin;
- float oppleg, adjleg, length;
- int i;
-
- if(stereoSep == 0 && xmin == -xmax)
- {
- // symmetric case can be simplified
- VectorCopy(dest->or.origin, ofsorigin);
-
- length = sqrt(xmax * xmax + zProj * zProj);
- oppleg = xmax / length;
- adjleg = zProj / length;
-
- VectorScale(dest->or.axis[0], oppleg, dest->frustum[0].normal);
- VectorMA(dest->frustum[0].normal, adjleg, dest->or.axis[1], dest->frustum[0].normal);
-
- VectorScale(dest->or.axis[0], oppleg, dest->frustum[1].normal);
- VectorMA(dest->frustum[1].normal, -adjleg, dest->or.axis[1], dest->frustum[1].normal);
- }
- else
- {
- // In stereo rendering, due to the modification of the projection matrix, dest->or.origin is not the
- // actual origin that we're rendering so offset the tip of the view pyramid.
- VectorMA(dest->or.origin, stereoSep, dest->or.axis[1], ofsorigin);
-
- oppleg = xmax + stereoSep;
- length = sqrt(oppleg * oppleg + zProj * zProj);
- VectorScale(dest->or.axis[0], oppleg / length, dest->frustum[0].normal);
- VectorMA(dest->frustum[0].normal, zProj / length, dest->or.axis[1], dest->frustum[0].normal);
-
- oppleg = xmin + stereoSep;
- length = sqrt(oppleg * oppleg + zProj * zProj);
- VectorScale(dest->or.axis[0], -oppleg / length, dest->frustum[1].normal);
- VectorMA(dest->frustum[1].normal, -zProj / length, dest->or.axis[1], dest->frustum[1].normal);
- }
-
- length = sqrt(ymax * ymax + zProj * zProj);
- oppleg = ymax / length;
- adjleg = zProj / length;
-
- VectorScale(dest->or.axis[0], oppleg, dest->frustum[2].normal);
- VectorMA(dest->frustum[2].normal, adjleg, dest->or.axis[2], dest->frustum[2].normal);
-
- VectorScale(dest->or.axis[0], oppleg, dest->frustum[3].normal);
- VectorMA(dest->frustum[3].normal, -adjleg, dest->or.axis[2], dest->frustum[3].normal);
-
- for (i=0 ; i<4 ; i++) {
- dest->frustum[i].type = PLANE_NON_AXIAL;
- dest->frustum[i].dist = DotProduct (ofsorigin, dest->frustum[i].normal);
- SetPlaneSignbits( &dest->frustum[i] );
- }
-
- if (zFar != 0.0f)
- {
- vec3_t farpoint;
-
- VectorMA(ofsorigin, zFar, dest->or.axis[0], farpoint);
- VectorScale(dest->or.axis[0], -1.0f, dest->frustum[4].normal);
-
- dest->frustum[4].type = PLANE_NON_AXIAL;
- dest->frustum[4].dist = DotProduct (farpoint, dest->frustum[4].normal);
- SetPlaneSignbits( &dest->frustum[4] );
- dest->flags |= VPF_FARPLANEFRUSTUM;
- }
-}
-
-/*
-===============
-R_SetupProjection
-===============
-*/
-void R_SetupProjection(viewParms_t *dest, float zProj, float zFar, qboolean computeFrustum)
-{
- float xmin, xmax, ymin, ymax;
- float width, height, stereoSep = r_stereoSeparation->value;
-
- /*
- * offset the view origin of the viewer for stereo rendering
- * by setting the projection matrix appropriately.
- */
-
- if(stereoSep != 0)
- {
- if(dest->stereoFrame == STEREO_LEFT)
- stereoSep = zProj / stereoSep;
- else if(dest->stereoFrame == STEREO_RIGHT)
- stereoSep = zProj / -stereoSep;
- else
- stereoSep = 0;
- }
-
- ymax = zProj * tan(dest->fovY * M_PI / 360.0f);
- ymin = -ymax;
-
- xmax = zProj * tan(dest->fovX * M_PI / 360.0f);
- xmin = -xmax;
-
- width = xmax - xmin;
- height = ymax - ymin;
-
- dest->projectionMatrix[0] = 2 * zProj / width;
- dest->projectionMatrix[4] = 0;
- dest->projectionMatrix[8] = (xmax + xmin + 2 * stereoSep) / width;
- dest->projectionMatrix[12] = 2 * zProj * stereoSep / width;
-
- dest->projectionMatrix[1] = 0;
- dest->projectionMatrix[5] = 2 * zProj / height;
- dest->projectionMatrix[9] = ( ymax + ymin ) / height; // normally 0
- dest->projectionMatrix[13] = 0;
-
- dest->projectionMatrix[3] = 0;
- dest->projectionMatrix[7] = 0;
- dest->projectionMatrix[11] = -1;
- dest->projectionMatrix[15] = 0;
-
- // Now that we have all the data for the projection matrix we can also setup the view frustum.
- if(computeFrustum)
- R_SetupFrustum(dest, xmin, xmax, ymax, zProj, zFar, stereoSep);
-}
-
-/*
-===============
-R_SetupProjectionZ
-
-Sets the z-component transformation part in the projection matrix
-===============
-*/
-void R_SetupProjectionZ(viewParms_t *dest)
-{
- float zNear, zFar, depth;
-
- zNear = r_znear->value;
- zFar = dest->zFar;
-
- depth = zFar - zNear;
-
- dest->projectionMatrix[2] = 0;
- dest->projectionMatrix[6] = 0;
- dest->projectionMatrix[10] = -( zFar + zNear ) / depth;
- dest->projectionMatrix[14] = -2 * zFar * zNear / depth;
-
- if (dest->isPortal)
- {
- float plane[4];
- float plane2[4];
- vec4_t q, c;
-
- // transform portal plane into camera space
- plane[0] = dest->portalPlane.normal[0];
- plane[1] = dest->portalPlane.normal[1];
- plane[2] = dest->portalPlane.normal[2];
- plane[3] = dest->portalPlane.dist;
-
- plane2[0] = -DotProduct (dest->or.axis[1], plane);
- plane2[1] = DotProduct (dest->or.axis[2], plane);
- plane2[2] = -DotProduct (dest->or.axis[0], plane);
- plane2[3] = DotProduct (plane, dest->or.origin) - plane[3];
-
- // Lengyel, Eric. "Modifying the Projection Matrix to Perform Oblique Near-plane Clipping".
- // Terathon Software 3D Graphics Library, 2004. http://www.terathon.com/code/oblique.html
- q[0] = (SGN(plane2[0]) + dest->projectionMatrix[8]) / dest->projectionMatrix[0];
- q[1] = (SGN(plane2[1]) + dest->projectionMatrix[9]) / dest->projectionMatrix[5];
- q[2] = -1.0f;
- q[3] = (1.0f + dest->projectionMatrix[10]) / dest->projectionMatrix[14];
-
- VectorScale4(plane2, 2.0f / DotProduct4(plane2, q), c);
-
- dest->projectionMatrix[2] = c[0];
- dest->projectionMatrix[6] = c[1];
- dest->projectionMatrix[10] = c[2] + 1.0f;
- dest->projectionMatrix[14] = c[3];
-
- }
-
-}
-
-/*
-===============
-R_SetupProjectionOrtho
-===============
-*/
-void R_SetupProjectionOrtho(viewParms_t *dest, vec3_t viewBounds[2])
-{
- float xmin, xmax, ymin, ymax, znear, zfar;
- //viewParms_t *dest = &tr.viewParms;
- int i;
- vec3_t pop;
-
- // Quake3: Projection:
- //
- // Z X Y Z
- // | / | /
- // |/ |/
- // Y--+ +--X
-
- xmin = viewBounds[0][1];
- xmax = viewBounds[1][1];
- ymin = -viewBounds[1][2];
- ymax = -viewBounds[0][2];
- znear = viewBounds[0][0];
- zfar = viewBounds[1][0];
-
- dest->projectionMatrix[0] = 2 / (xmax - xmin);
- dest->projectionMatrix[4] = 0;
- dest->projectionMatrix[8] = 0;
- dest->projectionMatrix[12] = (xmax + xmin) / (xmax - xmin);
-
- dest->projectionMatrix[1] = 0;
- dest->projectionMatrix[5] = 2 / (ymax - ymin);
- dest->projectionMatrix[9] = 0;
- dest->projectionMatrix[13] = (ymax + ymin) / (ymax - ymin);
-
- dest->projectionMatrix[2] = 0;
- dest->projectionMatrix[6] = 0;
- dest->projectionMatrix[10] = -2 / (zfar - znear);
- dest->projectionMatrix[14] = -(zfar + znear) / (zfar - znear);
-
- dest->projectionMatrix[3] = 0;
- dest->projectionMatrix[7] = 0;
- dest->projectionMatrix[11] = 0;
- dest->projectionMatrix[15] = 1;
-
- VectorScale(dest->or.axis[1], 1.0f, dest->frustum[0].normal);
- VectorMA(dest->or.origin, viewBounds[0][1], dest->frustum[0].normal, pop);
- dest->frustum[0].dist = DotProduct(pop, dest->frustum[0].normal);
-
- VectorScale(dest->or.axis[1], -1.0f, dest->frustum[1].normal);
- VectorMA(dest->or.origin, -viewBounds[1][1], dest->frustum[1].normal, pop);
- dest->frustum[1].dist = DotProduct(pop, dest->frustum[1].normal);
-
- VectorScale(dest->or.axis[2], 1.0f, dest->frustum[2].normal);
- VectorMA(dest->or.origin, viewBounds[0][2], dest->frustum[2].normal, pop);
- dest->frustum[2].dist = DotProduct(pop, dest->frustum[2].normal);
-
- VectorScale(dest->or.axis[2], -1.0f, dest->frustum[3].normal);
- VectorMA(dest->or.origin, -viewBounds[1][2], dest->frustum[3].normal, pop);
- dest->frustum[3].dist = DotProduct(pop, dest->frustum[3].normal);
-
- VectorScale(dest->or.axis[0], -1.0f, dest->frustum[4].normal);
- VectorMA(dest->or.origin, -viewBounds[1][0], dest->frustum[4].normal, pop);
- dest->frustum[4].dist = DotProduct(pop, dest->frustum[4].normal);
-
- for (i = 0; i < 5; i++)
- {
- dest->frustum[i].type = PLANE_NON_AXIAL;
- SetPlaneSignbits (&dest->frustum[i]);
- }
-
- dest->flags |= VPF_FARPLANEFRUSTUM;
-}
-
-/*
-=================
-R_MirrorPoint
-=================
-*/
-void R_MirrorPoint (vec3_t in, orientation_t *surface, orientation_t *camera, vec3_t out) {
- int i;
- vec3_t local;
- vec3_t transformed;
- float d;
-
- VectorSubtract( in, surface->origin, local );
-
- VectorClear( transformed );
- for ( i = 0 ; i < 3 ; i++ ) {
- d = DotProduct(local, surface->axis[i]);
- VectorMA( transformed, d, camera->axis[i], transformed );
- }
-
- VectorAdd( transformed, camera->origin, out );
-}
-
-void R_MirrorVector (vec3_t in, orientation_t *surface, orientation_t *camera, vec3_t out) {
- int i;
- float d;
-
- VectorClear( out );
- for ( i = 0 ; i < 3 ; i++ ) {
- d = DotProduct(in, surface->axis[i]);
- VectorMA( out, d, camera->axis[i], out );
- }
-}
-
-
-/*
-=============
-R_PlaneForSurface
-=============
-*/
-void R_PlaneForSurface (surfaceType_t *surfType, cplane_t *plane) {
- srfTriangles_t *tri;
- srfPoly_t *poly;
- srfVert_t *v1, *v2, *v3;
- vec4_t plane4;
-
- if (!surfType) {
- Com_Memset (plane, 0, sizeof(*plane));
- plane->normal[0] = 1;
- return;
- }
- switch (*surfType) {
- case SF_FACE:
- *plane = ((srfSurfaceFace_t *)surfType)->plane;
- return;
- case SF_TRIANGLES:
- tri = (srfTriangles_t *)surfType;
- v1 = tri->verts + tri->triangles[0].indexes[0];
- v2 = tri->verts + tri->triangles[0].indexes[1];
- v3 = tri->verts + tri->triangles[0].indexes[2];
- PlaneFromPoints( plane4, v1->xyz, v2->xyz, v3->xyz );
- VectorCopy( plane4, plane->normal );
- plane->dist = plane4[3];
- return;
- case SF_POLY:
- poly = (srfPoly_t *)surfType;
- PlaneFromPoints( plane4, poly->verts[0].xyz, poly->verts[1].xyz, poly->verts[2].xyz );
- VectorCopy( plane4, plane->normal );
- plane->dist = plane4[3];
- return;
- default:
- Com_Memset (plane, 0, sizeof(*plane));
- plane->normal[0] = 1;
- return;
- }
-}
-
-/*
-=================
-R_GetPortalOrientation
-
-entityNum is the entity that the portal surface is a part of, which may
-be moving and rotating.
-
-Returns qtrue if it should be mirrored
-=================
-*/
-qboolean R_GetPortalOrientations( drawSurf_t *drawSurf, int entityNum,
- orientation_t *surface, orientation_t *camera,
- vec3_t pvsOrigin, qboolean *mirror ) {
- int i;
- cplane_t originalPlane, plane;
- trRefEntity_t *e;
- float d;
- vec3_t transformed;
-
- // create plane axis for the portal we are seeing
- R_PlaneForSurface( drawSurf->surface, &originalPlane );
-
- // rotate the plane if necessary
- if ( entityNum != REFENTITYNUM_WORLD ) {
- tr.currentEntityNum = entityNum;
- tr.currentEntity = &tr.refdef.entities[entityNum];
-
- // get the orientation of the entity
- R_RotateForEntity( tr.currentEntity, &tr.viewParms, &tr.or );
-
- // rotate the plane, but keep the non-rotated version for matching
- // against the portalSurface entities
- R_LocalNormalToWorld( originalPlane.normal, plane.normal );
- plane.dist = originalPlane.dist + DotProduct( plane.normal, tr.or.origin );
-
- // translate the original plane
- originalPlane.dist = originalPlane.dist + DotProduct( originalPlane.normal, tr.or.origin );
- } else {
- plane = originalPlane;
- }
-
- VectorCopy( plane.normal, surface->axis[0] );
- PerpendicularVector( surface->axis[1], surface->axis[0] );
- CrossProduct( surface->axis[0], surface->axis[1], surface->axis[2] );
-
- // locate the portal entity closest to this plane.
- // origin will be the origin of the portal, origin2 will be
- // the origin of the camera
- for ( i = 0 ; i < tr.refdef.num_entities ; i++ ) {
- e = &tr.refdef.entities[i];
- if ( e->e.reType != RT_PORTALSURFACE ) {
- continue;
- }
-
- d = DotProduct( e->e.origin, originalPlane.normal ) - originalPlane.dist;
- if ( d > 64 || d < -64) {
- continue;
- }
-
- // get the pvsOrigin from the entity
- VectorCopy( e->e.oldorigin, pvsOrigin );
-
- // if the entity is just a mirror, don't use as a camera point
- if ( e->e.oldorigin[0] == e->e.origin[0] &&
- e->e.oldorigin[1] == e->e.origin[1] &&
- e->e.oldorigin[2] == e->e.origin[2] ) {
- VectorScale( plane.normal, plane.dist, surface->origin );
- VectorCopy( surface->origin, camera->origin );
- VectorSubtract( vec3_origin, surface->axis[0], camera->axis[0] );
- VectorCopy( surface->axis[1], camera->axis[1] );
- VectorCopy( surface->axis[2], camera->axis[2] );
-
- *mirror = qtrue;
- return qtrue;
- }
-
- // project the origin onto the surface plane to get
- // an origin point we can rotate around
- d = DotProduct( e->e.origin, plane.normal ) - plane.dist;
- VectorMA( e->e.origin, -d, surface->axis[0], surface->origin );
-
- // now get the camera origin and orientation
- VectorCopy( e->e.oldorigin, camera->origin );
- AxisCopy( e->e.axis, camera->axis );
- VectorSubtract( vec3_origin, camera->axis[0], camera->axis[0] );
- VectorSubtract( vec3_origin, camera->axis[1], camera->axis[1] );
-
- // optionally rotate
- if ( e->e.oldframe ) {
- // if a speed is specified
- if ( e->e.frame ) {
- // continuous rotate
- d = (tr.refdef.time/1000.0f) * e->e.frame;
- VectorCopy( camera->axis[1], transformed );
- RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d );
- CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] );
- } else {
- // bobbing rotate, with skinNum being the rotation offset
- d = sin( tr.refdef.time * 0.003f );
- d = e->e.skinNum + d * 4;
- VectorCopy( camera->axis[1], transformed );
- RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d );
- CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] );
- }
- }
- else if ( e->e.skinNum ) {
- d = e->e.skinNum;
- VectorCopy( camera->axis[1], transformed );
- RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d );
- CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] );
- }
- *mirror = qfalse;
- return qtrue;
- }
-
- // if we didn't locate a portal entity, don't render anything.
- // We don't want to just treat it as a mirror, because without a
- // portal entity the server won't have communicated a proper entity set
- // in the snapshot
-
- // unfortunately, with local movement prediction it is easily possible
- // to see a surface before the server has communicated the matching
- // portal surface entity, so we don't want to print anything here...
-
- //ri.Printf( PRINT_ALL, "Portal surface without a portal entity\n" );
-
- return qfalse;
-}
-
-static qboolean IsMirror( const drawSurf_t *drawSurf, int entityNum )
-{
- int i;
- cplane_t originalPlane, plane;
- trRefEntity_t *e;
- float d;
-
- // create plane axis for the portal we are seeing
- R_PlaneForSurface( drawSurf->surface, &originalPlane );
-
- // rotate the plane if necessary
- if ( entityNum != REFENTITYNUM_WORLD )
- {
- tr.currentEntityNum = entityNum;
- tr.currentEntity = &tr.refdef.entities[entityNum];
-
- // get the orientation of the entity
- R_RotateForEntity( tr.currentEntity, &tr.viewParms, &tr.or );
-
- // rotate the plane, but keep the non-rotated version for matching
- // against the portalSurface entities
- R_LocalNormalToWorld( originalPlane.normal, plane.normal );
- plane.dist = originalPlane.dist + DotProduct( plane.normal, tr.or.origin );
-
- // translate the original plane
- originalPlane.dist = originalPlane.dist + DotProduct( originalPlane.normal, tr.or.origin );
- }
- else
- {
- plane = originalPlane;
- }
-
- // locate the portal entity closest to this plane.
- // origin will be the origin of the portal, origin2 will be
- // the origin of the camera
- for ( i = 0 ; i < tr.refdef.num_entities ; i++ )
- {
- e = &tr.refdef.entities[i];
- if ( e->e.reType != RT_PORTALSURFACE ) {
- continue;
- }
-
- d = DotProduct( e->e.origin, originalPlane.normal ) - originalPlane.dist;
- if ( d > 64 || d < -64) {
- continue;
- }
-
- // if the entity is just a mirror, don't use as a camera point
- if ( e->e.oldorigin[0] == e->e.origin[0] &&
- e->e.oldorigin[1] == e->e.origin[1] &&
- e->e.oldorigin[2] == e->e.origin[2] )
- {
- return qtrue;
- }
-
- return qfalse;
- }
- return qfalse;
-}
-
-/*
-** SurfIsOffscreen
-**
-** Determines if a surface is completely offscreen.
-*/
-static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128] ) {
- float shortest = 100000000;
- int entityNum;
- int numTriangles;
- shader_t *shader;
- int fogNum;
- int dlighted;
- int pshadowed;
- vec4_t clip, eye;
- int i;
- unsigned int pointOr = 0;
- unsigned int pointAnd = (unsigned int)~0;
-
- R_RotateForViewer();
-
- R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed );
- RB_BeginSurface( shader, fogNum );
- rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
-
- assert( tess.numVertexes < 128 );
-
- for ( i = 0; i < tess.numVertexes; i++ )
- {
- int j;
- unsigned int pointFlags = 0;
-
- R_TransformModelToClip( tess.xyz[i], tr.or.modelMatrix, tr.viewParms.projectionMatrix, eye, clip );
-
- for ( j = 0; j < 3; j++ )
- {
- if ( clip[j] >= clip[3] )
- {
- pointFlags |= (1 << (j*2));
- }
- else if ( clip[j] <= -clip[3] )
- {
- pointFlags |= ( 1 << (j*2+1));
- }
- }
- pointAnd &= pointFlags;
- pointOr |= pointFlags;
- }
-
- // trivially reject
- if ( pointAnd )
- {
- return qtrue;
- }
-
- // determine if this surface is backfaced and also determine the distance
- // to the nearest vertex so we can cull based on portal range. Culling
- // based on vertex distance isn't 100% correct (we should be checking for
- // range to the surface), but it's good enough for the types of portals
- // we have in the game right now.
- numTriangles = tess.numIndexes / 3;
-
- for ( i = 0; i < tess.numIndexes; i += 3 )
- {
- vec3_t normal;
- float len;
-
- VectorSubtract( tess.xyz[tess.indexes[i]], tr.viewParms.or.origin, normal );
-
- len = VectorLengthSquared( normal ); // lose the sqrt
- if ( len < shortest )
- {
- shortest = len;
- }
-
- if ( DotProduct( normal, tess.normal[tess.indexes[i]] ) >= 0 )
- {
- numTriangles--;
- }
- }
- if ( !numTriangles )
- {
- return qtrue;
- }
-
- // mirrors can early out at this point, since we don't do a fade over distance
- // with them (although we could)
- if ( IsMirror( drawSurf, entityNum ) )
- {
- return qfalse;
- }
-
- if ( shortest > (tess.shader->portalRange*tess.shader->portalRange) )
- {
- return qtrue;
- }
-
- return qfalse;
-}
-
-/*
-========================
-R_MirrorViewBySurface
-
-Returns qtrue if another view has been rendered
-========================
-*/
-qboolean R_MirrorViewBySurface (drawSurf_t *drawSurf, int entityNum) {
- vec4_t clipDest[128];
- viewParms_t newParms;
- viewParms_t oldParms;
- orientation_t surface, camera;
-
- // don't recursively mirror
- if (tr.viewParms.isPortal) {
- ri.Printf( PRINT_DEVELOPER, "WARNING: recursive mirror/portal found\n" );
- return qfalse;
- }
-
- if ( r_noportals->integer || (r_fastsky->integer == 1) ) {
- return qfalse;
- }
-
- // trivially reject portal/mirror
- if ( SurfIsOffscreen( drawSurf, clipDest ) ) {
- return qfalse;
- }
-
- // save old viewParms so we can return to it after the mirror view
- oldParms = tr.viewParms;
-
- newParms = tr.viewParms;
- newParms.isPortal = qtrue;
- newParms.zFar = 0.0f;
- newParms.flags &= ~VPF_FARPLANEFRUSTUM;
- if ( !R_GetPortalOrientations( drawSurf, entityNum, &surface, &camera,
- newParms.pvsOrigin, &newParms.isMirror ) ) {
- return qfalse; // bad portal, no portalentity
- }
-
- R_MirrorPoint (oldParms.or.origin, &surface, &camera, newParms.or.origin );
-
- VectorSubtract( vec3_origin, camera.axis[0], newParms.portalPlane.normal );
- newParms.portalPlane.dist = DotProduct( camera.origin, newParms.portalPlane.normal );
-
- R_MirrorVector (oldParms.or.axis[0], &surface, &camera, newParms.or.axis[0]);
- R_MirrorVector (oldParms.or.axis[1], &surface, &camera, newParms.or.axis[1]);
- R_MirrorVector (oldParms.or.axis[2], &surface, &camera, newParms.or.axis[2]);
-
- // OPTIMIZE: restrict the viewport on the mirrored view
-
- // render the mirror view
- R_RenderView (&newParms);
-
- tr.viewParms = oldParms;
-
- return qtrue;
-}
-
-/*
-=================
-R_SpriteFogNum
-
-See if a sprite is inside a fog volume
-=================
-*/
-int R_SpriteFogNum( trRefEntity_t *ent ) {
- int i, j;
- fog_t *fog;
-
- if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
- return 0;
- }
-
- for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
- fog = &tr.world->fogs[i];
- for ( j = 0 ; j < 3 ; j++ ) {
- if ( ent->e.origin[j] - ent->e.radius >= fog->bounds[1][j] ) {
- break;
- }
- if ( ent->e.origin[j] + ent->e.radius <= fog->bounds[0][j] ) {
- break;
- }
- }
- if ( j == 3 ) {
- return i;
- }
- }
-
- return 0;
-}
-
-/*
-==========================================================================================
-
-DRAWSURF SORTING
-
-==========================================================================================
-*/
-
-/*
-===============
-R_Radix
-===============
-*/
-static ID_INLINE void R_Radix( int byte, int size, drawSurf_t *source, drawSurf_t *dest )
-{
- int count[ 256 ] = { 0 };
- int index[ 256 ];
- int i;
- unsigned char *sortKey = NULL;
- unsigned char *end = NULL;
-
- sortKey = ( (unsigned char *)&source[ 0 ].sort ) + byte;
- end = sortKey + ( size * sizeof( drawSurf_t ) );
- for( ; sortKey < end; sortKey += sizeof( drawSurf_t ) )
- ++count[ *sortKey ];
-
- index[ 0 ] = 0;
-
- for( i = 1; i < 256; ++i )
- index[ i ] = index[ i - 1 ] + count[ i - 1 ];
-
- sortKey = ( (unsigned char *)&source[ 0 ].sort ) + byte;
- for( i = 0; i < size; ++i, sortKey += sizeof( drawSurf_t ) )
- dest[ index[ *sortKey ]++ ] = source[ i ];
-}
-
-/*
-===============
-R_RadixSort
-
-Radix sort with 4 byte size buckets
-===============
-*/
-static void R_RadixSort( drawSurf_t *source, int size )
-{
- static drawSurf_t scratch[ MAX_DRAWSURFS ];
-#ifdef Q3_LITTLE_ENDIAN
- R_Radix( 0, size, source, scratch );
- R_Radix( 1, size, scratch, source );
- R_Radix( 2, size, source, scratch );
- R_Radix( 3, size, scratch, source );
-#else
- R_Radix( 3, size, source, scratch );
- R_Radix( 2, size, scratch, source );
- R_Radix( 1, size, source, scratch );
- R_Radix( 0, size, scratch, source );
-#endif //Q3_LITTLE_ENDIAN
-}
-
-//==========================================================================================
-
-/*
-=================
-R_AddDrawSurf
-=================
-*/
-void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader,
- int fogIndex, int dlightMap, int pshadowMap ) {
- int index;
-
- // instead of checking for overflow, we just mask the index
- // so it wraps around
- index = tr.refdef.numDrawSurfs & DRAWSURF_MASK;
- // the sort data is packed into a single 32 bit value so it can be
- // compared quickly during the qsorting process
- tr.refdef.drawSurfs[index].sort = (shader->sortedIndex << QSORT_SHADERNUM_SHIFT)
- | tr.shiftedEntityNum | ( fogIndex << QSORT_FOGNUM_SHIFT )
- | ((int)pshadowMap << QSORT_PSHADOW_SHIFT) | (int)dlightMap;
- tr.refdef.drawSurfs[index].surface = surface;
- tr.refdef.numDrawSurfs++;
-}
-
-/*
-=================
-R_DecomposeSort
-=================
-*/
-void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader,
- int *fogNum, int *dlightMap, int *pshadowMap ) {
- *fogNum = ( sort >> QSORT_FOGNUM_SHIFT ) & 31;
- *shader = tr.sortedShaders[ ( sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1) ];
- *entityNum = ( sort >> QSORT_REFENTITYNUM_SHIFT ) & REFENTITYNUM_MASK;
- *pshadowMap = (sort >> QSORT_PSHADOW_SHIFT ) & 1;
- *dlightMap = sort & 1;
-}
-
-/*
-=================
-R_SortDrawSurfs
-=================
-*/
-void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) {
- shader_t *shader;
- int fogNum;
- int entityNum;
- int dlighted;
- int pshadowed;
- int i;
-
- //ri.Printf(PRINT_ALL, "firstDrawSurf %d numDrawSurfs %d\n", (int)(drawSurfs - tr.refdef.drawSurfs), numDrawSurfs);
-
- // it is possible for some views to not have any surfaces
- if ( numDrawSurfs < 1 ) {
- // we still need to add it for hyperspace cases
- R_AddDrawSurfCmd( drawSurfs, numDrawSurfs );
- return;
- }
-
- // if we overflowed MAX_DRAWSURFS, the drawsurfs
- // wrapped around in the buffer and we will be missing
- // the first surfaces, not the last ones
- if ( numDrawSurfs > MAX_DRAWSURFS ) {
- numDrawSurfs = MAX_DRAWSURFS;
- }
-
- // sort the drawsurfs by sort type, then orientation, then shader
- R_RadixSort( drawSurfs, numDrawSurfs );
-
- // skip pass through drawing if rendering a shadow map
- if (tr.viewParms.flags & (VPF_SHADOWMAP | VPF_DEPTHSHADOW))
- {
- R_AddDrawSurfCmd( drawSurfs, numDrawSurfs );
- return;
- }
-
- // check for any pass through drawing, which
- // may cause another view to be rendered first
- for ( i = 0 ; i < numDrawSurfs ; i++ ) {
- R_DecomposeSort( (drawSurfs+i)->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed );
-
- if ( shader->sort > SS_PORTAL ) {
- break;
- }
-
- // no shader should ever have this sort type
- if ( shader->sort == SS_BAD ) {
- ri.Error (ERR_DROP, "Shader '%s'with sort == SS_BAD", shader->name );
- }
-
- // if the mirror was completely clipped away, we may need to check another surface
- if ( R_MirrorViewBySurface( (drawSurfs+i), entityNum) ) {
- // this is a debug option to see exactly what is being mirrored
- if ( r_portalOnly->integer ) {
- return;
- }
- break; // only one mirror view at a time
- }
- }
-
- R_AddDrawSurfCmd( drawSurfs, numDrawSurfs );
-}
-
-static void R_AddEntitySurface (int entityNum)
-{
- trRefEntity_t *ent;
- shader_t *shader;
-
- tr.currentEntityNum = entityNum;
-
- ent = tr.currentEntity = &tr.refdef.entities[tr.currentEntityNum];
-
- ent->needDlights = qfalse;
-
- // preshift the value we are going to OR into the drawsurf sort
- tr.shiftedEntityNum = tr.currentEntityNum << QSORT_REFENTITYNUM_SHIFT;
-
- //
- // the weapon model must be handled special --
- // we don't want the hacked weapon position showing in
- // mirrors, because the true body position will already be drawn
- //
- if ( (ent->e.renderfx & RF_FIRST_PERSON) && (tr.viewParms.isPortal
- || (tr.viewParms.flags & (VPF_SHADOWMAP | VPF_DEPTHSHADOW))) ) {
- return;
- }
-
- // simple generated models, like sprites and beams, are not culled
- switch ( ent->e.reType ) {
- case RT_PORTALSURFACE:
- break; // don't draw anything
- case RT_SPRITE:
- case RT_BEAM:
- case RT_LIGHTNING:
- case RT_RAIL_CORE:
- case RT_RAIL_RINGS:
- // self blood sprites, talk balloons, etc should not be drawn in the primary
- // view. We can't just do this check for all entities, because md3
- // entities may still want to cast shadows from them
- if ( (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal) {
- return;
- }
- shader = R_GetShaderByHandle( ent->e.customShader );
- R_AddDrawSurf( &entitySurface, shader, R_SpriteFogNum( ent ), 0, 0 );
- break;
-
- case RT_MODEL:
- // we must set up parts of tr.or for model culling
- R_RotateForEntity( ent, &tr.viewParms, &tr.or );
-
- tr.currentModel = R_GetModelByHandle( ent->e.hModel );
- if (!tr.currentModel) {
- R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0, 0 );
- } else {
- switch ( tr.currentModel->type ) {
- case MOD_MESH:
- R_AddMD3Surfaces( ent );
- break;
- case MOD_MD4:
- R_AddAnimSurfaces( ent );
- break;
-#ifdef RAVENMD4
- case MOD_MDR:
- R_MDRAddAnimSurfaces( ent );
- break;
-#endif
- case MOD_IQM:
- R_AddIQMSurfaces( ent );
- break;
- case MOD_BRUSH:
- R_AddBrushModelSurfaces( ent );
- break;
- case MOD_BAD: // null model axis
- if ( (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal) {
- break;
- }
- R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0, 0 );
- break;
- default:
- ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad modeltype" );
- break;
- }
- }
- break;
- default:
- ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad reType" );
- }
-}
-
-/*
-=============
-R_AddEntitySurfaces
-=============
-*/
-void R_AddEntitySurfaces (void) {
- int i;
-
- if ( !r_drawentities->integer ) {
- return;
- }
-
- for ( i = 0; i < tr.refdef.num_entities; i++)
- R_AddEntitySurface(i);
-}
-
-
-/*
-====================
-R_GenerateDrawSurfs
-====================
-*/
-void R_GenerateDrawSurfs( void ) {
- R_AddWorldSurfaces ();
-
- R_AddPolygonSurfaces();
-
- // set the projection matrix with the minimum zfar
- // now that we have the world bounded
- // this needs to be done before entities are
- // added, because they use the projection
- // matrix for lod calculation
-
- // dynamically compute far clip plane distance
- if (!(tr.viewParms.flags & VPF_SHADOWMAP))
- {
- R_SetFarClip();
- }
-
- // we know the size of the clipping volume. Now set the rest of the projection matrix.
- R_SetupProjectionZ (&tr.viewParms);
-
- R_AddEntitySurfaces ();
-}
-
-/*
-================
-R_DebugPolygon
-================
-*/
-void R_DebugPolygon( int color, int numPoints, float *points ) {
- // FIXME: implement this
-#if 0
- int i;
-
- GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
-
- // draw solid shade
-
- qglColor3f( color&1, (color>>1)&1, (color>>2)&1 );
- qglBegin( GL_POLYGON );
- for ( i = 0 ; i < numPoints ; i++ ) {
- qglVertex3fv( points + i * 3 );
- }
- qglEnd();
-
- // draw wireframe outline
- GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
- qglDepthRange( 0, 0 );
- qglColor3f( 1, 1, 1 );
- qglBegin( GL_POLYGON );
- for ( i = 0 ; i < numPoints ; i++ ) {
- qglVertex3fv( points + i * 3 );
- }
- qglEnd();
- qglDepthRange( 0, 1 );
-#endif
-}
-
-/*
-====================
-R_DebugGraphics
-
-Visualization aid for movement clipping debugging
-====================
-*/
-void R_DebugGraphics( void ) {
- if ( !r_debugSurface->integer ) {
- return;
- }
-
- R_IssuePendingRenderCommands();
-
- GL_Bind( tr.whiteImage);
- GL_Cull( CT_FRONT_SIDED );
- ri.CM_DrawDebugSurface( R_DebugPolygon );
-}
-
-
-/*
-================
-R_RenderView
-
-A view may be either the actual camera view,
-or a mirror / remote location
-================
-*/
-void R_RenderView (viewParms_t *parms) {
- int firstDrawSurf;
-
- if ( parms->viewportWidth <= 0 || parms->viewportHeight <= 0 ) {
- return;
- }
-
- tr.viewCount++;
-
- tr.viewParms = *parms;
- tr.viewParms.frameSceneNum = tr.frameSceneNum;
- tr.viewParms.frameCount = tr.frameCount;
-
- firstDrawSurf = tr.refdef.numDrawSurfs;
-
- tr.viewCount++;
-
- // set viewParms.world
- R_RotateForViewer ();
-
- R_SetupProjection(&tr.viewParms, r_zproj->value, tr.viewParms.zFar, qtrue);
-
- R_GenerateDrawSurfs();
-
- R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf );
-
- // draw main system development information (surface outlines, etc)
- R_DebugGraphics();
-}
-
-
-void R_RenderDlightCubemaps(const refdef_t *fd)
-{
- int i;
-
- for (i = 0; i < tr.refdef.num_dlights; i++)
- {
- viewParms_t shadowParms;
- int j;
-
- // use previous frame to determine visible dlights
- if ((1 << i) & tr.refdef.dlightMask)
- continue;
-
- Com_Memset( &shadowParms, 0, sizeof( shadowParms ) );
-
- shadowParms.viewportX = tr.refdef.x;
- shadowParms.viewportY = glConfig.vidHeight - ( tr.refdef.y + PSHADOW_MAP_SIZE );
- shadowParms.viewportWidth = PSHADOW_MAP_SIZE;
- shadowParms.viewportHeight = PSHADOW_MAP_SIZE;
- shadowParms.isPortal = qfalse;
- shadowParms.isMirror = qtrue; // because it is
-
- shadowParms.fovX = 90;
- shadowParms.fovY = 90;
-
- shadowParms.flags = VPF_SHADOWMAP | VPF_DEPTHSHADOW;
- shadowParms.zFar = tr.refdef.dlights[i].radius;
-
- VectorCopy( tr.refdef.dlights[i].origin, shadowParms.or.origin );
-
- for (j = 0; j < 6; j++)
- {
- switch(j)
- {
- case 0:
- // -X
- VectorSet( shadowParms.or.axis[0], -1, 0, 0);
- VectorSet( shadowParms.or.axis[1], 0, 0, -1);
- VectorSet( shadowParms.or.axis[2], 0, 1, 0);
- break;
- case 1:
- // +X
- VectorSet( shadowParms.or.axis[0], 1, 0, 0);
- VectorSet( shadowParms.or.axis[1], 0, 0, 1);
- VectorSet( shadowParms.or.axis[2], 0, 1, 0);
- break;
- case 2:
- // -Y
- VectorSet( shadowParms.or.axis[0], 0, -1, 0);
- VectorSet( shadowParms.or.axis[1], 1, 0, 0);
- VectorSet( shadowParms.or.axis[2], 0, 0, -1);
- break;
- case 3:
- // +Y
- VectorSet( shadowParms.or.axis[0], 0, 1, 0);
- VectorSet( shadowParms.or.axis[1], 1, 0, 0);
- VectorSet( shadowParms.or.axis[2], 0, 0, 1);
- break;
- case 4:
- // -Z
- VectorSet( shadowParms.or.axis[0], 0, 0, -1);
- VectorSet( shadowParms.or.axis[1], 1, 0, 0);
- VectorSet( shadowParms.or.axis[2], 0, 1, 0);
- break;
- case 5:
- // +Z
- VectorSet( shadowParms.or.axis[0], 0, 0, 1);
- VectorSet( shadowParms.or.axis[1], -1, 0, 0);
- VectorSet( shadowParms.or.axis[2], 0, 1, 0);
- break;
- }
-
- R_RenderView(&shadowParms);
- R_AddCapShadowmapCmd( i, j );
- }
- }
-}
-
-
-void R_RenderPshadowMaps(const refdef_t *fd)
-{
- viewParms_t shadowParms;
- int i;
-
- // first, make a list of shadows
- for ( i = 0; i < tr.refdef.num_entities; i++)
- {
- trRefEntity_t *ent = &tr.refdef.entities[i];
-
- if((ent->e.renderfx & (RF_FIRST_PERSON | RF_NOSHADOW)))
- continue;
-
- //if((ent->e.renderfx & RF_THIRD_PERSON))
- //continue;
-
- if (ent->e.reType == RT_MODEL)
- {
- model_t *model = R_GetModelByHandle( ent->e.hModel );
- pshadow_t shadow;
- float radius = 0.0f;
- float scale = 1.0f;
- vec3_t diff;
- int j;
-
- if (!model)
- continue;
-
- if (ent->e.nonNormalizedAxes)
- {
- scale = VectorLength( ent->e.axis[0] );
- }
-
- switch (model->type)
- {
- case MOD_MESH:
- {
- mdvFrame_t *frame = &model->mdv[0]->frames[ent->e.frame];
-
- radius = frame->radius * scale;
- }
- break;
-
- case MOD_MD4:
- {
- // FIXME: actually calculate the radius and bounds, this is a horrible hack
- radius = r_pshadowDist->value / 2.0f;
- }
- break;
-#ifdef RAVENMD4
- case MOD_MDR:
- {
- // FIXME: never actually tested this
- mdrHeader_t *header = model->modelData;
- int frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] );
- mdrFrame_t *frame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame);
-
- radius = frame->radius;
- }
- break;
-#endif
- case MOD_IQM:
- {
- // FIXME: never actually tested this
- iqmData_t *data = model->modelData;
- vec3_t diag;
- float *framebounds;
-
- framebounds = data->bounds + 6*ent->e.frame;
- VectorSubtract( framebounds+3, framebounds, diag );
- radius = 0.5f * VectorLength( diag );
- }
- break;
-
- default:
- break;
- }
-
- if (!radius)
- continue;
-
- // Cull entities that are behind the viewer by more than lightRadius
- VectorSubtract(ent->e.origin, fd->vieworg, diff);
- if (DotProduct(diff, fd->viewaxis[0]) < -r_pshadowDist->value)
- continue;
-
- memset(&shadow, 0, sizeof(shadow));
-
- shadow.numEntities = 1;
- shadow.entityNums[0] = i;
- shadow.viewRadius = radius;
- shadow.lightRadius = r_pshadowDist->value;
- VectorCopy(ent->e.origin, shadow.viewOrigin);
- shadow.sort = DotProduct(diff, diff) / (radius * radius);
- VectorCopy(ent->e.origin, shadow.entityOrigins[0]);
- shadow.entityRadiuses[0] = radius;
-
- for (j = 0; j < MAX_CALC_PSHADOWS; j++)
- {
- pshadow_t swap;
-
- if (j + 1 > tr.refdef.num_pshadows)
- {
- tr.refdef.num_pshadows = j + 1;
- tr.refdef.pshadows[j] = shadow;
- break;
- }
-
- // sort shadows by distance from camera divided by radius
- // FIXME: sort better
- if (tr.refdef.pshadows[j].sort <= shadow.sort)
- continue;
-
- swap = tr.refdef.pshadows[j];
- tr.refdef.pshadows[j] = shadow;
- shadow = swap;
- }
- }
- }
-
- // next, merge touching pshadows
- for ( i = 0; i < tr.refdef.num_pshadows; i++)
- {
- pshadow_t *ps1 = &tr.refdef.pshadows[i];
- int j;
-
- for (j = i + 1; j < tr.refdef.num_pshadows; j++)
- {
- pshadow_t *ps2 = &tr.refdef.pshadows[j];
- int k;
- qboolean touch;
-
- if (ps1->numEntities == 8)
- break;
-
- touch = qfalse;
- if (SpheresIntersect(ps1->viewOrigin, ps1->viewRadius, ps2->viewOrigin, ps2->viewRadius))
- {
- for (k = 0; k < ps1->numEntities; k++)
- {
- if (SpheresIntersect(ps1->entityOrigins[k], ps1->entityRadiuses[k], ps2->viewOrigin, ps2->viewRadius))
- {
- touch = qtrue;
- break;
- }
- }
- }
-
- if (touch)
- {
- vec3_t newOrigin;
- float newRadius;
-
- BoundingSphereOfSpheres(ps1->viewOrigin, ps1->viewRadius, ps2->viewOrigin, ps2->viewRadius, newOrigin, &newRadius);
- VectorCopy(newOrigin, ps1->viewOrigin);
- ps1->viewRadius = newRadius;
-
- ps1->entityNums[ps1->numEntities] = ps2->entityNums[0];
- VectorCopy(ps2->viewOrigin, ps1->entityOrigins[ps1->numEntities]);
- ps1->entityRadiuses[ps1->numEntities] = ps2->viewRadius;
-
- ps1->numEntities++;
-
- for (k = j; k < tr.refdef.num_pshadows - 1; k++)
- {
- tr.refdef.pshadows[k] = tr.refdef.pshadows[k + 1];
- }
-
- j--;
- tr.refdef.num_pshadows--;
- }
- }
- }
-
- // cap number of drawn pshadows
- if (tr.refdef.num_pshadows > MAX_DRAWN_PSHADOWS)
- {
- tr.refdef.num_pshadows = MAX_DRAWN_PSHADOWS;
- }
-
- // next, fill up the rest of the shadow info
- for ( i = 0; i < tr.refdef.num_pshadows; i++)
- {
- pshadow_t *shadow = &tr.refdef.pshadows[i];
- vec3_t up;
- vec3_t ambientLight, directedLight, lightDir;
-
- VectorSet(lightDir, 0.57735f, 0.57735f, 0.57735f);
-#if 1
- R_LightForPoint(shadow->viewOrigin, ambientLight, directedLight, lightDir);
-
- // sometimes there's no light
- if (DotProduct(lightDir, lightDir) < 0.9f)
- VectorSet(lightDir, 0.0f, 0.0f, 1.0f);
-#endif
-
- if (shadow->viewRadius * 3.0f > shadow->lightRadius)
- {
- shadow->lightRadius = shadow->viewRadius * 3.0f;
- }
-
- VectorMA(shadow->viewOrigin, shadow->viewRadius, lightDir, shadow->lightOrigin);
-
- // make up a projection, up doesn't matter
- VectorScale(lightDir, -1.0f, shadow->lightViewAxis[0]);
- VectorSet(up, 0, 0, -1);
-
- if ( abs(DotProduct(up, shadow->lightViewAxis[0])) > 0.9f )
- {
- VectorSet(up, -1, 0, 0);
- }
-
- CrossProduct(shadow->lightViewAxis[0], up, shadow->lightViewAxis[1]);
- VectorNormalize(shadow->lightViewAxis[1]);
- CrossProduct(shadow->lightViewAxis[0], shadow->lightViewAxis[1], shadow->lightViewAxis[2]);
-
- VectorCopy(shadow->lightViewAxis[0], shadow->cullPlane.normal);
- shadow->cullPlane.dist = DotProduct(shadow->cullPlane.normal, shadow->lightOrigin);
- shadow->cullPlane.type = PLANE_NON_AXIAL;
- SetPlaneSignbits(&shadow->cullPlane);
- }
-
- // next, render shadowmaps
- for ( i = 0; i < tr.refdef.num_pshadows; i++)
- {
- int firstDrawSurf;
- pshadow_t *shadow = &tr.refdef.pshadows[i];
- int j;
-
- Com_Memset( &shadowParms, 0, sizeof( shadowParms ) );
-
- if (glRefConfig.framebufferObject)
- {
- shadowParms.viewportX = 0;
- shadowParms.viewportY = 0;
- }
- else
- {
- shadowParms.viewportX = tr.refdef.x;
- shadowParms.viewportY = glConfig.vidHeight - ( tr.refdef.y + PSHADOW_MAP_SIZE );
- }
- shadowParms.viewportWidth = PSHADOW_MAP_SIZE;
- shadowParms.viewportHeight = PSHADOW_MAP_SIZE;
- shadowParms.isPortal = qfalse;
- shadowParms.isMirror = qfalse;
-
- shadowParms.fovX = 90;
- shadowParms.fovY = 90;
-
- if (glRefConfig.framebufferObject)
- shadowParms.targetFbo = tr.pshadowFbos[i];
-
- shadowParms.flags = VPF_SHADOWMAP | VPF_DEPTHSHADOW;
- shadowParms.zFar = shadow->lightRadius;
-
- VectorCopy(shadow->lightOrigin, shadowParms.or.origin);
-
- VectorCopy(shadow->lightViewAxis[0], shadowParms.or.axis[0]);
- VectorCopy(shadow->lightViewAxis[1], shadowParms.or.axis[1]);
- VectorCopy(shadow->lightViewAxis[2], shadowParms.or.axis[2]);
-
- {
- tr.viewCount++;
-
- tr.viewParms = shadowParms;
- tr.viewParms.frameSceneNum = tr.frameSceneNum;
- tr.viewParms.frameCount = tr.frameCount;
-
- firstDrawSurf = tr.refdef.numDrawSurfs;
-
- tr.viewCount++;
-
- // set viewParms.world
- R_RotateForViewer ();
-
- {
- float xmin, xmax, ymin, ymax, znear, zfar;
- viewParms_t *dest = &tr.viewParms;
- vec3_t pop;
-
- xmin = ymin = -shadow->viewRadius;
- xmax = ymax = shadow->viewRadius;
- znear = 0;
- zfar = shadow->lightRadius;
-
- dest->projectionMatrix[0] = 2 / (xmax - xmin);
- dest->projectionMatrix[4] = 0;
- dest->projectionMatrix[8] = (xmax + xmin) / (xmax - xmin);
- dest->projectionMatrix[12] =0;
-
- dest->projectionMatrix[1] = 0;
- dest->projectionMatrix[5] = 2 / (ymax - ymin);
- dest->projectionMatrix[9] = ( ymax + ymin ) / (ymax - ymin); // normally 0
- dest->projectionMatrix[13] = 0;
-
- dest->projectionMatrix[2] = 0;
- dest->projectionMatrix[6] = 0;
- dest->projectionMatrix[10] = 2 / (zfar - znear);
- dest->projectionMatrix[14] = 0;
-
- dest->projectionMatrix[3] = 0;
- dest->projectionMatrix[7] = 0;
- dest->projectionMatrix[11] = 0;
- dest->projectionMatrix[15] = 1;
-
- VectorScale(dest->or.axis[1], 1.0f, dest->frustum[0].normal);
- VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[0].normal, pop);
- dest->frustum[0].dist = DotProduct(pop, dest->frustum[0].normal);
-
- VectorScale(dest->or.axis[1], -1.0f, dest->frustum[1].normal);
- VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[1].normal, pop);
- dest->frustum[1].dist = DotProduct(pop, dest->frustum[1].normal);
-
- VectorScale(dest->or.axis[2], 1.0f, dest->frustum[2].normal);
- VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[2].normal, pop);
- dest->frustum[2].dist = DotProduct(pop, dest->frustum[2].normal);
-
- VectorScale(dest->or.axis[2], -1.0f, dest->frustum[3].normal);
- VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[3].normal, pop);
- dest->frustum[3].dist = DotProduct(pop, dest->frustum[3].normal);
-
- VectorScale(dest->or.axis[0], -1.0f, dest->frustum[4].normal);
- VectorMA(dest->or.origin, -shadow->lightRadius, dest->frustum[4].normal, pop);
- dest->frustum[4].dist = DotProduct(pop, dest->frustum[4].normal);
-
- for (j = 0; j < 5; j++)
- {
- dest->frustum[j].type = PLANE_NON_AXIAL;
- SetPlaneSignbits (&dest->frustum[j]);
- }
-
- dest->flags |= VPF_FARPLANEFRUSTUM;
- }
-
- for (j = 0; j < shadow->numEntities; j++)
- {
- R_AddEntitySurface(shadow->entityNums[j]);
- }
-
- R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf );
-
- if (!glRefConfig.framebufferObject)
- R_AddCapShadowmapCmd( i, -1 );
- }
- }
-}
-
-static float CalcSplit(float n, float f, float i, float m)
-{
- return (n * pow(f / n, i / m) + (f - n) * i / m) / 2.0f;
-}
-
-
-void R_RenderSunShadowMaps(const refdef_t *fd, int level)
-{
- viewParms_t shadowParms;
- vec4_t lightDir, lightCol;
- vec3_t lightViewAxis[3];
- vec3_t lightOrigin;
- float splitZNear, splitZFar, splitBias;
- float viewZNear, viewZFar;
- vec3_t lightviewBounds[2];
- qboolean lightViewIndependentOfCameraView = qfalse;
-
- if (r_forceSun->integer == 2)
- {
- int scale = 32768;
- float angle = (fd->time % scale) / (float)scale * M_PI;
- lightDir[0] = cos(angle);
- lightDir[1] = sin(35.0f * M_PI / 180.0f);
- lightDir[2] = sin(angle) * cos(35.0f * M_PI / 180.0f);
- lightDir[3] = 0.0f;
-
- if (1) //((fd->time % (scale * 2)) < scale)
- {
- lightCol[0] =
- lightCol[1] =
- lightCol[2] = CLAMP(sin(angle) * 2.0f, 0.0f, 1.0f) * 2.0f;
- lightCol[3] = 1.0f;
- }
- else
- {
- lightCol[0] =
- lightCol[1] =
- lightCol[2] = CLAMP(sin(angle) * 2.0f * 0.1f, 0.0f, 0.1f);
- lightCol[3] = 1.0f;
- }
-
- VectorCopy4(lightDir, tr.refdef.sunDir);
- VectorCopy4(lightCol, tr.refdef.sunCol);
- VectorScale4(lightCol, 0.2f, tr.refdef.sunAmbCol);
- }
- else
- {
- VectorCopy4(tr.refdef.sunDir, lightDir);
- }
-
- viewZNear = r_shadowCascadeZNear->value;
- viewZFar = r_shadowCascadeZFar->value;
- splitBias = r_shadowCascadeZBias->value;
-
- switch(level)
- {
- case 0:
- default:
- //splitZNear = r_znear->value;
- //splitZFar = 256;
- splitZNear = viewZNear;
- splitZFar = CalcSplit(viewZNear, viewZFar, 1, 3) + splitBias;
- break;
- case 1:
- splitZNear = CalcSplit(viewZNear, viewZFar, 1, 3) + splitBias;
- splitZFar = CalcSplit(viewZNear, viewZFar, 2, 3) + splitBias;
- //splitZNear = 256;
- //splitZFar = 896;
- break;
- case 2:
- splitZNear = CalcSplit(viewZNear, viewZFar, 2, 3) + splitBias;
- splitZFar = viewZFar;
- //splitZNear = 896;
- //splitZFar = 3072;
- break;
- }
-
- VectorCopy(fd->vieworg, lightOrigin);
-
-
- // Make up a projection
- VectorScale(lightDir, -1.0f, lightViewAxis[0]);
-
- if (lightViewIndependentOfCameraView)
- {
- // Use world up as light view up
- VectorSet(lightViewAxis[2], 0, 0, 1);
- }
- else if (level == 0)
- {
- // Level 0 tries to use a diamond texture orientation relative to camera view
- // Use halfway between camera view forward and left for light view up
- VectorAdd(fd->viewaxis[0], fd->viewaxis[1], lightViewAxis[2]);
- }
- else
- {
- // Use camera view up as light view up
- VectorCopy(fd->viewaxis[2], lightViewAxis[2]);
- }
-
- // Check if too close to parallel to light direction
- if (abs(DotProduct(lightViewAxis[2], lightViewAxis[0])) > 0.9f)
- {
- if (lightViewIndependentOfCameraView)
- {
- // Use world left as light view up
- VectorSet(lightViewAxis[2], 0, 1, 0);
- }
- else if (level == 0)
- {
- // Level 0 tries to use a diamond texture orientation relative to camera view
- // Use halfway between camera view forward and up for light view up
- VectorAdd(fd->viewaxis[0], fd->viewaxis[2], lightViewAxis[2]);
- }
- else
- {
- // Use camera view left as light view up
- VectorCopy(fd->viewaxis[1], lightViewAxis[2]);
- }
- }
-
- // clean axes
- CrossProduct(lightViewAxis[2], lightViewAxis[0], lightViewAxis[1]);
- VectorNormalize(lightViewAxis[1]);
- CrossProduct(lightViewAxis[0], lightViewAxis[1], lightViewAxis[2]);
-
- // Create bounds for light projection using slice of view projection
- {
- matrix_t lightViewMatrix;
- vec4_t point, base, lightViewPoint;
- float lx, ly;
-
- base[3] = 1;
- point[3] = 1;
- lightViewPoint[3] = 1;
-
- Matrix16View(lightViewAxis, lightOrigin, lightViewMatrix);
-
- ClearBounds(lightviewBounds[0], lightviewBounds[1]);
-
- // add view near plane
- lx = splitZNear * tan(fd->fov_x * M_PI / 360.0f);
- ly = splitZNear * tan(fd->fov_y * M_PI / 360.0f);
- VectorMA(fd->vieworg, splitZNear, fd->viewaxis[0], base);
-
- VectorMA(base, lx, fd->viewaxis[1], point);
- VectorMA(point, ly, fd->viewaxis[2], point);
- Matrix16Transform(lightViewMatrix, point, lightViewPoint);
- AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
-
- VectorMA(base, -lx, fd->viewaxis[1], point);
- VectorMA(point, ly, fd->viewaxis[2], point);
- Matrix16Transform(lightViewMatrix, point, lightViewPoint);
- AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
-
- VectorMA(base, lx, fd->viewaxis[1], point);
- VectorMA(point, -ly, fd->viewaxis[2], point);
- Matrix16Transform(lightViewMatrix, point, lightViewPoint);
- AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
-
- VectorMA(base, -lx, fd->viewaxis[1], point);
- VectorMA(point, -ly, fd->viewaxis[2], point);
- Matrix16Transform(lightViewMatrix, point, lightViewPoint);
- AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
-
-
- // add view far plane
- lx = splitZFar * tan(fd->fov_x * M_PI / 360.0f);
- ly = splitZFar * tan(fd->fov_y * M_PI / 360.0f);
- VectorMA(fd->vieworg, splitZFar, fd->viewaxis[0], base);
-
- VectorMA(base, lx, fd->viewaxis[1], point);
- VectorMA(point, ly, fd->viewaxis[2], point);
- Matrix16Transform(lightViewMatrix, point, lightViewPoint);
- AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
-
- VectorMA(base, -lx, fd->viewaxis[1], point);
- VectorMA(point, ly, fd->viewaxis[2], point);
- Matrix16Transform(lightViewMatrix, point, lightViewPoint);
- AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
-
- VectorMA(base, lx, fd->viewaxis[1], point);
- VectorMA(point, -ly, fd->viewaxis[2], point);
- Matrix16Transform(lightViewMatrix, point, lightViewPoint);
- AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
-
- VectorMA(base, -lx, fd->viewaxis[1], point);
- VectorMA(point, -ly, fd->viewaxis[2], point);
- Matrix16Transform(lightViewMatrix, point, lightViewPoint);
- AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
-
- if (!glRefConfig.depthClamp)
- lightviewBounds[0][0] = lightviewBounds[1][0] - 8192;
-
- // Moving the Light in Texel-Sized Increments
- // from http://msdn.microsoft.com/en-us/library/windows/desktop/ee416324%28v=vs.85%29.aspx
- //
- if (lightViewIndependentOfCameraView)
- {
- float cascadeBound, worldUnitsPerTexel, invWorldUnitsPerTexel;
-
- cascadeBound = MAX(lightviewBounds[1][0] - lightviewBounds[0][0], lightviewBounds[1][1] - lightviewBounds[0][1]);
- cascadeBound = MAX(cascadeBound, lightviewBounds[1][2] - lightviewBounds[0][2]);
- worldUnitsPerTexel = cascadeBound / tr.sunShadowFbo[level]->width;
- invWorldUnitsPerTexel = 1.0f / worldUnitsPerTexel;
-
- VectorScale(lightviewBounds[0], invWorldUnitsPerTexel, lightviewBounds[0]);
- lightviewBounds[0][0] = floor(lightviewBounds[0][0]);
- lightviewBounds[0][1] = floor(lightviewBounds[0][1]);
- lightviewBounds[0][2] = floor(lightviewBounds[0][2]);
- VectorScale(lightviewBounds[0], worldUnitsPerTexel, lightviewBounds[0]);
-
- VectorScale(lightviewBounds[1], invWorldUnitsPerTexel, lightviewBounds[1]);
- lightviewBounds[1][0] = floor(lightviewBounds[1][0]);
- lightviewBounds[1][1] = floor(lightviewBounds[1][1]);
- lightviewBounds[1][2] = floor(lightviewBounds[1][2]);
- VectorScale(lightviewBounds[1], worldUnitsPerTexel, lightviewBounds[1]);
- }
-
- //ri.Printf(PRINT_ALL, "znear %f zfar %f\n", lightviewBounds[0][0], lightviewBounds[1][0]);
- //ri.Printf(PRINT_ALL, "fovx %f fovy %f xmin %f xmax %f ymin %f ymax %f\n", fd->fov_x, fd->fov_y, xmin, xmax, ymin, ymax);
- }
-
-
- {
- int firstDrawSurf;
-
- Com_Memset( &shadowParms, 0, sizeof( shadowParms ) );
-
- if (glRefConfig.framebufferObject)
- {
- shadowParms.viewportX = 0;
- shadowParms.viewportY = 0;
- }
- else
- {
- shadowParms.viewportX = tr.refdef.x;
- shadowParms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.sunShadowFbo[level]->height );
- }
- shadowParms.viewportWidth = tr.sunShadowFbo[level]->width;
- shadowParms.viewportHeight = tr.sunShadowFbo[level]->height;
- shadowParms.isPortal = qfalse;
- shadowParms.isMirror = qfalse;
-
- shadowParms.fovX = 90;
- shadowParms.fovY = 90;
-
- if (glRefConfig.framebufferObject)
- shadowParms.targetFbo = tr.sunShadowFbo[level];
-
- shadowParms.flags = VPF_DEPTHSHADOW | VPF_DEPTHCLAMP | VPF_ORTHOGRAPHIC;
- shadowParms.zFar = lightviewBounds[1][0];
-
- VectorCopy(lightOrigin, shadowParms.or.origin);
-
- VectorCopy(lightViewAxis[0], shadowParms.or.axis[0]);
- VectorCopy(lightViewAxis[1], shadowParms.or.axis[1]);
- VectorCopy(lightViewAxis[2], shadowParms.or.axis[2]);
-
- VectorCopy(lightOrigin, shadowParms.pvsOrigin );
-
- {
- tr.viewCount++;
-
- tr.viewParms = shadowParms;
- tr.viewParms.frameSceneNum = tr.frameSceneNum;
- tr.viewParms.frameCount = tr.frameCount;
-
- firstDrawSurf = tr.refdef.numDrawSurfs;
-
- tr.viewCount++;
-
- // set viewParms.world
- R_RotateForViewer ();
-
- R_SetupProjectionOrtho(&tr.viewParms, lightviewBounds);
-
- R_AddWorldSurfaces ();
-
- R_AddPolygonSurfaces();
-
- R_AddEntitySurfaces ();
-
- R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf );
- }
-
- Matrix16Multiply(tr.viewParms.projectionMatrix, tr.viewParms.world.modelMatrix, tr.refdef.sunShadowMvp[level]);
- }
-}
diff --git a/src/rend2/tr_marks.c b/src/rend2/tr_marks.c
deleted file mode 100644
index f24459e2..00000000
--- a/src/rend2/tr_marks.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_marks.c -- polygon projection on the world polygons
-
-#include "tr_local.h"
-//#include "assert.h"
-
-#define MAX_VERTS_ON_POLY 64
-
-#define MARKER_OFFSET 0 // 1
-
-/*
-=============
-R_ChopPolyBehindPlane
-
-Out must have space for two more vertexes than in
-=============
-*/
-#define SIDE_FRONT 0
-#define SIDE_BACK 1
-#define SIDE_ON 2
-static void R_ChopPolyBehindPlane( int numInPoints, vec3_t inPoints[MAX_VERTS_ON_POLY],
- int *numOutPoints, vec3_t outPoints[MAX_VERTS_ON_POLY],
- vec3_t normal, vec_t dist, vec_t epsilon) {
- float dists[MAX_VERTS_ON_POLY+4];
- int sides[MAX_VERTS_ON_POLY+4];
- int counts[3];
- float dot;
- int i, j;
- float *p1, *p2, *clip;
- float d;
-
- // don't clip if it might overflow
- if ( numInPoints >= MAX_VERTS_ON_POLY - 2 ) {
- *numOutPoints = 0;
- return;
- }
-
- counts[0] = counts[1] = counts[2] = 0;
-
- // determine sides for each point
- for ( i = 0 ; i < numInPoints ; i++ ) {
- dot = DotProduct( inPoints[i], normal );
- dot -= dist;
- dists[i] = dot;
- if ( dot > epsilon ) {
- sides[i] = SIDE_FRONT;
- } else if ( dot < -epsilon ) {
- sides[i] = SIDE_BACK;
- } else {
- sides[i] = SIDE_ON;
- }
- counts[sides[i]]++;
- }
- sides[i] = sides[0];
- dists[i] = dists[0];
-
- *numOutPoints = 0;
-
- if ( !counts[0] ) {
- return;
- }
- if ( !counts[1] ) {
- *numOutPoints = numInPoints;
- Com_Memcpy( outPoints, inPoints, numInPoints * sizeof(vec3_t) );
- return;
- }
-
- for ( i = 0 ; i < numInPoints ; i++ ) {
- p1 = inPoints[i];
- clip = outPoints[ *numOutPoints ];
-
- if ( sides[i] == SIDE_ON ) {
- VectorCopy( p1, clip );
- (*numOutPoints)++;
- continue;
- }
-
- if ( sides[i] == SIDE_FRONT ) {
- VectorCopy( p1, clip );
- (*numOutPoints)++;
- clip = outPoints[ *numOutPoints ];
- }
-
- if ( sides[i+1] == SIDE_ON || sides[i+1] == sides[i] ) {
- continue;
- }
-
- // generate a split point
- p2 = inPoints[ (i+1) % numInPoints ];
-
- d = dists[i] - dists[i+1];
- if ( d == 0 ) {
- dot = 0;
- } else {
- dot = dists[i] / d;
- }
-
- // clip xyz
-
- for (j=0 ; j<3 ; j++) {
- clip[j] = p1[j] + dot * ( p2[j] - p1[j] );
- }
-
- (*numOutPoints)++;
- }
-}
-
-/*
-=================
-R_BoxSurfaces_r
-
-=================
-*/
-void R_BoxSurfaces_r(mnode_t *node, vec3_t mins, vec3_t maxs, surfaceType_t **list, int listsize, int *listlength, vec3_t dir) {
-
- int s, c;
- msurface_t *surf;
- int *mark;
-
- // do the tail recursion in a loop
- while ( node->contents == -1 ) {
- s = BoxOnPlaneSide( mins, maxs, node->plane );
- if (s == 1) {
- node = node->children[0];
- } else if (s == 2) {
- node = node->children[1];
- } else {
- R_BoxSurfaces_r(node->children[0], mins, maxs, list, listsize, listlength, dir);
- node = node->children[1];
- }
- }
-
- // add the individual surfaces
- mark = tr.world->marksurfaces + node->firstmarksurface;
- c = node->nummarksurfaces;
- while (c--) {
- int *surfViewCount;
- //
- if (*listlength >= listsize) break;
- //
- surfViewCount = &tr.world->surfacesViewCount[*mark];
- surf = tr.world->surfaces + *mark;
- // check if the surface has NOIMPACT or NOMARKS set
- if ( ( surf->shader->surfaceFlags & ( SURF_NOIMPACT | SURF_NOMARKS ) )
- || ( surf->shader->contentFlags & CONTENTS_FOG ) ) {
- *surfViewCount = tr.viewCount;
- }
- // extra check for surfaces to avoid list overflows
- else if (*(surf->data) == SF_FACE) {
- // the face plane should go through the box
- s = BoxOnPlaneSide( mins, maxs, &surf->cullinfo.plane );
- if (s == 1 || s == 2) {
- *surfViewCount = tr.viewCount;
- } else if (DotProduct(surf->cullinfo.plane.normal, dir) > -0.5) {
- // don't add faces that make sharp angles with the projection direction
- *surfViewCount = tr.viewCount;
- }
- }
- else if (*(surf->data) != SF_GRID &&
- *(surf->data) != SF_TRIANGLES)
- *surfViewCount = tr.viewCount;
- // check the viewCount because the surface may have
- // already been added if it spans multiple leafs
- if (*surfViewCount != tr.viewCount) {
- *surfViewCount = tr.viewCount;
- list[*listlength] = surf->data;
- (*listlength)++;
- }
- mark++;
- }
-}
-
-/*
-=================
-R_AddMarkFragments
-
-=================
-*/
-void R_AddMarkFragments(int numClipPoints, vec3_t clipPoints[2][MAX_VERTS_ON_POLY],
- int numPlanes, vec3_t *normals, float *dists,
- int maxPoints, vec3_t pointBuffer,
- int maxFragments, markFragment_t *fragmentBuffer,
- int *returnedPoints, int *returnedFragments,
- vec3_t mins, vec3_t maxs) {
- int pingPong, i;
- markFragment_t *mf;
-
- // chop the surface by all the bounding planes of the to be projected polygon
- pingPong = 0;
-
- for ( i = 0 ; i < numPlanes ; i++ ) {
-
- R_ChopPolyBehindPlane( numClipPoints, clipPoints[pingPong],
- &numClipPoints, clipPoints[!pingPong],
- normals[i], dists[i], 0.5 );
- pingPong ^= 1;
- if ( numClipPoints == 0 ) {
- break;
- }
- }
- // completely clipped away?
- if ( numClipPoints == 0 ) {
- return;
- }
-
- // add this fragment to the returned list
- if ( numClipPoints + (*returnedPoints) > maxPoints ) {
- return; // not enough space for this polygon
- }
- /*
- // all the clip points should be within the bounding box
- for ( i = 0 ; i < numClipPoints ; i++ ) {
- int j;
- for ( j = 0 ; j < 3 ; j++ ) {
- if (clipPoints[pingPong][i][j] < mins[j] - 0.5) break;
- if (clipPoints[pingPong][i][j] > maxs[j] + 0.5) break;
- }
- if (j < 3) break;
- }
- if (i < numClipPoints) return;
- */
-
- mf = fragmentBuffer + (*returnedFragments);
- mf->firstPoint = (*returnedPoints);
- mf->numPoints = numClipPoints;
- Com_Memcpy( pointBuffer + (*returnedPoints) * 3, clipPoints[pingPong], numClipPoints * sizeof(vec3_t) );
-
- (*returnedPoints) += numClipPoints;
- (*returnedFragments)++;
-}
-
-/*
-=================
-R_MarkFragments
-
-=================
-*/
-int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection,
- int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ) {
- int numsurfaces, numPlanes;
- int i, j, k, m, n;
- surfaceType_t *surfaces[64];
- vec3_t mins, maxs;
- int returnedFragments;
- int returnedPoints;
- vec3_t normals[MAX_VERTS_ON_POLY+2];
- float dists[MAX_VERTS_ON_POLY+2];
- vec3_t clipPoints[2][MAX_VERTS_ON_POLY];
- int numClipPoints;
- float *v;
- srfGridMesh_t *cv;
- srfTriangle_t *tri;
- srfVert_t *dv;
- vec3_t normal;
- vec3_t projectionDir;
- vec3_t v1, v2;
-
- if (numPoints <= 0) {
- return 0;
- }
-
- //increment view count for double check prevention
- tr.viewCount++;
-
- //
- VectorNormalize2( projection, projectionDir );
- // find all the brushes that are to be considered
- ClearBounds( mins, maxs );
- for ( i = 0 ; i < numPoints ; i++ ) {
- vec3_t temp;
-
- AddPointToBounds( points[i], mins, maxs );
- VectorAdd( points[i], projection, temp );
- AddPointToBounds( temp, mins, maxs );
- // make sure we get all the leafs (also the one(s) in front of the hit surface)
- VectorMA( points[i], -20, projectionDir, temp );
- AddPointToBounds( temp, mins, maxs );
- }
-
- if (numPoints > MAX_VERTS_ON_POLY) numPoints = MAX_VERTS_ON_POLY;
- // create the bounding planes for the to be projected polygon
- for ( i = 0 ; i < numPoints ; i++ ) {
- VectorSubtract(points[(i+1)%numPoints], points[i], v1);
- VectorAdd(points[i], projection, v2);
- VectorSubtract(points[i], v2, v2);
- CrossProduct(v1, v2, normals[i]);
- VectorNormalizeFast(normals[i]);
- dists[i] = DotProduct(normals[i], points[i]);
- }
- // add near and far clipping planes for projection
- VectorCopy(projectionDir, normals[numPoints]);
- dists[numPoints] = DotProduct(normals[numPoints], points[0]) - 32;
- VectorCopy(projectionDir, normals[numPoints+1]);
- VectorInverse(normals[numPoints+1]);
- dists[numPoints+1] = DotProduct(normals[numPoints+1], points[0]) - 20;
- numPlanes = numPoints + 2;
-
- numsurfaces = 0;
- R_BoxSurfaces_r(tr.world->nodes, mins, maxs, surfaces, 64, &numsurfaces, projectionDir);
- //assert(numsurfaces <= 64);
- //assert(numsurfaces != 64);
-
- returnedPoints = 0;
- returnedFragments = 0;
-
- for ( i = 0 ; i < numsurfaces ; i++ ) {
-
- if (*surfaces[i] == SF_GRID) {
-
- cv = (srfGridMesh_t *) surfaces[i];
- for ( m = 0 ; m < cv->height - 1 ; m++ ) {
- for ( n = 0 ; n < cv->width - 1 ; n++ ) {
- // We triangulate the grid and chop all triangles within
- // the bounding planes of the to be projected polygon.
- // LOD is not taken into account, not such a big deal though.
- //
- // It's probably much nicer to chop the grid itself and deal
- // with this grid as a normal SF_GRID surface so LOD will
- // be applied. However the LOD of that chopped grid must
- // be synced with the LOD of the original curve.
- // One way to do this; the chopped grid shares vertices with
- // the original curve. When LOD is applied to the original
- // curve the unused vertices are flagged. Now the chopped curve
- // should skip the flagged vertices. This still leaves the
- // problems with the vertices at the chopped grid edges.
- //
- // To avoid issues when LOD applied to "hollow curves" (like
- // the ones around many jump pads) we now just add a 2 unit
- // offset to the triangle vertices.
- // The offset is added in the vertex normal vector direction
- // so all triangles will still fit together.
- // The 2 unit offset should avoid pretty much all LOD problems.
-
- numClipPoints = 3;
-
- dv = cv->verts + m * cv->width + n;
-
- VectorCopy(dv[0].xyz, clipPoints[0][0]);
- VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0]);
- VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
- VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
- VectorCopy(dv[1].xyz, clipPoints[0][2]);
- VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2]);
- // check the normal of this triangle
- VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
- VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
- CrossProduct(v1, v2, normal);
- VectorNormalizeFast(normal);
- if (DotProduct(normal, projectionDir) < -0.1) {
- // add the fragments of this triangle
- R_AddMarkFragments(numClipPoints, clipPoints,
- numPlanes, normals, dists,
- maxPoints, pointBuffer,
- maxFragments, fragmentBuffer,
- &returnedPoints, &returnedFragments, mins, maxs);
-
- if ( returnedFragments == maxFragments ) {
- return returnedFragments; // not enough space for more fragments
- }
- }
-
- VectorCopy(dv[1].xyz, clipPoints[0][0]);
- VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0]);
- VectorCopy(dv[cv->width].xyz, clipPoints[0][1]);
- VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]);
- VectorCopy(dv[cv->width+1].xyz, clipPoints[0][2]);
- VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[cv->width+1].normal, clipPoints[0][2]);
- // check the normal of this triangle
- VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1);
- VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2);
- CrossProduct(v1, v2, normal);
- VectorNormalizeFast(normal);
- if (DotProduct(normal, projectionDir) < -0.05) {
- // add the fragments of this triangle
- R_AddMarkFragments(numClipPoints, clipPoints,
- numPlanes, normals, dists,
- maxPoints, pointBuffer,
- maxFragments, fragmentBuffer,
- &returnedPoints, &returnedFragments, mins, maxs);
-
- if ( returnedFragments == maxFragments ) {
- return returnedFragments; // not enough space for more fragments
- }
- }
- }
- }
- }
- else if (*surfaces[i] == SF_FACE) {
-
- srfSurfaceFace_t *surf = ( srfSurfaceFace_t * ) surfaces[i];
-
- // check the normal of this face
- if (DotProduct(surf->plane.normal, projectionDir) > -0.5) {
- continue;
- }
-
- for(k = 0, tri = surf->triangles; k < surf->numTriangles; k++, tri++)
- {
- for(j = 0; j < 3; j++)
- {
- v = surf->verts[tri->indexes[j]].xyz;
- VectorMA(v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j]);
- }
-
- // add the fragments of this face
- R_AddMarkFragments( 3 , clipPoints,
- numPlanes, normals, dists,
- maxPoints, pointBuffer,
- maxFragments, fragmentBuffer,
- &returnedPoints, &returnedFragments, mins, maxs);
- if ( returnedFragments == maxFragments ) {
- return returnedFragments; // not enough space for more fragments
- }
- }
- }
- else if(*surfaces[i] == SF_TRIANGLES && r_marksOnTriangleMeshes->integer) {
-
- srfTriangles_t *surf = (srfTriangles_t *) surfaces[i];
-
- for(k = 0, tri = surf->triangles; k < surf->numTriangles; k++, tri++)
- {
- for(j = 0; j < 3; j++)
- {
- v = surf->verts[tri->indexes[j]].xyz;
- VectorMA(v, MARKER_OFFSET, surf->verts[tri->indexes[j]].normal, clipPoints[0][j]);
- }
-
- // add the fragments of this face
- R_AddMarkFragments(3, clipPoints,
- numPlanes, normals, dists,
- maxPoints, pointBuffer,
- maxFragments, fragmentBuffer, &returnedPoints, &returnedFragments, mins, maxs);
- if(returnedFragments == maxFragments)
- {
- return returnedFragments; // not enough space for more fragments
- }
- }
- }
- }
- return returnedFragments;
-}
-
-
-
-
-
diff --git a/src/rend2/tr_mesh.c b/src/rend2/tr_mesh.c
deleted file mode 100644
index 342854bf..00000000
--- a/src/rend2/tr_mesh.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_mesh.c: triangle model functions
-
-#include "tr_local.h"
-
-static float ProjectRadius( float r, vec3_t location )
-{
- float pr;
- float dist;
- float c;
- vec3_t p;
- float projected[4];
-
- c = DotProduct( tr.viewParms.or.axis[0], tr.viewParms.or.origin );
- dist = DotProduct( tr.viewParms.or.axis[0], location ) - c;
-
- if ( dist <= 0 )
- return 0;
-
- p[0] = 0;
- p[1] = fabs( r );
- p[2] = -dist;
-
- projected[0] = p[0] * tr.viewParms.projectionMatrix[0] +
- p[1] * tr.viewParms.projectionMatrix[4] +
- p[2] * tr.viewParms.projectionMatrix[8] +
- tr.viewParms.projectionMatrix[12];
-
- projected[1] = p[0] * tr.viewParms.projectionMatrix[1] +
- p[1] * tr.viewParms.projectionMatrix[5] +
- p[2] * tr.viewParms.projectionMatrix[9] +
- tr.viewParms.projectionMatrix[13];
-
- projected[2] = p[0] * tr.viewParms.projectionMatrix[2] +
- p[1] * tr.viewParms.projectionMatrix[6] +
- p[2] * tr.viewParms.projectionMatrix[10] +
- tr.viewParms.projectionMatrix[14];
-
- projected[3] = p[0] * tr.viewParms.projectionMatrix[3] +
- p[1] * tr.viewParms.projectionMatrix[7] +
- p[2] * tr.viewParms.projectionMatrix[11] +
- tr.viewParms.projectionMatrix[15];
-
-
- pr = projected[1] / projected[3];
-
- if ( pr > 1.0f )
- pr = 1.0f;
-
- return pr;
-}
-
-/*
-=============
-R_CullModel
-=============
-*/
-static int R_CullModel( mdvModel_t *model, trRefEntity_t *ent ) {
- vec3_t bounds[2];
- mdvFrame_t *oldFrame, *newFrame;
- int i;
-
- // compute frame pointers
- newFrame = model->frames + ent->e.frame;
- oldFrame = model->frames + ent->e.oldframe;
-
- // cull bounding sphere ONLY if this is not an upscaled entity
- if ( !ent->e.nonNormalizedAxes )
- {
- if ( ent->e.frame == ent->e.oldframe )
- {
- switch ( R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius ) )
- {
- case CULL_OUT:
- tr.pc.c_sphere_cull_md3_out++;
- return CULL_OUT;
-
- case CULL_IN:
- tr.pc.c_sphere_cull_md3_in++;
- return CULL_IN;
-
- case CULL_CLIP:
- tr.pc.c_sphere_cull_md3_clip++;
- break;
- }
- }
- else
- {
- int sphereCull, sphereCullB;
-
- sphereCull = R_CullLocalPointAndRadius( newFrame->localOrigin, newFrame->radius );
- if ( newFrame == oldFrame ) {
- sphereCullB = sphereCull;
- } else {
- sphereCullB = R_CullLocalPointAndRadius( oldFrame->localOrigin, oldFrame->radius );
- }
-
- if ( sphereCull == sphereCullB )
- {
- if ( sphereCull == CULL_OUT )
- {
- tr.pc.c_sphere_cull_md3_out++;
- return CULL_OUT;
- }
- else if ( sphereCull == CULL_IN )
- {
- tr.pc.c_sphere_cull_md3_in++;
- return CULL_IN;
- }
- else
- {
- tr.pc.c_sphere_cull_md3_clip++;
- }
- }
- }
- }
-
- // calculate a bounding box in the current coordinate system
- for (i = 0 ; i < 3 ; i++) {
- bounds[0][i] = oldFrame->bounds[0][i] < newFrame->bounds[0][i] ? oldFrame->bounds[0][i] : newFrame->bounds[0][i];
- bounds[1][i] = oldFrame->bounds[1][i] > newFrame->bounds[1][i] ? oldFrame->bounds[1][i] : newFrame->bounds[1][i];
- }
-
- switch ( R_CullLocalBox( bounds ) )
- {
- case CULL_IN:
- tr.pc.c_box_cull_md3_in++;
- return CULL_IN;
- case CULL_CLIP:
- tr.pc.c_box_cull_md3_clip++;
- return CULL_CLIP;
- case CULL_OUT:
- default:
- tr.pc.c_box_cull_md3_out++;
- return CULL_OUT;
- }
-}
-
-
-/*
-=================
-R_ComputeLOD
-
-=================
-*/
-int R_ComputeLOD( trRefEntity_t *ent ) {
- float radius;
- float flod, lodscale;
- float projectedRadius;
- mdvFrame_t *frame;
-#ifdef RAVENMD4
- mdrHeader_t *mdr;
- mdrFrame_t *mdrframe;
-#endif
- int lod;
-
- if ( tr.currentModel->numLods < 2 )
- {
- // model has only 1 LOD level, skip computations and bias
- lod = 0;
- }
- else
- {
- // multiple LODs exist, so compute projected bounding sphere
- // and use that as a criteria for selecting LOD
-
-#ifdef RAVENMD4
- if(tr.currentModel->type == MOD_MDR)
- {
- int frameSize;
- mdr = (mdrHeader_t *) tr.currentModel->modelData;
- frameSize = (size_t) (&((mdrFrame_t *)0)->bones[mdr->numBones]);
-
- mdrframe = (mdrFrame_t *) ((byte *) mdr + mdr->ofsFrames + frameSize * ent->e.frame);
-
- radius = RadiusFromBounds(mdrframe->bounds[0], mdrframe->bounds[1]);
- }
- else
-#endif
- {
- //frame = ( md3Frame_t * ) ( ( ( unsigned char * ) tr.currentModel->md3[0] ) + tr.currentModel->md3[0]->ofsFrames );
- frame = tr.currentModel->mdv[0]->frames;
-
- frame += ent->e.frame;
-
- radius = RadiusFromBounds( frame->bounds[0], frame->bounds[1] );
- }
-
- if ( ( projectedRadius = ProjectRadius( radius, ent->e.origin ) ) != 0 )
- {
- lodscale = r_lodscale->value;
- if (lodscale > 20) lodscale = 20;
- flod = 1.0f - projectedRadius * lodscale;
- }
- else
- {
- // object intersects near view plane, e.g. view weapon
- flod = 0;
- }
-
- flod *= tr.currentModel->numLods;
- lod = ri.ftol(flod);
-
- if ( lod < 0 )
- {
- lod = 0;
- }
- else if ( lod >= tr.currentModel->numLods )
- {
- lod = tr.currentModel->numLods - 1;
- }
- }
-
- lod += r_lodbias->integer;
-
- if ( lod >= tr.currentModel->numLods )
- lod = tr.currentModel->numLods - 1;
- if ( lod < 0 )
- lod = 0;
-
- return lod;
-}
-
-/*
-=================
-R_ComputeFogNum
-
-=================
-*/
-int R_ComputeFogNum( mdvModel_t *model, trRefEntity_t *ent ) {
- int i, j;
- fog_t *fog;
- mdvFrame_t *mdvFrame;
- vec3_t localOrigin;
-
- if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
- return 0;
- }
-
- // FIXME: non-normalized axis issues
- mdvFrame = model->frames + ent->e.frame;
- VectorAdd( ent->e.origin, mdvFrame->localOrigin, localOrigin );
- for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
- fog = &tr.world->fogs[i];
- for ( j = 0 ; j < 3 ; j++ ) {
- if ( localOrigin[j] - mdvFrame->radius >= fog->bounds[1][j] ) {
- break;
- }
- if ( localOrigin[j] + mdvFrame->radius <= fog->bounds[0][j] ) {
- break;
- }
- }
- if ( j == 3 ) {
- return i;
- }
- }
-
- return 0;
-}
-
-/*
-=================
-R_AddMD3Surfaces
-
-=================
-*/
-void R_AddMD3Surfaces( trRefEntity_t *ent ) {
- int i;
- mdvModel_t *model = NULL;
- mdvSurface_t *surface = NULL;
- shader_t *shader = NULL;
- int cull;
- int lod;
- int fogNum;
- qboolean personalModel;
-
- // don't add third_person objects if not in a portal
- personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !(tr.viewParms.isPortal
- || (tr.viewParms.flags & (VPF_SHADOWMAP | VPF_DEPTHSHADOW)));
-
- if ( ent->e.renderfx & RF_WRAP_FRAMES ) {
- ent->e.frame %= tr.currentModel->mdv[0]->numFrames;
- ent->e.oldframe %= tr.currentModel->mdv[0]->numFrames;
- }
-
- //
- // Validate the frames so there is no chance of a crash.
- // This will write directly into the entity structure, so
- // when the surfaces are rendered, they don't need to be
- // range checked again.
- //
- if ( (ent->e.frame >= tr.currentModel->mdv[0]->numFrames)
- || (ent->e.frame < 0)
- || (ent->e.oldframe >= tr.currentModel->mdv[0]->numFrames)
- || (ent->e.oldframe < 0) ) {
- ri.Printf( PRINT_DEVELOPER, "R_AddMD3Surfaces: no such frame %d to %d for '%s'\n",
- ent->e.oldframe, ent->e.frame,
- tr.currentModel->name );
- ent->e.frame = 0;
- ent->e.oldframe = 0;
- }
-
- //
- // compute LOD
- //
- lod = R_ComputeLOD( ent );
-
- model = tr.currentModel->mdv[lod];
-
- //
- // cull the entire model if merged bounding box of both frames
- // is outside the view frustum.
- //
- cull = R_CullModel ( model, ent );
- if ( cull == CULL_OUT ) {
- return;
- }
-
- //
- // set up lighting now that we know we aren't culled
- //
- if ( !personalModel || r_shadows->integer > 1 ) {
- R_SetupEntityLighting( &tr.refdef, ent );
- }
-
- //
- // see if we are in a fog volume
- //
- fogNum = R_ComputeFogNum( model, ent );
-
- //
- // draw all surfaces
- //
- surface = model->surfaces;
- for ( i = 0 ; i < model->numSurfaces ; i++ ) {
-
- if ( ent->e.customShader ) {
- shader = R_GetShaderByHandle( ent->e.customShader );
- } else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins ) {
- skin_t *skin;
- int j;
-
- skin = R_GetSkinByHandle( ent->e.customSkin );
-
- // match the surface name to something in the skin file
- shader = tr.defaultShader;
- for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
- // the names have both been lowercased
- if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
- shader = skin->surfaces[j]->shader;
- break;
- }
- }
- if (shader == tr.defaultShader) {
- ri.Printf( PRINT_DEVELOPER, "WARNING: no shader for surface %s in skin %s\n", surface->name, skin->name);
- }
- else if (shader->defaultShader) {
- ri.Printf( PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
- }
- //} else if ( surface->numShaders <= 0 ) {
- //shader = tr.defaultShader;
- } else {
- //md3Shader = (md3Shader_t *) ( (byte *)surface + surface->ofsShaders );
- //md3Shader += ent->e.skinNum % surface->numShaders;
- //shader = tr.shaders[ md3Shader->shaderIndex ];
- shader = tr.shaders[ surface->shaderIndexes[ ent->e.skinNum % surface->numShaderIndexes ] ];
- }
-
- // don't add third_person objects if not viewing through a portal
- if(!personalModel)
- {
- srfVBOMDVMesh_t *vboSurface = &model->vboSurfaces[i];
-
- R_AddDrawSurf((void *)vboSurface, shader, fogNum, qfalse, qfalse );
- }
-
- surface++;
- }
-
-}
-
-
-
-
-
diff --git a/src/rend2/tr_model.c b/src/rend2/tr_model.c
deleted file mode 100644
index 5aeab8ef..00000000
--- a/src/rend2/tr_model.c
+++ /dev/null
@@ -1,1583 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_models.c -- model loading and caching
-
-#include "tr_local.h"
-
-#define LL(x) x=LittleLong(x)
-
-static qboolean R_LoadMD3(model_t *mod, int lod, void *buffer, int bufferSize, const char *modName);
-static qboolean R_LoadMD4(model_t *mod, void *buffer, const char *name );
-#ifdef RAVENMD4
-static qboolean R_LoadMDR(model_t *mod, void *buffer, int filesize, const char *name );
-#endif
-
-/*
-====================
-R_RegisterMD3
-====================
-*/
-qhandle_t R_RegisterMD3(const char *name, model_t *mod)
-{
- union {
- unsigned *u;
- void *v;
- } buf;
- int size;
- int lod;
- int ident;
- qboolean loaded = qfalse;
- int numLoaded;
- char filename[MAX_QPATH], namebuf[MAX_QPATH+20];
- char *fext, defex[] = "md3";
-
- numLoaded = 0;
-
- strcpy(filename, name);
-
- fext = strchr(filename, '.');
- if(!fext)
- fext = defex;
- else
- {
- *fext = '\0';
- fext++;
- }
-
- for (lod = MD3_MAX_LODS - 1 ; lod >= 0 ; lod--)
- {
- if(lod)
- Com_sprintf(namebuf, sizeof(namebuf), "%s_%d.%s", filename, lod, fext);
- else
- Com_sprintf(namebuf, sizeof(namebuf), "%s.%s", filename, fext);
-
- size = ri.FS_ReadFile( namebuf, &buf.v );
- if(!buf.u)
- continue;
-
- ident = LittleLong(* (unsigned *) buf.u);
- if (ident == MD4_IDENT)
- loaded = R_LoadMD4(mod, buf.u, name);
- else
- {
- if (ident == MD3_IDENT)
- loaded = R_LoadMD3(mod, lod, buf.u, size, name);
- else
- ri.Printf(PRINT_WARNING,"R_RegisterMD3: unknown fileid for %s\n", name);
- }
-
- ri.FS_FreeFile(buf.v);
-
- if(loaded)
- {
- mod->numLods++;
- numLoaded++;
- }
- else
- break;
- }
-
- if(numLoaded)
- {
- // duplicate into higher lod spots that weren't
- // loaded, in case the user changes r_lodbias on the fly
- for(lod--; lod >= 0; lod--)
- {
- mod->numLods++;
- mod->mdv[lod] = mod->mdv[lod + 1];
- }
-
- return mod->index;
- }
-
-#ifdef _DEBUG
- ri.Printf(PRINT_WARNING,"R_RegisterMD3: couldn't load %s\n", name);
-#endif
-
- mod->type = MOD_BAD;
- return 0;
-}
-
-#ifdef RAVENMD4
-/*
-====================
-R_RegisterMDR
-====================
-*/
-qhandle_t R_RegisterMDR(const char *name, model_t *mod)
-{
- union {
- unsigned *u;
- void *v;
- } buf;
- int ident;
- qboolean loaded = qfalse;
- int filesize;
-
- filesize = ri.FS_ReadFile(name, (void **) &buf.v);
- if(!buf.u)
- {
- mod->type = MOD_BAD;
- return 0;
- }
-
- ident = LittleLong(*(unsigned *)buf.u);
- if(ident == MDR_IDENT)
- loaded = R_LoadMDR(mod, buf.u, filesize, name);
-
- ri.FS_FreeFile (buf.v);
-
- if(!loaded)
- {
- ri.Printf(PRINT_WARNING,"R_RegisterMDR: couldn't load mdr file %s\n", name);
- mod->type = MOD_BAD;
- return 0;
- }
-
- return mod->index;
-}
-#endif
-
-/*
-====================
-R_RegisterIQM
-====================
-*/
-qhandle_t R_RegisterIQM(const char *name, model_t *mod)
-{
- union {
- unsigned *u;
- void *v;
- } buf;
- qboolean loaded = qfalse;
- int filesize;
-
- filesize = ri.FS_ReadFile(name, (void **) &buf.v);
- if(!buf.u)
- {
- mod->type = MOD_BAD;
- return 0;
- }
-
- loaded = R_LoadIQM(mod, buf.u, filesize, name);
-
- ri.FS_FreeFile (buf.v);
-
- if(!loaded)
- {
- ri.Printf(PRINT_WARNING,"R_RegisterIQM: couldn't load iqm file %s\n", name);
- mod->type = MOD_BAD;
- return 0;
- }
-
- return mod->index;
-}
-
-
-typedef struct
-{
- char *ext;
- qhandle_t (*ModelLoader)( const char *, model_t * );
-} modelExtToLoaderMap_t;
-
-// Note that the ordering indicates the order of preference used
-// when there are multiple models of different formats available
-static modelExtToLoaderMap_t modelLoaders[ ] =
-{
- { "iqm", R_RegisterIQM },
-#ifdef RAVENMD4
- { "mdr", R_RegisterMDR },
-#endif
- { "md4", R_RegisterMD3 },
- { "md3", R_RegisterMD3 }
-};
-
-static int numModelLoaders = ARRAY_LEN(modelLoaders);
-
-//===============================================================================
-
-/*
-** R_GetModelByHandle
-*/
-model_t *R_GetModelByHandle( qhandle_t index ) {
- model_t *mod;
-
- // out of range gets the defualt model
- if ( index < 1 || index >= tr.numModels ) {
- return tr.models[0];
- }
-
- mod = tr.models[index];
-
- return mod;
-}
-
-//===============================================================================
-
-/*
-** R_AllocModel
-*/
-model_t *R_AllocModel( void ) {
- model_t *mod;
-
- if ( tr.numModels == MAX_MOD_KNOWN ) {
- return NULL;
- }
-
- mod = ri.Hunk_Alloc( sizeof( *tr.models[tr.numModels] ), h_low );
- mod->index = tr.numModels;
- tr.models[tr.numModels] = mod;
- tr.numModels++;
-
- return mod;
-}
-
-/*
-====================
-RE_RegisterModel
-
-Loads in a model for the given name
-
-Zero will be returned if the model fails to load.
-An entry will be retained for failed models as an
-optimization to prevent disk rescanning if they are
-asked for again.
-====================
-*/
-qhandle_t RE_RegisterModel( const char *name ) {
- model_t *mod;
- qhandle_t hModel;
- qboolean orgNameFailed = qfalse;
- int orgLoader = -1;
- int i;
- char localName[ MAX_QPATH ];
- const char *ext;
- char altName[ MAX_QPATH ];
-
- if ( !name || !name[0] ) {
- ri.Printf( PRINT_ALL, "RE_RegisterModel: NULL name\n" );
- return 0;
- }
-
- if ( strlen( name ) >= MAX_QPATH ) {
- ri.Printf( PRINT_ALL, "Model name exceeds MAX_QPATH\n" );
- return 0;
- }
-
- //
- // search the currently loaded models
- //
- for ( hModel = 1 ; hModel < tr.numModels; hModel++ ) {
- mod = tr.models[hModel];
- if ( !strcmp( mod->name, name ) ) {
- if( mod->type == MOD_BAD ) {
- return 0;
- }
- return hModel;
- }
- }
-
- // allocate a new model_t
-
- if ( ( mod = R_AllocModel() ) == NULL ) {
- ri.Printf( PRINT_WARNING, "RE_RegisterModel: R_AllocModel() failed for '%s'\n", name);
- return 0;
- }
-
- // only set the name after the model has been successfully loaded
- Q_strncpyz( mod->name, name, sizeof( mod->name ) );
-
-
- R_IssuePendingRenderCommands();
-
- mod->type = MOD_BAD;
- mod->numLods = 0;
-
- //
- // load the files
- //
- Q_strncpyz( localName, name, MAX_QPATH );
-
- ext = COM_GetExtension( localName );
-
- if( *ext )
- {
- // Look for the correct loader and use it
- for( i = 0; i < numModelLoaders; i++ )
- {
- if( !Q_stricmp( ext, modelLoaders[ i ].ext ) )
- {
- // Load
- hModel = modelLoaders[ i ].ModelLoader( localName, mod );
- break;
- }
- }
-
- // A loader was found
- if( i < numModelLoaders )
- {
- if( !hModel )
- {
- // Loader failed, most likely because the file isn't there;
- // try again without the extension
- orgNameFailed = qtrue;
- orgLoader = i;
- COM_StripExtension( name, localName, MAX_QPATH );
- }
- else
- {
- // Something loaded
- return mod->index;
- }
- }
- }
-
- // Try and find a suitable match using all
- // the model formats supported
- for( i = 0; i < numModelLoaders; i++ )
- {
- if (i == orgLoader)
- continue;
-
- Com_sprintf( altName, sizeof (altName), "%s.%s", localName, modelLoaders[ i ].ext );
-
- // Load
- hModel = modelLoaders[ i ].ModelLoader( altName, mod );
-
- if( hModel )
- {
- if( orgNameFailed )
- {
- ri.Printf( PRINT_DEVELOPER, "WARNING: %s not present, using %s instead\n",
- name, altName );
- }
-
- break;
- }
- }
-
- return hModel;
-}
-
-/*
-=================
-R_LoadMD3
-=================
-*/
-static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize, const char *modName)
-{
- int f, i, j, k;
-
- md3Header_t *md3Model;
- md3Frame_t *md3Frame;
- md3Surface_t *md3Surf;
- md3Shader_t *md3Shader;
- md3Triangle_t *md3Tri;
- md3St_t *md3st;
- md3XyzNormal_t *md3xyz;
- md3Tag_t *md3Tag;
-
- mdvModel_t *mdvModel;
- mdvFrame_t *frame;
- mdvSurface_t *surf;//, *surface;
- int *shaderIndex;
- srfTriangle_t *tri;
- mdvVertex_t *v;
- mdvSt_t *st;
- mdvTag_t *tag;
- mdvTagName_t *tagName;
-
- int version;
- int size;
-
- md3Model = (md3Header_t *) buffer;
-
- version = LittleLong(md3Model->version);
- if(version != MD3_VERSION)
- {
- ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has wrong version (%i should be %i)\n", modName, version, MD3_VERSION);
- return qfalse;
- }
-
- mod->type = MOD_MESH;
- size = LittleLong(md3Model->ofsEnd);
- mod->dataSize += size;
- mdvModel = mod->mdv[lod] = ri.Hunk_Alloc(sizeof(mdvModel_t), h_low);
-
-// Com_Memcpy(mod->md3[lod], buffer, LittleLong(md3Model->ofsEnd));
-
- LL(md3Model->ident);
- LL(md3Model->version);
- LL(md3Model->numFrames);
- LL(md3Model->numTags);
- LL(md3Model->numSurfaces);
- LL(md3Model->ofsFrames);
- LL(md3Model->ofsTags);
- LL(md3Model->ofsSurfaces);
- LL(md3Model->ofsEnd);
-
- if(md3Model->numFrames < 1)
- {
- ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has no frames\n", modName);
- return qfalse;
- }
-
- // swap all the frames
- mdvModel->numFrames = md3Model->numFrames;
- mdvModel->frames = frame = ri.Hunk_Alloc(sizeof(*frame) * md3Model->numFrames, h_low);
-
- md3Frame = (md3Frame_t *) ((byte *) md3Model + md3Model->ofsFrames);
- for(i = 0; i < md3Model->numFrames; i++, frame++, md3Frame++)
- {
- frame->radius = LittleFloat(md3Frame->radius);
- for(j = 0; j < 3; j++)
- {
- frame->bounds[0][j] = LittleFloat(md3Frame->bounds[0][j]);
- frame->bounds[1][j] = LittleFloat(md3Frame->bounds[1][j]);
- frame->localOrigin[j] = LittleFloat(md3Frame->localOrigin[j]);
- }
- }
-
- // swap all the tags
- mdvModel->numTags = md3Model->numTags;
- mdvModel->tags = tag = ri.Hunk_Alloc(sizeof(*tag) * (md3Model->numTags * md3Model->numFrames), h_low);
-
- md3Tag = (md3Tag_t *) ((byte *) md3Model + md3Model->ofsTags);
- for(i = 0; i < md3Model->numTags * md3Model->numFrames; i++, tag++, md3Tag++)
- {
- for(j = 0; j < 3; j++)
- {
- tag->origin[j] = LittleFloat(md3Tag->origin[j]);
- tag->axis[0][j] = LittleFloat(md3Tag->axis[0][j]);
- tag->axis[1][j] = LittleFloat(md3Tag->axis[1][j]);
- tag->axis[2][j] = LittleFloat(md3Tag->axis[2][j]);
- }
- }
-
-
- mdvModel->tagNames = tagName = ri.Hunk_Alloc(sizeof(*tagName) * (md3Model->numTags), h_low);
-
- md3Tag = (md3Tag_t *) ((byte *) md3Model + md3Model->ofsTags);
- for(i = 0; i < md3Model->numTags; i++, tagName++, md3Tag++)
- {
- Q_strncpyz(tagName->name, md3Tag->name, sizeof(tagName->name));
- }
-
- // swap all the surfaces
- mdvModel->numSurfaces = md3Model->numSurfaces;
- mdvModel->surfaces = surf = ri.Hunk_Alloc(sizeof(*surf) * md3Model->numSurfaces, h_low);
-
- md3Surf = (md3Surface_t *) ((byte *) md3Model + md3Model->ofsSurfaces);
- for(i = 0; i < md3Model->numSurfaces; i++)
- {
- LL(md3Surf->ident);
- LL(md3Surf->flags);
- LL(md3Surf->numFrames);
- LL(md3Surf->numShaders);
- LL(md3Surf->numTriangles);
- LL(md3Surf->ofsTriangles);
- LL(md3Surf->numVerts);
- LL(md3Surf->ofsShaders);
- LL(md3Surf->ofsSt);
- LL(md3Surf->ofsXyzNormals);
- LL(md3Surf->ofsEnd);
-
- if(md3Surf->numVerts > SHADER_MAX_VERTEXES)
- {
- ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has more than %i verts on a surface (%i)",
- modName, SHADER_MAX_VERTEXES, md3Surf->numVerts);
- return qfalse;
- }
- if(md3Surf->numTriangles * 3 > SHADER_MAX_INDEXES)
- {
- ri.Printf(PRINT_WARNING, "R_LoadMD3: %s has more than %i triangles on a surface (%i)",
- modName, SHADER_MAX_INDEXES / 3, md3Surf->numTriangles);
- return qfalse;
- }
-
- // change to surface identifier
- surf->surfaceType = SF_MDV;
-
- // give pointer to model for Tess_SurfaceMDX
- surf->model = mdvModel;
-
- // copy surface name
- Q_strncpyz(surf->name, md3Surf->name, sizeof(surf->name));
-
- // lowercase the surface name so skin compares are faster
- Q_strlwr(surf->name);
-
- // strip off a trailing _1 or _2
- // this is a crutch for q3data being a mess
- j = strlen(surf->name);
- if(j > 2 && surf->name[j - 2] == '_')
- {
- surf->name[j - 2] = 0;
- }
-
- // register the shaders
- surf->numShaderIndexes = md3Surf->numShaders;
- surf->shaderIndexes = shaderIndex = ri.Hunk_Alloc(sizeof(*shaderIndex) * md3Surf->numShaders, h_low);
-
- md3Shader = (md3Shader_t *) ((byte *) md3Surf + md3Surf->ofsShaders);
- for(j = 0; j < md3Surf->numShaders; j++, shaderIndex++, md3Shader++)
- {
- shader_t *sh;
-
- sh = R_FindShader(md3Shader->name, LIGHTMAP_NONE, qtrue);
- if(sh->defaultShader)
- {
- *shaderIndex = 0;
- }
- else
- {
- *shaderIndex = sh->index;
- }
- }
-
- // swap all the triangles
- surf->numTriangles = md3Surf->numTriangles;
- surf->triangles = tri = ri.Hunk_Alloc(sizeof(*tri) * md3Surf->numTriangles, h_low);
-
- md3Tri = (md3Triangle_t *) ((byte *) md3Surf + md3Surf->ofsTriangles);
- for(j = 0; j < md3Surf->numTriangles; j++, tri++, md3Tri++)
- {
- tri->indexes[0] = LittleLong(md3Tri->indexes[0]);
- tri->indexes[1] = LittleLong(md3Tri->indexes[1]);
- tri->indexes[2] = LittleLong(md3Tri->indexes[2]);
- }
-
- R_CalcSurfaceTriangleNeighbors(surf->numTriangles, surf->triangles);
-
- // swap all the XyzNormals
- surf->numVerts = md3Surf->numVerts;
- surf->verts = v = ri.Hunk_Alloc(sizeof(*v) * (md3Surf->numVerts * md3Surf->numFrames), h_low);
-
- md3xyz = (md3XyzNormal_t *) ((byte *) md3Surf + md3Surf->ofsXyzNormals);
- for(j = 0; j < md3Surf->numVerts * md3Surf->numFrames; j++, md3xyz++, v++)
- {
- unsigned lat, lng;
- unsigned short normal;
-
- v->xyz[0] = LittleShort(md3xyz->xyz[0]) * MD3_XYZ_SCALE;
- v->xyz[1] = LittleShort(md3xyz->xyz[1]) * MD3_XYZ_SCALE;
- v->xyz[2] = LittleShort(md3xyz->xyz[2]) * MD3_XYZ_SCALE;
-
- normal = LittleShort(md3xyz->normal);
-
- lat = ( normal >> 8 ) & 0xff;
- lng = ( normal & 0xff );
- lat *= (FUNCTABLE_SIZE/256);
- lng *= (FUNCTABLE_SIZE/256);
-
- // decode X as cos( lat ) * sin( long )
- // decode Y as sin( lat ) * sin( long )
- // decode Z as cos( long )
-
- v->normal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
- v->normal[1] = tr.sinTable[lat] * tr.sinTable[lng];
- v->normal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
- }
-
- // swap all the ST
- surf->st = st = ri.Hunk_Alloc(sizeof(*st) * md3Surf->numVerts, h_low);
-
- md3st = (md3St_t *) ((byte *) md3Surf + md3Surf->ofsSt);
- for(j = 0; j < md3Surf->numVerts; j++, md3st++, st++)
- {
- st->st[0] = LittleFloat(md3st->st[0]);
- st->st[1] = LittleFloat(md3st->st[1]);
- }
-
-#ifdef USE_VERT_TANGENT_SPACE
- // calc tangent spaces
- {
- // Valgrind complaints: Conditional jump or move depends on uninitialised value(s)
- // So lets Initialize them.
- const float *v0 = NULL, *v1 = NULL, *v2 = NULL;
- const float *t0 = NULL, *t1 = NULL, *t2 = NULL;
- vec3_t tangent = { 0, 0, 0 };
- vec3_t bitangent = { 0, 0, 0 };
- vec3_t normal = { 0, 0, 0 };
-
- for(j = 0, v = surf->verts; j < (surf->numVerts * mdvModel->numFrames); j++, v++)
- {
- VectorClear(v->tangent);
- VectorClear(v->bitangent);
- if (r_recalcMD3Normals->integer)
- VectorClear(v->normal);
- }
-
- for(f = 0; f < mdvModel->numFrames; f++)
- {
- for(j = 0, tri = surf->triangles; j < surf->numTriangles; j++, tri++)
- {
- v0 = surf->verts[surf->numVerts * f + tri->indexes[0]].xyz;
- v1 = surf->verts[surf->numVerts * f + tri->indexes[1]].xyz;
- v2 = surf->verts[surf->numVerts * f + tri->indexes[2]].xyz;
-
- t0 = surf->st[tri->indexes[0]].st;
- t1 = surf->st[tri->indexes[1]].st;
- t2 = surf->st[tri->indexes[2]].st;
-
- if (!r_recalcMD3Normals->integer)
- VectorCopy(v->normal, normal);
- else
- VectorClear(normal);
-
- #if 1
- R_CalcTangentSpace(tangent, bitangent, normal, v0, v1, v2, t0, t1, t2);
- #else
- R_CalcNormalForTriangle(normal, v0, v1, v2);
- R_CalcTangentsForTriangle(tangent, bitangent, v0, v1, v2, t0, t1, t2);
- #endif
-
- for(k = 0; k < 3; k++)
- {
- float *v;
-
- v = surf->verts[surf->numVerts * f + tri->indexes[k]].tangent;
- VectorAdd(v, tangent, v);
-
- v = surf->verts[surf->numVerts * f + tri->indexes[k]].bitangent;
- VectorAdd(v, bitangent, v);
-
- if (r_recalcMD3Normals->integer)
- {
- v = surf->verts[surf->numVerts * f + tri->indexes[k]].normal;
- VectorAdd(v, normal, v);
- }
- }
- }
- }
-
- for(j = 0, v = surf->verts; j < (surf->numVerts * mdvModel->numFrames); j++, v++)
- {
- VectorNormalize(v->tangent);
- VectorNormalize(v->bitangent);
- VectorNormalize(v->normal);
- }
- }
-#endif
-
- // find the next surface
- md3Surf = (md3Surface_t *) ((byte *) md3Surf + md3Surf->ofsEnd);
- surf++;
- }
-
- {
- srfVBOMDVMesh_t *vboSurf;
-
- mdvModel->numVBOSurfaces = mdvModel->numSurfaces;
- mdvModel->vboSurfaces = ri.Hunk_Alloc(sizeof(*mdvModel->vboSurfaces) * mdvModel->numSurfaces, h_low);
-
- vboSurf = mdvModel->vboSurfaces;
- surf = mdvModel->surfaces;
- for (i = 0; i < mdvModel->numSurfaces; i++, vboSurf++, surf++)
- {
- vec3_t *verts;
- vec3_t *normals;
- vec2_t *texcoords;
-#ifdef USE_VERT_TANGENT_SPACE
- vec3_t *tangents;
- vec3_t *bitangents;
-#endif
-
- byte *data;
- int dataSize;
-
- int ofs_xyz, ofs_normal, ofs_st;
-#ifdef USE_VERT_TANGENT_SPACE
- int ofs_tangent, ofs_bitangent;
-#endif
-
- dataSize = 0;
-
- ofs_xyz = dataSize;
- dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*verts);
-
- ofs_normal = dataSize;
- dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*normals);
-
-#ifdef USE_VERT_TANGENT_SPACE
- ofs_tangent = dataSize;
- dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*tangents);
-
- ofs_bitangent = dataSize;
- dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*bitangents);
-#endif
-
- ofs_st = dataSize;
- dataSize += surf->numVerts * sizeof(*texcoords);
-
- data = ri.Malloc(dataSize);
-
- verts = (void *)(data + ofs_xyz);
- normals = (void *)(data + ofs_normal);
-#ifdef USE_VERT_TANGENT_SPACE
- tangents = (void *)(data + ofs_tangent);
- bitangents = (void *)(data + ofs_bitangent);
-#endif
- texcoords = (void *)(data + ofs_st);
-
- v = surf->verts;
- for ( j = 0; j < surf->numVerts * mdvModel->numFrames ; j++, v++ )
- {
- VectorCopy(v->xyz, verts[j]);
- VectorCopy(v->normal, normals[j]);
-#ifdef USE_VERT_TANGENT_SPACE
- VectorCopy(v->tangent, tangents[j]);
- VectorCopy(v->bitangent, bitangents[j]);
-#endif
- }
-
- st = surf->st;
- for ( j = 0 ; j < surf->numVerts ; j++, st++ ) {
- texcoords[j][0] = st->st[0];
- texcoords[j][1] = st->st[1];
- }
-
- vboSurf->surfaceType = SF_VBO_MDVMESH;
- vboSurf->mdvModel = mdvModel;
- vboSurf->mdvSurface = surf;
- vboSurf->numIndexes = surf->numTriangles * 3;
- vboSurf->numVerts = surf->numVerts;
-
- vboSurf->minIndex = 0;
- vboSurf->maxIndex = surf->numVerts;
-
- vboSurf->vbo = R_CreateVBO(va("staticMD3Mesh_VBO '%s'", surf->name), data, dataSize, VBO_USAGE_STATIC);
-
- vboSurf->vbo->ofs_xyz = ofs_xyz;
- vboSurf->vbo->ofs_normal = ofs_normal;
-#ifdef USE_VERT_TANGENT_SPACE
- vboSurf->vbo->ofs_tangent = ofs_tangent;
- vboSurf->vbo->ofs_bitangent = ofs_bitangent;
-#endif
- vboSurf->vbo->ofs_st = ofs_st;
-
- vboSurf->vbo->stride_xyz = sizeof(*verts);
- vboSurf->vbo->stride_normal = sizeof(*normals);
-#ifdef USE_VERT_TANGENT_SPACE
- vboSurf->vbo->stride_tangent = sizeof(*tangents);
- vboSurf->vbo->stride_bitangent = sizeof(*bitangents);
-#endif
- vboSurf->vbo->stride_st = sizeof(*st);
-
- vboSurf->vbo->size_xyz = sizeof(*verts) * surf->numVerts;
- vboSurf->vbo->size_normal = sizeof(*normals) * surf->numVerts;
-
- ri.Free(data);
-
- vboSurf->ibo = R_CreateIBO2(va("staticMD3Mesh_IBO %s", surf->name), surf->numTriangles, surf->triangles, VBO_USAGE_STATIC);
- }
- }
-
- return qtrue;
-}
-
-
-#ifdef RAVENMD4
-
-/*
-=================
-R_LoadMDR
-=================
-*/
-static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char *mod_name )
-{
- int i, j, k, l;
- mdrHeader_t *pinmodel, *mdr;
- mdrFrame_t *frame;
- mdrLOD_t *lod, *curlod;
- mdrSurface_t *surf, *cursurf;
- mdrTriangle_t *tri, *curtri;
- mdrVertex_t *v, *curv;
- mdrWeight_t *weight, *curweight;
- mdrTag_t *tag, *curtag;
- int size;
- shader_t *sh;
-
- pinmodel = (mdrHeader_t *)buffer;
-
- pinmodel->version = LittleLong(pinmodel->version);
- if (pinmodel->version != MDR_VERSION)
- {
- ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has wrong version (%i should be %i)\n", mod_name, pinmodel->version, MDR_VERSION);
- return qfalse;
- }
-
- size = LittleLong(pinmodel->ofsEnd);
-
- if(size > filesize)
- {
- ri.Printf(PRINT_WARNING, "R_LoadMDR: Header of %s is broken. Wrong filesize declared!\n", mod_name);
- return qfalse;
- }
-
- mod->type = MOD_MDR;
-
- LL(pinmodel->numFrames);
- LL(pinmodel->numBones);
- LL(pinmodel->ofsFrames);
-
- // This is a model that uses some type of compressed Bones. We don't want to uncompress every bone for each rendered frame
- // over and over again, we'll uncompress it in this function already, so we must adjust the size of the target md4.
- if(pinmodel->ofsFrames < 0)
- {
- // mdrFrame_t is larger than mdrCompFrame_t:
- size += pinmodel->numFrames * sizeof(frame->name);
- // now add enough space for the uncompressed bones.
- size += pinmodel->numFrames * pinmodel->numBones * ((sizeof(mdrBone_t) - sizeof(mdrCompBone_t)));
- }
-
- // simple bounds check
- if(pinmodel->numBones < 0 ||
- sizeof(*mdr) + pinmodel->numFrames * (sizeof(*frame) + (pinmodel->numBones - 1) * sizeof(*frame->bones)) > size)
- {
- ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name);
- return qfalse;
- }
-
- mod->dataSize += size;
- mod->modelData = mdr = ri.Hunk_Alloc( size, h_low );
-
- // Copy all the values over from the file and fix endian issues in the process, if necessary.
-
- mdr->ident = LittleLong(pinmodel->ident);
- mdr->version = pinmodel->version; // Don't need to swap byte order on this one, we already did above.
- Q_strncpyz(mdr->name, pinmodel->name, sizeof(mdr->name));
- mdr->numFrames = pinmodel->numFrames;
- mdr->numBones = pinmodel->numBones;
- mdr->numLODs = LittleLong(pinmodel->numLODs);
- mdr->numTags = LittleLong(pinmodel->numTags);
- // We don't care about the other offset values, we'll generate them ourselves while loading.
-
- mod->numLods = mdr->numLODs;
-
- if ( mdr->numFrames < 1 )
- {
- ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has no frames\n", mod_name);
- return qfalse;
- }
-
- /* The first frame will be put into the first free space after the header */
- frame = (mdrFrame_t *)(mdr + 1);
- mdr->ofsFrames = (int)((byte *) frame - (byte *) mdr);
-
- if (pinmodel->ofsFrames < 0)
- {
- mdrCompFrame_t *cframe;
-
- // compressed model...
- cframe = (mdrCompFrame_t *)((byte *) pinmodel - pinmodel->ofsFrames);
-
- for(i = 0; i < mdr->numFrames; i++)
- {
- for(j = 0; j < 3; j++)
- {
- frame->bounds[0][j] = LittleFloat(cframe->bounds[0][j]);
- frame->bounds[1][j] = LittleFloat(cframe->bounds[1][j]);
- frame->localOrigin[j] = LittleFloat(cframe->localOrigin[j]);
- }
-
- frame->radius = LittleFloat(cframe->radius);
- frame->name[0] = '\0'; // No name supplied in the compressed version.
-
- for(j = 0; j < mdr->numBones; j++)
- {
- for(k = 0; k < (sizeof(cframe->bones[j].Comp) / 2); k++)
- {
- // Do swapping for the uncompressing functions. They seem to use shorts
- // values only, so I assume this will work. Never tested it on other
- // platforms, though.
-
- ((unsigned short *)(cframe->bones[j].Comp))[k] =
- LittleShort( ((unsigned short *)(cframe->bones[j].Comp))[k] );
- }
-
- /* Now do the actual uncompressing */
- MC_UnCompress(frame->bones[j].matrix, cframe->bones[j].Comp);
- }
-
- // Next Frame...
- cframe = (mdrCompFrame_t *) &cframe->bones[j];
- frame = (mdrFrame_t *) &frame->bones[j];
- }
- }
- else
- {
- mdrFrame_t *curframe;
-
- // uncompressed model...
- //
-
- curframe = (mdrFrame_t *)((byte *) pinmodel + pinmodel->ofsFrames);
-
- // swap all the frames
- for ( i = 0 ; i < mdr->numFrames ; i++)
- {
- for(j = 0; j < 3; j++)
- {
- frame->bounds[0][j] = LittleFloat(curframe->bounds[0][j]);
- frame->bounds[1][j] = LittleFloat(curframe->bounds[1][j]);
- frame->localOrigin[j] = LittleFloat(curframe->localOrigin[j]);
- }
-
- frame->radius = LittleFloat(curframe->radius);
- Q_strncpyz(frame->name, curframe->name, sizeof(frame->name));
-
- for (j = 0; j < (int) (mdr->numBones * sizeof(mdrBone_t) / 4); j++)
- {
- ((float *)frame->bones)[j] = LittleFloat( ((float *)curframe->bones)[j] );
- }
-
- curframe = (mdrFrame_t *) &curframe->bones[mdr->numBones];
- frame = (mdrFrame_t *) &frame->bones[mdr->numBones];
- }
- }
-
- // frame should now point to the first free address after all frames.
- lod = (mdrLOD_t *) frame;
- mdr->ofsLODs = (int) ((byte *) lod - (byte *)mdr);
-
- curlod = (mdrLOD_t *)((byte *) pinmodel + LittleLong(pinmodel->ofsLODs));
-
- // swap all the LOD's
- for ( l = 0 ; l < mdr->numLODs ; l++)
- {
- // simple bounds check
- if((byte *) (lod + 1) > (byte *) mdr + size)
- {
- ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name);
- return qfalse;
- }
-
- lod->numSurfaces = LittleLong(curlod->numSurfaces);
-
- // swap all the surfaces
- surf = (mdrSurface_t *) (lod + 1);
- lod->ofsSurfaces = (int)((byte *) surf - (byte *) lod);
- cursurf = (mdrSurface_t *) ((byte *)curlod + LittleLong(curlod->ofsSurfaces));
-
- for ( i = 0 ; i < lod->numSurfaces ; i++)
- {
- // simple bounds check
- if((byte *) (surf + 1) > (byte *) mdr + size)
- {
- ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name);
- return qfalse;
- }
-
- // first do some copying stuff
-
- surf->ident = SF_MDR;
- Q_strncpyz(surf->name, cursurf->name, sizeof(surf->name));
- Q_strncpyz(surf->shader, cursurf->shader, sizeof(surf->shader));
-
- surf->ofsHeader = (byte *) mdr - (byte *) surf;
-
- surf->numVerts = LittleLong(cursurf->numVerts);
- surf->numTriangles = LittleLong(cursurf->numTriangles);
- // numBoneReferences and BoneReferences generally seem to be unused
-
- // now do the checks that may fail.
- if ( surf->numVerts > SHADER_MAX_VERTEXES )
- {
- ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i verts on a surface (%i).\n",
- mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
- return qfalse;
- }
- if ( surf->numTriangles*3 > SHADER_MAX_INDEXES )
- {
- ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has more than %i triangles on a surface (%i).\n",
- mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
- return qfalse;
- }
- // lowercase the surface name so skin compares are faster
- Q_strlwr( surf->name );
-
- // register the shaders
- sh = R_FindShader(surf->shader, LIGHTMAP_NONE, qtrue);
- if ( sh->defaultShader ) {
- surf->shaderIndex = 0;
- } else {
- surf->shaderIndex = sh->index;
- }
-
- // now copy the vertexes.
- v = (mdrVertex_t *) (surf + 1);
- surf->ofsVerts = (int)((byte *) v - (byte *) surf);
- curv = (mdrVertex_t *) ((byte *)cursurf + LittleLong(cursurf->ofsVerts));
-
- for(j = 0; j < surf->numVerts; j++)
- {
- LL(curv->numWeights);
-
- // simple bounds check
- if(curv->numWeights < 0 || (byte *) (v + 1) + (curv->numWeights - 1) * sizeof(*weight) > (byte *) mdr + size)
- {
- ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name);
- return qfalse;
- }
-
- v->normal[0] = LittleFloat(curv->normal[0]);
- v->normal[1] = LittleFloat(curv->normal[1]);
- v->normal[2] = LittleFloat(curv->normal[2]);
-
- v->texCoords[0] = LittleFloat(curv->texCoords[0]);
- v->texCoords[1] = LittleFloat(curv->texCoords[1]);
-
- v->numWeights = curv->numWeights;
- weight = &v->weights[0];
- curweight = &curv->weights[0];
-
- // Now copy all the weights
- for(k = 0; k < v->numWeights; k++)
- {
- weight->boneIndex = LittleLong(curweight->boneIndex);
- weight->boneWeight = LittleFloat(curweight->boneWeight);
-
- weight->offset[0] = LittleFloat(curweight->offset[0]);
- weight->offset[1] = LittleFloat(curweight->offset[1]);
- weight->offset[2] = LittleFloat(curweight->offset[2]);
-
- weight++;
- curweight++;
- }
-
- v = (mdrVertex_t *) weight;
- curv = (mdrVertex_t *) curweight;
- }
-
- // we know the offset to the triangles now:
- tri = (mdrTriangle_t *) v;
- surf->ofsTriangles = (int)((byte *) tri - (byte *) surf);
- curtri = (mdrTriangle_t *)((byte *) cursurf + LittleLong(cursurf->ofsTriangles));
-
- // simple bounds check
- if(surf->numTriangles < 0 || (byte *) (tri + surf->numTriangles) > (byte *) mdr + size)
- {
- ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name);
- return qfalse;
- }
-
- for(j = 0; j < surf->numTriangles; j++)
- {
- tri->indexes[0] = LittleLong(curtri->indexes[0]);
- tri->indexes[1] = LittleLong(curtri->indexes[1]);
- tri->indexes[2] = LittleLong(curtri->indexes[2]);
-
- tri++;
- curtri++;
- }
-
- // tri now points to the end of the surface.
- surf->ofsEnd = (byte *) tri - (byte *) surf;
- surf = (mdrSurface_t *) tri;
-
- // find the next surface.
- cursurf = (mdrSurface_t *) ((byte *) cursurf + LittleLong(cursurf->ofsEnd));
- }
-
- // surf points to the next lod now.
- lod->ofsEnd = (int)((byte *) surf - (byte *) lod);
- lod = (mdrLOD_t *) surf;
-
- // find the next LOD.
- curlod = (mdrLOD_t *)((byte *) curlod + LittleLong(curlod->ofsEnd));
- }
-
- // lod points to the first tag now, so update the offset too.
- tag = (mdrTag_t *) lod;
- mdr->ofsTags = (int)((byte *) tag - (byte *) mdr);
- curtag = (mdrTag_t *) ((byte *)pinmodel + LittleLong(pinmodel->ofsTags));
-
- // simple bounds check
- if(mdr->numTags < 0 || (byte *) (tag + mdr->numTags) > (byte *) mdr + size)
- {
- ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name);
- return qfalse;
- }
-
- for (i = 0 ; i < mdr->numTags ; i++)
- {
- tag->boneIndex = LittleLong(curtag->boneIndex);
- Q_strncpyz(tag->name, curtag->name, sizeof(tag->name));
-
- tag++;
- curtag++;
- }
-
- // And finally we know the real offset to the end.
- mdr->ofsEnd = (int)((byte *) tag - (byte *) mdr);
-
- // phew! we're done.
-
- return qtrue;
-}
-#endif
-
-/*
-=================
-R_LoadMD4
-=================
-*/
-
-static qboolean R_LoadMD4( model_t *mod, void *buffer, const char *mod_name ) {
- int i, j, k, lodindex;
- md4Header_t *pinmodel, *md4;
- md4Frame_t *frame;
- md4LOD_t *lod;
- md4Surface_t *surf;
- md4Triangle_t *tri;
- md4Vertex_t *v;
- int version;
- int size;
- shader_t *sh;
- int frameSize;
-
- pinmodel = (md4Header_t *)buffer;
-
- version = LittleLong (pinmodel->version);
- if (version != MD4_VERSION) {
- ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has wrong version (%i should be %i)\n",
- mod_name, version, MD4_VERSION);
- return qfalse;
- }
-
- mod->type = MOD_MD4;
- size = LittleLong(pinmodel->ofsEnd);
- mod->dataSize += size;
- mod->modelData = md4 = ri.Hunk_Alloc( size, h_low );
-
- Com_Memcpy(md4, buffer, size);
-
- LL(md4->ident);
- LL(md4->version);
- LL(md4->numFrames);
- LL(md4->numBones);
- LL(md4->numLODs);
- LL(md4->ofsFrames);
- LL(md4->ofsLODs);
- md4->ofsEnd = size;
-
- if ( md4->numFrames < 1 ) {
- ri.Printf( PRINT_WARNING, "R_LoadMD4: %s has no frames\n", mod_name );
- return qfalse;
- }
-
- // we don't need to swap tags in the renderer, they aren't used
-
- // swap all the frames
- frameSize = (size_t)( &((md4Frame_t *)0)->bones[ md4->numBones ] );
- for ( i = 0 ; i < md4->numFrames ; i++) {
- frame = (md4Frame_t *) ( (byte *)md4 + md4->ofsFrames + i * frameSize );
- frame->radius = LittleFloat( frame->radius );
- for ( j = 0 ; j < 3 ; j++ ) {
- frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] );
- frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] );
- frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] );
- }
- for ( j = 0 ; j < md4->numBones * sizeof( md4Bone_t ) / 4 ; j++ ) {
- ((float *)frame->bones)[j] = LittleFloat( ((float *)frame->bones)[j] );
- }
- }
-
- // swap all the LOD's
- lod = (md4LOD_t *) ( (byte *)md4 + md4->ofsLODs );
- for ( lodindex = 0 ; lodindex < md4->numLODs ; lodindex++ ) {
-
- // swap all the surfaces
- surf = (md4Surface_t *) ( (byte *)lod + lod->ofsSurfaces );
- for ( i = 0 ; i < lod->numSurfaces ; i++) {
- LL(surf->ident);
- LL(surf->numTriangles);
- LL(surf->ofsTriangles);
- LL(surf->numVerts);
- LL(surf->ofsVerts);
- LL(surf->ofsEnd);
-
- if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
- ri.Printf(PRINT_WARNING, "R_LoadMD4: %s has more than %i verts on a surface (%i).\n",
- mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
- return qfalse;
- }
- if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
- ri.Printf(PRINT_WARNING, "R_LoadMD4: %s has more than %i triangles on a surface (%i).\n",
- mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
- return qfalse;
- }
-
- // change to surface identifier
- surf->ident = SF_MD4;
-
- // lowercase the surface name so skin compares are faster
- Q_strlwr( surf->name );
-
- // register the shaders
- sh = R_FindShader( surf->shader, LIGHTMAP_NONE, qtrue );
- if ( sh->defaultShader ) {
- surf->shaderIndex = 0;
- } else {
- surf->shaderIndex = sh->index;
- }
-
- // swap all the triangles
- tri = (md4Triangle_t *) ( (byte *)surf + surf->ofsTriangles );
- for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) {
- LL(tri->indexes[0]);
- LL(tri->indexes[1]);
- LL(tri->indexes[2]);
- }
-
- // swap all the vertexes
- // FIXME
- // This makes TFC's skeletons work. Shouldn't be necessary anymore, but left
- // in for reference.
- //v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts + 12);
- v = (md4Vertex_t *) ( (byte *)surf + surf->ofsVerts);
- for ( j = 0 ; j < surf->numVerts ; j++ ) {
- v->normal[0] = LittleFloat( v->normal[0] );
- v->normal[1] = LittleFloat( v->normal[1] );
- v->normal[2] = LittleFloat( v->normal[2] );
-
- v->texCoords[0] = LittleFloat( v->texCoords[0] );
- v->texCoords[1] = LittleFloat( v->texCoords[1] );
-
- v->numWeights = LittleLong( v->numWeights );
-
- for ( k = 0 ; k < v->numWeights ; k++ ) {
- v->weights[k].boneIndex = LittleLong( v->weights[k].boneIndex );
- v->weights[k].boneWeight = LittleFloat( v->weights[k].boneWeight );
- v->weights[k].offset[0] = LittleFloat( v->weights[k].offset[0] );
- v->weights[k].offset[1] = LittleFloat( v->weights[k].offset[1] );
- v->weights[k].offset[2] = LittleFloat( v->weights[k].offset[2] );
- }
- // FIXME
- // This makes TFC's skeletons work. Shouldn't be necessary anymore, but left
- // in for reference.
- //v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights] + 12 );
- v = (md4Vertex_t *)( ( byte * )&v->weights[v->numWeights]);
- }
-
- // find the next surface
- surf = (md4Surface_t *)( (byte *)surf + surf->ofsEnd );
- }
-
- // find the next LOD
- lod = (md4LOD_t *)( (byte *)lod + lod->ofsEnd );
- }
-
- return qtrue;
-}
-
-
-
-//=============================================================================
-
-/*
-** RE_BeginRegistration
-*/
-void RE_BeginRegistration( glconfig_t *glconfigOut ) {
-
- R_Init();
-
- *glconfigOut = glConfig;
-
- R_IssuePendingRenderCommands();
-
- tr.visIndex = 0;
- memset(tr.visClusters, -2, sizeof(tr.visClusters)); // force markleafs to regenerate
-
- R_ClearFlares();
- RE_ClearScene();
-
- tr.registered = qtrue;
-
- // NOTE: this sucks, for some reason the first stretch pic is never drawn
- // without this we'd see a white flash on a level load because the very
- // first time the level shot would not be drawn
-// RE_StretchPic(0, 0, 0, 0, 0, 0, 1, 1, 0);
-}
-
-//=============================================================================
-
-/*
-===============
-R_ModelInit
-===============
-*/
-void R_ModelInit( void ) {
- model_t *mod;
-
- // leave a space for NULL model
- tr.numModels = 0;
-
- mod = R_AllocModel();
- mod->type = MOD_BAD;
-}
-
-
-/*
-================
-R_Modellist_f
-================
-*/
-void R_Modellist_f( void ) {
- int i, j;
- model_t *mod;
- int total;
- int lods;
-
- total = 0;
- for ( i = 1 ; i < tr.numModels; i++ ) {
- mod = tr.models[i];
- lods = 1;
- for ( j = 1 ; j < MD3_MAX_LODS ; j++ ) {
- if ( mod->mdv[j] && mod->mdv[j] != mod->mdv[j-1] ) {
- lods++;
- }
- }
- ri.Printf( PRINT_ALL, "%8i : (%i) %s\n",mod->dataSize, lods, mod->name );
- total += mod->dataSize;
- }
- ri.Printf( PRINT_ALL, "%8i : Total models\n", total );
-
-#if 0 // not working right with new hunk
- if ( tr.world ) {
- ri.Printf( PRINT_ALL, "\n%8i : %s\n", tr.world->dataSize, tr.world->name );
- }
-#endif
-}
-
-
-//=============================================================================
-
-
-/*
-================
-R_GetTag
-================
-*/
-static mdvTag_t *R_GetTag( mdvModel_t *mod, int frame, const char *_tagName ) {
- int i;
- mdvTag_t *tag;
- mdvTagName_t *tagName;
-
- if ( frame >= mod->numFrames ) {
- // it is possible to have a bad frame while changing models, so don't error
- frame = mod->numFrames - 1;
- }
-
- tag = mod->tags + frame * mod->numTags;
- tagName = mod->tagNames;
- for(i = 0; i < mod->numTags; i++, tag++, tagName++)
- {
- if(!strcmp(tagName->name, _tagName))
- {
- return tag;
- }
- }
-
- return NULL;
-}
-
-#ifdef RAVENMD4
-void R_GetAnimTag( mdrHeader_t *mod, int framenum, const char *tagName, md3Tag_t * dest)
-{
- int i, j, k;
- int frameSize;
- mdrFrame_t *frame;
- mdrTag_t *tag;
-
- if ( framenum >= mod->numFrames )
- {
- // it is possible to have a bad frame while changing models, so don't error
- framenum = mod->numFrames - 1;
- }
-
- tag = (mdrTag_t *)((byte *)mod + mod->ofsTags);
- for ( i = 0 ; i < mod->numTags ; i++, tag++ )
- {
- if ( !strcmp( tag->name, tagName ) )
- {
- Q_strncpyz(dest->name, tag->name, sizeof(dest->name));
-
- // uncompressed model...
- //
- frameSize = (intptr_t)( &((mdrFrame_t *)0)->bones[ mod->numBones ] );
- frame = (mdrFrame_t *)((byte *)mod + mod->ofsFrames + framenum * frameSize );
-
- for (j = 0; j < 3; j++)
- {
- for (k = 0; k < 3; k++)
- dest->axis[j][k]=frame->bones[tag->boneIndex].matrix[k][j];
- }
-
- dest->origin[0]=frame->bones[tag->boneIndex].matrix[0][3];
- dest->origin[1]=frame->bones[tag->boneIndex].matrix[1][3];
- dest->origin[2]=frame->bones[tag->boneIndex].matrix[2][3];
-
- return;
- }
- }
-
- AxisClear( dest->axis );
- VectorClear( dest->origin );
- strcpy(dest->name,"");
-}
-#endif
-
-/*
-================
-R_LerpTag
-================
-*/
-int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame,
- float frac, const char *tagName ) {
- mdvTag_t *start, *end;
-#ifdef RAVENMD4
- md3Tag_t start_space, end_space;
-#endif
- int i;
- float frontLerp, backLerp;
- model_t *model;
-
- model = R_GetModelByHandle( handle );
- if ( !model->mdv[0] )
- {
-#ifdef RAVENMD4
- if(model->type == MOD_MDR)
- {
- start = &start_space;
- end = &end_space;
- R_GetAnimTag((mdrHeader_t *) model->modelData, startFrame, tagName, start);
- R_GetAnimTag((mdrHeader_t *) model->modelData, endFrame, tagName, end);
- }
- else
-#endif
- if( model->type == MOD_IQM ) {
- return R_IQMLerpTag( tag, model->modelData,
- startFrame, endFrame,
- frac, tagName );
- } else {
-
- AxisClear( tag->axis );
- VectorClear( tag->origin );
- return qfalse;
-
- }
- }
- else
- {
- start = R_GetTag( model->mdv[0], startFrame, tagName );
- end = R_GetTag( model->mdv[0], endFrame, tagName );
- if ( !start || !end ) {
- AxisClear( tag->axis );
- VectorClear( tag->origin );
- return qfalse;
- }
- }
-
- frontLerp = frac;
- backLerp = 1.0f - frac;
-
- for ( i = 0 ; i < 3 ; i++ ) {
- tag->origin[i] = start->origin[i] * backLerp + end->origin[i] * frontLerp;
- tag->axis[0][i] = start->axis[0][i] * backLerp + end->axis[0][i] * frontLerp;
- tag->axis[1][i] = start->axis[1][i] * backLerp + end->axis[1][i] * frontLerp;
- tag->axis[2][i] = start->axis[2][i] * backLerp + end->axis[2][i] * frontLerp;
- }
- VectorNormalize( tag->axis[0] );
- VectorNormalize( tag->axis[1] );
- VectorNormalize( tag->axis[2] );
- return qtrue;
-}
-
-
-/*
-====================
-R_ModelBounds
-====================
-*/
-void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ) {
- model_t *model;
-
- model = R_GetModelByHandle( handle );
-
- if(model->type == MOD_BRUSH) {
- VectorCopy( model->bmodel->bounds[0], mins );
- VectorCopy( model->bmodel->bounds[1], maxs );
-
- return;
- } else if (model->type == MOD_MESH) {
- mdvModel_t *header;
- mdvFrame_t *frame;
-
- header = model->mdv[0];
- frame = header->frames;
-
- VectorCopy( frame->bounds[0], mins );
- VectorCopy( frame->bounds[1], maxs );
-
- return;
- } else if (model->type == MOD_MD4) {
- md4Header_t *header;
- md4Frame_t *frame;
-
- header = (md4Header_t *)model->modelData;
- frame = (md4Frame_t *) ((byte *)header + header->ofsFrames);
-
- VectorCopy( frame->bounds[0], mins );
- VectorCopy( frame->bounds[1], maxs );
-
- return;
-#ifdef RAVENMD4
- } else if (model->type == MOD_MDR) {
- mdrHeader_t *header;
- mdrFrame_t *frame;
-
- header = (mdrHeader_t *)model->modelData;
- frame = (mdrFrame_t *) ((byte *)header + header->ofsFrames);
-
- VectorCopy( frame->bounds[0], mins );
- VectorCopy( frame->bounds[1], maxs );
-
- return;
-#endif
- } else if(model->type == MOD_IQM) {
- iqmData_t *iqmData;
-
- iqmData = model->modelData;
-
- if(iqmData->bounds)
- {
- VectorCopy(iqmData->bounds, mins);
- VectorCopy(iqmData->bounds + 3, maxs);
- return;
- }
- }
-
- VectorClear( mins );
- VectorClear( maxs );
-}
diff --git a/src/rend2/tr_model_iqm.c b/src/rend2/tr_model_iqm.c
deleted file mode 100644
index 1f1bf747..00000000
--- a/src/rend2/tr_model_iqm.c
+++ /dev/null
@@ -1,1058 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 2011 Thilo Schulz <thilo@tjps.eu>
-Copyright (C) 2011 Matthias Bentrup <matthias.bentrup@googlemail.com>
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-#include "tr_local.h"
-
-#define LL(x) x=LittleLong(x)
-
-static qboolean IQM_CheckRange( iqmHeader_t *header, int offset,
- int count,int size ) {
- // return true if the range specified by offset, count and size
- // doesn't fit into the file
- return ( count <= 0 ||
- offset < 0 ||
- offset > header->filesize ||
- offset + count * size < 0 ||
- offset + count * size > header->filesize );
-}
-// "multiply" 3x4 matrices, these are assumed to be the top 3 rows
-// of a 4x4 matrix with the last row = (0 0 0 1)
-static void Matrix34Multiply( float *a, float *b, float *out ) {
- out[ 0] = a[0] * b[0] + a[1] * b[4] + a[ 2] * b[ 8];
- out[ 1] = a[0] * b[1] + a[1] * b[5] + a[ 2] * b[ 9];
- out[ 2] = a[0] * b[2] + a[1] * b[6] + a[ 2] * b[10];
- out[ 3] = a[0] * b[3] + a[1] * b[7] + a[ 2] * b[11] + a[ 3];
- out[ 4] = a[4] * b[0] + a[5] * b[4] + a[ 6] * b[ 8];
- out[ 5] = a[4] * b[1] + a[5] * b[5] + a[ 6] * b[ 9];
- out[ 6] = a[4] * b[2] + a[5] * b[6] + a[ 6] * b[10];
- out[ 7] = a[4] * b[3] + a[5] * b[7] + a[ 6] * b[11] + a[ 7];
- out[ 8] = a[8] * b[0] + a[9] * b[4] + a[10] * b[ 8];
- out[ 9] = a[8] * b[1] + a[9] * b[5] + a[10] * b[ 9];
- out[10] = a[8] * b[2] + a[9] * b[6] + a[10] * b[10];
- out[11] = a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11];
-}
-static void InterpolateMatrix( float *a, float *b, float lerp, float *mat ) {
- float unLerp = 1.0f - lerp;
-
- mat[ 0] = a[ 0] * unLerp + b[ 0] * lerp;
- mat[ 1] = a[ 1] * unLerp + b[ 1] * lerp;
- mat[ 2] = a[ 2] * unLerp + b[ 2] * lerp;
- mat[ 3] = a[ 3] * unLerp + b[ 3] * lerp;
- mat[ 4] = a[ 4] * unLerp + b[ 4] * lerp;
- mat[ 5] = a[ 5] * unLerp + b[ 5] * lerp;
- mat[ 6] = a[ 6] * unLerp + b[ 6] * lerp;
- mat[ 7] = a[ 7] * unLerp + b[ 7] * lerp;
- mat[ 8] = a[ 8] * unLerp + b[ 8] * lerp;
- mat[ 9] = a[ 9] * unLerp + b[ 9] * lerp;
- mat[10] = a[10] * unLerp + b[10] * lerp;
- mat[11] = a[11] * unLerp + b[11] * lerp;
-}
-static void JointToMatrix( vec4_t rot, vec3_t scale, vec3_t trans,
- float *mat ) {
- float xx = 2.0f * rot[0] * rot[0];
- float yy = 2.0f * rot[1] * rot[1];
- float zz = 2.0f * rot[2] * rot[2];
- float xy = 2.0f * rot[0] * rot[1];
- float xz = 2.0f * rot[0] * rot[2];
- float yz = 2.0f * rot[1] * rot[2];
- float wx = 2.0f * rot[3] * rot[0];
- float wy = 2.0f * rot[3] * rot[1];
- float wz = 2.0f * rot[3] * rot[2];
-
- mat[ 0] = scale[0] * (1.0f - (yy + zz));
- mat[ 1] = scale[0] * (xy - wz);
- mat[ 2] = scale[0] * (xz + wy);
- mat[ 3] = trans[0];
- mat[ 4] = scale[1] * (xy + wz);
- mat[ 5] = scale[1] * (1.0f - (xx + zz));
- mat[ 6] = scale[1] * (yz - wx);
- mat[ 7] = trans[1];
- mat[ 8] = scale[2] * (xz - wy);
- mat[ 9] = scale[2] * (yz + wx);
- mat[10] = scale[2] * (1.0f - (xx + yy));
- mat[11] = trans[2];
-}
-static void Matrix34Invert( float *inMat, float *outMat )
-{
- vec3_t trans;
- float invSqrLen, *v;
-
- outMat[ 0] = inMat[ 0]; outMat[ 1] = inMat[ 4]; outMat[ 2] = inMat[ 8];
- outMat[ 4] = inMat[ 1]; outMat[ 5] = inMat[ 5]; outMat[ 6] = inMat[ 9];
- outMat[ 8] = inMat[ 2]; outMat[ 9] = inMat[ 6]; outMat[10] = inMat[10];
-
- v = outMat + 0; invSqrLen = 1.0f / DotProduct(v, v); VectorScale(v, invSqrLen, v);
- v = outMat + 4; invSqrLen = 1.0f / DotProduct(v, v); VectorScale(v, invSqrLen, v);
- v = outMat + 8; invSqrLen = 1.0f / DotProduct(v, v); VectorScale(v, invSqrLen, v);
-
- trans[0] = inMat[ 3];
- trans[1] = inMat[ 7];
- trans[2] = inMat[11];
-
- outMat[ 3] = -DotProduct(outMat + 0, trans);
- outMat[ 7] = -DotProduct(outMat + 4, trans);
- outMat[11] = -DotProduct(outMat + 8, trans);
-}
-
-/*
-=================
-R_LoadIQM
-
-Load an IQM model and compute the joint matrices for every frame.
-=================
-*/
-qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_name ) {
- iqmHeader_t *header;
- iqmVertexArray_t *vertexarray;
- iqmTriangle_t *triangle;
- iqmMesh_t *mesh;
- iqmJoint_t *joint;
- iqmPose_t *pose;
- iqmBounds_t *bounds;
- unsigned short *framedata;
- char *str;
- int i, j;
- float jointMats[IQM_MAX_JOINTS * 2 * 12];
- float *mat;
- size_t size, joint_names;
- iqmData_t *iqmData;
- srfIQModel_t *surface;
-
- if( filesize < sizeof(iqmHeader_t) ) {
- return qfalse;
- }
-
- header = (iqmHeader_t *)buffer;
- if( Q_strncmp( header->magic, IQM_MAGIC, sizeof(header->magic) ) ) {
- return qfalse;
- }
-
- LL( header->version );
- if( header->version != IQM_VERSION ) {
- ri.Printf(PRINT_WARNING, "R_LoadIQM: %s is a unsupported IQM version (%d), only version %d is supported.\n",
- mod_name, header->version, IQM_VERSION);
- return qfalse;
- }
-
- LL( header->filesize );
- if( header->filesize > filesize || header->filesize > 16<<20 ) {
- return qfalse;
- }
-
- LL( header->flags );
- LL( header->num_text );
- LL( header->ofs_text );
- LL( header->num_meshes );
- LL( header->ofs_meshes );
- LL( header->num_vertexarrays );
- LL( header->num_vertexes );
- LL( header->ofs_vertexarrays );
- LL( header->num_triangles );
- LL( header->ofs_triangles );
- LL( header->ofs_adjacency );
- LL( header->num_joints );
- LL( header->ofs_joints );
- LL( header->num_poses );
- LL( header->ofs_poses );
- LL( header->num_anims );
- LL( header->ofs_anims );
- LL( header->num_frames );
- LL( header->num_framechannels );
- LL( header->ofs_frames );
- LL( header->ofs_bounds );
- LL( header->num_comment );
- LL( header->ofs_comment );
- LL( header->num_extensions );
- LL( header->ofs_extensions );
-
- // check ioq3 joint limit
- if ( header->num_joints > IQM_MAX_JOINTS ) {
- ri.Printf(PRINT_WARNING, "R_LoadIQM: %s has more than %d joints (%d).\n",
- mod_name, IQM_MAX_JOINTS, header->num_joints);
- return qfalse;
- }
-
- // check and swap vertex arrays
- if( IQM_CheckRange( header, header->ofs_vertexarrays,
- header->num_vertexarrays,
- sizeof(iqmVertexArray_t) ) ) {
- return qfalse;
- }
- vertexarray = (iqmVertexArray_t *)((byte *)header + header->ofs_vertexarrays);
- for( i = 0; i < header->num_vertexarrays; i++, vertexarray++ ) {
- int j, n, *intPtr;
-
- if( vertexarray->size <= 0 || vertexarray->size > 4 ) {
- return qfalse;
- }
-
- // total number of values
- n = header->num_vertexes * vertexarray->size;
-
- switch( vertexarray->format ) {
- case IQM_BYTE:
- case IQM_UBYTE:
- // 1 byte, no swapping necessary
- if( IQM_CheckRange( header, vertexarray->offset,
- n, sizeof(byte) ) ) {
- return qfalse;
- }
- break;
- case IQM_INT:
- case IQM_UINT:
- case IQM_FLOAT:
- // 4-byte swap
- if( IQM_CheckRange( header, vertexarray->offset,
- n, sizeof(float) ) ) {
- return qfalse;
- }
- intPtr = (int *)((byte *)header + vertexarray->offset);
- for( j = 0; j < n; j++, intPtr++ ) {
- LL( *intPtr );
- }
- break;
- default:
- // not supported
- return qfalse;
- break;
- }
-
- switch( vertexarray->type ) {
- case IQM_POSITION:
- case IQM_NORMAL:
- if( vertexarray->format != IQM_FLOAT ||
- vertexarray->size != 3 ) {
- return qfalse;
- }
- break;
- case IQM_TANGENT:
- if( vertexarray->format != IQM_FLOAT ||
- vertexarray->size != 4 ) {
- return qfalse;
- }
- break;
- case IQM_TEXCOORD:
- if( vertexarray->format != IQM_FLOAT ||
- vertexarray->size != 2 ) {
- return qfalse;
- }
- break;
- case IQM_BLENDINDEXES:
- case IQM_BLENDWEIGHTS:
- if( vertexarray->format != IQM_UBYTE ||
- vertexarray->size != 4 ) {
- return qfalse;
- }
- break;
- case IQM_COLOR:
- if( vertexarray->format != IQM_UBYTE ||
- vertexarray->size != 4 ) {
- return qfalse;
- }
- break;
- }
- }
-
- // check and swap triangles
- if( IQM_CheckRange( header, header->ofs_triangles,
- header->num_triangles, sizeof(iqmTriangle_t) ) ) {
- return qfalse;
- }
- triangle = (iqmTriangle_t *)((byte *)header + header->ofs_triangles);
- for( i = 0; i < header->num_triangles; i++, triangle++ ) {
- LL( triangle->vertex[0] );
- LL( triangle->vertex[1] );
- LL( triangle->vertex[2] );
-
- if( triangle->vertex[0] > header->num_vertexes ||
- triangle->vertex[1] > header->num_vertexes ||
- triangle->vertex[2] > header->num_vertexes ) {
- return qfalse;
- }
- }
-
- // check and swap meshes
- if( IQM_CheckRange( header, header->ofs_meshes,
- header->num_meshes, sizeof(iqmMesh_t) ) ) {
- return qfalse;
- }
- mesh = (iqmMesh_t *)((byte *)header + header->ofs_meshes);
- for( i = 0; i < header->num_meshes; i++, mesh++) {
- LL( mesh->name );
- LL( mesh->material );
- LL( mesh->first_vertex );
- LL( mesh->num_vertexes );
- LL( mesh->first_triangle );
- LL( mesh->num_triangles );
-
- // check ioq3 limits
- if ( mesh->num_vertexes > SHADER_MAX_VERTEXES )
- {
- ri.Printf(PRINT_WARNING, "R_LoadIQM: %s has more than %i verts on a surface (%i).\n",
- mod_name, SHADER_MAX_VERTEXES, mesh->num_vertexes );
- return qfalse;
- }
- if ( mesh->num_triangles*3 > SHADER_MAX_INDEXES )
- {
- ri.Printf(PRINT_WARNING, "R_LoadIQM: %s has more than %i triangles on a surface (%i).\n",
- mod_name, SHADER_MAX_INDEXES / 3, mesh->num_triangles );
- return qfalse;
- }
-
- if( mesh->first_vertex >= header->num_vertexes ||
- mesh->first_vertex + mesh->num_vertexes > header->num_vertexes ||
- mesh->first_triangle >= header->num_triangles ||
- mesh->first_triangle + mesh->num_triangles > header->num_triangles ||
- mesh->name >= header->num_text ||
- mesh->material >= header->num_text ) {
- return qfalse;
- }
- }
-
- // check and swap joints
- if( IQM_CheckRange( header, header->ofs_joints,
- header->num_joints, sizeof(iqmJoint_t) ) ) {
- return qfalse;
- }
- joint = (iqmJoint_t *)((byte *)header + header->ofs_joints);
- joint_names = 0;
- for( i = 0; i < header->num_joints; i++, joint++ ) {
- LL( joint->name );
- LL( joint->parent );
- LL( joint->translate[0] );
- LL( joint->translate[1] );
- LL( joint->translate[2] );
- LL( joint->rotate[0] );
- LL( joint->rotate[1] );
- LL( joint->rotate[2] );
- LL( joint->rotate[3] );
- LL( joint->scale[0] );
- LL( joint->scale[1] );
- LL( joint->scale[2] );
-
- if( joint->parent < -1 ||
- joint->parent >= (int)header->num_joints ||
- joint->name >= (int)header->num_text ) {
- return qfalse;
- }
- joint_names += strlen( (char *)header + header->ofs_text +
- joint->name ) + 1;
- }
-
- // check and swap poses
- if( header->num_poses != header->num_joints ) {
- return qfalse;
- }
- if( IQM_CheckRange( header, header->ofs_poses,
- header->num_poses, sizeof(iqmPose_t) ) ) {
- return qfalse;
- }
- pose = (iqmPose_t *)((byte *)header + header->ofs_poses);
- for( i = 0; i < header->num_poses; i++, pose++ ) {
- LL( pose->parent );
- LL( pose->mask );
- LL( pose->channeloffset[0] );
- LL( pose->channeloffset[1] );
- LL( pose->channeloffset[2] );
- LL( pose->channeloffset[3] );
- LL( pose->channeloffset[4] );
- LL( pose->channeloffset[5] );
- LL( pose->channeloffset[6] );
- LL( pose->channeloffset[7] );
- LL( pose->channeloffset[8] );
- LL( pose->channeloffset[9] );
- LL( pose->channelscale[0] );
- LL( pose->channelscale[1] );
- LL( pose->channelscale[2] );
- LL( pose->channelscale[3] );
- LL( pose->channelscale[4] );
- LL( pose->channelscale[5] );
- LL( pose->channelscale[6] );
- LL( pose->channelscale[7] );
- LL( pose->channelscale[8] );
- LL( pose->channelscale[9] );
- }
-
- if (header->ofs_bounds)
- {
- // check and swap model bounds
- if(IQM_CheckRange(header, header->ofs_bounds,
- header->num_frames, sizeof(*bounds)))
- {
- return qfalse;
- }
- bounds = (iqmBounds_t *) ((byte *) header + header->ofs_bounds);
- for(i = 0; i < header->num_frames; i++)
- {
- LL(bounds->bbmin[0]);
- LL(bounds->bbmin[1]);
- LL(bounds->bbmin[2]);
- LL(bounds->bbmax[0]);
- LL(bounds->bbmax[1]);
- LL(bounds->bbmax[2]);
-
- bounds++;
- }
- }
-
- // allocate the model and copy the data
- size = sizeof(iqmData_t);
- size += header->num_meshes * sizeof( srfIQModel_t );
- size += header->num_joints * header->num_frames * 12 * sizeof( float );
- if(header->ofs_bounds)
- size += header->num_frames * 6 * sizeof(float); // model bounds
- size += header->num_vertexes * 3 * sizeof(float); // positions
- size += header->num_vertexes * 2 * sizeof(float); // texcoords
- size += header->num_vertexes * 3 * sizeof(float); // normals
- size += header->num_vertexes * 4 * sizeof(float); // tangents
- size += header->num_vertexes * 4 * sizeof(byte); // blendIndexes
- size += header->num_vertexes * 4 * sizeof(byte); // blendWeights
- size += header->num_vertexes * 4 * sizeof(byte); // colors
- size += header->num_joints * sizeof(int); // parents
- size += header->num_triangles * 3 * sizeof(int); // triangles
- size += joint_names; // joint names
-
- mod->type = MOD_IQM;
- iqmData = (iqmData_t *)ri.Hunk_Alloc( size, h_low );
- mod->modelData = iqmData;
-
- // fill header
- iqmData->num_vertexes = header->num_vertexes;
- iqmData->num_triangles = header->num_triangles;
- iqmData->num_frames = header->num_frames;
- iqmData->num_surfaces = header->num_meshes;
- iqmData->num_joints = header->num_joints;
- iqmData->surfaces = (srfIQModel_t *)(iqmData + 1);
- iqmData->poseMats = (float *) (iqmData->surfaces + iqmData->num_surfaces);
- if(header->ofs_bounds)
- {
- iqmData->bounds = iqmData->poseMats + 12 * header->num_joints * header->num_frames;
- iqmData->positions = iqmData->bounds + 6 * header->num_frames;
- }
- else
- iqmData->positions = iqmData->poseMats + 12 * header->num_joints * header->num_frames;
- iqmData->texcoords = iqmData->positions + 3 * header->num_vertexes;
- iqmData->normals = iqmData->texcoords + 2 * header->num_vertexes;
- iqmData->tangents = iqmData->normals + 3 * header->num_vertexes;
- iqmData->blendIndexes = (byte *)(iqmData->tangents + 4 * header->num_vertexes);
- iqmData->blendWeights = iqmData->blendIndexes + 4 * header->num_vertexes;
- iqmData->colors = iqmData->blendWeights + 4 * header->num_vertexes;
- iqmData->jointParents = (int *)(iqmData->colors + 4 * header->num_vertexes);
- iqmData->triangles = iqmData->jointParents + header->num_joints;
- iqmData->names = (char *)(iqmData->triangles + 3 * header->num_triangles);
-
- // calculate joint matrices and their inverses
- // they are needed only until the pose matrices are calculated
- mat = jointMats;
- joint = (iqmJoint_t *)((byte *)header + header->ofs_joints);
- for( i = 0; i < header->num_joints; i++, joint++ ) {
- float baseFrame[12], invBaseFrame[12];
-
- JointToMatrix( joint->rotate, joint->scale, joint->translate, baseFrame );
- Matrix34Invert( baseFrame, invBaseFrame );
-
- if ( joint->parent >= 0 )
- {
- Matrix34Multiply( jointMats + 2 * 12 * joint->parent, baseFrame, mat );
- mat += 12;
- Matrix34Multiply( invBaseFrame, jointMats + 2 * 12 * joint->parent + 12, mat );
- mat += 12;
- }
- else
- {
- Com_Memcpy( mat, baseFrame, sizeof(baseFrame) );
- mat += 12;
- Com_Memcpy( mat, invBaseFrame, sizeof(invBaseFrame) );
- mat += 12;
- }
- }
-
- // calculate pose matrices
- framedata = (unsigned short *)((byte *)header + header->ofs_frames);
- mat = iqmData->poseMats;
- for( i = 0; i < header->num_frames; i++ ) {
- pose = (iqmPose_t *)((byte *)header + header->ofs_poses);
- for( j = 0; j < header->num_poses; j++, pose++ ) {
- vec3_t translate;
- vec4_t rotate;
- vec3_t scale;
- float mat1[12], mat2[12];
-
- translate[0] = pose->channeloffset[0];
- if( pose->mask & 0x001)
- translate[0] += *framedata++ * pose->channelscale[0];
- translate[1] = pose->channeloffset[1];
- if( pose->mask & 0x002)
- translate[1] += *framedata++ * pose->channelscale[1];
- translate[2] = pose->channeloffset[2];
- if( pose->mask & 0x004)
- translate[2] += *framedata++ * pose->channelscale[2];
-
- rotate[0] = pose->channeloffset[3];
- if( pose->mask & 0x008)
- rotate[0] += *framedata++ * pose->channelscale[3];
- rotate[1] = pose->channeloffset[4];
- if( pose->mask & 0x010)
- rotate[1] += *framedata++ * pose->channelscale[4];
- rotate[2] = pose->channeloffset[5];
- if( pose->mask & 0x020)
- rotate[2] += *framedata++ * pose->channelscale[5];
- rotate[3] = pose->channeloffset[6];
- if( pose->mask & 0x040)
- rotate[3] += *framedata++ * pose->channelscale[6];
-
- scale[0] = pose->channeloffset[7];
- if( pose->mask & 0x080)
- scale[0] += *framedata++ * pose->channelscale[7];
- scale[1] = pose->channeloffset[8];
- if( pose->mask & 0x100)
- scale[1] += *framedata++ * pose->channelscale[8];
- scale[2] = pose->channeloffset[9];
- if( pose->mask & 0x200)
- scale[2] += *framedata++ * pose->channelscale[9];
-
- // construct transformation matrix
- JointToMatrix( rotate, scale, translate, mat1 );
-
- if( pose->parent >= 0 ) {
- Matrix34Multiply( jointMats + 12 * 2 * pose->parent,
- mat1, mat2 );
- } else {
- Com_Memcpy( mat2, mat1, sizeof(mat1) );
- }
-
- Matrix34Multiply( mat2, jointMats + 12 * (2 * j + 1), mat );
- mat += 12;
- }
- }
-
- // register shaders
- // overwrite the material offset with the shader index
- mesh = (iqmMesh_t *)((byte *)header + header->ofs_meshes);
- surface = iqmData->surfaces;
- str = (char *)header + header->ofs_text;
- for( i = 0; i < header->num_meshes; i++, mesh++, surface++ ) {
- surface->surfaceType = SF_IQM;
- Q_strncpyz(surface->name, str + mesh->name, sizeof (surface->name));
- Q_strlwr(surface->name); // lowercase the surface name so skin compares are faster
- surface->shader = R_FindShader( str + mesh->material, LIGHTMAP_NONE, qtrue );
- if( surface->shader->defaultShader )
- surface->shader = tr.defaultShader;
- surface->data = iqmData;
- surface->first_vertex = mesh->first_vertex;
- surface->num_vertexes = mesh->num_vertexes;
- surface->first_triangle = mesh->first_triangle;
- surface->num_triangles = mesh->num_triangles;
- }
-
- // copy vertexarrays and indexes
- vertexarray = (iqmVertexArray_t *)((byte *)header + header->ofs_vertexarrays);
- for( i = 0; i < header->num_vertexarrays; i++, vertexarray++ ) {
- int n;
-
- // total number of values
- n = header->num_vertexes * vertexarray->size;
-
- switch( vertexarray->type ) {
- case IQM_POSITION:
- Com_Memcpy( iqmData->positions,
- (byte *)header + vertexarray->offset,
- n * sizeof(float) );
- break;
- case IQM_NORMAL:
- Com_Memcpy( iqmData->normals,
- (byte *)header + vertexarray->offset,
- n * sizeof(float) );
- break;
- case IQM_TANGENT:
- Com_Memcpy( iqmData->tangents,
- (byte *)header + vertexarray->offset,
- n * sizeof(float) );
- break;
- case IQM_TEXCOORD:
- Com_Memcpy( iqmData->texcoords,
- (byte *)header + vertexarray->offset,
- n * sizeof(float) );
- break;
- case IQM_BLENDINDEXES:
- Com_Memcpy( iqmData->blendIndexes,
- (byte *)header + vertexarray->offset,
- n * sizeof(byte) );
- break;
- case IQM_BLENDWEIGHTS:
- Com_Memcpy( iqmData->blendWeights,
- (byte *)header + vertexarray->offset,
- n * sizeof(byte) );
- break;
- case IQM_COLOR:
- Com_Memcpy( iqmData->colors,
- (byte *)header + vertexarray->offset,
- n * sizeof(byte) );
- break;
- }
- }
-
- // copy joint parents
- joint = (iqmJoint_t *)((byte *)header + header->ofs_joints);
- for( i = 0; i < header->num_joints; i++, joint++ ) {
- iqmData->jointParents[i] = joint->parent;
- }
-
- // copy triangles
- triangle = (iqmTriangle_t *)((byte *)header + header->ofs_triangles);
- for( i = 0; i < header->num_triangles; i++, triangle++ ) {
- iqmData->triangles[3*i+0] = triangle->vertex[0];
- iqmData->triangles[3*i+1] = triangle->vertex[1];
- iqmData->triangles[3*i+2] = triangle->vertex[2];
- }
-
- // copy joint names
- str = iqmData->names;
- joint = (iqmJoint_t *)((byte *)header + header->ofs_joints);
- for( i = 0; i < header->num_joints; i++, joint++ ) {
- char *name = (char *)header + header->ofs_text +
- joint->name;
- int len = strlen( name ) + 1;
- Com_Memcpy( str, name, len );
- str += len;
- }
-
- // copy model bounds
- if(header->ofs_bounds)
- {
- mat = iqmData->bounds;
- bounds = (iqmBounds_t *) ((byte *) header + header->ofs_bounds);
- for(i = 0; i < header->num_frames; i++)
- {
- mat[0] = bounds->bbmin[0];
- mat[1] = bounds->bbmin[1];
- mat[2] = bounds->bbmin[2];
- mat[3] = bounds->bbmax[0];
- mat[4] = bounds->bbmax[1];
- mat[5] = bounds->bbmax[2];
-
- mat += 6;
- bounds++;
- }
- }
-
- return qtrue;
-}
-
-/*
-=============
-R_CullIQM
-=============
-*/
-static int R_CullIQM( iqmData_t *data, trRefEntity_t *ent ) {
- vec3_t bounds[2];
- vec_t *oldBounds, *newBounds;
- int i;
-
- if (!data->bounds) {
- tr.pc.c_box_cull_md3_clip++;
- return CULL_CLIP;
- }
-
- // compute bounds pointers
- oldBounds = data->bounds + 6*ent->e.oldframe;
- newBounds = data->bounds + 6*ent->e.frame;
-
- // calculate a bounding box in the current coordinate system
- for (i = 0 ; i < 3 ; i++) {
- bounds[0][i] = oldBounds[i] < newBounds[i] ? oldBounds[i] : newBounds[i];
- bounds[1][i] = oldBounds[i+3] > newBounds[i+3] ? oldBounds[i+3] : newBounds[i+3];
- }
-
- switch ( R_CullLocalBox( bounds ) )
- {
- case CULL_IN:
- tr.pc.c_box_cull_md3_in++;
- return CULL_IN;
- case CULL_CLIP:
- tr.pc.c_box_cull_md3_clip++;
- return CULL_CLIP;
- case CULL_OUT:
- default:
- tr.pc.c_box_cull_md3_out++;
- return CULL_OUT;
- }
-}
-
-/*
-=================
-R_ComputeIQMFogNum
-
-=================
-*/
-int R_ComputeIQMFogNum( iqmData_t *data, trRefEntity_t *ent ) {
- int i, j;
- fog_t *fog;
- const vec_t *bounds;
- const vec_t defaultBounds[6] = { -8, -8, -8, 8, 8, 8 };
- vec3_t diag, center;
- vec3_t localOrigin;
- vec_t radius;
-
- if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
- return 0;
- }
-
- // FIXME: non-normalized axis issues
- if (data->bounds) {
- bounds = data->bounds + 6*ent->e.frame;
- } else {
- bounds = defaultBounds;
- }
- VectorSubtract( bounds+3, bounds, diag );
- VectorMA( bounds, 0.5f, diag, center );
- VectorAdd( ent->e.origin, center, localOrigin );
- radius = 0.5f * VectorLength( diag );
-
- for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
- fog = &tr.world->fogs[i];
- for ( j = 0 ; j < 3 ; j++ ) {
- if ( localOrigin[j] - radius >= fog->bounds[1][j] ) {
- break;
- }
- if ( localOrigin[j] + radius <= fog->bounds[0][j] ) {
- break;
- }
- }
- if ( j == 3 ) {
- return i;
- }
- }
-
- return 0;
-}
-
-/*
-=================
-R_AddIQMSurfaces
-
-Add all surfaces of this model
-=================
-*/
-void R_AddIQMSurfaces( trRefEntity_t *ent ) {
- iqmData_t *data;
- srfIQModel_t *surface;
- int i, j;
- qboolean personalModel;
- int cull;
- int fogNum;
- shader_t *shader;
- skin_t *skin;
-
- data = tr.currentModel->modelData;
- surface = data->surfaces;
-
- // don't add third_person objects if not in a portal
- personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal;
-
- if ( ent->e.renderfx & RF_WRAP_FRAMES ) {
- ent->e.frame %= data->num_frames;
- ent->e.oldframe %= data->num_frames;
- }
-
- //
- // Validate the frames so there is no chance of a crash.
- // This will write directly into the entity structure, so
- // when the surfaces are rendered, they don't need to be
- // range checked again.
- //
- if ( (ent->e.frame >= data->num_frames)
- || (ent->e.frame < 0)
- || (ent->e.oldframe >= data->num_frames)
- || (ent->e.oldframe < 0) ) {
- ri.Printf( PRINT_DEVELOPER, "R_AddIQMSurfaces: no such frame %d to %d for '%s'\n",
- ent->e.oldframe, ent->e.frame,
- tr.currentModel->name );
- ent->e.frame = 0;
- ent->e.oldframe = 0;
- }
-
- //
- // cull the entire model if merged bounding box of both frames
- // is outside the view frustum.
- //
- cull = R_CullIQM ( data, ent );
- if ( cull == CULL_OUT ) {
- return;
- }
-
- //
- // set up lighting now that we know we aren't culled
- //
- if ( !personalModel || r_shadows->integer > 1 ) {
- R_SetupEntityLighting( &tr.refdef, ent );
- }
-
- //
- // see if we are in a fog volume
- //
- fogNum = R_ComputeIQMFogNum( data, ent );
-
- for ( i = 0 ; i < data->num_surfaces ; i++ ) {
- if(ent->e.customShader)
- shader = R_GetShaderByHandle( ent->e.customShader );
- else if(ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins)
- {
- skin = R_GetSkinByHandle(ent->e.customSkin);
- shader = tr.defaultShader;
-
- for(j = 0; j < skin->numSurfaces; j++)
- {
- if (!strcmp(skin->surfaces[j]->name, surface->name))
- {
- shader = skin->surfaces[j]->shader;
- break;
- }
- }
- } else {
- shader = surface->shader;
- }
-
- // we will add shadows even if the main object isn't visible in the view
-
- // stencil shadows can't do personal models unless I polyhedron clip
- if ( !personalModel
- && r_shadows->integer == 2
- && fogNum == 0
- && !(ent->e.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )
- && shader->sort == SS_OPAQUE ) {
- R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, 0, 0 );
- }
-
- // projection shadows work fine with personal models
- if ( r_shadows->integer == 3
- && fogNum == 0
- && (ent->e.renderfx & RF_SHADOW_PLANE )
- && shader->sort == SS_OPAQUE ) {
- R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, 0, 0 );
- }
-
- if( !personalModel ) {
- R_AddDrawSurf( (void *)surface, shader, fogNum, 0, 0 );
- }
-
- surface++;
- }
-}
-
-
-static void ComputeJointMats( iqmData_t *data, int frame, int oldframe,
- float backlerp, float *mat ) {
- float *mat1, *mat2;
- int *joint = data->jointParents;
- int i;
-
- if ( oldframe == frame ) {
- mat1 = data->poseMats + 12 * data->num_joints * frame;
- for( i = 0; i < data->num_joints; i++, joint++ ) {
- if( *joint >= 0 ) {
- Matrix34Multiply( mat + 12 * *joint,
- mat1 + 12*i, mat + 12*i );
- } else {
- Com_Memcpy( mat + 12*i, mat1 + 12*i, 12 * sizeof(float) );
- }
- }
- } else {
- mat1 = data->poseMats + 12 * data->num_joints * frame;
- mat2 = data->poseMats + 12 * data->num_joints * oldframe;
-
- for( i = 0; i < data->num_joints; i++, joint++ ) {
- if( *joint >= 0 ) {
- float tmpMat[12];
- InterpolateMatrix( mat1 + 12*i, mat2 + 12*i,
- backlerp, tmpMat );
- Matrix34Multiply( mat + 12 * *joint,
- tmpMat, mat + 12*i );
-
- } else {
- InterpolateMatrix( mat1 + 12*i, mat2 + 12*i,
- backlerp, mat );
- }
- }
- }
-}
-
-
-/*
-=================
-RB_AddIQMSurfaces
-
-Compute vertices for this model surface
-=================
-*/
-void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
- srfIQModel_t *surf = (srfIQModel_t *)surface;
- iqmData_t *data = surf->data;
- float jointMats[IQM_MAX_JOINTS * 12];
- int i;
-
- vec4_t *outXYZ = &tess.xyz[tess.numVertexes];
- vec4_t *outNormal = &tess.normal[tess.numVertexes];
- vec2_t (*outTexCoord)[2] = &tess.texCoords[tess.numVertexes];
- vec4_t *outColor = &tess.vertexColors[tess.numVertexes];
-
- int frame = backEnd.currentEntity->e.frame % data->num_frames;
- int oldframe = backEnd.currentEntity->e.oldframe % data->num_frames;
- float backlerp = backEnd.currentEntity->e.backlerp;
-
- int *tri;
- glIndex_t *ptr;
- glIndex_t base;
-
- RB_CHECKOVERFLOW( surf->num_vertexes, surf->num_triangles * 3 );
-
- // compute interpolated joint matrices
- ComputeJointMats( data, frame, oldframe, backlerp, jointMats );
-
- // transform vertexes and fill other data
- for( i = 0; i < surf->num_vertexes;
- i++, outXYZ++, outNormal++, outTexCoord++, outColor++ ) {
- int j, k;
- float vtxMat[12];
- float nrmMat[9];
- int vtx = i + surf->first_vertex;
-
- // compute the vertex matrix by blending the up to
- // four blend weights
- for( k = 0; k < 12; k++ )
- vtxMat[k] = data->blendWeights[4*vtx]
- * jointMats[12*data->blendIndexes[4*vtx] + k];
- for( j = 1; j < 4; j++ ) {
- if( data->blendWeights[4*vtx + j] <= 0 )
- break;
- for( k = 0; k < 12; k++ )
- vtxMat[k] += data->blendWeights[4*vtx + j]
- * jointMats[12*data->blendIndexes[4*vtx + j] + k];
- }
- for( k = 0; k < 12; k++ )
- vtxMat[k] *= 1.0f / 255.0f;
-
- // compute the normal matrix as transpose of the adjoint
- // of the vertex matrix
- nrmMat[ 0] = vtxMat[ 5]*vtxMat[10] - vtxMat[ 6]*vtxMat[ 9];
- nrmMat[ 1] = vtxMat[ 6]*vtxMat[ 8] - vtxMat[ 4]*vtxMat[10];
- nrmMat[ 2] = vtxMat[ 4]*vtxMat[ 9] - vtxMat[ 5]*vtxMat[ 8];
- nrmMat[ 3] = vtxMat[ 2]*vtxMat[ 9] - vtxMat[ 1]*vtxMat[10];
- nrmMat[ 4] = vtxMat[ 0]*vtxMat[10] - vtxMat[ 2]*vtxMat[ 8];
- nrmMat[ 5] = vtxMat[ 1]*vtxMat[ 8] - vtxMat[ 0]*vtxMat[ 9];
- nrmMat[ 6] = vtxMat[ 1]*vtxMat[ 6] - vtxMat[ 2]*vtxMat[ 5];
- nrmMat[ 7] = vtxMat[ 2]*vtxMat[ 4] - vtxMat[ 0]*vtxMat[ 6];
- nrmMat[ 8] = vtxMat[ 0]*vtxMat[ 5] - vtxMat[ 1]*vtxMat[ 4];
-
- (*outTexCoord)[0][0] = data->texcoords[2*vtx + 0];
- (*outTexCoord)[0][1] = data->texcoords[2*vtx + 1];
- (*outTexCoord)[1][0] = (*outTexCoord)[0][0];
- (*outTexCoord)[1][1] = (*outTexCoord)[0][1];
-
- (*outXYZ)[0] =
- vtxMat[ 0] * data->positions[3*vtx+0] +
- vtxMat[ 1] * data->positions[3*vtx+1] +
- vtxMat[ 2] * data->positions[3*vtx+2] +
- vtxMat[ 3];
- (*outXYZ)[1] =
- vtxMat[ 4] * data->positions[3*vtx+0] +
- vtxMat[ 5] * data->positions[3*vtx+1] +
- vtxMat[ 6] * data->positions[3*vtx+2] +
- vtxMat[ 7];
- (*outXYZ)[2] =
- vtxMat[ 8] * data->positions[3*vtx+0] +
- vtxMat[ 9] * data->positions[3*vtx+1] +
- vtxMat[10] * data->positions[3*vtx+2] +
- vtxMat[11];
- (*outXYZ)[3] = 1.0f;
-
- (*outNormal)[0] =
- nrmMat[ 0] * data->normals[3*vtx+0] +
- nrmMat[ 1] * data->normals[3*vtx+1] +
- nrmMat[ 2] * data->normals[3*vtx+2];
- (*outNormal)[1] =
- nrmMat[ 3] * data->normals[3*vtx+0] +
- nrmMat[ 4] * data->normals[3*vtx+1] +
- nrmMat[ 5] * data->normals[3*vtx+2];
- (*outNormal)[2] =
- nrmMat[ 6] * data->normals[3*vtx+0] +
- nrmMat[ 7] * data->normals[3*vtx+1] +
- nrmMat[ 8] * data->normals[3*vtx+2];
- (*outNormal)[3] = 0.0f;
-
- (*outColor)[0] = data->colors[4*vtx+0] / 255.0f;
- (*outColor)[1] = data->colors[4*vtx+1] / 255.0f;
- (*outColor)[2] = data->colors[4*vtx+2] / 255.0f;
- (*outColor)[3] = data->colors[4*vtx+3] / 255.0f;
- }
-
- tri = data->triangles + 3 * surf->first_triangle;
- ptr = &tess.indexes[tess.numIndexes];
- base = tess.numVertexes;
-
- for( i = 0; i < surf->num_triangles; i++ ) {
- *ptr++ = base + (*tri++ - surf->first_vertex);
- *ptr++ = base + (*tri++ - surf->first_vertex);
- *ptr++ = base + (*tri++ - surf->first_vertex);
- }
-
- tess.numIndexes += 3 * surf->num_triangles;
- tess.numVertexes += surf->num_vertexes;
-}
-
-int R_IQMLerpTag( orientation_t *tag, iqmData_t *data,
- int startFrame, int endFrame,
- float frac, const char *tagName ) {
- float jointMats[IQM_MAX_JOINTS * 12];
- int joint;
- char *names = data->names;
-
- // get joint number by reading the joint names
- for( joint = 0; joint < data->num_joints; joint++ ) {
- if( !strcmp( tagName, names ) )
- break;
- names += strlen( names ) + 1;
- }
- if( joint >= data->num_joints ) {
- AxisClear( tag->axis );
- VectorClear( tag->origin );
- return qfalse;
- }
-
- ComputeJointMats( data, startFrame, endFrame, frac, jointMats );
-
- tag->axis[0][0] = jointMats[12 * joint + 0];
- tag->axis[1][0] = jointMats[12 * joint + 1];
- tag->axis[2][0] = jointMats[12 * joint + 2];
- tag->origin[0] = jointMats[12 * joint + 3];
- tag->axis[0][1] = jointMats[12 * joint + 4];
- tag->axis[1][1] = jointMats[12 * joint + 5];
- tag->axis[2][1] = jointMats[12 * joint + 6];
- tag->origin[1] = jointMats[12 * joint + 7];
- tag->axis[0][2] = jointMats[12 * joint + 8];
- tag->axis[1][2] = jointMats[12 * joint + 9];
- tag->axis[2][2] = jointMats[12 * joint + 10];
- tag->origin[2] = jointMats[12 * joint + 11];
-
- return qtrue;
-}
diff --git a/src/rend2/tr_noise.c b/src/rend2/tr_noise.c
deleted file mode 100644
index 40eafc33..00000000
--- a/src/rend2/tr_noise.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_noise.c
-#include "../qcommon/q_shared.h"
-#include "../qcommon/qfiles.h"
-#include "../qcommon/qcommon.h"
-
-#define NOISE_SIZE 256
-#define NOISE_MASK ( NOISE_SIZE - 1 )
-
-#define VAL( a ) s_noise_perm[ ( a ) & ( NOISE_MASK )]
-#define INDEX( x, y, z, t ) VAL( x + VAL( y + VAL( z + VAL( t ) ) ) )
-
-static float s_noise_table[NOISE_SIZE];
-static int s_noise_perm[NOISE_SIZE];
-
-static float GetNoiseValue( int x, int y, int z, int t )
-{
- int index = INDEX( ( int ) x, ( int ) y, ( int ) z, ( int ) t );
-
- return s_noise_table[index];
-}
-
-void R_NoiseInit( void )
-{
- int i;
-
- for ( i = 0; i < NOISE_SIZE; i++ )
- {
- s_noise_table[i] = ( float ) ( ( ( rand() / ( float ) RAND_MAX ) * 2.0 - 1.0 ) );
- s_noise_perm[i] = ( unsigned char ) ( rand() / ( float ) RAND_MAX * 255 );
- }
-}
-
-float R_NoiseGet4f( float x, float y, float z, float t )
-{
- int i;
- int ix, iy, iz, it;
- float fx, fy, fz, ft;
- float front[4];
- float back[4];
- float fvalue, bvalue, value[2], finalvalue;
-
- ix = ( int ) floor( x );
- fx = x - ix;
- iy = ( int ) floor( y );
- fy = y - iy;
- iz = ( int ) floor( z );
- fz = z - iz;
- it = ( int ) floor( t );
- ft = t - it;
-
- for ( i = 0; i < 2; i++ )
- {
- front[0] = GetNoiseValue( ix, iy, iz, it + i );
- front[1] = GetNoiseValue( ix+1, iy, iz, it + i );
- front[2] = GetNoiseValue( ix, iy+1, iz, it + i );
- front[3] = GetNoiseValue( ix+1, iy+1, iz, it + i );
-
- back[0] = GetNoiseValue( ix, iy, iz + 1, it + i );
- back[1] = GetNoiseValue( ix+1, iy, iz + 1, it + i );
- back[2] = GetNoiseValue( ix, iy+1, iz + 1, it + i );
- back[3] = GetNoiseValue( ix+1, iy+1, iz + 1, it + i );
-
- fvalue = LERP( LERP( front[0], front[1], fx ), LERP( front[2], front[3], fx ), fy );
- bvalue = LERP( LERP( back[0], back[1], fx ), LERP( back[2], back[3], fx ), fy );
-
- value[i] = LERP( fvalue, bvalue, fz );
- }
-
- finalvalue = LERP( value[0], value[1], ft );
-
- return finalvalue;
-}
diff --git a/src/rend2/tr_postprocess.c b/src/rend2/tr_postprocess.c
deleted file mode 100644
index a15c9b7a..00000000
--- a/src/rend2/tr_postprocess.c
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 2011 Andrei Drexler, Richard Allen, James Canete
-
-This file is part of Reaction source code.
-
-Reaction source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Reaction source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Reaction source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-#include "tr_local.h"
-
-void RB_ToneMap(FBO_t *hdrFbo, int autoExposure)
-{
- vec4i_t srcBox, dstBox;
- vec4_t color;
- static int lastFrameCount = 0;
-
- if (autoExposure)
- {
- if (lastFrameCount == 0 || tr.frameCount < lastFrameCount || tr.frameCount - lastFrameCount > 5)
- {
- // determine average log luminance
- FBO_t *srcFbo, *dstFbo, *tmp;
- int size = 256;
-
- lastFrameCount = tr.frameCount;
-
- VectorSet4(dstBox, 0, 0, size, size);
-
- srcFbo = hdrFbo;
- dstFbo = tr.textureScratchFbo[0];
- FBO_Blit(srcFbo, NULL, NULL, dstFbo, dstBox, &tr.calclevels4xShader[0], NULL, 0);
-
- srcFbo = tr.textureScratchFbo[0];
- dstFbo = tr.textureScratchFbo[1];
-
- // downscale to 1x1 texture
- while (size > 1)
- {
- VectorSet4(srcBox, 0, 0, size, size);
- //size >>= 2;
- size >>= 1;
- VectorSet4(dstBox, 0, 0, size, size);
-
- if (size == 1)
- dstFbo = tr.targetLevelsFbo;
-
- //FBO_Blit(targetFbo, srcBox, NULL, tr.textureScratchFbo[nextScratch], dstBox, &tr.calclevels4xShader[1], NULL, 0);
- FBO_FastBlit(srcFbo, srcBox, dstFbo, dstBox, GL_COLOR_BUFFER_BIT, GL_LINEAR);
-
- tmp = srcFbo;
- srcFbo = dstFbo;
- dstFbo = tmp;
- }
- }
-
- // blend with old log luminance for gradual change
- VectorSet4(srcBox, 0, 0, 0, 0);
-
- color[0] =
- color[1] =
- color[2] = 1.0f;
- if (glRefConfig.textureFloat)
- color[3] = 0.03f;
- else
- color[3] = 0.1f;
-
- FBO_Blit(tr.targetLevelsFbo, srcBox, NULL, tr.calcLevelsFbo, NULL, NULL, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
- }
-
- // tonemap
- color[0] =
- color[1] =
- color[2] = pow(2, r_cameraExposure->value); //exp2(r_cameraExposure->value);
- color[3] = 1.0f;
-
- if (autoExposure)
- GL_BindToTMU(tr.calcLevelsImage, TB_LEVELSMAP);
- else
- GL_BindToTMU(tr.fixedLevelsImage, TB_LEVELSMAP);
-
- FBO_Blit(hdrFbo, NULL, NULL, tr.screenScratchFbo, NULL, &tr.tonemapShader, color, 0);
-}
-
-
-void RB_BokehBlur(float blur)
-{
-// vec4i_t srcBox, dstBox;
- vec4_t color;
-
- blur *= 10.0f;
-
- if (blur < 0.004f)
- return;
-
- if (glRefConfig.framebufferObject)
- {
- // bokeh blur
- if (blur > 0.0f)
- {
- // create a quarter texture
- //FBO_Blit(NULL, NULL, NULL, tr.quarterFbo[0], NULL, NULL, NULL, 0);
- FBO_FastBlit(tr.screenScratchFbo, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
- }
-
-#ifndef HQ_BLUR
- if (blur > 1.0f)
- {
- // create a 1/16th texture
- //FBO_Blit(tr.quarterFbo[0], NULL, NULL, tr.textureScratchFbo[0], NULL, NULL, NULL, 0);
- FBO_FastBlit(tr.quarterFbo[0], NULL, tr.textureScratchFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
- }
-#endif
-
- if (blur > 0.0f && blur <= 1.0f)
- {
- // Crossfade original with quarter texture
- VectorSet4(color, 1, 1, 1, blur);
-
- FBO_Blit(tr.quarterFbo[0], NULL, NULL, tr.screenScratchFbo, NULL, NULL, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
- }
-#ifndef HQ_BLUR
- // ok blur, but can see some pixelization
- else if (blur > 1.0f && blur <= 2.0f)
- {
- // crossfade quarter texture with 1/16th texture
- FBO_Blit(tr.quarterFbo[0], NULL, NULL, tr.screenScratchFbo, NULL, NULL, NULL, 0);
-
- VectorSet4(color, 1, 1, 1, blur - 1.0f);
-
- FBO_Blit(tr.textureScratchFbo[0], NULL, NULL, tr.screenScratchFbo, NULL, NULL, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
- }
- else if (blur > 2.0f)
- {
- // blur 1/16th texture then replace
- int i;
-
- for (i = 0; i < 2; i++)
- {
- vec2_t blurTexScale;
- float subblur;
-
- subblur = ((blur - 2.0f) / 2.0f) / 3.0f * (float)(i + 1);
-
- blurTexScale[0] =
- blurTexScale[1] = subblur;
-
- color[0] =
- color[1] =
- color[2] = 0.5f;
- color[3] = 1.0f;
-
- if (i != 0)
- FBO_Blit(tr.textureScratchFbo[0], NULL, blurTexScale, tr.textureScratchFbo[1], NULL, &tr.bokehShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
- else
- FBO_Blit(tr.textureScratchFbo[0], NULL, blurTexScale, tr.textureScratchFbo[1], NULL, &tr.bokehShader, color, 0);
- }
-
- FBO_Blit(tr.textureScratchFbo[1], NULL, NULL, tr.screenScratchFbo, NULL, &tr.textureColorShader, NULL, 0);
- }
-#else // higher quality blur, but slower
- else if (blur > 1.0f)
- {
- // blur quarter texture then replace
- int i;
-
- src = tr.quarterFbo[0];
- dst = tr.quarterFbo[1];
-
- VectorSet4(color, 0.5f, 0.5f, 0.5f, 1);
-
- for (i = 0; i < 2; i++)
- {
- vec2_t blurTexScale;
- float subblur;
-
- subblur = (blur - 1.0f) / 2.0f * (float)(i + 1);
-
- blurTexScale[0] =
- blurTexScale[1] = subblur;
-
- color[0] =
- color[1] =
- color[2] = 1.0f;
- if (i != 0)
- color[3] = 1.0f;
- else
- color[3] = 0.5f;
-
- FBO_Blit(tr.quarterFbo[0], NULL, blurTexScale, tr.quarterFbo[1], NULL, &tr.bokehShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
- }
-
- FBO_Blit(tr.quarterFbo[1], NULL, NULL, tr.screenScratchFbo, NULL, &tr.textureColorShader, NULL, 0);
- }
-#endif
- }
-}
-
-
-static void RB_RadialBlur(FBO_t *srcFbo, FBO_t *dstFbo, int passes, float stretch, float x, float y, float w, float h, float xcenter, float ycenter, float alpha)
-{
- vec4i_t srcBox, dstBox;
- vec4_t color;
- const float inc = 1.f / passes;
- const float mul = powf(stretch, inc);
- float scale;
-
- {
- vec2_t texScale;
-
- texScale[0] =
- texScale[1] = 1.0f;
-
- alpha *= inc;
- VectorSet4(color, alpha, alpha, alpha, 1.0f);
-
- VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
- VectorSet4(dstBox, x, y, w, h);
- FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, 0);
-
- --passes;
- scale = mul;
- while (passes > 0)
- {
- float iscale = 1.f / scale;
- float s0 = xcenter * (1.f - iscale);
- float t0 = (1.0f - ycenter) * (1.f - iscale);
- float s1 = iscale + s0;
- float t1 = iscale + t0;
-
- srcBox[0] = s0 * srcFbo->width;
- srcBox[1] = t0 * srcFbo->height;
- srcBox[2] = (s1 - s0) * srcFbo->width;
- srcBox[3] = (t1 - t0) * srcFbo->height;
-
- FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
-
- scale *= mul;
- --passes;
- }
- }
-}
-
-
-static qboolean RB_UpdateSunFlareVis(void)
-{
- GLuint sampleCount = 0;
- if (!glRefConfig.occlusionQuery)
- return qtrue;
-
- tr.sunFlareQueryIndex ^= 1;
- if (!tr.sunFlareQueryActive[tr.sunFlareQueryIndex])
- return qtrue;
-
- /* debug code */
- if (0)
- {
- int iter;
- for (iter=0 ; ; ++iter)
- {
- GLint available = 0;
- qglGetQueryObjectivARB(tr.sunFlareQuery[tr.sunFlareQueryIndex], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
- if (available)
- break;
- }
-
- ri.Printf(PRINT_DEVELOPER, "Waited %d iterations\n", iter);
- }
-
- qglGetQueryObjectuivARB(tr.sunFlareQuery[tr.sunFlareQueryIndex], GL_QUERY_RESULT_ARB, &sampleCount);
- return sampleCount > 0;
-}
-
-void RB_SunRays(void)
-{
- vec4i_t srcBox, dstBox;
- vec4_t color;
- float dot;
- const float cutoff = 0.25f;
- qboolean colorize = qtrue;
-
-// float w, h, w2, h2;
- matrix_t mvp;
- vec4_t pos, hpos;
-
- dot = DotProduct(tr.sunDirection, backEnd.viewParms.or.axis[0]);
- if (dot < cutoff)
- return;
-
- if (!RB_UpdateSunFlareVis())
- return;
-
- // From RB_DrawSun()
- {
- float dist;
- matrix_t trans, model, mvp;
-
- Matrix16Translation( backEnd.viewParms.or.origin, trans );
- Matrix16Multiply( backEnd.viewParms.world.modelMatrix, trans, model );
- Matrix16Multiply(backEnd.viewParms.projectionMatrix, model, mvp);
-
- dist = backEnd.viewParms.zFar / 1.75; // div sqrt(3)
-
- VectorScale( tr.sunDirection, dist, pos );
- }
-
- // project sun point
- //Matrix16Multiply(backEnd.viewParms.projectionMatrix, backEnd.viewParms.world.modelMatrix, mvp);
- Matrix16Transform(mvp, pos, hpos);
-
- // transform to UV coords
- hpos[3] = 0.5f / hpos[3];
-
- pos[0] = 0.5f + hpos[0] * hpos[3];
- pos[1] = 0.5f - hpos[1] * hpos[3];
-
- // viewport dimensions
- // JBravo: Apparently not used
-/* w = glConfig.vidWidth;
- h = glConfig.vidHeight;
- w2 = glConfig.vidWidth / 2;
- h2 = glConfig.vidHeight / 2; */
-
- // initialize quarter buffers
- {
- float mul = 1.f;
- vec2_t texScale;
-
- texScale[0] =
- texScale[1] = 1.0f;
-
- VectorSet4(color, mul, mul, mul, 1);
-
- // first, downsample the framebuffer
- if (colorize)
- {
- FBO_FastBlit(tr.screenScratchFbo, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
- FBO_Blit(tr.sunRaysFbo, NULL, NULL, tr.quarterFbo[0], NULL, NULL, color, GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO);
- }
- else
- {
- FBO_FastBlit(tr.sunRaysFbo, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
- }
- }
-
- // radial blur passes, ping-ponging between the two quarter-size buffers
- {
- const float stretch_add = 2.f/3.f;
- float stretch = 1.f + stretch_add;
- int i;
- for (i=0; i<2; ++i)
- {
- RB_RadialBlur(tr.quarterFbo[i&1], tr.quarterFbo[(~i) & 1], 5, stretch, 0.f, 0.f, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height, pos[0], pos[1], 1.125f);
- stretch += stretch_add;
- }
- }
-
- // add result back on top of the main buffer
- {
- float mul = 1.f;
- vec2_t texScale;
-
- texScale[0] =
- texScale[1] = 1.0f;
-
- VectorSet4(color, mul, mul, mul, 1);
-
- VectorSet4(srcBox, 0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height);
- VectorSet4(dstBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
- FBO_Blit(tr.quarterFbo[0], srcBox, texScale, tr.screenScratchFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);
- }
-}
-
-static void RB_BlurAxis(FBO_t *srcFbo, FBO_t *dstFbo, float strength, qboolean horizontal)
-{
- float dx, dy;
- float xmul, ymul;
- float weights[3] = {
- 0.227027027f,
- 0.316216216f,
- 0.070270270f,
- };
- float offsets[3] = {
- 0.f,
- 1.3846153846f,
- 3.2307692308f,
- };
-
- xmul = horizontal;
- ymul = 1.f - xmul;
-
- xmul *= strength;
- ymul *= strength;
-
- {
- vec4i_t srcBox, dstBox;
- vec4_t color;
- vec2_t texScale;
-
- texScale[0] =
- texScale[1] = 1.0f;
-
- VectorSet4(color, weights[0], weights[0], weights[0], 1.0f);
- VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height);
- VectorSet4(dstBox, 0, 0, dstFbo->width, dstFbo->height);
- FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, 0 );
-
- VectorSet4(color, weights[1], weights[1], weights[1], 1.0f);
- dx = offsets[1] * xmul;
- dy = offsets[1] * ymul;
- VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height);
- FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
- VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height);
- FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
-
- VectorSet4(color, weights[2], weights[2], weights[2], 1.0f);
- dx = offsets[2] * xmul;
- dy = offsets[2] * ymul;
- VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height);
- FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
- VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height);
- FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
- }
-}
-
-static void RB_HBlur(FBO_t *srcFbo, FBO_t *dstFbo, float strength)
-{
- RB_BlurAxis(srcFbo, dstFbo, strength, qtrue);
-}
-
-static void RB_VBlur(FBO_t *srcFbo, FBO_t *dstFbo, float strength)
-{
- RB_BlurAxis(srcFbo, dstFbo, strength, qfalse);
-}
-
-void RB_GaussianBlur(float blur)
-{
- //float mul = 1.f;
- float factor = Com_Clamp(0.f, 1.f, blur);
-
- if (factor <= 0.f)
- return;
-
- {
- vec4i_t srcBox, dstBox;
- vec4_t color;
- vec2_t texScale;
-
- texScale[0] =
- texScale[1] = 1.0f;
-
- VectorSet4(color, 1, 1, 1, 1);
-
- // first, downsample the framebuffer
- FBO_FastBlit(tr.screenScratchFbo, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
- FBO_FastBlit(tr.quarterFbo[0], NULL, tr.textureScratchFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR);
-
- // set the alpha channel
- VectorSet4(srcBox, 0, 0, tr.whiteImage->width, tr.whiteImage->height);
- VectorSet4(dstBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height);
- qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
- FBO_BlitFromTexture(tr.whiteImage, srcBox, texScale, tr.textureScratchFbo[0], dstBox, &tr.textureColorShader, color, GLS_DEPTHTEST_DISABLE);
- qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-
- // blur the tiny buffer horizontally and vertically
- RB_HBlur(tr.textureScratchFbo[0], tr.textureScratchFbo[1], factor);
- RB_VBlur(tr.textureScratchFbo[1], tr.textureScratchFbo[0], factor);
-
- // finally, merge back to framebuffer
- VectorSet4(srcBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height);
- VectorSet4(dstBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight);
- color[3] = factor;
- FBO_Blit(tr.textureScratchFbo[0], srcBox, texScale, tr.screenScratchFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA);
- }
-}
diff --git a/src/rend2/tr_postprocess.h b/src/rend2/tr_postprocess.h
deleted file mode 100644
index 1e5ebefe..00000000
--- a/src/rend2/tr_postprocess.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 2011 Andrei Drexler, Richard Allen, James Canete
-
-This file is part of Reaction source code.
-
-Reaction source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Reaction source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Reaction source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-#ifndef TR_POSTPROCESS_H
-#define TR_POSTPROCESS_H
-
-#include "tr_fbo.h"
-
-void RB_ToneMap(FBO_t *hdrFbo, int autoExposure);
-void RB_BokehBlur(float blur);
-void RB_SunRays(void);
-void RB_GaussianBlur(float blur);
-
-#endif
diff --git a/src/rend2/tr_scene.c b/src/rend2/tr_scene.c
deleted file mode 100644
index 14c18339..00000000
--- a/src/rend2/tr_scene.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-#include "tr_local.h"
-
-int r_firstSceneDrawSurf;
-
-int r_numdlights;
-int r_firstSceneDlight;
-
-int r_numentities;
-int r_firstSceneEntity;
-
-int r_numpolys;
-int r_firstScenePoly;
-
-int r_numpolyverts;
-
-
-/*
-====================
-R_InitNextFrame
-
-====================
-*/
-void R_InitNextFrame( void ) {
- backEndData->commands.used = 0;
-
- r_firstSceneDrawSurf = 0;
-
- r_numdlights = 0;
- r_firstSceneDlight = 0;
-
- r_numentities = 0;
- r_firstSceneEntity = 0;
-
- r_numpolys = 0;
- r_firstScenePoly = 0;
-
- r_numpolyverts = 0;
-}
-
-
-/*
-====================
-RE_ClearScene
-
-====================
-*/
-void RE_ClearScene( void ) {
- r_firstSceneDlight = r_numdlights;
- r_firstSceneEntity = r_numentities;
- r_firstScenePoly = r_numpolys;
-}
-
-/*
-===========================================================================
-
-DISCRETE POLYS
-
-===========================================================================
-*/
-
-/*
-=====================
-R_AddPolygonSurfaces
-
-Adds all the scene's polys into this view's drawsurf list
-=====================
-*/
-void R_AddPolygonSurfaces( void ) {
- int i;
- shader_t *sh;
- srfPoly_t *poly;
-// JBravo: Fog fixes
- int fogMask;
-
- tr.currentEntityNum = REFENTITYNUM_WORLD;
- tr.shiftedEntityNum = tr.currentEntityNum << QSORT_REFENTITYNUM_SHIFT;
- fogMask = -((tr.refdef.rdflags & RDF_NOFOG) == 0);
-
- for ( i = 0, poly = tr.refdef.polys; i < tr.refdef.numPolys ; i++, poly++ ) {
- sh = R_GetShaderByHandle( poly->hShader );
- R_AddDrawSurf( ( void * )poly, sh, poly->fogIndex & fogMask, qfalse, qfalse );
- }
-}
-
-/*
-=====================
-RE_AddPolyToScene
-
-=====================
-*/
-void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ) {
- srfPoly_t *poly;
- int i, j;
- int fogIndex;
- fog_t *fog;
- vec3_t bounds[2];
-
- if ( !tr.registered ) {
- return;
- }
-
- if ( !hShader ) {
- // This isn't a useful warning, and an hShader of zero isn't a null shader, it's
- // the default shader.
- //ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolyToScene: NULL poly shader\n");
- //return;
- }
-
- for ( j = 0; j < numPolys; j++ ) {
- if ( r_numpolyverts + numVerts > max_polyverts || r_numpolys >= max_polys ) {
- /*
- NOTE TTimo this was initially a PRINT_WARNING
- but it happens a lot with high fighting scenes and particles
- since we don't plan on changing the const and making for room for those effects
- simply cut this message to developer only
- */
- ri.Printf( PRINT_DEVELOPER, "WARNING: RE_AddPolyToScene: r_max_polys or r_max_polyverts reached\n");
- return;
- }
-
- poly = &backEndData->polys[r_numpolys];
- poly->surfaceType = SF_POLY;
- poly->hShader = hShader;
- poly->numVerts = numVerts;
- poly->verts = &backEndData->polyVerts[r_numpolyverts];
-
- Com_Memcpy( poly->verts, &verts[numVerts*j], numVerts * sizeof( *verts ) );
-
- if ( glConfig.hardwareType == GLHW_RAGEPRO ) {
- poly->verts->modulate[0] = 255;
- poly->verts->modulate[1] = 255;
- poly->verts->modulate[2] = 255;
- poly->verts->modulate[3] = 255;
- }
- // done.
- r_numpolys++;
- r_numpolyverts += numVerts;
-
- // if no world is loaded
- if ( tr.world == NULL ) {
- fogIndex = 0;
- }
- // see if it is in a fog volume
- else if ( tr.world->numfogs == 1 ) {
- fogIndex = 0;
- } else {
- // find which fog volume the poly is in
- VectorCopy( poly->verts[0].xyz, bounds[0] );
- VectorCopy( poly->verts[0].xyz, bounds[1] );
- for ( i = 1 ; i < poly->numVerts ; i++ ) {
- AddPointToBounds( poly->verts[i].xyz, bounds[0], bounds[1] );
- }
- for ( fogIndex = 1 ; fogIndex < tr.world->numfogs ; fogIndex++ ) {
- fog = &tr.world->fogs[fogIndex];
- if ( bounds[1][0] >= fog->bounds[0][0]
- && bounds[1][1] >= fog->bounds[0][1]
- && bounds[1][2] >= fog->bounds[0][2]
- && bounds[0][0] <= fog->bounds[1][0]
- && bounds[0][1] <= fog->bounds[1][1]
- && bounds[0][2] <= fog->bounds[1][2] ) {
- break;
- }
- }
- if ( fogIndex == tr.world->numfogs ) {
- fogIndex = 0;
- }
- }
- poly->fogIndex = fogIndex;
- }
-}
-
-
-//=================================================================================
-
-
-/*
-=====================
-RE_AddRefEntityToScene
-
-=====================
-*/
-void RE_AddRefEntityToScene( const refEntity_t *ent ) {
- // JBravo: Mirrored models
- vec3_t cross;
-
- if ( !tr.registered ) {
- return;
- }
- if ( r_numentities >= MAX_REFENTITIES ) {
- ri.Printf(PRINT_DEVELOPER, "RE_AddRefEntityToScene: Dropping refEntity, reached MAX_REFENTITIES\n");
- return;
- }
- if ( Q_isnan(ent->origin[0]) || Q_isnan(ent->origin[1]) || Q_isnan(ent->origin[2]) ) {
- static qboolean firstTime = qtrue;
- if (firstTime) {
- firstTime = qfalse;
- ri.Printf( PRINT_WARNING, "RE_AddRefEntityToScene passed a refEntity which has an origin with a NaN component\n");
- }
- return;
- }
- if ( (int)ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) {
- ri.Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType );
- }
-
- backEndData->entities[r_numentities].e = *ent;
- backEndData->entities[r_numentities].lightingCalculated = qfalse;
-
- // JBravo: Mirrored models
- CrossProduct(ent->axis[0], ent->axis[1], cross);
- backEndData->entities[r_numentities].mirrored = (DotProduct(ent->axis[2], cross) < 0.f);
-
- r_numentities++;
-}
-
-
-/*
-=====================
-RE_AddDynamicLightToScene
-
-=====================
-*/
-void RE_AddDynamicLightToScene( const vec3_t org, float intensity, float r, float g, float b, int additive ) {
- dlight_t *dl;
-
- if ( !tr.registered ) {
- return;
- }
- if ( r_numdlights >= MAX_DLIGHTS ) {
- return;
- }
- if ( intensity <= 0 ) {
- return;
- }
- // these cards don't have the correct blend mode
- if ( glConfig.hardwareType == GLHW_RIVA128 || glConfig.hardwareType == GLHW_PERMEDIA2 ) {
- return;
- }
- dl = &backEndData->dlights[r_numdlights++];
- VectorCopy (org, dl->origin);
- dl->radius = intensity;
- dl->color[0] = r;
- dl->color[1] = g;
- dl->color[2] = b;
- dl->additive = additive;
-}
-
-/*
-=====================
-RE_AddLightToScene
-
-=====================
-*/
-void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
- RE_AddDynamicLightToScene( org, intensity, r, g, b, qfalse );
-}
-
-/*
-=====================
-RE_AddAdditiveLightToScene
-
-=====================
-*/
-void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
- RE_AddDynamicLightToScene( org, intensity, r, g, b, qtrue );
-}
-
-/*
-@@@@@@@@@@@@@@@@@@@@@
-RE_RenderScene
-
-Draw a 3D view into a part of the window, then return
-to 2D drawing.
-
-Rendering a scene may require multiple views to be rendered
-to handle mirrors,
-@@@@@@@@@@@@@@@@@@@@@
-*/
-void RE_RenderScene( const refdef_t *fd ) {
- viewParms_t parms;
- int startTime;
-
- if ( !tr.registered ) {
- return;
- }
- GLimp_LogComment( "====== RE_RenderScene =====\n" );
-
- if ( r_norefresh->integer ) {
- return;
- }
-
- startTime = ri.Milliseconds();
-
- if (!tr.world && !( fd->rdflags & RDF_NOWORLDMODEL ) ) {
- ri.Error (ERR_DROP, "R_RenderScene: NULL worldmodel");
- }
-
- Com_Memcpy( tr.refdef.text, fd->text, sizeof( tr.refdef.text ) );
-
- tr.refdef.x = fd->x;
- tr.refdef.y = fd->y;
- tr.refdef.width = fd->width;
- tr.refdef.height = fd->height;
- tr.refdef.fov_x = fd->fov_x;
- tr.refdef.fov_y = fd->fov_y;
-
- VectorCopy( fd->vieworg, tr.refdef.vieworg );
- VectorCopy( fd->viewaxis[0], tr.refdef.viewaxis[0] );
- VectorCopy( fd->viewaxis[1], tr.refdef.viewaxis[1] );
- VectorCopy( fd->viewaxis[2], tr.refdef.viewaxis[2] );
-
- tr.refdef.time = fd->time;
- tr.refdef.rdflags = fd->rdflags;
-
- // copy the areamask data over and note if it has changed, which
- // will force a reset of the visible leafs even if the view hasn't moved
- tr.refdef.areamaskModified = qfalse;
- if ( ! (tr.refdef.rdflags & RDF_NOWORLDMODEL) ) {
- int areaDiff;
- int i;
-
- // compare the area bits
- areaDiff = 0;
- for (i = 0 ; i < MAX_MAP_AREA_BYTES/4 ; i++) {
- areaDiff |= ((int *)tr.refdef.areamask)[i] ^ ((int *)fd->areamask)[i];
- ((int *)tr.refdef.areamask)[i] = ((int *)fd->areamask)[i];
- }
-
- if ( areaDiff ) {
- // a door just opened or something
- tr.refdef.areamaskModified = qtrue;
- }
- }
-
- tr.refdef.sunDir[3] = 0.0f;
- tr.refdef.sunCol[3] = 1.0f;
- tr.refdef.sunAmbCol[3] = 1.0f;
-
- VectorCopy(tr.sunDirection, tr.refdef.sunDir);
- if ( (tr.refdef.rdflags & RDF_NOWORLDMODEL) || !(r_depthPrepass->value) ){
- tr.refdef.colorScale = 1.0f;
- VectorSet(tr.refdef.sunCol, 0, 0, 0);
- VectorSet(tr.refdef.sunAmbCol, 0, 0, 0);
- }
- else if (r_forceSun->integer == 1)
- {
- float scale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits - 8);
- tr.refdef.colorScale = r_forceSunMapLightScale->value;
- VectorScale(tr.sunLight, scale * r_forceSunLightScale->value, tr.refdef.sunCol);
- VectorScale(tr.sunLight, scale * r_forceSunAmbientScale->value, tr.refdef.sunAmbCol);
- }
- else
- {
- float scale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits - 8);
- tr.refdef.colorScale = tr.mapLightScale;
- VectorScale(tr.sunLight, scale, tr.refdef.sunCol);
- VectorScale(tr.sunAmbient, scale, tr.refdef.sunAmbCol);
- }
-
- if (r_forceAutoExposure->integer)
- {
- tr.refdef.autoExposureMinMax[0] = r_forceAutoExposureMin->value;
- tr.refdef.autoExposureMinMax[1] = r_forceAutoExposureMax->value;
- }
- else
- {
- tr.refdef.autoExposureMinMax[0] = tr.autoExposureMinMax[0];
- tr.refdef.autoExposureMinMax[1] = tr.autoExposureMinMax[1];
- }
-
- if (r_forceToneMap->integer)
- {
- tr.refdef.toneMinAvgMaxLinear[0] = pow(2, r_forceToneMapMin->value);
- tr.refdef.toneMinAvgMaxLinear[1] = pow(2, r_forceToneMapAvg->value);
- tr.refdef.toneMinAvgMaxLinear[2] = pow(2, r_forceToneMapMax->value);
- }
- else
- {
- tr.refdef.toneMinAvgMaxLinear[0] = pow(2, tr.toneMinAvgMaxLevel[0]);
- tr.refdef.toneMinAvgMaxLinear[1] = pow(2, tr.toneMinAvgMaxLevel[1]);
- tr.refdef.toneMinAvgMaxLinear[2] = pow(2, tr.toneMinAvgMaxLevel[2]);
- }
-
- // Makro - copy exta info if present
- if (fd->rdflags & RDF_EXTRA) {
- const refdefex_t* extra = (const refdefex_t*) (fd+1);
-
- tr.refdef.blurFactor = extra->blurFactor;
-
- if (fd->rdflags & RDF_SUNLIGHT)
- {
- VectorCopy(extra->sunDir, tr.refdef.sunDir);
- VectorCopy(extra->sunCol, tr.refdef.sunCol);
- VectorCopy(extra->sunAmbCol, tr.refdef.sunAmbCol);
- }
- }
- else
- {
- tr.refdef.blurFactor = 0.0f;
- }
-
- // derived info
-
- tr.refdef.floatTime = tr.refdef.time * 0.001f;
-
- tr.refdef.numDrawSurfs = r_firstSceneDrawSurf;
- tr.refdef.drawSurfs = backEndData->drawSurfs;
-
- tr.refdef.num_entities = r_numentities - r_firstSceneEntity;
- tr.refdef.entities = &backEndData->entities[r_firstSceneEntity];
-
- tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight;
- tr.refdef.dlights = &backEndData->dlights[r_firstSceneDlight];
-
- tr.refdef.numPolys = r_numpolys - r_firstScenePoly;
- tr.refdef.polys = &backEndData->polys[r_firstScenePoly];
-
- tr.refdef.num_pshadows = 0;
- tr.refdef.pshadows = &backEndData->pshadows[0];
-
- // turn off dynamic lighting globally by clearing all the
- // dlights if it needs to be disabled or if vertex lighting is enabled
- if ( r_dynamiclight->integer == 0 ||
- r_vertexLight->integer == 1 ||
- glConfig.hardwareType == GLHW_PERMEDIA2 ) {
- tr.refdef.num_dlights = 0;
- }
-
- // a single frame may have multiple scenes draw inside it --
- // a 3D game view, 3D status bar renderings, 3D menus, etc.
- // They need to be distinguished by the light flare code, because
- // the visibility state for a given surface may be different in
- // each scene / view.
- tr.frameSceneNum++;
- tr.sceneCount++;
-
- // SmileTheory: playing with shadow mapping
- if (!( fd->rdflags & RDF_NOWORLDMODEL ) && tr.refdef.num_dlights && r_dlightMode->integer >= 2)
- {
- R_RenderDlightCubemaps(fd);
- }
-
- /* playing with more shadows */
- if(glRefConfig.framebufferObject && !( fd->rdflags & RDF_NOWORLDMODEL ) && r_shadows->integer == 4)
- {
- R_RenderPshadowMaps(fd);
- }
-
- // playing with even more shadows
- if(glRefConfig.framebufferObject && !( fd->rdflags & RDF_NOWORLDMODEL ) && (r_forceSun->integer || tr.sunShadows))
- {
- R_RenderSunShadowMaps(fd, 0);
- R_RenderSunShadowMaps(fd, 1);
- R_RenderSunShadowMaps(fd, 2);
- }
-
- // setup view parms for the initial view
- //
- // set up viewport
- // The refdef takes 0-at-the-top y coordinates, so
- // convert to GL's 0-at-the-bottom space
- //
- Com_Memset( &parms, 0, sizeof( parms ) );
- parms.viewportX = tr.refdef.x;
- parms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.refdef.height );
- parms.viewportWidth = tr.refdef.width;
- parms.viewportHeight = tr.refdef.height;
- parms.isPortal = qfalse;
-
- parms.fovX = tr.refdef.fov_x;
- parms.fovY = tr.refdef.fov_y;
-
- parms.stereoFrame = tr.refdef.stereoFrame;
-
- VectorCopy( fd->vieworg, parms.or.origin );
- VectorCopy( fd->viewaxis[0], parms.or.axis[0] );
- VectorCopy( fd->viewaxis[1], parms.or.axis[1] );
- VectorCopy( fd->viewaxis[2], parms.or.axis[2] );
-
- VectorCopy( fd->vieworg, parms.pvsOrigin );
-
- if(!( fd->rdflags & RDF_NOWORLDMODEL ) && r_depthPrepass->value && ((r_forceSun->integer) || tr.sunShadows))
- {
- parms.flags = VPF_USESUNLIGHT;
- }
-
- R_RenderView( &parms );
-
- if(!( fd->rdflags & RDF_NOWORLDMODEL ))
- R_AddPostProcessCmd();
-
- // the next scene rendered in this frame will tack on after this one
- r_firstSceneDrawSurf = tr.refdef.numDrawSurfs;
- r_firstSceneEntity = r_numentities;
- r_firstSceneDlight = r_numdlights;
- r_firstScenePoly = r_numpolys;
-
- tr.frontEndMsec += ri.Milliseconds() - startTime;
-}
diff --git a/src/rend2/tr_shade.c b/src/rend2/tr_shade.c
deleted file mode 100644
index b4758a86..00000000
--- a/src/rend2/tr_shade.c
+++ /dev/null
@@ -1,1866 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_shade.c
-
-#include "tr_local.h"
-#if idppc_altivec && !defined(MACOS_X)
-#include <altivec.h>
-#endif
-
-/*
-
- THIS ENTIRE FILE IS BACK END
-
- This file deals with applying shaders to surface data in the tess struct.
-*/
-
-
-/*
-==================
-R_DrawElements
-
-==================
-*/
-
-void R_DrawElementsVBO( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex, glIndex_t maxIndex )
-{
- if (glRefConfig.drawRangeElements)
- qglDrawRangeElementsEXT(GL_TRIANGLES, minIndex, maxIndex, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(GL_INDEX_TYPE)));
- else
- qglDrawElements(GL_TRIANGLES, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(GL_INDEX_TYPE)));
-
-}
-
-
-static void R_DrawMultiElementsVBO( int multiDrawPrimitives, glIndex_t *multiDrawMinIndex, glIndex_t *multiDrawMaxIndex,
- GLsizei *multiDrawNumIndexes, glIndex_t **multiDrawFirstIndex)
-{
- if (glRefConfig.multiDrawArrays)
- {
- qglMultiDrawElementsEXT(GL_TRIANGLES, multiDrawNumIndexes, GL_INDEX_TYPE, (const GLvoid **)multiDrawFirstIndex, multiDrawPrimitives);
- }
- else
- {
- int i;
-
- if (glRefConfig.drawRangeElements)
- {
- for (i = 0; i < multiDrawPrimitives; i++)
- {
- qglDrawRangeElementsEXT(GL_TRIANGLES, multiDrawMinIndex[i], multiDrawMaxIndex[i], multiDrawNumIndexes[i], GL_INDEX_TYPE, multiDrawFirstIndex[i]);
- }
- }
- else
- {
- for (i = 0; i < multiDrawPrimitives; i++)
- {
- qglDrawElements(GL_TRIANGLES, multiDrawNumIndexes[i], GL_INDEX_TYPE, multiDrawFirstIndex[i]);
- }
- }
- }
-}
-
-
-/*
-=============================================================
-
-SURFACE SHADERS
-
-=============================================================
-*/
-
-shaderCommands_t tess;
-
-
-/*
-=================
-R_BindAnimatedImageToTMU
-
-=================
-*/
-static void R_BindAnimatedImageToTMU( textureBundle_t *bundle, int tmu ) {
- int index;
-
- if ( bundle->isVideoMap ) {
- int oldtmu = glState.currenttmu;
- GL_SelectTexture(tmu);
- ri.CIN_RunCinematic(bundle->videoMapHandle);
- ri.CIN_UploadCinematic(bundle->videoMapHandle);
- GL_SelectTexture(oldtmu);
- return;
- }
-
- if ( bundle->numImageAnimations <= 1 ) {
- GL_BindToTMU( bundle->image[0], tmu);
- return;
- }
-
- // it is necessary to do this messy calc to make sure animations line up
- // exactly with waveforms of the same frequency
- index = ri.ftol(tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE);
- index >>= FUNCTABLE_SIZE2;
-
- if ( index < 0 ) {
- index = 0; // may happen with shader time offsets
- }
- index %= bundle->numImageAnimations;
-
- GL_BindToTMU( bundle->image[ index ], tmu );
-}
-
-
-/*
-================
-DrawTris
-
-Draws triangle outlines for debugging
-================
-*/
-static void DrawTris (shaderCommands_t *input) {
- GL_Bind( tr.whiteImage );
-
- GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
- qglDepthRange( 0, 0 );
-
- {
- shaderProgram_t *sp = &tr.textureColorShader;
- vec4_t color;
-
- GLSL_VertexAttribsState(ATTR_POSITION);
- GLSL_BindProgram(sp);
-
- GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
- VectorSet4(color, 1, 1, 1, 1);
- GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color);
-
- if (input->multiDrawPrimitives)
- {
- R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
- }
- else
- {
- R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
- }
- }
-
- qglDepthRange( 0, 1 );
-}
-
-
-/*
-================
-DrawNormals
-
-Draws vertex normals for debugging
-================
-*/
-static void DrawNormals (shaderCommands_t *input) {
- //FIXME: implement this
-}
-
-/*
-==============
-RB_BeginSurface
-
-We must set some things up before beginning any tesselation,
-because a surface may be forced to perform a RB_End due
-to overflow.
-==============
-*/
-void RB_BeginSurface( shader_t *shader, int fogNum ) {
-
- shader_t *state = (shader->remappedShader) ? shader->remappedShader : shader;
-
- tess.numIndexes = 0;
- tess.firstIndex = 0;
- tess.numVertexes = 0;
- tess.multiDrawPrimitives = 0;
- tess.shader = state;
- tess.fogNum = fogNum;
- tess.dlightBits = 0; // will be OR'd in by surface functions
- tess.pshadowBits = 0; // will be OR'd in by surface functions
- tess.xstages = state->stages;
- tess.numPasses = state->numUnfoggedPasses;
- tess.currentStageIteratorFunc = state->optimalStageIteratorFunc;
- tess.useInternalVBO = qtrue;
-
- tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
- if (tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime) {
- tess.shaderTime = tess.shader->clampTime;
- }
-
- if (backEnd.viewParms.flags & VPF_SHADOWMAP)
- {
- tess.currentStageIteratorFunc = RB_StageIteratorGeneric;
- }
-}
-
-
-
-extern float EvalWaveForm( const waveForm_t *wf );
-extern float EvalWaveFormClamped( const waveForm_t *wf );
-
-
-static void ComputeTexMatrix( shaderStage_t *pStage, int bundleNum, float *outmatrix)
-{
- int tm;
- float matrix[16], currentmatrix[16];
- textureBundle_t *bundle = &pStage->bundle[bundleNum];
-
- Matrix16Identity(outmatrix);
- Matrix16Identity(currentmatrix);
-
- for ( tm = 0; tm < bundle->numTexMods ; tm++ ) {
- switch ( bundle->texMods[tm].type )
- {
-
- case TMOD_NONE:
- tm = TR_MAX_TEXMODS; // break out of for loop
- break;
-
- case TMOD_TURBULENT:
- RB_CalcTurbulentTexMatrix( &bundle->texMods[tm].wave,
- matrix );
- outmatrix[12] = matrix[12];
- outmatrix[13] = matrix[13];
- Matrix16Copy(outmatrix, currentmatrix);
- break;
-
- case TMOD_ENTITY_TRANSLATE:
- RB_CalcScrollTexMatrix( backEnd.currentEntity->e.shaderTexCoord,
- matrix );
- Matrix16Multiply(matrix, currentmatrix, outmatrix);
- Matrix16Copy(outmatrix, currentmatrix);
- break;
-
- case TMOD_SCROLL:
- RB_CalcScrollTexMatrix( bundle->texMods[tm].scroll,
- matrix );
- Matrix16Multiply(matrix, currentmatrix, outmatrix);
- Matrix16Copy(outmatrix, currentmatrix);
- break;
-
- case TMOD_SCALE:
- RB_CalcScaleTexMatrix( bundle->texMods[tm].scale,
- matrix );
- Matrix16Multiply(matrix, currentmatrix, outmatrix);
- Matrix16Copy(outmatrix, currentmatrix);
- break;
-
- case TMOD_STRETCH:
- RB_CalcStretchTexMatrix( &bundle->texMods[tm].wave,
- matrix );
- Matrix16Multiply(matrix, currentmatrix, outmatrix);
- Matrix16Copy(outmatrix, currentmatrix);
- break;
-
- case TMOD_TRANSFORM:
- RB_CalcTransformTexMatrix( &bundle->texMods[tm],
- matrix );
- Matrix16Multiply(matrix, currentmatrix, outmatrix);
- Matrix16Copy(outmatrix, currentmatrix);
- break;
-
- case TMOD_ROTATE:
- RB_CalcRotateTexMatrix( bundle->texMods[tm].rotateSpeed,
- matrix );
- Matrix16Multiply(matrix, currentmatrix, outmatrix);
- Matrix16Copy(outmatrix, currentmatrix);
- break;
-
- default:
- ri.Error( ERR_DROP, "ERROR: unknown texmod '%d' in shader '%s'", bundle->texMods[tm].type, tess.shader->name );
- break;
- }
- }
-}
-
-
-static void ComputeDeformValues(int *deformGen, vec5_t deformParams)
-{
- // u_DeformGen
- *deformGen = DGEN_NONE;
- if(!ShaderRequiresCPUDeforms(tess.shader))
- {
- deformStage_t *ds;
-
- // only support the first one
- ds = &tess.shader->deforms[0];
-
- switch (ds->deformation)
- {
- case DEFORM_WAVE:
- *deformGen = ds->deformationWave.func;
-
- deformParams[0] = ds->deformationWave.base;
- deformParams[1] = ds->deformationWave.amplitude;
- deformParams[2] = ds->deformationWave.phase;
- deformParams[3] = ds->deformationWave.frequency;
- deformParams[4] = ds->deformationSpread;
- break;
-
- case DEFORM_BULGE:
- *deformGen = DGEN_BULGE;
-
- deformParams[0] = 0;
- deformParams[1] = ds->bulgeHeight; // amplitude
- deformParams[2] = ds->bulgeWidth; // phase
- deformParams[3] = ds->bulgeSpeed; // frequency
- deformParams[4] = 0;
- break;
-
- default:
- break;
- }
- }
-}
-
-
-static void ProjectDlightTexture( void ) {
- int l;
- vec3_t origin;
- float scale;
- float radius;
- int deformGen;
- vec5_t deformParams;
-
- if ( !backEnd.refdef.num_dlights ) {
- return;
- }
-
- ComputeDeformValues(&deformGen, deformParams);
-
- for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) {
- dlight_t *dl;
- shaderProgram_t *sp;
- vec4_t vector;
-
- if ( !( tess.dlightBits & ( 1 << l ) ) ) {
- continue; // this surface definately doesn't have any of this light
- }
-
- dl = &backEnd.refdef.dlights[l];
- VectorCopy( dl->transformed, origin );
- radius = dl->radius;
- scale = 1.0f / radius;
-
- sp = &tr.dlightShader[deformGen == DGEN_NONE ? 0 : 1];
-
- backEnd.pc.c_dlightDraws++;
-
- GLSL_BindProgram(sp);
-
- GLSL_SetUniformMatrix16(sp, DLIGHT_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
-
- GLSL_SetUniformFloat(sp, DLIGHT_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
-
- GLSL_SetUniformInt(sp, DLIGHT_UNIFORM_DEFORMGEN, deformGen);
- if (deformGen != DGEN_NONE)
- {
- GLSL_SetUniformFloat5(sp, DLIGHT_UNIFORM_DEFORMPARAMS, deformParams);
- GLSL_SetUniformFloat(sp, DLIGHT_UNIFORM_TIME, tess.shaderTime);
- }
-
- vector[0] = dl->color[0];
- vector[1] = dl->color[1];
- vector[2] = dl->color[2];
- vector[3] = 1.0f;
- GLSL_SetUniformVec4(sp, DLIGHT_UNIFORM_COLOR, vector);
-
- vector[0] = origin[0];
- vector[1] = origin[1];
- vector[2] = origin[2];
- vector[3] = scale;
- GLSL_SetUniformVec4(sp, DLIGHT_UNIFORM_DLIGHTINFO, vector);
-
- GL_Bind( tr.dlightImage );
-
- // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
- // where they aren't rendered
- if ( dl->additive ) {
- GL_State( GLS_ATEST_GT_0 | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
- }
- else {
- GL_State( GLS_ATEST_GT_0 | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
- }
-
- if (tess.multiDrawPrimitives)
- {
- shaderCommands_t *input = &tess;
- R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
- }
- else
- {
- R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);
- }
-
- backEnd.pc.c_totalIndexes += tess.numIndexes;
- backEnd.pc.c_dlightIndexes += tess.numIndexes;
- }
-}
-
-
-static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor )
-{
- //
- // rgbGen
- //
- switch ( pStage->rgbGen )
- {
- case CGEN_IDENTITY:
- baseColor[0] =
- baseColor[1] =
- baseColor[2] =
- baseColor[3] = 1.0f;
-
- vertColor[0] =
- vertColor[1] =
- vertColor[2] =
- vertColor[3] = 0.0f;
- break;
- case CGEN_IDENTITY_LIGHTING:
- baseColor[0] =
- baseColor[1] =
- baseColor[2] = tr.identityLight;
- baseColor[3] = 1.0f;
-
- vertColor[0] =
- vertColor[1] =
- vertColor[2] =
- vertColor[3] = 0.0f;
- break;
- case CGEN_EXACT_VERTEX:
- baseColor[0] =
- baseColor[1] =
- baseColor[2] =
- baseColor[3] = 0.0f;
-
- vertColor[0] =
- vertColor[1] =
- vertColor[2] =
- vertColor[3] = 1.0f;
- break;
- case CGEN_EXACT_VERTEX_LIT:
- baseColor[0] =
- baseColor[1] =
- baseColor[2] =
- baseColor[3] = 0.0f;
-
- vertColor[0] =
- vertColor[1] =
- vertColor[2] =
- vertColor[3] = 1.0f;
- break;
- case CGEN_CONST:
- baseColor[0] = pStage->constantColor[0] / 255.0f;
- baseColor[1] = pStage->constantColor[1] / 255.0f;
- baseColor[2] = pStage->constantColor[2] / 255.0f;
- baseColor[3] = pStage->constantColor[3] / 255.0f;
-
- vertColor[0] =
- vertColor[1] =
- vertColor[2] =
- vertColor[3] = 0.0f;
- break;
- case CGEN_VERTEX:
- baseColor[0] =
- baseColor[1] =
- baseColor[2] =
- baseColor[3] = 0.0f;
-
- vertColor[0] =
- vertColor[1] =
- vertColor[2] = tr.identityLight;
- vertColor[3] = 1.0f;
- break;
- case CGEN_VERTEX_LIT:
- baseColor[0] =
- baseColor[1] =
- baseColor[2] =
- baseColor[3] = 0.0f;
-
- vertColor[0] =
- vertColor[1] =
- vertColor[2] =
- vertColor[3] = tr.identityLight;
- break;
- case CGEN_ONE_MINUS_VERTEX:
- baseColor[0] =
- baseColor[1] =
- baseColor[2] = tr.identityLight;
- baseColor[3] = 1.0f;
-
- vertColor[0] =
- vertColor[1] =
- vertColor[2] = -tr.identityLight;
- vertColor[3] = 0.0f;
- break;
- case CGEN_FOG:
- {
- fog_t *fog;
-
- fog = tr.world->fogs + tess.fogNum;
-
- baseColor[0] = ((unsigned char *)(&fog->colorInt))[0] / 255.0f;
- baseColor[1] = ((unsigned char *)(&fog->colorInt))[1] / 255.0f;
- baseColor[2] = ((unsigned char *)(&fog->colorInt))[2] / 255.0f;
- baseColor[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f;
- }
-
- vertColor[0] =
- vertColor[1] =
- vertColor[2] =
- vertColor[3] = 0.0f;
- break;
- case CGEN_WAVEFORM:
- baseColor[0] =
- baseColor[1] =
- baseColor[2] = RB_CalcWaveColorSingle( &pStage->rgbWave );
- baseColor[3] = 1.0f;
-
- vertColor[0] =
- vertColor[1] =
- vertColor[2] =
- vertColor[3] = 0.0f;
- break;
- case CGEN_ENTITY:
- if (backEnd.currentEntity)
- {
- baseColor[0] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[0] / 255.0f;
- baseColor[1] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[1] / 255.0f;
- baseColor[2] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f;
- baseColor[3] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f;
- }
-
- vertColor[0] =
- vertColor[1] =
- vertColor[2] =
- vertColor[3] = 0.0f;
- break;
- case CGEN_ONE_MINUS_ENTITY:
- if (backEnd.currentEntity)
- {
- baseColor[0] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[0] / 255.0f;
- baseColor[1] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[1] / 255.0f;
- baseColor[2] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[2] / 255.0f;
- baseColor[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f;
- }
-
- vertColor[0] =
- vertColor[1] =
- vertColor[2] =
- vertColor[3] = 0.0f;
- break;
- case CGEN_LIGHTING_DIFFUSE:
- case CGEN_BAD:
- baseColor[0] =
- baseColor[1] =
- baseColor[2] =
- baseColor[3] = 1.0f;
-
- vertColor[0] =
- vertColor[1] =
- vertColor[2] =
- vertColor[3] = 0.0f;
- break;
- }
-
- //
- // alphaGen
- //
- switch ( pStage->alphaGen )
- {
- case AGEN_SKIP:
- break;
- case AGEN_IDENTITY:
- baseColor[3] = 1.0f;
- vertColor[3] = 0.0f;
- break;
- case AGEN_CONST:
- baseColor[3] = pStage->constantColor[3] / 255.0f;
- vertColor[3] = 0.0f;
- break;
- case AGEN_WAVEFORM:
- baseColor[3] = RB_CalcWaveAlphaSingle( &pStage->alphaWave );
- vertColor[3] = 0.0f;
- break;
- case AGEN_ENTITY:
- if (backEnd.currentEntity)
- {
- baseColor[3] = ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f;
- }
- vertColor[3] = 0.0f;
- break;
- case AGEN_ONE_MINUS_ENTITY:
- if (backEnd.currentEntity)
- {
- baseColor[3] = 1.0f - ((unsigned char *)backEnd.currentEntity->e.shaderRGBA)[3] / 255.0f;
- }
- vertColor[3] = 0.0f;
- break;
- case AGEN_VERTEX:
- baseColor[3] = 0.0f;
- vertColor[3] = 1.0f;
- break;
- case AGEN_ONE_MINUS_VERTEX:
- baseColor[3] = 1.0f;
- vertColor[3] = -1.0f;
- break;
- case AGEN_LIGHTING_SPECULAR:
- case AGEN_PORTAL:
- case AGEN_FRESNEL:
- // Done entirely in vertex program
- baseColor[3] = 1.0f;
- vertColor[3] = 0.0f;
- break;
- }
-
- // FIXME: find some way to implement this.
-#if 0
- // if in greyscale rendering mode turn all color values into greyscale.
- if(r_greyscale->integer)
- {
- int scale;
-
- for(i = 0; i < tess.numVertexes; i++)
- {
- scale = (tess.svars.colors[i][0] + tess.svars.colors[i][1] + tess.svars.colors[i][2]) / 3;
- tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale;
- }
- }
-#endif
-}
-
-
-static void ComputeFogValues(vec4_t fogDistanceVector, vec4_t fogDepthVector, float *eyeT)
-{
- // from RB_CalcFogTexCoords()
- fog_t *fog;
- vec3_t local;
-
- if (!tess.fogNum)
- return;
-
- fog = tr.world->fogs + tess.fogNum;
-
- VectorSubtract( backEnd.or.origin, backEnd.viewParms.or.origin, local );
- fogDistanceVector[0] = -backEnd.or.modelMatrix[2];
- fogDistanceVector[1] = -backEnd.or.modelMatrix[6];
- fogDistanceVector[2] = -backEnd.or.modelMatrix[10];
- fogDistanceVector[3] = DotProduct( local, backEnd.viewParms.or.axis[0] );
-
- // scale the fog vectors based on the fog's thickness
- VectorScale4(fogDistanceVector, fog->tcScale, fogDistanceVector);
-
- // rotate the gradient vector for this orientation
- if ( fog->hasSurface ) {
- fogDepthVector[0] = fog->surface[0] * backEnd.or.axis[0][0] +
- fog->surface[1] * backEnd.or.axis[0][1] + fog->surface[2] * backEnd.or.axis[0][2];
- fogDepthVector[1] = fog->surface[0] * backEnd.or.axis[1][0] +
- fog->surface[1] * backEnd.or.axis[1][1] + fog->surface[2] * backEnd.or.axis[1][2];
- fogDepthVector[2] = fog->surface[0] * backEnd.or.axis[2][0] +
- fog->surface[1] * backEnd.or.axis[2][1] + fog->surface[2] * backEnd.or.axis[2][2];
- fogDepthVector[3] = -fog->surface[3] + DotProduct( backEnd.or.origin, fog->surface );
-
- *eyeT = DotProduct( backEnd.or.viewOrigin, fogDepthVector ) + fogDepthVector[3];
- } else {
- *eyeT = 1; // non-surface fog always has eye inside
- }
-}
-
-
-static void ComputeFogColorMask( shaderStage_t *pStage, vec4_t fogColorMask )
-{
- switch(pStage->adjustColorsForFog)
- {
- case ACFF_MODULATE_RGB:
- fogColorMask[0] =
- fogColorMask[1] =
- fogColorMask[2] = 1.0f;
- fogColorMask[3] = 0.0f;
- break;
- case ACFF_MODULATE_ALPHA:
- fogColorMask[0] =
- fogColorMask[1] =
- fogColorMask[2] = 0.0f;
- fogColorMask[3] = 1.0f;
- break;
- case ACFF_MODULATE_RGBA:
- fogColorMask[0] =
- fogColorMask[1] =
- fogColorMask[2] =
- fogColorMask[3] = 1.0f;
- break;
- default:
- fogColorMask[0] =
- fogColorMask[1] =
- fogColorMask[2] =
- fogColorMask[3] = 0.0f;
- break;
- }
-}
-
-
-static void ForwardDlight( void ) {
- int l;
- //vec3_t origin;
- //float scale;
- float radius;
-
- int deformGen;
- vec5_t deformParams;
-
- vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0};
- float eyeT = 0;
-
- shaderCommands_t *input = &tess;
- shaderStage_t *pStage = tess.xstages[0];
-
- if ( !backEnd.refdef.num_dlights ) {
- return;
- }
-
- ComputeDeformValues(&deformGen, deformParams);
-
- ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT);
-
- for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) {
- dlight_t *dl;
- shaderProgram_t *sp;
- vec4_t vector;
- matrix_t matrix;
-
- if ( !( tess.dlightBits & ( 1 << l ) ) ) {
- continue; // this surface definately doesn't have any of this light
- }
-
- dl = &backEnd.refdef.dlights[l];
- //VectorCopy( dl->transformed, origin );
- radius = dl->radius;
- //scale = 1.0f / radius;
-
- //if (pStage->glslShaderGroup == tr.lightallShader)
- {
- int index = pStage->glslShaderIndex;
-
- index &= ~(LIGHTDEF_LIGHTTYPE_MASK | LIGHTDEF_USE_DELUXEMAP);
- index |= LIGHTDEF_USE_LIGHT_VECTOR;
-
- sp = &tr.lightallShader[index];
- }
-
- backEnd.pc.c_lightallDraws++;
-
- GLSL_BindProgram(sp);
-
- GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
- GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin);
-
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
-
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, deformGen);
- if (deformGen != DGEN_NONE)
- {
- GLSL_SetUniformFloat5(sp, GENERIC_UNIFORM_DEFORMPARAMS, deformParams);
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_TIME, tess.shaderTime);
- }
-
- if ( input->fogNum ) {
- vec4_t fogColorMask;
-
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDISTANCE, fogDistanceVector);
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDEPTH, fogDepthVector);
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_FOGEYET, eyeT);
-
- ComputeFogColorMask(pStage, fogColorMask);
-
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGCOLORMASK, fogColorMask);
- }
-
- {
- vec4_t baseColor;
- vec4_t vertColor;
-
- ComputeShaderColors(pStage, baseColor, vertColor);
-
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_BASECOLOR, baseColor);
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_VERTCOLOR, vertColor);
- }
-
- if (pStage->alphaGen == AGEN_PORTAL)
- {
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_PORTALRANGE, tess.shader->portalRange);
- }
-
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_COLORGEN, pStage->rgbGen);
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_ALPHAGEN, pStage->alphaGen);
-
- GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_DIRECTEDLIGHT, dl->color);
-
- VectorSet(vector, 0, 0, 0);
- GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_AMBIENTLIGHT, vector);
-
- VectorCopy(dl->origin, vector);
- vector[3] = 1.0f;
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_LIGHTORIGIN, vector);
-
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_LIGHTRADIUS, radius);
-
- GLSL_SetUniformVec2(sp, GENERIC_UNIFORM_MATERIALINFO, pStage->materialInfo);
-
- // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
- // where they aren't rendered
- GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
-
- GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELMATRIX, backEnd.or.transformMatrix);
-
- if (pStage->bundle[TB_DIFFUSEMAP].image[0])
- R_BindAnimatedImageToTMU( &pStage->bundle[TB_DIFFUSEMAP], TB_DIFFUSEMAP);
-
- if (pStage->bundle[TB_NORMALMAP].image[0])
- R_BindAnimatedImageToTMU( &pStage->bundle[TB_NORMALMAP], TB_NORMALMAP);
-
- if (pStage->bundle[TB_SPECULARMAP].image[0])
- R_BindAnimatedImageToTMU( &pStage->bundle[TB_SPECULARMAP], TB_SPECULARMAP);
-
- if (r_dlightMode->integer >= 2)
- {
- GL_SelectTexture(TB_SHADOWMAP);
- GL_BindCubemap(tr.shadowCubemaps[l]);
- GL_SelectTexture(0);
- }
-
- ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix );
-
- VectorSet4(vector, matrix[0], matrix[1], matrix[4], matrix[5]);
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_DIFFUSETEXMATRIX, vector);
-
- VectorSet4(vector, matrix[8], matrix[9], matrix[12], matrix[13]);
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_DIFFUSETEXOFFTURB, vector);
-
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_TCGEN0, pStage->bundle[0].tcGen);
-
- //
- // draw
- //
-
- if (input->multiDrawPrimitives)
- {
- R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
- }
- else
- {
- R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
- }
-
- backEnd.pc.c_totalIndexes += tess.numIndexes;
- backEnd.pc.c_dlightIndexes += tess.numIndexes;
- }
-}
-
-
-static void ForwardSunlight( void ) {
-// int l;
- //vec3_t origin;
- //float scale;
- int stage;
- int stageGlState[2];
- qboolean alphaOverride = qfalse;
-
- int deformGen;
- vec5_t deformParams;
-
- vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0};
- float eyeT = 0;
-
- shaderCommands_t *input = &tess;
-
- ComputeDeformValues(&deformGen, deformParams);
-
- ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT);
-
- // deal with vertex alpha blended surfaces
- if (input->xstages[0] && input->xstages[1] &&
- (input->xstages[1]->alphaGen == AGEN_VERTEX || input->xstages[1]->alphaGen == AGEN_ONE_MINUS_VERTEX))
- {
- stageGlState[0] = input->xstages[0]->stateBits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS);
-
- if (stageGlState[0] == 0 || stageGlState[0] == (GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO))
- {
- stageGlState[1] = input->xstages[1]->stateBits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS);
-
- if (stageGlState[1] == (GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA))
- {
- alphaOverride = qtrue;
- stageGlState[0] = GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL;
- stageGlState[1] = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL;
- }
- else if (stageGlState[1] == (GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA | GLS_DSTBLEND_SRC_ALPHA))
- {
- alphaOverride = qtrue;
- stageGlState[0] = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL;
- stageGlState[1] = GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL;
- }
- }
- }
-
- if (!alphaOverride)
- {
- stageGlState[0] =
- stageGlState[1] = GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL;
- }
-
- for ( stage = 0; stage < 2 /*MAX_SHADER_STAGES */; stage++ )
- {
- shaderStage_t *pStage = input->xstages[stage];
- shaderProgram_t *sp;
- vec4_t vector;
- matrix_t matrix;
-
- if ( !pStage )
- {
- break;
- }
-
- //VectorCopy( dl->transformed, origin );
-
- //if (pStage->glslShaderGroup == tr.lightallShader)
- {
- int index = pStage->glslShaderIndex;
-
- index &= ~(LIGHTDEF_LIGHTTYPE_MASK | LIGHTDEF_USE_DELUXEMAP);
- index |= LIGHTDEF_USE_LIGHT_VECTOR | LIGHTDEF_USE_SHADOWMAP;
-
- if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
- {
- index |= LIGHTDEF_ENTITY;
- }
-
- sp = &tr.lightallShader[index];
- }
-
- backEnd.pc.c_lightallDraws++;
-
- GLSL_BindProgram(sp);
-
- GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
- GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin);
-
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
-
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, deformGen);
- if (deformGen != DGEN_NONE)
- {
- GLSL_SetUniformFloat5(sp, GENERIC_UNIFORM_DEFORMPARAMS, deformParams);
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_TIME, tess.shaderTime);
- }
-
- if ( input->fogNum ) {
- vec4_t fogColorMask;
-
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDISTANCE, fogDistanceVector);
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDEPTH, fogDepthVector);
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_FOGEYET, eyeT);
-
- ComputeFogColorMask(pStage, fogColorMask);
-
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGCOLORMASK, fogColorMask);
- }
-
- {
- vec4_t baseColor;
- vec4_t vertColor;
-
- ComputeShaderColors(pStage, baseColor, vertColor);
-
- if (alphaOverride)
- {
- if (input->xstages[1]->alphaGen == AGEN_VERTEX)
- {
- baseColor[3] = 0.0f;
- vertColor[3] = 1.0f;
- }
- else if (input->xstages[1]->alphaGen == AGEN_ONE_MINUS_VERTEX)
- {
- baseColor[3] = 1.0f;
- vertColor[3] = -1.0f;
- }
- }
-
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_BASECOLOR, baseColor);
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_VERTCOLOR, vertColor);
- }
-
- if (pStage->alphaGen == AGEN_PORTAL)
- {
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_PORTALRANGE, tess.shader->portalRange);
- }
-
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_COLORGEN, pStage->rgbGen);
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_ALPHAGEN, pStage->alphaGen);
-
- GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_DIRECTEDLIGHT, backEnd.refdef.sunCol);
- GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_AMBIENTLIGHT, backEnd.refdef.sunAmbCol);
-
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_LIGHTORIGIN, backEnd.refdef.sunDir);
-
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_LIGHTRADIUS, 9999999999.9f);
-
- GLSL_SetUniformVec2(sp, GENERIC_UNIFORM_MATERIALINFO, pStage->materialInfo);
-
- GL_State( stageGlState[stage] );
-
- GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELMATRIX, backEnd.or.transformMatrix);
-
- if (pStage->bundle[TB_DIFFUSEMAP].image[0])
- R_BindAnimatedImageToTMU( &pStage->bundle[TB_DIFFUSEMAP], TB_DIFFUSEMAP);
-
- if (pStage->bundle[TB_NORMALMAP].image[0])
- R_BindAnimatedImageToTMU( &pStage->bundle[TB_NORMALMAP], TB_NORMALMAP);
-
- if (pStage->bundle[TB_SPECULARMAP].image[0])
- R_BindAnimatedImageToTMU( &pStage->bundle[TB_SPECULARMAP], TB_SPECULARMAP);
-
- /*
- {
- GL_BindToTMU(tr.sunShadowDepthImage[0], TB_SHADOWMAP);
- GL_BindToTMU(tr.sunShadowDepthImage[1], TB_SHADOWMAP2);
- GL_BindToTMU(tr.sunShadowDepthImage[2], TB_SHADOWMAP3);
- GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[0]);
- GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]);
- GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]);
- }
- */
- GL_BindToTMU(tr.screenShadowImage, TB_SHADOWMAP);
-
- ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix );
-
- VectorSet4(vector, matrix[0], matrix[1], matrix[4], matrix[5]);
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_DIFFUSETEXMATRIX, vector);
-
- VectorSet4(vector, matrix[8], matrix[9], matrix[12], matrix[13]);
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_DIFFUSETEXOFFTURB, vector);
-
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_TCGEN0, pStage->bundle[0].tcGen);
-
- //
- // draw
- //
-
- if (input->multiDrawPrimitives)
- {
- R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
- }
- else
- {
- R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
- }
-
- backEnd.pc.c_totalIndexes += tess.numIndexes;
- backEnd.pc.c_dlightIndexes += tess.numIndexes;
- }
-}
-
-
-static void ProjectPshadowVBOGLSL( void ) {
- int l;
- vec3_t origin;
- float radius;
-
- int deformGen;
- vec5_t deformParams;
-
- shaderCommands_t *input = &tess;
-
- if ( !backEnd.refdef.num_pshadows ) {
- return;
- }
-
- ComputeDeformValues(&deformGen, deformParams);
-
- for ( l = 0 ; l < backEnd.refdef.num_pshadows ; l++ ) {
- pshadow_t *ps;
- shaderProgram_t *sp;
- vec4_t vector;
-
- if ( !( tess.pshadowBits & ( 1 << l ) ) ) {
- continue; // this surface definately doesn't have any of this shadow
- }
-
- ps = &backEnd.refdef.pshadows[l];
- VectorCopy( ps->lightOrigin, origin );
- radius = ps->lightRadius;
-
- sp = &tr.pshadowShader;
-
- GLSL_BindProgram(sp);
-
- GLSL_SetUniformMatrix16(sp, PSHADOW_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
-
- VectorCopy(origin, vector);
- vector[3] = 1.0f;
- GLSL_SetUniformVec4(sp, PSHADOW_UNIFORM_LIGHTORIGIN, vector);
-
- VectorScale(ps->lightViewAxis[0], 1.0f / ps->viewRadius, vector);
- GLSL_SetUniformVec3(sp, PSHADOW_UNIFORM_LIGHTFORWARD, vector);
-
- VectorScale(ps->lightViewAxis[1], 1.0f / ps->viewRadius, vector);
- GLSL_SetUniformVec3(sp, PSHADOW_UNIFORM_LIGHTRIGHT, vector);
-
- VectorScale(ps->lightViewAxis[2], 1.0f / ps->viewRadius, vector);
- GLSL_SetUniformVec3(sp, PSHADOW_UNIFORM_LIGHTUP, vector);
-
- GLSL_SetUniformFloat(sp, PSHADOW_UNIFORM_LIGHTRADIUS, radius);
-
- // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
- // where they aren't rendered
- GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL );
-
- GL_BindToTMU( tr.pshadowMaps[l], TB_DIFFUSEMAP );
-
- //
- // draw
- //
-
- if (input->multiDrawPrimitives)
- {
- R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
- }
- else
- {
- R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
- }
-
- backEnd.pc.c_totalIndexes += tess.numIndexes;
- //backEnd.pc.c_dlightIndexes += tess.numIndexes;
- }
-}
-
-
-
-/*
-===================
-RB_FogPass
-
-Blends a fog texture on top of everything else
-===================
-*/
-static void RB_FogPass( void ) {
- fog_t *fog;
- vec4_t color;
- vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0};
- float eyeT = 0;
- shaderProgram_t *sp;
-
- int deformGen;
- vec5_t deformParams;
-
- ComputeDeformValues(&deformGen, deformParams);
-
- {
- int index = 0;
-
- if (deformGen != DGEN_NONE)
- index |= FOGDEF_USE_DEFORM_VERTEXES;
-
- if (glState.vertexAttribsInterpolation)
- index |= FOGDEF_USE_VERTEX_ANIMATION;
-
- sp = &tr.fogShader[index];
- }
-
- backEnd.pc.c_fogDraws++;
-
- GLSL_BindProgram(sp);
-
- fog = tr.world->fogs + tess.fogNum;
-
- GLSL_SetUniformMatrix16(sp, FOGPASS_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
-
- GLSL_SetUniformFloat(sp, FOGPASS_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
-
- GLSL_SetUniformInt(sp, FOGPASS_UNIFORM_DEFORMGEN, deformGen);
- if (deformGen != DGEN_NONE)
- {
- GLSL_SetUniformFloat5(sp, FOGPASS_UNIFORM_DEFORMPARAMS, deformParams);
- GLSL_SetUniformFloat(sp, FOGPASS_UNIFORM_TIME, tess.shaderTime);
- }
-
- color[0] = ((unsigned char *)(&fog->colorInt))[0] / 255.0f;
- color[1] = ((unsigned char *)(&fog->colorInt))[1] / 255.0f;
- color[2] = ((unsigned char *)(&fog->colorInt))[2] / 255.0f;
- color[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f;
- GLSL_SetUniformVec4(sp, FOGPASS_UNIFORM_COLOR, color);
-
- ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT);
-
- GLSL_SetUniformVec4(sp, FOGPASS_UNIFORM_FOGDISTANCE, fogDistanceVector);
- GLSL_SetUniformVec4(sp, FOGPASS_UNIFORM_FOGDEPTH, fogDepthVector);
- GLSL_SetUniformFloat(sp, FOGPASS_UNIFORM_FOGEYET, eyeT);
-
- if ( tess.shader->fogPass == FP_EQUAL ) {
- GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL );
- } else {
- GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
- }
-
- if (tess.multiDrawPrimitives)
- {
- shaderCommands_t *input = &tess;
- R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
- }
- else
- {
- R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);
- }
-}
-
-
-static unsigned int RB_CalcShaderVertexAttribs( shaderCommands_t *input )
-{
- unsigned int vertexAttribs = input->shader->vertexAttribs;
-
- if(glState.vertexAttribsInterpolation > 0.0f)
- {
- vertexAttribs |= ATTR_POSITION2;
- if (vertexAttribs & ATTR_NORMAL)
- {
- vertexAttribs |= ATTR_NORMAL2;
-#ifdef USE_VERT_TANGENT_SPACE
- vertexAttribs |= ATTR_TANGENT2;
- vertexAttribs |= ATTR_BITANGENT2;
-#endif
- }
- }
-
- return vertexAttribs;
-}
-
-static void RB_IterateStagesGeneric( shaderCommands_t *input )
-{
- int stage;
- matrix_t matrix;
-
- vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0};
- float eyeT = 0;
-
- int deformGen;
- vec5_t deformParams;
-
- ComputeDeformValues(&deformGen, deformParams);
-
- ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT);
-
- for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ )
- {
- shaderStage_t *pStage = input->xstages[stage];
- shaderProgram_t *sp;
-
- if ( !pStage )
- {
- break;
- }
-
- if (backEnd.depthFill)
- {
- if (pStage->glslShaderGroup)
- {
- int index = 0;
-
- if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
- {
- index |= LIGHTDEF_ENTITY;
- }
-
- if (pStage->stateBits & GLS_ATEST_BITS)
- {
- index |= LIGHTDEF_USE_TCGEN_AND_TCMOD;
- }
-
- sp = &pStage->glslShaderGroup[index];
- }
- else
- {
- int shaderAttribs = 0;
-
- if (tess.shader->numDeforms && !ShaderRequiresCPUDeforms(tess.shader))
- {
- shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES;
- }
-
- if (glState.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
- {
- shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION;
- }
-
- if (pStage->stateBits & GLS_ATEST_BITS)
- {
- shaderAttribs |= GENERICDEF_USE_TCGEN_AND_TCMOD;
- }
-
- sp = &tr.genericShader[shaderAttribs];
- }
- }
- else if (pStage->glslShaderGroup)
- {
- int index = pStage->glslShaderIndex;
-
- if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity)
- {
- index |= LIGHTDEF_ENTITY;
- }
-
- if (r_lightmap->integer && index & LIGHTDEF_USE_LIGHTMAP)
- {
- index = LIGHTDEF_USE_LIGHTMAP;
- }
-
- sp = &pStage->glslShaderGroup[index];
-
- if (pStage->glslShaderGroup == tr.lightallShader)
- {
- backEnd.pc.c_lightallDraws++;
- }
- }
- else
- {
- sp = GLSL_GetGenericShaderProgram(stage);
-
- backEnd.pc.c_genericDraws++;
- }
-
- GLSL_BindProgram(sp);
-
- GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
- GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin);
-
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
-
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, deformGen);
- if (deformGen != DGEN_NONE)
- {
- GLSL_SetUniformFloat5(sp, GENERIC_UNIFORM_DEFORMPARAMS, deformParams);
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_TIME, tess.shaderTime);
- }
-
- if ( input->fogNum ) {
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDISTANCE, fogDistanceVector);
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGDEPTH, fogDepthVector);
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_FOGEYET, eyeT);
- }
-
- GL_State( pStage->stateBits );
-
- {
- vec4_t baseColor;
- vec4_t vertColor;
- qboolean tint = qtrue;
- int stage2;
-
- ComputeShaderColors(pStage, baseColor, vertColor);
-
- for ( stage2 = stage + 1; stage2 < MAX_SHADER_STAGES; stage2++ )
- {
- shaderStage_t *pStage2 = input->xstages[stage2];
- unsigned int srcBlendBits;
- //unsigned int dstBlendBits;
-
- if ( !pStage2 )
- {
- break;
- }
-
- srcBlendBits = pStage2->stateBits & GLS_SRCBLEND_BITS;
- //dstBlendBits = pStage2->stateBits & GLS_DSTBLEND_BITS;
-
- if (srcBlendBits == GLS_SRCBLEND_DST_COLOR)
- {
- tint = qfalse;
- break;
- }
- }
-
- if (!((tr.sunShadows || r_forceSun->integer) && tess.shader->sort <= SS_OPAQUE
- && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) && tess.xstages[0]->glslShaderGroup == tr.lightallShader))
- {
- tint = qfalse;
- }
-
- if (tint)
- {
- // use VectorScale to only scale first three values, not alpha
- VectorScale(baseColor, backEnd.refdef.colorScale, baseColor);
- VectorScale(vertColor, backEnd.refdef.colorScale, vertColor);
- }
-
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_BASECOLOR, baseColor);
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_VERTCOLOR, vertColor);
- }
-
- if (pStage->rgbGen == CGEN_LIGHTING_DIFFUSE)
- {
- vec4_t vec;
-
- VectorScale(backEnd.currentEntity->ambientLight, 1.0f / 255.0f, vec);
- GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_AMBIENTLIGHT, vec);
-
- VectorScale(backEnd.currentEntity->directedLight, 1.0f / 255.0f, vec);
- GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_DIRECTEDLIGHT, vec);
-
- VectorCopy(backEnd.currentEntity->lightDir, vec);
- vec[3] = 0.0f;
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_LIGHTORIGIN, vec);
-
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_LIGHTRADIUS, 999999.0f);
- }
-
- if (pStage->alphaGen == AGEN_PORTAL)
- {
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_PORTALRANGE, tess.shader->portalRange);
- }
-
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_COLORGEN, pStage->rgbGen);
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_ALPHAGEN, pStage->alphaGen);
-
- if ( input->fogNum )
- {
- vec4_t fogColorMask;
-
- ComputeFogColorMask(pStage, fogColorMask);
-
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_FOGCOLORMASK, fogColorMask);
- }
-
- ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix );
-
- {
- vec4_t vector;
- VectorSet4(vector, matrix[0], matrix[1], matrix[4], matrix[5]);
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_DIFFUSETEXMATRIX, vector);
-
- VectorSet4(vector, matrix[8], matrix[9], matrix[12], matrix[13]);
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_DIFFUSETEXOFFTURB, vector);
- }
-
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_TCGEN0, pStage->bundle[0].tcGen);
- if (pStage->bundle[0].tcGen == TCGEN_VECTOR)
- {
- vec3_t vec;
-
- VectorCopy(pStage->bundle[0].tcGenVectors[0], vec);
- GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_TCGEN0VECTOR0, vec);
- VectorCopy(pStage->bundle[0].tcGenVectors[1], vec);
- GLSL_SetUniformVec3(sp, GENERIC_UNIFORM_TCGEN0VECTOR1, vec);
- }
-
- GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELMATRIX, backEnd.or.transformMatrix);
-
- GLSL_SetUniformVec2(sp, GENERIC_UNIFORM_MATERIALINFO, pStage->materialInfo);
-
- //GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_MAPLIGHTSCALE, backEnd.refdef.mapLightScale);
-
- //
- // do multitexture
- //
- if ( backEnd.depthFill )
- {
- if (!(pStage->stateBits & GLS_ATEST_BITS))
- GL_BindToTMU( tr.whiteImage, 0 );
- else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 )
- R_BindAnimatedImageToTMU( &pStage->bundle[TB_COLORMAP], TB_COLORMAP );
- }
- else if ( pStage->glslShaderGroup )
- {
- int i;
-
- if ((r_lightmap->integer == 1 || r_lightmap->integer == 2) && pStage->bundle[TB_LIGHTMAP].image[0])
- {
- for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
- {
- if (i == TB_LIGHTMAP)
- {
- R_BindAnimatedImageToTMU( &pStage->bundle[i], i);
- }
- else if (pStage->bundle[i].image[0])
- {
- GL_BindToTMU( tr.whiteImage, i);
- }
- }
- }
- else if (r_lightmap->integer == 3 && pStage->bundle[TB_DELUXEMAP].image[0])
- {
- for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
- {
- if (i == TB_LIGHTMAP)
- {
- R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], i);
- }
- else if (pStage->bundle[i].image[0])
- {
- GL_BindToTMU( tr.whiteImage, i);
- }
- }
- }
- else
- {
- for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
- {
- if (pStage->bundle[i].image[0])
- {
- R_BindAnimatedImageToTMU( &pStage->bundle[i], i);
- }
- }
- }
- }
- else if ( pStage->bundle[1].image[0] != 0 )
- {
- R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 );
-
- //
- // lightmap/secondary pass
- //
- if ( r_lightmap->integer ) {
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_TEXTURE1ENV, GL_REPLACE);
- } else {
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_TEXTURE1ENV, tess.shader->multitextureEnv);
- }
-
- R_BindAnimatedImageToTMU( &pStage->bundle[1], 1 );
- }
- else
- {
- //
- // set state
- //
- if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer )
- {
- GL_BindToTMU( tr.whiteImage, 0 );
- }
- else
- R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 );
-
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_TEXTURE1ENV, 0);
- }
-
- //
- // draw
- //
- if (input->multiDrawPrimitives)
- {
- R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
- }
- else
- {
- R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
- }
-
- // allow skipping out to show just lightmaps during development
- if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) )
- {
- break;
- }
-
- if (backEnd.depthFill)
- break;
- }
-}
-
-
-static void RB_RenderShadowmap( shaderCommands_t *input )
-{
- int deformGen;
- vec5_t deformParams;
-
- ComputeDeformValues(&deformGen, deformParams);
-
- {
- shaderProgram_t *sp = &tr.shadowmapShader;
-
- vec4_t vector;
-
- GLSL_BindProgram(sp);
-
- GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
-
- GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELMATRIX, backEnd.or.transformMatrix);
-
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation);
-
- GLSL_SetUniformInt(sp, GENERIC_UNIFORM_DEFORMGEN, deformGen);
- if (deformGen != DGEN_NONE)
- {
- GLSL_SetUniformFloat5(sp, GENERIC_UNIFORM_DEFORMPARAMS, deformParams);
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_TIME, tess.shaderTime);
- }
-
- VectorCopy(backEnd.viewParms.or.origin, vector);
- vector[3] = 1.0f;
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_LIGHTORIGIN, vector);
- GLSL_SetUniformFloat(sp, GENERIC_UNIFORM_LIGHTRADIUS, backEnd.viewParms.zFar);
-
- GL_State( 0 );
-
- //
- // do multitexture
- //
- //if ( pStage->glslShaderGroup )
- {
- //
- // draw
- //
-
- if (input->multiDrawPrimitives)
- {
- R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex);
- }
- else
- {
- R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex);
- }
- }
- }
-}
-
-
-
-/*
-** RB_StageIteratorGeneric
-*/
-void RB_StageIteratorGeneric( void )
-{
- shaderCommands_t *input;
- unsigned int vertexAttribs = 0;
-
- input = &tess;
-
- if (!input->numVertexes || !input->numIndexes)
- {
- return;
- }
-
- if (tess.useInternalVBO)
- {
- RB_DeformTessGeometry();
- }
-
- vertexAttribs = RB_CalcShaderVertexAttribs( input );
-
- if (tess.useInternalVBO)
- {
- RB_UpdateVBOs(vertexAttribs);
- }
- else
- {
- backEnd.pc.c_staticVboDraws++;
- }
-
- //
- // log this call
- //
- if ( r_logFile->integer )
- {
- // don't just call LogComment, or we will get
- // a call to va() every frame!
- GLimp_LogComment( va("--- RB_StageIteratorGeneric( %s ) ---\n", tess.shader->name) );
- }
-
- //
- // set face culling appropriately
- //
- if ((backEnd.viewParms.flags & VPF_DEPTHSHADOW))
- {
- //GL_Cull( CT_TWO_SIDED );
-
- if (input->shader->cullType == CT_TWO_SIDED)
- GL_Cull( CT_TWO_SIDED );
- else if (input->shader->cullType == CT_FRONT_SIDED)
- GL_Cull( CT_BACK_SIDED );
- else
- GL_Cull( CT_FRONT_SIDED );
-
- }
- else
- GL_Cull( input->shader->cullType );
-
- // set polygon offset if necessary
- if ( input->shader->polygonOffset )
- {
- qglEnable( GL_POLYGON_OFFSET_FILL );
- qglPolygonOffset( r_offsetFactor->value, r_offsetUnits->value );
- }
-
- //
- // Set vertex attribs and pointers
- //
- GLSL_VertexAttribsState(vertexAttribs);
-
- //
- // render depth if in depthfill mode
- //
- if (backEnd.depthFill)
- {
- RB_IterateStagesGeneric( input );
-
- //
- // reset polygon offset
- //
- if ( input->shader->polygonOffset )
- {
- qglDisable( GL_POLYGON_OFFSET_FILL );
- }
-
- return;
- }
-
- //
- // render shadowmap if in shadowmap mode
- //
- if (backEnd.viewParms.flags & VPF_SHADOWMAP)
- {
- if ( input->shader->sort == SS_OPAQUE )
- {
- RB_RenderShadowmap( input );
- }
- //
- // reset polygon offset
- //
- if ( input->shader->polygonOffset )
- {
- qglDisable( GL_POLYGON_OFFSET_FILL );
- }
-
- return;
- }
-
- //
- //
- // call shader function
- //
- RB_IterateStagesGeneric( input );
-
- //
- // pshadows!
- //
- if (glRefConfig.framebufferObject && tess.pshadowBits && tess.shader->sort <= SS_OPAQUE
- && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) {
- ProjectPshadowVBOGLSL();
- }
-
-
- //
- // now do any dynamic lighting needed
- //
- if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE
- && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) ) {
- if (tess.shader->numUnfoggedPasses == 1 && tess.xstages[0]->glslShaderGroup == tr.lightallShader
- && (tess.xstages[0]->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) && r_dlightMode->integer)
- {
- ForwardDlight();
- }
- else
- {
- ProjectDlightTexture();
- }
- }
-
- if ((backEnd.viewParms.flags & VPF_USESUNLIGHT) && tess.shader->sort <= SS_OPAQUE
- //if ((tr.sunShadows || r_forceSunlight->value > 0.0f) && tess.shader->sort <= SS_OPAQUE
- && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) && tess.xstages[0]->glslShaderGroup == tr.lightallShader) {
- ForwardSunlight();
- }
-
- //
- // now do fog
- //
- if ( tess.fogNum && tess.shader->fogPass ) {
- RB_FogPass();
- }
-
- //
- // reset polygon offset
- //
- if ( input->shader->polygonOffset )
- {
- qglDisable( GL_POLYGON_OFFSET_FILL );
- }
-}
-
-
-/*
-** RB_EndSurface
-*/
-void RB_EndSurface( void ) {
- shaderCommands_t *input;
-
- input = &tess;
-
- if (input->numIndexes == 0 || input->numVertexes == 0) {
- return;
- }
-
- if (input->indexes[SHADER_MAX_INDEXES-1] != 0) {
- ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_INDEXES hit");
- }
- if (input->xyz[SHADER_MAX_VERTEXES-1][0] != 0) {
- ri.Error (ERR_DROP, "RB_EndSurface() - SHADER_MAX_VERTEXES hit");
- }
-
- if ( tess.shader == tr.shadowShader ) {
- RB_ShadowTessEnd();
- return;
- }
-
- // for debugging of sort order issues, stop rendering after a given sort value
- if ( r_debugSort->integer && r_debugSort->integer < tess.shader->sort ) {
- return;
- }
-
- //
- // update performance counters
- //
- backEnd.pc.c_shaders++;
- backEnd.pc.c_vertexes += tess.numVertexes;
- backEnd.pc.c_indexes += tess.numIndexes;
- backEnd.pc.c_totalIndexes += tess.numIndexes * tess.numPasses;
-
- //
- // call off to shader specific tess end function
- //
- tess.currentStageIteratorFunc();
-
- //
- // draw debugging stuff
- //
- if ( r_showtris->integer ) {
- DrawTris (input);
- }
- if ( r_shownormals->integer ) {
- DrawNormals (input);
- }
- // clear shader so we can tell we don't have any unclosed surfaces
- tess.numIndexes = 0;
- tess.numVertexes = 0;
- tess.firstIndex = 0;
- tess.multiDrawPrimitives = 0;
-
- GLimp_LogComment( "----------\n" );
-}
diff --git a/src/rend2/tr_shade_calc.c b/src/rend2/tr_shade_calc.c
deleted file mode 100644
index 9421f646..00000000
--- a/src/rend2/tr_shade_calc.c
+++ /dev/null
@@ -1,1339 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_shade_calc.c
-
-#include "tr_local.h"
-#if idppc_altivec && !defined(MACOS_X)
-#include <altivec.h>
-#endif
-
-
-#define WAVEVALUE( table, base, amplitude, phase, freq ) ((base) + table[ ri.ftol( ( ( (phase) + tess.shaderTime * (freq) ) * FUNCTABLE_SIZE ) ) & FUNCTABLE_MASK ] * (amplitude))
-
-static float *TableForFunc( genFunc_t func )
-{
- switch ( func )
- {
- case GF_SIN:
- return tr.sinTable;
- case GF_TRIANGLE:
- return tr.triangleTable;
- case GF_SQUARE:
- return tr.squareTable;
- case GF_SAWTOOTH:
- return tr.sawToothTable;
- case GF_INVERSE_SAWTOOTH:
- return tr.inverseSawToothTable;
- case GF_NONE:
- default:
- break;
- }
-
- ri.Error( ERR_DROP, "TableForFunc called with invalid function '%d' in shader '%s'", func, tess.shader->name );
- return NULL;
-}
-
-/*
-** EvalWaveForm
-**
-** Evaluates a given waveForm_t, referencing backEnd.refdef.time directly
-*/
-static float EvalWaveForm( const waveForm_t *wf )
-{
- float *table;
-
- table = TableForFunc( wf->func );
-
- return WAVEVALUE( table, wf->base, wf->amplitude, wf->phase, wf->frequency );
-}
-
-static float EvalWaveFormClamped( const waveForm_t *wf )
-{
- float glow = EvalWaveForm( wf );
-
- if ( glow < 0 )
- {
- return 0;
- }
-
- if ( glow > 1 )
- {
- return 1;
- }
-
- return glow;
-}
-
-/*
-** RB_CalcStretchTexCoords
-*/
-void RB_CalcStretchTexCoords( const waveForm_t *wf, float *st )
-{
- float p;
- texModInfo_t tmi;
-
- p = 1.0f / EvalWaveForm( wf );
-
- tmi.matrix[0][0] = p;
- tmi.matrix[1][0] = 0;
- tmi.translate[0] = 0.5f - 0.5f * p;
-
- tmi.matrix[0][1] = 0;
- tmi.matrix[1][1] = p;
- tmi.translate[1] = 0.5f - 0.5f * p;
-
- RB_CalcTransformTexCoords( &tmi, st );
-}
-
-void RB_CalcStretchTexMatrix( const waveForm_t *wf, float *matrix )
-{
- float p;
- texModInfo_t tmi;
-
- p = 1.0f / EvalWaveForm( wf );
-
- tmi.matrix[0][0] = p;
- tmi.matrix[1][0] = 0;
- tmi.translate[0] = 0.5f - 0.5f * p;
-
- tmi.matrix[0][1] = 0;
- tmi.matrix[1][1] = p;
- tmi.translate[1] = 0.5f - 0.5f * p;
-
- RB_CalcTransformTexMatrix( &tmi, matrix );
-}
-
-/*
-====================================================================
-
-DEFORMATIONS
-
-====================================================================
-*/
-
-/*
-========================
-RB_CalcDeformVertexes
-
-========================
-*/
-void RB_CalcDeformVertexes( deformStage_t *ds )
-{
- int i;
- vec3_t offset;
- float scale;
- float *xyz = ( float * ) tess.xyz;
- float *normal = ( float * ) tess.normal;
- float *table;
-
- if ( ds->deformationWave.frequency == 0 )
- {
- scale = EvalWaveForm( &ds->deformationWave );
-
- for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 )
- {
- VectorScale( normal, scale, offset );
-
- xyz[0] += offset[0];
- xyz[1] += offset[1];
- xyz[2] += offset[2];
- }
- }
- else
- {
- table = TableForFunc( ds->deformationWave.func );
-
- for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 )
- {
- float off = ( xyz[0] + xyz[1] + xyz[2] ) * ds->deformationSpread;
-
- scale = WAVEVALUE( table, ds->deformationWave.base,
- ds->deformationWave.amplitude,
- ds->deformationWave.phase + off,
- ds->deformationWave.frequency );
-
- VectorScale( normal, scale, offset );
-
- xyz[0] += offset[0];
- xyz[1] += offset[1];
- xyz[2] += offset[2];
- }
- }
-}
-
-/*
-=========================
-RB_CalcDeformNormals
-
-Wiggle the normals for wavy environment mapping
-=========================
-*/
-void RB_CalcDeformNormals( deformStage_t *ds ) {
- int i;
- float scale;
- float *xyz = ( float * ) tess.xyz;
- float *normal = ( float * ) tess.normal;
-
- for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal += 4 ) {
- scale = 0.98f;
- scale = R_NoiseGet4f( xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
- tess.shaderTime * ds->deformationWave.frequency );
- normal[ 0 ] += ds->deformationWave.amplitude * scale;
-
- scale = 0.98f;
- scale = R_NoiseGet4f( 100 + xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
- tess.shaderTime * ds->deformationWave.frequency );
- normal[ 1 ] += ds->deformationWave.amplitude * scale;
-
- scale = 0.98f;
- scale = R_NoiseGet4f( 200 + xyz[0] * scale, xyz[1] * scale, xyz[2] * scale,
- tess.shaderTime * ds->deformationWave.frequency );
- normal[ 2 ] += ds->deformationWave.amplitude * scale;
-
- VectorNormalizeFast( normal );
- }
-}
-
-/*
-========================
-RB_CalcBulgeVertexes
-
-========================
-*/
-void RB_CalcBulgeVertexes( deformStage_t *ds ) {
- int i;
- const float *st = ( const float * ) tess.texCoords[0];
- float *xyz = ( float * ) tess.xyz;
- float *normal = ( float * ) tess.normal;
- float now;
-
- now = backEnd.refdef.time * ds->bulgeSpeed * 0.001f;
-
- for ( i = 0; i < tess.numVertexes; i++, xyz += 4, st += 4, normal += 4 ) {
- int off;
- float scale;
-
- off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * ds->bulgeWidth + now );
-
- scale = tr.sinTable[ off & FUNCTABLE_MASK ] * ds->bulgeHeight;
-
- xyz[0] += normal[0] * scale;
- xyz[1] += normal[1] * scale;
- xyz[2] += normal[2] * scale;
- }
-}
-
-
-/*
-======================
-RB_CalcMoveVertexes
-
-A deformation that can move an entire surface along a wave path
-======================
-*/
-void RB_CalcMoveVertexes( deformStage_t *ds ) {
- int i;
- float *xyz;
- float *table;
- float scale;
- vec3_t offset;
-
- table = TableForFunc( ds->deformationWave.func );
-
- scale = WAVEVALUE( table, ds->deformationWave.base,
- ds->deformationWave.amplitude,
- ds->deformationWave.phase,
- ds->deformationWave.frequency );
-
- VectorScale( ds->moveVector, scale, offset );
-
- xyz = ( float * ) tess.xyz;
- for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) {
- VectorAdd( xyz, offset, xyz );
- }
-}
-
-
-/*
-=============
-DeformText
-
-Change a polygon into a bunch of text polygons
-=============
-*/
-void DeformText( const char *text ) {
- int i;
- vec3_t origin, width, height;
- int len;
- int ch;
- float color[4];
- float bottom, top;
- vec3_t mid;
-
- height[0] = 0;
- height[1] = 0;
- height[2] = -1;
- CrossProduct( tess.normal[0], height, width );
-
- // find the midpoint of the box
- VectorClear( mid );
- bottom = 999999;
- top = -999999;
- for ( i = 0 ; i < 4 ; i++ ) {
- VectorAdd( tess.xyz[i], mid, mid );
- if ( tess.xyz[i][2] < bottom ) {
- bottom = tess.xyz[i][2];
- }
- if ( tess.xyz[i][2] > top ) {
- top = tess.xyz[i][2];
- }
- }
- VectorScale( mid, 0.25f, origin );
-
- // determine the individual character size
- height[0] = 0;
- height[1] = 0;
- height[2] = ( top - bottom ) * 0.5f;
-
- VectorScale( width, height[2] * -0.75f, width );
-
- // determine the starting position
- len = strlen( text );
- VectorMA( origin, (len-1), width, origin );
-
- // clear the shader indexes
- tess.numIndexes = 0;
- tess.numVertexes = 0;
- tess.firstIndex = 0;
-
- color[0] = color[1] = color[2] = color[3] = 1.0f;
-
- // draw each character
- for ( i = 0 ; i < len ; i++ ) {
- ch = text[i];
- ch &= 255;
-
- if ( ch != ' ' ) {
- int row, col;
- float frow, fcol, size;
-
- row = ch>>4;
- col = ch&15;
-
- frow = row*0.0625f;
- fcol = col*0.0625f;
- size = 0.0625f;
-
- RB_AddQuadStampExt( origin, width, height, color, fcol, frow, fcol + size, frow + size );
- }
- VectorMA( origin, -2, width, origin );
- }
-}
-
-/*
-==================
-GlobalVectorToLocal
-==================
-*/
-static void GlobalVectorToLocal( const vec3_t in, vec3_t out ) {
- out[0] = DotProduct( in, backEnd.or.axis[0] );
- out[1] = DotProduct( in, backEnd.or.axis[1] );
- out[2] = DotProduct( in, backEnd.or.axis[2] );
-}
-
-/*
-=====================
-AutospriteDeform
-
-Assuming all the triangles for this shader are independant
-quads, rebuild them as forward facing sprites
-=====================
-*/
-static void AutospriteDeform( void ) {
- int i;
- int oldVerts;
- float *xyz;
- vec3_t mid, delta;
- float radius;
- vec3_t left, up;
- vec3_t leftDir, upDir;
-
- if ( tess.numVertexes & 3 ) {
- ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd vertex count\n", tess.shader->name );
- }
- if ( tess.numIndexes != ( tess.numVertexes >> 2 ) * 6 ) {
- ri.Printf( PRINT_WARNING, "Autosprite shader %s had odd index count\n", tess.shader->name );
- }
-
- oldVerts = tess.numVertexes;
- tess.numVertexes = 0;
- tess.numIndexes = 0;
- tess.firstIndex = 0;
-
- if ( backEnd.currentEntity != &tr.worldEntity ) {
- GlobalVectorToLocal( backEnd.viewParms.or.axis[1], leftDir );
- GlobalVectorToLocal( backEnd.viewParms.or.axis[2], upDir );
- } else {
- VectorCopy( backEnd.viewParms.or.axis[1], leftDir );
- VectorCopy( backEnd.viewParms.or.axis[2], upDir );
- }
-
- for ( i = 0 ; i < oldVerts ; i+=4 ) {
- // find the midpoint
- xyz = tess.xyz[i];
-
- mid[0] = 0.25f * (xyz[0] + xyz[4] + xyz[8] + xyz[12]);
- mid[1] = 0.25f * (xyz[1] + xyz[5] + xyz[9] + xyz[13]);
- mid[2] = 0.25f * (xyz[2] + xyz[6] + xyz[10] + xyz[14]);
-
- VectorSubtract( xyz, mid, delta );
- radius = VectorLength( delta ) * 0.707f; // / sqrt(2)
-
- VectorScale( leftDir, radius, left );
- VectorScale( upDir, radius, up );
-
- if ( backEnd.viewParms.isMirror ) {
- VectorSubtract( vec3_origin, left, left );
- }
-
- // compensate for scale in the axes if necessary
- if ( backEnd.currentEntity->e.nonNormalizedAxes ) {
- float axisLength;
- axisLength = VectorLength( backEnd.currentEntity->e.axis[0] );
- if ( !axisLength ) {
- axisLength = 0;
- } else {
- axisLength = 1.0f / axisLength;
- }
- VectorScale(left, axisLength, left);
- VectorScale(up, axisLength, up);
- }
-
- RB_AddQuadStamp( mid, left, up, tess.vertexColors[i] );
- }
-}
-
-
-/*
-=====================
-Autosprite2Deform
-
-Autosprite2 will pivot a rectangular quad along the center of its long axis
-=====================
-*/
-int edgeVerts[6][2] = {
- { 0, 1 },
- { 0, 2 },
- { 0, 3 },
- { 1, 2 },
- { 1, 3 },
- { 2, 3 }
-};
-
-static void Autosprite2Deform( void ) {
- int i, j, k;
- int indexes;
- float *xyz;
- vec3_t forward;
-
- if ( tess.numVertexes & 3 ) {
- ri.Printf( PRINT_WARNING, "Autosprite2 shader %s had odd vertex count", tess.shader->name );
- }
- if ( tess.numIndexes != ( tess.numVertexes >> 2 ) * 6 ) {
- ri.Printf( PRINT_WARNING, "Autosprite2 shader %s had odd index count", tess.shader->name );
- }
-
- if ( backEnd.currentEntity != &tr.worldEntity ) {
- GlobalVectorToLocal( backEnd.viewParms.or.axis[0], forward );
- } else {
- VectorCopy( backEnd.viewParms.or.axis[0], forward );
- }
-
- // this is a lot of work for two triangles...
- // we could precalculate a lot of it is an issue, but it would mess up
- // the shader abstraction
- for ( i = 0, indexes = 0 ; i < tess.numVertexes ; i+=4, indexes+=6 ) {
- float lengths[2];
- int nums[2];
- vec3_t mid[2];
- vec3_t major, minor;
- float *v1, *v2;
-
- // find the midpoint
- xyz = tess.xyz[i];
-
- // identify the two shortest edges
- nums[0] = nums[1] = 0;
- lengths[0] = lengths[1] = 999999;
-
- for ( j = 0 ; j < 6 ; j++ ) {
- float l;
- vec3_t temp;
-
- v1 = xyz + 4 * edgeVerts[j][0];
- v2 = xyz + 4 * edgeVerts[j][1];
-
- VectorSubtract( v1, v2, temp );
-
- l = DotProduct( temp, temp );
- if ( l < lengths[0] ) {
- nums[1] = nums[0];
- lengths[1] = lengths[0];
- nums[0] = j;
- lengths[0] = l;
- } else if ( l < lengths[1] ) {
- nums[1] = j;
- lengths[1] = l;
- }
- }
-
- for ( j = 0 ; j < 2 ; j++ ) {
- v1 = xyz + 4 * edgeVerts[nums[j]][0];
- v2 = xyz + 4 * edgeVerts[nums[j]][1];
-
- mid[j][0] = 0.5f * (v1[0] + v2[0]);
- mid[j][1] = 0.5f * (v1[1] + v2[1]);
- mid[j][2] = 0.5f * (v1[2] + v2[2]);
- }
-
- // find the vector of the major axis
- VectorSubtract( mid[1], mid[0], major );
-
- // cross this with the view direction to get minor axis
- CrossProduct( major, forward, minor );
- VectorNormalize( minor );
-
- // re-project the points
- for ( j = 0 ; j < 2 ; j++ ) {
- float l;
-
- v1 = xyz + 4 * edgeVerts[nums[j]][0];
- v2 = xyz + 4 * edgeVerts[nums[j]][1];
-
- l = 0.5 * sqrt( lengths[j] );
-
- // we need to see which direction this edge
- // is used to determine direction of projection
- for ( k = 0 ; k < 5 ; k++ ) {
- if ( tess.indexes[ indexes + k ] == i + edgeVerts[nums[j]][0]
- && tess.indexes[ indexes + k + 1 ] == i + edgeVerts[nums[j]][1] ) {
- break;
- }
- }
-
- if ( k == 5 ) {
- VectorMA( mid[j], l, minor, v1 );
- VectorMA( mid[j], -l, minor, v2 );
- } else {
- VectorMA( mid[j], -l, minor, v1 );
- VectorMA( mid[j], l, minor, v2 );
- }
- }
- }
-}
-
-
-/*
-=====================
-RB_DeformTessGeometry
-
-=====================
-*/
-void RB_DeformTessGeometry( void ) {
- int i;
- deformStage_t *ds;
-
- if(!ShaderRequiresCPUDeforms(tess.shader))
- {
- // we don't need the following CPU deforms
- return;
- }
-
- for ( i = 0 ; i < tess.shader->numDeforms ; i++ ) {
- ds = &tess.shader->deforms[ i ];
-
- switch ( ds->deformation ) {
- case DEFORM_NONE:
- break;
- case DEFORM_NORMALS:
- RB_CalcDeformNormals( ds );
- break;
- case DEFORM_WAVE:
- RB_CalcDeformVertexes( ds );
- break;
- case DEFORM_BULGE:
- RB_CalcBulgeVertexes( ds );
- break;
- case DEFORM_MOVE:
- RB_CalcMoveVertexes( ds );
- break;
- case DEFORM_PROJECTION_SHADOW:
- RB_ProjectionShadowDeform();
- break;
- case DEFORM_AUTOSPRITE:
- AutospriteDeform();
- break;
- case DEFORM_AUTOSPRITE2:
- Autosprite2Deform();
- break;
- case DEFORM_TEXT0:
- case DEFORM_TEXT1:
- case DEFORM_TEXT2:
- case DEFORM_TEXT3:
- case DEFORM_TEXT4:
- case DEFORM_TEXT5:
- case DEFORM_TEXT6:
- case DEFORM_TEXT7:
- DeformText( backEnd.refdef.text[ds->deformation - DEFORM_TEXT0] );
- break;
- }
- }
-}
-
-/*
-====================================================================
-
-COLORS
-
-====================================================================
-*/
-
-
-/*
-** RB_CalcColorFromEntity
-*/
-void RB_CalcColorFromEntity( unsigned char *dstColors )
-{
- int i;
- int *pColors = ( int * ) dstColors;
- int c;
-
- if ( !backEnd.currentEntity )
- return;
-
- c = * ( int * ) backEnd.currentEntity->e.shaderRGBA;
-
- for ( i = 0; i < tess.numVertexes; i++, pColors++ )
- {
- *pColors = c;
- }
-}
-
-/*
-** RB_CalcColorFromOneMinusEntity
-*/
-void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors )
-{
- int i;
- int *pColors = ( int * ) dstColors;
- unsigned char invModulate[4];
- int c;
-
- if ( !backEnd.currentEntity )
- return;
-
- invModulate[0] = 255 - backEnd.currentEntity->e.shaderRGBA[0];
- invModulate[1] = 255 - backEnd.currentEntity->e.shaderRGBA[1];
- invModulate[2] = 255 - backEnd.currentEntity->e.shaderRGBA[2];
- invModulate[3] = 255 - backEnd.currentEntity->e.shaderRGBA[3]; // this trashes alpha, but the AGEN block fixes it
-
- c = * ( int * ) invModulate;
-
- for ( i = 0; i < tess.numVertexes; i++, pColors++ )
- {
- *pColors = c;
- }
-}
-
-/*
-** RB_CalcAlphaFromEntity
-*/
-void RB_CalcAlphaFromEntity( unsigned char *dstColors )
-{
- int i;
-
- if ( !backEnd.currentEntity )
- return;
-
- dstColors += 3;
-
- for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
- {
- *dstColors = backEnd.currentEntity->e.shaderRGBA[3];
- }
-}
-
-/*
-** RB_CalcAlphaFromOneMinusEntity
-*/
-void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors )
-{
- int i;
-
- if ( !backEnd.currentEntity )
- return;
-
- dstColors += 3;
-
- for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
- {
- *dstColors = 0xff - backEnd.currentEntity->e.shaderRGBA[3];
- }
-}
-
-/*
-** RB_CalcWaveColorSingle
-*/
-float RB_CalcWaveColorSingle( const waveForm_t *wf )
-{
- float glow;
-
- if ( wf->func == GF_NOISE ) {
- glow = wf->base + R_NoiseGet4f( 0, 0, 0, ( tess.shaderTime + wf->phase ) * wf->frequency ) * wf->amplitude;
- } else {
- glow = EvalWaveForm( wf ) * tr.identityLight;
- }
-
- if ( glow < 0 ) {
- glow = 0;
- }
- else if ( glow > 1 ) {
- glow = 1;
- }
-
- return glow;
-}
-
-/*
-** RB_CalcWaveColor
-*/
-void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors )
-{
- int i;
- int v;
- float glow;
- int *colors = ( int * ) dstColors;
- byte color[4];
-
- glow = RB_CalcWaveColorSingle( wf );
-
- v = ri.ftol(255 * glow);
- color[0] = color[1] = color[2] = v;
- color[3] = 255;
- v = *(int *)color;
-
- for ( i = 0; i < tess.numVertexes; i++, colors++ ) {
- *colors = v;
- }
-}
-
-/*
-** RB_CalcWaveAlphaSingle
-*/
-float RB_CalcWaveAlphaSingle( const waveForm_t *wf )
-{
- return EvalWaveFormClamped( wf );
-}
-
-/*
-** RB_CalcWaveAlpha
-*/
-void RB_CalcWaveAlpha( const waveForm_t *wf, unsigned char *dstColors )
-{
- int i;
- int v;
- float glow;
-
- glow = EvalWaveFormClamped( wf );
-
- v = 255 * glow;
-
- for ( i = 0; i < tess.numVertexes; i++, dstColors += 4 )
- {
- dstColors[3] = v;
- }
-}
-
-/*
-** RB_CalcModulateColorsByFog
-*/
-void RB_CalcModulateColorsByFog( unsigned char *colors ) {
- int i;
- float texCoords[SHADER_MAX_VERTEXES][2];
-
- // calculate texcoords so we can derive density
- // this is not wasted, because it would only have
- // been previously called if the surface was opaque
- RB_CalcFogTexCoords( texCoords[0] );
-
- for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
- float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
- colors[0] *= f;
- colors[1] *= f;
- colors[2] *= f;
- }
-}
-
-/*
-** RB_CalcModulateAlphasByFog
-*/
-void RB_CalcModulateAlphasByFog( unsigned char *colors ) {
- int i;
- float texCoords[SHADER_MAX_VERTEXES][2];
-
- // calculate texcoords so we can derive density
- // this is not wasted, because it would only have
- // been previously called if the surface was opaque
- RB_CalcFogTexCoords( texCoords[0] );
-
- for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
- float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
- colors[3] *= f;
- }
-}
-
-/*
-** RB_CalcModulateRGBAsByFog
-*/
-void RB_CalcModulateRGBAsByFog( unsigned char *colors ) {
- int i;
- float texCoords[SHADER_MAX_VERTEXES][2];
-
- // calculate texcoords so we can derive density
- // this is not wasted, because it would only have
- // been previously called if the surface was opaque
- RB_CalcFogTexCoords( texCoords[0] );
-
- for ( i = 0; i < tess.numVertexes; i++, colors += 4 ) {
- float f = 1.0 - R_FogFactor( texCoords[i][0], texCoords[i][1] );
- colors[0] *= f;
- colors[1] *= f;
- colors[2] *= f;
- colors[3] *= f;
- }
-}
-
-
-/*
-====================================================================
-
-TEX COORDS
-
-====================================================================
-*/
-
-/*
-========================
-RB_CalcFogTexCoords
-
-To do the clipped fog plane really correctly, we should use
-projected textures, but I don't trust the drivers and it
-doesn't fit our shader data.
-========================
-*/
-void RB_CalcFogTexCoords( float *st ) {
- int i;
- float *v;
- float s, t;
- float eyeT;
- qboolean eyeOutside;
- fog_t *fog;
- vec3_t local;
- vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0};
-
- fog = tr.world->fogs + tess.fogNum;
-
- // all fogging distance is based on world Z units
- VectorSubtract( backEnd.or.origin, backEnd.viewParms.or.origin, local );
- fogDistanceVector[0] = -backEnd.or.modelMatrix[2];
- fogDistanceVector[1] = -backEnd.or.modelMatrix[6];
- fogDistanceVector[2] = -backEnd.or.modelMatrix[10];
- fogDistanceVector[3] = DotProduct( local, backEnd.viewParms.or.axis[0] );
-
- // scale the fog vectors based on the fog's thickness
- fogDistanceVector[0] *= fog->tcScale;
- fogDistanceVector[1] *= fog->tcScale;
- fogDistanceVector[2] *= fog->tcScale;
- fogDistanceVector[3] *= fog->tcScale;
-
- // rotate the gradient vector for this orientation
- if ( fog->hasSurface ) {
- fogDepthVector[0] = fog->surface[0] * backEnd.or.axis[0][0] +
- fog->surface[1] * backEnd.or.axis[0][1] + fog->surface[2] * backEnd.or.axis[0][2];
- fogDepthVector[1] = fog->surface[0] * backEnd.or.axis[1][0] +
- fog->surface[1] * backEnd.or.axis[1][1] + fog->surface[2] * backEnd.or.axis[1][2];
- fogDepthVector[2] = fog->surface[0] * backEnd.or.axis[2][0] +
- fog->surface[1] * backEnd.or.axis[2][1] + fog->surface[2] * backEnd.or.axis[2][2];
- fogDepthVector[3] = -fog->surface[3] + DotProduct( backEnd.or.origin, fog->surface );
-
- eyeT = DotProduct( backEnd.or.viewOrigin, fogDepthVector ) + fogDepthVector[3];
- } else {
- eyeT = 1; // non-surface fog always has eye inside
- }
-
- // see if the viewpoint is outside
- // this is needed for clipping distance even for constant fog
-
- if ( eyeT < 0 ) {
- eyeOutside = qtrue;
- } else {
- eyeOutside = qfalse;
- }
-
- fogDistanceVector[3] += 1.0/512;
-
- // calculate density for each point
- for (i = 0, v = tess.xyz[0] ; i < tess.numVertexes ; i++, v += 4) {
- // calculate the length in fog
- s = DotProduct( v, fogDistanceVector ) + fogDistanceVector[3];
- t = DotProduct( v, fogDepthVector ) + fogDepthVector[3];
-
- // partially clipped fogs use the T axis
- if ( eyeOutside ) {
- if ( t < 1.0 ) {
- t = 1.0/32; // point is outside, so no fogging
- } else {
- t = 1.0/32 + 30.0/32 * t / ( t - eyeT ); // cut the distance at the fog plane
- }
- } else {
- if ( t < 0 ) {
- t = 1.0/32; // point is outside, so no fogging
- } else {
- t = 31.0/32;
- }
- }
-
- st[0] = s;
- st[1] = t;
- st += 2;
- }
-}
-
-
-
-/*
-** RB_CalcEnvironmentTexCoords
-*/
-void RB_CalcEnvironmentTexCoords( float *st )
-{
- int i;
- float *v, *normal;
- vec3_t viewer, reflected;
- float d;
-
- v = tess.xyz[0];
- normal = tess.normal[0];
-
- for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 )
- {
- VectorSubtract (backEnd.or.viewOrigin, v, viewer);
- VectorNormalizeFast (viewer);
-
- d = DotProduct (normal, viewer);
-
- reflected[0] = normal[0]*2*d - viewer[0];
- reflected[1] = normal[1]*2*d - viewer[1];
- reflected[2] = normal[2]*2*d - viewer[2];
-
- st[0] = 0.5 + reflected[1] * 0.5;
- st[1] = 0.5 - reflected[2] * 0.5;
- }
-}
-
-/*
-** RB_CalcTurbulentTexCoords
-*/
-void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *st )
-{
- int i;
- float now;
-
- now = ( wf->phase + tess.shaderTime * wf->frequency );
-
- for ( i = 0; i < tess.numVertexes; i++, st += 2 )
- {
- float s = st[0];
- float t = st[1];
-
- st[0] = s + tr.sinTable[ ( ( int ) ( ( ( tess.xyz[i][0] + tess.xyz[i][2] )* 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude;
- st[1] = t + tr.sinTable[ ( ( int ) ( ( tess.xyz[i][1] * 1.0/128 * 0.125 + now ) * FUNCTABLE_SIZE ) ) & ( FUNCTABLE_MASK ) ] * wf->amplitude;
- }
-}
-
-void RB_CalcTurbulentTexMatrix( const waveForm_t *wf, matrix_t matrix )
-{
- float now;
-
- now = ( wf->phase + tess.shaderTime * wf->frequency );
-
- // bit of a hack here, hide amplitude and now in the matrix
- // the vertex program will extract them and perform a turbulent pass last if it's nonzero
-
- matrix[ 0] = 1.0f; matrix[ 4] = 0.0f; matrix[ 8] = 0.0f; matrix[12] = wf->amplitude;
- matrix[ 1] = 0.0f; matrix[ 5] = 1.0f; matrix[ 9] = 0.0f; matrix[13] = now;
- matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
- matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
-}
-
-/*
-** RB_CalcScaleTexCoords
-*/
-void RB_CalcScaleTexCoords( const float scale[2], float *st )
-{
- int i;
-
- for ( i = 0; i < tess.numVertexes; i++, st += 2 )
- {
- st[0] *= scale[0];
- st[1] *= scale[1];
- }
-}
-
-void RB_CalcScaleTexMatrix( const float scale[2], float *matrix )
-{
- matrix[ 0] = scale[0]; matrix[ 4] = 0.0f; matrix[ 8] = 0.0f; matrix[12] = 0.0f;
- matrix[ 1] = 0.0f; matrix[ 5] = scale[1]; matrix[ 9] = 0.0f; matrix[13] = 0.0f;
- matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
- matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
-}
-
-/*
-** RB_CalcScrollTexCoords
-*/
-void RB_CalcScrollTexCoords( const float scrollSpeed[2], float *st )
-{
- int i;
- float timeScale = tess.shaderTime;
- float adjustedScrollS, adjustedScrollT;
-
- adjustedScrollS = scrollSpeed[0] * timeScale;
- adjustedScrollT = scrollSpeed[1] * timeScale;
-
- // clamp so coordinates don't continuously get larger, causing problems
- // with hardware limits
- adjustedScrollS = adjustedScrollS - floor( adjustedScrollS );
- adjustedScrollT = adjustedScrollT - floor( adjustedScrollT );
-
- for ( i = 0; i < tess.numVertexes; i++, st += 2 )
- {
- st[0] += adjustedScrollS;
- st[1] += adjustedScrollT;
- }
-}
-
-void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix )
-{
- float timeScale = tess.shaderTime;
- float adjustedScrollS, adjustedScrollT;
-
- adjustedScrollS = scrollSpeed[0] * timeScale;
- adjustedScrollT = scrollSpeed[1] * timeScale;
-
- // clamp so coordinates don't continuously get larger, causing problems
- // with hardware limits
- adjustedScrollS = adjustedScrollS - floor( adjustedScrollS );
- adjustedScrollT = adjustedScrollT - floor( adjustedScrollT );
-
-
- matrix[ 0] = 1.0f; matrix[ 4] = 0.0f; matrix[ 8] = adjustedScrollS; matrix[12] = 0.0f;
- matrix[ 1] = 0.0f; matrix[ 5] = 1.0f; matrix[ 9] = adjustedScrollT; matrix[13] = 0.0f;
- matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
- matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
-}
-
-/*
-** RB_CalcTransformTexCoords
-*/
-void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *st )
-{
- int i;
-
- for ( i = 0; i < tess.numVertexes; i++, st += 2 )
- {
- float s = st[0];
- float t = st[1];
-
- st[0] = s * tmi->matrix[0][0] + t * tmi->matrix[1][0] + tmi->translate[0];
- st[1] = s * tmi->matrix[0][1] + t * tmi->matrix[1][1] + tmi->translate[1];
- }
-}
-
-void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix )
-{
- matrix[ 0] = tmi->matrix[0][0]; matrix[ 4] = tmi->matrix[1][0]; matrix[ 8] = tmi->translate[0]; matrix[12] = 0.0f;
- matrix[ 1] = tmi->matrix[0][1]; matrix[ 5] = tmi->matrix[1][1]; matrix[ 9] = tmi->translate[1]; matrix[13] = 0.0f;
- matrix[ 2] = 0.0f; matrix[ 6] = 0.0f; matrix[10] = 1.0f; matrix[14] = 0.0f;
- matrix[ 3] = 0.0f; matrix[ 7] = 0.0f; matrix[11] = 0.0f; matrix[15] = 1.0f;
-}
-
-/*
-** RB_CalcRotateTexCoords
-*/
-void RB_CalcRotateTexCoords( float degsPerSecond, float *st )
-{
- float timeScale = tess.shaderTime;
- float degs;
- int index;
- float sinValue, cosValue;
- texModInfo_t tmi;
-
- degs = -degsPerSecond * timeScale;
- index = degs * ( FUNCTABLE_SIZE / 360.0f );
-
- sinValue = tr.sinTable[ index & FUNCTABLE_MASK ];
- cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ];
-
- tmi.matrix[0][0] = cosValue;
- tmi.matrix[1][0] = -sinValue;
- tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
-
- tmi.matrix[0][1] = sinValue;
- tmi.matrix[1][1] = cosValue;
- tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
-
- RB_CalcTransformTexCoords( &tmi, st );
-}
-
-void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix )
-{
- float timeScale = tess.shaderTime;
- float degs;
- int index;
- float sinValue, cosValue;
- texModInfo_t tmi;
-
- degs = -degsPerSecond * timeScale;
- index = degs * ( FUNCTABLE_SIZE / 360.0f );
-
- sinValue = tr.sinTable[ index & FUNCTABLE_MASK ];
- cosValue = tr.sinTable[ ( index + FUNCTABLE_SIZE / 4 ) & FUNCTABLE_MASK ];
-
- tmi.matrix[0][0] = cosValue;
- tmi.matrix[1][0] = -sinValue;
- tmi.translate[0] = 0.5 - 0.5 * cosValue + 0.5 * sinValue;
-
- tmi.matrix[0][1] = sinValue;
- tmi.matrix[1][1] = cosValue;
- tmi.translate[1] = 0.5 - 0.5 * sinValue - 0.5 * cosValue;
-
- RB_CalcTransformTexMatrix( &tmi, matrix );
-}
-/*
-** RB_CalcSpecularAlpha
-**
-** Calculates specular coefficient and places it in the alpha channel
-*/
-vec3_t lightOrigin = { -960, 1980, 96 }; // FIXME: track dynamically
-
-void RB_CalcSpecularAlpha( unsigned char *alphas ) {
- int i;
- float *v, *normal;
- vec3_t viewer, reflected;
- float l, d;
- int b;
- vec3_t lightDir;
- int numVertexes;
-
- v = tess.xyz[0];
- normal = tess.normal[0];
-
- alphas += 3;
-
- numVertexes = tess.numVertexes;
- for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4, alphas += 4) {
- float ilength;
-
- VectorSubtract( lightOrigin, v, lightDir );
-// ilength = Q_rsqrt( DotProduct( lightDir, lightDir ) );
- VectorNormalizeFast( lightDir );
-
- // calculate the specular color
- d = DotProduct (normal, lightDir);
-// d *= ilength;
-
- // we don't optimize for the d < 0 case since this tends to
- // cause visual artifacts such as faceted "snapping"
- reflected[0] = normal[0]*2*d - lightDir[0];
- reflected[1] = normal[1]*2*d - lightDir[1];
- reflected[2] = normal[2]*2*d - lightDir[2];
-
- VectorSubtract (backEnd.or.viewOrigin, v, viewer);
- ilength = Q_rsqrt( DotProduct( viewer, viewer ) );
- l = DotProduct (reflected, viewer);
- l *= ilength;
-
- if (l < 0) {
- b = 0;
- } else {
- l = l*l;
- l = l*l;
- b = l * 255;
- if (b > 255) {
- b = 255;
- }
- }
-
- *alphas = b;
- }
-}
-
-/*
-** RB_CalcDiffuseColor
-**
-** The basic vertex lighting calc
-*/
-#if idppc_altivec
-static void RB_CalcDiffuseColor_altivec( unsigned char *colors )
-{
- int i;
- float *v, *normal;
- trRefEntity_t *ent;
- int ambientLightInt;
- vec3_t lightDir;
- int numVertexes;
- vector unsigned char vSel = VECCONST_UINT8(0x00, 0x00, 0x00, 0xff,
- 0x00, 0x00, 0x00, 0xff,
- 0x00, 0x00, 0x00, 0xff,
- 0x00, 0x00, 0x00, 0xff);
- vector float ambientLightVec;
- vector float directedLightVec;
- vector float lightDirVec;
- vector float normalVec0, normalVec1;
- vector float incomingVec0, incomingVec1, incomingVec2;
- vector float zero, jVec;
- vector signed int jVecInt;
- vector signed short jVecShort;
- vector unsigned char jVecChar, normalPerm;
- ent = backEnd.currentEntity;
- ambientLightInt = ent->ambientLightInt;
- // A lot of this could be simplified if we made sure
- // entities light info was 16-byte aligned.
- jVecChar = vec_lvsl(0, ent->ambientLight);
- ambientLightVec = vec_ld(0, (vector float *)ent->ambientLight);
- jVec = vec_ld(11, (vector float *)ent->ambientLight);
- ambientLightVec = vec_perm(ambientLightVec,jVec,jVecChar);
-
- jVecChar = vec_lvsl(0, ent->directedLight);
- directedLightVec = vec_ld(0,(vector float *)ent->directedLight);
- jVec = vec_ld(11,(vector float *)ent->directedLight);
- directedLightVec = vec_perm(directedLightVec,jVec,jVecChar);
-
- jVecChar = vec_lvsl(0, ent->lightDir);
- lightDirVec = vec_ld(0,(vector float *)ent->lightDir);
- jVec = vec_ld(11,(vector float *)ent->lightDir);
- lightDirVec = vec_perm(lightDirVec,jVec,jVecChar);
-
- zero = (vector float)vec_splat_s8(0);
- VectorCopy( ent->lightDir, lightDir );
-
- v = tess.xyz[0];
- normal = tess.normal[0];
-
- normalPerm = vec_lvsl(0,normal);
- numVertexes = tess.numVertexes;
- for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
- normalVec0 = vec_ld(0,(vector float *)normal);
- normalVec1 = vec_ld(11,(vector float *)normal);
- normalVec0 = vec_perm(normalVec0,normalVec1,normalPerm);
- incomingVec0 = vec_madd(normalVec0, lightDirVec, zero);
- incomingVec1 = vec_sld(incomingVec0,incomingVec0,4);
- incomingVec2 = vec_add(incomingVec0,incomingVec1);
- incomingVec1 = vec_sld(incomingVec1,incomingVec1,4);
- incomingVec2 = vec_add(incomingVec2,incomingVec1);
- incomingVec0 = vec_splat(incomingVec2,0);
- incomingVec0 = vec_max(incomingVec0,zero);
- normalPerm = vec_lvsl(12,normal);
- jVec = vec_madd(incomingVec0, directedLightVec, ambientLightVec);
- jVecInt = vec_cts(jVec,0); // RGBx
- jVecShort = vec_pack(jVecInt,jVecInt); // RGBxRGBx
- jVecChar = vec_packsu(jVecShort,jVecShort); // RGBxRGBxRGBxRGBx
- jVecChar = vec_sel(jVecChar,vSel,vSel); // RGBARGBARGBARGBA replace alpha with 255
- vec_ste((vector unsigned int)jVecChar,0,(unsigned int *)&colors[i*4]); // store color
- }
-}
-#endif
-
-static void RB_CalcDiffuseColor_scalar( unsigned char *colors )
-{
- int i, j;
- float *v, *normal;
- float incoming;
- trRefEntity_t *ent;
- int ambientLightInt;
- vec3_t ambientLight;
- vec3_t lightDir;
- vec3_t directedLight;
- int numVertexes;
- ent = backEnd.currentEntity;
- ambientLightInt = ent->ambientLightInt;
- VectorCopy( ent->ambientLight, ambientLight );
- VectorCopy( ent->directedLight, directedLight );
- VectorCopy( ent->lightDir, lightDir );
-
- v = tess.xyz[0];
- normal = tess.normal[0];
-
- numVertexes = tess.numVertexes;
- for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) {
- incoming = DotProduct (normal, lightDir);
- if ( incoming <= 0 ) {
- *(int *)&colors[i*4] = ambientLightInt;
- continue;
- }
- j = ri.ftol(ambientLight[0] + incoming * directedLight[0]);
- if ( j > 255 ) {
- j = 255;
- }
- colors[i*4+0] = j;
-
- j = ri.ftol(ambientLight[1] + incoming * directedLight[1]);
- if ( j > 255 ) {
- j = 255;
- }
- colors[i*4+1] = j;
-
- j = ri.ftol(ambientLight[2] + incoming * directedLight[2]);
- if ( j > 255 ) {
- j = 255;
- }
- colors[i*4+2] = j;
-
- colors[i*4+3] = 255;
- }
-}
-
-void RB_CalcDiffuseColor( unsigned char *colors )
-{
-#if idppc_altivec
- if (com_altivec->integer) {
- // must be in a seperate function or G3 systems will crash.
- RB_CalcDiffuseColor_altivec( colors );
- return;
- }
-#endif
- RB_CalcDiffuseColor_scalar( colors );
-}
-
-
-
-
-
diff --git a/src/rend2/tr_shader.c b/src/rend2/tr_shader.c
deleted file mode 100644
index 8cad4b6b..00000000
--- a/src/rend2/tr_shader.c
+++ /dev/null
@@ -1,3741 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-#include "tr_local.h"
-
-// tr_shader.c -- this file deals with the parsing and definition of shaders
-
-static char *s_shaderText;
-
-// the shader is parsed into these global variables, then copied into
-// dynamically allocated memory if it is valid.
-static shaderStage_t stages[MAX_SHADER_STAGES];
-static shader_t shader;
-static texModInfo_t texMods[MAX_SHADER_STAGES][TR_MAX_TEXMODS];
-
-#define FILE_HASH_SIZE 1024
-static shader_t* hashTable[FILE_HASH_SIZE];
-
-#define MAX_SHADERTEXT_HASH 2048
-static char **shaderTextHashTable[MAX_SHADERTEXT_HASH];
-
-/*
-================
-return a hash value for the filename
-================
-*/
-#ifdef __GNUCC__
- #warning TODO: check if long is ok here
-#endif
-static long generateHashValue( const char *fname, const int size ) {
- int i;
- long hash;
- char letter;
-
- hash = 0;
- i = 0;
- while (fname[i] != '\0') {
- letter = tolower(fname[i]);
- if (letter =='.') break; // don't include extension
- if (letter =='\\') letter = '/'; // damn path names
- if (letter == PATH_SEP) letter = '/'; // damn path names
- hash+=(long)(letter)*(i+119);
- i++;
- }
- hash = (hash ^ (hash >> 10) ^ (hash >> 20));
- hash &= (size-1);
- return hash;
-}
-
-void R_RemapShader(const char *shaderName, const char *newShaderName, const char *timeOffset) {
- char strippedName[MAX_QPATH];
- int hash;
- shader_t *sh, *sh2;
- qhandle_t h;
-
- sh = R_FindShaderByName( shaderName );
- if (sh == NULL || sh == tr.defaultShader) {
- h = RE_RegisterShaderLightMap(shaderName, 0);
- sh = R_GetShaderByHandle(h);
- }
- if (sh == NULL || sh == tr.defaultShader) {
- ri.Printf( PRINT_WARNING, "WARNING: R_RemapShader: shader %s not found\n", shaderName );
- return;
- }
-
- sh2 = R_FindShaderByName( newShaderName );
- if (sh2 == NULL || sh2 == tr.defaultShader) {
- h = RE_RegisterShaderLightMap(newShaderName, 0);
- sh2 = R_GetShaderByHandle(h);
- }
-
- if (sh2 == NULL || sh2 == tr.defaultShader) {
- ri.Printf( PRINT_WARNING, "WARNING: R_RemapShader: new shader %s not found\n", newShaderName );
- return;
- }
-
- // remap all the shaders with the given name
- // even tho they might have different lightmaps
- COM_StripExtension(shaderName, strippedName, sizeof(strippedName));
- hash = generateHashValue(strippedName, FILE_HASH_SIZE);
- for (sh = hashTable[hash]; sh; sh = sh->next) {
- if (Q_stricmp(sh->name, strippedName) == 0) {
- if (sh != sh2) {
- sh->remappedShader = sh2;
- } else {
- sh->remappedShader = NULL;
- }
- }
- }
- if (timeOffset) {
- sh2->timeOffset = atof(timeOffset);
- }
-}
-
-/*
-===============
-ParseVector
-===============
-*/
-static qboolean ParseVector( char **text, int count, float *v ) {
- char *token;
- int i;
-
- // FIXME: spaces are currently required after parens, should change parseext...
- token = COM_ParseExt( text, qfalse );
- if ( strcmp( token, "(" ) ) {
- ri.Printf( PRINT_WARNING, "WARNING: missing parenthesis in shader '%s'\n", shader.name );
- return qfalse;
- }
-
- for ( i = 0 ; i < count ; i++ ) {
- token = COM_ParseExt( text, qfalse );
- if ( !token[0] ) {
- ri.Printf( PRINT_WARNING, "WARNING: missing vector element in shader '%s'\n", shader.name );
- return qfalse;
- }
- v[i] = atof( token );
- }
-
- token = COM_ParseExt( text, qfalse );
- if ( strcmp( token, ")" ) ) {
- ri.Printf( PRINT_WARNING, "WARNING: missing parenthesis in shader '%s'\n", shader.name );
- return qfalse;
- }
-
- return qtrue;
-}
-
-
-/*
-===============
-NameToAFunc
-===============
-*/
-static unsigned NameToAFunc( const char *funcname )
-{
- if ( !Q_stricmp( funcname, "GT0" ) )
- {
- return GLS_ATEST_GT_0;
- }
- else if ( !Q_stricmp( funcname, "LT128" ) )
- {
- return GLS_ATEST_LT_80;
- }
- else if ( !Q_stricmp( funcname, "GE128" ) )
- {
- return GLS_ATEST_GE_80;
- }
-
- ri.Printf( PRINT_WARNING, "WARNING: invalid alphaFunc name '%s' in shader '%s'\n", funcname, shader.name );
- return 0;
-}
-
-
-/*
-===============
-NameToSrcBlendMode
-===============
-*/
-static int NameToSrcBlendMode( const char *name )
-{
- if ( !Q_stricmp( name, "GL_ONE" ) )
- {
- return GLS_SRCBLEND_ONE;
- }
- else if ( !Q_stricmp( name, "GL_ZERO" ) )
- {
- return GLS_SRCBLEND_ZERO;
- }
- else if ( !Q_stricmp( name, "GL_DST_COLOR" ) )
- {
- return GLS_SRCBLEND_DST_COLOR;
- }
- else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_COLOR" ) )
- {
- return GLS_SRCBLEND_ONE_MINUS_DST_COLOR;
- }
- else if ( !Q_stricmp( name, "GL_SRC_ALPHA" ) )
- {
- return GLS_SRCBLEND_SRC_ALPHA;
- }
- else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_ALPHA" ) )
- {
- return GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA;
- }
- else if ( !Q_stricmp( name, "GL_DST_ALPHA" ) )
- {
- return GLS_SRCBLEND_DST_ALPHA;
- }
- else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_ALPHA" ) )
- {
- return GLS_SRCBLEND_ONE_MINUS_DST_ALPHA;
- }
- else if ( !Q_stricmp( name, "GL_SRC_ALPHA_SATURATE" ) )
- {
- return GLS_SRCBLEND_ALPHA_SATURATE;
- }
-
- ri.Printf( PRINT_WARNING, "WARNING: unknown blend mode '%s' in shader '%s', substituting GL_ONE\n", name, shader.name );
- return GLS_SRCBLEND_ONE;
-}
-
-/*
-===============
-NameToDstBlendMode
-===============
-*/
-static int NameToDstBlendMode( const char *name )
-{
- if ( !Q_stricmp( name, "GL_ONE" ) )
- {
- return GLS_DSTBLEND_ONE;
- }
- else if ( !Q_stricmp( name, "GL_ZERO" ) )
- {
- return GLS_DSTBLEND_ZERO;
- }
- else if ( !Q_stricmp( name, "GL_SRC_ALPHA" ) )
- {
- return GLS_DSTBLEND_SRC_ALPHA;
- }
- else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_ALPHA" ) )
- {
- return GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
- }
- else if ( !Q_stricmp( name, "GL_DST_ALPHA" ) )
- {
- return GLS_DSTBLEND_DST_ALPHA;
- }
- else if ( !Q_stricmp( name, "GL_ONE_MINUS_DST_ALPHA" ) )
- {
- return GLS_DSTBLEND_ONE_MINUS_DST_ALPHA;
- }
- else if ( !Q_stricmp( name, "GL_SRC_COLOR" ) )
- {
- return GLS_DSTBLEND_SRC_COLOR;
- }
- else if ( !Q_stricmp( name, "GL_ONE_MINUS_SRC_COLOR" ) )
- {
- return GLS_DSTBLEND_ONE_MINUS_SRC_COLOR;
- }
-
- ri.Printf( PRINT_WARNING, "WARNING: unknown blend mode '%s' in shader '%s', substituting GL_ONE\n", name, shader.name );
- return GLS_DSTBLEND_ONE;
-}
-
-/*
-===============
-NameToGenFunc
-===============
-*/
-static genFunc_t NameToGenFunc( const char *funcname )
-{
- if ( !Q_stricmp( funcname, "sin" ) )
- {
- return GF_SIN;
- }
- else if ( !Q_stricmp( funcname, "square" ) )
- {
- return GF_SQUARE;
- }
- else if ( !Q_stricmp( funcname, "triangle" ) )
- {
- return GF_TRIANGLE;
- }
- else if ( !Q_stricmp( funcname, "sawtooth" ) )
- {
- return GF_SAWTOOTH;
- }
- else if ( !Q_stricmp( funcname, "inversesawtooth" ) )
- {
- return GF_INVERSE_SAWTOOTH;
- }
- else if ( !Q_stricmp( funcname, "noise" ) )
- {
- return GF_NOISE;
- }
-
- ri.Printf( PRINT_WARNING, "WARNING: invalid genfunc name '%s' in shader '%s'\n", funcname, shader.name );
- return GF_SIN;
-}
-
-
-/*
-===================
-ParseWaveForm
-===================
-*/
-static void ParseWaveForm( char **text, waveForm_t *wave )
-{
- char *token;
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
- return;
- }
- wave->func = NameToGenFunc( token );
-
- // BASE, AMP, PHASE, FREQ
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
- return;
- }
- wave->base = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
- return;
- }
- wave->amplitude = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
- return;
- }
- wave->phase = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing waveform parm in shader '%s'\n", shader.name );
- return;
- }
- wave->frequency = atof( token );
-}
-
-
-/*
-===================
-ParseTexMod
-===================
-*/
-static void ParseTexMod( char *_text, shaderStage_t *stage )
-{
- const char *token;
- char **text = &_text;
- texModInfo_t *tmi;
-
- if ( stage->bundle[0].numTexMods == TR_MAX_TEXMODS ) {
- ri.Error( ERR_DROP, "ERROR: too many tcMod stages in shader '%s'", shader.name );
- return;
- }
-
- tmi = &stage->bundle[0].texMods[stage->bundle[0].numTexMods];
- stage->bundle[0].numTexMods++;
-
- token = COM_ParseExt( text, qfalse );
-
- //
- // turb
- //
- if ( !Q_stricmp( token, "turb" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->wave.base = atof( token );
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name );
- return;
- }
- tmi->wave.amplitude = atof( token );
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name );
- return;
- }
- tmi->wave.phase = atof( token );
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing tcMod turb in shader '%s'\n", shader.name );
- return;
- }
- tmi->wave.frequency = atof( token );
-
- tmi->type = TMOD_TURBULENT;
- }
- //
- // scale
- //
- else if ( !Q_stricmp( token, "scale" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing scale parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->scale[0] = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing scale parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->scale[1] = atof( token );
- tmi->type = TMOD_SCALE;
- }
- //
- // scroll
- //
- else if ( !Q_stricmp( token, "scroll" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing scale scroll parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->scroll[0] = atof( token );
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing scale scroll parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->scroll[1] = atof( token );
- tmi->type = TMOD_SCROLL;
- }
- //
- // stretch
- //
- else if ( !Q_stricmp( token, "stretch" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->wave.func = NameToGenFunc( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->wave.base = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->wave.amplitude = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->wave.phase = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing stretch parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->wave.frequency = atof( token );
-
- tmi->type = TMOD_STRETCH;
- }
- //
- // transform
- //
- else if ( !Q_stricmp( token, "transform" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->matrix[0][0] = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->matrix[0][1] = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->matrix[1][0] = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->matrix[1][1] = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->translate[0] = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing transform parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->translate[1] = atof( token );
-
- tmi->type = TMOD_TRANSFORM;
- }
- //
- // rotate
- //
- else if ( !Q_stricmp( token, "rotate" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing tcMod rotate parms in shader '%s'\n", shader.name );
- return;
- }
- tmi->rotateSpeed = atof( token );
- tmi->type = TMOD_ROTATE;
- }
- //
- // entityTranslate
- //
- else if ( !Q_stricmp( token, "entityTranslate" ) )
- {
- tmi->type = TMOD_ENTITY_TRANSLATE;
- }
- else
- {
- ri.Printf( PRINT_WARNING, "WARNING: unknown tcMod '%s' in shader '%s'\n", token, shader.name );
- }
-}
-
-
-/*
-===================
-ParseStage
-===================
-*/
-static qboolean ParseStage( shaderStage_t *stage, char **text )
-{
- char *token;
- int depthMaskBits = GLS_DEPTHMASK_TRUE, blendSrcBits = 0, blendDstBits = 0, atestBits = 0, depthFuncBits = 0;
- qboolean depthMaskExplicit = qfalse;
-
- stage->active = qtrue;
-
- while ( 1 )
- {
- token = COM_ParseExt( text, qtrue );
- if ( !token[0] )
- {
- ri.Printf( PRINT_WARNING, "WARNING: no matching '}' found\n" );
- return qfalse;
- }
-
- if ( token[0] == '}' )
- {
- break;
- }
- //
- // map <name>
- //
- else if ( !Q_stricmp( token, "map" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( !token[0] )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'map' keyword in shader '%s'\n", shader.name );
- return qfalse;
- }
-
- if ( !Q_stricmp( token, "$whiteimage" ) )
- {
- stage->bundle[0].image[0] = tr.whiteImage;
- continue;
- }
- else if ( !Q_stricmp( token, "$lightmap" ) )
- {
- stage->bundle[0].isLightmap = qtrue;
- if ( shader.lightmapIndex < 0 ) {
- stage->bundle[0].image[0] = tr.whiteImage;
- } else {
- stage->bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex];
- }
- continue;
- }
- else if ( !Q_stricmp( token, "$deluxemap" ) )
- {
- if (!tr.worldDeluxeMapping)
- {
- ri.Printf( PRINT_WARNING, "WARNING: shader '%s' wants a deluxe map in a map compiled without them\n", shader.name );
- return qfalse;
- }
-
- stage->bundle[0].isLightmap = qtrue;
- if ( shader.lightmapIndex < 0 ) {
- stage->bundle[0].image[0] = tr.whiteImage;
- } else {
- stage->bundle[0].image[0] = tr.deluxemaps[shader.lightmapIndex];
- }
- continue;
- }
- else
- {
- imgType_t type = IMGTYPE_COLORALPHA;
- imgFlags_t flags = IMGFLAG_NONE;
-
- if (!shader.noMipMaps)
- flags |= IMGFLAG_MIPMAP;
-
- if (!shader.noPicMip)
- flags |= IMGFLAG_PICMIP;
-
- if (stage->type == ST_NORMALMAP || stage->type == ST_NORMALPARALLAXMAP)
- {
- type = IMGTYPE_NORMAL;
- flags |= IMGFLAG_NOLIGHTSCALE;
-
- if (stage->type == ST_NORMALPARALLAXMAP)
- type = IMGTYPE_NORMALHEIGHT;
- }
- else
- {
- if (r_genNormalMaps->integer)
- flags |= IMGFLAG_GENNORMALMAP;
-
- if (r_srgb->integer)
- flags |= IMGFLAG_SRGB;
- }
-
- stage->bundle[0].image[0] = R_FindImageFile( token, type, flags );
-
- if ( !stage->bundle[0].image[0] )
- {
- ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
- return qfalse;
- }
- }
- }
- //
- // clampmap <name>
- //
- else if ( !Q_stricmp( token, "clampmap" ) )
- {
- imgType_t type = IMGTYPE_COLORALPHA;
- imgFlags_t flags = IMGFLAG_CLAMPTOEDGE | IMGFLAG_SRGB;
-
- token = COM_ParseExt( text, qfalse );
- if ( !token[0] )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'clampmap' keyword in shader '%s'\n", shader.name );
- return qfalse;
- }
-
- if (!shader.noMipMaps)
- flags |= IMGFLAG_MIPMAP;
-
- if (!shader.noPicMip)
- flags |= IMGFLAG_PICMIP;
-
- if (stage->type == ST_NORMALMAP || stage->type == ST_NORMALPARALLAXMAP)
- {
- type = IMGTYPE_NORMAL;
- flags |= IMGFLAG_NOLIGHTSCALE;
-
- if (stage->type == ST_NORMALPARALLAXMAP)
- type = IMGTYPE_NORMALHEIGHT;
- }
- else
- {
- if (r_genNormalMaps->integer)
- flags |= IMGFLAG_GENNORMALMAP;
-
- if (r_srgb->integer)
- flags |= IMGFLAG_SRGB;
- }
-
-
- stage->bundle[0].image[0] = R_FindImageFile( token, type, flags );
- if ( !stage->bundle[0].image[0] )
- {
- ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
- return qfalse;
- }
- }
- //
- // animMap <frequency> <image1> .... <imageN>
- //
- else if ( !Q_stricmp( token, "animMap" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( !token[0] )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'animMmap' keyword in shader '%s'\n", shader.name );
- return qfalse;
- }
- stage->bundle[0].imageAnimationSpeed = atof( token );
-
- // parse up to MAX_IMAGE_ANIMATIONS animations
- while ( 1 ) {
- int num;
-
- token = COM_ParseExt( text, qfalse );
- if ( !token[0] ) {
- break;
- }
- num = stage->bundle[0].numImageAnimations;
- if ( num < MAX_IMAGE_ANIMATIONS ) {
- imgFlags_t flags = IMGFLAG_SRGB;
-
- if (!shader.noMipMaps)
- flags |= IMGFLAG_MIPMAP;
-
- if (!shader.noPicMip)
- flags |= IMGFLAG_PICMIP;
-
- stage->bundle[0].image[num] = R_FindImageFile( token, IMGTYPE_COLORALPHA, flags );
- if ( !stage->bundle[0].image[num] )
- {
- ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name );
- return qfalse;
- }
- stage->bundle[0].numImageAnimations++;
- }
- }
- }
- else if ( !Q_stricmp( token, "videoMap" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( !token[0] )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'videoMmap' keyword in shader '%s'\n", shader.name );
- return qfalse;
- }
- stage->bundle[0].videoMapHandle = ri.CIN_PlayCinematic( token, 0, 0, 256, 256, (CIN_loop | CIN_silent | CIN_shader));
- if (stage->bundle[0].videoMapHandle != -1) {
- stage->bundle[0].isVideoMap = qtrue;
- stage->bundle[0].image[0] = tr.scratchImage[stage->bundle[0].videoMapHandle];
- }
- }
- //
- // alphafunc <func>
- //
- else if ( !Q_stricmp( token, "alphaFunc" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( !token[0] )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'alphaFunc' keyword in shader '%s'\n", shader.name );
- return qfalse;
- }
-
- atestBits = NameToAFunc( token );
- }
- //
- // depthFunc <func>
- //
- else if ( !Q_stricmp( token, "depthfunc" ) )
- {
- token = COM_ParseExt( text, qfalse );
-
- if ( !token[0] )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'depthfunc' keyword in shader '%s'\n", shader.name );
- return qfalse;
- }
-
- if ( !Q_stricmp( token, "lequal" ) )
- {
- depthFuncBits = 0;
- }
- else if ( !Q_stricmp( token, "equal" ) )
- {
- depthFuncBits = GLS_DEPTHFUNC_EQUAL;
- }
- else
- {
- ri.Printf( PRINT_WARNING, "WARNING: unknown depthfunc '%s' in shader '%s'\n", token, shader.name );
- continue;
- }
- }
- //
- // detail
- //
- else if ( !Q_stricmp( token, "detail" ) )
- {
- stage->isDetail = qtrue;
- }
- //
- // blendfunc <srcFactor> <dstFactor>
- // or blendfunc <add|filter|blend>
- //
- else if ( !Q_stricmp( token, "blendfunc" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing parm for blendFunc in shader '%s'\n", shader.name );
- continue;
- }
- // check for "simple" blends first
- if ( !Q_stricmp( token, "add" ) ) {
- blendSrcBits = GLS_SRCBLEND_ONE;
- blendDstBits = GLS_DSTBLEND_ONE;
- } else if ( !Q_stricmp( token, "filter" ) ) {
- blendSrcBits = GLS_SRCBLEND_DST_COLOR;
- blendDstBits = GLS_DSTBLEND_ZERO;
- } else if ( !Q_stricmp( token, "blend" ) ) {
- blendSrcBits = GLS_SRCBLEND_SRC_ALPHA;
- blendDstBits = GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
- } else {
- // complex double blends
- blendSrcBits = NameToSrcBlendMode( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing parm for blendFunc in shader '%s'\n", shader.name );
- continue;
- }
- blendDstBits = NameToDstBlendMode( token );
- }
-
- // clear depth mask for blended surfaces
- if ( !depthMaskExplicit )
- {
- depthMaskBits = 0;
- }
- }
- //
- // stage <type>
- //
- else if(!Q_stricmp(token, "stage"))
- {
- token = COM_ParseExt(text, qfalse);
- if(token[0] == 0)
- {
- ri.Printf(PRINT_WARNING, "WARNING: missing parameters for stage in shader '%s'\n", shader.name);
- continue;
- }
-
- if(!Q_stricmp(token, "diffuseMap"))
- {
- stage->type = ST_DIFFUSEMAP;
- }
- else if(!Q_stricmp(token, "normalMap") || !Q_stricmp(token, "bumpMap"))
- {
- stage->type = ST_NORMALMAP;
- }
- else if(!Q_stricmp(token, "normalParallaxMap") || !Q_stricmp(token, "bumpParallaxMap"))
- {
- if (r_parallaxMapping->integer)
- stage->type = ST_NORMALPARALLAXMAP;
- else
- stage->type = ST_NORMALMAP;
- }
- else if(!Q_stricmp(token, "specularMap"))
- {
- stage->type = ST_SPECULARMAP;
- stage->materialInfo[0] = 0.04f;
- stage->materialInfo[1] = 256.0f;
- }
- else
- {
- ri.Printf(PRINT_WARNING, "WARNING: unknown stage parameter '%s' in shader '%s'\n", token, shader.name);
- continue;
- }
- }
- //
- // specularReflectance <value>
- //
- else if (!Q_stricmp(token, "specularreflectance"))
- {
- token = COM_ParseExt(text, qfalse);
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specular reflectance in shader '%s'\n", shader.name );
- continue;
- }
- stage->materialInfo[0] = atof( token );
- }
- //
- // specularExponent <value>
- //
- else if (!Q_stricmp(token, "specularexponent"))
- {
- token = COM_ParseExt(text, qfalse);
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specular exponent in shader '%s'\n", shader.name );
- continue;
- }
- stage->materialInfo[1] = atof( token );
- }
- //
- // rgbGen
- //
- else if ( !Q_stricmp( token, "rgbGen" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing parameters for rgbGen in shader '%s'\n", shader.name );
- continue;
- }
-
- if ( !Q_stricmp( token, "wave" ) )
- {
- ParseWaveForm( text, &stage->rgbWave );
- stage->rgbGen = CGEN_WAVEFORM;
- }
- else if ( !Q_stricmp( token, "const" ) )
- {
- vec3_t color;
-
- ParseVector( text, 3, color );
- stage->constantColor[0] = 255 * color[0];
- stage->constantColor[1] = 255 * color[1];
- stage->constantColor[2] = 255 * color[2];
-
- stage->rgbGen = CGEN_CONST;
- }
- else if ( !Q_stricmp( token, "identity" ) )
- {
- stage->rgbGen = CGEN_IDENTITY;
- }
- else if ( !Q_stricmp( token, "identityLighting" ) )
- {
- stage->rgbGen = CGEN_IDENTITY_LIGHTING;
- }
- else if ( !Q_stricmp( token, "entity" ) )
- {
- stage->rgbGen = CGEN_ENTITY;
- }
- else if ( !Q_stricmp( token, "oneMinusEntity" ) )
- {
- stage->rgbGen = CGEN_ONE_MINUS_ENTITY;
- }
- else if ( !Q_stricmp( token, "vertex" ) )
- {
- stage->rgbGen = CGEN_VERTEX;
- if ( stage->alphaGen == 0 ) {
- stage->alphaGen = AGEN_VERTEX;
- }
- }
- else if ( !Q_stricmp( token, "exactVertex" ) )
- {
- stage->rgbGen = CGEN_EXACT_VERTEX;
- }
- else if ( !Q_stricmp( token, "vertexLit" ) )
- {
- stage->rgbGen = CGEN_VERTEX_LIT;
- if ( stage->alphaGen == 0 ) {
- stage->alphaGen = AGEN_VERTEX;
- }
- }
- else if ( !Q_stricmp( token, "exactVertexLit" ) )
- {
- stage->rgbGen = CGEN_EXACT_VERTEX_LIT;
- }
- else if ( !Q_stricmp( token, "lightingDiffuse" ) )
- {
- stage->rgbGen = CGEN_LIGHTING_DIFFUSE;
- }
- else if ( !Q_stricmp( token, "oneMinusVertex" ) )
- {
- stage->rgbGen = CGEN_ONE_MINUS_VERTEX;
- }
- else
- {
- ri.Printf( PRINT_WARNING, "WARNING: unknown rgbGen parameter '%s' in shader '%s'\n", token, shader.name );
- continue;
- }
- }
- //
- // alphaGen
- //
- else if ( !Q_stricmp( token, "alphaGen" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing parameters for alphaGen in shader '%s'\n", shader.name );
- continue;
- }
-
- if ( !Q_stricmp( token, "wave" ) )
- {
- ParseWaveForm( text, &stage->alphaWave );
- stage->alphaGen = AGEN_WAVEFORM;
- }
- else if ( !Q_stricmp( token, "const" ) )
- {
- token = COM_ParseExt( text, qfalse );
- stage->constantColor[3] = 255 * atof( token );
- stage->alphaGen = AGEN_CONST;
- }
- else if ( !Q_stricmp( token, "identity" ) )
- {
- stage->alphaGen = AGEN_IDENTITY;
- }
- else if ( !Q_stricmp( token, "entity" ) )
- {
- stage->alphaGen = AGEN_ENTITY;
- }
- else if ( !Q_stricmp( token, "oneMinusEntity" ) )
- {
- stage->alphaGen = AGEN_ONE_MINUS_ENTITY;
- }
- else if ( !Q_stricmp( token, "vertex" ) )
- {
- stage->alphaGen = AGEN_VERTEX;
- }
- else if ( !Q_stricmp( token, "lightingSpecular" ) )
- {
- stage->alphaGen = AGEN_LIGHTING_SPECULAR;
- }
- else if ( !Q_stricmp( token, "oneMinusVertex" ) )
- {
- stage->alphaGen = AGEN_ONE_MINUS_VERTEX;
- }
- else if ( !Q_stricmp( token, "portal" ) )
- {
- stage->alphaGen = AGEN_PORTAL;
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- shader.portalRange = 256;
- ri.Printf( PRINT_WARNING, "WARNING: missing range parameter for alphaGen portal in shader '%s', defaulting to 256\n", shader.name );
- }
- else
- {
- shader.portalRange = atof( token );
- }
- }
- else if ( !Q_stricmp( token, "fresnel" ) )
- {
- stage->alphaGen = AGEN_FRESNEL;
- }
- else
- {
- ri.Printf( PRINT_WARNING, "WARNING: unknown alphaGen parameter '%s' in shader '%s'\n", token, shader.name );
- continue;
- }
- }
- //
- // tcGen <function>
- //
- else if ( !Q_stricmp(token, "texgen") || !Q_stricmp( token, "tcGen" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing texgen parm in shader '%s'\n", shader.name );
- continue;
- }
-
- if ( !Q_stricmp( token, "environment" ) )
- {
- stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_MAPPED;
- }
- else if ( !Q_stricmp( token, "lightmap" ) )
- {
- stage->bundle[0].tcGen = TCGEN_LIGHTMAP;
- }
- else if ( !Q_stricmp( token, "texture" ) || !Q_stricmp( token, "base" ) )
- {
- stage->bundle[0].tcGen = TCGEN_TEXTURE;
- }
- else if ( !Q_stricmp( token, "vector" ) )
- {
- ParseVector( text, 3, stage->bundle[0].tcGenVectors[0] );
- ParseVector( text, 3, stage->bundle[0].tcGenVectors[1] );
-
- stage->bundle[0].tcGen = TCGEN_VECTOR;
- }
- else
- {
- ri.Printf( PRINT_WARNING, "WARNING: unknown texgen parm in shader '%s'\n", shader.name );
- }
- }
- //
- // tcMod <type> <...>
- //
- else if ( !Q_stricmp( token, "tcMod" ) )
- {
- char buffer[1024] = "";
-
- while ( 1 )
- {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- break;
- strcat( buffer, token );
- strcat( buffer, " " );
- }
-
- ParseTexMod( buffer, stage );
-
- continue;
- }
- //
- // depthmask
- //
- else if ( !Q_stricmp( token, "depthwrite" ) )
- {
- depthMaskBits = GLS_DEPTHMASK_TRUE;
- depthMaskExplicit = qtrue;
-
- continue;
- }
- else
- {
- ri.Printf( PRINT_WARNING, "WARNING: unknown parameter '%s' in shader '%s'\n", token, shader.name );
- return qfalse;
- }
- }
-
- //
- // if cgen isn't explicitly specified, use either identity or identitylighting
- //
- if ( stage->rgbGen == CGEN_BAD ) {
- if ( blendSrcBits == 0 ||
- blendSrcBits == GLS_SRCBLEND_ONE ||
- blendSrcBits == GLS_SRCBLEND_SRC_ALPHA ) {
- stage->rgbGen = CGEN_IDENTITY_LIGHTING;
- } else {
- stage->rgbGen = CGEN_IDENTITY;
- }
- }
-
-
- //
- // implicitly assume that a GL_ONE GL_ZERO blend mask disables blending
- //
- if ( ( blendSrcBits == GLS_SRCBLEND_ONE ) &&
- ( blendDstBits == GLS_DSTBLEND_ZERO ) )
- {
- blendDstBits = blendSrcBits = 0;
- depthMaskBits = GLS_DEPTHMASK_TRUE;
- }
-
- // decide which agens we can skip
- if ( stage->alphaGen == AGEN_IDENTITY ) {
- if ( stage->rgbGen == CGEN_IDENTITY
- || stage->rgbGen == CGEN_LIGHTING_DIFFUSE ) {
- stage->alphaGen = AGEN_SKIP;
- }
- }
-
- //
- // compute state bits
- //
- stage->stateBits = depthMaskBits |
- blendSrcBits | blendDstBits |
- atestBits |
- depthFuncBits;
-
- return qtrue;
-}
-
-/*
-===============
-ParseDeform
-
-deformVertexes wave <spread> <waveform> <base> <amplitude> <phase> <frequency>
-deformVertexes normal <frequency> <amplitude>
-deformVertexes move <vector> <waveform> <base> <amplitude> <phase> <frequency>
-deformVertexes bulge <bulgeWidth> <bulgeHeight> <bulgeSpeed>
-deformVertexes projectionShadow
-deformVertexes autoSprite
-deformVertexes autoSprite2
-deformVertexes text[0-7]
-===============
-*/
-static void ParseDeform( char **text ) {
- char *token;
- deformStage_t *ds;
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing deform parm in shader '%s'\n", shader.name );
- return;
- }
-
- if ( shader.numDeforms == MAX_SHADER_DEFORMS ) {
- ri.Printf( PRINT_WARNING, "WARNING: MAX_SHADER_DEFORMS in '%s'\n", shader.name );
- return;
- }
-
- ds = &shader.deforms[ shader.numDeforms ];
- shader.numDeforms++;
-
- if ( !Q_stricmp( token, "projectionShadow" ) ) {
- ds->deformation = DEFORM_PROJECTION_SHADOW;
- return;
- }
-
- if ( !Q_stricmp( token, "autosprite" ) ) {
- ds->deformation = DEFORM_AUTOSPRITE;
- return;
- }
-
- if ( !Q_stricmp( token, "autosprite2" ) ) {
- ds->deformation = DEFORM_AUTOSPRITE2;
- return;
- }
-
- if ( !Q_stricmpn( token, "text", 4 ) ) {
- int n;
-
- n = token[4] - '0';
- if ( n < 0 || n > 7 ) {
- n = 0;
- }
- ds->deformation = DEFORM_TEXT0 + n;
- return;
- }
-
- if ( !Q_stricmp( token, "bulge" ) ) {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name );
- return;
- }
- ds->bulgeWidth = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name );
- return;
- }
- ds->bulgeHeight = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes bulge parm in shader '%s'\n", shader.name );
- return;
- }
- ds->bulgeSpeed = atof( token );
-
- ds->deformation = DEFORM_BULGE;
- return;
- }
-
- if ( !Q_stricmp( token, "wave" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
- return;
- }
-
- if ( atof( token ) != 0 )
- {
- ds->deformationSpread = 1.0f / atof( token );
- }
- else
- {
- ds->deformationSpread = 100.0f;
- ri.Printf( PRINT_WARNING, "WARNING: illegal div value of 0 in deformVertexes command for shader '%s'\n", shader.name );
- }
-
- ParseWaveForm( text, &ds->deformationWave );
- ds->deformation = DEFORM_WAVE;
- return;
- }
-
- if ( !Q_stricmp( token, "normal" ) )
- {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
- return;
- }
- ds->deformationWave.amplitude = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
- return;
- }
- ds->deformationWave.frequency = atof( token );
-
- ds->deformation = DEFORM_NORMALS;
- return;
- }
-
- if ( !Q_stricmp( token, "move" ) ) {
- int i;
-
- for ( i = 0 ; i < 3 ; i++ ) {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 ) {
- ri.Printf( PRINT_WARNING, "WARNING: missing deformVertexes parm in shader '%s'\n", shader.name );
- return;
- }
- ds->moveVector[i] = atof( token );
- }
-
- ParseWaveForm( text, &ds->deformationWave );
- ds->deformation = DEFORM_MOVE;
- return;
- }
-
- ri.Printf( PRINT_WARNING, "WARNING: unknown deformVertexes subtype '%s' found in shader '%s'\n", token, shader.name );
-}
-
-
-/*
-===============
-ParseSkyParms
-
-skyParms <outerbox> <cloudheight> <innerbox>
-===============
-*/
-static void ParseSkyParms( char **text ) {
- char *token;
- static char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
- char pathname[MAX_QPATH];
- int i;
-
- // outerbox
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 ) {
- ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name );
- return;
- }
- if ( strcmp( token, "-" ) ) {
- for (i=0 ; i<6 ; i++) {
- Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga"
- , token, suf[i] );
- shader.sky.outerbox[i] = R_FindImageFile( ( char * ) pathname, IMGTYPE_COLORALPHA, IMGFLAG_SRGB | IMGFLAG_MIPMAP | IMGFLAG_PICMIP | IMGFLAG_CLAMPTOEDGE );
-
- if ( !shader.sky.outerbox[i] ) {
- shader.sky.outerbox[i] = tr.defaultImage;
- }
- }
- }
-
- // cloudheight
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 ) {
- ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name );
- return;
- }
- shader.sky.cloudHeight = atof( token );
- if ( !shader.sky.cloudHeight ) {
- shader.sky.cloudHeight = 512;
- }
- R_InitSkyTexCoords( shader.sky.cloudHeight );
-
-
- // innerbox
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 ) {
- ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name );
- return;
- }
- if ( strcmp( token, "-" ) ) {
- for (i=0 ; i<6 ; i++) {
- Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga"
- , token, suf[i] );
- shader.sky.innerbox[i] = R_FindImageFile( ( char * ) pathname, IMGTYPE_COLORALPHA, IMGFLAG_SRGB | IMGFLAG_MIPMAP | IMGFLAG_PICMIP );
- if ( !shader.sky.innerbox[i] ) {
- shader.sky.innerbox[i] = tr.defaultImage;
- }
- }
- }
-
- shader.isSky = qtrue;
-}
-
-
-/*
-=================
-ParseSort
-=================
-*/
-void ParseSort( char **text ) {
- char *token;
-
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 ) {
- ri.Printf( PRINT_WARNING, "WARNING: missing sort parameter in shader '%s'\n", shader.name );
- return;
- }
-
- if ( !Q_stricmp( token, "portal" ) ) {
- shader.sort = SS_PORTAL;
- } else if ( !Q_stricmp( token, "sky" ) ) {
- shader.sort = SS_ENVIRONMENT;
- } else if ( !Q_stricmp( token, "opaque" ) ) {
- shader.sort = SS_OPAQUE;
- }else if ( !Q_stricmp( token, "decal" ) ) {
- shader.sort = SS_DECAL;
- } else if ( !Q_stricmp( token, "seeThrough" ) ) {
- shader.sort = SS_SEE_THROUGH;
- } else if ( !Q_stricmp( token, "banner" ) ) {
- shader.sort = SS_BANNER;
- } else if ( !Q_stricmp( token, "additive" ) ) {
- shader.sort = SS_BLEND1;
- } else if ( !Q_stricmp( token, "nearest" ) ) {
- shader.sort = SS_NEAREST;
- } else if ( !Q_stricmp( token, "underwater" ) ) {
- shader.sort = SS_UNDERWATER;
- } else {
- shader.sort = atof( token );
- }
-}
-
-
-
-// this table is also present in q3map
-
-typedef struct {
- char *name;
- int clearSolid, surfaceFlags, contents;
-} infoParm_t;
-
-infoParm_t infoParms[] = {
- // server relevant contents
- {"water", 1, 0, CONTENTS_WATER },
- {"slime", 1, 0, CONTENTS_SLIME }, // mildly damaging
- {"lava", 1, 0, CONTENTS_LAVA }, // very damaging
- {"playerclip", 1, 0, CONTENTS_PLAYERCLIP },
- {"monsterclip", 1, 0, CONTENTS_MONSTERCLIP },
- {"nodrop", 1, 0, CONTENTS_NODROP }, // don't drop items or leave bodies (death fog, lava, etc)
- {"nonsolid", 1, SURF_NONSOLID, 0}, // clears the solid flag
-
- // utility relevant attributes
- {"origin", 1, 0, CONTENTS_ORIGIN }, // center of rotating brushes
- {"trans", 0, 0, CONTENTS_TRANSLUCENT }, // don't eat contained surfaces
- {"detail", 0, 0, CONTENTS_DETAIL }, // don't include in structural bsp
- {"structural", 0, 0, CONTENTS_STRUCTURAL }, // force into structural bsp even if trnas
- {"areaportal", 1, 0, CONTENTS_AREAPORTAL }, // divides areas
- {"clusterportal", 1,0, CONTENTS_CLUSTERPORTAL }, // for bots
- {"donotenter", 1, 0, CONTENTS_DONOTENTER }, // for bots
-
- {"fog", 1, 0, CONTENTS_FOG}, // carves surfaces entering
- {"sky", 0, SURF_SKY, 0 }, // emit light from an environment map
- {"lightfilter", 0, SURF_LIGHTFILTER, 0 }, // filter light going through it
- {"alphashadow", 0, SURF_ALPHASHADOW, 0 }, // test light on a per-pixel basis
- {"hint", 0, SURF_HINT, 0 }, // use as a primary splitter
-
- // server attributes
- {"slick", 0, SURF_SLICK, 0 },
- {"noimpact", 0, SURF_NOIMPACT, 0 }, // don't make impact explosions or marks
- {"nomarks", 0, SURF_NOMARKS, 0 }, // don't make impact marks, but still explode
- {"ladder", 0, SURF_LADDER, 0 },
- {"nodamage", 0, SURF_NODAMAGE, 0 },
- {"metalsteps", 0, SURF_METALSTEPS,0 },
- {"flesh", 0, SURF_FLESH, 0 },
- {"nosteps", 0, SURF_NOSTEPS, 0 },
-
- // drawsurf attributes
- {"nodraw", 0, SURF_NODRAW, 0 }, // don't generate a drawsurface (or a lightmap)
- {"pointlight", 0, SURF_POINTLIGHT, 0 }, // sample lighting at vertexes
- {"nolightmap", 0, SURF_NOLIGHTMAP,0 }, // don't generate a lightmap
- {"nodlight", 0, SURF_NODLIGHT, 0 }, // don't ever add dynamic lights
- {"dust", 0, SURF_DUST, 0} // leave a dust trail when walking on this surface
-};
-
-
-/*
-===============
-ParseSurfaceParm
-
-surfaceparm <name>
-===============
-*/
-static void ParseSurfaceParm( char **text ) {
- char *token;
- int numInfoParms = ARRAY_LEN( infoParms );
- int i;
-
- token = COM_ParseExt( text, qfalse );
- for ( i = 0 ; i < numInfoParms ; i++ ) {
- if ( !Q_stricmp( token, infoParms[i].name ) ) {
- shader.surfaceFlags |= infoParms[i].surfaceFlags;
- shader.contentFlags |= infoParms[i].contents;
-#if 0
- if ( infoParms[i].clearSolid ) {
- si->contents &= ~CONTENTS_SOLID;
- }
-#endif
- break;
- }
- }
-}
-
-/*
-=================
-ParseShader
-
-The current text pointer is at the explicit text definition of the
-shader. Parse it into the global shader variable. Later functions
-will optimize it.
-=================
-*/
-static qboolean ParseShader( char **text )
-{
- char *token;
- int s;
-
- s = 0;
-
- token = COM_ParseExt( text, qtrue );
- if ( token[0] != '{' )
- {
- ri.Printf( PRINT_WARNING, "WARNING: expecting '{', found '%s' instead in shader '%s'\n", token, shader.name );
- return qfalse;
- }
-
- while ( 1 )
- {
- token = COM_ParseExt( text, qtrue );
- if ( !token[0] )
- {
- ri.Printf( PRINT_WARNING, "WARNING: no concluding '}' in shader %s\n", shader.name );
- return qfalse;
- }
-
- // end of shader definition
- if ( token[0] == '}' )
- {
- break;
- }
- // stage definition
- else if ( token[0] == '{' )
- {
- if ( s >= MAX_SHADER_STAGES ) {
- ri.Printf( PRINT_WARNING, "WARNING: too many stages in shader %s\n", shader.name );
- return qfalse;
- }
-
- if ( !ParseStage( &stages[s], text ) )
- {
- return qfalse;
- }
- stages[s].active = qtrue;
- s++;
-
- continue;
- }
- // skip stuff that only the QuakeEdRadient needs
- else if ( !Q_stricmpn( token, "qer", 3 ) ) {
- SkipRestOfLine( text );
- continue;
- }
- // sun parms
- else if ( !Q_stricmp( token, "q3map_sun" ) || !Q_stricmp( token, "q3map_sunExt" ) || !Q_stricmp( token, "q3gl2_sun" ) ) {
- float a, b;
- qboolean isGL2Sun = qfalse;
-
- if (!Q_stricmp( token, "q3gl2_sun" ) && r_sunShadows->integer )
- {
- isGL2Sun = qtrue;
- tr.sunShadows = qtrue;
- }
-
- token = COM_ParseExt( text, qfalse );
- tr.sunLight[0] = atof( token );
- token = COM_ParseExt( text, qfalse );
- tr.sunLight[1] = atof( token );
- token = COM_ParseExt( text, qfalse );
- tr.sunLight[2] = atof( token );
-
- VectorNormalize( tr.sunLight );
-
- token = COM_ParseExt( text, qfalse );
- a = atof( token );
- VectorScale( tr.sunLight, a, tr.sunLight);
-
- VectorSet( tr.sunAmbient, 0.0f, 0.0f, 0.0f);
-
- token = COM_ParseExt( text, qfalse );
- a = atof( token );
- a = a / 180 * M_PI;
-
- token = COM_ParseExt( text, qfalse );
- b = atof( token );
- b = b / 180 * M_PI;
-
- tr.sunDirection[0] = cos( a ) * cos( b );
- tr.sunDirection[1] = sin( a ) * cos( b );
- tr.sunDirection[2] = sin( b );
-
- if (isGL2Sun)
- {
- token = COM_ParseExt( text, qfalse );
- tr.mapLightScale = atof(token);
-
- token = COM_ParseExt( text, qfalse );
- VectorScale( tr.sunLight, atof(token), tr.sunAmbient );
- }
-
- SkipRestOfLine( text );
- continue;
- }
- // tonemap parms
- else if ( !Q_stricmp( token, "q3gl2_tonemap" ) ) {
- token = COM_ParseExt( text, qfalse );
- tr.toneMinAvgMaxLevel[0] = atof( token );
- token = COM_ParseExt( text, qfalse );
- tr.toneMinAvgMaxLevel[1] = atof( token );
- token = COM_ParseExt( text, qfalse );
- tr.toneMinAvgMaxLevel[2] = atof( token );
-
- token = COM_ParseExt( text, qfalse );
- tr.autoExposureMinMax[0] = atof( token );
- token = COM_ParseExt( text, qfalse );
- tr.autoExposureMinMax[1] = atof( token );
-
- SkipRestOfLine( text );
- continue;
- }
- else if ( !Q_stricmp( token, "deformVertexes" ) ) {
- ParseDeform( text );
- continue;
- }
- else if ( !Q_stricmp( token, "tesssize" ) ) {
- SkipRestOfLine( text );
- continue;
- }
- else if ( !Q_stricmp( token, "clampTime" ) ) {
- token = COM_ParseExt( text, qfalse );
- if (token[0]) {
- shader.clampTime = atof(token);
- }
- }
- // skip stuff that only the q3map needs
- else if ( !Q_stricmpn( token, "q3map", 5 ) ) {
- SkipRestOfLine( text );
- continue;
- }
- // skip stuff that only q3map or the server needs
- else if ( !Q_stricmp( token, "surfaceParm" ) ) {
- ParseSurfaceParm( text );
- continue;
- }
- // no mip maps
- else if ( !Q_stricmp( token, "nomipmaps" ) )
- {
- shader.noMipMaps = qtrue;
- shader.noPicMip = qtrue;
- continue;
- }
- // no picmip adjustment
- else if ( !Q_stricmp( token, "nopicmip" ) )
- {
- shader.noPicMip = qtrue;
- continue;
- }
- // polygonOffset
- else if ( !Q_stricmp( token, "polygonOffset" ) )
- {
- shader.polygonOffset = qtrue;
- continue;
- }
- // entityMergable, allowing sprite surfaces from multiple entities
- // to be merged into one batch. This is a savings for smoke
- // puffs and blood, but can't be used for anything where the
- // shader calcs (not the surface function) reference the entity color or scroll
- else if ( !Q_stricmp( token, "entityMergable" ) )
- {
- shader.entityMergable = qtrue;
- continue;
- }
- // fogParms
- else if ( !Q_stricmp( token, "fogParms" ) )
- {
- if ( !ParseVector( text, 3, shader.fogParms.color ) ) {
- return qfalse;
- }
-
- token = COM_ParseExt( text, qfalse );
- if ( !token[0] )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing parm for 'fogParms' keyword in shader '%s'\n", shader.name );
- continue;
- }
- shader.fogParms.depthForOpaque = atof( token );
-
- // skip any old gradient directions
- SkipRestOfLine( text );
- continue;
- }
- // portal
- else if ( !Q_stricmp(token, "portal") )
- {
- shader.sort = SS_PORTAL;
- shader.isPortal = qtrue;
- continue;
- }
- // skyparms <cloudheight> <outerbox> <innerbox>
- else if ( !Q_stricmp( token, "skyparms" ) )
- {
- ParseSkyParms( text );
- continue;
- }
- // light <value> determines flaring in q3map, not needed here
- else if ( !Q_stricmp(token, "light") )
- {
- token = COM_ParseExt( text, qfalse );
- continue;
- }
- // cull <face>
- else if ( !Q_stricmp( token, "cull") )
- {
- token = COM_ParseExt( text, qfalse );
- if ( token[0] == 0 )
- {
- ri.Printf( PRINT_WARNING, "WARNING: missing cull parms in shader '%s'\n", shader.name );
- continue;
- }
-
- if ( !Q_stricmp( token, "none" ) || !Q_stricmp( token, "twosided" ) || !Q_stricmp( token, "disable" ) )
- {
- shader.cullType = CT_TWO_SIDED;
- }
- else if ( !Q_stricmp( token, "back" ) || !Q_stricmp( token, "backside" ) || !Q_stricmp( token, "backsided" ) )
- {
- shader.cullType = CT_BACK_SIDED;
- }
- else
- {
- ri.Printf( PRINT_WARNING, "WARNING: invalid cull parm '%s' in shader '%s'\n", token, shader.name );
- }
- continue;
- }
- // sort
- else if ( !Q_stricmp( token, "sort" ) )
- {
- ParseSort( text );
- continue;
- }
- else
- {
- ri.Printf( PRINT_WARNING, "WARNING: unknown general shader parameter '%s' in '%s'\n", token, shader.name );
- return qfalse;
- }
- }
-
- //
- // ignore shaders that don't have any stages, unless it is a sky or fog
- //
- if ( s == 0 && !shader.isSky && !(shader.contentFlags & CONTENTS_FOG ) ) {
- return qfalse;
- }
-
- shader.explicitlyDefined = qtrue;
-
- return qtrue;
-}
-
-/*
-========================================================================================
-
-SHADER OPTIMIZATION AND FOGGING
-
-========================================================================================
-*/
-
-/*
-===================
-ComputeStageIteratorFunc
-
-See if we can use on of the simple fastpath stage functions,
-otherwise set to the generic stage function
-===================
-*/
-static void ComputeStageIteratorFunc( void )
-{
- shader.optimalStageIteratorFunc = RB_StageIteratorGeneric;
-
- //
- // see if this should go into the sky path
- //
- if ( shader.isSky )
- {
- shader.optimalStageIteratorFunc = RB_StageIteratorSky;
- return;
- }
-}
-
-/*
-===================
-ComputeVertexAttribs
-
-Check which vertex attributes we only need, so we
-don't need to submit/copy all of them.
-===================
-*/
-static void ComputeVertexAttribs(void)
-{
- int i, stage;
-
- // dlights always need ATTR_NORMAL
- shader.vertexAttribs = ATTR_POSITION | ATTR_NORMAL;
-
- // portals always need normals, for SurfIsOffscreen()
- if (shader.isPortal)
- {
- shader.vertexAttribs |= ATTR_NORMAL;
- }
-
- if (shader.defaultShader)
- {
- shader.vertexAttribs |= ATTR_TEXCOORD;
- return;
- }
-
- if(shader.numDeforms)
- {
- for ( i = 0; i < shader.numDeforms; i++)
- {
- deformStage_t *ds = &shader.deforms[i];
-
- switch (ds->deformation)
- {
- case DEFORM_BULGE:
- shader.vertexAttribs |= ATTR_NORMAL | ATTR_TEXCOORD;
- break;
-
- case DEFORM_AUTOSPRITE:
- shader.vertexAttribs |= ATTR_NORMAL | ATTR_COLOR;
- break;
-
- case DEFORM_WAVE:
- case DEFORM_NORMALS:
- case DEFORM_TEXT0:
- case DEFORM_TEXT1:
- case DEFORM_TEXT2:
- case DEFORM_TEXT3:
- case DEFORM_TEXT4:
- case DEFORM_TEXT5:
- case DEFORM_TEXT6:
- case DEFORM_TEXT7:
- shader.vertexAttribs |= ATTR_NORMAL;
- break;
-
- default:
- case DEFORM_NONE:
- case DEFORM_MOVE:
- case DEFORM_PROJECTION_SHADOW:
- case DEFORM_AUTOSPRITE2:
- break;
- }
- }
- }
-
- for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ )
- {
- shaderStage_t *pStage = &stages[stage];
-
- if ( !pStage->active )
- {
- break;
- }
-
- if (pStage->glslShaderGroup == tr.lightallShader)
- {
- shader.vertexAttribs |= ATTR_NORMAL;
-
-#ifdef USE_VERT_TANGENT_SPACE
- if (pStage->glslShaderIndex & LIGHTDEF_USE_NORMALMAP)
- {
- shader.vertexAttribs |= ATTR_BITANGENT | ATTR_TANGENT;
- }
-#endif
-
- switch (pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK)
- {
- case LIGHTDEF_USE_LIGHTMAP:
- case LIGHTDEF_USE_LIGHT_VERTEX:
- shader.vertexAttribs |= ATTR_LIGHTDIRECTION;
- break;
- default:
- break;
- }
- }
-
- for (i = 0; i < NUM_TEXTURE_BUNDLES; i++)
- {
- if ( pStage->bundle[i].image[0] == 0 )
- {
- continue;
- }
-
- switch(pStage->bundle[i].tcGen)
- {
- case TCGEN_TEXTURE:
- shader.vertexAttribs |= ATTR_TEXCOORD;
- break;
- case TCGEN_LIGHTMAP:
- shader.vertexAttribs |= ATTR_LIGHTCOORD;
- break;
- case TCGEN_ENVIRONMENT_MAPPED:
- shader.vertexAttribs |= ATTR_NORMAL;
- break;
-
- default:
- break;
- }
- }
-
- switch(pStage->rgbGen)
- {
- case CGEN_EXACT_VERTEX:
- case CGEN_VERTEX:
- case CGEN_EXACT_VERTEX_LIT:
- case CGEN_VERTEX_LIT:
- case CGEN_ONE_MINUS_VERTEX:
- shader.vertexAttribs |= ATTR_COLOR;
- break;
-
- case CGEN_LIGHTING_DIFFUSE:
- shader.vertexAttribs |= ATTR_NORMAL;
- break;
-
- default:
- break;
- }
-
- switch(pStage->alphaGen)
- {
- case AGEN_LIGHTING_SPECULAR:
- case AGEN_FRESNEL:
- shader.vertexAttribs |= ATTR_NORMAL;
- break;
-
- case AGEN_VERTEX:
- case AGEN_ONE_MINUS_VERTEX:
- shader.vertexAttribs |= ATTR_COLOR;
- break;
-
- default:
- break;
- }
- }
-}
-
-typedef struct {
- int blendA;
- int blendB;
-
- int multitextureEnv;
- int multitextureBlend;
-} collapse_t;
-
-static collapse_t collapse[] = {
- { 0, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO,
- GL_MODULATE, 0 },
-
- { 0, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR,
- GL_MODULATE, 0 },
-
- { GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR,
- GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR },
-
- { GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR,
- GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR },
-
- { GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO,
- GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR },
-
- { GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO,
- GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR },
-
- { 0, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE,
- GL_ADD, 0 },
-
- { GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE,
- GL_ADD, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE },
-#if 0
- { 0, GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_SRCBLEND_SRC_ALPHA,
- GL_DECAL, 0 },
-#endif
- { -1 }
-};
-
-/*
-================
-CollapseMultitexture
-
-Attempt to combine two stages into a single multitexture stage
-FIXME: I think modulated add + modulated add collapses incorrectly
-=================
-*/
-static qboolean CollapseMultitexture( void ) {
- int abits, bbits;
- int i;
- textureBundle_t tmpBundle;
-
- if ( !qglActiveTextureARB ) {
- return qfalse;
- }
-
- // make sure both stages are active
- if ( !stages[0].active || !stages[1].active ) {
- return qfalse;
- }
-
- // on voodoo2, don't combine different tmus
- if ( glConfig.driverType == GLDRV_VOODOO ) {
- if ( stages[0].bundle[0].image[0]->TMU ==
- stages[1].bundle[0].image[0]->TMU ) {
- return qfalse;
- }
- }
-
- abits = stages[0].stateBits;
- bbits = stages[1].stateBits;
-
- // make sure that both stages have identical state other than blend modes
- if ( ( abits & ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS | GLS_DEPTHMASK_TRUE ) ) !=
- ( bbits & ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS | GLS_DEPTHMASK_TRUE ) ) ) {
- return qfalse;
- }
-
- abits &= ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
- bbits &= ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
-
- // search for a valid multitexture blend function
- for ( i = 0; collapse[i].blendA != -1 ; i++ ) {
- if ( abits == collapse[i].blendA
- && bbits == collapse[i].blendB ) {
- break;
- }
- }
-
- // nothing found
- if ( collapse[i].blendA == -1 ) {
- return qfalse;
- }
-
- // GL_ADD is a separate extension
- if ( collapse[i].multitextureEnv == GL_ADD && !glConfig.textureEnvAddAvailable ) {
- return qfalse;
- }
-
- // make sure waveforms have identical parameters
- if ( ( stages[0].rgbGen != stages[1].rgbGen ) ||
- ( stages[0].alphaGen != stages[1].alphaGen ) ) {
- return qfalse;
- }
-
- // an add collapse can only have identity colors
- if ( collapse[i].multitextureEnv == GL_ADD && stages[0].rgbGen != CGEN_IDENTITY ) {
- return qfalse;
- }
-
- if ( stages[0].rgbGen == CGEN_WAVEFORM )
- {
- if ( memcmp( &stages[0].rgbWave,
- &stages[1].rgbWave,
- sizeof( stages[0].rgbWave ) ) )
- {
- return qfalse;
- }
- }
- if ( stages[0].alphaGen == AGEN_WAVEFORM )
- {
- if ( memcmp( &stages[0].alphaWave,
- &stages[1].alphaWave,
- sizeof( stages[0].alphaWave ) ) )
- {
- return qfalse;
- }
- }
-
-
- // make sure that lightmaps are in bundle 1 for 3dfx
- if ( stages[0].bundle[0].isLightmap )
- {
- tmpBundle = stages[0].bundle[0];
- stages[0].bundle[0] = stages[1].bundle[0];
- stages[0].bundle[1] = tmpBundle;
- }
- else
- {
- stages[0].bundle[1] = stages[1].bundle[0];
- }
-
- // set the new blend state bits
- shader.multitextureEnv = collapse[i].multitextureEnv;
- stages[0].stateBits &= ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
- stages[0].stateBits |= collapse[i].multitextureBlend;
-
- //
- // move down subsequent shaders
- //
- memmove( &stages[1], &stages[2], sizeof( stages[0] ) * ( MAX_SHADER_STAGES - 2 ) );
- Com_Memset( &stages[MAX_SHADER_STAGES-1], 0, sizeof( stages[0] ) );
-
- return qtrue;
-}
-
-static void CollapseStagesToLightall(shaderStage_t *diffuse,
- shaderStage_t *normal, shaderStage_t *specular, shaderStage_t *lightmap,
- qboolean useLightVector, qboolean useLightVertex, qboolean parallax, qboolean environment)
-{
- int defs = 0;
-
- //ri.Printf(PRINT_ALL, "shader %s has diffuse %s", shader.name, diffuse->bundle[0].image[0]->imgName);
-
- // reuse diffuse, mark others inactive
- diffuse->type = ST_GLSL;
-
- if (lightmap)
- {
- //ri.Printf(PRINT_ALL, ", lightmap");
- diffuse->bundle[TB_LIGHTMAP] = lightmap->bundle[0];
- defs |= LIGHTDEF_USE_LIGHTMAP;
- }
- else if (useLightVector)
- {
- defs |= LIGHTDEF_USE_LIGHT_VECTOR;
- }
- else if (useLightVertex)
- {
- defs |= LIGHTDEF_USE_LIGHT_VERTEX;
- }
-
- if (r_deluxeMapping->integer && tr.worldDeluxeMapping && lightmap)
- {
- //ri.Printf(PRINT_ALL, ", deluxemap");
- diffuse->bundle[TB_DELUXEMAP] = lightmap->bundle[0];
- diffuse->bundle[TB_DELUXEMAP].image[0] = tr.deluxemaps[shader.lightmapIndex];
- defs |= LIGHTDEF_USE_DELUXEMAP;
- }
-
- if (r_normalMapping->integer)
- {
- image_t *diffuseImg;
- if (normal)
- {
- //ri.Printf(PRINT_ALL, ", normalmap %s", normal->bundle[0].image[0]->imgName);
- diffuse->bundle[TB_NORMALMAP] = normal->bundle[0];
- defs |= LIGHTDEF_USE_NORMALMAP;
- if (parallax && r_parallaxMapping->integer)
- defs |= LIGHTDEF_USE_PARALLAXMAP;
- }
- else if ((lightmap || useLightVector || useLightVertex) && (diffuseImg = diffuse->bundle[TB_DIFFUSEMAP].image[0]))
- {
- char normalName[MAX_QPATH];
- image_t *normalImg;
- imgFlags_t normalFlags = (diffuseImg->flags & ~(IMGFLAG_GENNORMALMAP | IMGFLAG_SRGB)) | IMGFLAG_NOLIGHTSCALE;
-
- COM_StripExtension(diffuseImg->imgName, normalName, MAX_QPATH);
- Q_strcat(normalName, MAX_QPATH, "_n");
-
- normalImg = R_FindImageFile(normalName, IMGTYPE_NORMAL, normalFlags);
-
- if (normalImg)
- {
- diffuse->bundle[TB_NORMALMAP] = diffuse->bundle[0];
- diffuse->bundle[TB_NORMALMAP].image[0] = normalImg;
-
- defs |= LIGHTDEF_USE_NORMALMAP;
- if (parallax && r_parallaxMapping->integer)
- defs |= LIGHTDEF_USE_PARALLAXMAP;
- }
- }
- }
-
- if (r_specularMapping->integer)
- {
- if (specular)
- {
- //ri.Printf(PRINT_ALL, ", specularmap %s", specular->bundle[0].image[0]->imgName);
- diffuse->bundle[TB_SPECULARMAP] = specular->bundle[0];
- diffuse->materialInfo[0] = specular->materialInfo[0];
- diffuse->materialInfo[1] = specular->materialInfo[1];
- defs |= LIGHTDEF_USE_SPECULARMAP;
- }
- }
-
- if (environment || diffuse->bundle[0].numTexMods)
- {
- defs |= LIGHTDEF_USE_TCGEN_AND_TCMOD;
- }
-
- //ri.Printf(PRINT_ALL, ".\n");
-
- diffuse->glslShaderGroup = tr.lightallShader;
- diffuse->glslShaderIndex = defs;
-}
-
-
-static qboolean CollapseStagesToGLSL(void)
-{
- int i, j, numStages;
- qboolean skip = qfalse;
-
- // skip shaders with deforms
- if (shader.numDeforms != 0)
- {
- skip = qtrue;
- }
-
- if (!skip)
- {
- // if 2+ stages and first stage is lightmap, switch them
- // this makes it easier for the later bits to process
- if (stages[0].active && stages[0].bundle[0].isLightmap && stages[1].active)
- {
- int blendBits = stages[1].stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
-
- if (blendBits == (GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO)
- || blendBits == (GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR))
- {
- int stateBits0 = stages[0].stateBits;
- int stateBits1 = stages[1].stateBits;
- shaderStage_t swapStage;
-
- swapStage = stages[0];
- stages[0] = stages[1];
- stages[1] = swapStage;
-
- stages[0].stateBits = stateBits0;
- stages[1].stateBits = stateBits1;
- }
- }
- }
-
- if (!skip)
- {
- // scan for shaders that aren't supported
- for (i = 0; i < MAX_SHADER_STAGES; i++)
- {
- shaderStage_t *pStage = &stages[i];
-
- if (!pStage->active)
- continue;
-
- if (pStage->adjustColorsForFog)
- {
- skip = qtrue;
- break;
- }
-
- if (pStage->bundle[0].isLightmap)
- {
- int blendBits = pStage->stateBits & ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
-
- if (blendBits != (GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO)
- && blendBits != (GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR))
- {
- skip = qtrue;
- break;
- }
- }
-
- switch(pStage->bundle[0].tcGen)
- {
- case TCGEN_TEXTURE:
- case TCGEN_LIGHTMAP:
- case TCGEN_ENVIRONMENT_MAPPED:
- break;
- default:
- skip = qtrue;
- break;
- }
-
- switch(pStage->alphaGen)
- {
- case AGEN_LIGHTING_SPECULAR:
- case AGEN_PORTAL:
- case AGEN_FRESNEL:
- skip = qtrue;
- break;
- default:
- break;
- }
- }
- }
-
- if (!skip)
- {
- for (i = 0; i < MAX_SHADER_STAGES; i++)
- {
- shaderStage_t *pStage = &stages[i];
- shaderStage_t *diffuse, *normal, *specular, *lightmap;
- qboolean parallax, environment, diffuselit, vertexlit;
-
- if (!pStage->active)
- continue;
-
- // skip normal and specular maps
- if (pStage->type != ST_COLORMAP)
- continue;
-
- // skip lightmaps
- if (pStage->bundle[0].isLightmap)
- continue;
-
- diffuse = pStage;
- normal = NULL;
- parallax = qfalse;
- specular = NULL;
- lightmap = NULL;
-
- // we have a diffuse map, find matching normal, specular, and lightmap
- for (j = i + 1; j < MAX_SHADER_STAGES; j++)
- {
- shaderStage_t *pStage2 = &stages[j];
-
- if (!pStage2->active)
- continue;
-
- switch(pStage2->type)
- {
- case ST_NORMALMAP:
- if (!normal)
- {
- normal = pStage2;
- }
- break;
-
- case ST_NORMALPARALLAXMAP:
- if (!normal)
- {
- normal = pStage2;
- parallax = qtrue;
- }
- break;
-
- case ST_SPECULARMAP:
- if (!specular)
- {
- specular = pStage2;
- }
- break;
-
- case ST_COLORMAP:
- if (pStage2->bundle[0].isLightmap)
- {
- lightmap = pStage2;
- }
- break;
-
- default:
- break;
- }
- }
-
- environment = qfalse;
- if (diffuse->bundle[0].tcGen == TCGEN_ENVIRONMENT_MAPPED)
- {
- environment = qtrue;
- }
-
- diffuselit = qfalse;
- if (diffuse->rgbGen == CGEN_LIGHTING_DIFFUSE)
- {
- diffuselit = qtrue;
- }
-
- vertexlit = qfalse;
- if (diffuse->rgbGen == CGEN_VERTEX_LIT || diffuse->rgbGen == CGEN_EXACT_VERTEX_LIT)
- {
- vertexlit = qtrue;
- }
-
- CollapseStagesToLightall(diffuse, normal, specular, lightmap, diffuselit, vertexlit, parallax, environment);
- }
-
- // deactivate lightmap stages
- for (i = 0; i < MAX_SHADER_STAGES; i++)
- {
- shaderStage_t *pStage = &stages[i];
-
- if (!pStage->active)
- continue;
-
- if (pStage->bundle[0].isLightmap)
- {
- pStage->active = qfalse;
- }
- }
- }
-
- // deactivate normal and specular stages
- for (i = 0; i < MAX_SHADER_STAGES; i++)
- {
- shaderStage_t *pStage = &stages[i];
-
- if (!pStage->active)
- continue;
-
- if (pStage->type == ST_NORMALMAP)
- {
- pStage->active = qfalse;
- }
-
- if (pStage->type == ST_NORMALPARALLAXMAP)
- {
- pStage->active = qfalse;
- }
-
- if (pStage->type == ST_SPECULARMAP)
- {
- pStage->active = qfalse;
- }
- }
-
- // remove inactive stages
- numStages = 0;
- for (i = 0; i < MAX_SHADER_STAGES; i++)
- {
- if (!stages[i].active)
- continue;
-
- if (i == numStages)
- {
- numStages++;
- continue;
- }
-
- stages[numStages] = stages[i];
- stages[i].active = qfalse;
- numStages++;
- }
-
- if (numStages == i && i >= 2 && CollapseMultitexture())
- numStages--;
-
- return numStages;
-}
-
-/*
-=============
-
-FixRenderCommandList
-https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=493
-Arnout: this is a nasty issue. Shaders can be registered after drawsurfaces are generated
-but before the frame is rendered. This will, for the duration of one frame, cause drawsurfaces
-to be rendered with bad shaders. To fix this, need to go through all render commands and fix
-sortedIndex.
-==============
-*/
-static void FixRenderCommandList( int newShader ) {
- renderCommandList_t *cmdList = &backEndData->commands;
-
- if( cmdList ) {
- const void *curCmd = cmdList->cmds;
-
- while ( 1 ) {
- curCmd = PADP(curCmd, sizeof(void *));
-
- switch ( *(const int *)curCmd ) {
- case RC_SET_COLOR:
- {
- const setColorCommand_t *sc_cmd = (const setColorCommand_t *)curCmd;
- curCmd = (const void *)(sc_cmd + 1);
- break;
- }
- case RC_STRETCH_PIC:
- {
- const stretchPicCommand_t *sp_cmd = (const stretchPicCommand_t *)curCmd;
- curCmd = (const void *)(sp_cmd + 1);
- break;
- }
- case RC_DRAW_SURFS:
- {
- int i;
- drawSurf_t *drawSurf;
- shader_t *shader;
- int fogNum;
- int entityNum;
- int dlightMap;
- int pshadowMap;
- int sortedIndex;
- const drawSurfsCommand_t *ds_cmd = (const drawSurfsCommand_t *)curCmd;
-
- for( i = 0, drawSurf = ds_cmd->drawSurfs; i < ds_cmd->numDrawSurfs; i++, drawSurf++ ) {
- R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlightMap, &pshadowMap );
- sortedIndex = (( drawSurf->sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1));
- if( sortedIndex >= newShader ) {
- sortedIndex++;
- drawSurf->sort = (sortedIndex << QSORT_SHADERNUM_SHIFT) | entityNum | ( fogNum << QSORT_FOGNUM_SHIFT ) | ( (int)pshadowMap << QSORT_PSHADOW_SHIFT) | (int)dlightMap;
- }
- }
- curCmd = (const void *)(ds_cmd + 1);
- break;
- }
- case RC_DRAW_BUFFER:
- {
- const drawBufferCommand_t *db_cmd = (const drawBufferCommand_t *)curCmd;
- curCmd = (const void *)(db_cmd + 1);
- break;
- }
- case RC_SWAP_BUFFERS:
- {
- const swapBuffersCommand_t *sb_cmd = (const swapBuffersCommand_t *)curCmd;
- curCmd = (const void *)(sb_cmd + 1);
- break;
- }
- case RC_END_OF_LIST:
- default:
- return;
- }
- }
- }
-}
-
-/*
-==============
-SortNewShader
-
-Positions the most recently created shader in the tr.sortedShaders[]
-array so that the shader->sort key is sorted reletive to the other
-shaders.
-
-Sets shader->sortedIndex
-==============
-*/
-static void SortNewShader( void ) {
- int i;
- float sort;
- shader_t *newShader;
-
- newShader = tr.shaders[ tr.numShaders - 1 ];
- sort = newShader->sort;
-
- for ( i = tr.numShaders - 2 ; i >= 0 ; i-- ) {
- if ( tr.sortedShaders[ i ]->sort <= sort ) {
- break;
- }
- tr.sortedShaders[i+1] = tr.sortedShaders[i];
- tr.sortedShaders[i+1]->sortedIndex++;
- }
-
- // Arnout: fix rendercommandlist
- // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=493
- FixRenderCommandList( i+1 );
-
- newShader->sortedIndex = i+1;
- tr.sortedShaders[i+1] = newShader;
-}
-
-
-/*
-====================
-GeneratePermanentShader
-====================
-*/
-static shader_t *GeneratePermanentShader( void ) {
- shader_t *newShader;
- int i, b;
- int size, hash;
-
- if ( tr.numShaders == MAX_SHADERS ) {
- ri.Printf( PRINT_WARNING, "WARNING: GeneratePermanentShader - MAX_SHADERS hit\n");
- return tr.defaultShader;
- }
-
- newShader = ri.Hunk_Alloc( sizeof( shader_t ), h_low );
-
- *newShader = shader;
-
- if ( shader.sort <= SS_OPAQUE ) {
- newShader->fogPass = FP_EQUAL;
- } else if ( shader.contentFlags & CONTENTS_FOG ) {
- newShader->fogPass = FP_LE;
- }
-
- tr.shaders[ tr.numShaders ] = newShader;
- newShader->index = tr.numShaders;
-
- tr.sortedShaders[ tr.numShaders ] = newShader;
- newShader->sortedIndex = tr.numShaders;
-
- tr.numShaders++;
-
- for ( i = 0 ; i < newShader->numUnfoggedPasses ; i++ ) {
- if ( !stages[i].active ) {
- break;
- }
- newShader->stages[i] = ri.Hunk_Alloc( sizeof( stages[i] ), h_low );
- *newShader->stages[i] = stages[i];
-
- for ( b = 0 ; b < NUM_TEXTURE_BUNDLES ; b++ ) {
- size = newShader->stages[i]->bundle[b].numTexMods * sizeof( texModInfo_t );
- newShader->stages[i]->bundle[b].texMods = ri.Hunk_Alloc( size, h_low );
- Com_Memcpy( newShader->stages[i]->bundle[b].texMods, stages[i].bundle[b].texMods, size );
- }
- }
-
- SortNewShader();
-
- hash = generateHashValue(newShader->name, FILE_HASH_SIZE);
- newShader->next = hashTable[hash];
- hashTable[hash] = newShader;
-
- return newShader;
-}
-
-/*
-=================
-VertexLightingCollapse
-
-If vertex lighting is enabled, only render a single
-pass, trying to guess which is the correct one to best aproximate
-what it is supposed to look like.
-=================
-*/
-static void VertexLightingCollapse( void ) {
- int stage;
- shaderStage_t *bestStage;
- int bestImageRank;
- int rank;
-
- // if we aren't opaque, just use the first pass
- if ( shader.sort == SS_OPAQUE ) {
-
- // pick the best texture for the single pass
- bestStage = &stages[0];
- bestImageRank = -999999;
-
- for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) {
- shaderStage_t *pStage = &stages[stage];
-
- if ( !pStage->active ) {
- break;
- }
- rank = 0;
-
- if ( pStage->bundle[0].isLightmap ) {
- rank -= 100;
- }
- if ( pStage->bundle[0].tcGen != TCGEN_TEXTURE ) {
- rank -= 5;
- }
- if ( pStage->bundle[0].numTexMods ) {
- rank -= 5;
- }
- if ( pStage->rgbGen != CGEN_IDENTITY && pStage->rgbGen != CGEN_IDENTITY_LIGHTING ) {
- rank -= 3;
- }
-
- if ( rank > bestImageRank ) {
- bestImageRank = rank;
- bestStage = pStage;
- }
- }
-
- stages[0].bundle[0] = bestStage->bundle[0];
- stages[0].stateBits &= ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS );
- stages[0].stateBits |= GLS_DEPTHMASK_TRUE;
- if ( shader.lightmapIndex == LIGHTMAP_NONE ) {
- stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE;
- } else {
- stages[0].rgbGen = CGEN_EXACT_VERTEX;
- }
- stages[0].alphaGen = AGEN_SKIP;
- } else {
- // don't use a lightmap (tesla coils)
- if ( stages[0].bundle[0].isLightmap ) {
- stages[0] = stages[1];
- }
-
- // if we were in a cross-fade cgen, hack it to normal
- if ( stages[0].rgbGen == CGEN_ONE_MINUS_ENTITY || stages[1].rgbGen == CGEN_ONE_MINUS_ENTITY ) {
- stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
- }
- if ( ( stages[0].rgbGen == CGEN_WAVEFORM && stages[0].rgbWave.func == GF_SAWTOOTH )
- && ( stages[1].rgbGen == CGEN_WAVEFORM && stages[1].rgbWave.func == GF_INVERSE_SAWTOOTH ) ) {
- stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
- }
- if ( ( stages[0].rgbGen == CGEN_WAVEFORM && stages[0].rgbWave.func == GF_INVERSE_SAWTOOTH )
- && ( stages[1].rgbGen == CGEN_WAVEFORM && stages[1].rgbWave.func == GF_SAWTOOTH ) ) {
- stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
- }
- }
-
- for ( stage = 1; stage < MAX_SHADER_STAGES; stage++ ) {
- shaderStage_t *pStage = &stages[stage];
-
- if ( !pStage->active ) {
- break;
- }
-
- Com_Memset( pStage, 0, sizeof( *pStage ) );
- }
-}
-
-/*
-=========================
-FinishShader
-
-Returns a freshly allocated shader with all the needed info
-from the current global working shader
-=========================
-*/
-static shader_t *FinishShader( void ) {
- int stage;
- qboolean hasLightmapStage;
- qboolean vertexLightmap;
-
- hasLightmapStage = qfalse;
- vertexLightmap = qfalse;
-
- //
- // set sky stuff appropriate
- //
- if ( shader.isSky ) {
- shader.sort = SS_ENVIRONMENT;
- }
-
- //
- // set polygon offset
- //
- if ( shader.polygonOffset && !shader.sort ) {
- shader.sort = SS_DECAL;
- }
-
- //
- // set appropriate stage information
- //
- for ( stage = 0; stage < MAX_SHADER_STAGES; ) {
- shaderStage_t *pStage = &stages[stage];
-
- if ( !pStage->active ) {
- break;
- }
-
- // check for a missing texture
- if ( !pStage->bundle[0].image[0] ) {
- ri.Printf( PRINT_WARNING, "Shader %s has a stage with no image\n", shader.name );
- pStage->active = qfalse;
- stage++;
- continue;
- }
-
- //
- // ditch this stage if it's detail and detail textures are disabled
- //
- if ( pStage->isDetail && !r_detailTextures->integer )
- {
- int index;
-
- for(index = stage + 1; index < MAX_SHADER_STAGES; index++)
- {
- if(!stages[index].active)
- break;
- }
-
- if(index < MAX_SHADER_STAGES)
- memmove(pStage, pStage + 1, sizeof(*pStage) * (index - stage));
- else
- {
- if(stage + 1 < MAX_SHADER_STAGES)
- memmove(pStage, pStage + 1, sizeof(*pStage) * (index - stage - 1));
-
- Com_Memset(&stages[index - 1], 0, sizeof(*stages));
- }
-
- continue;
- }
-
- //
- // default texture coordinate generation
- //
- if ( pStage->bundle[0].isLightmap ) {
- if ( pStage->bundle[0].tcGen == TCGEN_BAD ) {
- pStage->bundle[0].tcGen = TCGEN_LIGHTMAP;
- }
- hasLightmapStage = qtrue;
- } else {
- if ( pStage->bundle[0].tcGen == TCGEN_BAD ) {
- pStage->bundle[0].tcGen = TCGEN_TEXTURE;
- }
- }
-
-
- // not a true lightmap but we want to leave existing
- // behaviour in place and not print out a warning
- //if (pStage->rgbGen == CGEN_VERTEX) {
- // vertexLightmap = qtrue;
- //}
-
-
-
- //
- // determine sort order and fog color adjustment
- //
- if ( ( pStage->stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) &&
- ( stages[0].stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) ) {
- int blendSrcBits = pStage->stateBits & GLS_SRCBLEND_BITS;
- int blendDstBits = pStage->stateBits & GLS_DSTBLEND_BITS;
-
- // fog color adjustment only works for blend modes that have a contribution
- // that aproaches 0 as the modulate values aproach 0 --
- // GL_ONE, GL_ONE
- // GL_ZERO, GL_ONE_MINUS_SRC_COLOR
- // GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
-
- // modulate, additive
- if ( ( ( blendSrcBits == GLS_SRCBLEND_ONE ) && ( blendDstBits == GLS_DSTBLEND_ONE ) ) ||
- ( ( blendSrcBits == GLS_SRCBLEND_ZERO ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR ) ) ) {
- pStage->adjustColorsForFog = ACFF_MODULATE_RGB;
- }
- // strict blend
- else if ( ( blendSrcBits == GLS_SRCBLEND_SRC_ALPHA ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) )
- {
- pStage->adjustColorsForFog = ACFF_MODULATE_ALPHA;
- }
- // premultiplied alpha
- else if ( ( blendSrcBits == GLS_SRCBLEND_ONE ) && ( blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ) )
- {
- pStage->adjustColorsForFog = ACFF_MODULATE_RGBA;
- } else {
- // we can't adjust this one correctly, so it won't be exactly correct in fog
- }
-
- // don't screw with sort order if this is a portal or environment
- if ( !shader.sort ) {
- // see through item, like a grill or grate
- if ( pStage->stateBits & GLS_DEPTHMASK_TRUE ) {
- shader.sort = SS_SEE_THROUGH;
- } else {
- shader.sort = SS_BLEND0;
- }
- }
- }
-
- stage++;
- }
-
- // there are times when you will need to manually apply a sort to
- // opaque alpha tested shaders that have later blend passes
- if ( !shader.sort ) {
- shader.sort = SS_OPAQUE;
- }
-
- //
- // if we are in r_vertexLight mode, never use a lightmap texture
- //
- if ( stage > 1 && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) ) {
- VertexLightingCollapse();
- stage = 1;
- hasLightmapStage = qfalse;
- }
-
- //
- // look for multitexture potential
- //
- stage = CollapseStagesToGLSL();
-
- if ( shader.lightmapIndex >= 0 && !hasLightmapStage ) {
- if (vertexLightmap) {
- ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has VERTEX forced lightmap!\n", shader.name );
- } else {
- ri.Printf( PRINT_DEVELOPER, "WARNING: shader '%s' has lightmap but no lightmap stage!\n", shader.name );
- // Don't set this, it will just add duplicate shaders to the hash
- //shader.lightmapIndex = LIGHTMAP_NONE;
- }
- }
-
-
- //
- // compute number of passes
- //
- shader.numUnfoggedPasses = stage;
-
- // fogonly shaders don't have any normal passes
- if (stage == 0 && !shader.isSky)
- shader.sort = SS_FOG;
-
- // determine which stage iterator function is appropriate
- ComputeStageIteratorFunc();
-
- // determine which vertex attributes this shader needs
- ComputeVertexAttribs();
-
- return GeneratePermanentShader();
-}
-
-//========================================================================================
-
-/*
-====================
-FindShaderInShaderText
-
-Scans the combined text description of all the shader files for
-the given shader name.
-
-return NULL if not found
-
-If found, it will return a valid shader
-=====================
-*/
-static char *FindShaderInShaderText( const char *shadername ) {
-
- char *token, *p;
-
- int i, hash;
-
- hash = generateHashValue(shadername, MAX_SHADERTEXT_HASH);
-
- if(shaderTextHashTable[hash])
- {
- for (i = 0; shaderTextHashTable[hash][i]; i++)
- {
- p = shaderTextHashTable[hash][i];
- token = COM_ParseExt(&p, qtrue);
-
- if(!Q_stricmp(token, shadername))
- return p;
- }
- }
-
- p = s_shaderText;
-
- if ( !p ) {
- return NULL;
- }
-
- // look for label
- while ( 1 ) {
- token = COM_ParseExt( &p, qtrue );
- if ( token[0] == 0 ) {
- break;
- }
-
- if ( !Q_stricmp( token, shadername ) ) {
- return p;
- }
- else {
- // skip the definition
- SkipBracedSection( &p );
- }
- }
-
- return NULL;
-}
-
-
-/*
-==================
-R_FindShaderByName
-
-Will always return a valid shader, but it might be the
-default shader if the real one can't be found.
-==================
-*/
-shader_t *R_FindShaderByName( const char *name ) {
- char strippedName[MAX_QPATH];
- int hash;
- shader_t *sh;
-
- if ( (name==NULL) || (name[0] == 0) ) {
- return tr.defaultShader;
- }
-
- COM_StripExtension(name, strippedName, sizeof(strippedName));
-
- hash = generateHashValue(strippedName, FILE_HASH_SIZE);
-
- //
- // see if the shader is already loaded
- //
- for (sh=hashTable[hash]; sh; sh=sh->next) {
- // NOTE: if there was no shader or image available with the name strippedName
- // then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we
- // have to check all default shaders otherwise for every call to R_FindShader
- // with that same strippedName a new default shader is created.
- if (Q_stricmp(sh->name, strippedName) == 0) {
- // match found
- return sh;
- }
- }
-
- return tr.defaultShader;
-}
-
-
-/*
-===============
-R_FindShader
-
-Will always return a valid shader, but it might be the
-default shader if the real one can't be found.
-
-In the interest of not requiring an explicit shader text entry to
-be defined for every single image used in the game, three default
-shader behaviors can be auto-created for any image:
-
-If lightmapIndex == LIGHTMAP_NONE, then the image will have
-dynamic diffuse lighting applied to it, as apropriate for most
-entity skin surfaces.
-
-If lightmapIndex == LIGHTMAP_2D, then the image will be used
-for 2D rendering unless an explicit shader is found
-
-If lightmapIndex == LIGHTMAP_BY_VERTEX, then the image will use
-the vertex rgba modulate values, as apropriate for misc_model
-pre-lit surfaces.
-
-Other lightmapIndex values will have a lightmap stage created
-and src*dest blending applied with the texture, as apropriate for
-most world construction surfaces.
-
-===============
-*/
-shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage ) {
- char strippedName[MAX_QPATH];
- int i, hash;
- char *shaderText;
- image_t *image;
- shader_t *sh;
-
- if ( name[0] == 0 ) {
- return tr.defaultShader;
- }
-
- // use (fullbright) vertex lighting if the bsp file doesn't have
- // lightmaps
- if ( lightmapIndex >= 0 && lightmapIndex >= tr.numLightmaps ) {
- lightmapIndex = LIGHTMAP_BY_VERTEX;
- } else if ( lightmapIndex < LIGHTMAP_2D ) {
- // negative lightmap indexes cause stray pointers (think tr.lightmaps[lightmapIndex])
- ri.Printf( PRINT_WARNING, "WARNING: shader '%s' has invalid lightmap index of %d\n", name, lightmapIndex );
- lightmapIndex = LIGHTMAP_BY_VERTEX;
- }
-
- COM_StripExtension(name, strippedName, sizeof(strippedName));
-
- hash = generateHashValue(strippedName, FILE_HASH_SIZE);
-
- //
- // see if the shader is already loaded
- //
- for (sh = hashTable[hash]; sh; sh = sh->next) {
- // NOTE: if there was no shader or image available with the name strippedName
- // then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we
- // have to check all default shaders otherwise for every call to R_FindShader
- // with that same strippedName a new default shader is created.
- if ( (sh->lightmapIndex == lightmapIndex || sh->defaultShader) &&
- !Q_stricmp(sh->name, strippedName)) {
- // match found
- return sh;
- }
- }
-
- // clear the global shader
- Com_Memset( &shader, 0, sizeof( shader ) );
- Com_Memset( &stages, 0, sizeof( stages ) );
- Q_strncpyz(shader.name, strippedName, sizeof(shader.name));
- shader.lightmapIndex = lightmapIndex;
- for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) {
- stages[i].bundle[0].texMods = texMods[i];
- }
-
- //
- // attempt to define shader from an explicit parameter file
- //
- shaderText = FindShaderInShaderText( strippedName );
- if ( shaderText ) {
- // enable this when building a pak file to get a global list
- // of all explicit shaders
- if ( r_printShaders->integer ) {
- ri.Printf( PRINT_ALL, "*SHADER* %s\n", name );
- }
-
- if ( !ParseShader( &shaderText ) ) {
- // had errors, so use default shader
- shader.defaultShader = qtrue;
- }
- sh = FinishShader();
- return sh;
- }
-
-
- //
- // if not defined in the in-memory shader descriptions,
- // look for a single supported image file
- //
- {
- imgFlags_t flags;
-
- flags = IMGFLAG_NONE;
-
- if (r_srgb->integer)
- flags |= IMGFLAG_SRGB;
-
- if (mipRawImage)
- {
- flags |= IMGFLAG_MIPMAP | IMGFLAG_PICMIP;
-
- if (r_genNormalMaps->integer)
- flags |= IMGFLAG_GENNORMALMAP;
- }
- else
- {
- flags |= IMGFLAG_CLAMPTOEDGE;
- }
-
- image = R_FindImageFile( name, IMGTYPE_COLORALPHA, flags );
- if ( !image ) {
- ri.Printf( PRINT_DEVELOPER, "Couldn't find image file for shader %s\n", name );
- shader.defaultShader = qtrue;
- return FinishShader();
- }
- }
-
- //
- // create the default shading commands
- //
- if ( shader.lightmapIndex == LIGHTMAP_NONE ) {
- // dynamic colors at vertexes
- stages[0].bundle[0].image[0] = image;
- stages[0].active = qtrue;
- stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE;
- stages[0].stateBits = GLS_DEFAULT;
- } else if ( shader.lightmapIndex == LIGHTMAP_BY_VERTEX ) {
- // explicit colors at vertexes
- stages[0].bundle[0].image[0] = image;
- stages[0].active = qtrue;
- stages[0].rgbGen = CGEN_EXACT_VERTEX;
- stages[0].alphaGen = AGEN_SKIP;
- stages[0].stateBits = GLS_DEFAULT;
- } else if ( shader.lightmapIndex == LIGHTMAP_2D ) {
- // GUI elements
- stages[0].bundle[0].image[0] = image;
- stages[0].active = qtrue;
- stages[0].rgbGen = CGEN_VERTEX;
- stages[0].alphaGen = AGEN_VERTEX;
- stages[0].stateBits = GLS_DEPTHTEST_DISABLE |
- GLS_SRCBLEND_SRC_ALPHA |
- GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
- } else if ( shader.lightmapIndex == LIGHTMAP_WHITEIMAGE ) {
- // fullbright level
- stages[0].bundle[0].image[0] = tr.whiteImage;
- stages[0].active = qtrue;
- stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
- stages[0].stateBits = GLS_DEFAULT;
-
- stages[1].bundle[0].image[0] = image;
- stages[1].active = qtrue;
- stages[1].rgbGen = CGEN_IDENTITY;
- stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
- } else {
- // two pass lightmap
- stages[0].bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex];
- stages[0].bundle[0].isLightmap = qtrue;
- stages[0].active = qtrue;
- stages[0].rgbGen = CGEN_IDENTITY; // lightmaps are scaled on creation
- // for identitylight
- stages[0].stateBits = GLS_DEFAULT;
-
- stages[1].bundle[0].image[0] = image;
- stages[1].active = qtrue;
- stages[1].rgbGen = CGEN_IDENTITY;
- stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
- }
-
- return FinishShader();
-}
-
-
-qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage) {
- int i, hash;
- shader_t *sh;
-
- hash = generateHashValue(name, FILE_HASH_SIZE);
-
- // probably not necessary since this function
- // only gets called from tr_font.c with lightmapIndex == LIGHTMAP_2D
- // but better safe than sorry.
- if ( lightmapIndex >= tr.numLightmaps ) {
- lightmapIndex = LIGHTMAP_WHITEIMAGE;
- }
-
- //
- // see if the shader is already loaded
- //
- for (sh=hashTable[hash]; sh; sh=sh->next) {
- // NOTE: if there was no shader or image available with the name strippedName
- // then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we
- // have to check all default shaders otherwise for every call to R_FindShader
- // with that same strippedName a new default shader is created.
- if ( (sh->lightmapIndex == lightmapIndex || sh->defaultShader) &&
- // index by name
- !Q_stricmp(sh->name, name)) {
- // match found
- return sh->index;
- }
- }
-
- // clear the global shader
- Com_Memset( &shader, 0, sizeof( shader ) );
- Com_Memset( &stages, 0, sizeof( stages ) );
- Q_strncpyz(shader.name, name, sizeof(shader.name));
- shader.lightmapIndex = lightmapIndex;
- for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) {
- stages[i].bundle[0].texMods = texMods[i];
- }
-
- //
- // create the default shading commands
- //
- if ( shader.lightmapIndex == LIGHTMAP_NONE ) {
- // dynamic colors at vertexes
- stages[0].bundle[0].image[0] = image;
- stages[0].active = qtrue;
- stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE;
- stages[0].stateBits = GLS_DEFAULT;
- } else if ( shader.lightmapIndex == LIGHTMAP_BY_VERTEX ) {
- // explicit colors at vertexes
- stages[0].bundle[0].image[0] = image;
- stages[0].active = qtrue;
- stages[0].rgbGen = CGEN_EXACT_VERTEX;
- stages[0].alphaGen = AGEN_SKIP;
- stages[0].stateBits = GLS_DEFAULT;
- } else if ( shader.lightmapIndex == LIGHTMAP_2D ) {
- // GUI elements
- stages[0].bundle[0].image[0] = image;
- stages[0].active = qtrue;
- stages[0].rgbGen = CGEN_VERTEX;
- stages[0].alphaGen = AGEN_VERTEX;
- stages[0].stateBits = GLS_DEPTHTEST_DISABLE |
- GLS_SRCBLEND_SRC_ALPHA |
- GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA;
- } else if ( shader.lightmapIndex == LIGHTMAP_WHITEIMAGE ) {
- // fullbright level
- stages[0].bundle[0].image[0] = tr.whiteImage;
- stages[0].active = qtrue;
- stages[0].rgbGen = CGEN_IDENTITY_LIGHTING;
- stages[0].stateBits = GLS_DEFAULT;
-
- stages[1].bundle[0].image[0] = image;
- stages[1].active = qtrue;
- stages[1].rgbGen = CGEN_IDENTITY;
- stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
- } else {
- // two pass lightmap
- stages[0].bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex];
- stages[0].bundle[0].isLightmap = qtrue;
- stages[0].active = qtrue;
- stages[0].rgbGen = CGEN_IDENTITY; // lightmaps are scaled on creation
- // for identitylight
- stages[0].stateBits = GLS_DEFAULT;
-
- stages[1].bundle[0].image[0] = image;
- stages[1].active = qtrue;
- stages[1].rgbGen = CGEN_IDENTITY;
- stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO;
- }
-
- sh = FinishShader();
- return sh->index;
-}
-
-
-/*
-====================
-RE_RegisterShader
-
-This is the exported shader entry point for the rest of the system
-It will always return an index that will be valid.
-
-This should really only be used for explicit shaders, because there is no
-way to ask for different implicit lighting modes (vertex, lightmap, etc)
-====================
-*/
-qhandle_t RE_RegisterShaderLightMap( const char *name, int lightmapIndex ) {
- shader_t *sh;
-
- if ( strlen( name ) >= MAX_QPATH ) {
- ri.Printf( PRINT_ALL, "Shader name exceeds MAX_QPATH\n" );
- return 0;
- }
-
- sh = R_FindShader( name, lightmapIndex, qtrue );
-
- // we want to return 0 if the shader failed to
- // load for some reason, but R_FindShader should
- // still keep a name allocated for it, so if
- // something calls RE_RegisterShader again with
- // the same name, we don't try looking for it again
- if ( sh->defaultShader ) {
- return 0;
- }
-
- return sh->index;
-}
-
-
-/*
-====================
-RE_RegisterShader
-
-This is the exported shader entry point for the rest of the system
-It will always return an index that will be valid.
-
-This should really only be used for explicit shaders, because there is no
-way to ask for different implicit lighting modes (vertex, lightmap, etc)
-====================
-*/
-qhandle_t RE_RegisterShader( const char *name ) {
- shader_t *sh;
-
- if ( strlen( name ) >= MAX_QPATH ) {
- ri.Printf( PRINT_ALL, "Shader name exceeds MAX_QPATH\n" );
- return 0;
- }
-
- sh = R_FindShader( name, LIGHTMAP_2D, qtrue );
-
- // we want to return 0 if the shader failed to
- // load for some reason, but R_FindShader should
- // still keep a name allocated for it, so if
- // something calls RE_RegisterShader again with
- // the same name, we don't try looking for it again
- if ( sh->defaultShader ) {
- return 0;
- }
-
- return sh->index;
-}
-
-
-/*
-====================
-RE_RegisterShaderNoMip
-
-For menu graphics that should never be picmiped
-====================
-*/
-qhandle_t RE_RegisterShaderNoMip( const char *name ) {
- shader_t *sh;
-
- if ( strlen( name ) >= MAX_QPATH ) {
- ri.Printf( PRINT_ALL, "Shader name exceeds MAX_QPATH\n" );
- return 0;
- }
-
- sh = R_FindShader( name, LIGHTMAP_2D, qfalse );
-
- // we want to return 0 if the shader failed to
- // load for some reason, but R_FindShader should
- // still keep a name allocated for it, so if
- // something calls RE_RegisterShader again with
- // the same name, we don't try looking for it again
- if ( sh->defaultShader ) {
- return 0;
- }
-
- return sh->index;
-}
-
-/*
-====================
-R_GetShaderByHandle
-
-When a handle is passed in by another module, this range checks
-it and returns a valid (possibly default) shader_t to be used internally.
-====================
-*/
-shader_t *R_GetShaderByHandle( qhandle_t hShader ) {
- if ( hShader < 0 ) {
- ri.Printf( PRINT_WARNING, "R_GetShaderByHandle: out of range hShader '%d'\n", hShader );
- return tr.defaultShader;
- }
- if ( hShader >= tr.numShaders ) {
- ri.Printf( PRINT_WARNING, "R_GetShaderByHandle: out of range hShader '%d'\n", hShader );
- return tr.defaultShader;
- }
- return tr.shaders[hShader];
-}
-
-/*
-===============
-R_ShaderList_f
-
-Dump information on all valid shaders to the console
-A second parameter will cause it to print in sorted order
-===============
-*/
-void R_ShaderList_f (void) {
- int i;
- int count;
- shader_t *shader;
-
- ri.Printf (PRINT_ALL, "-----------------------\n");
-
- count = 0;
- for ( i = 0 ; i < tr.numShaders ; i++ ) {
- if ( ri.Cmd_Argc() > 1 ) {
- shader = tr.sortedShaders[i];
- } else {
- shader = tr.shaders[i];
- }
-
- ri.Printf( PRINT_ALL, "%i ", shader->numUnfoggedPasses );
-
- if (shader->lightmapIndex >= 0 ) {
- ri.Printf (PRINT_ALL, "L ");
- } else {
- ri.Printf (PRINT_ALL, " ");
- }
- if ( shader->multitextureEnv == GL_ADD ) {
- ri.Printf( PRINT_ALL, "MT(a) " );
- } else if ( shader->multitextureEnv == GL_MODULATE ) {
- ri.Printf( PRINT_ALL, "MT(m) " );
- } else if ( shader->multitextureEnv == GL_DECAL ) {
- ri.Printf( PRINT_ALL, "MT(d) " );
- } else {
- ri.Printf( PRINT_ALL, " " );
- }
- if ( shader->explicitlyDefined ) {
- ri.Printf( PRINT_ALL, "E " );
- } else {
- ri.Printf( PRINT_ALL, " " );
- }
-
- if ( shader->optimalStageIteratorFunc == RB_StageIteratorGeneric ) {
- ri.Printf( PRINT_ALL, "gen " );
- } else if ( shader->optimalStageIteratorFunc == RB_StageIteratorSky ) {
- ri.Printf( PRINT_ALL, "sky " );
- } else {
- ri.Printf( PRINT_ALL, " " );
- }
-
- if ( shader->defaultShader ) {
- ri.Printf (PRINT_ALL, ": %s (DEFAULTED)\n", shader->name);
- } else {
- ri.Printf (PRINT_ALL, ": %s\n", shader->name);
- }
- count++;
- }
- ri.Printf (PRINT_ALL, "%i total shaders\n", count);
- ri.Printf (PRINT_ALL, "------------------\n");
-}
-
-/*
-====================
-ScanAndLoadShaderFiles
-
-Finds and loads all .shader files, combining them into
-a single large text block that can be scanned for shader names
-=====================
-*/
-#define MAX_SHADER_FILES 4096
-static void ScanAndLoadShaderFiles( void )
-{
- char **shaderFiles;
- char *buffers[MAX_SHADER_FILES];
- char *p;
- int numShaderFiles;
- int i;
- char *oldp, *token, *hashMem, *textEnd;
- int shaderTextHashTableSizes[MAX_SHADERTEXT_HASH], hash, size;
-
- long sum = 0, summand;
- // scan for shader files
- shaderFiles = ri.FS_ListFiles( "scripts", ".shader", &numShaderFiles );
-
- if ( !shaderFiles || !numShaderFiles )
- {
- ri.Printf( PRINT_WARNING, "WARNING: no shader files found\n" );
- return;
- }
-
- if ( numShaderFiles > MAX_SHADER_FILES ) {
- numShaderFiles = MAX_SHADER_FILES;
- }
-
- // load and parse shader files
- for ( i = 0; i < numShaderFiles; i++ )
- {
- char filename[MAX_QPATH];
-
- // look for a .mtr file first
- {
- char *ext;
- Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFiles[i] );
- if ( (ext = strrchr(filename, '.')) )
- {
- strcpy(ext, ".mtr");
- }
-
- if ( ri.FS_ReadFile( filename, NULL ) <= 0 )
- {
- Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFiles[i] );
- }
- }
-
- ri.Printf( PRINT_DEVELOPER, "...loading '%s'\n", filename );
- summand = ri.FS_ReadFile( filename, (void **)&buffers[i] );
-
- if ( !buffers[i] )
- ri.Error( ERR_DROP, "Couldn't load %s", filename );
-
- // Do a simple check on the shader structure in that file to make sure one bad shader file cannot fuck up all other shaders.
- p = buffers[i];
- while(1)
- {
- token = COM_ParseExt(&p, qtrue);
-
- if(!*token)
- break;
-
- oldp = p;
-
- token = COM_ParseExt(&p, qtrue);
- if(token[0] != '{' && token[1] != '\0')
- {
- ri.Printf(PRINT_WARNING, "WARNING: Bad shader file %s has incorrect syntax.\n", filename);
- ri.FS_FreeFile(buffers[i]);
- buffers[i] = NULL;
- break;
- }
-
- SkipBracedSection(&oldp);
- p = oldp;
- }
-
-
- if (buffers[i])
- sum += summand;
- }
-
- // build single large buffer
- s_shaderText = ri.Hunk_Alloc( sum + numShaderFiles*2, h_low );
- s_shaderText[ 0 ] = '\0';
- textEnd = s_shaderText;
-
- // free in reverse order, so the temp files are all dumped
- for ( i = numShaderFiles - 1; i >= 0 ; i-- )
- {
- if ( !buffers[i] )
- continue;
-
- strcat( textEnd, buffers[i] );
- strcat( textEnd, "\n" );
- textEnd += strlen( textEnd );
- ri.FS_FreeFile( buffers[i] );
- }
-
- COM_Compress( s_shaderText );
-
- // free up memory
- ri.FS_FreeFileList( shaderFiles );
-
- Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes));
- size = 0;
-
- p = s_shaderText;
- // look for shader names
- while ( 1 ) {
- token = COM_ParseExt( &p, qtrue );
- if ( token[0] == 0 ) {
- break;
- }
-
- hash = generateHashValue(token, MAX_SHADERTEXT_HASH);
- shaderTextHashTableSizes[hash]++;
- size++;
- SkipBracedSection(&p);
- }
-
- size += MAX_SHADERTEXT_HASH;
-
- hashMem = ri.Hunk_Alloc( size * sizeof(char *), h_low );
-
- for (i = 0; i < MAX_SHADERTEXT_HASH; i++) {
- shaderTextHashTable[i] = (char **) hashMem;
- hashMem = ((char *) hashMem) + ((shaderTextHashTableSizes[i] + 1) * sizeof(char *));
- }
-
- Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes));
-
- p = s_shaderText;
- // look for shader names
- while ( 1 ) {
- oldp = p;
- token = COM_ParseExt( &p, qtrue );
- if ( token[0] == 0 ) {
- break;
- }
-
- hash = generateHashValue(token, MAX_SHADERTEXT_HASH);
- shaderTextHashTable[hash][shaderTextHashTableSizes[hash]++] = oldp;
-
- SkipBracedSection(&p);
- }
-
- return;
-
-}
-
-
-/*
-====================
-CreateInternalShaders
-====================
-*/
-static void CreateInternalShaders( void ) {
- tr.numShaders = 0;
-
- // init the default shader
- Com_Memset( &shader, 0, sizeof( shader ) );
- Com_Memset( &stages, 0, sizeof( stages ) );
-
- Q_strncpyz( shader.name, "<default>", sizeof( shader.name ) );
-
- shader.lightmapIndex = LIGHTMAP_NONE;
- stages[0].bundle[0].image[0] = tr.defaultImage;
- stages[0].active = qtrue;
- stages[0].stateBits = GLS_DEFAULT;
- tr.defaultShader = FinishShader();
-
- // shadow shader is just a marker
- Q_strncpyz( shader.name, "<stencil shadow>", sizeof( shader.name ) );
- shader.sort = SS_STENCIL_SHADOW;
- tr.shadowShader = FinishShader();
-}
-
-static void CreateExternalShaders( void ) {
- tr.projectionShadowShader = R_FindShader( "projectionShadow", LIGHTMAP_NONE, qtrue );
- tr.flareShader = R_FindShader( "flareShader", LIGHTMAP_NONE, qtrue );
-
- // Hack to make fogging work correctly on flares. Fog colors are calculated
- // in tr_flare.c already.
- if(!tr.flareShader->defaultShader)
- {
- int index;
-
- for(index = 0; index < tr.flareShader->numUnfoggedPasses; index++)
- {
- tr.flareShader->stages[index]->adjustColorsForFog = ACFF_NONE;
- tr.flareShader->stages[index]->stateBits |= GLS_DEPTHTEST_DISABLE;
- }
- }
-
- tr.sunShader = R_FindShader( "sun", LIGHTMAP_NONE, qtrue );
-
- tr.sunFlareShader = R_FindShader( "gfx/2d/sunflare", LIGHTMAP_NONE, qtrue);
-
- // HACK: if sunflare is missing, make one using the flare image or dlight image
- if (tr.sunFlareShader->defaultShader)
- {
- image_t *image;
-
- if (!tr.flareShader->defaultShader && tr.flareShader->stages[0] && tr.flareShader->stages[0]->bundle[0].image[0])
- image = tr.flareShader->stages[0]->bundle[0].image[0];
- else
- image = tr.dlightImage;
-
- Com_Memset( &shader, 0, sizeof( shader ) );
- Com_Memset( &stages, 0, sizeof( stages ) );
-
- Q_strncpyz( shader.name, "gfx/2d/sunflare", sizeof( shader.name ) );
-
- shader.lightmapIndex = LIGHTMAP_NONE;
- stages[0].bundle[0].image[0] = image;
- stages[0].active = qtrue;
- stages[0].stateBits = GLS_DEFAULT;
- tr.sunFlareShader = FinishShader();
- }
-
-}
-
-/*
-==================
-R_InitShaders
-==================
-*/
-void R_InitShaders( void ) {
- ri.Printf( PRINT_ALL, "Initializing Shaders\n" );
-
- Com_Memset(hashTable, 0, sizeof(hashTable));
-
- CreateInternalShaders();
-
- ScanAndLoadShaderFiles();
-
- CreateExternalShaders();
-}
diff --git a/src/rend2/tr_shadows.c b/src/rend2/tr_shadows.c
deleted file mode 100644
index f412b00d..00000000
--- a/src/rend2/tr_shadows.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-#include "tr_local.h"
-
-
-/*
-
- for a projection shadow:
-
- point[x] += light vector * ( z - shadow plane )
- point[y] +=
- point[z] = shadow plane
-
- 1 0 light[x] / light[z]
-
-*/
-
-typedef struct {
- int i2;
- int facing;
-} edgeDef_t;
-
-#define MAX_EDGE_DEFS 32
-
-static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS];
-static int numEdgeDefs[SHADER_MAX_VERTEXES];
-static int facing[SHADER_MAX_INDEXES/3];
-
-void R_AddEdgeDef( int i1, int i2, int facing ) {
- int c;
-
- c = numEdgeDefs[ i1 ];
- if ( c == MAX_EDGE_DEFS ) {
- return; // overflow
- }
- edgeDefs[ i1 ][ c ].i2 = i2;
- edgeDefs[ i1 ][ c ].facing = facing;
-
- numEdgeDefs[ i1 ]++;
-}
-
-void R_RenderShadowEdges( void ) {
- int i;
-
-#if 0
- int numTris;
-
- // dumb way -- render every triangle's edges
- numTris = tess.numIndexes / 3;
-
- for ( i = 0 ; i < numTris ; i++ ) {
- int i1, i2, i3;
-
- if ( !facing[i] ) {
- continue;
- }
-
- i1 = tess.indexes[ i*3 + 0 ];
- i2 = tess.indexes[ i*3 + 1 ];
- i3 = tess.indexes[ i*3 + 2 ];
-
- qglBegin( GL_TRIANGLE_STRIP );
- qglVertex3fv( tess.xyz[ i1 ] );
- qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] );
- qglVertex3fv( tess.xyz[ i2 ] );
- qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
- qglVertex3fv( tess.xyz[ i3 ] );
- qglVertex3fv( tess.xyz[ i3 + tess.numVertexes ] );
- qglVertex3fv( tess.xyz[ i1 ] );
- qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] );
- qglEnd();
- }
-#else
- int c, c2;
- int j, k;
- int i2;
- int c_edges, c_rejected;
- int hit[2];
-
- // an edge is NOT a silhouette edge if its face doesn't face the light,
- // or if it has a reverse paired edge that also faces the light.
- // A well behaved polyhedron would have exactly two faces for each edge,
- // but lots of models have dangling edges or overfanned edges
- c_edges = 0;
- c_rejected = 0;
-
- for ( i = 0 ; i < tess.numVertexes ; i++ ) {
- c = numEdgeDefs[ i ];
- for ( j = 0 ; j < c ; j++ ) {
- if ( !edgeDefs[ i ][ j ].facing ) {
- continue;
- }
-
- hit[0] = 0;
- hit[1] = 0;
-
- i2 = edgeDefs[ i ][ j ].i2;
- c2 = numEdgeDefs[ i2 ];
- for ( k = 0 ; k < c2 ; k++ ) {
- if ( edgeDefs[ i2 ][ k ].i2 == i ) {
- hit[ edgeDefs[ i2 ][ k ].facing ]++;
- }
- }
-
- // if it doesn't share the edge with another front facing
- // triangle, it is a sil edge
- if ( hit[ 1 ] == 0 ) {
- qglBegin( GL_TRIANGLE_STRIP );
- qglVertex3fv( tess.xyz[ i ] );
- qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
- qglVertex3fv( tess.xyz[ i2 ] );
- qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
- qglEnd();
- c_edges++;
- } else {
- c_rejected++;
- }
- }
- }
-#endif
-}
-
-/*
-=================
-RB_ShadowTessEnd
-
-triangleFromEdge[ v1 ][ v2 ]
-
-
- set triangle from edge( v1, v2, tri )
- if ( facing[ triangleFromEdge[ v1 ][ v2 ] ] && !facing[ triangleFromEdge[ v2 ][ v1 ] ) {
- }
-=================
-*/
-void RB_ShadowTessEnd( void ) {
- int i;
- int numTris;
- vec3_t lightDir;
- GLboolean rgba[4];
-
- // we can only do this if we have enough space in the vertex buffers
- if ( tess.numVertexes >= SHADER_MAX_VERTEXES / 2 ) {
- return;
- }
-
- if ( glConfig.stencilBits < 4 ) {
- return;
- }
-
- VectorCopy( backEnd.currentEntity->lightDir, lightDir );
-
- // project vertexes away from light direction
- for ( i = 0 ; i < tess.numVertexes ; i++ ) {
- VectorMA( tess.xyz[i], -512, lightDir, tess.xyz[i+tess.numVertexes] );
- }
-
- // decide which triangles face the light
- Com_Memset( numEdgeDefs, 0, 4 * tess.numVertexes );
-
- numTris = tess.numIndexes / 3;
- for ( i = 0 ; i < numTris ; i++ ) {
- int i1, i2, i3;
- vec3_t d1, d2, normal;
- float *v1, *v2, *v3;
- float d;
-
- i1 = tess.indexes[ i*3 + 0 ];
- i2 = tess.indexes[ i*3 + 1 ];
- i3 = tess.indexes[ i*3 + 2 ];
-
- v1 = tess.xyz[ i1 ];
- v2 = tess.xyz[ i2 ];
- v3 = tess.xyz[ i3 ];
-
- VectorSubtract( v2, v1, d1 );
- VectorSubtract( v3, v1, d2 );
- CrossProduct( d1, d2, normal );
-
- d = DotProduct( normal, lightDir );
- if ( d > 0 ) {
- facing[ i ] = 1;
- } else {
- facing[ i ] = 0;
- }
-
- // create the edges
- R_AddEdgeDef( i1, i2, facing[ i ] );
- R_AddEdgeDef( i2, i3, facing[ i ] );
- R_AddEdgeDef( i3, i1, facing[ i ] );
- }
-
- // draw the silhouette edges
-
- GL_Bind( tr.whiteImage );
- qglEnable( GL_CULL_FACE );
- GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
- qglColor3f( 0.2f, 0.2f, 0.2f );
-
- // don't write to the color buffer
- qglGetBooleanv(GL_COLOR_WRITEMASK, rgba);
- qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
-
- qglEnable( GL_STENCIL_TEST );
- qglStencilFunc( GL_ALWAYS, 1, 255 );
-
- // mirrors have the culling order reversed
- if ( backEnd.viewParms.isMirror ) {
- qglCullFace( GL_FRONT );
- qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
-
- R_RenderShadowEdges();
-
- qglCullFace( GL_BACK );
- qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
-
- R_RenderShadowEdges();
- } else {
- qglCullFace( GL_BACK );
- qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
-
- R_RenderShadowEdges();
-
- qglCullFace( GL_FRONT );
- qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
-
- R_RenderShadowEdges();
- }
-
-
- // reenable writing to the color buffer
- qglColorMask(rgba[0], rgba[1], rgba[2], rgba[3]);
-}
-
-
-/*
-=================
-RB_ShadowFinish
-
-Darken everything that is is a shadow volume.
-We have to delay this until everything has been shadowed,
-because otherwise shadows from different body parts would
-overlap and double darken.
-=================
-*/
-void RB_ShadowFinish( void ) {
- if ( r_shadows->integer != 2 ) {
- return;
- }
- if ( glConfig.stencilBits < 4 ) {
- return;
- }
- qglEnable( GL_STENCIL_TEST );
- qglStencilFunc( GL_NOTEQUAL, 0, 255 );
-
- qglDisable (GL_CLIP_PLANE0);
- qglDisable (GL_CULL_FACE);
-
- GL_Bind( tr.whiteImage );
-
- qglLoadIdentity ();
-
- qglColor3f( 0.6f, 0.6f, 0.6f );
- GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO );
-
-// qglColor3f( 1, 0, 0 );
-// GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
-
- qglBegin( GL_QUADS );
- qglVertex3f( -100, 100, -10 );
- qglVertex3f( 100, 100, -10 );
- qglVertex3f( 100, -100, -10 );
- qglVertex3f( -100, -100, -10 );
- qglEnd ();
-
- qglColor4f(1,1,1,1);
- qglDisable( GL_STENCIL_TEST );
-}
-
-
-/*
-=================
-RB_ProjectionShadowDeform
-
-=================
-*/
-void RB_ProjectionShadowDeform( void ) {
- float *xyz;
- int i;
- float h;
- vec3_t ground;
- vec3_t light;
- float groundDist;
- float d;
- vec3_t lightDir;
-
- xyz = ( float * ) tess.xyz;
-
- ground[0] = backEnd.or.axis[0][2];
- ground[1] = backEnd.or.axis[1][2];
- ground[2] = backEnd.or.axis[2][2];
-
- groundDist = backEnd.or.origin[2] - backEnd.currentEntity->e.shadowPlane;
-
- VectorCopy( backEnd.currentEntity->lightDir, lightDir );
- d = DotProduct( lightDir, ground );
- // don't let the shadows get too long or go negative
- if ( d < 0.5 ) {
- VectorMA( lightDir, (0.5 - d), ground, lightDir );
- d = DotProduct( lightDir, ground );
- }
- d = 1.0 / d;
-
- light[0] = lightDir[0] * d;
- light[1] = lightDir[1] * d;
- light[2] = lightDir[2] * d;
-
- for ( i = 0; i < tess.numVertexes; i++, xyz += 4 ) {
- h = DotProduct( xyz, ground ) + groundDist;
-
- xyz[0] -= light[0] * h;
- xyz[1] -= light[1] * h;
- xyz[2] -= light[2] * h;
- }
-}
diff --git a/src/rend2/tr_sky.c b/src/rend2/tr_sky.c
deleted file mode 100644
index f3c24a45..00000000
--- a/src/rend2/tr_sky.c
+++ /dev/null
@@ -1,916 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_sky.c
-#include "tr_local.h"
-
-#define SKY_SUBDIVISIONS 8
-#define HALF_SKY_SUBDIVISIONS (SKY_SUBDIVISIONS/2)
-
-static float s_cloudTexCoords[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2];
-static float s_cloudTexP[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1];
-
-/*
-===================================================================================
-
-POLYGON TO BOX SIDE PROJECTION
-
-===================================================================================
-*/
-
-static vec3_t sky_clip[6] =
-{
- {1,1,0},
- {1,-1,0},
- {0,-1,1},
- {0,1,1},
- {1,0,1},
- {-1,0,1}
-};
-
-static float sky_mins[2][6], sky_maxs[2][6];
-static float sky_min, sky_max;
-
-/*
-================
-AddSkyPolygon
-================
-*/
-static void AddSkyPolygon (int nump, vec3_t vecs)
-{
- int i,j;
- vec3_t v, av;
- float s, t, dv;
- int axis;
- float *vp;
- // s = [0]/[2], t = [1]/[2]
- static int vec_to_st[6][3] =
- {
- {-2,3,1},
- {2,3,-1},
-
- {1,3,2},
- {-1,3,-2},
-
- {-2,-1,3},
- {-2,1,-3}
-
- // {-1,2,3},
- // {1,2,-3}
- };
-
- // decide which face it maps to
- VectorCopy (vec3_origin, v);
- for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
- {
- VectorAdd (vp, v, v);
- }
- av[0] = fabs(v[0]);
- av[1] = fabs(v[1]);
- av[2] = fabs(v[2]);
- if (av[0] > av[1] && av[0] > av[2])
- {
- if (v[0] < 0)
- axis = 1;
- else
- axis = 0;
- }
- else if (av[1] > av[2] && av[1] > av[0])
- {
- if (v[1] < 0)
- axis = 3;
- else
- axis = 2;
- }
- else
- {
- if (v[2] < 0)
- axis = 5;
- else
- axis = 4;
- }
-
- // project new texture coords
- for (i=0 ; i<nump ; i++, vecs+=3)
- {
- j = vec_to_st[axis][2];
- if (j > 0)
- dv = vecs[j - 1];
- else
- dv = -vecs[-j - 1];
- if (dv < 0.001)
- continue; // don't divide by zero
- j = vec_to_st[axis][0];
- if (j < 0)
- s = -vecs[-j -1] / dv;
- else
- s = vecs[j-1] / dv;
- j = vec_to_st[axis][1];
- if (j < 0)
- t = -vecs[-j -1] / dv;
- else
- t = vecs[j-1] / dv;
-
- if (s < sky_mins[0][axis])
- sky_mins[0][axis] = s;
- if (t < sky_mins[1][axis])
- sky_mins[1][axis] = t;
- if (s > sky_maxs[0][axis])
- sky_maxs[0][axis] = s;
- if (t > sky_maxs[1][axis])
- sky_maxs[1][axis] = t;
- }
-}
-
-#define ON_EPSILON 0.1f // point on plane side epsilon
-#define MAX_CLIP_VERTS 64
-/*
-================
-ClipSkyPolygon
-================
-*/
-static void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
-{
- float *norm;
- float *v;
- qboolean front, back;
- float d, e;
- float dists[MAX_CLIP_VERTS];
- int sides[MAX_CLIP_VERTS];
- vec3_t newv[2][MAX_CLIP_VERTS];
- int newc[2];
- int i, j;
-
- if (nump > MAX_CLIP_VERTS-2)
- ri.Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS");
- if (stage == 6)
- { // fully clipped, so draw it
- AddSkyPolygon (nump, vecs);
- return;
- }
-
- front = back = qfalse;
- norm = sky_clip[stage];
- for (i=0, v = vecs ; i<nump ; i++, v+=3)
- {
- d = DotProduct (v, norm);
- if (d > ON_EPSILON)
- {
- front = qtrue;
- sides[i] = SIDE_FRONT;
- }
- else if (d < -ON_EPSILON)
- {
- back = qtrue;
- sides[i] = SIDE_BACK;
- }
- else
- sides[i] = SIDE_ON;
- dists[i] = d;
- }
-
- if (!front || !back)
- { // not clipped
- ClipSkyPolygon (nump, vecs, stage+1);
- return;
- }
-
- // clip it
- sides[i] = sides[0];
- dists[i] = dists[0];
- VectorCopy (vecs, (vecs+(i*3)) );
- newc[0] = newc[1] = 0;
-
- for (i=0, v = vecs ; i<nump ; i++, v+=3)
- {
- switch (sides[i])
- {
- case SIDE_FRONT:
- VectorCopy (v, newv[0][newc[0]]);
- newc[0]++;
- break;
- case SIDE_BACK:
- VectorCopy (v, newv[1][newc[1]]);
- newc[1]++;
- break;
- case SIDE_ON:
- VectorCopy (v, newv[0][newc[0]]);
- newc[0]++;
- VectorCopy (v, newv[1][newc[1]]);
- newc[1]++;
- break;
- }
-
- if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
- continue;
-
- d = dists[i] / (dists[i] - dists[i+1]);
- for (j=0 ; j<3 ; j++)
- {
- e = v[j] + d*(v[j+3] - v[j]);
- newv[0][newc[0]][j] = e;
- newv[1][newc[1]][j] = e;
- }
- newc[0]++;
- newc[1]++;
- }
-
- // continue
- ClipSkyPolygon (newc[0], newv[0][0], stage+1);
- ClipSkyPolygon (newc[1], newv[1][0], stage+1);
-}
-
-/*
-==============
-ClearSkyBox
-==============
-*/
-static void ClearSkyBox (void) {
- int i;
-
- for (i=0 ; i<6 ; i++) {
- sky_mins[0][i] = sky_mins[1][i] = 9999;
- sky_maxs[0][i] = sky_maxs[1][i] = -9999;
- }
-}
-
-/*
-================
-RB_ClipSkyPolygons
-================
-*/
-void RB_ClipSkyPolygons( shaderCommands_t *input )
-{
- vec3_t p[5]; // need one extra point for clipping
- int i, j;
-
- ClearSkyBox();
-
- for ( i = 0; i < input->numIndexes; i += 3 )
- {
- for (j = 0 ; j < 3 ; j++)
- {
- VectorSubtract( input->xyz[input->indexes[i+j]],
- backEnd.viewParms.or.origin,
- p[j] );
- }
- ClipSkyPolygon( 3, p[0], 0 );
- }
-}
-
-/*
-===================================================================================
-
-CLOUD VERTEX GENERATION
-
-===================================================================================
-*/
-
-/*
-** MakeSkyVec
-**
-** Parms: s, t range from -1 to 1
-*/
-static void MakeSkyVec( float s, float t, int axis, float outSt[2], vec3_t outXYZ )
-{
- // 1 = s, 2 = t, 3 = 2048
- static int st_to_vec[6][3] =
- {
- {3,-1,2},
- {-3,1,2},
-
- {1,3,2},
- {-1,-3,2},
-
- {-2,-1,3}, // 0 degrees yaw, look straight up
- {2,-1,-3} // look straight down
- };
-
- vec3_t b;
- int j, k;
- float boxSize;
-
- boxSize = backEnd.viewParms.zFar / 1.75; // div sqrt(3)
- b[0] = s*boxSize;
- b[1] = t*boxSize;
- b[2] = boxSize;
-
- for (j=0 ; j<3 ; j++)
- {
- k = st_to_vec[axis][j];
- if (k < 0)
- {
- outXYZ[j] = -b[-k - 1];
- }
- else
- {
- outXYZ[j] = b[k - 1];
- }
- }
-
- // avoid bilerp seam
- s = (s+1)*0.5;
- t = (t+1)*0.5;
- if (s < sky_min)
- {
- s = sky_min;
- }
- else if (s > sky_max)
- {
- s = sky_max;
- }
-
- if (t < sky_min)
- {
- t = sky_min;
- }
- else if (t > sky_max)
- {
- t = sky_max;
- }
-
- t = 1.0 - t;
-
-
- if ( outSt )
- {
- outSt[0] = s;
- outSt[1] = t;
- }
-}
-
-static int sky_texorder[6] = {0,2,1,3,4,5};
-static vec3_t s_skyPoints[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1];
-static float s_skyTexCoords[SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2];
-
-static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] )
-{
- int s, t;
- int firstVertex = tess.numVertexes;
- //int firstIndex = tess.numIndexes;
- int minIndex = tess.minIndex;
- int maxIndex = tess.maxIndex;
- vec4_t color;
-
- //tess.numVertexes = 0;
- //tess.numIndexes = 0;
- tess.firstIndex = tess.numIndexes;
-
- GL_Bind( image );
- GL_Cull( CT_TWO_SIDED );
-
- for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
- {
- for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
- {
- tess.xyz[tess.numVertexes][0] = s_skyPoints[t][s][0];
- tess.xyz[tess.numVertexes][1] = s_skyPoints[t][s][1];
- tess.xyz[tess.numVertexes][2] = s_skyPoints[t][s][2];
- tess.xyz[tess.numVertexes][3] = 1.0;
-
- tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0];
- tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1];
-
- tess.numVertexes++;
-
- if(tess.numVertexes >= SHADER_MAX_VERTEXES)
- {
- ri.Error(ERR_DROP, "SHADER_MAX_VERTEXES hit in DrawSkySideVBO()");
- }
- }
- }
-
- for ( t = 0; t < maxs[1] - mins[1]; t++ )
- {
- for ( s = 0; s < maxs[0] - mins[0]; s++ )
- {
- if (tess.numIndexes + 6 >= SHADER_MAX_INDEXES)
- {
- ri.Error(ERR_DROP, "SHADER_MAX_INDEXES hit in DrawSkySideVBO()");
- }
-
- tess.indexes[tess.numIndexes++] = s + t * (maxs[0] - mins[0] + 1) + firstVertex;
- tess.indexes[tess.numIndexes++] = s + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex;
- tess.indexes[tess.numIndexes++] = (s + 1) + t * (maxs[0] - mins[0] + 1) + firstVertex;
-
- tess.indexes[tess.numIndexes++] = (s + 1) + t * (maxs[0] - mins[0] + 1) + firstVertex;
- tess.indexes[tess.numIndexes++] = s + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex;
- tess.indexes[tess.numIndexes++] = (s + 1) + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex;
- }
- }
-
- tess.minIndex = firstVertex;
- tess.maxIndex = tess.numVertexes;
-
- // FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function
- RB_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD);
-/*
- {
- shaderProgram_t *sp = &tr.textureColorShader;
-
- GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD);
- GLSL_BindProgram(sp);
-
- GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
-
- color[0] =
- color[1] =
- color[2] = tr.identityLight;
- color[3] = 1.0f;
- GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color);
- }
-*/
- {
- shaderProgram_t *sp = &tr.lightallShader[0];
- vec4_t vector;
-
- GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD);
- GLSL_BindProgram(sp);
-
- GLSL_SetUniformMatrix16(sp, GENERIC_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
-
- color[0] =
- color[1] =
- color[2] = tr.identityLight;
- color[3] = 1.0f;
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_BASECOLOR, color);
-
- color[0] =
- color[1] =
- color[2] =
- color[3] = 0.0f;
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_VERTCOLOR, color);
-
- VectorSet4(vector, 1.0, 0.0, 0.0, 1.0);
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_DIFFUSETEXMATRIX, vector);
-
- VectorSet4(vector, 0.0, 0.0, 0.0, 0.0);
- GLSL_SetUniformVec4(sp, GENERIC_UNIFORM_DIFFUSETEXOFFTURB, vector);
- }
-
- R_DrawElementsVBO(tess.numIndexes - tess.firstIndex, tess.firstIndex, tess.minIndex, tess.maxIndex);
-
- //qglDrawElements(GL_TRIANGLES, tess.numIndexes - tess.firstIndex, GL_INDEX_TYPE, BUFFER_OFFSET(tess.firstIndex * sizeof(GL_INDEX_TYPE)));
-
- //R_BindNullVBO();
- //R_BindNullIBO();
-
- tess.numIndexes = tess.firstIndex;
- tess.numVertexes = firstVertex;
- tess.firstIndex = 0;
- tess.minIndex = minIndex;
- tess.maxIndex = maxIndex;
-}
-
-static void DrawSkyBox( shader_t *shader )
-{
- int i;
-
- sky_min = 0;
- sky_max = 1;
-
- Com_Memset( s_skyTexCoords, 0, sizeof( s_skyTexCoords ) );
-
- for (i=0 ; i<6 ; i++)
- {
- int sky_mins_subd[2], sky_maxs_subd[2];
- int s, t;
-
- sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
- sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
- sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
- sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
-
- if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) ||
- ( sky_mins[1][i] >= sky_maxs[1][i] ) )
- {
- continue;
- }
-
- sky_mins_subd[0] = sky_mins[0][i] * HALF_SKY_SUBDIVISIONS;
- sky_mins_subd[1] = sky_mins[1][i] * HALF_SKY_SUBDIVISIONS;
- sky_maxs_subd[0] = sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS;
- sky_maxs_subd[1] = sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS;
-
- if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS )
- sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS;
- else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS )
- sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS;
- if ( sky_mins_subd[1] < -HALF_SKY_SUBDIVISIONS )
- sky_mins_subd[1] = -HALF_SKY_SUBDIVISIONS;
- else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS )
- sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS;
-
- if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS )
- sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS;
- else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS )
- sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS;
- if ( sky_maxs_subd[1] < -HALF_SKY_SUBDIVISIONS )
- sky_maxs_subd[1] = -HALF_SKY_SUBDIVISIONS;
- else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS )
- sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS;
-
- //
- // iterate through the subdivisions
- //
- for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ )
- {
- for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ )
- {
- MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
- ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
- i,
- s_skyTexCoords[t][s],
- s_skyPoints[t][s] );
- }
- }
-
- DrawSkySide( shader->sky.outerbox[sky_texorder[i]],
- sky_mins_subd,
- sky_maxs_subd );
- }
-
-}
-
-static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean addIndexes )
-{
- int s, t;
- int vertexStart = tess.numVertexes;
- int tHeight, sWidth;
-
- tHeight = maxs[1] - mins[1] + 1;
- sWidth = maxs[0] - mins[0] + 1;
-
- for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
- {
- for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
- {
- VectorAdd( s_skyPoints[t][s], backEnd.viewParms.or.origin, tess.xyz[tess.numVertexes] );
- tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0];
- tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1];
-
- tess.numVertexes++;
-
- if ( tess.numVertexes >= SHADER_MAX_VERTEXES )
- {
- ri.Error( ERR_DROP, "SHADER_MAX_VERTEXES hit in FillCloudySkySide()" );
- }
- }
- }
-
- // only add indexes for one pass, otherwise it would draw multiple times for each pass
- if ( addIndexes ) {
- for ( t = 0; t < tHeight-1; t++ )
- {
- for ( s = 0; s < sWidth-1; s++ )
- {
- tess.indexes[tess.numIndexes] = vertexStart + s + t * ( sWidth );
- tess.numIndexes++;
- tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth );
- tess.numIndexes++;
- tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth );
- tess.numIndexes++;
-
- tess.indexes[tess.numIndexes] = vertexStart + s + ( t + 1 ) * ( sWidth );
- tess.numIndexes++;
- tess.indexes[tess.numIndexes] = vertexStart + s + 1 + ( t + 1 ) * ( sWidth );
- tess.numIndexes++;
- tess.indexes[tess.numIndexes] = vertexStart + s + 1 + t * ( sWidth );
- tess.numIndexes++;
- }
- }
- }
-}
-
-static void FillCloudBox( const shader_t *shader, int stage )
-{
- int i;
-
- for ( i =0; i < 6; i++ )
- {
- int sky_mins_subd[2], sky_maxs_subd[2];
- int s, t;
- float MIN_T;
-
- if ( 1 ) // FIXME? shader->sky.fullClouds )
- {
- MIN_T = -HALF_SKY_SUBDIVISIONS;
-
- // still don't want to draw the bottom, even if fullClouds
- if ( i == 5 )
- continue;
- }
- else
- {
- switch( i )
- {
- case 0:
- case 1:
- case 2:
- case 3:
- MIN_T = -1;
- break;
- case 5:
- // don't draw clouds beneath you
- continue;
- case 4: // top
- default:
- MIN_T = -HALF_SKY_SUBDIVISIONS;
- break;
- }
- }
-
- sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
- sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
- sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
- sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS;
-
- if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) ||
- ( sky_mins[1][i] >= sky_maxs[1][i] ) )
- {
- continue;
- }
-
- sky_mins_subd[0] = ri.ftol(sky_mins[0][i] * HALF_SKY_SUBDIVISIONS);
- sky_mins_subd[1] = ri.ftol(sky_mins[1][i] * HALF_SKY_SUBDIVISIONS);
- sky_maxs_subd[0] = ri.ftol(sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS);
- sky_maxs_subd[1] = ri.ftol(sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS);
-
- if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS )
- sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS;
- else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS )
- sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS;
- if ( sky_mins_subd[1] < MIN_T )
- sky_mins_subd[1] = MIN_T;
- else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS )
- sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS;
-
- if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS )
- sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS;
- else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS )
- sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS;
- if ( sky_maxs_subd[1] < MIN_T )
- sky_maxs_subd[1] = MIN_T;
- else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS )
- sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS;
-
- //
- // iterate through the subdivisions
- //
- for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ )
- {
- for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ )
- {
- MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
- ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
- i,
- NULL,
- s_skyPoints[t][s] );
-
- s_skyTexCoords[t][s][0] = s_cloudTexCoords[i][t][s][0];
- s_skyTexCoords[t][s][1] = s_cloudTexCoords[i][t][s][1];
- }
- }
-
- // only add indexes for first stage
- FillCloudySkySide( sky_mins_subd, sky_maxs_subd, ( stage == 0 ) );
- }
-}
-
-/*
-** R_BuildCloudData
-*/
-void R_BuildCloudData( shaderCommands_t *input )
-{
- int i;
- shader_t *shader;
-
- shader = input->shader;
-
- assert( shader->isSky );
-
- sky_min = 1.0 / 256.0f; // FIXME: not correct?
- sky_max = 255.0 / 256.0f;
-
- // set up for drawing
- tess.numIndexes = 0;
- tess.numVertexes = 0;
- tess.firstIndex = 0;
-
- if ( shader->sky.cloudHeight )
- {
- for ( i = 0; i < MAX_SHADER_STAGES; i++ )
- {
- if ( !tess.xstages[i] ) {
- break;
- }
- FillCloudBox( shader, i );
- }
- }
-}
-
-/*
-** R_InitSkyTexCoords
-** Called when a sky shader is parsed
-*/
-#define SQR( a ) ((a)*(a))
-void R_InitSkyTexCoords( float heightCloud )
-{
- int i, s, t;
- float radiusWorld = 4096;
- float p;
- float sRad, tRad;
- vec3_t skyVec;
- vec3_t v;
-
- // init zfar so MakeSkyVec works even though
- // a world hasn't been bounded
- backEnd.viewParms.zFar = 1024;
-
- for ( i = 0; i < 6; i++ )
- {
- for ( t = 0; t <= SKY_SUBDIVISIONS; t++ )
- {
- for ( s = 0; s <= SKY_SUBDIVISIONS; s++ )
- {
- // compute vector from view origin to sky side integral point
- MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
- ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS,
- i,
- NULL,
- skyVec );
-
- // compute parametric value 'p' that intersects with cloud layer
- p = ( 1.0f / ( 2 * DotProduct( skyVec, skyVec ) ) ) *
- ( -2 * skyVec[2] * radiusWorld +
- 2 * sqrt( SQR( skyVec[2] ) * SQR( radiusWorld ) +
- 2 * SQR( skyVec[0] ) * radiusWorld * heightCloud +
- SQR( skyVec[0] ) * SQR( heightCloud ) +
- 2 * SQR( skyVec[1] ) * radiusWorld * heightCloud +
- SQR( skyVec[1] ) * SQR( heightCloud ) +
- 2 * SQR( skyVec[2] ) * radiusWorld * heightCloud +
- SQR( skyVec[2] ) * SQR( heightCloud ) ) );
-
- s_cloudTexP[i][t][s] = p;
-
- // compute intersection point based on p
- VectorScale( skyVec, p, v );
- v[2] += radiusWorld;
-
- // compute vector from world origin to intersection point 'v'
- VectorNormalize( v );
-
- sRad = Q_acos( v[0] );
- tRad = Q_acos( v[1] );
-
- s_cloudTexCoords[i][t][s][0] = sRad;
- s_cloudTexCoords[i][t][s][1] = tRad;
- }
- }
- }
-}
-
-//======================================================================================
-
-/*
-** RB_DrawSun
-*/
-void RB_DrawSun( float scale, shader_t *shader ) {
- float size;
- float dist;
- vec3_t origin, vec1, vec2;
-
- if ( !backEnd.skyRenderedThisView ) {
- return;
- }
-
- //qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
- //qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
- {
- // FIXME: this could be a lot cleaner
- matrix_t translation, modelview;
-
- Matrix16Translation( backEnd.viewParms.or.origin, translation );
- Matrix16Multiply( backEnd.viewParms.world.modelMatrix, translation, modelview );
- GL_SetModelviewMatrix( modelview );
- }
-
- dist = backEnd.viewParms.zFar / 1.75; // div sqrt(3)
- size = dist * scale;
-
- VectorScale( tr.sunDirection, dist, origin );
- PerpendicularVector( vec1, tr.sunDirection );
- CrossProduct( tr.sunDirection, vec1, vec2 );
-
- VectorScale( vec1, size, vec1 );
- VectorScale( vec2, size, vec2 );
-
- // farthest depth range
- qglDepthRange( 1.0, 1.0 );
-
- RB_BeginSurface( shader, 0 );
-
- {
- vec4_t color;
- color[0] = color[1] = color[2] = color[3] = 1;
- RB_AddQuadStamp(origin, vec1, vec2, color);
- }
-
- RB_EndSurface();
-
- // back to normal depth range
- qglDepthRange( 0.0, 1.0 );
-}
-
-
-
-
-/*
-================
-RB_StageIteratorSky
-
-All of the visible sky triangles are in tess
-
-Other things could be stuck in here, like birds in the sky, etc
-================
-*/
-void RB_StageIteratorSky( void ) {
- if ( r_fastsky->integer ) {
- return;
- }
-
- // go through all the polygons and project them onto
- // the sky box to see which blocks on each side need
- // to be drawn
- RB_ClipSkyPolygons( &tess );
-
- // r_showsky will let all the sky blocks be drawn in
- // front of everything to allow developers to see how
- // much sky is getting sucked in
- if ( r_showsky->integer ) {
- qglDepthRange( 0.0, 0.0 );
- } else {
- qglDepthRange( 1.0, 1.0 );
- }
-
- // draw the outer skybox
- if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) {
- matrix_t oldmodelview;
-
- GL_State( 0 );
- //qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]);
-
- {
- // FIXME: this could be a lot cleaner
- matrix_t trans, product;
-
- Matrix16Copy( glState.modelview, oldmodelview );
- Matrix16Translation( backEnd.viewParms.or.origin, trans );
- Matrix16Multiply( glState.modelview, trans, product );
- GL_SetModelviewMatrix( product );
-
- }
-
- DrawSkyBox( tess.shader );
-
- GL_SetModelviewMatrix( oldmodelview );
- }
-
- // generate the vertexes for all the clouds, which will be drawn
- // by the generic shader routine
- R_BuildCloudData( &tess );
-
- RB_StageIteratorGeneric();
-
- // draw the inner skybox
-
-
- // back to normal depth range
- qglDepthRange( 0.0, 1.0 );
-
- // note that sky was drawn so we will draw a sun later
- backEnd.skyRenderedThisView = qtrue;
-}
-
-
-
-
-
diff --git a/src/rend2/tr_subs.c b/src/rend2/tr_subs.c
deleted file mode 100644
index 6f490128..00000000
--- a/src/rend2/tr_subs.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 2010 James Canete (use.less01@gmail.com)
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_subs.c - common function replacements for modular renderer
-
-#include "tr_local.h"
-
-void QDECL Com_Printf( const char *msg, ... )
-{
- va_list argptr;
- char text[1024];
-
- va_start(argptr, msg);
- Q_vsnprintf(text, sizeof(text), msg, argptr);
- va_end(argptr);
-
- ri.Printf(PRINT_ALL, "%s", text);
-}
-
-void QDECL Com_Error( int level, const char *error, ... )
-{
- va_list argptr;
- char text[1024];
-
- va_start(argptr, error);
- Q_vsnprintf(text, sizeof(text), error, argptr);
- va_end(argptr);
-
- ri.Error(level, "%s", text);
-}
diff --git a/src/rend2/tr_surface.c b/src/rend2/tr_surface.c
deleted file mode 100644
index ad7f5a5f..00000000
--- a/src/rend2/tr_surface.c
+++ /dev/null
@@ -1,1698 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_surf.c
-#include "tr_local.h"
-#if idppc_altivec && !defined(MACOS_X)
-#include <altivec.h>
-#endif
-
-/*
-
- THIS ENTIRE FILE IS BACK END
-
-backEnd.currentEntity will be valid.
-
-Tess_Begin has already been called for the surface's shader.
-
-The modelview matrix will be set.
-
-It is safe to actually issue drawing commands here if you don't want to
-use the shader system.
-*/
-
-
-//============================================================================
-
-
-/*
-==============
-RB_CheckOverflow
-==============
-*/
-void RB_CheckOverflow( int verts, int indexes ) {
- if (tess.numVertexes + verts < SHADER_MAX_VERTEXES
- && tess.numIndexes + indexes < SHADER_MAX_INDEXES) {
- return;
- }
-
- RB_EndSurface();
-
- if ( verts >= SHADER_MAX_VERTEXES ) {
- ri.Error(ERR_DROP, "RB_CheckOverflow: verts > MAX (%d > %d)", verts, SHADER_MAX_VERTEXES );
- }
- if ( indexes >= SHADER_MAX_INDEXES ) {
- ri.Error(ERR_DROP, "RB_CheckOverflow: indices > MAX (%d > %d)", indexes, SHADER_MAX_INDEXES );
- }
-
- RB_BeginSurface(tess.shader, tess.fogNum );
-}
-
-void RB_CheckVBOandIBO(VBO_t *vbo, IBO_t *ibo)
-{
- if (!(vbo == glState.currentVBO && ibo == glState.currentIBO) || tess.multiDrawPrimitives >= MAX_MULTIDRAW_PRIMITIVES)
- {
- RB_EndSurface();
- RB_BeginSurface(tess.shader, tess.fogNum);
-
- R_BindVBO(vbo);
- R_BindIBO(ibo);
- }
-
- if (vbo != tess.vbo && ibo != tess.ibo)
- tess.useInternalVBO = qfalse;
-}
-
-
-/*
-==============
-RB_AddQuadStampExt
-==============
-*/
-void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float color[4], float s1, float t1, float s2, float t2 ) {
- vec3_t normal;
- int ndx;
-
- RB_CHECKOVERFLOW( 4, 6 );
-
- ndx = tess.numVertexes;
-
- // triangle indexes for a simple quad
- tess.indexes[ tess.numIndexes ] = ndx;
- tess.indexes[ tess.numIndexes + 1 ] = ndx + 1;
- tess.indexes[ tess.numIndexes + 2 ] = ndx + 3;
-
- tess.indexes[ tess.numIndexes + 3 ] = ndx + 3;
- tess.indexes[ tess.numIndexes + 4 ] = ndx + 1;
- tess.indexes[ tess.numIndexes + 5 ] = ndx + 2;
-
- tess.xyz[ndx][0] = origin[0] + left[0] + up[0];
- tess.xyz[ndx][1] = origin[1] + left[1] + up[1];
- tess.xyz[ndx][2] = origin[2] + left[2] + up[2];
-
- tess.xyz[ndx+1][0] = origin[0] - left[0] + up[0];
- tess.xyz[ndx+1][1] = origin[1] - left[1] + up[1];
- tess.xyz[ndx+1][2] = origin[2] - left[2] + up[2];
-
- tess.xyz[ndx+2][0] = origin[0] - left[0] - up[0];
- tess.xyz[ndx+2][1] = origin[1] - left[1] - up[1];
- tess.xyz[ndx+2][2] = origin[2] - left[2] - up[2];
-
- tess.xyz[ndx+3][0] = origin[0] + left[0] - up[0];
- tess.xyz[ndx+3][1] = origin[1] + left[1] - up[1];
- tess.xyz[ndx+3][2] = origin[2] + left[2] - up[2];
-
-
- // constant normal all the way around
- VectorSubtract( vec3_origin, backEnd.viewParms.or.axis[0], normal );
-
- tess.normal[ndx][0] = tess.normal[ndx+1][0] = tess.normal[ndx+2][0] = tess.normal[ndx+3][0] = normal[0];
- tess.normal[ndx][1] = tess.normal[ndx+1][1] = tess.normal[ndx+2][1] = tess.normal[ndx+3][1] = normal[1];
- tess.normal[ndx][2] = tess.normal[ndx+1][2] = tess.normal[ndx+2][2] = tess.normal[ndx+3][2] = normal[2];
-
- // standard square texture coordinates
- tess.texCoords[ndx][0][0] = tess.texCoords[ndx][1][0] = s1;
- tess.texCoords[ndx][0][1] = tess.texCoords[ndx][1][1] = t1;
-
- tess.texCoords[ndx+1][0][0] = tess.texCoords[ndx+1][1][0] = s2;
- tess.texCoords[ndx+1][0][1] = tess.texCoords[ndx+1][1][1] = t1;
-
- tess.texCoords[ndx+2][0][0] = tess.texCoords[ndx+2][1][0] = s2;
- tess.texCoords[ndx+2][0][1] = tess.texCoords[ndx+2][1][1] = t2;
-
- tess.texCoords[ndx+3][0][0] = tess.texCoords[ndx+3][1][0] = s1;
- tess.texCoords[ndx+3][0][1] = tess.texCoords[ndx+3][1][1] = t2;
-
- // constant color all the way around
- // should this be identity and let the shader specify from entity?
- tess.vertexColors[ndx][0] = color[0];
- tess.vertexColors[ndx][1] = color[1];
- tess.vertexColors[ndx][2] = color[2];
- tess.vertexColors[ndx][3] = color[3];
-
- tess.vertexColors[ndx+1][0] = color[0];
- tess.vertexColors[ndx+1][1] = color[1];
- tess.vertexColors[ndx+1][2] = color[2];
- tess.vertexColors[ndx+1][3] = color[3];
-
- tess.vertexColors[ndx+2][0] = color[0];
- tess.vertexColors[ndx+2][1] = color[1];
- tess.vertexColors[ndx+2][2] = color[2];
- tess.vertexColors[ndx+2][3] = color[3];
-
- tess.vertexColors[ndx+3][0] = color[0];
- tess.vertexColors[ndx+3][1] = color[1];
- tess.vertexColors[ndx+3][2] = color[2];
- tess.vertexColors[ndx+3][3] = color[3];
-
- tess.numVertexes += 4;
- tess.numIndexes += 6;
-}
-
-/*
-==============
-RB_AddQuadStamp
-==============
-*/
-void RB_AddQuadStamp( vec3_t origin, vec3_t left, vec3_t up, float color[4] ) {
- RB_AddQuadStampExt( origin, left, up, color, 0, 0, 1, 1 );
-}
-
-
-/*
-==============
-RB_InstantQuad
-
-based on Tess_InstantQuad from xreal
-==============
-*/
-void RB_InstantQuad2(vec4_t quadVerts[4], vec2_t texCoords[4])
-{
- GLimp_LogComment("--- RB_InstantQuad2 ---\n");
-
- tess.numVertexes = 0;
- tess.numIndexes = 0;
- tess.firstIndex = 0;
-
- VectorCopy4(quadVerts[0], tess.xyz[tess.numVertexes]);
- VectorCopy2(texCoords[0], tess.texCoords[tess.numVertexes][0]);
- tess.numVertexes++;
-
- VectorCopy4(quadVerts[1], tess.xyz[tess.numVertexes]);
- VectorCopy2(texCoords[1], tess.texCoords[tess.numVertexes][0]);
- tess.numVertexes++;
-
- VectorCopy4(quadVerts[2], tess.xyz[tess.numVertexes]);
- VectorCopy2(texCoords[2], tess.texCoords[tess.numVertexes][0]);
- tess.numVertexes++;
-
- VectorCopy4(quadVerts[3], tess.xyz[tess.numVertexes]);
- VectorCopy2(texCoords[3], tess.texCoords[tess.numVertexes][0]);
- tess.numVertexes++;
-
- tess.indexes[tess.numIndexes++] = 0;
- tess.indexes[tess.numIndexes++] = 1;
- tess.indexes[tess.numIndexes++] = 2;
- tess.indexes[tess.numIndexes++] = 0;
- tess.indexes[tess.numIndexes++] = 2;
- tess.indexes[tess.numIndexes++] = 3;
- tess.minIndex = 0;
- tess.maxIndex = 3;
-
- RB_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD);
-
- GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD);
-
- R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);
-
- tess.numIndexes = 0;
- tess.numVertexes = 0;
- tess.firstIndex = 0;
- tess.minIndex = 0;
- tess.maxIndex = 0;
-}
-
-
-void RB_InstantQuad(vec4_t quadVerts[4])
-{
- vec4_t color;
- vec2_t texCoords[4];
- vec2_t invTexRes;
-
- VectorSet4(color, 1, 1, 1, 1);
-
- texCoords[0][0] = 0;
- texCoords[0][1] = 0;
-
- texCoords[1][0] = 1;
- texCoords[1][1] = 0;
-
- texCoords[2][0] = 1;
- texCoords[2][1] = 1;
-
- texCoords[3][0] = 0;
- texCoords[3][1] = 1;
-
- invTexRes[0] = 1.0f / 256.0f;
- invTexRes[1] = 1.0f / 256.0f;
-
- GLSL_BindProgram(&tr.textureColorShader);
-
- GLSL_SetUniformMatrix16(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
- GLSL_SetUniformVec4(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_COLOR, color);
- GLSL_SetUniformVec2(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_INVTEXRES, invTexRes);
- GLSL_SetUniformVec2(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_AUTOEXPOSUREMINMAX, tr.refdef.autoExposureMinMax);
- GLSL_SetUniformVec3(&tr.textureColorShader, TEXTURECOLOR_UNIFORM_TONEMINAVGMAXLINEAR, tr.refdef.toneMinAvgMaxLinear);
-
- RB_InstantQuad2(quadVerts, texCoords); //, color, &tr.textureColorShader, invTexRes);
-}
-
-
-/*
-==============
-RB_SurfaceSprite
-==============
-*/
-static void RB_SurfaceSprite( void ) {
- vec3_t left, up;
- float radius;
- float colors[4];
- trRefEntity_t *ent = backEnd.currentEntity;
-
- // calculate the xyz locations for the four corners
- radius = ent->e.radius;
- if ( ent->e.rotation == 0 ) {
- VectorScale( backEnd.viewParms.or.axis[1], radius, left );
- VectorScale( backEnd.viewParms.or.axis[2], radius, up );
- } else {
- float s, c;
- float ang;
-
- ang = M_PI * ent->e.rotation / 180;
- s = sin( ang );
- c = cos( ang );
-
- VectorScale( backEnd.viewParms.or.axis[1], c * radius, left );
- VectorMA( left, -s * radius, backEnd.viewParms.or.axis[2], left );
-
- VectorScale( backEnd.viewParms.or.axis[2], c * radius, up );
- VectorMA( up, s * radius, backEnd.viewParms.or.axis[1], up );
- }
- if ( backEnd.viewParms.isMirror ) {
- VectorSubtract( vec3_origin, left, left );
- }
-
- VectorScale4(ent->e.shaderRGBA, 1.0f / 255.0f, colors);
-
- RB_AddQuadStamp( ent->e.origin, left, up, colors );
-}
-
-
-/*
-=============
-RB_SurfacePolychain
-=============
-*/
-static void RB_SurfacePolychain( srfPoly_t *p ) {
- int i;
- int numv;
-
- RB_CHECKOVERFLOW( p->numVerts, 3*(p->numVerts - 2) );
-
- // fan triangles into the tess array
- numv = tess.numVertexes;
- for ( i = 0; i < p->numVerts; i++ ) {
- VectorCopy( p->verts[i].xyz, tess.xyz[numv] );
- tess.texCoords[numv][0][0] = p->verts[i].st[0];
- tess.texCoords[numv][0][1] = p->verts[i].st[1];
- tess.vertexColors[numv][0] = p->verts[ i ].modulate[0] / 255.0f;
- tess.vertexColors[numv][1] = p->verts[ i ].modulate[1] / 255.0f;
- tess.vertexColors[numv][2] = p->verts[ i ].modulate[2] / 255.0f;
- tess.vertexColors[numv][3] = p->verts[ i ].modulate[3] / 255.0f;
-
- numv++;
- }
-
- // generate fan indexes into the tess array
- for ( i = 0; i < p->numVerts-2; i++ ) {
- tess.indexes[tess.numIndexes + 0] = tess.numVertexes;
- tess.indexes[tess.numIndexes + 1] = tess.numVertexes + i + 1;
- tess.indexes[tess.numIndexes + 2] = tess.numVertexes + i + 2;
- tess.numIndexes += 3;
- }
-
- tess.numVertexes = numv;
-}
-
-static void RB_SurfaceHelper( int numVerts, srfVert_t *verts, int numTriangles, srfTriangle_t *triangles, int dlightBits, int pshadowBits)
-{
- int i;
- srfTriangle_t *tri;
- srfVert_t *dv;
- float *xyz, *normal, *texCoords, *lightCoords, *lightdir;
-#ifdef USE_VERT_TANGENT_SPACE
- float *tangent, *bitangent;
-#endif
- glIndex_t *index;
- float *color;
-
- RB_CheckVBOandIBO(tess.vbo, tess.ibo);
-
- RB_CHECKOVERFLOW( numVerts, numTriangles * 3 );
-
- tri = triangles;
- index = &tess.indexes[ tess.numIndexes ];
- for ( i = 0 ; i < numTriangles ; i++, tri++ ) {
- *index++ = tess.numVertexes + tri->indexes[0];
- *index++ = tess.numVertexes + tri->indexes[1];
- *index++ = tess.numVertexes + tri->indexes[2];
- }
- tess.numIndexes += numTriangles * 3;
-
- if ( tess.shader->vertexAttribs & ATTR_POSITION )
- {
- dv = verts;
- xyz = tess.xyz[ tess.numVertexes ];
- for ( i = 0 ; i < numVerts ; i++, dv++, xyz+=4 )
- VectorCopy(dv->xyz, xyz);
- }
-
- if ( tess.shader->vertexAttribs & ATTR_NORMAL )
- {
- dv = verts;
- normal = tess.normal[ tess.numVertexes ];
- for ( i = 0 ; i < numVerts ; i++, dv++, normal+=4 )
- VectorCopy(dv->normal, normal);
- }
-
-#ifdef USE_VERT_TANGENT_SPACE
- if ( tess.shader->vertexAttribs & ATTR_TANGENT )
- {
- dv = verts;
- tangent = tess.tangent[ tess.numVertexes ];
- for ( i = 0 ; i < numVerts ; i++, dv++, tangent+=4 )
- VectorCopy(dv->tangent, tangent);
- }
-
- if ( tess.shader->vertexAttribs & ATTR_BITANGENT )
- {
- dv = verts;
- bitangent = tess.bitangent[ tess.numVertexes ];
- for ( i = 0 ; i < numVerts ; i++, dv++, bitangent+=4 )
- VectorCopy(dv->bitangent, bitangent);
- }
-#endif
-
- if ( tess.shader->vertexAttribs & ATTR_TEXCOORD )
- {
- dv = verts;
- texCoords = tess.texCoords[ tess.numVertexes ][0];
- for ( i = 0 ; i < numVerts ; i++, dv++, texCoords+=4 )
- VectorCopy2(dv->st, texCoords);
- }
-
- if ( tess.shader->vertexAttribs & ATTR_LIGHTCOORD )
- {
- dv = verts;
- lightCoords = tess.texCoords[ tess.numVertexes ][1];
- for ( i = 0 ; i < numVerts ; i++, dv++, lightCoords+=4 )
- VectorCopy2(dv->lightmap, lightCoords);
- }
-
- if ( tess.shader->vertexAttribs & ATTR_COLOR )
- {
- dv = verts;
- color = tess.vertexColors[ tess.numVertexes ];
- for ( i = 0 ; i < numVerts ; i++, dv++, color+=4 )
- VectorCopy4(dv->vertexColors, color);
- }
-
- if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION )
- {
- dv = verts;
- lightdir = tess.lightdir[ tess.numVertexes ];
- for ( i = 0 ; i < numVerts ; i++, dv++, lightdir+=4 )
- VectorCopy(dv->lightdir, lightdir);
- }
-
-#if 0 // nothing even uses vertex dlightbits
- for ( i = 0 ; i < numVerts ; i++ ) {
- tess.vertexDlightBits[ tess.numVertexes + i ] = dlightBits;
- }
-#endif
-
- tess.dlightBits |= dlightBits;
- tess.pshadowBits |= pshadowBits;
-
- tess.numVertexes += numVerts;
-}
-
-static qboolean RB_SurfaceHelperVBO(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndexes, int firstIndex, int minIndex, int maxIndex, int dlightBits, int pshadowBits, qboolean shaderCheck)
-{
- int i, mergeForward, mergeBack;
- GLvoid *firstIndexOffset, *lastIndexOffset;
-
- if (!vbo || !ibo)
- {
- return qfalse;
- }
-
- if (shaderCheck && !(!ShaderRequiresCPUDeforms(tess.shader) && !tess.shader->isSky && !tess.shader->isPortal))
- {
- return qfalse;
- }
-
- RB_CheckVBOandIBO(vbo, ibo);
-
- tess.dlightBits |= dlightBits;
- tess.pshadowBits |= pshadowBits;
-
- // merge this into any existing multidraw primitives
- mergeForward = -1;
- mergeBack = -1;
- firstIndexOffset = BUFFER_OFFSET(firstIndex * sizeof(GL_INDEX_TYPE));
- lastIndexOffset = BUFFER_OFFSET((firstIndex + numIndexes) * sizeof(GL_INDEX_TYPE));
-
- if (r_mergeMultidraws->integer)
- {
- i = 0;
-
- if (r_mergeMultidraws->integer == 1)
- {
- // lazy merge, only check the last primitive
- if (tess.multiDrawPrimitives)
- {
- i = tess.multiDrawPrimitives - 1;
- }
- }
-
- for (; i < tess.multiDrawPrimitives; i++)
- {
- if (tess.multiDrawLastIndex[i] == firstIndexOffset)
- {
- mergeBack = i;
- }
-
- if (lastIndexOffset == tess.multiDrawFirstIndex[i])
- {
- mergeForward = i;
- }
- }
- }
-
- if (mergeBack != -1 && mergeForward == -1)
- {
- tess.multiDrawNumIndexes[mergeBack] += numIndexes;
- tess.multiDrawLastIndex[mergeBack] = tess.multiDrawFirstIndex[mergeBack] + tess.multiDrawNumIndexes[mergeBack];
- tess.multiDrawMinIndex[mergeBack] = MIN(tess.multiDrawMinIndex[mergeBack], minIndex);
- tess.multiDrawMaxIndex[mergeBack] = MAX(tess.multiDrawMaxIndex[mergeBack], maxIndex);
- backEnd.pc.c_multidrawsMerged++;
- }
- else if (mergeBack == -1 && mergeForward != -1)
- {
- tess.multiDrawNumIndexes[mergeForward] += numIndexes;
- tess.multiDrawFirstIndex[mergeForward] = firstIndexOffset;
- tess.multiDrawLastIndex[mergeForward] = tess.multiDrawFirstIndex[mergeForward] + tess.multiDrawNumIndexes[mergeForward];
- tess.multiDrawMinIndex[mergeForward] = MIN(tess.multiDrawMinIndex[mergeForward], minIndex);
- tess.multiDrawMaxIndex[mergeForward] = MAX(tess.multiDrawMaxIndex[mergeForward], maxIndex);
- backEnd.pc.c_multidrawsMerged++;
- }
- else if (mergeBack != -1 && mergeForward != -1)
- {
- tess.multiDrawNumIndexes[mergeBack] += numIndexes + tess.multiDrawNumIndexes[mergeForward];
- tess.multiDrawLastIndex[mergeBack] = tess.multiDrawFirstIndex[mergeBack] + tess.multiDrawNumIndexes[mergeBack];
- tess.multiDrawMinIndex[mergeBack] = MIN(tess.multiDrawMinIndex[mergeBack], MIN(tess.multiDrawMinIndex[mergeForward], minIndex));
- tess.multiDrawMaxIndex[mergeBack] = MAX(tess.multiDrawMaxIndex[mergeBack], MAX(tess.multiDrawMaxIndex[mergeForward], maxIndex));
- tess.multiDrawPrimitives--;
-
- if (mergeForward != tess.multiDrawPrimitives)
- {
- tess.multiDrawNumIndexes[mergeForward] = tess.multiDrawNumIndexes[tess.multiDrawPrimitives];
- tess.multiDrawFirstIndex[mergeForward] = tess.multiDrawFirstIndex[tess.multiDrawPrimitives];
- }
- backEnd.pc.c_multidrawsMerged += 2;
- }
- else if (mergeBack == -1 && mergeForward == -1)
- {
- tess.multiDrawNumIndexes[tess.multiDrawPrimitives] = numIndexes;
- tess.multiDrawFirstIndex[tess.multiDrawPrimitives] = firstIndexOffset;
- tess.multiDrawLastIndex[tess.multiDrawPrimitives] = lastIndexOffset;
- tess.multiDrawMinIndex[tess.multiDrawPrimitives] = minIndex;
- tess.multiDrawMaxIndex[tess.multiDrawPrimitives] = maxIndex;
- tess.multiDrawPrimitives++;
- }
-
- backEnd.pc.c_multidraws++;
-
- tess.numIndexes += numIndexes;
- tess.numVertexes += numVerts;
-
- return qtrue;
-}
-
-/*
-=============
-RB_SurfaceTriangles
-=============
-*/
-static void RB_SurfaceTriangles( srfTriangles_t *srf ) {
- if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3,
- srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) )
- {
- return;
- }
-
- RB_SurfaceHelper(srf->numVerts, srf->verts, srf->numTriangles,
- srf->triangles, srf->dlightBits, srf->pshadowBits);
-}
-
-
-
-/*
-==============
-RB_SurfaceBeam
-==============
-*/
-static void RB_SurfaceBeam( void )
-{
-#define NUM_BEAM_SEGS 6
- refEntity_t *e;
- int i;
- vec3_t perpvec;
- vec3_t direction, normalized_direction;
- vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
- vec3_t oldorigin, origin;
-
- e = &backEnd.currentEntity->e;
-
- oldorigin[0] = e->oldorigin[0];
- oldorigin[1] = e->oldorigin[1];
- oldorigin[2] = e->oldorigin[2];
-
- origin[0] = e->origin[0];
- origin[1] = e->origin[1];
- origin[2] = e->origin[2];
-
- normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
- normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
- normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];
-
- if ( VectorNormalize( normalized_direction ) == 0 )
- return;
-
- PerpendicularVector( perpvec, normalized_direction );
-
- VectorScale( perpvec, 4, perpvec );
-
- for ( i = 0; i < NUM_BEAM_SEGS ; i++ )
- {
- RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i );
-// VectorAdd( start_points[i], origin, start_points[i] );
- VectorAdd( start_points[i], direction, end_points[i] );
- }
-
- GL_Bind( tr.whiteImage );
-
- GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
-
- // FIXME: Quake3 doesn't use this, so I never tested it
- tess.numVertexes = 0;
- tess.numIndexes = 0;
- tess.firstIndex = 0;
- tess.minIndex = 0;
- tess.maxIndex = 0;
-
- for ( i = 0; i <= NUM_BEAM_SEGS; i++ ) {
- VectorCopy(start_points[ i % NUM_BEAM_SEGS ], tess.xyz[tess.numVertexes++]);
- VectorCopy(end_points [ i % NUM_BEAM_SEGS ], tess.xyz[tess.numVertexes++]);
- }
-
- for ( i = 0; i < NUM_BEAM_SEGS; i++ ) {
- tess.indexes[tess.numIndexes++] = i * 2;
- tess.indexes[tess.numIndexes++] = (i + 1) * 2;
- tess.indexes[tess.numIndexes++] = 1 + i * 2;
-
- tess.indexes[tess.numIndexes++] = 1 + i * 2;
- tess.indexes[tess.numIndexes++] = (i + 1) * 2;
- tess.indexes[tess.numIndexes++] = 1 + (i + 1) * 2;
- }
-
- tess.minIndex = 0;
- tess.maxIndex = tess.numVertexes;
-
- // FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function
- RB_UpdateVBOs(ATTR_POSITION);
-
- {
- shaderProgram_t *sp = &tr.textureColorShader;
- vec4_t color;
-
- GLSL_VertexAttribsState(ATTR_POSITION);
- GLSL_BindProgram(sp);
-
- GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection);
-
- color[0] = 1.0f;
- color[1] = 0.0f;
- color[2] = 0.0f;
- color[3] = 1.0f;
- GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color);
- }
-
- R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex);
-
- tess.numIndexes = 0;
- tess.numVertexes = 0;
- tess.firstIndex = 0;
- tess.minIndex = 0;
- tess.maxIndex = 0;
-}
-
-//================================================================================
-
-static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, float len, float spanWidth )
-{
- float spanWidth2;
- int vbase;
- float t = len / 256.0f;
-
- vbase = tess.numVertexes;
-
- spanWidth2 = -spanWidth;
-
- // FIXME: use quad stamp?
- VectorMA( start, spanWidth, up, tess.xyz[tess.numVertexes] );
- tess.texCoords[tess.numVertexes][0][0] = 0;
- tess.texCoords[tess.numVertexes][0][1] = 0;
- tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 0.25 / 255.0f;
- tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 0.25 / 255.0f;
- tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 0.25 / 255.0f;
- tess.numVertexes++;
-
- VectorMA( start, spanWidth2, up, tess.xyz[tess.numVertexes] );
- tess.texCoords[tess.numVertexes][0][0] = 0;
- tess.texCoords[tess.numVertexes][0][1] = 1;
- tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] / 255.0f;
- tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] / 255.0f;
- tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] / 255.0f;
- tess.numVertexes++;
-
- VectorMA( end, spanWidth, up, tess.xyz[tess.numVertexes] );
-
- tess.texCoords[tess.numVertexes][0][0] = t;
- tess.texCoords[tess.numVertexes][0][1] = 0;
- tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] / 255.0f;
- tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] / 255.0f;
- tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] / 255.0f;
- tess.numVertexes++;
-
- VectorMA( end, spanWidth2, up, tess.xyz[tess.numVertexes] );
- tess.texCoords[tess.numVertexes][0][0] = t;
- tess.texCoords[tess.numVertexes][0][1] = 1;
- tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] / 255.0f;
- tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] / 255.0f;
- tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] / 255.0f;
- tess.numVertexes++;
-
- tess.indexes[tess.numIndexes++] = vbase;
- tess.indexes[tess.numIndexes++] = vbase + 1;
- tess.indexes[tess.numIndexes++] = vbase + 2;
-
- tess.indexes[tess.numIndexes++] = vbase + 2;
- tess.indexes[tess.numIndexes++] = vbase + 1;
- tess.indexes[tess.numIndexes++] = vbase + 3;
-}
-
-static void DoRailDiscs( int numSegs, const vec3_t start, const vec3_t dir, const vec3_t right, const vec3_t up )
-{
- int i;
- vec3_t pos[4];
- vec3_t v;
- int spanWidth = r_railWidth->integer;
- float c, s;
- float scale;
-
- if ( numSegs > 1 )
- numSegs--;
- if ( !numSegs )
- return;
-
- scale = 0.25;
-
- for ( i = 0; i < 4; i++ )
- {
- c = cos( DEG2RAD( 45 + i * 90 ) );
- s = sin( DEG2RAD( 45 + i * 90 ) );
- v[0] = ( right[0] * c + up[0] * s ) * scale * spanWidth;
- v[1] = ( right[1] * c + up[1] * s ) * scale * spanWidth;
- v[2] = ( right[2] * c + up[2] * s ) * scale * spanWidth;
- VectorAdd( start, v, pos[i] );
-
- if ( numSegs > 1 )
- {
- // offset by 1 segment if we're doing a long distance shot
- VectorAdd( pos[i], dir, pos[i] );
- }
- }
-
- for ( i = 0; i < numSegs; i++ )
- {
- int j;
-
- RB_CHECKOVERFLOW( 4, 6 );
-
- for ( j = 0; j < 4; j++ )
- {
- VectorCopy( pos[j], tess.xyz[tess.numVertexes] );
- tess.texCoords[tess.numVertexes][0][0] = ( j < 2 );
- tess.texCoords[tess.numVertexes][0][1] = ( j && j != 3 );
- tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] / 255.0f;
- tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] / 255.0f;
- tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] / 255.0f;
- tess.numVertexes++;
-
- VectorAdd( pos[j], dir, pos[j] );
- }
-
- tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 0;
- tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1;
- tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3;
- tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 3;
- tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 1;
- tess.indexes[tess.numIndexes++] = tess.numVertexes - 4 + 2;
- }
-}
-
-/*
-** RB_SurfaceRailRinges
-*/
-static void RB_SurfaceRailRings( void ) {
- refEntity_t *e;
- int numSegs;
- int len;
- vec3_t vec;
- vec3_t right, up;
- vec3_t start, end;
-
- e = &backEnd.currentEntity->e;
-
- VectorCopy( e->oldorigin, start );
- VectorCopy( e->origin, end );
-
- // compute variables
- VectorSubtract( end, start, vec );
- len = VectorNormalize( vec );
- MakeNormalVectors( vec, right, up );
- numSegs = ( len ) / r_railSegmentLength->value;
- if ( numSegs <= 0 ) {
- numSegs = 1;
- }
-
- VectorScale( vec, r_railSegmentLength->value, vec );
-
- DoRailDiscs( numSegs, start, vec, right, up );
-}
-
-/*
-** RB_SurfaceRailCore
-*/
-static void RB_SurfaceRailCore( void ) {
- refEntity_t *e;
- int len;
- vec3_t right;
- vec3_t vec;
- vec3_t start, end;
- vec3_t v1, v2;
-
- e = &backEnd.currentEntity->e;
-
- VectorCopy( e->oldorigin, start );
- VectorCopy( e->origin, end );
-
- VectorSubtract( end, start, vec );
- len = VectorNormalize( vec );
-
- // compute side vector
- VectorSubtract( start, backEnd.viewParms.or.origin, v1 );
- VectorNormalize( v1 );
- VectorSubtract( end, backEnd.viewParms.or.origin, v2 );
- VectorNormalize( v2 );
- CrossProduct( v1, v2, right );
- VectorNormalize( right );
-
- DoRailCore( start, end, right, len, r_railCoreWidth->integer );
-}
-
-/*
-** RB_SurfaceLightningBolt
-*/
-static void RB_SurfaceLightningBolt( void ) {
- refEntity_t *e;
- int len;
- vec3_t right;
- vec3_t vec;
- vec3_t start, end;
- vec3_t v1, v2;
- int i;
-
- e = &backEnd.currentEntity->e;
-
- VectorCopy( e->oldorigin, end );
- VectorCopy( e->origin, start );
-
- // compute variables
- VectorSubtract( end, start, vec );
- len = VectorNormalize( vec );
-
- // compute side vector
- VectorSubtract( start, backEnd.viewParms.or.origin, v1 );
- VectorNormalize( v1 );
- VectorSubtract( end, backEnd.viewParms.or.origin, v2 );
- VectorNormalize( v2 );
- CrossProduct( v1, v2, right );
- VectorNormalize( right );
-
- for ( i = 0 ; i < 4 ; i++ ) {
- vec3_t temp;
-
- DoRailCore( start, end, right, len, 8 );
- RotatePointAroundVector( temp, vec, right, 45 );
- VectorCopy( temp, right );
- }
-}
-
-/*
-** VectorArrayNormalize
-*
-* The inputs to this routing seem to always be close to length = 1.0 (about 0.6 to 2.0)
-* This means that we don't have to worry about zero length or enormously long vectors.
-*/
-static void VectorArrayNormalize(vec4_t *normals, unsigned int count)
-{
-// assert(count);
-
-#if idppc
- {
- register float half = 0.5;
- register float one = 1.0;
- float *components = (float *)normals;
-
- // Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction,
- // runs *much* faster than calling sqrt(). We'll use a single Newton-Raphson
- // refinement step to get a little more precision. This seems to yeild results
- // that are correct to 3 decimal places and usually correct to at least 4 (sometimes 5).
- // (That is, for the given input range of about 0.6 to 2.0).
- do {
- float x, y, z;
- float B, y0, y1;
-
- x = components[0];
- y = components[1];
- z = components[2];
- components += 4;
- B = x*x + y*y + z*z;
-
-#ifdef __GNUC__
- asm("frsqrte %0,%1" : "=f" (y0) : "f" (B));
-#else
- y0 = __frsqrte(B);
-#endif
- y1 = y0 + half*y0*(one - B*y0*y0);
-
- x = x * y1;
- y = y * y1;
- components[-4] = x;
- z = z * y1;
- components[-3] = y;
- components[-2] = z;
- } while(count--);
- }
-#else // No assembly version for this architecture, or C_ONLY defined
- // given the input, it's safe to call VectorNormalizeFast
- while (count--) {
- VectorNormalizeFast(normals[0]);
- normals++;
- }
-#endif
-
-}
-
-
-
-/*
-** LerpMeshVertexes
-*/
-#if idppc_altivec
-static void LerpMeshVertexes_altivec(md3Surface_t *surf, float backlerp)
-{
- short *oldXyz, *newXyz, *oldNormals, *newNormals;
- float *outXyz, *outNormal;
- float oldXyzScale QALIGN(16);
- float newXyzScale QALIGN(16);
- float oldNormalScale QALIGN(16);
- float newNormalScale QALIGN(16);
- int vertNum;
- unsigned lat, lng;
- int numVerts;
-
- outXyz = tess.xyz[tess.numVertexes];
- outNormal = tess.normal[tess.numVertexes];
-
- newXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
- + (backEnd.currentEntity->e.frame * surf->numVerts * 4);
- newNormals = newXyz + 3;
-
- newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
- newNormalScale = 1.0 - backlerp;
-
- numVerts = surf->numVerts;
-
- if ( backlerp == 0 ) {
- vector signed short newNormalsVec0;
- vector signed short newNormalsVec1;
- vector signed int newNormalsIntVec;
- vector float newNormalsFloatVec;
- vector float newXyzScaleVec;
- vector unsigned char newNormalsLoadPermute;
- vector unsigned char newNormalsStorePermute;
- vector float zero;
-
- newNormalsStorePermute = vec_lvsl(0,(float *)&newXyzScaleVec);
- newXyzScaleVec = *(vector float *)&newXyzScale;
- newXyzScaleVec = vec_perm(newXyzScaleVec,newXyzScaleVec,newNormalsStorePermute);
- newXyzScaleVec = vec_splat(newXyzScaleVec,0);
- newNormalsLoadPermute = vec_lvsl(0,newXyz);
- newNormalsStorePermute = vec_lvsr(0,outXyz);
- zero = (vector float)vec_splat_s8(0);
- //
- // just copy the vertexes
- //
- for (vertNum=0 ; vertNum < numVerts ; vertNum++,
- newXyz += 4, newNormals += 4,
- outXyz += 4, outNormal += 4)
- {
- newNormalsLoadPermute = vec_lvsl(0,newXyz);
- newNormalsStorePermute = vec_lvsr(0,outXyz);
- newNormalsVec0 = vec_ld(0,newXyz);
- newNormalsVec1 = vec_ld(16,newXyz);
- newNormalsVec0 = vec_perm(newNormalsVec0,newNormalsVec1,newNormalsLoadPermute);
- newNormalsIntVec = vec_unpackh(newNormalsVec0);
- newNormalsFloatVec = vec_ctf(newNormalsIntVec,0);
- newNormalsFloatVec = vec_madd(newNormalsFloatVec,newXyzScaleVec,zero);
- newNormalsFloatVec = vec_perm(newNormalsFloatVec,newNormalsFloatVec,newNormalsStorePermute);
- //outXyz[0] = newXyz[0] * newXyzScale;
- //outXyz[1] = newXyz[1] * newXyzScale;
- //outXyz[2] = newXyz[2] * newXyzScale;
-
- lat = ( newNormals[0] >> 8 ) & 0xff;
- lng = ( newNormals[0] & 0xff );
- lat *= (FUNCTABLE_SIZE/256);
- lng *= (FUNCTABLE_SIZE/256);
-
- // decode X as cos( lat ) * sin( long )
- // decode Y as sin( lat ) * sin( long )
- // decode Z as cos( long )
-
- outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
- outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
- outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
-
- vec_ste(newNormalsFloatVec,0,outXyz);
- vec_ste(newNormalsFloatVec,4,outXyz);
- vec_ste(newNormalsFloatVec,8,outXyz);
- }
- } else {
- //
- // interpolate and copy the vertex and normal
- //
- oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
- + (backEnd.currentEntity->e.oldframe * surf->numVerts * 4);
- oldNormals = oldXyz + 3;
-
- oldXyzScale = MD3_XYZ_SCALE * backlerp;
- oldNormalScale = backlerp;
-
- for (vertNum=0 ; vertNum < numVerts ; vertNum++,
- oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4,
- outXyz += 4, outNormal += 4)
- {
- vec3_t uncompressedOldNormal, uncompressedNewNormal;
-
- // interpolate the xyz
- outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale;
- outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale;
- outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale;
-
- // FIXME: interpolate lat/long instead?
- lat = ( newNormals[0] >> 8 ) & 0xff;
- lng = ( newNormals[0] & 0xff );
- lat *= 4;
- lng *= 4;
- uncompressedNewNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
- uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
- uncompressedNewNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
-
- lat = ( oldNormals[0] >> 8 ) & 0xff;
- lng = ( oldNormals[0] & 0xff );
- lat *= 4;
- lng *= 4;
-
- uncompressedOldNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
- uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
- uncompressedOldNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
-
- outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale;
- outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale;
- outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale;
-
-// VectorNormalize (outNormal);
- }
- VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts);
- }
-}
-#endif
-
-static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp)
-{
-#if 0
- short *oldXyz, *newXyz, *oldNormals, *newNormals;
- float *outXyz, *outNormal;
- float oldXyzScale, newXyzScale;
- float oldNormalScale, newNormalScale;
- int vertNum;
- unsigned lat, lng;
- int numVerts;
-
- outXyz = tess.xyz[tess.numVertexes];
- outNormal = tess.normal[tess.numVertexes];
-
- newXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
- + (backEnd.currentEntity->e.frame * surf->numVerts * 4);
- newNormals = newXyz + 3;
-
- newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp);
- newNormalScale = 1.0 - backlerp;
-
- numVerts = surf->numVerts;
-
- if ( backlerp == 0 ) {
- //
- // just copy the vertexes
- //
- for (vertNum=0 ; vertNum < numVerts ; vertNum++,
- newXyz += 4, newNormals += 4,
- outXyz += 4, outNormal += 4)
- {
-
- outXyz[0] = newXyz[0] * newXyzScale;
- outXyz[1] = newXyz[1] * newXyzScale;
- outXyz[2] = newXyz[2] * newXyzScale;
-
- lat = ( newNormals[0] >> 8 ) & 0xff;
- lng = ( newNormals[0] & 0xff );
- lat *= (FUNCTABLE_SIZE/256);
- lng *= (FUNCTABLE_SIZE/256);
-
- // decode X as cos( lat ) * sin( long )
- // decode Y as sin( lat ) * sin( long )
- // decode Z as cos( long )
-
- outNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
- outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
- outNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
- }
- } else {
- //
- // interpolate and copy the vertex and normal
- //
- oldXyz = (short *)((byte *)surf + surf->ofsXyzNormals)
- + (backEnd.currentEntity->e.oldframe * surf->numVerts * 4);
- oldNormals = oldXyz + 3;
-
- oldXyzScale = MD3_XYZ_SCALE * backlerp;
- oldNormalScale = backlerp;
-
- for (vertNum=0 ; vertNum < numVerts ; vertNum++,
- oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4,
- outXyz += 4, outNormal += 4)
- {
- vec3_t uncompressedOldNormal, uncompressedNewNormal;
-
- // interpolate the xyz
- outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale;
- outXyz[1] = oldXyz[1] * oldXyzScale + newXyz[1] * newXyzScale;
- outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale;
-
- // FIXME: interpolate lat/long instead?
- lat = ( newNormals[0] >> 8 ) & 0xff;
- lng = ( newNormals[0] & 0xff );
- lat *= 4;
- lng *= 4;
- uncompressedNewNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
- uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
- uncompressedNewNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
-
- lat = ( oldNormals[0] >> 8 ) & 0xff;
- lng = ( oldNormals[0] & 0xff );
- lat *= 4;
- lng *= 4;
-
- uncompressedOldNormal[0] = tr.sinTable[(lat+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK] * tr.sinTable[lng];
- uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng];
- uncompressedOldNormal[2] = tr.sinTable[(lng+(FUNCTABLE_SIZE/4))&FUNCTABLE_MASK];
-
- outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale;
- outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale;
- outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale;
-
-// VectorNormalize (outNormal);
- }
- VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], numVerts);
- }
-#endif
- float *outXyz, *outNormal;
- mdvVertex_t *newVerts;
- int vertNum;
-
- newVerts = surf->verts + backEnd.currentEntity->e.frame * surf->numVerts;
-
- outXyz = tess.xyz[tess.numVertexes];
- outNormal = tess.normal[tess.numVertexes];
-
- if (backlerp == 0)
- {
- //
- // just copy the vertexes
- //
-
- for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
- {
- VectorCopy(newVerts->xyz, outXyz);
- VectorCopy(newVerts->normal, outNormal);
- newVerts++;
- outXyz += 4;
- outNormal += 4;
- }
- }
- else
- {
- //
- // interpolate and copy the vertex and normal
- //
-
- mdvVertex_t *oldVerts;
-
- oldVerts = surf->verts + backEnd.currentEntity->e.oldframe * surf->numVerts;
-
- for (vertNum=0 ; vertNum < surf->numVerts ; vertNum++)
- {
- VectorLerp(backlerp, newVerts->xyz, oldVerts->xyz, outXyz);
- VectorLerp(backlerp, newVerts->normal, oldVerts->normal, outNormal);
- //VectorNormalize(outNormal);
- newVerts++;
- oldVerts++;
- outXyz += 4;
- outNormal += 4;
- }
- VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes], surf->numVerts);
- }
-
-}
-
-static void LerpMeshVertexes(mdvSurface_t *surf, float backlerp)
-{
-#if 0
-#if idppc_altivec
- if (com_altivec->integer) {
- // must be in a seperate function or G3 systems will crash.
- LerpMeshVertexes_altivec( surf, backlerp );
- return;
- }
-#endif // idppc_altivec
-#endif
- LerpMeshVertexes_scalar( surf, backlerp );
-}
-
-
-/*
-=============
-RB_SurfaceMesh
-=============
-*/
-static void RB_SurfaceMesh(mdvSurface_t *surface) {
- int j;
- float backlerp;
- srfTriangle_t *triangles;
- mdvSt_t *texCoords;
- int indexes;
- int Bob, Doug;
- int numVerts;
-
- if ( backEnd.currentEntity->e.oldframe == backEnd.currentEntity->e.frame ) {
- backlerp = 0;
- } else {
- backlerp = backEnd.currentEntity->e.backlerp;
- }
-
- RB_CHECKOVERFLOW( surface->numVerts, surface->numTriangles*3 );
-
- LerpMeshVertexes (surface, backlerp);
-
- triangles = surface->triangles;
- indexes = surface->numTriangles * 3;
- Bob = tess.numIndexes;
- Doug = tess.numVertexes;
- for (j = 0 ; j < surface->numTriangles ; j++) {
- tess.indexes[Bob + j*3 + 0] = Doug + triangles[j].indexes[0];
- tess.indexes[Bob + j*3 + 1] = Doug + triangles[j].indexes[1];
- tess.indexes[Bob + j*3 + 2] = Doug + triangles[j].indexes[2];
- }
- tess.numIndexes += indexes;
-
- texCoords = surface->st;
-
- numVerts = surface->numVerts;
- for ( j = 0; j < numVerts; j++ ) {
- tess.texCoords[Doug + j][0][0] = texCoords[j].st[0];
- tess.texCoords[Doug + j][0][1] = texCoords[j].st[1];
- // FIXME: fill in lightmapST for completeness?
- }
-
- tess.numVertexes += surface->numVerts;
-
-}
-
-
-/*
-==============
-RB_SurfaceFace
-==============
-*/
-static void RB_SurfaceFace( srfSurfaceFace_t *srf ) {
- if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3,
- srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) )
- {
- return;
- }
-
- RB_SurfaceHelper(srf->numVerts, srf->verts, srf->numTriangles,
- srf->triangles, srf->dlightBits, srf->pshadowBits);
-}
-
-
-static float LodErrorForVolume( vec3_t local, float radius ) {
- vec3_t world;
- float d;
-
- // never let it go negative
- if ( r_lodCurveError->value < 0 ) {
- return 0;
- }
-
- world[0] = local[0] * backEnd.or.axis[0][0] + local[1] * backEnd.or.axis[1][0] +
- local[2] * backEnd.or.axis[2][0] + backEnd.or.origin[0];
- world[1] = local[0] * backEnd.or.axis[0][1] + local[1] * backEnd.or.axis[1][1] +
- local[2] * backEnd.or.axis[2][1] + backEnd.or.origin[1];
- world[2] = local[0] * backEnd.or.axis[0][2] + local[1] * backEnd.or.axis[1][2] +
- local[2] * backEnd.or.axis[2][2] + backEnd.or.origin[2];
-
- VectorSubtract( world, backEnd.viewParms.or.origin, world );
- d = DotProduct( world, backEnd.viewParms.or.axis[0] );
-
- if ( d < 0 ) {
- d = -d;
- }
- d -= radius;
- if ( d < 1 ) {
- d = 1;
- }
-
- return r_lodCurveError->value / d;
-}
-
-/*
-=============
-RB_SurfaceGrid
-
-Just copy the grid of points and triangulate
-=============
-*/
-static void RB_SurfaceGrid( srfGridMesh_t *srf ) {
- int i, j;
- float *xyz;
- float *texCoords, *lightCoords;
- float *normal;
-#ifdef USE_VERT_TANGENT_SPACE
- float *tangent, *bitangent;
-#endif
- float *color, *lightdir;
- srfVert_t *dv;
- int rows, irows, vrows;
- int used;
- int widthTable[MAX_GRID_SIZE];
- int heightTable[MAX_GRID_SIZE];
- float lodError;
- int lodWidth, lodHeight;
- int numVertexes;
- int dlightBits;
- int pshadowBits;
- //int *vDlightBits;
-
- if( RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numTriangles * 3,
- srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) )
- {
- return;
- }
-
- dlightBits = srf->dlightBits;
- tess.dlightBits |= dlightBits;
-
- pshadowBits = srf->pshadowBits;
- tess.pshadowBits |= pshadowBits;
-
- // determine the allowable discrepance
- lodError = LodErrorForVolume( srf->lodOrigin, srf->lodRadius );
-
- // determine which rows and columns of the subdivision
- // we are actually going to use
- widthTable[0] = 0;
- lodWidth = 1;
- for ( i = 1 ; i < srf->width-1 ; i++ ) {
- if ( srf->widthLodError[i] <= lodError ) {
- widthTable[lodWidth] = i;
- lodWidth++;
- }
- }
- widthTable[lodWidth] = srf->width-1;
- lodWidth++;
-
- heightTable[0] = 0;
- lodHeight = 1;
- for ( i = 1 ; i < srf->height-1 ; i++ ) {
- if ( srf->heightLodError[i] <= lodError ) {
- heightTable[lodHeight] = i;
- lodHeight++;
- }
- }
- heightTable[lodHeight] = srf->height-1;
- lodHeight++;
-
-
- // very large grids may have more points or indexes than can be fit
- // in the tess structure, so we may have to issue it in multiple passes
-
- used = 0;
- while ( used < lodHeight - 1 ) {
- // see how many rows of both verts and indexes we can add without overflowing
- do {
- vrows = ( SHADER_MAX_VERTEXES - tess.numVertexes ) / lodWidth;
- irows = ( SHADER_MAX_INDEXES - tess.numIndexes ) / ( lodWidth * 6 );
-
- // if we don't have enough space for at least one strip, flush the buffer
- if ( vrows < 2 || irows < 1 ) {
- RB_EndSurface();
- RB_BeginSurface(tess.shader, tess.fogNum );
- } else {
- break;
- }
- } while ( 1 );
-
- rows = irows;
- if ( vrows < irows + 1 ) {
- rows = vrows - 1;
- }
- if ( used + rows > lodHeight ) {
- rows = lodHeight - used;
- }
-
- numVertexes = tess.numVertexes;
-
- xyz = tess.xyz[numVertexes];
- normal = tess.normal[numVertexes];
-#ifdef USE_VERT_TANGENT_SPACE
- tangent = tess.tangent[numVertexes];
- bitangent = tess.bitangent[numVertexes];
-#endif
- texCoords = tess.texCoords[numVertexes][0];
- lightCoords = tess.texCoords[numVertexes][1];
- color = tess.vertexColors[numVertexes];
- lightdir = tess.lightdir[numVertexes];
- //vDlightBits = &tess.vertexDlightBits[numVertexes];
-
- for ( i = 0 ; i < rows ; i++ ) {
- for ( j = 0 ; j < lodWidth ; j++ ) {
- dv = srf->verts + heightTable[ used + i ] * srf->width
- + widthTable[ j ];
-
- if ( tess.shader->vertexAttribs & ATTR_POSITION )
- {
- VectorCopy(dv->xyz, xyz);
- xyz += 4;
- }
-
- if ( tess.shader->vertexAttribs & ATTR_NORMAL )
- {
- VectorCopy(dv->normal, normal);
- normal += 4;
- }
-
-#ifdef USE_VERT_TANGENT_SPACE
- if ( tess.shader->vertexAttribs & ATTR_TANGENT )
- {
- VectorCopy(dv->tangent, tangent);
- tangent += 4;
- }
-
- if ( tess.shader->vertexAttribs & ATTR_BITANGENT )
- {
- VectorCopy(dv->bitangent, bitangent);
- bitangent += 4;
- }
-#endif
- if ( tess.shader->vertexAttribs & ATTR_TEXCOORD )
- {
- VectorCopy2(dv->st, texCoords);
- texCoords += 4;
- }
-
- if ( tess.shader->vertexAttribs & ATTR_LIGHTCOORD )
- {
- VectorCopy2(dv->lightmap, lightCoords);
- lightCoords += 4;
- }
-
- if ( tess.shader->vertexAttribs & ATTR_COLOR )
- {
- VectorCopy4(dv->vertexColors, color);
- color += 4;
- }
-
- if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION )
- {
- VectorCopy(dv->lightdir, lightdir);
- lightdir += 4;
- }
-
- //*vDlightBits++ = dlightBits;
- }
- }
-
-
- // add the indexes
- {
- int numIndexes;
- int w, h;
-
- h = rows - 1;
- w = lodWidth - 1;
- numIndexes = tess.numIndexes;
- for (i = 0 ; i < h ; i++) {
- for (j = 0 ; j < w ; j++) {
- int v1, v2, v3, v4;
-
- // vertex order to be reckognized as tristrips
- v1 = numVertexes + i*lodWidth + j + 1;
- v2 = v1 - 1;
- v3 = v2 + lodWidth;
- v4 = v3 + 1;
-
- tess.indexes[numIndexes] = v2;
- tess.indexes[numIndexes+1] = v3;
- tess.indexes[numIndexes+2] = v1;
-
- tess.indexes[numIndexes+3] = v1;
- tess.indexes[numIndexes+4] = v3;
- tess.indexes[numIndexes+5] = v4;
- numIndexes += 6;
- }
- }
-
- tess.numIndexes = numIndexes;
- }
-
- tess.numVertexes += rows * lodWidth;
-
- used += rows - 1;
- }
-}
-
-
-/*
-===========================================================================
-
-NULL MODEL
-
-===========================================================================
-*/
-
-/*
-===================
-RB_SurfaceAxis
-
-Draws x/y/z lines from the origin for orientation debugging
-===================
-*/
-static void RB_SurfaceAxis( void ) {
- // FIXME: implement this
-#if 0
- GL_Bind( tr.whiteImage );
- qglLineWidth( 3 );
- qglBegin( GL_LINES );
- qglColor3f( 1,0,0 );
- qglVertex3f( 0,0,0 );
- qglVertex3f( 16,0,0 );
- qglColor3f( 0,1,0 );
- qglVertex3f( 0,0,0 );
- qglVertex3f( 0,16,0 );
- qglColor3f( 0,0,1 );
- qglVertex3f( 0,0,0 );
- qglVertex3f( 0,0,16 );
- qglEnd();
- qglLineWidth( 1 );
-#endif
-}
-
-//===========================================================================
-
-/*
-====================
-RB_SurfaceEntity
-
-Entities that have a single procedurally generated surface
-====================
-*/
-static void RB_SurfaceEntity( surfaceType_t *surfType ) {
- switch( backEnd.currentEntity->e.reType ) {
- case RT_SPRITE:
- RB_SurfaceSprite();
- break;
- case RT_BEAM:
- RB_SurfaceBeam();
- break;
- case RT_RAIL_CORE:
- RB_SurfaceRailCore();
- break;
- case RT_RAIL_RINGS:
- RB_SurfaceRailRings();
- break;
- case RT_LIGHTNING:
- RB_SurfaceLightningBolt();
- break;
- default:
- RB_SurfaceAxis();
- break;
- }
- return;
-}
-
-static void RB_SurfaceBad( surfaceType_t *surfType ) {
- ri.Printf( PRINT_ALL, "Bad surface tesselated.\n" );
-}
-
-static void RB_SurfaceFlare(srfFlare_t *surf)
-{
- if (r_flares->integer)
- RB_AddFlare(surf, tess.fogNum, surf->origin, surf->color, surf->normal);
-}
-
-static void RB_SurfaceVBOMesh(srfVBOMesh_t * srf)
-{
- RB_SurfaceHelperVBO (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, srf->firstIndex,
- srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qfalse );
-}
-
-void RB_SurfaceVBOMDVMesh(srfVBOMDVMesh_t * surface)
-{
- //mdvModel_t *mdvModel;
- //mdvSurface_t *mdvSurface;
- refEntity_t *refEnt;
-
- GLimp_LogComment("--- RB_SurfaceVBOMDVMesh ---\n");
-
- if(!surface->vbo || !surface->ibo)
- return;
-
- //RB_CheckVBOandIBO(surface->vbo, surface->ibo);
- RB_EndSurface();
- RB_BeginSurface(tess.shader, tess.fogNum);
-
- R_BindVBO(surface->vbo);
- R_BindIBO(surface->ibo);
-
- tess.useInternalVBO = qfalse;
-
- tess.numIndexes += surface->numIndexes;
- tess.numVertexes += surface->numVerts;
- tess.minIndex = surface->minIndex;
- tess.maxIndex = surface->maxIndex;
-
- //mdvModel = surface->mdvModel;
- //mdvSurface = surface->mdvSurface;
-
- refEnt = &backEnd.currentEntity->e;
-
- if(refEnt->oldframe == refEnt->frame)
- {
- glState.vertexAttribsInterpolation = 0;
- }
- else
- {
- glState.vertexAttribsInterpolation = refEnt->backlerp;
- }
-
- glState.vertexAttribsOldFrame = refEnt->oldframe;
- glState.vertexAttribsNewFrame = refEnt->frame;
-
- RB_EndSurface();
-
- // So we don't lerp surfaces that shouldn't be lerped
- glState.vertexAttribsInterpolation = 0;
-}
-
-static void RB_SurfaceDisplayList( srfDisplayList_t *surf ) {
- // all apropriate state must be set in RB_BeginSurface
- // this isn't implemented yet...
- qglCallList( surf->listNum );
-}
-
-static void RB_SurfaceSkip( void *surf ) {
-}
-
-
-void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = {
- (void(*)(void*))RB_SurfaceBad, // SF_BAD,
- (void(*)(void*))RB_SurfaceSkip, // SF_SKIP,
- (void(*)(void*))RB_SurfaceFace, // SF_FACE,
- (void(*)(void*))RB_SurfaceGrid, // SF_GRID,
- (void(*)(void*))RB_SurfaceTriangles, // SF_TRIANGLES,
- (void(*)(void*))RB_SurfacePolychain, // SF_POLY,
- (void(*)(void*))RB_SurfaceMesh, // SF_MDV,
- (void(*)(void*))RB_SurfaceAnim, // SF_MD4,
-#ifdef RAVENMD4
- (void(*)(void*))RB_MDRSurfaceAnim, // SF_MDR,
-#endif
- (void(*)(void*))RB_IQMSurfaceAnim, // SF_IQM,
- (void(*)(void*))RB_SurfaceFlare, // SF_FLARE,
- (void(*)(void*))RB_SurfaceEntity, // SF_ENTITY
- (void(*)(void*))RB_SurfaceDisplayList, // SF_DISPLAY_LIST
- (void(*)(void*))RB_SurfaceVBOMesh, // SF_VBO_MESH,
- (void(*)(void*))RB_SurfaceVBOMDVMesh, // SF_VBO_MDVMESH
-};
diff --git a/src/rend2/tr_vbo.c b/src/rend2/tr_vbo.c
deleted file mode 100644
index 483df2e3..00000000
--- a/src/rend2/tr_vbo.c
+++ /dev/null
@@ -1,928 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 2007-2009 Robert Beckebans <trebor_7@users.sourceforge.net>
-
-This file is part of XreaL source code.
-
-XreaL source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-XreaL source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with XreaL source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-// tr_vbo.c
-#include "tr_local.h"
-
-/*
-============
-R_CreateVBO
-============
-*/
-VBO_t *R_CreateVBO(const char *name, byte * vertexes, int vertexesSize, vboUsage_t usage)
-{
- VBO_t *vbo;
- int glUsage;
-
- switch (usage)
- {
- case VBO_USAGE_STATIC:
- glUsage = GL_STATIC_DRAW_ARB;
- break;
-
- case VBO_USAGE_DYNAMIC:
- glUsage = GL_DYNAMIC_DRAW_ARB;
- break;
-
- default:
- Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage);
- return NULL;
- }
-
- if(strlen(name) >= MAX_QPATH)
- {
- ri.Error(ERR_DROP, "R_CreateVBO: \"%s\" is too long", name);
- }
-
- if ( tr.numVBOs == MAX_VBOS ) {
- ri.Error( ERR_DROP, "R_CreateVBO: MAX_VBOS hit");
- }
-
- R_IssuePendingRenderCommands();
-
- vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low);
- tr.numVBOs++;
-
- memset(vbo, 0, sizeof(*vbo));
-
- Q_strncpyz(vbo->name, name, sizeof(vbo->name));
-
- vbo->vertexesSize = vertexesSize;
-
- qglGenBuffersARB(1, &vbo->vertexesVBO);
-
- qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO);
- qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexesSize, vertexes, glUsage);
-
- qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
-
- glState.currentVBO = NULL;
-
- GL_CheckErrors();
-
- return vbo;
-}
-
-/*
-============
-R_CreateVBO2
-============
-*/
-VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * verts, unsigned int stateBits, vboUsage_t usage)
-{
- VBO_t *vbo;
- int i;
-
- byte *data;
- int dataSize;
- int dataOfs;
-
- int glUsage;
-
- switch (usage)
- {
- case VBO_USAGE_STATIC:
- glUsage = GL_STATIC_DRAW_ARB;
- break;
-
- case VBO_USAGE_DYNAMIC:
- glUsage = GL_DYNAMIC_DRAW_ARB;
- break;
-
- default:
- Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage);
- return NULL;
- }
-
- if(!numVertexes)
- return NULL;
-
- if(strlen(name) >= MAX_QPATH)
- {
- ri.Error(ERR_DROP, "R_CreateVBO2: \"%s\" is too long", name);
- }
-
- if ( tr.numVBOs == MAX_VBOS ) {
- ri.Error( ERR_DROP, "R_CreateVBO2: MAX_VBOS hit");
- }
-
- R_IssuePendingRenderCommands();
-
- vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low);
- tr.numVBOs++;
-
- memset(vbo, 0, sizeof(*vbo));
-
- Q_strncpyz(vbo->name, name, sizeof(vbo->name));
-
- if (usage == VBO_USAGE_STATIC)
- {
- // since these vertex attributes are never altered, interleave them
- vbo->ofs_xyz = 0;
- dataSize = sizeof(verts[0].xyz);
-
- if(stateBits & ATTR_NORMAL)
- {
- vbo->ofs_normal = dataSize;
- dataSize += sizeof(verts[0].normal);
- }
-
-#ifdef USE_VERT_TANGENT_SPACE
- if(stateBits & ATTR_TANGENT)
- {
- vbo->ofs_tangent = dataSize;
- dataSize += sizeof(verts[0].tangent);
- }
-
- if(stateBits & ATTR_BITANGENT)
- {
- vbo->ofs_bitangent = dataSize;
- dataSize += sizeof(verts[0].bitangent);
- }
-#endif
-
- if(stateBits & ATTR_TEXCOORD)
- {
- vbo->ofs_st = dataSize;
- dataSize += sizeof(verts[0].st);
- }
-
- if(stateBits & ATTR_LIGHTCOORD)
- {
- vbo->ofs_lightmap = dataSize;
- dataSize += sizeof(verts[0].lightmap);
- }
-
- if(stateBits & ATTR_COLOR)
- {
- vbo->ofs_vertexcolor = dataSize;
- dataSize += sizeof(verts[0].vertexColors);
- }
-
- if(stateBits & ATTR_LIGHTDIRECTION)
- {
- vbo->ofs_lightdir = dataSize;
- dataSize += sizeof(verts[0].lightdir);
- }
-
- vbo->stride_xyz = dataSize;
- vbo->stride_normal = dataSize;
-#ifdef USE_VERT_TANGENT_SPACE
- vbo->stride_tangent = dataSize;
- vbo->stride_bitangent = dataSize;
-#endif
- vbo->stride_st = dataSize;
- vbo->stride_lightmap = dataSize;
- vbo->stride_vertexcolor = dataSize;
- vbo->stride_lightdir = dataSize;
-
- // create VBO
- dataSize *= numVertexes;
- data = ri.Hunk_AllocateTempMemory(dataSize);
- dataOfs = 0;
-
- //ri.Printf(PRINT_ALL, "CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor,
- //vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor);
-
- for (i = 0; i < numVertexes; i++)
- {
- // xyz
- memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz));
- dataOfs += sizeof(verts[i].xyz);
-
- // normal
- if(stateBits & ATTR_NORMAL)
- {
- memcpy(data + dataOfs, &verts[i].normal, sizeof(verts[i].normal));
- dataOfs += sizeof(verts[i].normal);
- }
-
-#ifdef USE_VERT_TANGENT_SPACE
- // tangent
- if(stateBits & ATTR_TANGENT)
- {
- memcpy(data + dataOfs, &verts[i].tangent, sizeof(verts[i].tangent));
- dataOfs += sizeof(verts[i].tangent);
- }
-
- // bitangent
- if(stateBits & ATTR_BITANGENT)
- {
- memcpy(data + dataOfs, &verts[i].bitangent, sizeof(verts[i].bitangent));
- dataOfs += sizeof(verts[i].bitangent);
- }
-#endif
-
- // vertex texcoords
- if(stateBits & ATTR_TEXCOORD)
- {
- memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st));
- dataOfs += sizeof(verts[i].st);
- }
-
- // feed vertex lightmap texcoords
- if(stateBits & ATTR_LIGHTCOORD)
- {
- memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap));
- dataOfs += sizeof(verts[i].lightmap);
- }
-
- // feed vertex colors
- if(stateBits & ATTR_COLOR)
- {
- memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors));
- dataOfs += sizeof(verts[i].vertexColors);
- }
-
- // feed vertex light directions
- if(stateBits & ATTR_LIGHTDIRECTION)
- {
- memcpy(data + dataOfs, &verts[i].lightdir, sizeof(verts[i].lightdir));
- dataOfs += sizeof(verts[i].lightdir);
- }
- }
- }
- else
- {
- // since these vertex attributes may be changed, put them in flat arrays
- dataSize = sizeof(verts[0].xyz);
-
- if(stateBits & ATTR_NORMAL)
- {
- dataSize += sizeof(verts[0].normal);
- }
-
-#ifdef USE_VERT_TANGENT_SPACE
- if(stateBits & ATTR_TANGENT)
- {
- dataSize += sizeof(verts[0].tangent);
- }
-
- if(stateBits & ATTR_BITANGENT)
- {
- dataSize += sizeof(verts[0].bitangent);
- }
-#endif
-
- if(stateBits & ATTR_TEXCOORD)
- {
- dataSize += sizeof(verts[0].st);
- }
-
- if(stateBits & ATTR_LIGHTCOORD)
- {
- dataSize += sizeof(verts[0].lightmap);
- }
-
- if(stateBits & ATTR_COLOR)
- {
- dataSize += sizeof(verts[0].vertexColors);
- }
-
- if(stateBits & ATTR_LIGHTDIRECTION)
- {
- dataSize += sizeof(verts[0].lightdir);
- }
-
- // create VBO
- dataSize *= numVertexes;
- data = ri.Hunk_AllocateTempMemory(dataSize);
- dataOfs = 0;
-
- vbo->ofs_xyz = 0;
- vbo->ofs_normal = 0;
-#ifdef USE_VERT_TANGENT_SPACE
- vbo->ofs_tangent = 0;
- vbo->ofs_bitangent = 0;
-#endif
- vbo->ofs_st = 0;
- vbo->ofs_lightmap = 0;
- vbo->ofs_vertexcolor = 0;
- vbo->ofs_lightdir = 0;
-
- vbo->stride_xyz = sizeof(verts[0].xyz);
- vbo->stride_normal = sizeof(verts[0].normal);
-#ifdef USE_VERT_TANGENT_SPACE
- vbo->stride_tangent = sizeof(verts[0].tangent);
- vbo->stride_bitangent = sizeof(verts[0].bitangent);
-#endif
- vbo->stride_vertexcolor = sizeof(verts[0].vertexColors);
- vbo->stride_st = sizeof(verts[0].st);
- vbo->stride_lightmap = sizeof(verts[0].lightmap);
- vbo->stride_lightdir = sizeof(verts[0].lightdir);
-
- //ri.Printf(PRINT_ALL, "2CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor,
- //vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor);
-
- // xyz
- for (i = 0; i < numVertexes; i++)
- {
- memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz));
- dataOfs += sizeof(verts[i].xyz);
- }
-
- // normal
- if(stateBits & ATTR_NORMAL)
- {
- vbo->ofs_normal = dataOfs;
- for (i = 0; i < numVertexes; i++)
- {
- memcpy(data + dataOfs, &verts[i].normal, sizeof(verts[i].normal));
- dataOfs += sizeof(verts[i].normal);
- }
- }
-
-#ifdef USE_VERT_TANGENT_SPACE
- // tangent
- if(stateBits & ATTR_TANGENT)
- {
- vbo->ofs_tangent = dataOfs;
- for (i = 0; i < numVertexes; i++)
- {
- memcpy(data + dataOfs, &verts[i].tangent, sizeof(verts[i].tangent));
- dataOfs += sizeof(verts[i].tangent);
- }
- }
-
- // bitangent
- if(stateBits & ATTR_BITANGENT)
- {
- vbo->ofs_bitangent = dataOfs;
- for (i = 0; i < numVertexes; i++)
- {
- memcpy(data + dataOfs, &verts[i].bitangent, sizeof(verts[i].bitangent));
- dataOfs += sizeof(verts[i].bitangent);
- }
- }
-#endif
-
- // vertex texcoords
- if(stateBits & ATTR_TEXCOORD)
- {
- vbo->ofs_st = dataOfs;
- for (i = 0; i < numVertexes; i++)
- {
- memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st));
- dataOfs += sizeof(verts[i].st);
- }
- }
-
- // feed vertex lightmap texcoords
- if(stateBits & ATTR_LIGHTCOORD)
- {
- vbo->ofs_lightmap = dataOfs;
- for (i = 0; i < numVertexes; i++)
- {
- memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap));
- dataOfs += sizeof(verts[i].lightmap);
- }
- }
-
- // feed vertex colors
- if(stateBits & ATTR_COLOR)
- {
- vbo->ofs_vertexcolor = dataOfs;
- for (i = 0; i < numVertexes; i++)
- {
- memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors));
- dataOfs += sizeof(verts[i].vertexColors);
- }
- }
-
- // feed vertex lightdirs
- if(stateBits & ATTR_LIGHTDIRECTION)
- {
- vbo->ofs_lightdir = dataOfs;
- for (i = 0; i < numVertexes; i++)
- {
- memcpy(data + dataOfs, &verts[i].lightdir, sizeof(verts[i].lightdir));
- dataOfs += sizeof(verts[i].lightdir);
- }
- }
- }
-
-
- vbo->vertexesSize = dataSize;
-
- qglGenBuffersARB(1, &vbo->vertexesVBO);
-
- qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO);
- qglBufferDataARB(GL_ARRAY_BUFFER_ARB, dataSize, data, glUsage);
-
- qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
-
- glState.currentVBO = NULL;
-
- GL_CheckErrors();
-
- ri.Hunk_FreeTempMemory(data);
-
- return vbo;
-}
-
-
-/*
-============
-R_CreateIBO
-============
-*/
-IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage)
-{
- IBO_t *ibo;
- int glUsage;
-
- switch (usage)
- {
- case VBO_USAGE_STATIC:
- glUsage = GL_STATIC_DRAW_ARB;
- break;
-
- case VBO_USAGE_DYNAMIC:
- glUsage = GL_DYNAMIC_DRAW_ARB;
- break;
-
- default:
- Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage);
- return NULL;
- }
-
- if(strlen(name) >= MAX_QPATH)
- {
- ri.Error(ERR_DROP, "R_CreateIBO: \"%s\" is too long", name);
- }
-
- if ( tr.numIBOs == MAX_IBOS ) {
- ri.Error( ERR_DROP, "R_CreateIBO: MAX_IBOS hit");
- }
-
- R_IssuePendingRenderCommands();
-
- ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low);
- tr.numIBOs++;
-
- Q_strncpyz(ibo->name, name, sizeof(ibo->name));
-
- ibo->indexesSize = indexesSize;
-
- qglGenBuffersARB(1, &ibo->indexesVBO);
-
- qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO);
- qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage);
-
- qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
-
- glState.currentIBO = NULL;
-
- GL_CheckErrors();
-
- return ibo;
-}
-
-/*
-============
-R_CreateIBO2
-============
-*/
-IBO_t *R_CreateIBO2(const char *name, int numTriangles, srfTriangle_t * triangles, vboUsage_t usage)
-{
- IBO_t *ibo;
- int i, j;
-
- byte *indexes;
- int indexesSize;
- int indexesOfs;
-
- srfTriangle_t *tri;
- glIndex_t index;
- int glUsage;
-
- switch (usage)
- {
- case VBO_USAGE_STATIC:
- glUsage = GL_STATIC_DRAW_ARB;
- break;
-
- case VBO_USAGE_DYNAMIC:
- glUsage = GL_DYNAMIC_DRAW_ARB;
- break;
-
- default:
- Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage);
- return NULL;
- }
-
- if(!numTriangles)
- return NULL;
-
- if(strlen(name) >= MAX_QPATH)
- {
- ri.Error(ERR_DROP, "R_CreateIBO2: \"%s\" is too long", name);
- }
-
- if ( tr.numIBOs == MAX_IBOS ) {
- ri.Error( ERR_DROP, "R_CreateIBO2: MAX_IBOS hit");
- }
-
- R_IssuePendingRenderCommands();
-
- ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low);
- tr.numIBOs++;
-
- Q_strncpyz(ibo->name, name, sizeof(ibo->name));
-
- indexesSize = numTriangles * 3 * sizeof(int);
- indexes = ri.Hunk_AllocateTempMemory(indexesSize);
- indexesOfs = 0;
-
- for(i = 0, tri = triangles; i < numTriangles; i++, tri++)
- {
- for(j = 0; j < 3; j++)
- {
- index = tri->indexes[j];
- memcpy(indexes + indexesOfs, &index, sizeof(glIndex_t));
- indexesOfs += sizeof(glIndex_t);
- }
- }
-
- ibo->indexesSize = indexesSize;
-
- qglGenBuffersARB(1, &ibo->indexesVBO);
-
- qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO);
- qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage);
-
- qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
-
- glState.currentIBO = NULL;
-
- GL_CheckErrors();
-
- ri.Hunk_FreeTempMemory(indexes);
-
- return ibo;
-}
-
-/*
-============
-R_BindVBO
-============
-*/
-void R_BindVBO(VBO_t * vbo)
-{
- if(!vbo)
- {
- //R_BindNullVBO();
- ri.Error(ERR_DROP, "R_BindNullVBO: NULL vbo");
- return;
- }
-
- if(r_logFile->integer)
- {
- // don't just call LogComment, or we will get a call to va() every frame!
- GLimp_LogComment(va("--- R_BindVBO( %s ) ---\n", vbo->name));
- }
-
- if(glState.currentVBO != vbo)
- {
- glState.currentVBO = vbo;
- glState.vertexAttribPointersSet = 0;
-
- glState.vertexAttribsInterpolation = 0;
- glState.vertexAttribsOldFrame = 0;
- glState.vertexAttribsNewFrame = 0;
-
- qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO);
-
- backEnd.pc.c_vboVertexBuffers++;
- }
-}
-
-/*
-============
-R_BindNullVBO
-============
-*/
-void R_BindNullVBO(void)
-{
- GLimp_LogComment("--- R_BindNullVBO ---\n");
-
- if(glState.currentVBO)
- {
- qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- glState.currentVBO = NULL;
- }
-
- GL_CheckErrors();
-}
-
-/*
-============
-R_BindIBO
-============
-*/
-void R_BindIBO(IBO_t * ibo)
-{
- if(!ibo)
- {
- //R_BindNullIBO();
- ri.Error(ERR_DROP, "R_BindIBO: NULL ibo");
- return;
- }
-
- if(r_logFile->integer)
- {
- // don't just call LogComment, or we will get a call to va() every frame!
- GLimp_LogComment(va("--- R_BindIBO( %s ) ---\n", ibo->name));
- }
-
- if(glState.currentIBO != ibo)
- {
- qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO);
-
- glState.currentIBO = ibo;
-
- backEnd.pc.c_vboIndexBuffers++;
- }
-}
-
-/*
-============
-R_BindNullIBO
-============
-*/
-void R_BindNullIBO(void)
-{
- GLimp_LogComment("--- R_BindNullIBO ---\n");
-
- if(glState.currentIBO)
- {
- qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
- glState.currentIBO = NULL;
- glState.vertexAttribPointersSet = 0;
- }
-}
-
-/*
-============
-R_InitVBOs
-============
-*/
-void R_InitVBOs(void)
-{
- int dataSize;
- int offset;
-
- ri.Printf(PRINT_ALL, "------- R_InitVBOs -------\n");
-
- tr.numVBOs = 0;
- tr.numIBOs = 0;
-
- dataSize = sizeof(tess.xyz[0]);
- dataSize += sizeof(tess.normal[0]);
-#ifdef USE_VERT_TANGENT_SPACE
- dataSize += sizeof(tess.tangent[0]);
- dataSize += sizeof(tess.bitangent[0]);
-#endif
- dataSize += sizeof(tess.vertexColors[0]);
- dataSize += sizeof(tess.texCoords[0][0]) * 2;
- dataSize += sizeof(tess.lightdir[0]);
- dataSize *= SHADER_MAX_VERTEXES;
-
- tess.vbo = R_CreateVBO("tessVertexArray_VBO", NULL, dataSize, VBO_USAGE_DYNAMIC);
-
- offset = 0;
-
- tess.vbo->ofs_xyz = offset; offset += sizeof(tess.xyz[0]) * SHADER_MAX_VERTEXES;
- tess.vbo->ofs_normal = offset; offset += sizeof(tess.normal[0]) * SHADER_MAX_VERTEXES;
-#ifdef USE_VERT_TANGENT_SPACE
- tess.vbo->ofs_tangent = offset; offset += sizeof(tess.tangent[0]) * SHADER_MAX_VERTEXES;
- tess.vbo->ofs_bitangent = offset; offset += sizeof(tess.bitangent[0]) * SHADER_MAX_VERTEXES;
-#endif
- // these next two are actually interleaved
- tess.vbo->ofs_st = offset;
- tess.vbo->ofs_lightmap = offset + sizeof(tess.texCoords[0][0]);
- offset += sizeof(tess.texCoords[0][0]) * 2 * SHADER_MAX_VERTEXES;
-
- tess.vbo->ofs_vertexcolor = offset; offset += sizeof(tess.vertexColors[0]) * SHADER_MAX_VERTEXES;
- tess.vbo->ofs_lightdir = offset;
-
- tess.vbo->stride_xyz = sizeof(tess.xyz[0]);
- tess.vbo->stride_normal = sizeof(tess.normal[0]);
-#ifdef USE_VERT_TANGENT_SPACE
- tess.vbo->stride_tangent = sizeof(tess.tangent[0]);
- tess.vbo->stride_bitangent = sizeof(tess.bitangent[0]);
-#endif
- tess.vbo->stride_vertexcolor = sizeof(tess.vertexColors[0]);
- tess.vbo->stride_st = sizeof(tess.texCoords[0][0]) * 2;
- tess.vbo->stride_lightmap = sizeof(tess.texCoords[0][0]) * 2;
- tess.vbo->stride_lightdir = sizeof(tess.lightdir[0]);
-
- dataSize = sizeof(tess.indexes[0]) * SHADER_MAX_INDEXES;
-
- tess.ibo = R_CreateIBO("tessVertexArray_IBO", NULL, dataSize, VBO_USAGE_DYNAMIC);
-
- R_BindNullVBO();
- R_BindNullIBO();
-
- GL_CheckErrors();
-}
-
-/*
-============
-R_ShutdownVBOs
-============
-*/
-void R_ShutdownVBOs(void)
-{
- int i;
- VBO_t *vbo;
- IBO_t *ibo;
-
- ri.Printf(PRINT_ALL, "------- R_ShutdownVBOs -------\n");
-
- R_BindNullVBO();
- R_BindNullIBO();
-
-
- for(i = 0; i < tr.numVBOs; i++)
- {
- vbo = tr.vbos[i];
-
- if(vbo->vertexesVBO)
- {
- qglDeleteBuffersARB(1, &vbo->vertexesVBO);
- }
-
- //ri.Free(vbo);
- }
-
- for(i = 0; i < tr.numIBOs; i++)
- {
- ibo = tr.ibos[i];
-
- if(ibo->indexesVBO)
- {
- qglDeleteBuffersARB(1, &ibo->indexesVBO);
- }
-
- //ri.Free(ibo);
- }
-
- tr.numVBOs = 0;
- tr.numIBOs = 0;
-}
-
-/*
-============
-R_VBOList_f
-============
-*/
-void R_VBOList_f(void)
-{
- int i;
- VBO_t *vbo;
- IBO_t *ibo;
- int vertexesSize = 0;
- int indexesSize = 0;
-
- ri.Printf(PRINT_ALL, " size name\n");
- ri.Printf(PRINT_ALL, "----------------------------------------------------------\n");
-
- for(i = 0; i < tr.numVBOs; i++)
- {
- vbo = tr.vbos[i];
-
- ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", vbo->vertexesSize / (1024 * 1024),
- (vbo->vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024), vbo->name);
-
- vertexesSize += vbo->vertexesSize;
- }
-
- for(i = 0; i < tr.numIBOs; i++)
- {
- ibo = tr.ibos[i];
-
- ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", ibo->indexesSize / (1024 * 1024),
- (ibo->indexesSize % (1024 * 1024)) * 100 / (1024 * 1024), ibo->name);
-
- indexesSize += ibo->indexesSize;
- }
-
- ri.Printf(PRINT_ALL, " %i total VBOs\n", tr.numVBOs);
- ri.Printf(PRINT_ALL, " %d.%02d MB total vertices memory\n", vertexesSize / (1024 * 1024),
- (vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024));
-
- ri.Printf(PRINT_ALL, " %i total IBOs\n", tr.numIBOs);
- ri.Printf(PRINT_ALL, " %d.%02d MB total triangle indices memory\n", indexesSize / (1024 * 1024),
- (indexesSize % (1024 * 1024)) * 100 / (1024 * 1024));
-}
-
-
-/*
-==============
-RB_UpdateVBOs
-
-Adapted from Tess_UpdateVBOs from xreal
-
-Tr3B: update the default VBO to replace the client side vertex arrays
-==============
-*/
-void RB_UpdateVBOs(unsigned int attribBits)
-{
- GLimp_LogComment("--- RB_UpdateVBOs ---\n");
-
- backEnd.pc.c_dynamicVboDraws++;
-
- // update the default VBO
- if(tess.numVertexes > 0 && tess.numVertexes <= SHADER_MAX_VERTEXES)
- {
- R_BindVBO(tess.vbo);
-
- if(attribBits & ATTR_BITS)
- {
- if(attribBits & ATTR_POSITION)
- {
- //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0]));
- qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0]), tess.xyz);
- }
-
- if(attribBits & ATTR_TEXCOORD || attribBits & ATTR_LIGHTCOORD)
- {
- // these are interleaved, so we update both if either need it
- //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2);
- qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2, tess.texCoords);
- }
-
- if(attribBits & ATTR_NORMAL)
- {
- //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]));
- qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]), tess.normal);
- }
-
-#ifdef USE_VERT_TANGENT_SPACE
- if(attribBits & ATTR_TANGENT)
- {
- //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]));
- qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]), tess.tangent);
- }
-
- if(attribBits & ATTR_BITANGENT)
- {
- //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_bitangent, tess.numVertexes * sizeof(tess.bitangent[0]));
- qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_bitangent, tess.numVertexes * sizeof(tess.bitangent[0]), tess.bitangent);
- }
-#endif
-
- if(attribBits & ATTR_COLOR)
- {
- //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]));
- qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]), tess.vertexColors);
- }
-
- if(attribBits & ATTR_LIGHTDIRECTION)
- {
- //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_lightdir, tess.numVertexes * sizeof(tess.lightdir[0]));
- qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_lightdir, tess.numVertexes * sizeof(tess.lightdir[0]), tess.lightdir);
- }
- }
- else
- {
- qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0]), tess.xyz);
- qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2, tess.texCoords);
- qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]), tess.normal);
-#ifdef USE_VERT_TANGENT_SPACE
- qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]), tess.tangent);
- qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_bitangent, tess.numVertexes * sizeof(tess.bitangent[0]), tess.bitangent);
-#endif
- qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]), tess.vertexColors);
- qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_lightdir, tess.numVertexes * sizeof(tess.lightdir[0]), tess.lightdir);
- }
-
- }
-
- // update the default IBO
- if(tess.numIndexes > 0 && tess.numIndexes <= SHADER_MAX_INDEXES)
- {
- R_BindIBO(tess.ibo);
-
- qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes);
- }
-}
diff --git a/src/rend2/tr_world.c b/src/rend2/tr_world.c
deleted file mode 100644
index 950ee6a4..00000000
--- a/src/rend2/tr_world.c
+++ /dev/null
@@ -1,850 +0,0 @@
-/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quake III Arena source code; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-#include "tr_local.h"
-
-
-
-/*
-================
-R_CullSurface
-
-Tries to cull surfaces before they are lighted or
-added to the sorting list.
-================
-*/
-static qboolean R_CullSurface( msurface_t *surf ) {
- if ( r_nocull->integer || surf->cullinfo.type == CULLINFO_NONE) {
- return qfalse;
- }
-
- if (surf->cullinfo.type & CULLINFO_PLANE)
- {
- // Only true for SF_FACE, so treat like its own function
- float d;
- cullType_t ct;
-
- if ( !r_facePlaneCull->integer ) {
- return qfalse;
- }
-
- ct = surf->shader->cullType;
-
- if (ct == CT_TWO_SIDED)
- {
- return qfalse;
- }
-
- // don't cull for depth shadow
- /*
- if ( tr.viewParms.flags & VPF_DEPTHSHADOW )
- {
- return qfalse;
- }
- */
-
- // shadowmaps draw back surfaces
- if ( tr.viewParms.flags & (VPF_SHADOWMAP | VPF_DEPTHSHADOW) )
- {
- if (ct == CT_FRONT_SIDED)
- {
- ct = CT_BACK_SIDED;
- }
- else
- {
- ct = CT_FRONT_SIDED;
- }
- }
-
- // do proper cull for orthographic projection
- if (tr.viewParms.flags & VPF_ORTHOGRAPHIC) {
- d = DotProduct(tr.viewParms.or.axis[0], surf->cullinfo.plane.normal);
- if ( ct == CT_FRONT_SIDED ) {
- if (d > 0)
- return qtrue;
- } else {
- if (d < 0)
- return qtrue;
- }
- return qfalse;
- }
-
- d = DotProduct (tr.or.viewOrigin, surf->cullinfo.plane.normal);
-
- // don't cull exactly on the plane, because there are levels of rounding
- // through the BSP, ICD, and hardware that may cause pixel gaps if an
- // epsilon isn't allowed here
- if ( ct == CT_FRONT_SIDED ) {
- if ( d < surf->cullinfo.plane.dist - 8 ) {
- return qtrue;
- }
- } else {
- if ( d > surf->cullinfo.plane.dist + 8 ) {
- return qtrue;
- }
- }
-
- return qfalse;
- }
-
- if (surf->cullinfo.type & CULLINFO_SPHERE)
- {
- int sphereCull;
-
- if ( tr.currentEntityNum != REFENTITYNUM_WORLD ) {
- sphereCull = R_CullLocalPointAndRadius( surf->cullinfo.localOrigin, surf->cullinfo.radius );
- } else {
- sphereCull = R_CullPointAndRadius( surf->cullinfo.localOrigin, surf->cullinfo.radius );
- }
-
- if ( sphereCull == CULL_OUT )
- {
- return qtrue;
- }
- }
-
- if (surf->cullinfo.type & CULLINFO_BOX)
- {
- int boxCull;
-
- if ( tr.currentEntityNum != REFENTITYNUM_WORLD ) {
- boxCull = R_CullLocalBox( surf->cullinfo.bounds );
- } else {
- boxCull = R_CullBox( surf->cullinfo.bounds );
- }
-
- if ( boxCull == CULL_OUT )
- {
- return qtrue;
- }
- }
-
- return qfalse;
-}
-
-
-/*
-====================
-R_DlightSurface
-
-The given surface is going to be drawn, and it touches a leaf
-that is touched by one or more dlights, so try to throw out
-more dlights if possible.
-====================
-*/
-static int R_DlightSurface( msurface_t *surf, int dlightBits ) {
- float d;
- int i;
- dlight_t *dl;
-
- if ( surf->cullinfo.type & CULLINFO_PLANE )
- {
- int i;
- for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
- if ( ! ( dlightBits & ( 1 << i ) ) ) {
- continue;
- }
- dl = &tr.refdef.dlights[i];
- d = DotProduct( dl->origin, surf->cullinfo.plane.normal ) - surf->cullinfo.plane.dist;
- if ( d < -dl->radius || d > dl->radius ) {
- // dlight doesn't reach the plane
- dlightBits &= ~( 1 << i );
- }
- }
- }
-
- if ( surf->cullinfo.type & CULLINFO_BOX )
- {
- for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
- if ( ! ( dlightBits & ( 1 << i ) ) ) {
- continue;
- }
- dl = &tr.refdef.dlights[i];
- if ( dl->origin[0] - dl->radius > surf->cullinfo.bounds[1][0]
- || dl->origin[0] + dl->radius < surf->cullinfo.bounds[0][0]
- || dl->origin[1] - dl->radius > surf->cullinfo.bounds[1][1]
- || dl->origin[1] + dl->radius < surf->cullinfo.bounds[0][1]
- || dl->origin[2] - dl->radius > surf->cullinfo.bounds[1][2]
- || dl->origin[2] + dl->radius < surf->cullinfo.bounds[0][2] ) {
- // dlight doesn't reach the bounds
- dlightBits &= ~( 1 << i );
- }
- }
- }
-
- if ( surf->cullinfo.type & CULLINFO_SPHERE )
- {
- for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
- if ( ! ( dlightBits & ( 1 << i ) ) ) {
- continue;
- }
- dl = &tr.refdef.dlights[i];
- if (!SpheresIntersect(dl->origin, dl->radius, surf->cullinfo.localOrigin, surf->cullinfo.radius))
- {
- // dlight doesn't reach the bounds
- dlightBits &= ~( 1 << i );
- }
- }
- }
-
- if ( *surf->data == SF_FACE ) {
- ((srfSurfaceFace_t *)surf->data)->dlightBits = dlightBits;
- } else if ( *surf->data == SF_GRID ) {
- ((srfGridMesh_t *)surf->data)->dlightBits = dlightBits;
- } else if ( *surf->data == SF_TRIANGLES ) {
- ((srfTriangles_t *)surf->data)->dlightBits = dlightBits;
- } else if ( *surf->data == SF_VBO_MESH ) {
- ((srfVBOMesh_t *)surf->data)->dlightBits = dlightBits;
- } else {
- dlightBits = 0;
- }
-
- if ( dlightBits ) {
- tr.pc.c_dlightSurfaces++;
- }
-
- return dlightBits;
-}
-
-/*
-====================
-R_PshadowSurface
-
-Just like R_DlightSurface, cull any we can
-====================
-*/
-static int R_PshadowSurface( msurface_t *surf, int pshadowBits ) {
- float d;
- int i;
- pshadow_t *ps;
-
- if ( surf->cullinfo.type & CULLINFO_PLANE )
- {
- int i;
- for ( i = 0 ; i < tr.refdef.num_pshadows ; i++ ) {
- if ( ! ( pshadowBits & ( 1 << i ) ) ) {
- continue;
- }
- ps = &tr.refdef.pshadows[i];
- d = DotProduct( ps->lightOrigin, surf->cullinfo.plane.normal ) - surf->cullinfo.plane.dist;
- if ( d < -ps->lightRadius || d > ps->lightRadius ) {
- // pshadow doesn't reach the plane
- pshadowBits &= ~( 1 << i );
- }
- }
- }
-
- if ( surf->cullinfo.type & CULLINFO_BOX )
- {
- for ( i = 0 ; i < tr.refdef.num_pshadows ; i++ ) {
- if ( ! ( pshadowBits & ( 1 << i ) ) ) {
- continue;
- }
- ps = &tr.refdef.pshadows[i];
- if ( ps->lightOrigin[0] - ps->lightRadius > surf->cullinfo.bounds[1][0]
- || ps->lightOrigin[0] + ps->lightRadius < surf->cullinfo.bounds[0][0]
- || ps->lightOrigin[1] - ps->lightRadius > surf->cullinfo.bounds[1][1]
- || ps->lightOrigin[1] + ps->lightRadius < surf->cullinfo.bounds[0][1]
- || ps->lightOrigin[2] - ps->lightRadius > surf->cullinfo.bounds[1][2]
- || ps->lightOrigin[2] + ps->lightRadius < surf->cullinfo.bounds[0][2]
- || BoxOnPlaneSide(surf->cullinfo.bounds[0], surf->cullinfo.bounds[1], &ps->cullPlane) == 2 ) {
- // pshadow doesn't reach the bounds
- pshadowBits &= ~( 1 << i );
- }
- }
- }
-
- if ( surf->cullinfo.type & CULLINFO_SPHERE )
- {
- for ( i = 0 ; i < tr.refdef.num_pshadows ; i++ ) {
- if ( ! ( pshadowBits & ( 1 << i ) ) ) {
- continue;
- }
- ps = &tr.refdef.pshadows[i];
- if (!SpheresIntersect(ps->viewOrigin, ps->viewRadius, surf->cullinfo.localOrigin, surf->cullinfo.radius)
- || DotProduct( surf->cullinfo.localOrigin, ps->cullPlane.normal ) - ps->cullPlane.dist < -surf->cullinfo.radius)
- {
- // pshadow doesn't reach the bounds
- pshadowBits &= ~( 1 << i );
- }
- }
- }
-
- if ( *surf->data == SF_FACE ) {
- ((srfSurfaceFace_t *)surf->data)->pshadowBits = pshadowBits;
- } else if ( *surf->data == SF_GRID ) {
- ((srfGridMesh_t *)surf->data)->pshadowBits = pshadowBits;
- } else if ( *surf->data == SF_TRIANGLES ) {
- ((srfTriangles_t *)surf->data)->pshadowBits = pshadowBits;
- } else if ( *surf->data == SF_VBO_MESH ) {
- ((srfVBOMesh_t *)surf->data)->pshadowBits = pshadowBits;
- } else {
- pshadowBits = 0;
- }
-
- if ( pshadowBits ) {
- //tr.pc.c_dlightSurfaces++;
- }
-
- return pshadowBits;
-}
-
-
-/*
-======================
-R_AddWorldSurface
-======================
-*/
-static void R_AddWorldSurface( msurface_t *surf, int dlightBits, int pshadowBits ) {
- // FIXME: bmodel fog?
-
- // try to cull before dlighting or adding
- if ( R_CullSurface( surf ) ) {
- return;
- }
-
- // check for dlighting
- if ( dlightBits ) {
- dlightBits = R_DlightSurface( surf, dlightBits );
- dlightBits = ( dlightBits != 0 );
- }
-
- // check for pshadows
- /*if ( pshadowBits ) */{
- pshadowBits = R_PshadowSurface( surf, pshadowBits);
- pshadowBits = ( pshadowBits != 0 );
- }
-
- R_AddDrawSurf( surf->data, surf->shader, surf->fogIndex, dlightBits, pshadowBits );
-}
-
-/*
-=============================================================
-
- BRUSH MODELS
-
-=============================================================
-*/
-
-/*
-=================
-R_AddBrushModelSurfaces
-=================
-*/
-void R_AddBrushModelSurfaces ( trRefEntity_t *ent ) {
- bmodel_t *bmodel;
- int clip;
- model_t *pModel;
- int i;
-
- pModel = R_GetModelByHandle( ent->e.hModel );
-
- bmodel = pModel->bmodel;
-
- clip = R_CullLocalBox( bmodel->bounds );
- if ( clip == CULL_OUT ) {
- return;
- }
-
- R_SetupEntityLighting( &tr.refdef, ent );
- R_DlightBmodel( bmodel );
-
- for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) {
- int surf = bmodel->firstSurface + i;
-
- if (tr.world->surfacesViewCount[surf] != tr.viewCount)
- {
- tr.world->surfacesViewCount[surf] = tr.viewCount;
- R_AddWorldSurface( tr.world->surfaces + surf, tr.currentEntity->needDlights, 0 );
- }
- }
-}
-
-
-/*
-=============================================================
-
- WORLD MODEL
-
-=============================================================
-*/
-
-
-/*
-================
-R_RecursiveWorldNode
-================
-*/
-static void R_RecursiveWorldNode( mnode_t *node, int planeBits, int dlightBits, int pshadowBits ) {
-
- do {
- int newDlights[2];
- unsigned int newPShadows[2];
-
- // if the node wasn't marked as potentially visible, exit
- // pvs is skipped for depth shadows
- if (!(tr.viewParms.flags & VPF_DEPTHSHADOW) && node->visCounts[tr.visIndex] != tr.visCounts[tr.visIndex]) {
- return;
- }
-
- // if the bounding volume is outside the frustum, nothing
- // inside can be visible OPTIMIZE: don't do this all the way to leafs?
-
- if ( !r_nocull->integer ) {
- int r;
-
- if ( planeBits & 1 ) {
- r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[0]);
- if (r == 2) {
- return; // culled
- }
- if ( r == 1 ) {
- planeBits &= ~1; // all descendants will also be in front
- }
- }
-
- if ( planeBits & 2 ) {
- r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[1]);
- if (r == 2) {
- return; // culled
- }
- if ( r == 1 ) {
- planeBits &= ~2; // all descendants will also be in front
- }
- }
-
- if ( planeBits & 4 ) {
- r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[2]);
- if (r == 2) {
- return; // culled
- }
- if ( r == 1 ) {
- planeBits &= ~4; // all descendants will also be in front
- }
- }
-
- if ( planeBits & 8 ) {
- r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[3]);
- if (r == 2) {
- return; // culled
- }
- if ( r == 1 ) {
- planeBits &= ~8; // all descendants will also be in front
- }
- }
-
- if ( planeBits & 16 ) {
- r = BoxOnPlaneSide(node->mins, node->maxs, &tr.viewParms.frustum[4]);
- if (r == 2) {
- return; // culled
- }
- if ( r == 1 ) {
- planeBits &= ~16; // all descendants will also be in front
- }
- }
- }
-
- if ( node->contents != -1 ) {
- break;
- }
-
- // node is just a decision point, so go down both sides
- // since we don't care about sort orders, just go positive to negative
-
- // determine which dlights are needed
- newDlights[0] = 0;
- newDlights[1] = 0;
- if ( dlightBits ) {
- int i;
-
- for ( i = 0 ; i < tr.refdef.num_dlights ; i++ ) {
- dlight_t *dl;
- float dist;
-
- if ( dlightBits & ( 1 << i ) ) {
- dl = &tr.refdef.dlights[i];
- dist = DotProduct( dl->origin, node->plane->normal ) - node->plane->dist;
-
- if ( dist > -dl->radius ) {
- newDlights[0] |= ( 1 << i );
- }
- if ( dist < dl->radius ) {
- newDlights[1] |= ( 1 << i );
- }
- }
- }
- }
-
- newPShadows[0] = 0;
- newPShadows[1] = 0;
- if ( pshadowBits ) {
- int i;
-
- for ( i = 0 ; i < tr.refdef.num_pshadows ; i++ ) {
- pshadow_t *shadow;
- float dist;
-
- if ( pshadowBits & ( 1 << i ) ) {
- shadow = &tr.refdef.pshadows[i];
- dist = DotProduct( shadow->lightOrigin, node->plane->normal ) - node->plane->dist;
-
- if ( dist > -shadow->lightRadius ) {
- newPShadows[0] |= ( 1 << i );
- }
- if ( dist < shadow->lightRadius ) {
- newPShadows[1] |= ( 1 << i );
- }
- }
- }
- }
-
- // recurse down the children, front side first
- R_RecursiveWorldNode (node->children[0], planeBits, newDlights[0], newPShadows[0] );
-
- // tail recurse
- node = node->children[1];
- dlightBits = newDlights[1];
- pshadowBits = newPShadows[1];
- } while ( 1 );
-
- {
- // leaf node, so add mark surfaces
- int c;
- int surf, *view;
-
- tr.pc.c_leafs++;
-
- // add to z buffer bounds
- if ( node->mins[0] < tr.viewParms.visBounds[0][0] ) {
- tr.viewParms.visBounds[0][0] = node->mins[0];
- }
- if ( node->mins[1] < tr.viewParms.visBounds[0][1] ) {
- tr.viewParms.visBounds[0][1] = node->mins[1];
- }
- if ( node->mins[2] < tr.viewParms.visBounds[0][2] ) {
- tr.viewParms.visBounds[0][2] = node->mins[2];
- }
-
- if ( node->maxs[0] > tr.viewParms.visBounds[1][0] ) {
- tr.viewParms.visBounds[1][0] = node->maxs[0];
- }
- if ( node->maxs[1] > tr.viewParms.visBounds[1][1] ) {
- tr.viewParms.visBounds[1][1] = node->maxs[1];
- }
- if ( node->maxs[2] > tr.viewParms.visBounds[1][2] ) {
- tr.viewParms.visBounds[1][2] = node->maxs[2];
- }
-
- // add merged and unmerged surfaces
- if (tr.world->viewSurfaces)
- view = tr.world->viewSurfaces + node->firstmarksurface;
- else
- view = tr.world->marksurfaces + node->firstmarksurface;
-
- c = node->nummarksurfaces;
- while (c--) {
- // just mark it as visible, so we don't jump out of the cache derefencing the surface
- surf = *view;
- if (surf < 0)
- {
- if (tr.world->mergedSurfacesViewCount[-surf - 1] != tr.viewCount)
- {
- tr.world->mergedSurfacesViewCount[-surf - 1] = tr.viewCount;
- tr.world->mergedSurfacesDlightBits[-surf - 1] = dlightBits;
- tr.world->mergedSurfacesPshadowBits[-surf - 1] = pshadowBits;
- }
- else
- {
- tr.world->mergedSurfacesDlightBits[-surf - 1] |= dlightBits;
- tr.world->mergedSurfacesPshadowBits[-surf - 1] |= pshadowBits;
- }
- }
- else
- {
- if (tr.world->surfacesViewCount[surf] != tr.viewCount)
- {
- tr.world->surfacesViewCount[surf] = tr.viewCount;
- tr.world->surfacesDlightBits[surf] = dlightBits;
- tr.world->surfacesPshadowBits[surf] = pshadowBits;
- }
- else
- {
- tr.world->surfacesDlightBits[surf] |= dlightBits;
- tr.world->surfacesPshadowBits[surf] |= pshadowBits;
- }
- }
- view++;
- }
- }
-
-}
-
-
-/*
-===============
-R_PointInLeaf
-===============
-*/
-static mnode_t *R_PointInLeaf( const vec3_t p ) {
- mnode_t *node;
- float d;
- cplane_t *plane;
-
- if ( !tr.world ) {
- ri.Error (ERR_DROP, "R_PointInLeaf: bad model");
- }
-
- node = tr.world->nodes;
- while( 1 ) {
- if (node->contents != -1) {
- break;
- }
- plane = node->plane;
- d = DotProduct (p,plane->normal) - plane->dist;
- if (d > 0) {
- node = node->children[0];
- } else {
- node = node->children[1];
- }
- }
-
- return node;
-}
-
-/*
-==============
-R_ClusterPVS
-==============
-*/
-static const byte *R_ClusterPVS (int cluster) {
- if (!tr.world || !tr.world->vis || cluster < 0 || cluster >= tr.world->numClusters ) {
- return tr.world->novis;
- }
-
- return tr.world->vis + cluster * tr.world->clusterBytes;
-}
-
-/*
-=================
-R_inPVS
-=================
-*/
-qboolean R_inPVS( const vec3_t p1, const vec3_t p2 ) {
- mnode_t *leaf;
- byte *vis;
-
- leaf = R_PointInLeaf( p1 );
- vis = ri.CM_ClusterPVS( leaf->cluster ); // why not R_ClusterPVS ??
- leaf = R_PointInLeaf( p2 );
-
- if ( !(vis[leaf->cluster>>3] & (1<<(leaf->cluster&7))) ) {
- return qfalse;
- }
- return qtrue;
-}
-
-/*
-===============
-R_MarkLeaves
-
-Mark the leaves and nodes that are in the PVS for the current
-cluster
-===============
-*/
-static void R_MarkLeaves (void) {
- const byte *vis;
- mnode_t *leaf, *parent;
- int i;
- int cluster;
-
- // lockpvs lets designers walk around to determine the
- // extent of the current pvs
- if ( r_lockpvs->integer ) {
- return;
- }
-
- // current viewcluster
- leaf = R_PointInLeaf( tr.viewParms.pvsOrigin );
- cluster = leaf->cluster;
-
- // if the cluster is the same and the area visibility matrix
- // hasn't changed, we don't need to mark everything again
-
- for(i = 0; i < MAX_VISCOUNTS; i++)
- {
- if(tr.visClusters[i] == cluster)
- {
- //tr.visIndex = i;
- break;
- }
- }
-
- // if r_showcluster was just turned on, remark everything
- if(i != MAX_VISCOUNTS && !tr.refdef.areamaskModified && !r_showcluster->modified)// && !r_dynamicBspOcclusionCulling->modified)
- {
- if(tr.visClusters[i] != tr.visClusters[tr.visIndex] && r_showcluster->integer)
- {
- ri.Printf(PRINT_ALL, "found cluster:%i area:%i index:%i\n", cluster, leaf->area, i);
- }
- tr.visIndex = i;
- return;
- }
-
- // if the areamask was modified, invalidate all visclusters
- // this caused doors to open into undrawn areas
- if (tr.refdef.areamaskModified)
- {
- memset(tr.visClusters, -2, sizeof(tr.visClusters));
- }
-
- tr.visIndex = (tr.visIndex + 1) % MAX_VISCOUNTS;
- tr.visCounts[tr.visIndex]++;
- tr.visClusters[tr.visIndex] = cluster;
-
- if ( r_showcluster->modified || r_showcluster->integer ) {
- r_showcluster->modified = qfalse;
- if ( r_showcluster->integer ) {
- ri.Printf( PRINT_ALL, "cluster:%i area:%i\n", cluster, leaf->area );
- }
- }
-
- // set all nodes to visible if there is no vis
- // this caused some levels to simply not render
- if (r_novis->integer || !tr.world->vis || tr.visClusters[tr.visIndex] == -1) {
- for (i=0 ; i<tr.world->numnodes ; i++) {
- if (tr.world->nodes[i].contents != CONTENTS_SOLID) {
- tr.world->nodes[i].visCounts[tr.visIndex] = tr.visCounts[tr.visIndex];
- }
- }
- return;
- }
-
- vis = R_ClusterPVS(tr.visClusters[tr.visIndex]);
-
- for (i=0,leaf=tr.world->nodes ; i<tr.world->numnodes ; i++, leaf++) {
- cluster = leaf->cluster;
- if ( cluster < 0 || cluster >= tr.world->numClusters ) {
- continue;
- }
-
- // check general pvs
- if ( !(vis[cluster>>3] & (1<<(cluster&7))) ) {
- continue;
- }
-
- // check for door connection
- if ( (tr.refdef.areamask[leaf->area>>3] & (1<<(leaf->area&7)) ) ) {
- continue; // not visible
- }
-
- parent = leaf;
- do {
- if(parent->visCounts[tr.visIndex] == tr.visCounts[tr.visIndex])
- break;
- parent->visCounts[tr.visIndex] = tr.visCounts[tr.visIndex];
- parent = parent->parent;
- } while (parent);
- }
-}
-
-
-/*
-=============
-R_AddWorldSurfaces
-=============
-*/
-void R_AddWorldSurfaces (void) {
- int planeBits, dlightBits, pshadowBits;
-
- if ( !r_drawworld->integer ) {
- return;
- }
-
- if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
- return;
- }
-
- tr.currentEntityNum = REFENTITYNUM_WORLD;
- tr.shiftedEntityNum = tr.currentEntityNum << QSORT_REFENTITYNUM_SHIFT;
-
- // determine which leaves are in the PVS / areamask
- if (!(tr.viewParms.flags & VPF_DEPTHSHADOW))
- R_MarkLeaves ();
-
- // clear out the visible min/max
- ClearBounds( tr.viewParms.visBounds[0], tr.viewParms.visBounds[1] );
-
- // perform frustum culling and flag all the potentially visible surfaces
- if ( tr.refdef.num_dlights > 32 ) {
- tr.refdef.num_dlights = 32 ;
- }
-
- if ( tr.refdef.num_pshadows > 32 ) {
- tr.refdef.num_pshadows = 32 ;
- }
-
- planeBits = (tr.viewParms.flags & VPF_FARPLANEFRUSTUM) ? 31 : 15;
-
- if ( tr.viewParms.flags & VPF_DEPTHSHADOW )
- {
- dlightBits = 0;
- pshadowBits = 0;
- }
- else if ( !(tr.viewParms.flags & VPF_SHADOWMAP) )
- {
- dlightBits = ( 1 << tr.refdef.num_dlights ) - 1;
- pshadowBits = ( 1 << tr.refdef.num_pshadows ) - 1;
- }
- else
- {
- dlightBits = ( 1 << tr.refdef.num_dlights ) - 1;
- pshadowBits = 0;
- }
-
- R_RecursiveWorldNode( tr.world->nodes, planeBits, dlightBits, pshadowBits);
-
- // now add all the potentially visible surfaces
- // also mask invisible dlights for next frame
- {
- int i;
-
- tr.refdef.dlightMask = 0;
-
- for (i = 0; i < tr.world->numWorldSurfaces; i++)
- {
- if (tr.world->surfacesViewCount[i] != tr.viewCount)
- continue;
-
- R_AddWorldSurface( tr.world->surfaces + i, tr.world->surfacesDlightBits[i], tr.world->surfacesPshadowBits[i] );
- tr.refdef.dlightMask |= tr.world->surfacesDlightBits[i];
- }
- for (i = 0; i < tr.world->numMergedSurfaces; i++)
- {
- if (tr.world->mergedSurfacesViewCount[i] != tr.viewCount)
- continue;
-
- R_AddWorldSurface( tr.world->mergedSurfaces + i, tr.world->mergedSurfacesDlightBits[i], tr.world->mergedSurfacesPshadowBits[i] );
- tr.refdef.dlightMask |= tr.world->mergedSurfacesDlightBits[i];
- }
-
- tr.refdef.dlightMask = ~tr.refdef.dlightMask;
- }
-}