2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; // used only by R_GetCurrentTexture
38 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
39 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
40 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
41 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
42 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
43 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
44 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
45 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
46 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
47 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
48 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
49 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
50 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
51 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
52 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
53 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
54 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
55 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
56 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
57 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
58 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
59 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
60 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
61 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
62 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
63 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows DOWN, otherwise use the model lighting"};
64 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
65 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
66 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
67 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
68 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
69 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
71 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
72 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
73 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
74 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
75 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
76 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
77 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
78 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
80 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
82 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
83 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
84 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
85 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
86 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
87 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
88 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
89 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
90 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
91 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
92 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
93 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
95 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
96 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
97 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
98 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
99 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
101 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
102 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
103 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
104 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
106 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
107 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
108 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
109 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
110 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
111 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
112 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
114 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
115 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
116 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
117 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
119 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
121 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
123 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
125 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
126 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
127 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
128 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
129 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
130 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
132 extern cvar_t v_glslgamma;
134 extern qboolean v_flipped_state;
136 static struct r_bloomstate_s
141 int bloomwidth, bloomheight;
143 int screentexturewidth, screentextureheight;
144 rtexture_t *texture_screen;
146 int bloomtexturewidth, bloomtextureheight;
147 rtexture_t *texture_bloom;
149 // arrays for rendering the screen passes
150 float screentexcoord2f[8];
151 float bloomtexcoord2f[8];
152 float offsettexcoord2f[8];
156 r_waterstate_t r_waterstate;
158 // shadow volume bsp struct with automatically growing nodes buffer
161 rtexture_t *r_texture_blanknormalmap;
162 rtexture_t *r_texture_white;
163 rtexture_t *r_texture_grey128;
164 rtexture_t *r_texture_black;
165 rtexture_t *r_texture_notexture;
166 rtexture_t *r_texture_whitecube;
167 rtexture_t *r_texture_normalizationcube;
168 rtexture_t *r_texture_fogattenuation;
169 rtexture_t *r_texture_gammaramps;
170 unsigned int r_texture_gammaramps_serial;
171 //rtexture_t *r_texture_fogintensity;
173 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
174 unsigned int r_numqueries;
175 unsigned int r_maxqueries;
177 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
178 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
180 // vertex coordinates for a quad that covers the screen exactly
181 const static float r_screenvertex3f[12] =
189 extern void R_DrawModelShadows(void);
191 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
194 for (i = 0;i < verts;i++)
205 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
208 for (i = 0;i < verts;i++)
218 // FIXME: move this to client?
221 if (gamemode == GAME_NEHAHRA)
223 Cvar_Set("gl_fogenable", "0");
224 Cvar_Set("gl_fogdensity", "0.2");
225 Cvar_Set("gl_fogred", "0.3");
226 Cvar_Set("gl_foggreen", "0.3");
227 Cvar_Set("gl_fogblue", "0.3");
229 r_refdef.fog_density = 0;
230 r_refdef.fog_red = 0;
231 r_refdef.fog_green = 0;
232 r_refdef.fog_blue = 0;
233 r_refdef.fog_alpha = 1;
234 r_refdef.fog_start = 0;
235 r_refdef.fog_end = 0;
238 float FogForDistance(vec_t dist)
240 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
241 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
244 float FogPoint_World(const vec3_t p)
246 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
249 float FogPoint_Model(const vec3_t p)
251 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
254 static void R_BuildBlankTextures(void)
256 unsigned char data[4];
257 data[2] = 128; // normal X
258 data[1] = 128; // normal Y
259 data[0] = 255; // normal Z
260 data[3] = 128; // height
261 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
266 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
271 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
276 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
279 static void R_BuildNoTexture(void)
282 unsigned char pix[16][16][4];
283 // this makes a light grey/dark grey checkerboard texture
284 for (y = 0;y < 16;y++)
286 for (x = 0;x < 16;x++)
288 if ((y < 8) ^ (x < 8))
304 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
307 static void R_BuildWhiteCube(void)
309 unsigned char data[6*1*1*4];
310 memset(data, 255, sizeof(data));
311 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
314 static void R_BuildNormalizationCube(void)
318 vec_t s, t, intensity;
320 unsigned char data[6][NORMSIZE][NORMSIZE][4];
321 for (side = 0;side < 6;side++)
323 for (y = 0;y < NORMSIZE;y++)
325 for (x = 0;x < NORMSIZE;x++)
327 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
328 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
363 intensity = 127.0f / sqrt(DotProduct(v, v));
364 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
365 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
366 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
367 data[side][y][x][3] = 255;
371 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
374 static void R_BuildFogTexture(void)
378 unsigned char data1[FOGWIDTH][4];
379 //unsigned char data2[FOGWIDTH][4];
382 r_refdef.fogmasktable_start = r_refdef.fog_start;
383 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
384 r_refdef.fogmasktable_range = r_refdef.fogrange;
385 r_refdef.fogmasktable_density = r_refdef.fog_density;
387 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
388 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
390 d = (x * r - r_refdef.fogmasktable_start);
391 if(developer.integer >= 100)
392 Con_Printf("%f ", d);
394 if (r_fog_exp2.integer)
395 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
397 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
398 if(developer.integer >= 100)
399 Con_Printf(" : %f ", alpha);
400 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
401 if(developer.integer >= 100)
402 Con_Printf(" = %f\n", alpha);
403 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
406 for (x = 0;x < FOGWIDTH;x++)
408 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
413 //data2[x][0] = 255 - b;
414 //data2[x][1] = 255 - b;
415 //data2[x][2] = 255 - b;
418 if (r_texture_fogattenuation)
420 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
421 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
425 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
426 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
430 static const char *builtinshaderstring =
431 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
432 "// written by Forest 'LordHavoc' Hale\n"
434 "// common definitions between vertex shader and fragment shader:\n"
436 "//#ifdef __GLSL_CG_DATA_TYPES\n"
437 "//# define myhalf half\n"
438 "//# define myhalf2 half2\n"
439 "//# define myhalf3 half3\n"
440 "//# define myhalf4 half4\n"
442 "# define myhalf float\n"
443 "# define myhalf2 vec2\n"
444 "# define myhalf3 vec3\n"
445 "# define myhalf4 vec4\n"
448 "#ifdef MODE_DEPTH_OR_SHADOW\n"
450 "# ifdef VERTEX_SHADER\n"
453 " gl_Position = ftransform();\n"
459 "#ifdef MODE_POSTPROCESS\n"
460 "# ifdef VERTEX_SHADER\n"
463 " gl_FrontColor = gl_Color;\n"
464 " gl_Position = ftransform();\n"
465 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
467 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
471 "# ifdef FRAGMENT_SHADER\n"
473 "uniform sampler2D Texture_First;\n"
475 "uniform sampler2D Texture_Second;\n"
477 "#ifdef USEGAMMARAMPS\n"
478 "uniform sampler2D Texture_GammaRamps;\n"
480 "#ifdef USEVERTEXTEXTUREBLEND\n"
481 "uniform vec4 TintColor;\n"
483 "#ifdef USECOLORMOD\n"
484 "uniform vec3 Gamma;\n"
486 "//uncomment these if you want to use them:\n"
487 "uniform vec4 UserVec1;\n"
488 "// uniform vec4 UserVec2;\n"
489 "// uniform vec4 UserVec3;\n"
490 "// uniform vec4 UserVec4;\n"
491 "// uniform float ClientTime;\n"
492 "uniform vec2 PixelSize;\n"
495 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
497 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
499 "#ifdef USEVERTEXTEXTUREBLEND\n"
500 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
503 "#ifdef USEPOSTPROCESSING\n"
504 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
505 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
506 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
507 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
508 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
509 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
510 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
511 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
514 "#ifdef USEGAMMARAMPS\n"
515 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
516 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
517 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
524 "#ifdef MODE_GENERIC\n"
525 "# ifdef VERTEX_SHADER\n"
528 " gl_FrontColor = gl_Color;\n"
529 "# ifdef USEDIFFUSE\n"
530 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
532 "# ifdef USESPECULAR\n"
533 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
535 " gl_Position = ftransform();\n"
538 "# ifdef FRAGMENT_SHADER\n"
540 "# ifdef USEDIFFUSE\n"
541 "uniform sampler2D Texture_First;\n"
543 "# ifdef USESPECULAR\n"
544 "uniform sampler2D Texture_Second;\n"
549 " gl_FragColor = gl_Color;\n"
550 "# ifdef USEDIFFUSE\n"
551 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
554 "# ifdef USESPECULAR\n"
555 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
557 "# ifdef USECOLORMAPPING\n"
558 " gl_FragColor *= tex2;\n"
561 " gl_FragColor += tex2;\n"
563 "# ifdef USEVERTEXTEXTUREBLEND\n"
564 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
569 "#else // !MODE_GENERIC\n"
571 "varying vec2 TexCoord;\n"
572 "varying vec2 TexCoordLightmap;\n"
574 "#ifdef MODE_LIGHTSOURCE\n"
575 "varying vec3 CubeVector;\n"
578 "#ifdef MODE_LIGHTSOURCE\n"
579 "varying vec3 LightVector;\n"
581 "#ifdef MODE_LIGHTDIRECTION\n"
582 "varying vec3 LightVector;\n"
585 "varying vec3 EyeVector;\n"
587 "varying vec3 EyeVectorModelSpace;\n"
590 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
591 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
592 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
594 "#ifdef MODE_WATER\n"
595 "varying vec4 ModelViewProjectionPosition;\n"
597 "#ifdef MODE_REFRACTION\n"
598 "varying vec4 ModelViewProjectionPosition;\n"
600 "#ifdef USEREFLECTION\n"
601 "varying vec4 ModelViewProjectionPosition;\n"
608 "// vertex shader specific:\n"
609 "#ifdef VERTEX_SHADER\n"
611 "uniform vec3 LightPosition;\n"
612 "uniform vec3 EyePosition;\n"
613 "uniform vec3 LightDir;\n"
615 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
619 " gl_FrontColor = gl_Color;\n"
620 " // copy the surface texcoord\n"
621 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
622 "#ifndef MODE_LIGHTSOURCE\n"
623 "# ifndef MODE_LIGHTDIRECTION\n"
624 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
628 "#ifdef MODE_LIGHTSOURCE\n"
629 " // transform vertex position into light attenuation/cubemap space\n"
630 " // (-1 to +1 across the light box)\n"
631 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
633 " // transform unnormalized light direction into tangent space\n"
634 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
635 " // normalize it per pixel)\n"
636 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
637 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
638 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
639 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
642 "#ifdef MODE_LIGHTDIRECTION\n"
643 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
644 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
645 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
648 " // transform unnormalized eye direction into tangent space\n"
650 " vec3 EyeVectorModelSpace;\n"
652 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
653 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
654 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
655 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
657 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
658 " VectorS = gl_MultiTexCoord1.xyz;\n"
659 " VectorT = gl_MultiTexCoord2.xyz;\n"
660 " VectorR = gl_MultiTexCoord3.xyz;\n"
663 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
664 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
665 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
666 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
669 "// transform vertex to camera space, using ftransform to match non-VS\n"
671 " gl_Position = ftransform();\n"
673 "#ifdef MODE_WATER\n"
674 " ModelViewProjectionPosition = gl_Position;\n"
676 "#ifdef MODE_REFRACTION\n"
677 " ModelViewProjectionPosition = gl_Position;\n"
679 "#ifdef USEREFLECTION\n"
680 " ModelViewProjectionPosition = gl_Position;\n"
684 "#endif // VERTEX_SHADER\n"
689 "// fragment shader specific:\n"
690 "#ifdef FRAGMENT_SHADER\n"
692 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
693 "uniform sampler2D Texture_Normal;\n"
694 "uniform sampler2D Texture_Color;\n"
695 "uniform sampler2D Texture_Gloss;\n"
696 "uniform sampler2D Texture_Glow;\n"
697 "uniform sampler2D Texture_SecondaryNormal;\n"
698 "uniform sampler2D Texture_SecondaryColor;\n"
699 "uniform sampler2D Texture_SecondaryGloss;\n"
700 "uniform sampler2D Texture_SecondaryGlow;\n"
701 "uniform sampler2D Texture_Pants;\n"
702 "uniform sampler2D Texture_Shirt;\n"
703 "uniform sampler2D Texture_FogMask;\n"
704 "uniform sampler2D Texture_Lightmap;\n"
705 "uniform sampler2D Texture_Deluxemap;\n"
706 "uniform sampler2D Texture_Refraction;\n"
707 "uniform sampler2D Texture_Reflection;\n"
708 "uniform sampler2D Texture_Attenuation;\n"
709 "uniform samplerCube Texture_Cube;\n"
711 "uniform myhalf3 LightColor;\n"
712 "uniform myhalf3 AmbientColor;\n"
713 "uniform myhalf3 DiffuseColor;\n"
714 "uniform myhalf3 SpecularColor;\n"
715 "uniform myhalf3 Color_Pants;\n"
716 "uniform myhalf3 Color_Shirt;\n"
717 "uniform myhalf3 FogColor;\n"
719 "uniform myhalf4 TintColor;\n"
722 "//#ifdef MODE_WATER\n"
723 "uniform vec4 DistortScaleRefractReflect;\n"
724 "uniform vec4 ScreenScaleRefractReflect;\n"
725 "uniform vec4 ScreenCenterRefractReflect;\n"
726 "uniform myhalf4 RefractColor;\n"
727 "uniform myhalf4 ReflectColor;\n"
728 "uniform myhalf ReflectFactor;\n"
729 "uniform myhalf ReflectOffset;\n"
731 "//# ifdef MODE_REFRACTION\n"
732 "//uniform vec4 DistortScaleRefractReflect;\n"
733 "//uniform vec4 ScreenScaleRefractReflect;\n"
734 "//uniform vec4 ScreenCenterRefractReflect;\n"
735 "//uniform myhalf4 RefractColor;\n"
736 "//# ifdef USEREFLECTION\n"
737 "//uniform myhalf4 ReflectColor;\n"
740 "//# ifdef USEREFLECTION\n"
741 "//uniform vec4 DistortScaleRefractReflect;\n"
742 "//uniform vec4 ScreenScaleRefractReflect;\n"
743 "//uniform vec4 ScreenCenterRefractReflect;\n"
744 "//uniform myhalf4 ReflectColor;\n"
749 "uniform myhalf GlowScale;\n"
750 "uniform myhalf SceneBrightness;\n"
751 "#ifdef USECONTRASTBOOST\n"
752 "uniform myhalf ContrastBoostCoeff;\n"
755 "uniform float OffsetMapping_Scale;\n"
756 "uniform float OffsetMapping_Bias;\n"
757 "uniform float FogRangeRecip;\n"
759 "uniform myhalf AmbientScale;\n"
760 "uniform myhalf DiffuseScale;\n"
761 "uniform myhalf SpecularScale;\n"
762 "uniform myhalf SpecularPower;\n"
764 "#ifdef USEOFFSETMAPPING\n"
765 "vec2 OffsetMapping(vec2 TexCoord)\n"
767 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
768 " // 14 sample relief mapping: linear search and then binary search\n"
769 " // this basically steps forward a small amount repeatedly until it finds\n"
770 " // itself inside solid, then jitters forward and back using decreasing\n"
771 " // amounts to find the impact\n"
772 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
773 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
774 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
775 " vec3 RT = vec3(TexCoord, 1);\n"
776 " OffsetVector *= 0.1;\n"
777 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
778 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
779 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
780 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
781 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
782 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
783 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
784 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
785 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
786 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
787 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
788 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
789 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
790 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
793 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
794 " // this basically moves forward the full distance, and then backs up based\n"
795 " // on height of samples\n"
796 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
797 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
798 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
799 " TexCoord += OffsetVector;\n"
800 " OffsetVector *= 0.333;\n"
801 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
802 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
803 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
804 " return TexCoord;\n"
807 "#endif // USEOFFSETMAPPING\n"
809 "#ifdef MODE_WATER\n"
814 "#ifdef USEOFFSETMAPPING\n"
815 " // apply offsetmapping\n"
816 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
817 "#define TexCoord TexCoordOffset\n"
820 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
821 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
822 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
823 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
824 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
827 "#else // !MODE_WATER\n"
828 "#ifdef MODE_REFRACTION\n"
830 "// refraction pass\n"
833 "#ifdef USEOFFSETMAPPING\n"
834 " // apply offsetmapping\n"
835 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
836 "#define TexCoord TexCoordOffset\n"
839 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
840 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
841 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
842 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
845 "#else // !MODE_REFRACTION\n"
848 "#ifdef USEOFFSETMAPPING\n"
849 " // apply offsetmapping\n"
850 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
851 "#define TexCoord TexCoordOffset\n"
854 " // combine the diffuse textures (base, pants, shirt)\n"
855 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
856 "#ifdef USECOLORMAPPING\n"
857 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
859 "#ifdef USEVERTEXTEXTUREBLEND\n"
860 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
861 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
862 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
863 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord)), color.rgb, terrainblend);\n"
865 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
868 "#ifdef USEDIFFUSE\n"
869 " // get the surface normal and the gloss color\n"
870 "# ifdef USEVERTEXTEXTUREBLEND\n"
871 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
872 "# ifdef USESPECULAR\n"
873 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
876 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
877 "# ifdef USESPECULAR\n"
878 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
885 "#ifdef MODE_LIGHTSOURCE\n"
888 " // calculate surface normal, light normal, and specular normal\n"
889 " // compute color intensity for the two textures (colormap and glossmap)\n"
890 " // scale by light color and attenuation as efficiently as possible\n"
891 " // (do as much scalar math as possible rather than vector math)\n"
892 "# ifdef USEDIFFUSE\n"
893 " // get the light normal\n"
894 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
896 "# ifdef USESPECULAR\n"
897 "# ifndef USEEXACTSPECULARMATH\n"
898 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
901 " // calculate directional shading\n"
902 "# ifdef USEEXACTSPECULARMATH\n"
903 " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n"
905 " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * glosscolor);\n"
908 "# ifdef USEDIFFUSE\n"
909 " // calculate directional shading\n"
910 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
912 " // calculate directionless shading\n"
913 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
917 "# ifdef USECUBEFILTER\n"
918 " // apply light cubemap filter\n"
919 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
920 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
922 "#endif // MODE_LIGHTSOURCE\n"
927 "#ifdef MODE_LIGHTDIRECTION\n"
928 " // directional model lighting\n"
929 "# ifdef USEDIFFUSE\n"
930 " // get the light normal\n"
931 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
933 "# ifdef USESPECULAR\n"
934 " // calculate directional shading\n"
935 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
936 "# ifdef USEEXACTSPECULARMATH\n"
937 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
939 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
940 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
943 "# ifdef USEDIFFUSE\n"
945 " // calculate directional shading\n"
946 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
948 " color.rgb *= AmbientColor;\n"
951 "#endif // MODE_LIGHTDIRECTION\n"
956 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
957 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
959 " // get the light normal\n"
960 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
961 " myhalf3 diffusenormal;\n"
962 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
963 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
964 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
965 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
966 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
967 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
968 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
969 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
970 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
971 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
972 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
973 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
974 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
975 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
976 "# ifdef USESPECULAR\n"
977 "# ifdef USEEXACTSPECULARMATH\n"
978 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
980 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
981 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
985 " // apply lightmap color\n"
986 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
987 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
992 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
993 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
995 " // get the light normal\n"
996 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
997 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
998 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
999 "# ifdef USESPECULAR\n"
1000 "# ifdef USEEXACTSPECULARMATH\n"
1001 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1003 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1004 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1008 " // apply lightmap color\n"
1009 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1010 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1015 "#ifdef MODE_LIGHTMAP\n"
1016 " // apply lightmap color\n"
1017 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1018 "#endif // MODE_LIGHTMAP\n"
1023 "#ifdef MODE_VERTEXCOLOR\n"
1024 " // apply lightmap color\n"
1025 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1026 "#endif // MODE_VERTEXCOLOR\n"
1031 "#ifdef MODE_FLATCOLOR\n"
1032 "#endif // MODE_FLATCOLOR\n"
1040 " color *= TintColor;\n"
1043 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1046 "#ifdef USECONTRASTBOOST\n"
1047 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1050 " color.rgb *= SceneBrightness;\n"
1052 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1054 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1057 " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1058 "#ifdef USEREFLECTION\n"
1059 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1060 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1061 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1062 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1065 " gl_FragColor = vec4(color);\n"
1067 "#endif // !MODE_REFRACTION\n"
1068 "#endif // !MODE_WATER\n"
1070 "#endif // FRAGMENT_SHADER\n"
1072 "#endif // !MODE_GENERIC\n"
1073 "#endif // !MODE_POSTPROCESS\n"
1074 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1077 typedef struct shaderpermutationinfo_s
1079 const char *pretext;
1082 shaderpermutationinfo_t;
1084 typedef struct shadermodeinfo_s
1086 const char *vertexfilename;
1087 const char *geometryfilename;
1088 const char *fragmentfilename;
1089 const char *pretext;
1094 typedef enum shaderpermutation_e
1096 SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
1097 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1098 SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
1099 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1100 SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
1101 SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
1102 SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
1103 SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
1104 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, // (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1105 SHADERPERMUTATION_REFLECTION = 1<<9, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1106 SHADERPERMUTATION_OFFSETMAPPING = 1<<10, // adjust texcoords to roughly simulate a displacement mapped surface
1107 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1108 SHADERPERMUTATION_GAMMARAMPS = 1<<12, // gamma (postprocessing only)
1109 SHADERPERMUTATION_POSTPROCESSING = 1<<13, // user defined postprocessing
1110 SHADERPERMUTATION_LIMIT = 1<<14, // size of permutations array
1111 SHADERPERMUTATION_COUNT = 14 // size of shaderpermutationinfo array
1113 shaderpermutation_t;
1115 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1116 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1118 {"#define USEDIFFUSE\n", " diffuse"},
1119 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1120 {"#define USECOLORMAPPING\n", " colormapping"},
1121 {"#define USECONTRASTBOOST\n", " contrastboost"},
1122 {"#define USEFOG\n", " fog"},
1123 {"#define USECUBEFILTER\n", " cubefilter"},
1124 {"#define USEGLOW\n", " glow"},
1125 {"#define USESPECULAR\n", " specular"},
1126 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1127 {"#define USEREFLECTION\n", " reflection"},
1128 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1129 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1130 {"#define USEGAMMARAMPS\n", " gammaramps"},
1131 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1134 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
1135 typedef enum shadermode_e
1137 SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
1138 SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
1139 SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
1140 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1141 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
1142 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1143 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1144 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1145 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1146 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
1147 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
1148 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1153 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1154 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1156 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1157 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1158 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1159 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1160 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1161 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1162 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1163 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1164 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1165 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1166 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1167 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1170 typedef struct r_glsl_permutation_s
1172 // indicates if we have tried compiling this permutation already
1174 // 0 if compilation failed
1176 // locations of detected uniforms in program object, or -1 if not found
1177 int loc_Texture_First;
1178 int loc_Texture_Second;
1179 int loc_Texture_GammaRamps;
1180 int loc_Texture_Normal;
1181 int loc_Texture_Color;
1182 int loc_Texture_Gloss;
1183 int loc_Texture_Glow;
1184 int loc_Texture_SecondaryNormal;
1185 int loc_Texture_SecondaryColor;
1186 int loc_Texture_SecondaryGloss;
1187 int loc_Texture_SecondaryGlow;
1188 int loc_Texture_Pants;
1189 int loc_Texture_Shirt;
1190 int loc_Texture_FogMask;
1191 int loc_Texture_Lightmap;
1192 int loc_Texture_Deluxemap;
1193 int loc_Texture_Attenuation;
1194 int loc_Texture_Cube;
1195 int loc_Texture_Refraction;
1196 int loc_Texture_Reflection;
1198 int loc_LightPosition;
1199 int loc_EyePosition;
1200 int loc_Color_Pants;
1201 int loc_Color_Shirt;
1202 int loc_FogRangeRecip;
1203 int loc_AmbientScale;
1204 int loc_DiffuseScale;
1205 int loc_SpecularScale;
1206 int loc_SpecularPower;
1208 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1209 int loc_OffsetMapping_Scale;
1211 int loc_AmbientColor;
1212 int loc_DiffuseColor;
1213 int loc_SpecularColor;
1215 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1216 int loc_GammaCoeff; // 1 / gamma
1217 int loc_DistortScaleRefractReflect;
1218 int loc_ScreenScaleRefractReflect;
1219 int loc_ScreenCenterRefractReflect;
1220 int loc_RefractColor;
1221 int loc_ReflectColor;
1222 int loc_ReflectFactor;
1223 int loc_ReflectOffset;
1231 r_glsl_permutation_t;
1233 // information about each possible shader permutation
1234 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1235 // currently selected permutation
1236 r_glsl_permutation_t *r_glsl_permutation;
1238 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1241 if (!filename || !filename[0])
1243 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1246 if (printfromdisknotice)
1247 Con_DPrint("from disk... ");
1248 return shaderstring;
1250 else if (!strcmp(filename, "glsl/default.glsl"))
1252 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1253 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1255 return shaderstring;
1258 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1261 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1262 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1263 int vertstrings_count = 0;
1264 int geomstrings_count = 0;
1265 int fragstrings_count = 0;
1266 char *vertexstring, *geometrystring, *fragmentstring;
1267 const char *vertstrings_list[32+3];
1268 const char *geomstrings_list[32+3];
1269 const char *fragstrings_list[32+3];
1270 char permutationname[256];
1277 permutationname[0] = 0;
1278 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1279 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1280 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1282 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1284 // the first pretext is which type of shader to compile as
1285 // (later these will all be bound together as a program object)
1286 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1287 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1288 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1290 // the second pretext is the mode (for example a light source)
1291 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1292 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1293 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1294 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1296 // now add all the permutation pretexts
1297 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1299 if (permutation & (1<<i))
1301 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1302 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1303 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1304 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1308 // keep line numbers correct
1309 vertstrings_list[vertstrings_count++] = "\n";
1310 geomstrings_list[geomstrings_count++] = "\n";
1311 fragstrings_list[fragstrings_count++] = "\n";
1315 // now append the shader text itself
1316 vertstrings_list[vertstrings_count++] = vertexstring;
1317 geomstrings_list[geomstrings_count++] = geometrystring;
1318 fragstrings_list[fragstrings_count++] = fragmentstring;
1320 // if any sources were NULL, clear the respective list
1322 vertstrings_count = 0;
1323 if (!geometrystring)
1324 geomstrings_count = 0;
1325 if (!fragmentstring)
1326 fragstrings_count = 0;
1328 // compile the shader program
1329 if (vertstrings_count + geomstrings_count + fragstrings_count)
1330 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1334 qglUseProgramObjectARB(p->program);CHECKGLERROR
1335 // look up all the uniform variable names we care about, so we don't
1336 // have to look them up every time we set them
1337 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1338 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1339 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1340 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1341 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1342 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1343 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1344 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1345 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1346 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1347 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1348 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1349 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1350 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1351 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1352 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1353 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1354 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1355 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1356 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1357 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1358 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1359 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1360 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1361 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1362 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1363 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1364 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1365 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1366 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1367 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1368 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1369 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1370 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1371 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1372 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1373 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1374 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1375 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1376 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1377 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1378 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1379 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1380 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1381 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1382 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1383 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1384 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1385 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1386 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1387 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1388 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1389 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1390 // initialize the samplers to refer to the texture units we use
1391 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1392 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1393 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1394 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1395 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1396 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1397 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1398 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1399 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1400 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1401 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1402 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1403 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1404 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1405 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1406 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1407 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1408 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1409 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1410 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1412 if (developer.integer)
1413 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1416 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1420 Mem_Free(vertexstring);
1422 Mem_Free(geometrystring);
1424 Mem_Free(fragmentstring);
1427 void R_GLSL_Restart_f(void)
1430 unsigned int permutation;
1431 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1432 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1433 if (r_glsl_permutations[mode][permutation].program)
1434 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1435 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1438 void R_GLSL_DumpShader_f(void)
1442 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1445 Con_Printf("failed to write to glsl/default.glsl\n");
1449 FS_Print(file, "// The engine may define the following macros:\n");
1450 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1451 for (i = 0;i < SHADERMODE_COUNT;i++)
1452 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1453 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1454 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1455 FS_Print(file, "\n");
1456 FS_Print(file, builtinshaderstring);
1459 Con_Printf("glsl/default.glsl written\n");
1462 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1464 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1465 if (r_glsl_permutation != perm)
1467 r_glsl_permutation = perm;
1468 if (!r_glsl_permutation->program)
1470 if (!r_glsl_permutation->compiled)
1471 R_GLSL_CompilePermutation(mode, permutation);
1472 if (!r_glsl_permutation->program)
1474 // remove features until we find a valid permutation
1476 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1478 // reduce i more quickly whenever it would not remove any bits
1479 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1480 if (!(permutation & j))
1483 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1484 if (!r_glsl_permutation->compiled)
1485 R_GLSL_CompilePermutation(mode, permutation);
1486 if (r_glsl_permutation->program)
1489 if (i >= SHADERPERMUTATION_COUNT)
1491 Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n");
1492 Cvar_SetValueQuick(&r_glsl, 0);
1493 R_GLSL_Restart_f(); // unload shaders
1494 return; // no bit left to clear
1499 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1503 void R_SetupGenericShader(qboolean usetexture)
1505 if (gl_support_fragment_shader)
1507 if (r_glsl.integer && r_glsl_usegeneric.integer)
1508 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1509 else if (r_glsl_permutation)
1511 r_glsl_permutation = NULL;
1512 qglUseProgramObjectARB(0);CHECKGLERROR
1517 void R_SetupGenericTwoTextureShader(int texturemode)
1519 if (gl_support_fragment_shader)
1521 if (r_glsl.integer && r_glsl_usegeneric.integer)
1522 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1523 else if (r_glsl_permutation)
1525 r_glsl_permutation = NULL;
1526 qglUseProgramObjectARB(0);CHECKGLERROR
1529 if (!r_glsl_permutation)
1531 if (texturemode == GL_DECAL && gl_combine.integer)
1532 texturemode = GL_INTERPOLATE_ARB;
1533 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1537 void R_SetupDepthOrShadowShader(void)
1539 if (gl_support_fragment_shader)
1541 if (r_glsl.integer && r_glsl_usegeneric.integer)
1542 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1543 else if (r_glsl_permutation)
1545 r_glsl_permutation = NULL;
1546 qglUseProgramObjectARB(0);CHECKGLERROR
1551 extern rtexture_t *r_shadow_attenuationgradienttexture;
1552 extern rtexture_t *r_shadow_attenuation2dtexture;
1553 extern rtexture_t *r_shadow_attenuation3dtexture;
1554 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1556 // select a permutation of the lighting shader appropriate to this
1557 // combination of texture, entity, light source, and fogging, only use the
1558 // minimum features necessary to avoid wasting rendering time in the
1559 // fragment shader on features that are not being used
1560 unsigned int permutation = 0;
1561 unsigned int mode = 0;
1562 // TODO: implement geometry-shader based shadow volumes someday
1563 if (r_glsl_offsetmapping.integer)
1565 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1566 if (r_glsl_offsetmapping_reliefmapping.integer)
1567 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1569 if (rsurfacepass == RSURFPASS_BACKGROUND)
1571 // distorted background
1572 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1573 mode = SHADERMODE_WATER;
1575 mode = SHADERMODE_REFRACTION;
1577 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1580 mode = SHADERMODE_LIGHTSOURCE;
1581 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1582 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1583 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1584 permutation |= SHADERPERMUTATION_CUBEFILTER;
1585 if (diffusescale > 0)
1586 permutation |= SHADERPERMUTATION_DIFFUSE;
1587 if (specularscale > 0)
1588 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1589 if (r_refdef.fogenabled)
1590 permutation |= SHADERPERMUTATION_FOG;
1591 if (rsurface.texture->colormapping)
1592 permutation |= SHADERPERMUTATION_COLORMAPPING;
1593 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1594 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1596 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1598 // unshaded geometry (fullbright or ambient model lighting)
1599 mode = SHADERMODE_FLATCOLOR;
1600 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1601 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1602 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1603 permutation |= SHADERPERMUTATION_GLOW;
1604 if (r_refdef.fogenabled)
1605 permutation |= SHADERPERMUTATION_FOG;
1606 if (rsurface.texture->colormapping)
1607 permutation |= SHADERPERMUTATION_COLORMAPPING;
1608 if (r_glsl_offsetmapping.integer)
1610 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1611 if (r_glsl_offsetmapping_reliefmapping.integer)
1612 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1614 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1615 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1616 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1617 permutation |= SHADERPERMUTATION_REFLECTION;
1619 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1621 // directional model lighting
1622 mode = SHADERMODE_LIGHTDIRECTION;
1623 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1624 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1625 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1626 permutation |= SHADERPERMUTATION_GLOW;
1627 permutation |= SHADERPERMUTATION_DIFFUSE;
1628 if (specularscale > 0)
1629 permutation |= SHADERPERMUTATION_SPECULAR;
1630 if (r_refdef.fogenabled)
1631 permutation |= SHADERPERMUTATION_FOG;
1632 if (rsurface.texture->colormapping)
1633 permutation |= SHADERPERMUTATION_COLORMAPPING;
1634 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1635 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1636 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1637 permutation |= SHADERPERMUTATION_REFLECTION;
1639 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1641 // ambient model lighting
1642 mode = SHADERMODE_LIGHTDIRECTION;
1643 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1644 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1645 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1646 permutation |= SHADERPERMUTATION_GLOW;
1647 if (r_refdef.fogenabled)
1648 permutation |= SHADERPERMUTATION_FOG;
1649 if (rsurface.texture->colormapping)
1650 permutation |= SHADERPERMUTATION_COLORMAPPING;
1651 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1652 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1653 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1654 permutation |= SHADERPERMUTATION_REFLECTION;
1659 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1661 // deluxemapping (light direction texture)
1662 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1663 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1665 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1666 permutation |= SHADERPERMUTATION_DIFFUSE;
1667 if (specularscale > 0)
1668 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1670 else if (r_glsl_deluxemapping.integer >= 2)
1672 // fake deluxemapping (uniform light direction in tangentspace)
1673 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1674 permutation |= SHADERPERMUTATION_DIFFUSE;
1675 if (specularscale > 0)
1676 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1678 else if (rsurface.uselightmaptexture)
1680 // ordinary lightmapping (q1bsp, q3bsp)
1681 mode = SHADERMODE_LIGHTMAP;
1685 // ordinary vertex coloring (q3bsp)
1686 mode = SHADERMODE_VERTEXCOLOR;
1688 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1689 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1690 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1691 permutation |= SHADERPERMUTATION_GLOW;
1692 if (r_refdef.fogenabled)
1693 permutation |= SHADERPERMUTATION_FOG;
1694 if (rsurface.texture->colormapping)
1695 permutation |= SHADERPERMUTATION_COLORMAPPING;
1696 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1697 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1698 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1699 permutation |= SHADERPERMUTATION_REFLECTION;
1701 if(permutation & SHADERPERMUTATION_SPECULAR)
1702 if(r_shadow_glossexact.integer)
1703 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
1704 R_SetupShader_SetPermutation(mode, permutation);
1705 if (mode == SHADERMODE_LIGHTSOURCE)
1707 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1708 if (permutation & SHADERPERMUTATION_DIFFUSE)
1710 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1711 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1712 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1713 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1717 // ambient only is simpler
1718 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale, rsurface.texture->lightmapcolor[3]);
1719 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1720 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1721 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1723 // additive passes are only darkened by fog, not tinted
1724 if (r_glsl_permutation->loc_FogColor >= 0)
1725 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1729 if (mode == SHADERMODE_LIGHTDIRECTION)
1731 if (r_glsl_permutation->loc_AmbientColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale * 0.5f, rsurface.modellight_ambient[1] * ambientscale * 0.5f, rsurface.modellight_ambient[2] * ambientscale * 0.5f);
1732 if (r_glsl_permutation->loc_DiffuseColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale * 0.5f, rsurface.modellight_diffuse[1] * diffusescale * 0.5f, rsurface.modellight_diffuse[2] * diffusescale * 0.5f);
1733 if (r_glsl_permutation->loc_SpecularColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * 0.5f, rsurface.modellight_diffuse[1] * specularscale * 0.5f, rsurface.modellight_diffuse[2] * specularscale * 0.5f);
1734 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1738 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
1739 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1740 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1742 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
1743 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1744 // additive passes are only darkened by fog, not tinted
1745 if (r_glsl_permutation->loc_FogColor >= 0)
1747 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1748 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1750 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1752 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
1753 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
1754 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
1755 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1756 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1757 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1758 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1760 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1762 // The formula used is actually:
1763 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1764 // color.rgb *= SceneBrightness;
1766 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1767 // and do [[calculations]] here in the engine
1768 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1769 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1772 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1773 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1774 if (r_glsl_permutation->loc_Color_Pants >= 0)
1776 if (rsurface.texture->currentskinframe->pants)
1777 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1779 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1781 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1783 if (rsurface.texture->currentskinframe->shirt)
1784 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1786 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1788 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
1789 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
1791 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
1795 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1797 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1801 #define SKINFRAME_HASH 1024
1805 int loadsequence; // incremented each level change
1806 memexpandablearray_t array;
1807 skinframe_t *hash[SKINFRAME_HASH];
1810 r_skinframe_t r_skinframe;
1812 void R_SkinFrame_PrepareForPurge(void)
1814 r_skinframe.loadsequence++;
1815 // wrap it without hitting zero
1816 if (r_skinframe.loadsequence >= 200)
1817 r_skinframe.loadsequence = 1;
1820 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1824 // mark the skinframe as used for the purging code
1825 skinframe->loadsequence = r_skinframe.loadsequence;
1828 void R_SkinFrame_Purge(void)
1832 for (i = 0;i < SKINFRAME_HASH;i++)
1834 for (s = r_skinframe.hash[i];s;s = s->next)
1836 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1838 if (s->merged == s->base)
1840 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1841 R_PurgeTexture(s->stain );s->stain = NULL;
1842 R_PurgeTexture(s->merged);s->merged = NULL;
1843 R_PurgeTexture(s->base );s->base = NULL;
1844 R_PurgeTexture(s->pants );s->pants = NULL;
1845 R_PurgeTexture(s->shirt );s->shirt = NULL;
1846 R_PurgeTexture(s->nmap );s->nmap = NULL;
1847 R_PurgeTexture(s->gloss );s->gloss = NULL;
1848 R_PurgeTexture(s->glow );s->glow = NULL;
1849 R_PurgeTexture(s->fog );s->fog = NULL;
1850 s->loadsequence = 0;
1856 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1858 char basename[MAX_QPATH];
1860 Image_StripImageExtension(name, basename, sizeof(basename));
1862 if( last == NULL ) {
1864 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1865 item = r_skinframe.hash[hashindex];
1870 // linearly search through the hash bucket
1871 for( ; item ; item = item->next ) {
1872 if( !strcmp( item->basename, basename ) ) {
1879 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1883 char basename[MAX_QPATH];
1885 Image_StripImageExtension(name, basename, sizeof(basename));
1887 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1888 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1889 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1893 rtexture_t *dyntexture;
1894 // check whether its a dynamic texture
1895 dyntexture = CL_GetDynTexture( basename );
1896 if (!add && !dyntexture)
1898 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1899 memset(item, 0, sizeof(*item));
1900 strlcpy(item->basename, basename, sizeof(item->basename));
1901 item->base = dyntexture; // either NULL or dyntexture handle
1902 item->textureflags = textureflags;
1903 item->comparewidth = comparewidth;
1904 item->compareheight = compareheight;
1905 item->comparecrc = comparecrc;
1906 item->next = r_skinframe.hash[hashindex];
1907 r_skinframe.hash[hashindex] = item;
1909 else if( item->base == NULL )
1911 rtexture_t *dyntexture;
1912 // check whether its a dynamic texture
1913 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
1914 dyntexture = CL_GetDynTexture( basename );
1915 item->base = dyntexture; // either NULL or dyntexture handle
1918 R_SkinFrame_MarkUsed(item);
1922 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
1924 unsigned long long avgcolor[5], wsum; \
1932 for(pix = 0; pix < cnt; ++pix) \
1935 for(comp = 0; comp < 3; ++comp) \
1937 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
1940 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1942 for(comp = 0; comp < 3; ++comp) \
1943 avgcolor[comp] += getpixel * w; \
1946 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1947 avgcolor[4] += getpixel; \
1949 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
1951 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
1952 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
1953 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
1954 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
1957 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
1959 // FIXME: it should be possible to disable loading various layers using
1960 // cvars, to prevent wasted loading time and memory usage if the user does
1962 qboolean loadnormalmap = true;
1963 qboolean loadgloss = true;
1964 qboolean loadpantsandshirt = true;
1965 qboolean loadglow = true;
1967 unsigned char *pixels;
1968 unsigned char *bumppixels;
1969 unsigned char *basepixels = NULL;
1970 int basepixels_width;
1971 int basepixels_height;
1972 skinframe_t *skinframe;
1976 if (cls.state == ca_dedicated)
1979 // return an existing skinframe if already loaded
1980 // if loading of the first image fails, don't make a new skinframe as it
1981 // would cause all future lookups of this to be missing
1982 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1983 if (skinframe && skinframe->base)
1986 basepixels = loadimagepixelsbgra(name, complain, true);
1987 if (basepixels == NULL)
1990 if (developer_loading.integer)
1991 Con_Printf("loading skin \"%s\"\n", name);
1993 // we've got some pixels to store, so really allocate this new texture now
1995 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1996 skinframe->stain = NULL;
1997 skinframe->merged = NULL;
1998 skinframe->base = r_texture_notexture;
1999 skinframe->pants = NULL;
2000 skinframe->shirt = NULL;
2001 skinframe->nmap = r_texture_blanknormalmap;
2002 skinframe->gloss = NULL;
2003 skinframe->glow = NULL;
2004 skinframe->fog = NULL;
2006 basepixels_width = image_width;
2007 basepixels_height = image_height;
2008 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2010 if (textureflags & TEXF_ALPHA)
2012 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2013 if (basepixels[j] < 255)
2015 if (j < basepixels_width * basepixels_height * 4)
2017 // has transparent pixels
2019 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2020 for (j = 0;j < image_width * image_height * 4;j += 4)
2025 pixels[j+3] = basepixels[j+3];
2027 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2032 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2033 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2035 // _norm is the name used by tenebrae and has been adopted as standard
2038 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2040 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2044 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2046 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2047 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2048 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2050 Mem_Free(bumppixels);
2052 else if (r_shadow_bumpscale_basetexture.value > 0)
2054 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2055 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2056 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2060 // _luma is supported for tenebrae compatibility
2061 // (I think it's a very stupid name, but oh well)
2062 // _glow is the preferred name
2063 if (loadglow && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) != NULL || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2064 if (loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2065 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2066 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2069 Mem_Free(basepixels);
2074 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2077 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2080 static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
2085 for (i = 0;i < width*height;i++)
2086 if (((unsigned char *)&palette[in[i]])[3] > 0)
2088 if (i == width*height)
2091 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2094 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2095 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2098 unsigned char *temp1, *temp2;
2099 skinframe_t *skinframe;
2101 if (cls.state == ca_dedicated)
2104 // if already loaded just return it, otherwise make a new skinframe
2105 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2106 if (skinframe && skinframe->base)
2109 skinframe->stain = NULL;
2110 skinframe->merged = NULL;
2111 skinframe->base = r_texture_notexture;
2112 skinframe->pants = NULL;
2113 skinframe->shirt = NULL;
2114 skinframe->nmap = r_texture_blanknormalmap;
2115 skinframe->gloss = NULL;
2116 skinframe->glow = NULL;
2117 skinframe->fog = NULL;
2119 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2123 if (developer_loading.integer)
2124 Con_Printf("loading 32bit skin \"%s\"\n", name);
2126 if (r_shadow_bumpscale_basetexture.value > 0)
2128 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2129 temp2 = temp1 + width * height * 4;
2130 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2131 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2134 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2135 if (textureflags & TEXF_ALPHA)
2137 for (i = 3;i < width * height * 4;i += 4)
2138 if (skindata[i] < 255)
2140 if (i < width * height * 4)
2142 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2143 memcpy(fogpixels, skindata, width * height * 4);
2144 for (i = 0;i < width * height * 4;i += 4)
2145 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2146 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2147 Mem_Free(fogpixels);
2151 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2152 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2157 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2160 unsigned char *temp1, *temp2;
2161 unsigned int *palette;
2162 skinframe_t *skinframe;
2164 if (cls.state == ca_dedicated)
2167 // if already loaded just return it, otherwise make a new skinframe
2168 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2169 if (skinframe && skinframe->base)
2172 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2174 skinframe->stain = NULL;
2175 skinframe->merged = NULL;
2176 skinframe->base = r_texture_notexture;
2177 skinframe->pants = NULL;
2178 skinframe->shirt = NULL;
2179 skinframe->nmap = r_texture_blanknormalmap;
2180 skinframe->gloss = NULL;
2181 skinframe->glow = NULL;
2182 skinframe->fog = NULL;
2184 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2188 if (developer_loading.integer)
2189 Con_Printf("loading quake skin \"%s\"\n", name);
2191 if (r_shadow_bumpscale_basetexture.value > 0)
2193 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2194 temp2 = temp1 + width * height * 4;
2195 // use either a custom palette or the quake palette
2196 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2197 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2198 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2201 // use either a custom palette, or the quake palette
2202 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2203 if (loadglowtexture)
2204 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2205 if (loadpantsandshirt)
2207 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2208 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2210 if (skinframe->pants || skinframe->shirt)
2211 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename), loadglowtexture ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap, skinframe->textureflags, false); // no special colors
2212 if (textureflags & TEXF_ALPHA)
2214 for (i = 0;i < width * height;i++)
2215 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2217 if (i < width * height)
2218 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2221 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2222 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2227 skinframe_t *R_SkinFrame_LoadMissing(void)
2229 skinframe_t *skinframe;
2231 if (cls.state == ca_dedicated)
2234 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2235 skinframe->stain = NULL;
2236 skinframe->merged = NULL;
2237 skinframe->base = r_texture_notexture;
2238 skinframe->pants = NULL;
2239 skinframe->shirt = NULL;
2240 skinframe->nmap = r_texture_blanknormalmap;
2241 skinframe->gloss = NULL;
2242 skinframe->glow = NULL;
2243 skinframe->fog = NULL;
2245 skinframe->avgcolor[0] = rand() / RAND_MAX;
2246 skinframe->avgcolor[1] = rand() / RAND_MAX;
2247 skinframe->avgcolor[2] = rand() / RAND_MAX;
2248 skinframe->avgcolor[3] = 1;
2253 void gl_main_start(void)
2257 memset(r_queries, 0, sizeof(r_queries));
2259 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2260 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2262 // set up r_skinframe loading system for textures
2263 memset(&r_skinframe, 0, sizeof(r_skinframe));
2264 r_skinframe.loadsequence = 1;
2265 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2267 r_main_texturepool = R_AllocTexturePool();
2268 R_BuildBlankTextures();
2270 if (gl_texturecubemap)
2273 R_BuildNormalizationCube();
2275 r_texture_fogattenuation = NULL;
2276 r_texture_gammaramps = NULL;
2277 //r_texture_fogintensity = NULL;
2278 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2279 memset(&r_waterstate, 0, sizeof(r_waterstate));
2280 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2281 memset(&r_svbsp, 0, sizeof (r_svbsp));
2283 r_refdef.fogmasktable_density = 0;
2286 extern rtexture_t *loadingscreentexture;
2287 void gl_main_shutdown(void)
2290 qglDeleteQueriesARB(r_maxqueries, r_queries);
2294 memset(r_queries, 0, sizeof(r_queries));
2296 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2297 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2299 // clear out the r_skinframe state
2300 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2301 memset(&r_skinframe, 0, sizeof(r_skinframe));
2304 Mem_Free(r_svbsp.nodes);
2305 memset(&r_svbsp, 0, sizeof (r_svbsp));
2306 R_FreeTexturePool(&r_main_texturepool);
2307 loadingscreentexture = NULL;
2308 r_texture_blanknormalmap = NULL;
2309 r_texture_white = NULL;
2310 r_texture_grey128 = NULL;
2311 r_texture_black = NULL;
2312 r_texture_whitecube = NULL;
2313 r_texture_normalizationcube = NULL;
2314 r_texture_fogattenuation = NULL;
2315 r_texture_gammaramps = NULL;
2316 //r_texture_fogintensity = NULL;
2317 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2318 memset(&r_waterstate, 0, sizeof(r_waterstate));
2322 extern void CL_ParseEntityLump(char *entitystring);
2323 void gl_main_newmap(void)
2325 // FIXME: move this code to client
2327 char *entities, entname[MAX_QPATH];
2330 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2331 l = (int)strlen(entname) - 4;
2332 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2334 memcpy(entname + l, ".ent", 5);
2335 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2337 CL_ParseEntityLump(entities);
2342 if (cl.worldmodel->brush.entities)
2343 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2347 void GL_Main_Init(void)
2349 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2351 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2352 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2353 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2354 if (gamemode == GAME_NEHAHRA)
2356 Cvar_RegisterVariable (&gl_fogenable);
2357 Cvar_RegisterVariable (&gl_fogdensity);
2358 Cvar_RegisterVariable (&gl_fogred);
2359 Cvar_RegisterVariable (&gl_foggreen);
2360 Cvar_RegisterVariable (&gl_fogblue);
2361 Cvar_RegisterVariable (&gl_fogstart);
2362 Cvar_RegisterVariable (&gl_fogend);
2363 Cvar_RegisterVariable (&gl_skyclip);
2365 Cvar_RegisterVariable(&r_depthfirst);
2366 Cvar_RegisterVariable(&r_useinfinitefarclip);
2367 Cvar_RegisterVariable(&r_nearclip);
2368 Cvar_RegisterVariable(&r_showbboxes);
2369 Cvar_RegisterVariable(&r_showsurfaces);
2370 Cvar_RegisterVariable(&r_showtris);
2371 Cvar_RegisterVariable(&r_shownormals);
2372 Cvar_RegisterVariable(&r_showlighting);
2373 Cvar_RegisterVariable(&r_showshadowvolumes);
2374 Cvar_RegisterVariable(&r_showcollisionbrushes);
2375 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2376 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2377 Cvar_RegisterVariable(&r_showdisabledepthtest);
2378 Cvar_RegisterVariable(&r_drawportals);
2379 Cvar_RegisterVariable(&r_drawentities);
2380 Cvar_RegisterVariable(&r_cullentities_trace);
2381 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2382 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2383 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2384 Cvar_RegisterVariable(&r_drawviewmodel);
2385 Cvar_RegisterVariable(&r_speeds);
2386 Cvar_RegisterVariable(&r_fullbrights);
2387 Cvar_RegisterVariable(&r_wateralpha);
2388 Cvar_RegisterVariable(&r_dynamic);
2389 Cvar_RegisterVariable(&r_fullbright);
2390 Cvar_RegisterVariable(&r_shadows);
2391 Cvar_RegisterVariable(&r_shadows_throwdistance);
2392 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2393 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2394 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2395 Cvar_RegisterVariable(&r_fog_exp2);
2396 Cvar_RegisterVariable(&r_drawfog);
2397 Cvar_RegisterVariable(&r_textureunits);
2398 Cvar_RegisterVariable(&r_glsl);
2399 Cvar_RegisterVariable(&r_glsl_contrastboost);
2400 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2401 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2402 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2403 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2404 Cvar_RegisterVariable(&r_glsl_postprocess);
2405 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2406 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2407 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2408 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2409 Cvar_RegisterVariable(&r_glsl_usegeneric);
2410 Cvar_RegisterVariable(&r_water);
2411 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2412 Cvar_RegisterVariable(&r_water_clippingplanebias);
2413 Cvar_RegisterVariable(&r_water_refractdistort);
2414 Cvar_RegisterVariable(&r_water_reflectdistort);
2415 Cvar_RegisterVariable(&r_lerpsprites);
2416 Cvar_RegisterVariable(&r_lerpmodels);
2417 Cvar_RegisterVariable(&r_lerplightstyles);
2418 Cvar_RegisterVariable(&r_waterscroll);
2419 Cvar_RegisterVariable(&r_bloom);
2420 Cvar_RegisterVariable(&r_bloom_colorscale);
2421 Cvar_RegisterVariable(&r_bloom_brighten);
2422 Cvar_RegisterVariable(&r_bloom_blur);
2423 Cvar_RegisterVariable(&r_bloom_resolution);
2424 Cvar_RegisterVariable(&r_bloom_colorexponent);
2425 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2426 Cvar_RegisterVariable(&r_hdr);
2427 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2428 Cvar_RegisterVariable(&r_hdr_glowintensity);
2429 Cvar_RegisterVariable(&r_hdr_range);
2430 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2431 Cvar_RegisterVariable(&developer_texturelogging);
2432 Cvar_RegisterVariable(&gl_lightmaps);
2433 Cvar_RegisterVariable(&r_test);
2434 Cvar_RegisterVariable(&r_batchmode);
2435 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2436 Cvar_SetValue("r_fullbrights", 0);
2437 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2439 Cvar_RegisterVariable(&r_track_sprites);
2440 Cvar_RegisterVariable(&r_track_sprites_flags);
2441 Cvar_RegisterVariable(&r_track_sprites_scalew);
2442 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2445 extern void R_Textures_Init(void);
2446 extern void GL_Draw_Init(void);
2447 extern void GL_Main_Init(void);
2448 extern void R_Shadow_Init(void);
2449 extern void R_Sky_Init(void);
2450 extern void GL_Surf_Init(void);
2451 extern void R_Particles_Init(void);
2452 extern void R_Explosion_Init(void);
2453 extern void gl_backend_init(void);
2454 extern void Sbar_Init(void);
2455 extern void R_LightningBeams_Init(void);
2456 extern void Mod_RenderInit(void);
2458 void Render_Init(void)
2470 R_LightningBeams_Init();
2479 extern char *ENGINE_EXTENSIONS;
2482 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2483 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2484 gl_version = (const char *)qglGetString(GL_VERSION);
2485 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2489 if (!gl_platformextensions)
2490 gl_platformextensions = "";
2492 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2493 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2494 Con_Printf("GL_VERSION: %s\n", gl_version);
2495 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2496 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2498 VID_CheckExtensions();
2500 // LordHavoc: report supported extensions
2501 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2503 // clear to black (loading plaque will be seen over this)
2505 qglClearColor(0,0,0,1);CHECKGLERROR
2506 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2509 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2513 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2515 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2518 p = r_refdef.view.frustum + i;
2523 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2527 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2531 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2535 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2539 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2543 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2547 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2551 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2559 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2563 for (i = 0;i < numplanes;i++)
2570 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2574 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2578 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2582 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2586 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2590 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2594 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2598 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2606 //==================================================================================
2608 static void R_View_UpdateEntityLighting (void)
2611 entity_render_t *ent;
2612 vec3_t tempdiffusenormal;
2614 for (i = 0;i < r_refdef.scene.numentities;i++)
2616 ent = r_refdef.scene.entities[i];
2618 // skip unseen models
2619 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
2623 if (ent->model && ent->model->brush.num_leafs)
2625 // TODO: use modellight for r_ambient settings on world?
2626 VectorSet(ent->modellight_ambient, 0, 0, 0);
2627 VectorSet(ent->modellight_diffuse, 0, 0, 0);
2628 VectorSet(ent->modellight_lightdir, 0, 0, 1);
2632 // fetch the lighting from the worldmodel data
2633 VectorSet(ent->modellight_ambient, r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f));
2634 VectorClear(ent->modellight_diffuse);
2635 VectorClear(tempdiffusenormal);
2636 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
2639 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2640 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2643 VectorSet(ent->modellight_ambient, 1, 1, 1);
2645 // move the light direction into modelspace coordinates for lighting code
2646 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2647 if(VectorLength2(ent->modellight_lightdir) == 0)
2648 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2649 VectorNormalize(ent->modellight_lightdir);
2653 static void R_View_UpdateEntityVisible (void)
2656 entity_render_t *ent;
2658 if (!r_drawentities.integer)
2661 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2662 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2664 // worldmodel can check visibility
2665 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2666 for (i = 0;i < r_refdef.scene.numentities;i++)
2668 ent = r_refdef.scene.entities[i];
2669 if (!(ent->flags & renderimask))
2670 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
2671 if ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
2672 r_refdef.viewcache.entityvisible[i] = true;
2674 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2676 for (i = 0;i < r_refdef.scene.numentities;i++)
2678 ent = r_refdef.scene.entities[i];
2679 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2681 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.scene.worldmodel, r_refdef.view.origin, ent->mins, ent->maxs))
2682 ent->last_trace_visibility = realtime;
2683 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2684 r_refdef.viewcache.entityvisible[i] = 0;
2691 // no worldmodel or it can't check visibility
2692 for (i = 0;i < r_refdef.scene.numentities;i++)
2694 ent = r_refdef.scene.entities[i];
2695 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
2700 // only used if skyrendermasked, and normally returns false
2701 int R_DrawBrushModelsSky (void)
2704 entity_render_t *ent;
2706 if (!r_drawentities.integer)
2710 for (i = 0;i < r_refdef.scene.numentities;i++)
2712 if (!r_refdef.viewcache.entityvisible[i])
2714 ent = r_refdef.scene.entities[i];
2715 if (!ent->model || !ent->model->DrawSky)
2717 ent->model->DrawSky(ent);
2723 static void R_DrawNoModel(entity_render_t *ent);
2724 static void R_DrawModels(void)
2727 entity_render_t *ent;
2729 if (!r_drawentities.integer)
2732 for (i = 0;i < r_refdef.scene.numentities;i++)
2734 if (!r_refdef.viewcache.entityvisible[i])
2736 ent = r_refdef.scene.entities[i];
2737 r_refdef.stats.entities++;
2738 if (ent->model && ent->model->Draw != NULL)
2739 ent->model->Draw(ent);
2745 static void R_DrawModelsDepth(void)
2748 entity_render_t *ent;
2750 if (!r_drawentities.integer)
2753 for (i = 0;i < r_refdef.scene.numentities;i++)
2755 if (!r_refdef.viewcache.entityvisible[i])
2757 ent = r_refdef.scene.entities[i];
2758 if (ent->model && ent->model->DrawDepth != NULL)
2759 ent->model->DrawDepth(ent);
2763 static void R_DrawModelsDebug(void)
2766 entity_render_t *ent;
2768 if (!r_drawentities.integer)
2771 for (i = 0;i < r_refdef.scene.numentities;i++)
2773 if (!r_refdef.viewcache.entityvisible[i])
2775 ent = r_refdef.scene.entities[i];
2776 if (ent->model && ent->model->DrawDebug != NULL)
2777 ent->model->DrawDebug(ent);
2781 static void R_DrawModelsAddWaterPlanes(void)
2784 entity_render_t *ent;
2786 if (!r_drawentities.integer)
2789 for (i = 0;i < r_refdef.scene.numentities;i++)
2791 if (!r_refdef.viewcache.entityvisible[i])
2793 ent = r_refdef.scene.entities[i];
2794 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2795 ent->model->DrawAddWaterPlanes(ent);
2799 static void R_View_SetFrustum(void)
2802 double slopex, slopey;
2803 vec3_t forward, left, up, origin;
2805 // we can't trust r_refdef.view.forward and friends in reflected scenes
2806 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2809 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2810 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2811 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2812 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2813 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2814 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2815 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2816 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2817 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2818 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2819 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2820 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2824 zNear = r_refdef.nearclip;
2825 nudge = 1.0 - 1.0 / (1<<23);
2826 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2827 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2828 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2829 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2830 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2831 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2832 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2833 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2839 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2840 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2841 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2842 r_refdef.view.frustum[0].dist = m[15] - m[12];
2844 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2845 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2846 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2847 r_refdef.view.frustum[1].dist = m[15] + m[12];
2849 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2850 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2851 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2852 r_refdef.view.frustum[2].dist = m[15] - m[13];
2854 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2855 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2856 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2857 r_refdef.view.frustum[3].dist = m[15] + m[13];
2859 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2860 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2861 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2862 r_refdef.view.frustum[4].dist = m[15] - m[14];
2864 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2865 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2866 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2867 r_refdef.view.frustum[5].dist = m[15] + m[14];
2870 if (r_refdef.view.useperspective)
2872 slopex = 1.0 / r_refdef.view.frustum_x;
2873 slopey = 1.0 / r_refdef.view.frustum_y;
2874 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2875 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
2876 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
2877 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
2878 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2880 // Leaving those out was a mistake, those were in the old code, and they
2881 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2882 // I couldn't reproduce it after adding those normalizations. --blub
2883 VectorNormalize(r_refdef.view.frustum[0].normal);
2884 VectorNormalize(r_refdef.view.frustum[1].normal);
2885 VectorNormalize(r_refdef.view.frustum[2].normal);
2886 VectorNormalize(r_refdef.view.frustum[3].normal);
2888 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2889 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2890 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2891 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2892 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2894 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2895 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2896 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2897 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2898 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2902 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2903 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2904 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2905 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2906 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2907 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2908 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2909 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2910 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2911 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2913 r_refdef.view.numfrustumplanes = 5;
2915 if (r_refdef.view.useclipplane)
2917 r_refdef.view.numfrustumplanes = 6;
2918 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2921 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2922 PlaneClassify(r_refdef.view.frustum + i);
2924 // LordHavoc: note to all quake engine coders, Quake had a special case
2925 // for 90 degrees which assumed a square view (wrong), so I removed it,
2926 // Quake2 has it disabled as well.
2928 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2929 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2930 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2931 //PlaneClassify(&frustum[0]);
2933 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2934 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2935 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2936 //PlaneClassify(&frustum[1]);
2938 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2939 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2940 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2941 //PlaneClassify(&frustum[2]);
2943 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2944 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2945 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2946 //PlaneClassify(&frustum[3]);
2949 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2950 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2951 //PlaneClassify(&frustum[4]);
2954 void R_View_Update(void)
2956 R_View_SetFrustum();
2957 R_View_WorldVisibility(r_refdef.view.useclipplane);
2958 R_View_UpdateEntityVisible();
2959 R_View_UpdateEntityLighting();
2962 void R_SetupView(qboolean allowwaterclippingplane)
2964 if (!r_refdef.view.useperspective)
2965 GL_SetupView_Mode_Ortho(-r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
2966 else if (gl_stencil && r_useinfinitefarclip.integer)
2967 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2969 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2971 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2973 if (r_refdef.view.useclipplane && allowwaterclippingplane)
2975 // LordHavoc: couldn't figure out how to make this approach the
2976 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2977 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2978 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2979 dist = r_refdef.view.clipplane.dist;
2980 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2984 void R_ResetViewRendering2D(void)
2988 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2989 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2990 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2991 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2992 GL_Color(1, 1, 1, 1);
2993 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2994 GL_BlendFunc(GL_ONE, GL_ZERO);
2995 GL_AlphaTest(false);
2996 GL_ScissorTest(false);
2997 GL_DepthMask(false);
2998 GL_DepthRange(0, 1);
2999 GL_DepthTest(false);
3000 R_Mesh_Matrix(&identitymatrix);
3001 R_Mesh_ResetTextureState();
3002 GL_PolygonOffset(0, 0);
3003 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3004 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3005 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3006 qglStencilMask(~0);CHECKGLERROR
3007 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3008 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3009 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3010 R_SetupGenericShader(true);
3013 void R_ResetViewRendering3D(void)
3017 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3018 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3020 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3021 GL_Color(1, 1, 1, 1);
3022 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3023 GL_BlendFunc(GL_ONE, GL_ZERO);
3024 GL_AlphaTest(false);
3025 GL_ScissorTest(true);
3027 GL_DepthRange(0, 1);
3029 R_Mesh_Matrix(&identitymatrix);
3030 R_Mesh_ResetTextureState();
3031 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3032 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3033 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3034 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3035 qglStencilMask(~0);CHECKGLERROR
3036 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3037 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3038 GL_CullFace(r_refdef.view.cullface_back);
3039 R_SetupGenericShader(true);
3042 void R_RenderScene(void);
3043 void R_RenderWaterPlanes(void);
3045 static void R_Water_StartFrame(void)
3048 int waterwidth, waterheight, texturewidth, textureheight;
3049 r_waterstate_waterplane_t *p;
3051 // set waterwidth and waterheight to the water resolution that will be
3052 // used (often less than the screen resolution for faster rendering)
3053 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3054 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3056 // calculate desired texture sizes
3057 // can't use water if the card does not support the texture size
3058 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3059 texturewidth = textureheight = waterwidth = waterheight = 0;
3060 else if (gl_support_arb_texture_non_power_of_two)
3062 texturewidth = waterwidth;
3063 textureheight = waterheight;
3067 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3068 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3071 // allocate textures as needed
3072 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3074 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3075 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3077 if (p->texture_refraction)
3078 R_FreeTexture(p->texture_refraction);
3079 p->texture_refraction = NULL;
3080 if (p->texture_reflection)
3081 R_FreeTexture(p->texture_reflection);
3082 p->texture_reflection = NULL;
3084 memset(&r_waterstate, 0, sizeof(r_waterstate));
3085 r_waterstate.waterwidth = waterwidth;
3086 r_waterstate.waterheight = waterheight;
3087 r_waterstate.texturewidth = texturewidth;
3088 r_waterstate.textureheight = textureheight;
3091 if (r_waterstate.waterwidth)
3093 r_waterstate.enabled = true;
3095 // set up variables that will be used in shader setup
3096 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3097 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3098 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3099 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3102 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3103 r_waterstate.numwaterplanes = 0;
3106 void R_Water_AddWaterPlane(msurface_t *surface)
3108 int triangleindex, planeindex;
3114 r_waterstate_waterplane_t *p;
3115 texture_t *t = R_GetCurrentTexture(surface->texture);
3116 // just use the first triangle with a valid normal for any decisions
3117 VectorClear(normal);
3118 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3120 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3121 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3122 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3123 TriangleNormal(vert[0], vert[1], vert[2], normal);
3124 if (VectorLength2(normal) >= 0.001)
3128 VectorCopy(normal, plane.normal);
3129 VectorNormalize(plane.normal);
3130 plane.dist = DotProduct(vert[0], plane.normal);
3131 PlaneClassify(&plane);
3132 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3134 // skip backfaces (except if nocullface is set)
3135 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3137 VectorNegate(plane.normal, plane.normal);
3139 PlaneClassify(&plane);
3143 // find a matching plane if there is one
3144 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3145 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3147 if (planeindex >= r_waterstate.maxwaterplanes)
3148 return; // nothing we can do, out of planes
3150 // if this triangle does not fit any known plane rendered this frame, add one
3151 if (planeindex >= r_waterstate.numwaterplanes)
3153 // store the new plane
3154 r_waterstate.numwaterplanes++;
3156 // clear materialflags and pvs
3157 p->materialflags = 0;
3158 p->pvsvalid = false;
3160 // merge this surface's materialflags into the waterplane
3161 p->materialflags |= t->currentmaterialflags;
3162 // merge this surface's PVS into the waterplane
3163 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3164 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3165 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3167 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3172 static void R_Water_ProcessPlanes(void)
3174 r_refdef_view_t originalview;
3175 r_refdef_view_t myview;
3177 r_waterstate_waterplane_t *p;
3179 originalview = r_refdef.view;
3181 // make sure enough textures are allocated
3182 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3184 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3186 if (!p->texture_refraction)
3187 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3188 if (!p->texture_refraction)
3192 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3194 if (!p->texture_reflection)
3195 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3196 if (!p->texture_reflection)
3202 r_refdef.view = originalview;
3203 r_refdef.view.showdebug = false;
3204 r_refdef.view.width = r_waterstate.waterwidth;
3205 r_refdef.view.height = r_waterstate.waterheight;
3206 r_refdef.view.useclipplane = true;
3207 myview = r_refdef.view;
3208 r_waterstate.renderingscene = true;
3209 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3211 // render the normal view scene and copy into texture
3212 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
3213 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3215 r_refdef.view = myview;
3216 r_refdef.view.clipplane = p->plane;
3217 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3218 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3219 PlaneClassify(&r_refdef.view.clipplane);
3221 R_ResetViewRendering3D();
3222 R_ClearScreen(r_refdef.fogenabled);
3226 // copy view into the screen texture
3227 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3228 GL_ActiveTexture(0);
3230 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3233 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3235 r_refdef.view = myview;
3236 // render reflected scene and copy into texture
3237 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3238 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3239 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3240 r_refdef.view.clipplane = p->plane;
3241 // reverse the cullface settings for this render
3242 r_refdef.view.cullface_front = GL_FRONT;
3243 r_refdef.view.cullface_back = GL_BACK;
3244 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3246 r_refdef.view.usecustompvs = true;
3248 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3250 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3253 R_ResetViewRendering3D();
3254 R_ClearScreen(r_refdef.fogenabled);
3258 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3259 GL_ActiveTexture(0);
3261 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3264 r_waterstate.renderingscene = false;
3265 r_refdef.view = originalview;
3266 R_ResetViewRendering3D();
3267 R_ClearScreen(r_refdef.fogenabled);
3271 r_refdef.view = originalview;
3272 r_waterstate.renderingscene = false;
3273 Cvar_SetValueQuick(&r_water, 0);
3274 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3278 void R_Bloom_StartFrame(void)
3280 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3282 // set bloomwidth and bloomheight to the bloom resolution that will be
3283 // used (often less than the screen resolution for faster rendering)
3284 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3285 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3286 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3287 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3288 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3290 // calculate desired texture sizes
3291 if (gl_support_arb_texture_non_power_of_two)
3293 screentexturewidth = r_refdef.view.width;
3294 screentextureheight = r_refdef.view.height;
3295 bloomtexturewidth = r_bloomstate.bloomwidth;
3296 bloomtextureheight = r_bloomstate.bloomheight;
3300 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3301 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3302 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3303 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3306 if ((r_hdr.integer || r_bloom.integer) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
3308 Cvar_SetValueQuick(&r_hdr, 0);
3309 Cvar_SetValueQuick(&r_bloom, 0);
3312 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
3313 screentexturewidth = screentextureheight = 0;
3314 if (!r_hdr.integer && !r_bloom.integer)
3315 bloomtexturewidth = bloomtextureheight = 0;
3317 // allocate textures as needed
3318 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3320 if (r_bloomstate.texture_screen)
3321 R_FreeTexture(r_bloomstate.texture_screen);
3322 r_bloomstate.texture_screen = NULL;
3323 r_bloomstate.screentexturewidth = screentexturewidth;
3324 r_bloomstate.screentextureheight = screentextureheight;
3325 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3326 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3328 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3330 if (r_bloomstate.texture_bloom)
3331 R_FreeTexture(r_bloomstate.texture_bloom);
3332 r_bloomstate.texture_bloom = NULL;
3333 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3334 r_bloomstate.bloomtextureheight = bloomtextureheight;
3335 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3336 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3339 // set up a texcoord array for the full resolution screen image
3340 // (we have to keep this around to copy back during final render)
3341 r_bloomstate.screentexcoord2f[0] = 0;
3342 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3343 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3344 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3345 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3346 r_bloomstate.screentexcoord2f[5] = 0;
3347 r_bloomstate.screentexcoord2f[6] = 0;
3348 r_bloomstate.screentexcoord2f[7] = 0;
3350 // set up a texcoord array for the reduced resolution bloom image
3351 // (which will be additive blended over the screen image)
3352 r_bloomstate.bloomtexcoord2f[0] = 0;
3353 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3354 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3355 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3356 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3357 r_bloomstate.bloomtexcoord2f[5] = 0;
3358 r_bloomstate.bloomtexcoord2f[6] = 0;
3359 r_bloomstate.bloomtexcoord2f[7] = 0;
3361 if (r_hdr.integer || r_bloom.integer)
3363 r_bloomstate.enabled = true;
3364 r_bloomstate.hdr = r_hdr.integer != 0;
3368 void R_Bloom_CopyBloomTexture(float colorscale)
3370 r_refdef.stats.bloom++;
3372 // scale down screen texture to the bloom texture size
3374 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3375 GL_BlendFunc(GL_ONE, GL_ZERO);
3376 GL_Color(colorscale, colorscale, colorscale, 1);
3377 // TODO: optimize with multitexture or GLSL
3378 R_SetupGenericShader(true);
3379 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3380 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3381 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3382 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3384 // we now have a bloom image in the framebuffer
3385 // copy it into the bloom image texture for later processing
3386 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3387 GL_ActiveTexture(0);
3389 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3390 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3393 void R_Bloom_CopyHDRTexture(void)
3395 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3396 GL_ActiveTexture(0);
3398 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3399 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3402 void R_Bloom_MakeTexture(void)
3405 float xoffset, yoffset, r, brighten;
3407 r_refdef.stats.bloom++;
3409 R_ResetViewRendering2D();
3410 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3411 R_Mesh_ColorPointer(NULL, 0, 0);
3412 R_SetupGenericShader(true);
3414 // we have a bloom image in the framebuffer
3416 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3418 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3421 r = bound(0, r_bloom_colorexponent.value / x, 1);
3422 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3423 GL_Color(r, r, r, 1);
3424 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3425 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3426 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3427 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3429 // copy the vertically blurred bloom view to a texture
3430 GL_ActiveTexture(0);
3432 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3433 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3436 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3437 brighten = r_bloom_brighten.value;
3439 brighten *= r_hdr_range.value;
3440 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3441 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3443 for (dir = 0;dir < 2;dir++)
3445 // blend on at multiple vertical offsets to achieve a vertical blur
3446 // TODO: do offset blends using GLSL
3447 GL_BlendFunc(GL_ONE, GL_ZERO);
3448 for (x = -range;x <= range;x++)
3450 if (!dir){xoffset = 0;yoffset = x;}
3451 else {xoffset = x;yoffset = 0;}
3452 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3453 yoffset /= (float)r_bloomstate.bloomtextureheight;
3454 // compute a texcoord array with the specified x and y offset
3455 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3456 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3457 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3458 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3459 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3460 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3461 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3462 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3463 // this r value looks like a 'dot' particle, fading sharply to
3464 // black at the edges
3465 // (probably not realistic but looks good enough)
3466 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3467 //r = (dir ? 1.0f : brighten)/(range*2+1);
3468 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3469 GL_Color(r, r, r, 1);
3470 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3471 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3472 GL_BlendFunc(GL_ONE, GL_ONE);
3475 // copy the vertically blurred bloom view to a texture
3476 GL_ActiveTexture(0);
3478 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3479 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3482 // apply subtract last
3483 // (just like it would be in a GLSL shader)
3484 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3486 GL_BlendFunc(GL_ONE, GL_ZERO);
3487 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3488 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3489 GL_Color(1, 1, 1, 1);
3490 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3491 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3493 GL_BlendFunc(GL_ONE, GL_ONE);
3494 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3495 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3496 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3497 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3498 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3499 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3500 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3502 // copy the darkened bloom view to a texture
3503 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3504 GL_ActiveTexture(0);
3506 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3507 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3511 void R_HDR_RenderBloomTexture(void)
3513 int oldwidth, oldheight;
3514 float oldcolorscale;
3516 oldcolorscale = r_refdef.view.colorscale;
3517 oldwidth = r_refdef.view.width;
3518 oldheight = r_refdef.view.height;
3519 r_refdef.view.width = r_bloomstate.bloomwidth;
3520 r_refdef.view.height = r_bloomstate.bloomheight;
3522 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3523 // TODO: add exposure compensation features
3524 // TODO: add fp16 framebuffer support
3526 r_refdef.view.showdebug = false;
3527 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3529 R_ResetViewRendering3D();
3531 R_ClearScreen(r_refdef.fogenabled);
3532 if (r_timereport_active)
3533 R_TimeReport("HDRclear");
3536 if (r_timereport_active)
3537 R_TimeReport("visibility");
3539 r_waterstate.numwaterplanes = 0;
3540 if (r_waterstate.enabled)
3541 R_RenderWaterPlanes();
3543 r_refdef.view.showdebug = true;
3545 r_waterstate.numwaterplanes = 0;
3547 R_ResetViewRendering2D();
3549 R_Bloom_CopyHDRTexture();
3550 R_Bloom_MakeTexture();
3552 // restore the view settings
3553 r_refdef.view.width = oldwidth;
3554 r_refdef.view.height = oldheight;
3555 r_refdef.view.colorscale = oldcolorscale;
3557 R_ResetViewRendering3D();
3559 R_ClearScreen(r_refdef.fogenabled);
3560 if (r_timereport_active)
3561 R_TimeReport("viewclear");
3564 static void R_BlendView(void)
3566 if (r_bloomstate.texture_screen)
3568 // copy view into the screen texture
3569 R_ResetViewRendering2D();
3570 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3571 R_Mesh_ColorPointer(NULL, 0, 0);
3572 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3573 GL_ActiveTexture(0);CHECKGLERROR
3574 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3575 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3578 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3580 unsigned int permutation =
3581 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3582 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3583 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3584 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0);
3586 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3588 // render simple bloom effect
3589 // copy the screen and shrink it and darken it for the bloom process
3590 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3591 // make the bloom texture
3592 R_Bloom_MakeTexture();
3595 R_ResetViewRendering2D();
3596 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3597 R_Mesh_ColorPointer(NULL, 0, 0);
3598 GL_Color(1, 1, 1, 1);
3599 GL_BlendFunc(GL_ONE, GL_ZERO);
3600 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3601 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3602 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3603 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3604 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3605 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3606 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3607 if (r_glsl_permutation->loc_TintColor >= 0)
3608 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3609 if (r_glsl_permutation->loc_ClientTime >= 0)
3610 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3611 if (r_glsl_permutation->loc_PixelSize >= 0)
3612 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3613 if (r_glsl_permutation->loc_UserVec1 >= 0)
3615 float a=0, b=0, c=0, d=0;
3616 #if _MSC_VER >= 1400
3617 #define sscanf sscanf_s
3619 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3620 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3622 if (r_glsl_permutation->loc_UserVec2 >= 0)
3624 float a=0, b=0, c=0, d=0;
3625 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3626 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3628 if (r_glsl_permutation->loc_UserVec3 >= 0)
3630 float a=0, b=0, c=0, d=0;
3631 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3632 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3634 if (r_glsl_permutation->loc_UserVec4 >= 0)
3636 float a=0, b=0, c=0, d=0;
3637 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3638 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3640 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3641 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3647 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3649 // render high dynamic range bloom effect
3650 // the bloom texture was made earlier this render, so we just need to
3651 // blend it onto the screen...
3652 R_ResetViewRendering2D();
3653 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3654 R_Mesh_ColorPointer(NULL, 0, 0);
3655 R_SetupGenericShader(true);
3656 GL_Color(1, 1, 1, 1);
3657 GL_BlendFunc(GL_ONE, GL_ONE);
3658 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3659 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3660 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3661 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3663 else if (r_bloomstate.texture_bloom)
3665 // render simple bloom effect
3666 // copy the screen and shrink it and darken it for the bloom process
3667 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3668 // make the bloom texture
3669 R_Bloom_MakeTexture();
3670 // put the original screen image back in place and blend the bloom
3672 R_ResetViewRendering2D();
3673 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3674 R_Mesh_ColorPointer(NULL, 0, 0);
3675 GL_Color(1, 1, 1, 1);
3676 GL_BlendFunc(GL_ONE, GL_ZERO);
3677 // do both in one pass if possible
3678 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3679 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3680 if (r_textureunits.integer >= 2 && gl_combine.integer)
3682 R_SetupGenericTwoTextureShader(GL_ADD);
3683 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3684 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3688 R_SetupGenericShader(true);
3689 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3690 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3691 // now blend on the bloom texture
3692 GL_BlendFunc(GL_ONE, GL_ONE);
3693 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3694 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3696 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3697 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3699 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3701 // apply a color tint to the whole view
3702 R_ResetViewRendering2D();
3703 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3704 R_Mesh_ColorPointer(NULL, 0, 0);
3705 R_SetupGenericShader(false);
3706 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3707 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3708 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3712 matrix4x4_t r_waterscrollmatrix;
3714 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3716 if (r_refdef.fog_density)
3718 r_refdef.fogcolor[0] = r_refdef.fog_red;
3719 r_refdef.fogcolor[1] = r_refdef.fog_green;
3720 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3724 VectorCopy(r_refdef.fogcolor, fogvec);
3725 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3727 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3728 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3729 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3730 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3732 // color.rgb *= ContrastBoost * SceneBrightness;
3733 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3734 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3735 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3736 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3741 void R_UpdateVariables(void)
3745 r_refdef.scene.ambient = r_ambient.value;
3747 r_refdef.farclip = 4096;
3748 if (r_refdef.scene.worldmodel)
3749 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3750 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3752 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3753 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3754 r_refdef.polygonfactor = 0;
3755 r_refdef.polygonoffset = 0;
3756 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3757 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3759 r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
3760 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3761 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3762 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3763 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3764 if (r_showsurfaces.integer)
3766 r_refdef.scene.rtworld = false;
3767 r_refdef.scene.rtworldshadows = false;
3768 r_refdef.scene.rtdlight = false;
3769 r_refdef.scene.rtdlightshadows = false;
3770 r_refdef.lightmapintensity = 0;
3773 if (gamemode == GAME_NEHAHRA)
3775 if (gl_fogenable.integer)
3777 r_refdef.oldgl_fogenable = true;
3778 r_refdef.fog_density = gl_fogdensity.value;
3779 r_refdef.fog_red = gl_fogred.value;
3780 r_refdef.fog_green = gl_foggreen.value;
3781 r_refdef.fog_blue = gl_fogblue.value;
3782 r_refdef.fog_alpha = 1;
3783 r_refdef.fog_start = 0;
3784 r_refdef.fog_end = gl_skyclip.value;
3786 else if (r_refdef.oldgl_fogenable)
3788 r_refdef.oldgl_fogenable = false;
3789 r_refdef.fog_density = 0;
3790 r_refdef.fog_red = 0;
3791 r_refdef.fog_green = 0;
3792 r_refdef.fog_blue = 0;
3793 r_refdef.fog_alpha = 0;
3794 r_refdef.fog_start = 0;
3795 r_refdef.fog_end = 0;
3799 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3800 r_refdef.fog_start = max(0, r_refdef.fog_start);
3801 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3803 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3805 if (r_refdef.fog_density && r_drawfog.integer)
3807 r_refdef.fogenabled = true;
3808 // this is the point where the fog reaches 0.9986 alpha, which we
3809 // consider a good enough cutoff point for the texture
3810 // (0.9986 * 256 == 255.6)
3811 if (r_fog_exp2.integer)
3812 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3814 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3815 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3816 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3817 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3818 // fog color was already set
3819 // update the fog texture
3820 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
3821 R_BuildFogTexture();
3824 r_refdef.fogenabled = false;
3826 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
3828 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
3830 // build GLSL gamma texture
3831 #define RAMPWIDTH 256
3832 unsigned short ramp[RAMPWIDTH * 3];
3833 unsigned char rampbgr[RAMPWIDTH][4];
3836 r_texture_gammaramps_serial = vid_gammatables_serial;
3838 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
3839 for(i = 0; i < RAMPWIDTH; ++i)
3841 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3842 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3843 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
3846 if (r_texture_gammaramps)
3848 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
3852 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
3858 // remove GLSL gamma texture
3862 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3863 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3869 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3870 if( scenetype != r_currentscenetype ) {
3871 // store the old scenetype
3872 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3873 r_currentscenetype = scenetype;
3874 // move in the new scene
3875 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3884 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3886 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3887 if( scenetype == r_currentscenetype ) {
3888 return &r_refdef.scene;
3890 return &r_scenes_store[ scenetype ];
3899 void R_RenderView(void)
3901 r_frame++; // used only by R_GetCurrentTexture
3902 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3904 if (r_refdef.view.isoverlay)
3906 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
3907 GL_Clear( GL_DEPTH_BUFFER_BIT );
3908 R_TimeReport("depthclear");
3910 r_refdef.view.showdebug = false;
3912 r_waterstate.enabled = false;
3913 r_waterstate.numwaterplanes = 0;
3921 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
3922 return; //Host_Error ("R_RenderView: NULL worldmodel");
3924 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3926 // break apart the view matrix into vectors for various purposes
3927 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3928 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3929 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3930 VectorNegate(r_refdef.view.left, r_refdef.view.right);
3931 // make an inverted copy of the view matrix for tracking sprites
3932 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3934 R_Shadow_UpdateWorldLightSelection();
3936 R_Bloom_StartFrame();
3937 R_Water_StartFrame();
3940 if (r_timereport_active)
3941 R_TimeReport("viewsetup");
3943 R_ResetViewRendering3D();
3945 if (r_refdef.view.clear || r_refdef.fogenabled)
3947 R_ClearScreen(r_refdef.fogenabled);
3948 if (r_timereport_active)
3949 R_TimeReport("viewclear");
3951 r_refdef.view.clear = true;
3953 // this produces a bloom texture to be used in R_BlendView() later
3955 R_HDR_RenderBloomTexture();
3957 r_refdef.view.showdebug = true;
3960 if (r_timereport_active)
3961 R_TimeReport("visibility");
3963 r_waterstate.numwaterplanes = 0;
3964 if (r_waterstate.enabled)
3965 R_RenderWaterPlanes();
3968 r_waterstate.numwaterplanes = 0;
3971 if (r_timereport_active)
3972 R_TimeReport("blendview");
3974 GL_Scissor(0, 0, vid.width, vid.height);
3975 GL_ScissorTest(false);
3979 void R_RenderWaterPlanes(void)
3981 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3983 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3984 if (r_timereport_active)
3985 R_TimeReport("waterworld");
3988 // don't let sound skip if going slow
3989 if (r_refdef.scene.extraupdate)
3992 R_DrawModelsAddWaterPlanes();
3993 if (r_timereport_active)
3994 R_TimeReport("watermodels");
3996 if (r_waterstate.numwaterplanes)
3998 R_Water_ProcessPlanes();
3999 if (r_timereport_active)
4000 R_TimeReport("waterscenes");
4004 extern void R_DrawLightningBeams (void);
4005 extern void VM_CL_AddPolygonsToMeshQueue (void);
4006 extern void R_DrawPortals (void);
4007 extern cvar_t cl_locs_show;
4008 static void R_DrawLocs(void);
4009 static void R_DrawEntityBBoxes(void);
4010 void R_RenderScene(void)
4012 r_refdef.stats.renders++;
4016 // don't let sound skip if going slow
4017 if (r_refdef.scene.extraupdate)
4020 R_MeshQueue_BeginScene();
4024 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
4026 if (cl.csqc_vidvars.drawworld)
4028 // don't let sound skip if going slow
4029 if (r_refdef.scene.extraupdate)
4032 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4034 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4035 if (r_timereport_active)
4036 R_TimeReport("worldsky");
4039 if (R_DrawBrushModelsSky() && r_timereport_active)
4040 R_TimeReport("bmodelsky");
4043 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4045 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4046 if (r_timereport_active)
4047 R_TimeReport("worlddepth");
4049 if (r_depthfirst.integer >= 2)
4051 R_DrawModelsDepth();
4052 if (r_timereport_active)
4053 R_TimeReport("modeldepth");
4056 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4058 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4059 if (r_timereport_active)
4060 R_TimeReport("world");
4063 // don't let sound skip if going slow
4064 if (r_refdef.scene.extraupdate)
4068 if (r_timereport_active)
4069 R_TimeReport("models");
4071 // don't let sound skip if going slow
4072 if (r_refdef.scene.extraupdate)
4075 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
4077 R_DrawModelShadows();
4079 R_ResetViewRendering3D();
4081 // don't let sound skip if going slow
4082 if (r_refdef.scene.extraupdate)
4086 R_ShadowVolumeLighting(false);
4087 if (r_timereport_active)
4088 R_TimeReport("rtlights");
4090 // don't let sound skip if going slow
4091 if (r_refdef.scene.extraupdate)
4094 if (cl.csqc_vidvars.drawworld)
4096 R_DrawLightningBeams();
4097 if (r_timereport_active)
4098 R_TimeReport("lightning");
4101 if (r_timereport_active)
4102 R_TimeReport("decals");
4105 if (r_timereport_active)
4106 R_TimeReport("particles");
4109 if (r_timereport_active)
4110 R_TimeReport("explosions");
4113 R_SetupGenericShader(true);
4114 VM_CL_AddPolygonsToMeshQueue();
4116 if (r_refdef.view.showdebug)
4118 if (cl_locs_show.integer)
4121 if (r_timereport_active)
4122 R_TimeReport("showlocs");
4125 if (r_drawportals.integer)
4128 if (r_timereport_active)
4129 R_TimeReport("portals");
4132 if (r_showbboxes.value > 0)
4134 R_DrawEntityBBoxes();
4135 if (r_timereport_active)
4136 R_TimeReport("bboxes");
4140 R_SetupGenericShader(true);
4141 R_MeshQueue_RenderTransparent();
4142 if (r_timereport_active)
4143 R_TimeReport("drawtrans");
4145 R_SetupGenericShader(true);
4147 if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0))
4149 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4150 if (r_timereport_active)
4151 R_TimeReport("worlddebug");
4152 R_DrawModelsDebug();
4153 if (r_timereport_active)
4154 R_TimeReport("modeldebug");
4157 R_SetupGenericShader(true);
4159 if (cl.csqc_vidvars.drawworld)
4162 if (r_timereport_active)
4163 R_TimeReport("coronas");
4166 // don't let sound skip if going slow
4167 if (r_refdef.scene.extraupdate)
4170 R_ResetViewRendering2D();
4173 static const unsigned short bboxelements[36] =
4183 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4186 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4187 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4188 GL_DepthMask(false);
4189 GL_DepthRange(0, 1);
4190 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4191 R_Mesh_Matrix(&identitymatrix);
4192 R_Mesh_ResetTextureState();
4194 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4195 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4196 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4197 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4198 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4199 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4200 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4201 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4202 R_FillColors(color4f, 8, cr, cg, cb, ca);
4203 if (r_refdef.fogenabled)
4205 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4207 f1 = FogPoint_World(v);
4209 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4210 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4211 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4214 R_Mesh_VertexPointer(vertex3f, 0, 0);
4215 R_Mesh_ColorPointer(color4f, 0, 0);
4216 R_Mesh_ResetTextureState();
4217 R_SetupGenericShader(false);
4218 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4221 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4225 prvm_edict_t *edict;
4226 prvm_prog_t *prog_save = prog;
4228 // this function draws bounding boxes of server entities
4232 GL_CullFace(GL_NONE);
4233 R_SetupGenericShader(false);
4237 for (i = 0;i < numsurfaces;i++)
4239 edict = PRVM_EDICT_NUM(surfacelist[i]);
4240 switch ((int)edict->fields.server->solid)
4242 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4243 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4244 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4245 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4246 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4247 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4249 color[3] *= r_showbboxes.value;
4250 color[3] = bound(0, color[3], 1);
4251 GL_DepthTest(!r_showdisabledepthtest.integer);
4252 GL_CullFace(r_refdef.view.cullface_front);
4253 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4259 static void R_DrawEntityBBoxes(void)
4262 prvm_edict_t *edict;
4264 prvm_prog_t *prog_save = prog;
4266 // this function draws bounding boxes of server entities
4272 for (i = 0;i < prog->num_edicts;i++)
4274 edict = PRVM_EDICT_NUM(i);
4275 if (edict->priv.server->free)
4277 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4278 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4280 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4282 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4283 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4289 unsigned short nomodelelements[24] =
4301 float nomodelvertex3f[6*3] =
4311 float nomodelcolor4f[6*4] =
4313 0.0f, 0.0f, 0.5f, 1.0f,
4314 0.0f, 0.0f, 0.5f, 1.0f,
4315 0.0f, 0.5f, 0.0f, 1.0f,
4316 0.0f, 0.5f, 0.0f, 1.0f,
4317 0.5f, 0.0f, 0.0f, 1.0f,
4318 0.5f, 0.0f, 0.0f, 1.0f
4321 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4326 // this is only called once per entity so numsurfaces is always 1, and
4327 // surfacelist is always {0}, so this code does not handle batches
4328 R_Mesh_Matrix(&ent->matrix);
4330 if (ent->flags & EF_ADDITIVE)
4332 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4333 GL_DepthMask(false);
4335 else if (ent->alpha < 1)
4337 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4338 GL_DepthMask(false);
4342 GL_BlendFunc(GL_ONE, GL_ZERO);
4345 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4346 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4347 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4348 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4349 R_SetupGenericShader(false);
4350 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4351 if (r_refdef.fogenabled)
4354 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4355 R_Mesh_ColorPointer(color4f, 0, 0);
4356 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4357 f1 = FogPoint_World(org);
4359 for (i = 0, c = color4f;i < 6;i++, c += 4)
4361 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4362 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4363 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4367 else if (ent->alpha != 1)
4369 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4370 R_Mesh_ColorPointer(color4f, 0, 0);
4371 for (i = 0, c = color4f;i < 6;i++, c += 4)
4375 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4376 R_Mesh_ResetTextureState();
4377 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4380 void R_DrawNoModel(entity_render_t *ent)
4383 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4384 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4385 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4387 // R_DrawNoModelCallback(ent, 0);
4390 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4392 vec3_t right1, right2, diff, normal;
4394 VectorSubtract (org2, org1, normal);
4396 // calculate 'right' vector for start
4397 VectorSubtract (r_refdef.view.origin, org1, diff);
4398 CrossProduct (normal, diff, right1);
4399 VectorNormalize (right1);
4401 // calculate 'right' vector for end
4402 VectorSubtract (r_refdef.view.origin, org2, diff);
4403 CrossProduct (normal, diff, right2);
4404 VectorNormalize (right2);
4406 vert[ 0] = org1[0] + width * right1[0];
4407 vert[ 1] = org1[1] + width * right1[1];
4408 vert[ 2] = org1[2] + width * right1[2];
4409 vert[ 3] = org1[0] - width * right1[0];
4410 vert[ 4] = org1[1] - width * right1[1];
4411 vert[ 5] = org1[2] - width * right1[2];
4412 vert[ 6] = org2[0] - width * right2[0];
4413 vert[ 7] = org2[1] - width * right2[1];
4414 vert[ 8] = org2[2] - width * right2[2];
4415 vert[ 9] = org2[0] + width * right2[0];
4416 vert[10] = org2[1] + width * right2[1];
4417 vert[11] = org2[2] + width * right2[2];
4420 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4422 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, qboolean depthdisable, qboolean depthshort, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
4424 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4428 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4429 fog = FogPoint_World(origin);
4431 R_Mesh_Matrix(&identitymatrix);
4432 GL_BlendFunc(blendfunc1, blendfunc2);
4434 GL_CullFace(GL_NONE);
4436 GL_DepthMask(false);
4437 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4438 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4439 GL_DepthTest(!depthdisable);
4441 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4442 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4443 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4444 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4445 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4446 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4447 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4448 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4449 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4450 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4451 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4452 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4454 R_Mesh_VertexPointer(vertex3f, 0, 0);
4455 R_Mesh_ColorPointer(NULL, 0, 0);
4456 R_Mesh_ResetTextureState();
4457 R_SetupGenericShader(true);
4458 R_Mesh_TexBind(0, R_GetTexture(texture));
4459 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4460 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4461 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4462 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4464 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4466 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4467 GL_BlendFunc(blendfunc1, GL_ONE);
4469 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4470 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4474 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4479 VectorSet(v, x, y, z);
4480 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4481 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4483 if (i == mesh->numvertices)
4485 if (mesh->numvertices < mesh->maxvertices)
4487 VectorCopy(v, vertex3f);
4488 mesh->numvertices++;
4490 return mesh->numvertices;
4496 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4500 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4501 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4502 e = mesh->element3i + mesh->numtriangles * 3;
4503 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4505 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4506 if (mesh->numtriangles < mesh->maxtriangles)
4511 mesh->numtriangles++;
4513 element[1] = element[2];
4517 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4521 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4522 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4523 e = mesh->element3i + mesh->numtriangles * 3;
4524 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4526 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4527 if (mesh->numtriangles < mesh->maxtriangles)
4532 mesh->numtriangles++;
4534 element[1] = element[2];
4538 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4539 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4541 int planenum, planenum2;
4544 mplane_t *plane, *plane2;
4546 double temppoints[2][256*3];
4547 // figure out how large a bounding box we need to properly compute this brush
4549 for (w = 0;w < numplanes;w++)
4550 maxdist = max(maxdist, planes[w].dist);
4551 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4552 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4553 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4557 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4558 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4560 if (planenum2 == planenum)
4562 PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
4565 if (tempnumpoints < 3)
4567 // generate elements forming a triangle fan for this polygon
4568 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4572 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
4574 texturelayer_t *layer;
4575 layer = t->currentlayers + t->currentnumlayers++;
4577 layer->depthmask = depthmask;
4578 layer->blendfunc1 = blendfunc1;
4579 layer->blendfunc2 = blendfunc2;
4580 layer->texture = texture;
4581 layer->texmatrix = *matrix;
4582 layer->color[0] = r * r_refdef.view.colorscale;
4583 layer->color[1] = g * r_refdef.view.colorscale;
4584 layer->color[2] = b * r_refdef.view.colorscale;
4585 layer->color[3] = a;
4588 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4591 index = parms[2] + r_refdef.scene.time * parms[3];
4592 index -= floor(index);
4596 case Q3WAVEFUNC_NONE:
4597 case Q3WAVEFUNC_NOISE:
4598 case Q3WAVEFUNC_COUNT:
4601 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4602 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4603 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4604 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4605 case Q3WAVEFUNC_TRIANGLE:
4607 f = index - floor(index);
4618 return (float)(parms[0] + parms[1] * f);
4621 texture_t *R_GetCurrentTexture(texture_t *t)
4625 const entity_render_t *ent = rsurface.entity;
4626 dp_model_t *model = ent->model;
4629 q3shaderinfo_layer_tcmod_t *tcmod;
4631 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
4632 return t->currentframe;
4633 t->update_lastrenderframe = r_frame;
4634 t->update_lastrenderentity = (void *)ent;
4636 // switch to an alternate material if this is a q1bsp animated material
4638 texture_t *texture = t;
4639 int s = ent->skinnum;
4640 if ((unsigned int)s >= (unsigned int)model->numskins)
4642 if (model->skinscenes)
4644 if (model->skinscenes[s].framecount > 1)
4645 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4647 s = model->skinscenes[s].firstframe;
4650 t = t + s * model->num_surfaces;
4653 // use an alternate animation if the entity's frame is not 0,
4654 // and only if the texture has an alternate animation
4655 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
4656 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4658 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4660 texture->currentframe = t;
4663 // update currentskinframe to be a qw skin or animation frame
4664 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[i].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl"))
4666 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4668 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4669 if (developer_loading.integer)
4670 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4671 r_qwskincache_skinframe[i] = R_SkinFrame_LoadExternal(va("skins/%s", r_qwskincache[i]), TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS, developer.integer > 0);
4673 t->currentskinframe = r_qwskincache_skinframe[i];
4674 if (t->currentskinframe == NULL)
4675 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4677 else if (t->numskinframes >= 2)
4678 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4679 if (t->backgroundnumskinframes >= 2)
4680 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
4682 t->currentmaterialflags = t->basematerialflags;
4683 t->currentalpha = ent->alpha;
4684 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4685 t->currentalpha *= r_wateralpha.value;
4686 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4687 t->currentalpha *= t->r_water_wateralpha;
4688 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4689 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4690 if (!(ent->flags & RENDER_LIGHT))
4691 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4692 else if (rsurface.modeltexcoordlightmap2f == NULL)
4694 // pick a model lighting mode
4695 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4696 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4698 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4700 if (ent->effects & EF_ADDITIVE)
4701 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4702 else if (t->currentalpha < 1)
4703 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4704 if (ent->effects & EF_DOUBLESIDED)
4705 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4706 if (ent->effects & EF_NODEPTHTEST)
4707 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4708 if (ent->flags & RENDER_VIEWMODEL)
4709 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4710 if (t->backgroundnumskinframes)
4711 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4712 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4714 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4715 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4718 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4720 // there is no tcmod
4721 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4722 t->currenttexmatrix = r_waterscrollmatrix;
4724 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4727 switch(tcmod->tcmod)
4731 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4732 matrix = r_waterscrollmatrix;
4734 matrix = identitymatrix;
4736 case Q3TCMOD_ENTITYTRANSLATE:
4737 // this is used in Q3 to allow the gamecode to control texcoord
4738 // scrolling on the entity, which is not supported in darkplaces yet.
4739 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4741 case Q3TCMOD_ROTATE:
4742 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4743 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4744 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4747 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4749 case Q3TCMOD_SCROLL:
4750 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4752 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4753 w = (int) tcmod->parms[0];
4754 h = (int) tcmod->parms[1];
4755 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4757 idx = (int) floor(f * w * h);
4758 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4760 case Q3TCMOD_STRETCH:
4761 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4762 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4764 case Q3TCMOD_TRANSFORM:
4765 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4766 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4767 VectorSet(tcmat + 6, 0 , 0 , 1);
4768 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4769 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4771 case Q3TCMOD_TURBULENT:
4772 // this is handled in the RSurf_PrepareVertices function
4773 matrix = identitymatrix;
4776 // either replace or concatenate the transformation
4778 t->currenttexmatrix = matrix;
4781 matrix4x4_t temp = t->currenttexmatrix;
4782 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4786 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4787 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4788 t->glosstexture = r_texture_black;
4789 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4790 t->backgroundglosstexture = r_texture_black;
4791 t->specularpower = r_shadow_glossexponent.value;
4792 // TODO: store reference values for these in the texture?
4793 t->specularscale = 0;
4794 if (r_shadow_gloss.integer > 0)
4796 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4798 if (r_shadow_glossintensity.value > 0)
4800 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4801 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4802 t->specularscale = r_shadow_glossintensity.value;
4805 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4807 t->glosstexture = r_texture_white;
4808 t->backgroundglosstexture = r_texture_white;
4809 t->specularscale = r_shadow_gloss2intensity.value;
4813 // lightmaps mode looks bad with dlights using actual texturing, so turn
4814 // off the colormap and glossmap, but leave the normalmap on as it still
4815 // accurately represents the shading involved
4816 if (gl_lightmaps.integer)
4818 t->basetexture = r_texture_grey128;
4819 t->backgroundbasetexture = NULL;
4820 t->specularscale = 0;
4821 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
4824 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4825 VectorClear(t->dlightcolor);
4826 t->currentnumlayers = 0;
4827 if (t->currentmaterialflags & MATERIALFLAG_WALL)
4830 int blendfunc1, blendfunc2, depthmask;
4831 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4833 blendfunc1 = GL_SRC_ALPHA;
4834 blendfunc2 = GL_ONE;
4836 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4838 blendfunc1 = GL_SRC_ALPHA;
4839 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4841 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4843 blendfunc1 = t->customblendfunc[0];
4844 blendfunc2 = t->customblendfunc[1];
4848 blendfunc1 = GL_ONE;
4849 blendfunc2 = GL_ZERO;
4851 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4852 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4853 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4854 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4856 // fullbright is not affected by r_refdef.lightmapintensity
4857 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4858 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4859 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4860 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4861 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4865 vec3_t ambientcolor;
4867 // set the color tint used for lights affecting this surface
4868 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4870 // q3bsp has no lightmap updates, so the lightstylevalue that
4871 // would normally be baked into the lightmap must be
4872 // applied to the color
4873 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4874 if (ent->model->type == mod_brushq3)
4875 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4876 colorscale *= r_refdef.lightmapintensity;
4877 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
4878 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4879 // basic lit geometry
4880 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4881 // add pants/shirt if needed
4882 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4883 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4884 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4885 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4886 // now add ambient passes if needed
4887 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4889 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
4890 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4891 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4892 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4893 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4896 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4897 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->lightmapcolor[3]);
4898 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4900 // if this is opaque use alpha blend which will darken the earlier
4903 // if this is an alpha blended material, all the earlier passes
4904 // were darkened by fog already, so we only need to add the fog
4905 // color ontop through the fog mask texture
4907 // if this is an additive blended material, all the earlier passes
4908 // were darkened by fog already, and we should not add fog color
4909 // (because the background was not darkened, there is no fog color
4910 // that was lost behind it).
4911 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0] / r_refdef.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]);
4915 return t->currentframe;
4918 rsurfacestate_t rsurface;
4920 void R_Mesh_ResizeArrays(int newvertices)
4923 if (rsurface.array_size >= newvertices)
4925 if (rsurface.array_modelvertex3f)
4926 Mem_Free(rsurface.array_modelvertex3f);
4927 rsurface.array_size = (newvertices + 1023) & ~1023;
4928 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4929 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4930 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4931 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4932 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4933 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4934 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4935 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4936 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4937 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4938 rsurface.array_color4f = base + rsurface.array_size * 27;
4939 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4942 void RSurf_ActiveWorldEntity(void)
4944 dp_model_t *model = r_refdef.scene.worldmodel;
4945 //if (rsurface.entity == r_refdef.scene.worldentity)
4947 rsurface.entity = r_refdef.scene.worldentity;
4948 if (rsurface.array_size < model->surfmesh.num_vertices)
4949 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4950 rsurface.matrix = identitymatrix;
4951 rsurface.inversematrix = identitymatrix;
4952 R_Mesh_Matrix(&identitymatrix);
4953 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4954 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4955 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4956 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4957 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4958 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4959 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
4960 rsurface.frameblend[0].lerp = 1;
4961 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4962 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4963 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4964 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4965 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4966 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4967 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4968 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4969 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4970 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4971 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4972 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4973 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4974 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4975 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4976 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4977 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4978 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4979 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4980 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4981 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4982 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4983 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4984 rsurface.modelelement3i = model->surfmesh.data_element3i;
4985 rsurface.modelelement3s = model->surfmesh.data_element3s;
4986 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
4987 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
4988 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4989 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4990 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4991 rsurface.modelsurfaces = model->data_surfaces;
4992 rsurface.generatedvertex = false;
4993 rsurface.vertex3f = rsurface.modelvertex3f;
4994 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4995 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4996 rsurface.svector3f = rsurface.modelsvector3f;
4997 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4998 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4999 rsurface.tvector3f = rsurface.modeltvector3f;
5000 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5001 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5002 rsurface.normal3f = rsurface.modelnormal3f;
5003 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5004 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5005 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5008 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5010 dp_model_t *model = ent->model;
5011 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5013 rsurface.entity = (entity_render_t *)ent;
5014 if (rsurface.array_size < model->surfmesh.num_vertices)
5015 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5016 rsurface.matrix = ent->matrix;
5017 rsurface.inversematrix = ent->inversematrix;
5018 R_Mesh_Matrix(&rsurface.matrix);
5019 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5020 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5021 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5022 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5023 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5024 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5025 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5026 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5027 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5028 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5029 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5030 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5031 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5032 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5033 if (ent->model->brush.submodel)
5035 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5036 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5038 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5042 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5043 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5044 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5045 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5046 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5048 else if (wantnormals)
5050 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5051 rsurface.modelsvector3f = NULL;
5052 rsurface.modeltvector3f = NULL;
5053 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5054 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5058 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5059 rsurface.modelsvector3f = NULL;
5060 rsurface.modeltvector3f = NULL;
5061 rsurface.modelnormal3f = NULL;
5062 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5064 rsurface.modelvertex3f_bufferobject = 0;
5065 rsurface.modelvertex3f_bufferoffset = 0;
5066 rsurface.modelsvector3f_bufferobject = 0;
5067 rsurface.modelsvector3f_bufferoffset = 0;
5068 rsurface.modeltvector3f_bufferobject = 0;
5069 rsurface.modeltvector3f_bufferoffset = 0;
5070 rsurface.modelnormal3f_bufferobject = 0;
5071 rsurface.modelnormal3f_bufferoffset = 0;
5072 rsurface.generatedvertex = true;
5076 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5077 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5078 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5079 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5080 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5081 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5082 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5083 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5084 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5085 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5086 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5087 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5088 rsurface.generatedvertex = false;
5090 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5091 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5092 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5093 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5094 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5095 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5096 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5097 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5098 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5099 rsurface.modelelement3i = model->surfmesh.data_element3i;
5100 rsurface.modelelement3s = model->surfmesh.data_element3s;
5101 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5102 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5103 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5104 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5105 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5106 rsurface.modelsurfaces = model->data_surfaces;
5107 rsurface.vertex3f = rsurface.modelvertex3f;
5108 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5109 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5110 rsurface.svector3f = rsurface.modelsvector3f;
5111 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5112 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5113 rsurface.tvector3f = rsurface.modeltvector3f;
5114 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5115 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5116 rsurface.normal3f = rsurface.modelnormal3f;
5117 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5118 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5119 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5122 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5123 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5126 int texturesurfaceindex;
5131 const float *v1, *in_tc;
5133 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5135 q3shaderinfo_deform_t *deform;
5136 // if vertices are dynamic (animated models), generate them into the temporary rsurface.array_model* arrays and point rsurface.model* at them instead of the static data from the model itself
5137 if (rsurface.generatedvertex)
5139 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5140 generatenormals = true;
5141 for (i = 0;i < Q3MAXDEFORMS;i++)
5143 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5145 generatetangents = true;
5146 generatenormals = true;
5148 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5149 generatenormals = true;
5151 if (generatenormals && !rsurface.modelnormal3f)
5153 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5154 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5155 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5156 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5158 if (generatetangents && !rsurface.modelsvector3f)
5160 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5161 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5162 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5163 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5164 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5165 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5166 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer);
5169 rsurface.vertex3f = rsurface.modelvertex3f;
5170 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5171 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5172 rsurface.svector3f = rsurface.modelsvector3f;
5173 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5174 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5175 rsurface.tvector3f = rsurface.modeltvector3f;
5176 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5177 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5178 rsurface.normal3f = rsurface.modelnormal3f;
5179 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5180 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5181 // if vertices are deformed (sprite flares and things in maps, possibly
5182 // water waves, bulges and other deformations), generate them into
5183 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5184 // (may be static model data or generated data for an animated model, or
5185 // the previous deform pass)
5186 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5188 switch (deform->deform)
5191 case Q3DEFORM_PROJECTIONSHADOW:
5192 case Q3DEFORM_TEXT0:
5193 case Q3DEFORM_TEXT1:
5194 case Q3DEFORM_TEXT2:
5195 case Q3DEFORM_TEXT3:
5196 case Q3DEFORM_TEXT4:
5197 case Q3DEFORM_TEXT5:
5198 case Q3DEFORM_TEXT6:
5199 case Q3DEFORM_TEXT7:
5202 case Q3DEFORM_AUTOSPRITE:
5203 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5204 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5205 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5206 VectorNormalize(newforward);
5207 VectorNormalize(newright);
5208 VectorNormalize(newup);
5209 // make deformed versions of only the model vertices used by the specified surfaces
5210 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5212 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5213 // a single autosprite surface can contain multiple sprites...
5214 for (j = 0;j < surface->num_vertices - 3;j += 4)
5216 VectorClear(center);
5217 for (i = 0;i < 4;i++)
5218 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5219 VectorScale(center, 0.25f, center);
5220 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5221 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5222 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5223 for (i = 0;i < 4;i++)
5225 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5226 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5229 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer);
5230 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
5232 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5233 rsurface.vertex3f_bufferobject = 0;
5234 rsurface.vertex3f_bufferoffset = 0;
5235 rsurface.svector3f = rsurface.array_deformedsvector3f;
5236 rsurface.svector3f_bufferobject = 0;
5237 rsurface.svector3f_bufferoffset = 0;
5238 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5239 rsurface.tvector3f_bufferobject = 0;
5240 rsurface.tvector3f_bufferoffset = 0;
5241 rsurface.normal3f = rsurface.array_deformednormal3f;
5242 rsurface.normal3f_bufferobject = 0;
5243 rsurface.normal3f_bufferoffset = 0;
5245 case Q3DEFORM_AUTOSPRITE2:
5246 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5247 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5248 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5249 VectorNormalize(newforward);
5250 VectorNormalize(newright);
5251 VectorNormalize(newup);
5252 // make deformed versions of only the model vertices used by the specified surfaces
5253 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5255 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5256 const float *v1, *v2;
5266 memset(shortest, 0, sizeof(shortest));
5267 // a single autosprite surface can contain multiple sprites...
5268 for (j = 0;j < surface->num_vertices - 3;j += 4)
5270 VectorClear(center);
5271 for (i = 0;i < 4;i++)
5272 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5273 VectorScale(center, 0.25f, center);
5274 // find the two shortest edges, then use them to define the
5275 // axis vectors for rotating around the central axis
5276 for (i = 0;i < 6;i++)
5278 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5279 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5281 Debug_PolygonBegin(NULL, 0);
5282 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5283 Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
5284 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5287 l = VectorDistance2(v1, v2);
5288 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5290 l += (1.0f / 1024.0f);
5291 if (shortest[0].length2 > l || i == 0)
5293 shortest[1] = shortest[0];
5294 shortest[0].length2 = l;
5295 shortest[0].v1 = v1;
5296 shortest[0].v2 = v2;
5298 else if (shortest[1].length2 > l || i == 1)
5300 shortest[1].length2 = l;
5301 shortest[1].v1 = v1;
5302 shortest[1].v2 = v2;
5305 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5306 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5308 Debug_PolygonBegin(NULL, 0);
5309 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5310 Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
5311 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5314 // this calculates the right vector from the shortest edge
5315 // and the up vector from the edge midpoints
5316 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5317 VectorNormalize(right);
5318 VectorSubtract(end, start, up);
5319 VectorNormalize(up);
5320 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5321 //VectorSubtract(rsurface.modelorg, center, forward);
5322 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5323 VectorNegate(forward, forward);
5324 VectorReflect(forward, 0, up, forward);
5325 VectorNormalize(forward);
5326 CrossProduct(up, forward, newright);
5327 VectorNormalize(newright);
5329 Debug_PolygonBegin(NULL, 0);
5330 Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
5331 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5332 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5336 Debug_PolygonBegin(NULL, 0);
5337 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5338 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5339 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5342 // rotate the quad around the up axis vector, this is made
5343 // especially easy by the fact we know the quad is flat,
5344 // so we only have to subtract the center position and
5345 // measure distance along the right vector, and then
5346 // multiply that by the newright vector and add back the
5348 // we also need to subtract the old position to undo the
5349 // displacement from the center, which we do with a
5350 // DotProduct, the subtraction/addition of center is also
5351 // optimized into DotProducts here
5352 l = DotProduct(right, center);
5353 for (i = 0;i < 4;i++)
5355 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5356 f = DotProduct(right, v1) - l;
5357 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5360 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer);
5361 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
5363 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5364 rsurface.vertex3f_bufferobject = 0;
5365 rsurface.vertex3f_bufferoffset = 0;
5366 rsurface.svector3f = rsurface.array_deformedsvector3f;
5367 rsurface.svector3f_bufferobject = 0;
5368 rsurface.svector3f_bufferoffset = 0;
5369 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5370 rsurface.tvector3f_bufferobject = 0;
5371 rsurface.tvector3f_bufferoffset = 0;
5372 rsurface.normal3f = rsurface.array_deformednormal3f;
5373 rsurface.normal3f_bufferobject = 0;
5374 rsurface.normal3f_bufferoffset = 0;
5376 case Q3DEFORM_NORMAL:
5377 // deform the normals to make reflections wavey
5378 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5380 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5381 for (j = 0;j < surface->num_vertices;j++)
5384 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5385 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5386 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5387 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5388 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5389 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5390 VectorNormalize(normal);
5392 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
5394 rsurface.svector3f = rsurface.array_deformedsvector3f;
5395 rsurface.svector3f_bufferobject = 0;
5396 rsurface.svector3f_bufferoffset = 0;
5397 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5398 rsurface.tvector3f_bufferobject = 0;
5399 rsurface.tvector3f_bufferoffset = 0;
5400 rsurface.normal3f = rsurface.array_deformednormal3f;
5401 rsurface.normal3f_bufferobject = 0;
5402 rsurface.normal3f_bufferoffset = 0;
5405 // deform vertex array to make wavey water and flags and such
5406 waveparms[0] = deform->waveparms[0];
5407 waveparms[1] = deform->waveparms[1];
5408 waveparms[2] = deform->waveparms[2];
5409 waveparms[3] = deform->waveparms[3];
5410 // this is how a divisor of vertex influence on deformation
5411 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5412 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5413 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5415 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5416 for (j = 0;j < surface->num_vertices;j++)
5418 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5419 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5420 // if the wavefunc depends on time, evaluate it per-vertex
5423 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5424 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5426 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5429 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5430 rsurface.vertex3f_bufferobject = 0;
5431 rsurface.vertex3f_bufferoffset = 0;
5433 case Q3DEFORM_BULGE:
5434 // deform vertex array to make the surface have moving bulges
5435 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5437 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5438 for (j = 0;j < surface->num_vertices;j++)
5440 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5441 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5444 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5445 rsurface.vertex3f_bufferobject = 0;
5446 rsurface.vertex3f_bufferoffset = 0;
5449 // deform vertex array
5450 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5451 VectorScale(deform->parms, scale, waveparms);
5452 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5454 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5455 for (j = 0;j < surface->num_vertices;j++)
5456 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5458 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5459 rsurface.vertex3f_bufferobject = 0;
5460 rsurface.vertex3f_bufferoffset = 0;
5464 // generate texcoords based on the chosen texcoord source
5465 switch(rsurface.texture->tcgen.tcgen)
5468 case Q3TCGEN_TEXTURE:
5469 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5470 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5471 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5473 case Q3TCGEN_LIGHTMAP:
5474 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5475 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5476 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5478 case Q3TCGEN_VECTOR:
5479 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5481 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5482 for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, out_tc += 2)
5484 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5485 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5488 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5489 rsurface.texcoordtexture2f_bufferobject = 0;
5490 rsurface.texcoordtexture2f_bufferoffset = 0;
5492 case Q3TCGEN_ENVIRONMENT:
5493 // make environment reflections using a spheremap
5494 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5496 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5497 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5498 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5499 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5500 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5502 float l, d, eyedir[3];
5503 VectorSubtract(rsurface.modelorg, vertex, eyedir);
5504 l = 0.5f / VectorLength(eyedir);
5505 d = DotProduct(normal, eyedir)*2;
5506 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
5507 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
5510 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5511 rsurface.texcoordtexture2f_bufferobject = 0;
5512 rsurface.texcoordtexture2f_bufferoffset = 0;
5515 // the only tcmod that needs software vertex processing is turbulent, so
5516 // check for it here and apply the changes if needed
5517 // and we only support that as the first one
5518 // (handling a mixture of turbulent and other tcmods would be problematic
5519 // without punting it entirely to a software path)
5520 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5522 amplitude = rsurface.texture->tcmods[0].parms[1];
5523 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5524 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5526 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5527 for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, in_tc = rsurface.texcoordtexture2f + 2 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, in_tc += 2, out_tc += 2)
5529 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5530 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5533 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5534 rsurface.texcoordtexture2f_bufferobject = 0;
5535 rsurface.texcoordtexture2f_bufferoffset = 0;
5537 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5538 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5539 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5540 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5543 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5546 const msurface_t *surface = texturesurfacelist[0];
5547 const msurface_t *surface2;
5552 // TODO: lock all array ranges before render, rather than on each surface
5553 if (texturenumsurfaces == 1)
5555 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5556 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5558 else if (r_batchmode.integer == 2)
5560 #define MAXBATCHTRIANGLES 4096
5561 int batchtriangles = 0;
5562 int batchelements[MAXBATCHTRIANGLES*3];
5563 for (i = 0;i < texturenumsurfaces;i = j)
5565 surface = texturesurfacelist[i];
5567 if (surface->num_triangles > MAXBATCHTRIANGLES)
5569 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5572 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5573 batchtriangles = surface->num_triangles;
5574 firstvertex = surface->num_firstvertex;
5575 endvertex = surface->num_firstvertex + surface->num_vertices;
5576 for (;j < texturenumsurfaces;j++)
5578 surface2 = texturesurfacelist[j];
5579 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5581 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5582 batchtriangles += surface2->num_triangles;
5583 firstvertex = min(firstvertex, surface2->num_firstvertex);
5584 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5586 surface2 = texturesurfacelist[j-1];
5587 numvertices = endvertex - firstvertex;
5588 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5591 else if (r_batchmode.integer == 1)
5593 for (i = 0;i < texturenumsurfaces;i = j)
5595 surface = texturesurfacelist[i];
5596 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5597 if (texturesurfacelist[j] != surface2)
5599 surface2 = texturesurfacelist[j-1];
5600 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5601 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5602 GL_LockArrays(surface->num_firstvertex, numvertices);
5603 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5608 for (i = 0;i < texturenumsurfaces;i++)
5610 surface = texturesurfacelist[i];
5611 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5612 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5617 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5619 int i, planeindex, vertexindex;
5623 r_waterstate_waterplane_t *p, *bestp;
5624 msurface_t *surface;
5625 if (r_waterstate.renderingscene)
5627 for (i = 0;i < texturenumsurfaces;i++)
5629 surface = texturesurfacelist[i];
5630 if (lightmaptexunit >= 0)
5631 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5632 if (deluxemaptexunit >= 0)
5633 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5634 // pick the closest matching water plane
5637 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5640 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5642 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5643 d += fabs(PlaneDiff(vert, &p->plane));
5645 if (bestd > d || !bestp)
5653 if (refractiontexunit >= 0)
5654 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5655 if (reflectiontexunit >= 0)
5656 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5660 if (refractiontexunit >= 0)
5661 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5662 if (reflectiontexunit >= 0)
5663 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5665 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5666 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5670 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5674 const msurface_t *surface = texturesurfacelist[0];
5675 const msurface_t *surface2;
5680 // TODO: lock all array ranges before render, rather than on each surface
5681 if (texturenumsurfaces == 1)
5683 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5684 if (deluxemaptexunit >= 0)
5685 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5686 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5687 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5689 else if (r_batchmode.integer == 2)
5691 #define MAXBATCHTRIANGLES 4096
5692 int batchtriangles = 0;
5693 int batchelements[MAXBATCHTRIANGLES*3];
5694 for (i = 0;i < texturenumsurfaces;i = j)
5696 surface = texturesurfacelist[i];
5697 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5698 if (deluxemaptexunit >= 0)
5699 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5701 if (surface->num_triangles > MAXBATCHTRIANGLES)
5703 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5706 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5707 batchtriangles = surface->num_triangles;
5708 firstvertex = surface->num_firstvertex;
5709 endvertex = surface->num_firstvertex + surface->num_vertices;
5710 for (;j < texturenumsurfaces;j++)
5712 surface2 = texturesurfacelist[j];
5713 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5715 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5716 batchtriangles += surface2->num_triangles;
5717 firstvertex = min(firstvertex, surface2->num_firstvertex);
5718 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5720 surface2 = texturesurfacelist[j-1];
5721 numvertices = endvertex - firstvertex;
5722 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5725 else if (r_batchmode.integer == 1)
5728 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5729 for (i = 0;i < texturenumsurfaces;i = j)
5731 surface = texturesurfacelist[i];
5732 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5733 if (texturesurfacelist[j] != surface2)
5735 Con_Printf(" %i", j - i);
5738 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5740 for (i = 0;i < texturenumsurfaces;i = j)
5742 surface = texturesurfacelist[i];
5743 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5744 if (deluxemaptexunit >= 0)
5745 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5746 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5747 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5750 Con_Printf(" %i", j - i);
5752 surface2 = texturesurfacelist[j-1];
5753 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5754 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5755 GL_LockArrays(surface->num_firstvertex, numvertices);
5756 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5764 for (i = 0;i < texturenumsurfaces;i++)
5766 surface = texturesurfacelist[i];
5767 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5768 if (deluxemaptexunit >= 0)
5769 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5770 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5771 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5776 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5779 int texturesurfaceindex;
5780 if (r_showsurfaces.integer == 2)
5782 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5784 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5785 for (j = 0;j < surface->num_triangles;j++)
5787 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5788 GL_Color(f, f, f, 1);
5789 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5795 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5797 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5798 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5799 GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1);
5800 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5801 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5806 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
5808 int texturesurfaceindex;
5811 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5813 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5814 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
5822 rsurface.lightmapcolor4f = rsurface.array_color4f;
5823 rsurface.lightmapcolor4f_bufferobject = 0;
5824 rsurface.lightmapcolor4f_bufferoffset = 0;
5827 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5829 int texturesurfaceindex;
5833 if (rsurface.lightmapcolor4f)
5835 // generate color arrays for the surfaces in this list
5836 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5838 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5839 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
5841 f = FogPoint_Model(v);
5851 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5853 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5854 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
5856 f = FogPoint_Model(v);
5864 rsurface.lightmapcolor4f = rsurface.array_color4f;
5865 rsurface.lightmapcolor4f_bufferobject = 0;
5866 rsurface.lightmapcolor4f_bufferoffset = 0;
5869 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
5871 int texturesurfaceindex;
5875 if (!rsurface.lightmapcolor4f)
5877 // generate color arrays for the surfaces in this list
5878 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5880 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5881 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
5883 f = FogPoint_Model(v);
5884 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
5885 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
5886 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
5890 rsurface.lightmapcolor4f = rsurface.array_color4f;
5891 rsurface.lightmapcolor4f_bufferobject = 0;
5892 rsurface.lightmapcolor4f_bufferoffset = 0;
5895 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5897 int texturesurfaceindex;
5900 if (!rsurface.lightmapcolor4f)
5902 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5904 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5905 for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
5913 rsurface.lightmapcolor4f = rsurface.array_color4f;
5914 rsurface.lightmapcolor4f_bufferobject = 0;
5915 rsurface.lightmapcolor4f_bufferoffset = 0;
5918 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
5920 int texturesurfaceindex;
5923 if (!rsurface.lightmapcolor4f)
5925 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5927 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5928 for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
5930 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
5931 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
5932 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
5936 rsurface.lightmapcolor4f = rsurface.array_color4f;
5937 rsurface.lightmapcolor4f_bufferobject = 0;
5938 rsurface.lightmapcolor4f_bufferoffset = 0;
5941 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5944 rsurface.lightmapcolor4f = NULL;
5945 rsurface.lightmapcolor4f_bufferobject = 0;
5946 rsurface.lightmapcolor4f_bufferoffset = 0;
5947 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5948 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5949 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5950 GL_Color(r, g, b, a);
5951 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5954 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5956 // TODO: optimize applyfog && applycolor case
5957 // just apply fog if necessary, and tint the fog color array if necessary
5958 rsurface.lightmapcolor4f = NULL;
5959 rsurface.lightmapcolor4f_bufferobject = 0;
5960 rsurface.lightmapcolor4f_bufferoffset = 0;
5961 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5962 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5963 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5964 GL_Color(r, g, b, a);
5965 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5968 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5970 int texturesurfaceindex;
5974 if (texturesurfacelist[0]->lightmapinfo)
5976 // generate color arrays for the surfaces in this list
5977 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5979 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5980 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5982 if (surface->lightmapinfo->samples)
5984 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5985 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5986 VectorScale(lm, scale, c);
5987 if (surface->lightmapinfo->styles[1] != 255)
5989 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5991 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5992 VectorMA(c, scale, lm, c);
5993 if (surface->lightmapinfo->styles[2] != 255)
5996 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5997 VectorMA(c, scale, lm, c);
5998 if (surface->lightmapinfo->styles[3] != 255)
6001 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6002 VectorMA(c, scale, lm, c);
6012 rsurface.lightmapcolor4f = rsurface.array_color4f;
6013 rsurface.lightmapcolor4f_bufferobject = 0;
6014 rsurface.lightmapcolor4f_bufferoffset = 0;
6018 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6019 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6020 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6022 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6023 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6024 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6025 GL_Color(r, g, b, a);
6026 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6029 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6031 int texturesurfaceindex;
6034 float *v, *c, *c2, alpha;
6035 vec3_t ambientcolor;
6036 vec3_t diffusecolor;
6040 VectorCopy(rsurface.modellight_lightdir, lightdir);
6041 f = 0.5f * r_refdef.lightmapintensity;
6042 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6043 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6044 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6045 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6046 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6047 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6049 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6051 // generate color arrays for the surfaces in this list
6052 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6054 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6055 int numverts = surface->num_vertices;
6056 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6057 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6058 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6059 // q3-style directional shading
6060 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6062 if ((f = DotProduct(c2, lightdir)) > 0)
6063 VectorMA(ambientcolor, f, diffusecolor, c);
6065 VectorCopy(ambientcolor, c);
6073 rsurface.lightmapcolor4f = rsurface.array_color4f;
6074 rsurface.lightmapcolor4f_bufferobject = 0;
6075 rsurface.lightmapcolor4f_bufferoffset = 0;
6076 *applycolor = false;
6080 *r = ambientcolor[0];
6081 *g = ambientcolor[1];
6082 *b = ambientcolor[2];
6083 rsurface.lightmapcolor4f = NULL;
6084 rsurface.lightmapcolor4f_bufferobject = 0;
6085 rsurface.lightmapcolor4f_bufferoffset = 0;
6089 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6091 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6092 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6093 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6094 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6095 GL_Color(r, g, b, a);
6096 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6099 void RSurf_SetupDepthAndCulling(void)
6101 // submodels are biased to avoid z-fighting with world surfaces that they
6102 // may be exactly overlapping (avoids z-fighting artifacts on certain
6103 // doors and things in Quake maps)
6104 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6105 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6106 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6107 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6110 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6112 // transparent sky would be ridiculous
6113 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6115 R_SetupGenericShader(false);
6118 skyrendernow = false;
6119 // we have to force off the water clipping plane while rendering sky
6123 // restore entity matrix
6124 R_Mesh_Matrix(&rsurface.matrix);
6126 RSurf_SetupDepthAndCulling();
6128 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6129 // skymasking on them, and Quake3 never did sky masking (unlike
6130 // software Quake and software Quake2), so disable the sky masking
6131 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6132 // and skymasking also looks very bad when noclipping outside the
6133 // level, so don't use it then either.
6134 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6136 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6137 R_Mesh_ColorPointer(NULL, 0, 0);
6138 R_Mesh_ResetTextureState();
6139 if (skyrendermasked)
6141 R_SetupDepthOrShadowShader();
6142 // depth-only (masking)
6143 GL_ColorMask(0,0,0,0);
6144 // just to make sure that braindead drivers don't draw
6145 // anything despite that colormask...
6146 GL_BlendFunc(GL_ZERO, GL_ONE);
6150 R_SetupGenericShader(false);
6152 GL_BlendFunc(GL_ONE, GL_ZERO);
6154 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6155 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6156 if (skyrendermasked)
6157 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6159 R_Mesh_ResetTextureState();
6160 GL_Color(1, 1, 1, 1);
6163 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6165 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6168 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6169 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6170 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6171 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6172 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6173 if (rsurface.texture->backgroundcurrentskinframe)
6175 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6176 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6177 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6178 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6180 if(rsurface.texture->colormapping)
6182 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6183 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6185 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6186 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6187 R_Mesh_ColorPointer(NULL, 0, 0);
6189 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6191 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6193 // render background
6194 GL_BlendFunc(GL_ONE, GL_ZERO);
6196 GL_AlphaTest(false);
6198 GL_Color(1, 1, 1, 1);
6199 R_Mesh_ColorPointer(NULL, 0, 0);
6201 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6202 if (r_glsl_permutation)
6204 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6205 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6206 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6207 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6208 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6209 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6210 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
6212 GL_LockArrays(0, 0);
6214 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6215 GL_DepthMask(false);
6216 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6217 R_Mesh_ColorPointer(NULL, 0, 0);
6219 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6220 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6221 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6224 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6225 if (!r_glsl_permutation)
6228 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6229 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6230 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6231 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6232 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6233 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6235 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6237 GL_BlendFunc(GL_ONE, GL_ZERO);
6239 GL_AlphaTest(false);
6243 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6244 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6245 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6248 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6250 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6251 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
6253 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6257 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6258 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
6260 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6262 GL_LockArrays(0, 0);
6265 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6267 // OpenGL 1.3 path - anything not completely ancient
6268 int texturesurfaceindex;
6269 qboolean applycolor;
6273 const texturelayer_t *layer;
6274 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6276 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6279 int layertexrgbscale;
6280 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6282 if (layerindex == 0)
6286 GL_AlphaTest(false);
6287 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6290 GL_DepthMask(layer->depthmask && writedepth);
6291 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6292 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6294 layertexrgbscale = 4;
6295 VectorScale(layer->color, 0.25f, layercolor);
6297 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6299 layertexrgbscale = 2;
6300 VectorScale(layer->color, 0.5f, layercolor);
6304 layertexrgbscale = 1;
6305 VectorScale(layer->color, 1.0f, layercolor);
6307 layercolor[3] = layer->color[3];
6308 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6309 R_Mesh_ColorPointer(NULL, 0, 0);
6310 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6311 switch (layer->type)
6313 case TEXTURELAYERTYPE_LITTEXTURE:
6314 memset(&m, 0, sizeof(m));
6315 m.tex[0] = R_GetTexture(r_texture_white);
6316 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6317 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6318 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6319 m.tex[1] = R_GetTexture(layer->texture);
6320 m.texmatrix[1] = layer->texmatrix;
6321 m.texrgbscale[1] = layertexrgbscale;
6322 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6323 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6324 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6325 R_Mesh_TextureState(&m);
6326 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6327 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6328 else if (rsurface.uselightmaptexture)
6329 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6331 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6333 case TEXTURELAYERTYPE_TEXTURE:
6334 memset(&m, 0, sizeof(m));
6335 m.tex[0] = R_GetTexture(layer->texture);
6336 m.texmatrix[0] = layer->texmatrix;
6337 m.texrgbscale[0] = layertexrgbscale;
6338 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6339 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6340 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6341 R_Mesh_TextureState(&m);
6342 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6344 case TEXTURELAYERTYPE_FOG:
6345 memset(&m, 0, sizeof(m));
6346 m.texrgbscale[0] = layertexrgbscale;
6349 m.tex[0] = R_GetTexture(layer->texture);
6350 m.texmatrix[0] = layer->texmatrix;
6351 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6352 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6353 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6355 R_Mesh_TextureState(&m);
6356 // generate a color array for the fog pass
6357 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6358 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6362 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6363 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
6365 f = 1 - FogPoint_Model(v);
6366 c[0] = layercolor[0];
6367 c[1] = layercolor[1];
6368 c[2] = layercolor[2];
6369 c[3] = f * layercolor[3];
6372 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6375 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6377 GL_LockArrays(0, 0);
6380 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6382 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6383 GL_AlphaTest(false);
6387 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6389 // OpenGL 1.1 - crusty old voodoo path
6390 int texturesurfaceindex;
6394 const texturelayer_t *layer;
6395 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6397 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6399 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6401 if (layerindex == 0)
6405 GL_AlphaTest(false);
6406 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6409 GL_DepthMask(layer->depthmask && writedepth);
6410 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6411 R_Mesh_ColorPointer(NULL, 0, 0);
6412 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6413 switch (layer->type)
6415 case TEXTURELAYERTYPE_LITTEXTURE:
6416 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6418 // two-pass lit texture with 2x rgbscale
6419 // first the lightmap pass
6420 memset(&m, 0, sizeof(m));
6421 m.tex[0] = R_GetTexture(r_texture_white);
6422 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6423 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6424 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6425 R_Mesh_TextureState(&m);
6426 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6427 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6428 else if (rsurface.uselightmaptexture)
6429 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6431 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6432 GL_LockArrays(0, 0);
6433 // then apply the texture to it
6434 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6435 memset(&m, 0, sizeof(m));
6436 m.tex[0] = R_GetTexture(layer->texture);
6437 m.texmatrix[0] = layer->texmatrix;
6438 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6439 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6440 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6441 R_Mesh_TextureState(&m);
6442 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
6446 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6447 memset(&m, 0, sizeof(m));
6448 m.tex[0] = R_GetTexture(layer->texture);
6449 m.texmatrix[0] = layer->texmatrix;
6450 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6451 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6452 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6453 R_Mesh_TextureState(&m);
6454 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6455 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
6457 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
6460 case TEXTURELAYERTYPE_TEXTURE:
6461 // singletexture unlit texture with transparency support
6462 memset(&m, 0, sizeof(m));
6463 m.tex[0] = R_GetTexture(layer->texture);
6464 m.texmatrix[0] = layer->texmatrix;
6465 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6466 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6467 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6468 R_Mesh_TextureState(&m);
6469 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
6471 case TEXTURELAYERTYPE_FOG:
6472 // singletexture fogging
6473 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6476 memset(&m, 0, sizeof(m));
6477 m.tex[0] = R_GetTexture(layer->texture);
6478 m.texmatrix[0] = layer->texmatrix;
6479 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6480 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6481 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6482 R_Mesh_TextureState(&m);
6485 R_Mesh_ResetTextureState();
6486 // generate a color array for the fog pass
6487 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6491 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6492 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
6494 f = 1 - FogPoint_Model(v);
6495 c[0] = layer->color[0];
6496 c[1] = layer->color[1];
6497 c[2] = layer->color[2];
6498 c[3] = f * layer->color[3];
6501 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6504 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6506 GL_LockArrays(0, 0);
6509 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6511 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6512 GL_AlphaTest(false);
6516 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6520 GL_AlphaTest(false);
6521 R_Mesh_ColorPointer(NULL, 0, 0);
6522 R_Mesh_ResetTextureState();
6523 R_SetupGenericShader(false);
6525 if(rsurface.texture && rsurface.texture->currentskinframe)
6526 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6535 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6537 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
6538 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
6539 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
6542 // brighten it up (as texture value 127 means "unlit")
6543 c[0] *= 2 * r_refdef.view.colorscale;
6544 c[1] *= 2 * r_refdef.view.colorscale;
6545 c[2] *= 2 * r_refdef.view.colorscale;
6547 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6548 c[3] *= r_wateralpha.value;
6550 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6552 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6553 GL_DepthMask(false);
6555 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6557 GL_BlendFunc(GL_ONE, GL_ONE);
6558 GL_DepthMask(false);
6560 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6562 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6563 GL_DepthMask(false);
6565 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6567 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6568 GL_DepthMask(false);
6572 GL_BlendFunc(GL_ONE, GL_ZERO);
6573 GL_DepthMask(writedepth);
6576 rsurface.lightmapcolor4f = NULL;
6578 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6580 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6582 rsurface.lightmapcolor4f = NULL;
6583 rsurface.lightmapcolor4f_bufferobject = 0;
6584 rsurface.lightmapcolor4f_bufferoffset = 0;
6586 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6588 qboolean applycolor = true;
6591 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6593 r_refdef.lightmapintensity = 1;
6594 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6595 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6599 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6601 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6602 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6603 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6606 if(!rsurface.lightmapcolor4f)
6607 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6609 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6610 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6611 if(r_refdef.fogenabled)
6612 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6614 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6615 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6618 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6621 RSurf_SetupDepthAndCulling();
6622 if (r_showsurfaces.integer == 3)
6623 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6624 else if (r_glsl.integer && gl_support_fragment_shader)
6625 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6626 else if (gl_combine.integer && r_textureunits.integer >= 2)
6627 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6629 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6633 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6636 RSurf_SetupDepthAndCulling();
6637 if (r_showsurfaces.integer == 3)
6638 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6639 else if (r_glsl.integer && gl_support_fragment_shader)
6640 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6641 else if (gl_combine.integer && r_textureunits.integer >= 2)
6642 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6644 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6648 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6651 int texturenumsurfaces, endsurface;
6653 msurface_t *surface;
6654 msurface_t *texturesurfacelist[1024];
6656 // if the model is static it doesn't matter what value we give for
6657 // wantnormals and wanttangents, so this logic uses only rules applicable
6658 // to a model, knowing that they are meaningless otherwise
6659 if (ent == r_refdef.scene.worldentity)
6660 RSurf_ActiveWorldEntity();
6661 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6662 RSurf_ActiveModelEntity(ent, false, false);
6664 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6666 for (i = 0;i < numsurfaces;i = j)
6669 surface = rsurface.modelsurfaces + surfacelist[i];
6670 texture = surface->texture;
6671 rsurface.texture = R_GetCurrentTexture(texture);
6672 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6673 // scan ahead until we find a different texture
6674 endsurface = min(i + 1024, numsurfaces);
6675 texturenumsurfaces = 0;
6676 texturesurfacelist[texturenumsurfaces++] = surface;
6677 for (;j < endsurface;j++)
6679 surface = rsurface.modelsurfaces + surfacelist[j];
6680 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6682 texturesurfacelist[texturenumsurfaces++] = surface;
6684 // render the range of surfaces
6685 if (ent == r_refdef.scene.worldentity)
6686 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6688 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6690 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6691 GL_AlphaTest(false);
6694 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6696 const entity_render_t *queueentity = r_refdef.scene.worldentity;
6700 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6702 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6704 RSurf_SetupDepthAndCulling();
6705 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6706 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6708 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6710 RSurf_SetupDepthAndCulling();
6711 GL_AlphaTest(false);
6712 R_Mesh_ColorPointer(NULL, 0, 0);
6713 R_Mesh_ResetTextureState();
6714 R_SetupGenericShader(false);
6715 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6717 GL_BlendFunc(GL_ONE, GL_ZERO);
6718 GL_Color(0, 0, 0, 1);
6719 GL_DepthTest(writedepth);
6720 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6722 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6724 RSurf_SetupDepthAndCulling();
6725 GL_AlphaTest(false);
6726 R_Mesh_ColorPointer(NULL, 0, 0);
6727 R_Mesh_ResetTextureState();
6728 R_SetupGenericShader(false);
6729 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6731 GL_BlendFunc(GL_ONE, GL_ZERO);
6733 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6735 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6736 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6737 else if (!rsurface.texture->currentnumlayers)
6739 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6741 // transparent surfaces get pushed off into the transparent queue
6742 int surfacelistindex;
6743 const msurface_t *surface;
6744 vec3_t tempcenter, center;
6745 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6747 surface = texturesurfacelist[surfacelistindex];
6748 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6749 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6750 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6751 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6752 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6757 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6758 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6763 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6767 // break the surface list down into batches by texture and use of lightmapping
6768 for (i = 0;i < numsurfaces;i = j)
6771 // texture is the base texture pointer, rsurface.texture is the
6772 // current frame/skin the texture is directing us to use (for example
6773 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6774 // use skin 1 instead)
6775 texture = surfacelist[i]->texture;
6776 rsurface.texture = R_GetCurrentTexture(texture);
6777 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6778 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6780 // if this texture is not the kind we want, skip ahead to the next one
6781 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6785 // simply scan ahead until we find a different texture or lightmap state
6786 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6788 // render the range of surfaces
6789 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6793 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6798 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6800 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6802 RSurf_SetupDepthAndCulling();
6803 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6804 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6806 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6808 RSurf_SetupDepthAndCulling();
6809 GL_AlphaTest(false);
6810 R_Mesh_ColorPointer(NULL, 0, 0);
6811 R_Mesh_ResetTextureState();
6812 R_SetupGenericShader(false);
6813 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6815 GL_BlendFunc(GL_ONE, GL_ZERO);
6816 GL_Color(0, 0, 0, 1);
6817 GL_DepthTest(writedepth);
6818 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6820 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6822 RSurf_SetupDepthAndCulling();
6823 GL_AlphaTest(false);
6824 R_Mesh_ColorPointer(NULL, 0, 0);
6825 R_Mesh_ResetTextureState();
6826 R_SetupGenericShader(false);
6827 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6829 GL_BlendFunc(GL_ONE, GL_ZERO);
6831 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6833 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6834 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6835 else if (!rsurface.texture->currentnumlayers)
6837 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6839 // transparent surfaces get pushed off into the transparent queue
6840 int surfacelistindex;
6841 const msurface_t *surface;
6842 vec3_t tempcenter, center;
6843 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6845 surface = texturesurfacelist[surfacelistindex];
6846 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6847 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6848 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6849 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6850 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6855 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6856 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6861 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6865 // break the surface list down into batches by texture and use of lightmapping
6866 for (i = 0;i < numsurfaces;i = j)
6869 // texture is the base texture pointer, rsurface.texture is the
6870 // current frame/skin the texture is directing us to use (for example
6871 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6872 // use skin 1 instead)
6873 texture = surfacelist[i]->texture;
6874 rsurface.texture = R_GetCurrentTexture(texture);
6875 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6876 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6878 // if this texture is not the kind we want, skip ahead to the next one
6879 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6883 // simply scan ahead until we find a different texture or lightmap state
6884 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6886 // render the range of surfaces
6887 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6891 float locboxvertex3f[6*4*3] =
6893 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6894 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6895 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6896 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6897 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6898 1,0,0, 0,0,0, 0,1,0, 1,1,0
6901 unsigned short locboxelements[6*2*3] =
6911 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6914 cl_locnode_t *loc = (cl_locnode_t *)ent;
6916 float vertex3f[6*4*3];
6918 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6919 GL_DepthMask(false);
6920 GL_DepthRange(0, 1);
6921 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6923 GL_CullFace(GL_NONE);
6924 R_Mesh_Matrix(&identitymatrix);
6926 R_Mesh_VertexPointer(vertex3f, 0, 0);
6927 R_Mesh_ColorPointer(NULL, 0, 0);
6928 R_Mesh_ResetTextureState();
6929 R_SetupGenericShader(false);
6932 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6933 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6934 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6935 surfacelist[0] < 0 ? 0.5f : 0.125f);
6937 if (VectorCompare(loc->mins, loc->maxs))
6939 VectorSet(size, 2, 2, 2);
6940 VectorMA(loc->mins, -0.5f, size, mins);
6944 VectorCopy(loc->mins, mins);
6945 VectorSubtract(loc->maxs, loc->mins, size);
6948 for (i = 0;i < 6*4*3;)
6949 for (j = 0;j < 3;j++, i++)
6950 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6952 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
6955 void R_DrawLocs(void)
6958 cl_locnode_t *loc, *nearestloc;
6960 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6961 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6963 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6964 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6968 void R_DrawDebugModel(entity_render_t *ent)
6970 int i, j, k, l, flagsmask;
6971 const int *elements;
6973 msurface_t *surface;
6974 dp_model_t *model = ent->model;
6977 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
6979 R_Mesh_ColorPointer(NULL, 0, 0);
6980 R_Mesh_ResetTextureState();
6981 R_SetupGenericShader(false);
6982 GL_DepthRange(0, 1);
6983 GL_DepthTest(!r_showdisabledepthtest.integer);
6984 GL_DepthMask(false);
6985 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6987 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6989 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6990 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6992 if (brush->colbrushf && brush->colbrushf->numtriangles)
6994 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6995 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
6996 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
6999 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7001 if (surface->num_collisiontriangles)
7003 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7004 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
7005 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7010 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7012 if (r_showtris.integer || r_shownormals.integer)
7014 if (r_showdisabledepthtest.integer)
7016 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7017 GL_DepthMask(false);
7021 GL_BlendFunc(GL_ONE, GL_ZERO);
7024 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7026 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7028 rsurface.texture = R_GetCurrentTexture(surface->texture);
7029 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7031 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7032 if (r_showtris.value > 0)
7034 if (!rsurface.texture->currentlayers->depthmask)
7035 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7036 else if (ent == r_refdef.scene.worldentity)
7037 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7039 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7040 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7041 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7042 R_Mesh_ColorPointer(NULL, 0, 0);
7043 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7044 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7045 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7046 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7047 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7050 if (r_shownormals.value < 0)
7053 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7055 VectorCopy(rsurface.vertex3f + l * 3, v);
7056 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7057 qglVertex3f(v[0], v[1], v[2]);
7058 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7059 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7060 qglVertex3f(v[0], v[1], v[2]);
7065 if (r_shownormals.value > 0)
7068 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7070 VectorCopy(rsurface.vertex3f + l * 3, v);
7071 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7072 qglVertex3f(v[0], v[1], v[2]);
7073 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7074 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7075 qglVertex3f(v[0], v[1], v[2]);
7080 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7082 VectorCopy(rsurface.vertex3f + l * 3, v);
7083 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7084 qglVertex3f(v[0], v[1], v[2]);
7085 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7086 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7087 qglVertex3f(v[0], v[1], v[2]);
7092 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7094 VectorCopy(rsurface.vertex3f + l * 3, v);
7095 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7096 qglVertex3f(v[0], v[1], v[2]);
7097 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7098 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7099 qglVertex3f(v[0], v[1], v[2]);
7106 rsurface.texture = NULL;
7110 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7111 int r_maxsurfacelist = 0;
7112 msurface_t **r_surfacelist = NULL;
7113 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7115 int i, j, endj, f, flagsmask;
7117 dp_model_t *model = r_refdef.scene.worldmodel;
7118 msurface_t *surfaces;
7119 unsigned char *update;
7120 int numsurfacelist = 0;
7124 if (r_maxsurfacelist < model->num_surfaces)
7126 r_maxsurfacelist = model->num_surfaces;
7128 Mem_Free(r_surfacelist);
7129 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7132 RSurf_ActiveWorldEntity();
7134 surfaces = model->data_surfaces;
7135 update = model->brushq1.lightmapupdateflags;
7137 // update light styles on this submodel
7138 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7140 model_brush_lightstyleinfo_t *style;
7141 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7143 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7145 int *list = style->surfacelist;
7146 style->value = r_refdef.scene.lightstylevalue[style->style];
7147 for (j = 0;j < style->numsurfaces;j++)
7148 update[list[j]] = true;
7153 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7157 R_DrawDebugModel(r_refdef.scene.worldentity);
7158 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7164 rsurface.uselightmaptexture = false;
7165 rsurface.texture = NULL;
7166 rsurface.rtlight = NULL;
7168 // add visible surfaces to draw list
7169 for (i = 0;i < model->nummodelsurfaces;i++)
7171 j = model->sortedmodelsurfaces[i];
7172 if (r_refdef.viewcache.world_surfacevisible[j])
7173 r_surfacelist[numsurfacelist++] = surfaces + j;
7175 // update lightmaps if needed
7177 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7178 if (r_refdef.viewcache.world_surfacevisible[j])
7180 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7181 // don't do anything if there were no surfaces
7182 if (!numsurfacelist)
7184 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7187 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7188 GL_AlphaTest(false);
7190 // add to stats if desired
7191 if (r_speeds.integer && !skysurfaces && !depthonly)
7193 r_refdef.stats.world_surfaces += numsurfacelist;
7194 for (j = 0;j < numsurfacelist;j++)
7195 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7197 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7200 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7202 int i, j, endj, f, flagsmask;
7204 dp_model_t *model = ent->model;
7205 msurface_t *surfaces;
7206 unsigned char *update;
7207 int numsurfacelist = 0;
7211 if (r_maxsurfacelist < model->num_surfaces)
7213 r_maxsurfacelist = model->num_surfaces;
7215 Mem_Free(r_surfacelist);
7216 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7219 // if the model is static it doesn't matter what value we give for
7220 // wantnormals and wanttangents, so this logic uses only rules applicable
7221 // to a model, knowing that they are meaningless otherwise
7222 if (ent == r_refdef.scene.worldentity)
7223 RSurf_ActiveWorldEntity();
7224 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
7225 RSurf_ActiveModelEntity(ent, false, false);
7227 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7229 surfaces = model->data_surfaces;
7230 update = model->brushq1.lightmapupdateflags;
7232 // update light styles
7233 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7235 model_brush_lightstyleinfo_t *style;
7236 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7238 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7240 int *list = style->surfacelist;
7241 style->value = r_refdef.scene.lightstylevalue[style->style];
7242 for (j = 0;j < style->numsurfaces;j++)
7243 update[list[j]] = true;
7248 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7252 R_DrawDebugModel(ent);
7253 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7259 rsurface.uselightmaptexture = false;
7260 rsurface.texture = NULL;
7261 rsurface.rtlight = NULL;
7263 // add visible surfaces to draw list
7264 for (i = 0;i < model->nummodelsurfaces;i++)
7265 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7266 // don't do anything if there were no surfaces
7267 if (!numsurfacelist)
7269 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7272 // update lightmaps if needed
7274 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7276 R_BuildLightMap(ent, surfaces + j);
7277 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7278 GL_AlphaTest(false);
7280 // add to stats if desired
7281 if (r_speeds.integer && !skysurfaces && !depthonly)
7283 r_refdef.stats.entities_surfaces += numsurfacelist;
7284 for (j = 0;j < numsurfacelist;j++)
7285 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7287 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity