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_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
42 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
43 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
44 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
46 cvar_t r_motionblur_debug = {0, "r_motionblur_debug", "0", "outputs current motionblur alpha value"};
48 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
50 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"};
51 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
52 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
53 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
54 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)"};
55 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
56 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
57 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"};
58 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"};
59 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
60 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"};
61 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"};
62 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"};
63 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
64 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
65 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
66 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
67 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
68 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
69 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
70 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
71 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
72 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
73 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
74 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
75 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"};
76 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
77 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
78 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"};
79 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"};
80 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
81 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
83 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
84 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
85 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
86 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
87 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
88 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
89 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
90 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
92 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)"};
94 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
95 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)"};
96 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)"};
97 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
98 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
99 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
100 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
101 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)"};
102 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)"};
103 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)"};
104 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)"};
105 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)"};
107 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)"};
108 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
109 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"};
110 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
111 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
113 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
114 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
115 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
116 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
118 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
119 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
120 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
121 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
122 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
123 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
124 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
126 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
127 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
128 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
129 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)"};
131 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"};
133 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"};
135 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
137 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
138 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
139 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"};
140 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
141 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
142 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
143 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
145 extern cvar_t v_glslgamma;
147 extern qboolean v_flipped_state;
149 static struct r_bloomstate_s
154 int bloomwidth, bloomheight;
156 int screentexturewidth, screentextureheight;
157 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
159 int bloomtexturewidth, bloomtextureheight;
160 rtexture_t *texture_bloom;
162 // arrays for rendering the screen passes
163 float screentexcoord2f[8];
164 float bloomtexcoord2f[8];
165 float offsettexcoord2f[8];
169 r_waterstate_t r_waterstate;
171 /// shadow volume bsp struct with automatically growing nodes buffer
174 rtexture_t *r_texture_blanknormalmap;
175 rtexture_t *r_texture_white;
176 rtexture_t *r_texture_grey128;
177 rtexture_t *r_texture_black;
178 rtexture_t *r_texture_notexture;
179 rtexture_t *r_texture_whitecube;
180 rtexture_t *r_texture_normalizationcube;
181 rtexture_t *r_texture_fogattenuation;
182 rtexture_t *r_texture_gammaramps;
183 unsigned int r_texture_gammaramps_serial;
184 //rtexture_t *r_texture_fogintensity;
186 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
187 unsigned int r_numqueries;
188 unsigned int r_maxqueries;
190 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
191 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
193 /// vertex coordinates for a quad that covers the screen exactly
194 const static float r_screenvertex3f[12] =
202 extern void R_DrawModelShadows(void);
204 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
207 for (i = 0;i < verts;i++)
218 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
221 for (i = 0;i < verts;i++)
231 // FIXME: move this to client?
234 if (gamemode == GAME_NEHAHRA)
236 Cvar_Set("gl_fogenable", "0");
237 Cvar_Set("gl_fogdensity", "0.2");
238 Cvar_Set("gl_fogred", "0.3");
239 Cvar_Set("gl_foggreen", "0.3");
240 Cvar_Set("gl_fogblue", "0.3");
242 r_refdef.fog_density = 0;
243 r_refdef.fog_red = 0;
244 r_refdef.fog_green = 0;
245 r_refdef.fog_blue = 0;
246 r_refdef.fog_alpha = 1;
247 r_refdef.fog_start = 0;
248 r_refdef.fog_end = 0;
251 float FogForDistance(vec_t dist)
253 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
254 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
257 float FogPoint_World(const vec3_t p)
259 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
262 float FogPoint_Model(const vec3_t p)
264 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
267 static void R_BuildBlankTextures(void)
269 unsigned char data[4];
270 data[2] = 128; // normal X
271 data[1] = 128; // normal Y
272 data[0] = 255; // normal Z
273 data[3] = 128; // height
274 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
279 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
284 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
289 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
292 static void R_BuildNoTexture(void)
295 unsigned char pix[16][16][4];
296 // this makes a light grey/dark grey checkerboard texture
297 for (y = 0;y < 16;y++)
299 for (x = 0;x < 16;x++)
301 if ((y < 8) ^ (x < 8))
317 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
320 static void R_BuildWhiteCube(void)
322 unsigned char data[6*1*1*4];
323 memset(data, 255, sizeof(data));
324 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
327 static void R_BuildNormalizationCube(void)
331 vec_t s, t, intensity;
333 unsigned char data[6][NORMSIZE][NORMSIZE][4];
334 for (side = 0;side < 6;side++)
336 for (y = 0;y < NORMSIZE;y++)
338 for (x = 0;x < NORMSIZE;x++)
340 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
341 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
376 intensity = 127.0f / sqrt(DotProduct(v, v));
377 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
378 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
379 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
380 data[side][y][x][3] = 255;
384 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
387 static void R_BuildFogTexture(void)
391 unsigned char data1[FOGWIDTH][4];
392 //unsigned char data2[FOGWIDTH][4];
395 r_refdef.fogmasktable_start = r_refdef.fog_start;
396 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
397 r_refdef.fogmasktable_range = r_refdef.fogrange;
398 r_refdef.fogmasktable_density = r_refdef.fog_density;
400 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
401 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
403 d = (x * r - r_refdef.fogmasktable_start);
404 if(developer.integer >= 100)
405 Con_Printf("%f ", d);
407 if (r_fog_exp2.integer)
408 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
410 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
411 if(developer.integer >= 100)
412 Con_Printf(" : %f ", alpha);
413 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
414 if(developer.integer >= 100)
415 Con_Printf(" = %f\n", alpha);
416 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
419 for (x = 0;x < FOGWIDTH;x++)
421 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
426 //data2[x][0] = 255 - b;
427 //data2[x][1] = 255 - b;
428 //data2[x][2] = 255 - b;
431 if (r_texture_fogattenuation)
433 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
434 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
438 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);
439 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
443 static const char *builtinshaderstring =
444 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
445 "// written by Forest 'LordHavoc' Hale\n"
447 "// common definitions between vertex shader and fragment shader:\n"
449 "//#ifdef __GLSL_CG_DATA_TYPES\n"
450 "//# define myhalf half\n"
451 "//# define myhalf2 half2\n"
452 "//# define myhalf3 half3\n"
453 "//# define myhalf4 half4\n"
455 "# define myhalf float\n"
456 "# define myhalf2 vec2\n"
457 "# define myhalf3 vec3\n"
458 "# define myhalf4 vec4\n"
461 "#ifdef MODE_DEPTH_OR_SHADOW\n"
463 "# ifdef VERTEX_SHADER\n"
466 " gl_Position = ftransform();\n"
472 "#ifdef MODE_POSTPROCESS\n"
473 "# ifdef VERTEX_SHADER\n"
476 " gl_FrontColor = gl_Color;\n"
477 " gl_Position = ftransform();\n"
478 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
480 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
484 "# ifdef FRAGMENT_SHADER\n"
486 "uniform sampler2D Texture_First;\n"
488 "uniform sampler2D Texture_Second;\n"
490 "#ifdef USEGAMMARAMPS\n"
491 "uniform sampler2D Texture_GammaRamps;\n"
493 "#ifdef USESATURATION\n"
494 "uniform float Saturation;\n"
496 "#ifdef USEVERTEXTEXTUREBLEND\n"
497 "uniform vec4 TintColor;\n"
499 "#ifdef USECOLORMOD\n"
500 "uniform vec3 Gamma;\n"
502 "//uncomment these if you want to use them:\n"
503 "uniform vec4 UserVec1;\n"
504 "// uniform vec4 UserVec2;\n"
505 "// uniform vec4 UserVec3;\n"
506 "// uniform vec4 UserVec4;\n"
507 "// uniform float ClientTime;\n"
508 "uniform vec2 PixelSize;\n"
511 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
513 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
515 "#ifdef USEVERTEXTEXTUREBLEND\n"
516 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
519 "#ifdef USEPOSTPROCESSING\n"
520 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
521 "// 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"
522 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
523 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
524 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
525 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
526 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
527 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
530 "#ifdef USESATURATION\n"
531 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
532 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
533 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
534 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" // TODO: test this on ATI
537 "#ifdef USEGAMMARAMPS\n"
538 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
539 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
540 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
547 "#ifdef MODE_GENERIC\n"
548 "# ifdef VERTEX_SHADER\n"
551 " gl_FrontColor = gl_Color;\n"
552 "# ifdef USEDIFFUSE\n"
553 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
555 "# ifdef USESPECULAR\n"
556 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
558 " gl_Position = ftransform();\n"
561 "# ifdef FRAGMENT_SHADER\n"
563 "# ifdef USEDIFFUSE\n"
564 "uniform sampler2D Texture_First;\n"
566 "# ifdef USESPECULAR\n"
567 "uniform sampler2D Texture_Second;\n"
572 " gl_FragColor = gl_Color;\n"
573 "# ifdef USEDIFFUSE\n"
574 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
577 "# ifdef USESPECULAR\n"
578 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
580 "# ifdef USECOLORMAPPING\n"
581 " gl_FragColor *= tex2;\n"
584 " gl_FragColor += tex2;\n"
586 "# ifdef USEVERTEXTEXTUREBLEND\n"
587 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
592 "#else // !MODE_GENERIC\n"
594 "varying vec2 TexCoord;\n"
595 "#ifdef USEVERTEXTEXTUREBLEND\n"
596 "varying vec2 TexCoord2;\n"
598 "varying vec2 TexCoordLightmap;\n"
600 "#ifdef MODE_LIGHTSOURCE\n"
601 "varying vec3 CubeVector;\n"
604 "#ifdef MODE_LIGHTSOURCE\n"
605 "varying vec3 LightVector;\n"
607 "#ifdef MODE_LIGHTDIRECTION\n"
608 "varying vec3 LightVector;\n"
611 "varying vec3 EyeVector;\n"
613 "varying vec3 EyeVectorModelSpace;\n"
616 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
617 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
618 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
620 "#ifdef MODE_WATER\n"
621 "varying vec4 ModelViewProjectionPosition;\n"
623 "#ifdef MODE_REFRACTION\n"
624 "varying vec4 ModelViewProjectionPosition;\n"
626 "#ifdef USEREFLECTION\n"
627 "varying vec4 ModelViewProjectionPosition;\n"
634 "// vertex shader specific:\n"
635 "#ifdef VERTEX_SHADER\n"
637 "uniform vec3 LightPosition;\n"
638 "uniform vec3 EyePosition;\n"
639 "uniform vec3 LightDir;\n"
641 "// 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"
645 " gl_FrontColor = gl_Color;\n"
646 " // copy the surface texcoord\n"
647 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
648 "#ifdef USEVERTEXTEXTUREBLEND\n"
649 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
651 "#ifndef MODE_LIGHTSOURCE\n"
652 "# ifndef MODE_LIGHTDIRECTION\n"
653 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
657 "#ifdef MODE_LIGHTSOURCE\n"
658 " // transform vertex position into light attenuation/cubemap space\n"
659 " // (-1 to +1 across the light box)\n"
660 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
662 " // transform unnormalized light direction into tangent space\n"
663 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
664 " // normalize it per pixel)\n"
665 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
666 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
667 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
668 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
671 "#ifdef MODE_LIGHTDIRECTION\n"
672 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
673 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
674 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
677 " // transform unnormalized eye direction into tangent space\n"
679 " vec3 EyeVectorModelSpace;\n"
681 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
682 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
683 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
684 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
686 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
687 " VectorS = gl_MultiTexCoord1.xyz;\n"
688 " VectorT = gl_MultiTexCoord2.xyz;\n"
689 " VectorR = gl_MultiTexCoord3.xyz;\n"
692 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
693 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
694 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
695 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
698 "// transform vertex to camera space, using ftransform to match non-VS\n"
700 " gl_Position = ftransform();\n"
702 "#ifdef MODE_WATER\n"
703 " ModelViewProjectionPosition = gl_Position;\n"
705 "#ifdef MODE_REFRACTION\n"
706 " ModelViewProjectionPosition = gl_Position;\n"
708 "#ifdef USEREFLECTION\n"
709 " ModelViewProjectionPosition = gl_Position;\n"
713 "#endif // VERTEX_SHADER\n"
718 "// fragment shader specific:\n"
719 "#ifdef FRAGMENT_SHADER\n"
721 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
722 "uniform sampler2D Texture_Normal;\n"
723 "uniform sampler2D Texture_Color;\n"
724 "uniform sampler2D Texture_Gloss;\n"
725 "uniform sampler2D Texture_Glow;\n"
726 "uniform sampler2D Texture_SecondaryNormal;\n"
727 "uniform sampler2D Texture_SecondaryColor;\n"
728 "uniform sampler2D Texture_SecondaryGloss;\n"
729 "uniform sampler2D Texture_SecondaryGlow;\n"
730 "uniform sampler2D Texture_Pants;\n"
731 "uniform sampler2D Texture_Shirt;\n"
732 "uniform sampler2D Texture_FogMask;\n"
733 "uniform sampler2D Texture_Lightmap;\n"
734 "uniform sampler2D Texture_Deluxemap;\n"
735 "uniform sampler2D Texture_Refraction;\n"
736 "uniform sampler2D Texture_Reflection;\n"
737 "uniform sampler2D Texture_Attenuation;\n"
738 "uniform samplerCube Texture_Cube;\n"
740 "uniform myhalf3 LightColor;\n"
741 "uniform myhalf3 AmbientColor;\n"
742 "uniform myhalf3 DiffuseColor;\n"
743 "uniform myhalf3 SpecularColor;\n"
744 "uniform myhalf3 Color_Pants;\n"
745 "uniform myhalf3 Color_Shirt;\n"
746 "uniform myhalf3 FogColor;\n"
748 "uniform myhalf4 TintColor;\n"
751 "//#ifdef MODE_WATER\n"
752 "uniform vec4 DistortScaleRefractReflect;\n"
753 "uniform vec4 ScreenScaleRefractReflect;\n"
754 "uniform vec4 ScreenCenterRefractReflect;\n"
755 "uniform myhalf4 RefractColor;\n"
756 "uniform myhalf4 ReflectColor;\n"
757 "uniform myhalf ReflectFactor;\n"
758 "uniform myhalf ReflectOffset;\n"
760 "//# ifdef MODE_REFRACTION\n"
761 "//uniform vec4 DistortScaleRefractReflect;\n"
762 "//uniform vec4 ScreenScaleRefractReflect;\n"
763 "//uniform vec4 ScreenCenterRefractReflect;\n"
764 "//uniform myhalf4 RefractColor;\n"
765 "//# ifdef USEREFLECTION\n"
766 "//uniform myhalf4 ReflectColor;\n"
769 "//# ifdef USEREFLECTION\n"
770 "//uniform vec4 DistortScaleRefractReflect;\n"
771 "//uniform vec4 ScreenScaleRefractReflect;\n"
772 "//uniform vec4 ScreenCenterRefractReflect;\n"
773 "//uniform myhalf4 ReflectColor;\n"
778 "uniform myhalf GlowScale;\n"
779 "uniform myhalf SceneBrightness;\n"
780 "#ifdef USECONTRASTBOOST\n"
781 "uniform myhalf ContrastBoostCoeff;\n"
784 "uniform float OffsetMapping_Scale;\n"
785 "uniform float OffsetMapping_Bias;\n"
786 "uniform float FogRangeRecip;\n"
788 "uniform myhalf AmbientScale;\n"
789 "uniform myhalf DiffuseScale;\n"
790 "uniform myhalf SpecularScale;\n"
791 "uniform myhalf SpecularPower;\n"
793 "#ifdef USEOFFSETMAPPING\n"
794 "vec2 OffsetMapping(vec2 TexCoord)\n"
796 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
797 " // 14 sample relief mapping: linear search and then binary search\n"
798 " // this basically steps forward a small amount repeatedly until it finds\n"
799 " // itself inside solid, then jitters forward and back using decreasing\n"
800 " // amounts to find the impact\n"
801 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
802 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
803 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
804 " vec3 RT = vec3(TexCoord, 1);\n"
805 " OffsetVector *= 0.1;\n"
806 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
807 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
808 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
809 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
810 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
811 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
812 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
813 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
814 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
815 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
816 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
817 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
818 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
819 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
822 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
823 " // this basically moves forward the full distance, and then backs up based\n"
824 " // on height of samples\n"
825 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
826 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
827 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
828 " TexCoord += OffsetVector;\n"
829 " OffsetVector *= 0.333;\n"
830 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
831 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
832 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
833 " return TexCoord;\n"
836 "#endif // USEOFFSETMAPPING\n"
838 "#ifdef MODE_WATER\n"
843 "#ifdef USEOFFSETMAPPING\n"
844 " // apply offsetmapping\n"
845 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
846 "#define TexCoord TexCoordOffset\n"
849 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
850 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
851 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
852 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
853 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
856 "#else // !MODE_WATER\n"
857 "#ifdef MODE_REFRACTION\n"
859 "// refraction pass\n"
862 "#ifdef USEOFFSETMAPPING\n"
863 " // apply offsetmapping\n"
864 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
865 "#define TexCoord TexCoordOffset\n"
868 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
869 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
870 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
871 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
874 "#else // !MODE_REFRACTION\n"
877 "#ifdef USEOFFSETMAPPING\n"
878 " // apply offsetmapping\n"
879 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
880 "#define TexCoord TexCoordOffset\n"
883 " // combine the diffuse textures (base, pants, shirt)\n"
884 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
885 "#ifdef USECOLORMAPPING\n"
886 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
888 "#ifdef USEVERTEXTEXTUREBLEND\n"
889 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
890 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
891 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
892 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
894 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
897 "#ifdef USEDIFFUSE\n"
898 " // get the surface normal and the gloss color\n"
899 "# ifdef USEVERTEXTEXTUREBLEND\n"
900 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
901 "# ifdef USESPECULAR\n"
902 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
905 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
906 "# ifdef USESPECULAR\n"
907 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
914 "#ifdef MODE_LIGHTSOURCE\n"
917 " // calculate surface normal, light normal, and specular normal\n"
918 " // compute color intensity for the two textures (colormap and glossmap)\n"
919 " // scale by light color and attenuation as efficiently as possible\n"
920 " // (do as much scalar math as possible rather than vector math)\n"
921 "# ifdef USEDIFFUSE\n"
922 " // get the light normal\n"
923 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
925 "# ifdef USESPECULAR\n"
926 "# ifndef USEEXACTSPECULARMATH\n"
927 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
930 " // calculate directional shading\n"
931 "# ifdef USEEXACTSPECULARMATH\n"
932 " 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"
934 " 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"
937 "# ifdef USEDIFFUSE\n"
938 " // calculate directional shading\n"
939 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
941 " // calculate directionless shading\n"
942 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
946 "# ifdef USECUBEFILTER\n"
947 " // apply light cubemap filter\n"
948 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
949 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
951 "#endif // MODE_LIGHTSOURCE\n"
956 "#ifdef MODE_LIGHTDIRECTION\n"
957 " // directional model lighting\n"
958 "# ifdef USEDIFFUSE\n"
959 " // get the light normal\n"
960 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
962 "# ifdef USESPECULAR\n"
963 " // calculate directional shading\n"
964 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
965 "# ifdef USEEXACTSPECULARMATH\n"
966 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
968 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
969 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
972 "# ifdef USEDIFFUSE\n"
974 " // calculate directional shading\n"
975 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
977 " color.rgb *= AmbientColor;\n"
980 "#endif // MODE_LIGHTDIRECTION\n"
985 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
986 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
988 " // get the light normal\n"
989 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
990 " myhalf3 diffusenormal;\n"
991 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
992 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
993 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
994 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
995 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
996 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
997 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
998 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
999 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1000 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1001 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1002 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1003 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1004 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1005 "# ifdef USESPECULAR\n"
1006 "# ifdef USEEXACTSPECULARMATH\n"
1007 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1009 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1010 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1014 " // apply lightmap color\n"
1015 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1016 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1021 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1022 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1024 " // get the light normal\n"
1025 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1026 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1027 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1028 "# ifdef USESPECULAR\n"
1029 "# ifdef USEEXACTSPECULARMATH\n"
1030 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1032 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1033 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1037 " // apply lightmap color\n"
1038 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1039 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1044 "#ifdef MODE_LIGHTMAP\n"
1045 " // apply lightmap color\n"
1046 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1047 "#endif // MODE_LIGHTMAP\n"
1052 "#ifdef MODE_VERTEXCOLOR\n"
1053 " // apply lightmap color\n"
1054 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1055 "#endif // MODE_VERTEXCOLOR\n"
1060 "#ifdef MODE_FLATCOLOR\n"
1061 "#endif // MODE_FLATCOLOR\n"
1069 " color *= TintColor;\n"
1072 "#ifdef USEVERTEXTEXTUREBLEND\n"
1073 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1075 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1079 "#ifdef USECONTRASTBOOST\n"
1080 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1083 " color.rgb *= SceneBrightness;\n"
1085 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1087 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1090 " // 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"
1091 "#ifdef USEREFLECTION\n"
1092 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1093 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1094 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1095 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1098 " gl_FragColor = vec4(color);\n"
1100 "#endif // !MODE_REFRACTION\n"
1101 "#endif // !MODE_WATER\n"
1103 "#endif // FRAGMENT_SHADER\n"
1105 "#endif // !MODE_GENERIC\n"
1106 "#endif // !MODE_POSTPROCESS\n"
1107 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1110 typedef struct shaderpermutationinfo_s
1112 const char *pretext;
1115 shaderpermutationinfo_t;
1117 typedef struct shadermodeinfo_s
1119 const char *vertexfilename;
1120 const char *geometryfilename;
1121 const char *fragmentfilename;
1122 const char *pretext;
1127 typedef enum shaderpermutation_e
1129 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1130 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1131 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1132 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, ///< r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1133 SHADERPERMUTATION_FOG = 1<<4, ///< tint the color by fog color or black if using additive blend mode
1134 SHADERPERMUTATION_CUBEFILTER = 1<<5, ///< (lightsource) use cubemap light filter
1135 SHADERPERMUTATION_GLOW = 1<<6, ///< (lightmap) blend in an additive glow texture
1136 SHADERPERMUTATION_SPECULAR = 1<<7, ///< (lightsource or deluxemapping) render specular effects
1137 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1138 SHADERPERMUTATION_REFLECTION = 1<<9, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1139 SHADERPERMUTATION_OFFSETMAPPING = 1<<10, ///< adjust texcoords to roughly simulate a displacement mapped surface
1140 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1141 SHADERPERMUTATION_GAMMARAMPS = 1<<12, ///< gamma (postprocessing only)
1142 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing
1143 SHADERPERMUTATION_SATURATION = 1<<14, ///< user defined postprocessing
1144 SHADERPERMUTATION_LIMIT = 1<<15, ///< size of permutations array
1145 SHADERPERMUTATION_COUNT = 15 ///< size of shaderpermutationinfo array
1147 shaderpermutation_t;
1149 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1150 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1152 {"#define USEDIFFUSE\n", " diffuse"},
1153 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1154 {"#define USECOLORMAPPING\n", " colormapping"},
1155 {"#define USECONTRASTBOOST\n", " contrastboost"},
1156 {"#define USEFOG\n", " fog"},
1157 {"#define USECUBEFILTER\n", " cubefilter"},
1158 {"#define USEGLOW\n", " glow"},
1159 {"#define USESPECULAR\n", " specular"},
1160 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1161 {"#define USEREFLECTION\n", " reflection"},
1162 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1163 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1164 {"#define USEGAMMARAMPS\n", " gammaramps"},
1165 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1166 {"#define USESATURATION\n", " saturation"},
1169 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1170 typedef enum shadermode_e
1172 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1173 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1174 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1175 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1176 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1177 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1178 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1179 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1180 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1181 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1182 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1183 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1188 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1189 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1191 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1192 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1193 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1194 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1195 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1196 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1197 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1198 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1199 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1200 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1201 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1202 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1205 typedef struct r_glsl_permutation_s
1207 /// indicates if we have tried compiling this permutation already
1209 /// 0 if compilation failed
1211 /// locations of detected uniforms in program object, or -1 if not found
1212 int loc_Texture_First;
1213 int loc_Texture_Second;
1214 int loc_Texture_GammaRamps;
1215 int loc_Texture_Normal;
1216 int loc_Texture_Color;
1217 int loc_Texture_Gloss;
1218 int loc_Texture_Glow;
1219 int loc_Texture_SecondaryNormal;
1220 int loc_Texture_SecondaryColor;
1221 int loc_Texture_SecondaryGloss;
1222 int loc_Texture_SecondaryGlow;
1223 int loc_Texture_Pants;
1224 int loc_Texture_Shirt;
1225 int loc_Texture_FogMask;
1226 int loc_Texture_Lightmap;
1227 int loc_Texture_Deluxemap;
1228 int loc_Texture_Attenuation;
1229 int loc_Texture_Cube;
1230 int loc_Texture_Refraction;
1231 int loc_Texture_Reflection;
1233 int loc_LightPosition;
1234 int loc_EyePosition;
1235 int loc_Color_Pants;
1236 int loc_Color_Shirt;
1237 int loc_FogRangeRecip;
1238 int loc_AmbientScale;
1239 int loc_DiffuseScale;
1240 int loc_SpecularScale;
1241 int loc_SpecularPower;
1243 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1244 int loc_OffsetMapping_Scale;
1246 int loc_AmbientColor;
1247 int loc_DiffuseColor;
1248 int loc_SpecularColor;
1250 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1251 int loc_GammaCoeff; ///< 1 / gamma
1252 int loc_DistortScaleRefractReflect;
1253 int loc_ScreenScaleRefractReflect;
1254 int loc_ScreenCenterRefractReflect;
1255 int loc_RefractColor;
1256 int loc_ReflectColor;
1257 int loc_ReflectFactor;
1258 int loc_ReflectOffset;
1267 r_glsl_permutation_t;
1269 /// information about each possible shader permutation
1270 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1271 /// currently selected permutation
1272 r_glsl_permutation_t *r_glsl_permutation;
1274 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1277 if (!filename || !filename[0])
1279 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1282 if (printfromdisknotice)
1283 Con_DPrint("from disk... ");
1284 return shaderstring;
1286 else if (!strcmp(filename, "glsl/default.glsl"))
1288 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1289 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1291 return shaderstring;
1294 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1297 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1298 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1299 int vertstrings_count = 0;
1300 int geomstrings_count = 0;
1301 int fragstrings_count = 0;
1302 char *vertexstring, *geometrystring, *fragmentstring;
1303 const char *vertstrings_list[32+3];
1304 const char *geomstrings_list[32+3];
1305 const char *fragstrings_list[32+3];
1306 char permutationname[256];
1313 permutationname[0] = 0;
1314 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1315 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1316 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1318 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1320 // the first pretext is which type of shader to compile as
1321 // (later these will all be bound together as a program object)
1322 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1323 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1324 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1326 // the second pretext is the mode (for example a light source)
1327 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1328 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1329 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1330 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1332 // now add all the permutation pretexts
1333 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1335 if (permutation & (1<<i))
1337 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1338 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1339 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1340 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1344 // keep line numbers correct
1345 vertstrings_list[vertstrings_count++] = "\n";
1346 geomstrings_list[geomstrings_count++] = "\n";
1347 fragstrings_list[fragstrings_count++] = "\n";
1351 // now append the shader text itself
1352 vertstrings_list[vertstrings_count++] = vertexstring;
1353 geomstrings_list[geomstrings_count++] = geometrystring;
1354 fragstrings_list[fragstrings_count++] = fragmentstring;
1356 // if any sources were NULL, clear the respective list
1358 vertstrings_count = 0;
1359 if (!geometrystring)
1360 geomstrings_count = 0;
1361 if (!fragmentstring)
1362 fragstrings_count = 0;
1364 // compile the shader program
1365 if (vertstrings_count + geomstrings_count + fragstrings_count)
1366 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1370 qglUseProgramObjectARB(p->program);CHECKGLERROR
1371 // look up all the uniform variable names we care about, so we don't
1372 // have to look them up every time we set them
1373 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1374 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1375 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1376 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1377 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1378 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1379 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1380 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1381 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1382 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1383 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1384 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1385 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1386 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1387 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1388 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1389 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1390 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1391 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1392 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1393 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1394 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1395 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1396 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1397 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1398 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1399 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1400 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1401 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1402 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1403 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1404 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1405 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1406 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1407 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1408 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1409 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1410 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1411 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1412 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1413 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1414 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1415 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1416 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1417 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1418 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1419 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1420 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1421 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1422 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1423 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1424 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1425 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1426 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1427 // initialize the samplers to refer to the texture units we use
1428 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1429 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1430 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1431 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1432 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1433 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1434 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1435 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1436 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1437 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1438 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1439 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1440 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1441 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1442 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1443 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1444 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1445 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1446 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1447 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1449 if (developer.integer)
1450 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1453 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1457 Mem_Free(vertexstring);
1459 Mem_Free(geometrystring);
1461 Mem_Free(fragmentstring);
1464 void R_GLSL_Restart_f(void)
1467 unsigned int permutation;
1468 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1469 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1470 if (r_glsl_permutations[mode][permutation].program)
1471 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1472 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1475 void R_GLSL_DumpShader_f(void)
1479 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1482 Con_Printf("failed to write to glsl/default.glsl\n");
1486 FS_Print(file, "// The engine may define the following macros:\n");
1487 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1488 for (i = 0;i < SHADERMODE_COUNT;i++)
1489 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1490 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1491 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1492 FS_Print(file, "\n");
1493 FS_Print(file, builtinshaderstring);
1496 Con_Printf("glsl/default.glsl written\n");
1499 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1501 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1502 if (r_glsl_permutation != perm)
1504 r_glsl_permutation = perm;
1505 if (!r_glsl_permutation->program)
1507 if (!r_glsl_permutation->compiled)
1508 R_GLSL_CompilePermutation(mode, permutation);
1509 if (!r_glsl_permutation->program)
1511 // remove features until we find a valid permutation
1513 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1515 // reduce i more quickly whenever it would not remove any bits
1516 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1517 if (!(permutation & j))
1520 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1521 if (!r_glsl_permutation->compiled)
1522 R_GLSL_CompilePermutation(mode, permutation);
1523 if (r_glsl_permutation->program)
1526 if (i >= SHADERPERMUTATION_COUNT)
1528 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");
1529 Cvar_SetValueQuick(&r_glsl, 0);
1530 R_GLSL_Restart_f(); // unload shaders
1531 return; // no bit left to clear
1536 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1540 void R_SetupGenericShader(qboolean usetexture)
1542 if (gl_support_fragment_shader)
1544 if (r_glsl.integer && r_glsl_usegeneric.integer)
1545 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1546 else if (r_glsl_permutation)
1548 r_glsl_permutation = NULL;
1549 qglUseProgramObjectARB(0);CHECKGLERROR
1554 void R_SetupGenericTwoTextureShader(int texturemode)
1556 if (gl_support_fragment_shader)
1558 if (r_glsl.integer && r_glsl_usegeneric.integer)
1559 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))));
1560 else if (r_glsl_permutation)
1562 r_glsl_permutation = NULL;
1563 qglUseProgramObjectARB(0);CHECKGLERROR
1566 if (!r_glsl_permutation)
1568 if (texturemode == GL_DECAL && gl_combine.integer)
1569 texturemode = GL_INTERPOLATE_ARB;
1570 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1574 void R_SetupDepthOrShadowShader(void)
1576 if (gl_support_fragment_shader)
1578 if (r_glsl.integer && r_glsl_usegeneric.integer)
1579 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1580 else if (r_glsl_permutation)
1582 r_glsl_permutation = NULL;
1583 qglUseProgramObjectARB(0);CHECKGLERROR
1588 extern rtexture_t *r_shadow_attenuationgradienttexture;
1589 extern rtexture_t *r_shadow_attenuation2dtexture;
1590 extern rtexture_t *r_shadow_attenuation3dtexture;
1591 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1593 // select a permutation of the lighting shader appropriate to this
1594 // combination of texture, entity, light source, and fogging, only use the
1595 // minimum features necessary to avoid wasting rendering time in the
1596 // fragment shader on features that are not being used
1597 unsigned int permutation = 0;
1598 unsigned int mode = 0;
1599 // TODO: implement geometry-shader based shadow volumes someday
1600 if (r_glsl_offsetmapping.integer)
1602 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1603 if (r_glsl_offsetmapping_reliefmapping.integer)
1604 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1606 if (rsurfacepass == RSURFPASS_BACKGROUND)
1608 // distorted background
1609 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1610 mode = SHADERMODE_WATER;
1612 mode = SHADERMODE_REFRACTION;
1614 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1617 mode = SHADERMODE_LIGHTSOURCE;
1618 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1619 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1620 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1621 permutation |= SHADERPERMUTATION_CUBEFILTER;
1622 if (diffusescale > 0)
1623 permutation |= SHADERPERMUTATION_DIFFUSE;
1624 if (specularscale > 0)
1625 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1626 if (r_refdef.fogenabled)
1627 permutation |= SHADERPERMUTATION_FOG;
1628 if (rsurface.texture->colormapping)
1629 permutation |= SHADERPERMUTATION_COLORMAPPING;
1630 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1631 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1633 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1635 // unshaded geometry (fullbright or ambient model lighting)
1636 mode = SHADERMODE_FLATCOLOR;
1637 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1638 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1639 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1640 permutation |= SHADERPERMUTATION_GLOW;
1641 if (r_refdef.fogenabled)
1642 permutation |= SHADERPERMUTATION_FOG;
1643 if (rsurface.texture->colormapping)
1644 permutation |= SHADERPERMUTATION_COLORMAPPING;
1645 if (r_glsl_offsetmapping.integer)
1647 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1648 if (r_glsl_offsetmapping_reliefmapping.integer)
1649 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
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;
1656 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1658 // directional model lighting
1659 mode = SHADERMODE_LIGHTDIRECTION;
1660 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1661 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1662 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1663 permutation |= SHADERPERMUTATION_GLOW;
1664 permutation |= SHADERPERMUTATION_DIFFUSE;
1665 if (specularscale > 0)
1666 permutation |= SHADERPERMUTATION_SPECULAR;
1667 if (r_refdef.fogenabled)
1668 permutation |= SHADERPERMUTATION_FOG;
1669 if (rsurface.texture->colormapping)
1670 permutation |= SHADERPERMUTATION_COLORMAPPING;
1671 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1672 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1673 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1674 permutation |= SHADERPERMUTATION_REFLECTION;
1676 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1678 // ambient model lighting
1679 mode = SHADERMODE_LIGHTDIRECTION;
1680 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1681 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1682 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1683 permutation |= SHADERPERMUTATION_GLOW;
1684 if (r_refdef.fogenabled)
1685 permutation |= SHADERPERMUTATION_FOG;
1686 if (rsurface.texture->colormapping)
1687 permutation |= SHADERPERMUTATION_COLORMAPPING;
1688 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1689 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1690 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1691 permutation |= SHADERPERMUTATION_REFLECTION;
1696 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1698 // deluxemapping (light direction texture)
1699 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1700 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1702 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1703 permutation |= SHADERPERMUTATION_DIFFUSE;
1704 if (specularscale > 0)
1705 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1707 else if (r_glsl_deluxemapping.integer >= 2)
1709 // fake deluxemapping (uniform light direction in tangentspace)
1710 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1711 permutation |= SHADERPERMUTATION_DIFFUSE;
1712 if (specularscale > 0)
1713 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1715 else if (rsurface.uselightmaptexture)
1717 // ordinary lightmapping (q1bsp, q3bsp)
1718 mode = SHADERMODE_LIGHTMAP;
1722 // ordinary vertex coloring (q3bsp)
1723 mode = SHADERMODE_VERTEXCOLOR;
1725 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1726 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1727 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1728 permutation |= SHADERPERMUTATION_GLOW;
1729 if (r_refdef.fogenabled)
1730 permutation |= SHADERPERMUTATION_FOG;
1731 if (rsurface.texture->colormapping)
1732 permutation |= SHADERPERMUTATION_COLORMAPPING;
1733 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1734 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1735 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1736 permutation |= SHADERPERMUTATION_REFLECTION;
1738 if(permutation & SHADERPERMUTATION_SPECULAR)
1739 if(r_shadow_glossexact.integer)
1740 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
1741 R_SetupShader_SetPermutation(mode, permutation);
1742 if (mode == SHADERMODE_LIGHTSOURCE)
1744 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1745 if (permutation & SHADERPERMUTATION_DIFFUSE)
1747 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1748 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1749 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1750 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1754 // ambient only is simpler
1755 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]);
1756 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1757 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1758 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1760 // additive passes are only darkened by fog, not tinted
1761 if (r_glsl_permutation->loc_FogColor >= 0)
1762 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1766 if (mode == SHADERMODE_LIGHTDIRECTION)
1768 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);
1769 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);
1770 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);
1771 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]);
1775 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
1776 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1777 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1779 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]);
1780 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1781 // additive passes are only darkened by fog, not tinted
1782 if (r_glsl_permutation->loc_FogColor >= 0)
1784 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1785 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1787 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1789 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);
1790 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]);
1791 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]);
1792 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1793 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1794 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1795 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1797 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1799 // The formula used is actually:
1800 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1801 // color.rgb *= SceneBrightness;
1803 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1804 // and do [[calculations]] here in the engine
1805 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1806 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1809 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1810 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1811 if (r_glsl_permutation->loc_Color_Pants >= 0)
1813 if (rsurface.texture->currentskinframe->pants)
1814 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1816 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1818 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1820 if (rsurface.texture->currentskinframe->shirt)
1821 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1823 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1825 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
1826 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
1828 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
1832 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1834 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1838 #define SKINFRAME_HASH 1024
1842 int loadsequence; // incremented each level change
1843 memexpandablearray_t array;
1844 skinframe_t *hash[SKINFRAME_HASH];
1847 r_skinframe_t r_skinframe;
1849 void R_SkinFrame_PrepareForPurge(void)
1851 r_skinframe.loadsequence++;
1852 // wrap it without hitting zero
1853 if (r_skinframe.loadsequence >= 200)
1854 r_skinframe.loadsequence = 1;
1857 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1861 // mark the skinframe as used for the purging code
1862 skinframe->loadsequence = r_skinframe.loadsequence;
1865 void R_SkinFrame_Purge(void)
1869 for (i = 0;i < SKINFRAME_HASH;i++)
1871 for (s = r_skinframe.hash[i];s;s = s->next)
1873 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1875 if (s->merged == s->base)
1877 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1878 R_PurgeTexture(s->stain );s->stain = NULL;
1879 R_PurgeTexture(s->merged);s->merged = NULL;
1880 R_PurgeTexture(s->base );s->base = NULL;
1881 R_PurgeTexture(s->pants );s->pants = NULL;
1882 R_PurgeTexture(s->shirt );s->shirt = NULL;
1883 R_PurgeTexture(s->nmap );s->nmap = NULL;
1884 R_PurgeTexture(s->gloss );s->gloss = NULL;
1885 R_PurgeTexture(s->glow );s->glow = NULL;
1886 R_PurgeTexture(s->fog );s->fog = NULL;
1887 s->loadsequence = 0;
1893 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1895 char basename[MAX_QPATH];
1897 Image_StripImageExtension(name, basename, sizeof(basename));
1899 if( last == NULL ) {
1901 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1902 item = r_skinframe.hash[hashindex];
1907 // linearly search through the hash bucket
1908 for( ; item ; item = item->next ) {
1909 if( !strcmp( item->basename, basename ) ) {
1916 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1920 char basename[MAX_QPATH];
1922 Image_StripImageExtension(name, basename, sizeof(basename));
1924 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1925 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1926 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1930 rtexture_t *dyntexture;
1931 // check whether its a dynamic texture
1932 dyntexture = CL_GetDynTexture( basename );
1933 if (!add && !dyntexture)
1935 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1936 memset(item, 0, sizeof(*item));
1937 strlcpy(item->basename, basename, sizeof(item->basename));
1938 item->base = dyntexture; // either NULL or dyntexture handle
1939 item->textureflags = textureflags;
1940 item->comparewidth = comparewidth;
1941 item->compareheight = compareheight;
1942 item->comparecrc = comparecrc;
1943 item->next = r_skinframe.hash[hashindex];
1944 r_skinframe.hash[hashindex] = item;
1946 else if( item->base == NULL )
1948 rtexture_t *dyntexture;
1949 // check whether its a dynamic texture
1950 // 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]
1951 dyntexture = CL_GetDynTexture( basename );
1952 item->base = dyntexture; // either NULL or dyntexture handle
1955 R_SkinFrame_MarkUsed(item);
1959 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
1961 unsigned long long avgcolor[5], wsum; \
1969 for(pix = 0; pix < cnt; ++pix) \
1972 for(comp = 0; comp < 3; ++comp) \
1974 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
1977 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1979 for(comp = 0; comp < 3; ++comp) \
1980 avgcolor[comp] += getpixel * w; \
1983 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1984 avgcolor[4] += getpixel; \
1986 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
1988 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
1989 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
1990 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
1991 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
1994 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
1996 // FIXME: it should be possible to disable loading various layers using
1997 // cvars, to prevent wasted loading time and memory usage if the user does
1999 qboolean loadnormalmap = true;
2000 qboolean loadgloss = true;
2001 qboolean loadpantsandshirt = true;
2002 qboolean loadglow = true;
2004 unsigned char *pixels;
2005 unsigned char *bumppixels;
2006 unsigned char *basepixels = NULL;
2007 int basepixels_width;
2008 int basepixels_height;
2009 skinframe_t *skinframe;
2013 if (cls.state == ca_dedicated)
2016 // return an existing skinframe if already loaded
2017 // if loading of the first image fails, don't make a new skinframe as it
2018 // would cause all future lookups of this to be missing
2019 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2020 if (skinframe && skinframe->base)
2023 basepixels = loadimagepixelsbgra(name, complain, true);
2024 if (basepixels == NULL)
2027 if (developer_loading.integer)
2028 Con_Printf("loading skin \"%s\"\n", name);
2030 // we've got some pixels to store, so really allocate this new texture now
2032 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2033 skinframe->stain = NULL;
2034 skinframe->merged = NULL;
2035 skinframe->base = r_texture_notexture;
2036 skinframe->pants = NULL;
2037 skinframe->shirt = NULL;
2038 skinframe->nmap = r_texture_blanknormalmap;
2039 skinframe->gloss = NULL;
2040 skinframe->glow = NULL;
2041 skinframe->fog = NULL;
2043 basepixels_width = image_width;
2044 basepixels_height = image_height;
2045 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);
2047 if (textureflags & TEXF_ALPHA)
2049 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2050 if (basepixels[j] < 255)
2052 if (j < basepixels_width * basepixels_height * 4)
2054 // has transparent pixels
2056 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2057 for (j = 0;j < image_width * image_height * 4;j += 4)
2062 pixels[j+3] = basepixels[j+3];
2064 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);
2069 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2070 //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]);
2072 // _norm is the name used by tenebrae and has been adopted as standard
2075 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2077 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);
2081 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2083 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2084 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2085 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);
2087 Mem_Free(bumppixels);
2089 else if (r_shadow_bumpscale_basetexture.value > 0)
2091 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2092 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2093 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);
2097 // _luma is supported for tenebrae compatibility
2098 // (I think it's a very stupid name, but oh well)
2099 // _glow is the preferred name
2100 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;}
2101 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;}
2102 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;}
2103 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;}
2106 Mem_Free(basepixels);
2111 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2114 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2117 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)
2122 for (i = 0;i < width*height;i++)
2123 if (((unsigned char *)&palette[in[i]])[3] > 0)
2125 if (i == width*height)
2128 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2131 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2132 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2135 unsigned char *temp1, *temp2;
2136 skinframe_t *skinframe;
2138 if (cls.state == ca_dedicated)
2141 // if already loaded just return it, otherwise make a new skinframe
2142 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2143 if (skinframe && skinframe->base)
2146 skinframe->stain = NULL;
2147 skinframe->merged = NULL;
2148 skinframe->base = r_texture_notexture;
2149 skinframe->pants = NULL;
2150 skinframe->shirt = NULL;
2151 skinframe->nmap = r_texture_blanknormalmap;
2152 skinframe->gloss = NULL;
2153 skinframe->glow = NULL;
2154 skinframe->fog = NULL;
2156 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2160 if (developer_loading.integer)
2161 Con_Printf("loading 32bit skin \"%s\"\n", name);
2163 if (r_shadow_bumpscale_basetexture.value > 0)
2165 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2166 temp2 = temp1 + width * height * 4;
2167 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2168 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2171 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2172 if (textureflags & TEXF_ALPHA)
2174 for (i = 3;i < width * height * 4;i += 4)
2175 if (skindata[i] < 255)
2177 if (i < width * height * 4)
2179 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2180 memcpy(fogpixels, skindata, width * height * 4);
2181 for (i = 0;i < width * height * 4;i += 4)
2182 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2183 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2184 Mem_Free(fogpixels);
2188 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2189 //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]);
2194 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2197 unsigned char *temp1, *temp2;
2198 unsigned int *palette;
2199 skinframe_t *skinframe;
2201 if (cls.state == ca_dedicated)
2204 // if already loaded just return it, otherwise make a new skinframe
2205 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2206 if (skinframe && skinframe->base)
2209 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2211 skinframe->stain = NULL;
2212 skinframe->merged = NULL;
2213 skinframe->base = r_texture_notexture;
2214 skinframe->pants = NULL;
2215 skinframe->shirt = NULL;
2216 skinframe->nmap = r_texture_blanknormalmap;
2217 skinframe->gloss = NULL;
2218 skinframe->glow = NULL;
2219 skinframe->fog = NULL;
2221 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2225 if (developer_loading.integer)
2226 Con_Printf("loading quake skin \"%s\"\n", name);
2228 if (r_shadow_bumpscale_basetexture.value > 0)
2230 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2231 temp2 = temp1 + width * height * 4;
2232 // use either a custom palette or the quake palette
2233 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2234 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2235 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2238 // use either a custom palette, or the quake palette
2239 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2240 if (loadglowtexture)
2241 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2242 if (loadpantsandshirt)
2244 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2245 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2247 if (skinframe->pants || skinframe->shirt)
2248 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
2249 if (textureflags & TEXF_ALPHA)
2251 for (i = 0;i < width * height;i++)
2252 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2254 if (i < width * height)
2255 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2258 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2259 //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]);
2264 skinframe_t *R_SkinFrame_LoadMissing(void)
2266 skinframe_t *skinframe;
2268 if (cls.state == ca_dedicated)
2271 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2272 skinframe->stain = NULL;
2273 skinframe->merged = NULL;
2274 skinframe->base = r_texture_notexture;
2275 skinframe->pants = NULL;
2276 skinframe->shirt = NULL;
2277 skinframe->nmap = r_texture_blanknormalmap;
2278 skinframe->gloss = NULL;
2279 skinframe->glow = NULL;
2280 skinframe->fog = NULL;
2282 skinframe->avgcolor[0] = rand() / RAND_MAX;
2283 skinframe->avgcolor[1] = rand() / RAND_MAX;
2284 skinframe->avgcolor[2] = rand() / RAND_MAX;
2285 skinframe->avgcolor[3] = 1;
2290 void gl_main_start(void)
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 // set up r_skinframe loading system for textures
2300 memset(&r_skinframe, 0, sizeof(r_skinframe));
2301 r_skinframe.loadsequence = 1;
2302 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2304 r_main_texturepool = R_AllocTexturePool();
2305 R_BuildBlankTextures();
2307 if (gl_texturecubemap)
2310 R_BuildNormalizationCube();
2312 r_texture_fogattenuation = NULL;
2313 r_texture_gammaramps = NULL;
2314 //r_texture_fogintensity = NULL;
2315 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2316 memset(&r_waterstate, 0, sizeof(r_waterstate));
2317 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2318 memset(&r_svbsp, 0, sizeof (r_svbsp));
2320 r_refdef.fogmasktable_density = 0;
2323 extern rtexture_t *loadingscreentexture;
2324 void gl_main_shutdown(void)
2327 qglDeleteQueriesARB(r_maxqueries, r_queries);
2331 memset(r_queries, 0, sizeof(r_queries));
2333 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2334 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2336 // clear out the r_skinframe state
2337 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2338 memset(&r_skinframe, 0, sizeof(r_skinframe));
2341 Mem_Free(r_svbsp.nodes);
2342 memset(&r_svbsp, 0, sizeof (r_svbsp));
2343 R_FreeTexturePool(&r_main_texturepool);
2344 loadingscreentexture = NULL;
2345 r_texture_blanknormalmap = NULL;
2346 r_texture_white = NULL;
2347 r_texture_grey128 = NULL;
2348 r_texture_black = NULL;
2349 r_texture_whitecube = NULL;
2350 r_texture_normalizationcube = NULL;
2351 r_texture_fogattenuation = NULL;
2352 r_texture_gammaramps = NULL;
2353 //r_texture_fogintensity = NULL;
2354 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2355 memset(&r_waterstate, 0, sizeof(r_waterstate));
2359 extern void CL_ParseEntityLump(char *entitystring);
2360 void gl_main_newmap(void)
2362 // FIXME: move this code to client
2364 char *entities, entname[MAX_QPATH];
2367 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2368 l = (int)strlen(entname) - 4;
2369 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2371 memcpy(entname + l, ".ent", 5);
2372 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2374 CL_ParseEntityLump(entities);
2379 if (cl.worldmodel->brush.entities)
2380 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2384 void GL_Main_Init(void)
2386 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2388 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2389 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2390 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2391 if (gamemode == GAME_NEHAHRA)
2393 Cvar_RegisterVariable (&gl_fogenable);
2394 Cvar_RegisterVariable (&gl_fogdensity);
2395 Cvar_RegisterVariable (&gl_fogred);
2396 Cvar_RegisterVariable (&gl_foggreen);
2397 Cvar_RegisterVariable (&gl_fogblue);
2398 Cvar_RegisterVariable (&gl_fogstart);
2399 Cvar_RegisterVariable (&gl_fogend);
2400 Cvar_RegisterVariable (&gl_skyclip);
2402 Cvar_RegisterVariable(&r_motionblur);
2403 Cvar_RegisterVariable(&r_motionblur_maxblur);
2404 Cvar_RegisterVariable(&r_motionblur_bmin);
2405 Cvar_RegisterVariable(&r_motionblur_vmin);
2406 Cvar_RegisterVariable(&r_motionblur_vmax);
2407 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2408 Cvar_RegisterVariable(&r_motionblur_randomize);
2409 Cvar_RegisterVariable(&r_damageblur);
2410 Cvar_RegisterVariable(&r_animcache);
2411 Cvar_RegisterVariable(&r_motionblur_debug);
2412 Cvar_RegisterVariable(&r_depthfirst);
2413 Cvar_RegisterVariable(&r_useinfinitefarclip);
2414 Cvar_RegisterVariable(&r_nearclip);
2415 Cvar_RegisterVariable(&r_showbboxes);
2416 Cvar_RegisterVariable(&r_showsurfaces);
2417 Cvar_RegisterVariable(&r_showtris);
2418 Cvar_RegisterVariable(&r_shownormals);
2419 Cvar_RegisterVariable(&r_showlighting);
2420 Cvar_RegisterVariable(&r_showshadowvolumes);
2421 Cvar_RegisterVariable(&r_showcollisionbrushes);
2422 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2423 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2424 Cvar_RegisterVariable(&r_showdisabledepthtest);
2425 Cvar_RegisterVariable(&r_drawportals);
2426 Cvar_RegisterVariable(&r_drawentities);
2427 Cvar_RegisterVariable(&r_cullentities_trace);
2428 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2429 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2430 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2431 Cvar_RegisterVariable(&r_drawviewmodel);
2432 Cvar_RegisterVariable(&r_speeds);
2433 Cvar_RegisterVariable(&r_fullbrights);
2434 Cvar_RegisterVariable(&r_wateralpha);
2435 Cvar_RegisterVariable(&r_dynamic);
2436 Cvar_RegisterVariable(&r_fullbright);
2437 Cvar_RegisterVariable(&r_shadows);
2438 Cvar_RegisterVariable(&r_shadows_throwdistance);
2439 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2440 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2441 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2442 Cvar_RegisterVariable(&r_fog_exp2);
2443 Cvar_RegisterVariable(&r_drawfog);
2444 Cvar_RegisterVariable(&r_textureunits);
2445 Cvar_RegisterVariable(&r_glsl);
2446 Cvar_RegisterVariable(&r_glsl_contrastboost);
2447 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2448 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2449 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2450 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2451 Cvar_RegisterVariable(&r_glsl_postprocess);
2452 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2453 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2454 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2455 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2456 Cvar_RegisterVariable(&r_glsl_usegeneric);
2457 Cvar_RegisterVariable(&r_water);
2458 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2459 Cvar_RegisterVariable(&r_water_clippingplanebias);
2460 Cvar_RegisterVariable(&r_water_refractdistort);
2461 Cvar_RegisterVariable(&r_water_reflectdistort);
2462 Cvar_RegisterVariable(&r_lerpsprites);
2463 Cvar_RegisterVariable(&r_lerpmodels);
2464 Cvar_RegisterVariable(&r_lerplightstyles);
2465 Cvar_RegisterVariable(&r_waterscroll);
2466 Cvar_RegisterVariable(&r_bloom);
2467 Cvar_RegisterVariable(&r_bloom_colorscale);
2468 Cvar_RegisterVariable(&r_bloom_brighten);
2469 Cvar_RegisterVariable(&r_bloom_blur);
2470 Cvar_RegisterVariable(&r_bloom_resolution);
2471 Cvar_RegisterVariable(&r_bloom_colorexponent);
2472 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2473 Cvar_RegisterVariable(&r_hdr);
2474 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2475 Cvar_RegisterVariable(&r_hdr_glowintensity);
2476 Cvar_RegisterVariable(&r_hdr_range);
2477 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2478 Cvar_RegisterVariable(&developer_texturelogging);
2479 Cvar_RegisterVariable(&gl_lightmaps);
2480 Cvar_RegisterVariable(&r_test);
2481 Cvar_RegisterVariable(&r_batchmode);
2482 Cvar_RegisterVariable(&r_glsl_saturation);
2483 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2484 Cvar_SetValue("r_fullbrights", 0);
2485 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2487 Cvar_RegisterVariable(&r_track_sprites);
2488 Cvar_RegisterVariable(&r_track_sprites_flags);
2489 Cvar_RegisterVariable(&r_track_sprites_scalew);
2490 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2493 extern void R_Textures_Init(void);
2494 extern void GL_Draw_Init(void);
2495 extern void GL_Main_Init(void);
2496 extern void R_Shadow_Init(void);
2497 extern void R_Sky_Init(void);
2498 extern void GL_Surf_Init(void);
2499 extern void R_Particles_Init(void);
2500 extern void R_Explosion_Init(void);
2501 extern void gl_backend_init(void);
2502 extern void Sbar_Init(void);
2503 extern void R_LightningBeams_Init(void);
2504 extern void Mod_RenderInit(void);
2506 void Render_Init(void)
2518 R_LightningBeams_Init();
2527 extern char *ENGINE_EXTENSIONS;
2530 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2531 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2532 gl_version = (const char *)qglGetString(GL_VERSION);
2533 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2537 if (!gl_platformextensions)
2538 gl_platformextensions = "";
2540 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2541 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2542 Con_Printf("GL_VERSION: %s\n", gl_version);
2543 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2544 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2546 VID_CheckExtensions();
2548 // LordHavoc: report supported extensions
2549 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2551 // clear to black (loading plaque will be seen over this)
2553 qglClearColor(0,0,0,1);CHECKGLERROR
2554 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2557 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2561 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2563 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2566 p = r_refdef.view.frustum + i;
2571 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2575 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2579 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2583 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2587 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2591 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2595 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2599 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2607 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2611 for (i = 0;i < numplanes;i++)
2618 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2622 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2626 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2630 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2634 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2638 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2642 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2646 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2654 //==================================================================================
2656 // LordHavoc: animcache written by Echon, refactored and reformatted by me
2659 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
2660 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
2661 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
2664 typedef struct r_animcache_entity_s
2671 qboolean wantnormals;
2672 qboolean wanttangents;
2674 r_animcache_entity_t;
2676 typedef struct r_animcache_s
2678 r_animcache_entity_t entity[MAX_EDICTS];
2684 static r_animcache_t r_animcachestate;
2686 void R_AnimCache_Free(void)
2689 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
2691 r_animcachestate.entity[idx].maxvertices = 0;
2692 Mem_Free(r_animcachestate.entity[idx].vertex3f);
2693 r_animcachestate.entity[idx].vertex3f = NULL;
2694 r_animcachestate.entity[idx].normal3f = NULL;
2695 r_animcachestate.entity[idx].svector3f = NULL;
2696 r_animcachestate.entity[idx].tvector3f = NULL;
2698 r_animcachestate.currentindex = 0;
2699 r_animcachestate.maxindex = 0;
2702 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
2706 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
2708 if (cache->maxvertices >= numvertices)
2711 // Release existing memory
2712 if (cache->vertex3f)
2713 Mem_Free(cache->vertex3f);
2715 // Pad by 1024 verts
2716 cache->maxvertices = (numvertices + 1023) & ~1023;
2717 arraySize = cache->maxvertices * 3;
2719 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
2720 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
2721 r_animcachestate.entity[cacheIdx].vertex3f = base;
2722 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
2723 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
2724 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
2726 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
2729 void R_AnimCache_NewFrame(void)
2733 if (r_animcache.integer && r_drawentities.integer)
2734 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
2735 else if (r_animcachestate.maxindex)
2738 r_animcachestate.currentindex = 0;
2740 for (i = 0;i < r_refdef.scene.numentities;i++)
2741 r_refdef.scene.entities[i]->animcacheindex = -1;
2744 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2746 dp_model_t *model = ent->model;
2747 r_animcache_entity_t *c;
2748 // see if it's already cached this frame
2749 if (ent->animcacheindex >= 0)
2751 // add normals/tangents if needed
2752 c = r_animcachestate.entity + ent->animcacheindex;
2754 wantnormals = false;
2755 if (c->wanttangents)
2756 wanttangents = false;
2757 if (wantnormals || wanttangents)
2758 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
2762 // see if this ent is worth caching
2763 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
2765 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
2767 // assign it a cache entry and make sure the arrays are big enough
2768 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
2769 ent->animcacheindex = r_animcachestate.currentindex++;
2770 c = r_animcachestate.entity + ent->animcacheindex;
2771 c->wantnormals = wantnormals;
2772 c->wanttangents = wanttangents;
2773 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
2778 void R_AnimCache_CacheVisibleEntities(void)
2781 qboolean wantnormals;
2782 qboolean wanttangents;
2784 if (!r_animcachestate.maxindex)
2787 wantnormals = !r_showsurfaces.integer;
2788 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
2790 // TODO: thread this?
2792 for (i = 0;i < r_refdef.scene.numentities;i++)
2794 if (!r_refdef.viewcache.entityvisible[i])
2796 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
2800 //==================================================================================
2802 static void R_View_UpdateEntityLighting (void)
2805 entity_render_t *ent;
2806 vec3_t tempdiffusenormal;
2808 for (i = 0;i < r_refdef.scene.numentities;i++)
2810 ent = r_refdef.scene.entities[i];
2812 // skip unseen models
2813 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
2817 if (ent->model && ent->model->brush.num_leafs)
2819 // TODO: use modellight for r_ambient settings on world?
2820 VectorSet(ent->modellight_ambient, 0, 0, 0);
2821 VectorSet(ent->modellight_diffuse, 0, 0, 0);
2822 VectorSet(ent->modellight_lightdir, 0, 0, 1);
2826 // fetch the lighting from the worldmodel data
2827 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));
2828 VectorClear(ent->modellight_diffuse);
2829 VectorClear(tempdiffusenormal);
2830 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
2833 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2834 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2837 VectorSet(ent->modellight_ambient, 1, 1, 1);
2839 // move the light direction into modelspace coordinates for lighting code
2840 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2841 if(VectorLength2(ent->modellight_lightdir) == 0)
2842 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2843 VectorNormalize(ent->modellight_lightdir);
2847 static void R_View_UpdateEntityVisible (void)
2850 entity_render_t *ent;
2852 if (!r_drawentities.integer)
2855 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2856 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2858 // worldmodel can check visibility
2859 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2860 for (i = 0;i < r_refdef.scene.numentities;i++)
2862 ent = r_refdef.scene.entities[i];
2863 if (!(ent->flags & renderimask))
2864 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)))
2865 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))
2866 r_refdef.viewcache.entityvisible[i] = true;
2868 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2870 for (i = 0;i < r_refdef.scene.numentities;i++)
2872 ent = r_refdef.scene.entities[i];
2873 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2875 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))
2876 ent->last_trace_visibility = realtime;
2877 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2878 r_refdef.viewcache.entityvisible[i] = 0;
2885 // no worldmodel or it can't check visibility
2886 for (i = 0;i < r_refdef.scene.numentities;i++)
2888 ent = r_refdef.scene.entities[i];
2889 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));
2894 /// only used if skyrendermasked, and normally returns false
2895 int R_DrawBrushModelsSky (void)
2898 entity_render_t *ent;
2900 if (!r_drawentities.integer)
2904 for (i = 0;i < r_refdef.scene.numentities;i++)
2906 if (!r_refdef.viewcache.entityvisible[i])
2908 ent = r_refdef.scene.entities[i];
2909 if (!ent->model || !ent->model->DrawSky)
2911 ent->model->DrawSky(ent);
2917 static void R_DrawNoModel(entity_render_t *ent);
2918 static void R_DrawModels(void)
2921 entity_render_t *ent;
2923 if (!r_drawentities.integer)
2926 for (i = 0;i < r_refdef.scene.numentities;i++)
2928 if (!r_refdef.viewcache.entityvisible[i])
2930 ent = r_refdef.scene.entities[i];
2931 r_refdef.stats.entities++;
2932 if (ent->model && ent->model->Draw != NULL)
2933 ent->model->Draw(ent);
2939 static void R_DrawModelsDepth(void)
2942 entity_render_t *ent;
2944 if (!r_drawentities.integer)
2947 for (i = 0;i < r_refdef.scene.numentities;i++)
2949 if (!r_refdef.viewcache.entityvisible[i])
2951 ent = r_refdef.scene.entities[i];
2952 if (ent->model && ent->model->DrawDepth != NULL)
2953 ent->model->DrawDepth(ent);
2957 static void R_DrawModelsDebug(void)
2960 entity_render_t *ent;
2962 if (!r_drawentities.integer)
2965 for (i = 0;i < r_refdef.scene.numentities;i++)
2967 if (!r_refdef.viewcache.entityvisible[i])
2969 ent = r_refdef.scene.entities[i];
2970 if (ent->model && ent->model->DrawDebug != NULL)
2971 ent->model->DrawDebug(ent);
2975 static void R_DrawModelsAddWaterPlanes(void)
2978 entity_render_t *ent;
2980 if (!r_drawentities.integer)
2983 for (i = 0;i < r_refdef.scene.numentities;i++)
2985 if (!r_refdef.viewcache.entityvisible[i])
2987 ent = r_refdef.scene.entities[i];
2988 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2989 ent->model->DrawAddWaterPlanes(ent);
2993 static void R_View_SetFrustum(void)
2996 double slopex, slopey;
2997 vec3_t forward, left, up, origin;
2999 // we can't trust r_refdef.view.forward and friends in reflected scenes
3000 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3003 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3004 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3005 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3006 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3007 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3008 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3009 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3010 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3011 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3012 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3013 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3014 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3018 zNear = r_refdef.nearclip;
3019 nudge = 1.0 - 1.0 / (1<<23);
3020 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3021 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3022 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3023 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3024 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3025 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3026 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3027 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3033 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3034 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3035 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3036 r_refdef.view.frustum[0].dist = m[15] - m[12];
3038 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3039 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3040 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3041 r_refdef.view.frustum[1].dist = m[15] + m[12];
3043 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3044 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3045 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3046 r_refdef.view.frustum[2].dist = m[15] - m[13];
3048 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3049 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3050 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3051 r_refdef.view.frustum[3].dist = m[15] + m[13];
3053 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3054 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3055 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3056 r_refdef.view.frustum[4].dist = m[15] - m[14];
3058 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3059 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3060 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3061 r_refdef.view.frustum[5].dist = m[15] + m[14];
3064 if (r_refdef.view.useperspective)
3066 slopex = 1.0 / r_refdef.view.frustum_x;
3067 slopey = 1.0 / r_refdef.view.frustum_y;
3068 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3069 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3070 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3071 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3072 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3074 // Leaving those out was a mistake, those were in the old code, and they
3075 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3076 // I couldn't reproduce it after adding those normalizations. --blub
3077 VectorNormalize(r_refdef.view.frustum[0].normal);
3078 VectorNormalize(r_refdef.view.frustum[1].normal);
3079 VectorNormalize(r_refdef.view.frustum[2].normal);
3080 VectorNormalize(r_refdef.view.frustum[3].normal);
3082 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3083 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
3084 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
3085 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
3086 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
3088 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3089 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3090 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3091 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3092 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3096 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3097 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3098 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3099 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3100 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3101 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3102 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3103 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3104 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3105 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3107 r_refdef.view.numfrustumplanes = 5;
3109 if (r_refdef.view.useclipplane)
3111 r_refdef.view.numfrustumplanes = 6;
3112 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3115 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3116 PlaneClassify(r_refdef.view.frustum + i);
3118 // LordHavoc: note to all quake engine coders, Quake had a special case
3119 // for 90 degrees which assumed a square view (wrong), so I removed it,
3120 // Quake2 has it disabled as well.
3122 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3123 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3124 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3125 //PlaneClassify(&frustum[0]);
3127 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3128 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3129 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3130 //PlaneClassify(&frustum[1]);
3132 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3133 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3134 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3135 //PlaneClassify(&frustum[2]);
3137 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3138 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3139 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3140 //PlaneClassify(&frustum[3]);
3143 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3144 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3145 //PlaneClassify(&frustum[4]);
3148 void R_View_Update(void)
3150 R_View_SetFrustum();
3151 R_View_WorldVisibility(r_refdef.view.useclipplane);
3152 R_View_UpdateEntityVisible();
3153 R_View_UpdateEntityLighting();
3156 void R_SetupView(qboolean allowwaterclippingplane)
3158 if (!r_refdef.view.useperspective)
3159 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);
3160 else if (gl_stencil && r_useinfinitefarclip.integer)
3161 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
3163 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
3165 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
3167 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3169 // LordHavoc: couldn't figure out how to make this approach the
3170 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3171 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3172 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3173 dist = r_refdef.view.clipplane.dist;
3174 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
3178 void R_ResetViewRendering2D(void)
3182 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3183 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3184 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
3185 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3186 GL_Color(1, 1, 1, 1);
3187 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3188 GL_BlendFunc(GL_ONE, GL_ZERO);
3189 GL_AlphaTest(false);
3190 GL_ScissorTest(false);
3191 GL_DepthMask(false);
3192 GL_DepthRange(0, 1);
3193 GL_DepthTest(false);
3194 R_Mesh_Matrix(&identitymatrix);
3195 R_Mesh_ResetTextureState();
3196 GL_PolygonOffset(0, 0);
3197 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3198 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3199 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3200 qglStencilMask(~0);CHECKGLERROR
3201 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3202 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3203 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3204 R_SetupGenericShader(true);
3207 void R_ResetViewRendering3D(void)
3211 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3212 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3214 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3215 GL_Color(1, 1, 1, 1);
3216 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3217 GL_BlendFunc(GL_ONE, GL_ZERO);
3218 GL_AlphaTest(false);
3219 GL_ScissorTest(true);
3221 GL_DepthRange(0, 1);
3223 R_Mesh_Matrix(&identitymatrix);
3224 R_Mesh_ResetTextureState();
3225 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3226 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3227 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3228 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3229 qglStencilMask(~0);CHECKGLERROR
3230 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3231 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3232 GL_CullFace(r_refdef.view.cullface_back);
3233 R_SetupGenericShader(true);
3236 void R_RenderScene(void);
3237 void R_RenderWaterPlanes(void);
3239 static void R_Water_StartFrame(void)
3242 int waterwidth, waterheight, texturewidth, textureheight;
3243 r_waterstate_waterplane_t *p;
3245 // set waterwidth and waterheight to the water resolution that will be
3246 // used (often less than the screen resolution for faster rendering)
3247 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3248 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3250 // calculate desired texture sizes
3251 // can't use water if the card does not support the texture size
3252 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3253 texturewidth = textureheight = waterwidth = waterheight = 0;
3254 else if (gl_support_arb_texture_non_power_of_two)
3256 texturewidth = waterwidth;
3257 textureheight = waterheight;
3261 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3262 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3265 // allocate textures as needed
3266 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3268 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3269 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3271 if (p->texture_refraction)
3272 R_FreeTexture(p->texture_refraction);
3273 p->texture_refraction = NULL;
3274 if (p->texture_reflection)
3275 R_FreeTexture(p->texture_reflection);
3276 p->texture_reflection = NULL;
3278 memset(&r_waterstate, 0, sizeof(r_waterstate));
3279 r_waterstate.waterwidth = waterwidth;
3280 r_waterstate.waterheight = waterheight;
3281 r_waterstate.texturewidth = texturewidth;
3282 r_waterstate.textureheight = textureheight;
3285 if (r_waterstate.waterwidth)
3287 r_waterstate.enabled = true;
3289 // set up variables that will be used in shader setup
3290 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3291 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3292 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3293 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3296 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3297 r_waterstate.numwaterplanes = 0;
3300 void R_Water_AddWaterPlane(msurface_t *surface)
3302 int triangleindex, planeindex;
3308 r_waterstate_waterplane_t *p;
3309 texture_t *t = R_GetCurrentTexture(surface->texture);
3310 // just use the first triangle with a valid normal for any decisions
3311 VectorClear(normal);
3312 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3314 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3315 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3316 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3317 TriangleNormal(vert[0], vert[1], vert[2], normal);
3318 if (VectorLength2(normal) >= 0.001)
3322 VectorCopy(normal, plane.normal);
3323 VectorNormalize(plane.normal);
3324 plane.dist = DotProduct(vert[0], plane.normal);
3325 PlaneClassify(&plane);
3326 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3328 // skip backfaces (except if nocullface is set)
3329 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3331 VectorNegate(plane.normal, plane.normal);
3333 PlaneClassify(&plane);
3337 // find a matching plane if there is one
3338 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3339 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3341 if (planeindex >= r_waterstate.maxwaterplanes)
3342 return; // nothing we can do, out of planes
3344 // if this triangle does not fit any known plane rendered this frame, add one
3345 if (planeindex >= r_waterstate.numwaterplanes)
3347 // store the new plane
3348 r_waterstate.numwaterplanes++;
3350 // clear materialflags and pvs
3351 p->materialflags = 0;
3352 p->pvsvalid = false;
3354 // merge this surface's materialflags into the waterplane
3355 p->materialflags |= t->currentmaterialflags;
3356 // merge this surface's PVS into the waterplane
3357 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3358 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3359 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3361 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3366 static void R_Water_ProcessPlanes(void)
3368 r_refdef_view_t originalview;
3369 r_refdef_view_t myview;
3371 r_waterstate_waterplane_t *p;
3373 originalview = r_refdef.view;
3375 // make sure enough textures are allocated
3376 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3378 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3380 if (!p->texture_refraction)
3381 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);
3382 if (!p->texture_refraction)
3386 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3388 if (!p->texture_reflection)
3389 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);
3390 if (!p->texture_reflection)
3396 r_refdef.view = originalview;
3397 r_refdef.view.showdebug = false;
3398 r_refdef.view.width = r_waterstate.waterwidth;
3399 r_refdef.view.height = r_waterstate.waterheight;
3400 r_refdef.view.useclipplane = true;
3401 myview = r_refdef.view;
3402 r_waterstate.renderingscene = true;
3403 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3405 // render the normal view scene and copy into texture
3406 // (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)
3407 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3409 r_refdef.view = myview;
3410 r_refdef.view.clipplane = p->plane;
3411 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3412 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3413 PlaneClassify(&r_refdef.view.clipplane);
3415 R_ResetViewRendering3D();
3416 R_ClearScreen(r_refdef.fogenabled);
3420 // copy view into the screen texture
3421 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3422 GL_ActiveTexture(0);
3424 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
3427 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3429 r_refdef.view = myview;
3430 // render reflected scene and copy into texture
3431 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3432 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3433 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3434 r_refdef.view.clipplane = p->plane;
3435 // reverse the cullface settings for this render
3436 r_refdef.view.cullface_front = GL_FRONT;
3437 r_refdef.view.cullface_back = GL_BACK;
3438 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3440 r_refdef.view.usecustompvs = true;
3442 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3444 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3447 R_ResetViewRendering3D();
3448 R_ClearScreen(r_refdef.fogenabled);
3452 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3453 GL_ActiveTexture(0);
3455 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
3458 r_waterstate.renderingscene = false;
3459 r_refdef.view = originalview;
3460 R_ResetViewRendering3D();
3461 R_ClearScreen(r_refdef.fogenabled);
3465 r_refdef.view = originalview;
3466 r_waterstate.renderingscene = false;
3467 Cvar_SetValueQuick(&r_water, 0);
3468 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3472 void R_Bloom_StartFrame(void)
3474 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3476 // set bloomwidth and bloomheight to the bloom resolution that will be
3477 // used (often less than the screen resolution for faster rendering)
3478 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3479 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3480 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3481 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3482 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3484 // calculate desired texture sizes
3485 if (gl_support_arb_texture_non_power_of_two)
3487 screentexturewidth = r_refdef.view.width;
3488 screentextureheight = r_refdef.view.height;
3489 bloomtexturewidth = r_bloomstate.bloomwidth;
3490 bloomtextureheight = r_bloomstate.bloomheight;
3494 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3495 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3496 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3497 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3500 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((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))
3502 Cvar_SetValueQuick(&r_hdr, 0);
3503 Cvar_SetValueQuick(&r_bloom, 0);
3504 Cvar_SetValueQuick(&r_motionblur, 0);
3505 Cvar_SetValueQuick(&r_damageblur, 0);
3508 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
3509 screentexturewidth = screentextureheight = 0;
3510 if (!r_hdr.integer && !r_bloom.integer)
3511 bloomtexturewidth = bloomtextureheight = 0;
3513 // allocate textures as needed
3514 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3516 if (r_bloomstate.texture_screen)
3517 R_FreeTexture(r_bloomstate.texture_screen);
3518 r_bloomstate.texture_screen = NULL;
3519 r_bloomstate.screentexturewidth = screentexturewidth;
3520 r_bloomstate.screentextureheight = screentextureheight;
3521 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3522 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);
3524 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3526 if (r_bloomstate.texture_bloom)
3527 R_FreeTexture(r_bloomstate.texture_bloom);
3528 r_bloomstate.texture_bloom = NULL;
3529 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3530 r_bloomstate.bloomtextureheight = bloomtextureheight;
3531 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3532 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);
3535 // set up a texcoord array for the full resolution screen image
3536 // (we have to keep this around to copy back during final render)
3537 r_bloomstate.screentexcoord2f[0] = 0;
3538 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3539 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3540 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3541 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3542 r_bloomstate.screentexcoord2f[5] = 0;
3543 r_bloomstate.screentexcoord2f[6] = 0;
3544 r_bloomstate.screentexcoord2f[7] = 0;
3546 // set up a texcoord array for the reduced resolution bloom image
3547 // (which will be additive blended over the screen image)
3548 r_bloomstate.bloomtexcoord2f[0] = 0;
3549 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3550 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3551 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3552 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3553 r_bloomstate.bloomtexcoord2f[5] = 0;
3554 r_bloomstate.bloomtexcoord2f[6] = 0;
3555 r_bloomstate.bloomtexcoord2f[7] = 0;
3557 if (r_hdr.integer || r_bloom.integer)
3559 r_bloomstate.enabled = true;
3560 r_bloomstate.hdr = r_hdr.integer != 0;
3564 void R_Bloom_CopyBloomTexture(float colorscale)
3566 r_refdef.stats.bloom++;
3568 // scale down screen texture to the bloom texture size
3570 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3571 GL_BlendFunc(GL_ONE, GL_ZERO);
3572 GL_Color(colorscale, colorscale, colorscale, 1);
3573 // TODO: optimize with multitexture or GLSL
3574 R_SetupGenericShader(true);
3575 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3576 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3577 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3578 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3580 // we now have a bloom image in the framebuffer
3581 // copy it into the bloom image texture for later processing
3582 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3583 GL_ActiveTexture(0);
3585 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
3586 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3589 void R_Bloom_CopyHDRTexture(void)
3591 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3592 GL_ActiveTexture(0);
3594 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
3595 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3598 void R_Bloom_MakeTexture(void)
3601 float xoffset, yoffset, r, brighten;
3603 r_refdef.stats.bloom++;
3605 R_ResetViewRendering2D();
3606 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3607 R_Mesh_ColorPointer(NULL, 0, 0);
3608 R_SetupGenericShader(true);
3610 // we have a bloom image in the framebuffer
3612 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3614 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3617 r = bound(0, r_bloom_colorexponent.value / x, 1);
3618 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3619 GL_Color(r, r, r, 1);
3620 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3621 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3622 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3623 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3625 // copy the vertically blurred bloom view to a texture
3626 GL_ActiveTexture(0);
3628 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
3629 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3632 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3633 brighten = r_bloom_brighten.value;
3635 brighten *= r_hdr_range.value;
3636 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3637 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3639 for (dir = 0;dir < 2;dir++)
3641 // blend on at multiple vertical offsets to achieve a vertical blur
3642 // TODO: do offset blends using GLSL
3643 GL_BlendFunc(GL_ONE, GL_ZERO);
3644 for (x = -range;x <= range;x++)
3646 if (!dir){xoffset = 0;yoffset = x;}
3647 else {xoffset = x;yoffset = 0;}
3648 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3649 yoffset /= (float)r_bloomstate.bloomtextureheight;
3650 // compute a texcoord array with the specified x and y offset
3651 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3652 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3653 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3654 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3655 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3656 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3657 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3658 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3659 // this r value looks like a 'dot' particle, fading sharply to
3660 // black at the edges
3661 // (probably not realistic but looks good enough)
3662 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3663 //r = (dir ? 1.0f : brighten)/(range*2+1);
3664 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3665 GL_Color(r, r, r, 1);
3666 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3667 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3668 GL_BlendFunc(GL_ONE, GL_ONE);
3671 // copy the vertically blurred bloom view to a texture
3672 GL_ActiveTexture(0);
3674 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
3675 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3678 // apply subtract last
3679 // (just like it would be in a GLSL shader)
3680 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3682 GL_BlendFunc(GL_ONE, GL_ZERO);
3683 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3684 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3685 GL_Color(1, 1, 1, 1);
3686 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3687 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3689 GL_BlendFunc(GL_ONE, GL_ONE);
3690 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3691 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3692 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3693 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3694 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3695 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3696 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3698 // copy the darkened bloom view to a texture
3699 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3700 GL_ActiveTexture(0);
3702 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
3703 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3707 void R_HDR_RenderBloomTexture(void)
3709 int oldwidth, oldheight;
3710 float oldcolorscale;
3712 oldcolorscale = r_refdef.view.colorscale;
3713 oldwidth = r_refdef.view.width;
3714 oldheight = r_refdef.view.height;
3715 r_refdef.view.width = r_bloomstate.bloomwidth;
3716 r_refdef.view.height = r_bloomstate.bloomheight;
3718 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3719 // TODO: add exposure compensation features
3720 // TODO: add fp16 framebuffer support
3722 r_refdef.view.showdebug = false;
3723 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3725 R_ResetViewRendering3D();
3727 R_ClearScreen(r_refdef.fogenabled);
3728 if (r_timereport_active)
3729 R_TimeReport("HDRclear");
3732 if (r_timereport_active)
3733 R_TimeReport("visibility");
3735 r_waterstate.numwaterplanes = 0;
3736 if (r_waterstate.enabled)
3737 R_RenderWaterPlanes();
3739 r_refdef.view.showdebug = true;
3741 r_waterstate.numwaterplanes = 0;
3743 R_ResetViewRendering2D();
3745 R_Bloom_CopyHDRTexture();
3746 R_Bloom_MakeTexture();
3748 // restore the view settings
3749 r_refdef.view.width = oldwidth;
3750 r_refdef.view.height = oldheight;
3751 r_refdef.view.colorscale = oldcolorscale;
3753 R_ResetViewRendering3D();
3755 R_ClearScreen(r_refdef.fogenabled);
3756 if (r_timereport_active)
3757 R_TimeReport("viewclear");
3760 static void R_BlendView(void)
3762 if (r_bloomstate.texture_screen)
3764 // make sure the buffer is available
3765 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
3767 R_ResetViewRendering2D();
3768 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3769 R_Mesh_ColorPointer(NULL, 0, 0);
3770 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3771 GL_ActiveTexture(0);CHECKGLERROR
3773 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
3775 // declare alpha variable
3778 static float avgspeed;
3780 speed = VectorLength(cl.movement_velocity);
3782 a = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
3783 avgspeed = avgspeed * (1 - a) + speed * a;
3785 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
3786 speed = bound(0, speed, 1);
3787 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
3789 // calculate values into a standard alpha
3792 (r_motionblur.value * speed / 80)
3794 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
3797 max(0.0001, cl.time - cl.oldtime) // fps independent
3800 a *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
3801 a = bound(0, a, r_motionblur_maxblur.value);
3803 // developer debug of current value
3804 if (r_motionblur_debug.value) { Con_Printf("blur alpha = %f\n", a); }
3809 R_SetupGenericShader(true);
3810 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3811 GL_Color(1, 1, 1, a); // to do: add color changing support for damage blur
3812 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3813 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3814 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3815 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3819 // copy view into the screen texture
3820 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
3821 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3824 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3826 unsigned int permutation =
3827 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3828 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3829 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3830 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
3831 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
3833 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3835 // render simple bloom effect
3836 // copy the screen and shrink it and darken it for the bloom process
3837 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3838 // make the bloom texture
3839 R_Bloom_MakeTexture();
3842 R_ResetViewRendering2D();
3843 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3844 R_Mesh_ColorPointer(NULL, 0, 0);
3845 GL_Color(1, 1, 1, 1);
3846 GL_BlendFunc(GL_ONE, GL_ZERO);
3847 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3848 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3849 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3850 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3851 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3852 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3853 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3854 if (r_glsl_permutation->loc_TintColor >= 0)
3855 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3856 if (r_glsl_permutation->loc_ClientTime >= 0)
3857 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3858 if (r_glsl_permutation->loc_PixelSize >= 0)
3859 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3860 if (r_glsl_permutation->loc_UserVec1 >= 0)
3862 float a=0, b=0, c=0, d=0;
3863 #if _MSC_VER >= 1400
3864 #define sscanf sscanf_s
3866 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3867 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3869 if (r_glsl_permutation->loc_UserVec2 >= 0)
3871 float a=0, b=0, c=0, d=0;
3872 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3873 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3875 if (r_glsl_permutation->loc_UserVec3 >= 0)
3877 float a=0, b=0, c=0, d=0;
3878 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3879 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3881 if (r_glsl_permutation->loc_UserVec4 >= 0)
3883 float a=0, b=0, c=0, d=0;
3884 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3885 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3887 if (r_glsl_permutation->loc_Saturation >= 0)
3888 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
3889 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3890 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3896 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3898 // render high dynamic range bloom effect
3899 // the bloom texture was made earlier this render, so we just need to
3900 // blend it onto the screen...
3901 R_ResetViewRendering2D();
3902 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3903 R_Mesh_ColorPointer(NULL, 0, 0);
3904 R_SetupGenericShader(true);
3905 GL_Color(1, 1, 1, 1);
3906 GL_BlendFunc(GL_ONE, GL_ONE);
3907 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3908 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3909 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3910 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3912 else if (r_bloomstate.texture_bloom)
3914 // render simple bloom effect
3915 // copy the screen and shrink it and darken it for the bloom process
3916 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3917 // make the bloom texture
3918 R_Bloom_MakeTexture();
3919 // put the original screen image back in place and blend the bloom
3921 R_ResetViewRendering2D();
3922 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3923 R_Mesh_ColorPointer(NULL, 0, 0);
3924 GL_Color(1, 1, 1, 1);
3925 GL_BlendFunc(GL_ONE, GL_ZERO);
3926 // do both in one pass if possible
3927 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3928 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3929 if (r_textureunits.integer >= 2 && gl_combine.integer)
3931 R_SetupGenericTwoTextureShader(GL_ADD);
3932 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3933 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3937 R_SetupGenericShader(true);
3938 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3939 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3940 // now blend on the bloom texture
3941 GL_BlendFunc(GL_ONE, GL_ONE);
3942 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3943 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3945 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3946 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3948 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3950 // apply a color tint to the whole view
3951 R_ResetViewRendering2D();
3952 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3953 R_Mesh_ColorPointer(NULL, 0, 0);
3954 R_SetupGenericShader(false);
3955 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3956 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3957 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3961 matrix4x4_t r_waterscrollmatrix;
3963 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3965 if (r_refdef.fog_density)
3967 r_refdef.fogcolor[0] = r_refdef.fog_red;
3968 r_refdef.fogcolor[1] = r_refdef.fog_green;
3969 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3973 VectorCopy(r_refdef.fogcolor, fogvec);
3974 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3976 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3977 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3978 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3979 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3981 // color.rgb *= ContrastBoost * SceneBrightness;
3982 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3983 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3984 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3985 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3990 void R_UpdateVariables(void)
3994 r_refdef.scene.ambient = r_ambient.value;
3996 r_refdef.farclip = 4096;
3997 if (r_refdef.scene.worldmodel)
3998 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3999 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4001 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4002 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4003 r_refdef.polygonfactor = 0;
4004 r_refdef.polygonoffset = 0;
4005 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4006 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4008 r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
4009 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4010 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4011 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4012 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4013 if (r_showsurfaces.integer)
4015 r_refdef.scene.rtworld = false;
4016 r_refdef.scene.rtworldshadows = false;
4017 r_refdef.scene.rtdlight = false;
4018 r_refdef.scene.rtdlightshadows = false;
4019 r_refdef.lightmapintensity = 0;
4022 if (gamemode == GAME_NEHAHRA)
4024 if (gl_fogenable.integer)
4026 r_refdef.oldgl_fogenable = true;
4027 r_refdef.fog_density = gl_fogdensity.value;
4028 r_refdef.fog_red = gl_fogred.value;
4029 r_refdef.fog_green = gl_foggreen.value;
4030 r_refdef.fog_blue = gl_fogblue.value;
4031 r_refdef.fog_alpha = 1;
4032 r_refdef.fog_start = 0;
4033 r_refdef.fog_end = gl_skyclip.value;
4035 else if (r_refdef.oldgl_fogenable)
4037 r_refdef.oldgl_fogenable = false;
4038 r_refdef.fog_density = 0;
4039 r_refdef.fog_red = 0;
4040 r_refdef.fog_green = 0;
4041 r_refdef.fog_blue = 0;
4042 r_refdef.fog_alpha = 0;
4043 r_refdef.fog_start = 0;
4044 r_refdef.fog_end = 0;
4048 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4049 r_refdef.fog_start = max(0, r_refdef.fog_start);
4050 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4052 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4054 if (r_refdef.fog_density && r_drawfog.integer)
4056 r_refdef.fogenabled = true;
4057 // this is the point where the fog reaches 0.9986 alpha, which we
4058 // consider a good enough cutoff point for the texture
4059 // (0.9986 * 256 == 255.6)
4060 if (r_fog_exp2.integer)
4061 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4063 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4064 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4065 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4066 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4067 // fog color was already set
4068 // update the fog texture
4069 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)
4070 R_BuildFogTexture();
4073 r_refdef.fogenabled = false;
4075 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4077 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4079 // build GLSL gamma texture
4080 #define RAMPWIDTH 256
4081 unsigned short ramp[RAMPWIDTH * 3];
4082 unsigned char rampbgr[RAMPWIDTH][4];
4085 r_texture_gammaramps_serial = vid_gammatables_serial;
4087 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4088 for(i = 0; i < RAMPWIDTH; ++i)
4090 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4091 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4092 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4095 if (r_texture_gammaramps)
4097 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4101 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);
4107 // remove GLSL gamma texture
4111 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4112 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4118 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4119 if( scenetype != r_currentscenetype ) {
4120 // store the old scenetype
4121 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4122 r_currentscenetype = scenetype;
4123 // move in the new scene
4124 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4133 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4135 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4136 if( scenetype == r_currentscenetype ) {
4137 return &r_refdef.scene;
4139 return &r_scenes_store[ scenetype ];
4148 void R_RenderView(void)
4150 r_frame++; // used only by R_GetCurrentTexture
4151 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4153 R_AnimCache_NewFrame();
4155 if (r_refdef.view.isoverlay)
4157 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4158 GL_Clear( GL_DEPTH_BUFFER_BIT );
4159 R_TimeReport("depthclear");
4161 r_refdef.view.showdebug = false;
4163 r_waterstate.enabled = false;
4164 r_waterstate.numwaterplanes = 0;
4172 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4173 return; //Host_Error ("R_RenderView: NULL worldmodel");
4175 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4177 // break apart the view matrix into vectors for various purposes
4178 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4179 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4180 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4181 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4182 // make an inverted copy of the view matrix for tracking sprites
4183 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4185 R_Shadow_UpdateWorldLightSelection();
4187 R_Bloom_StartFrame();
4188 R_Water_StartFrame();
4191 if (r_timereport_active)
4192 R_TimeReport("viewsetup");
4194 R_ResetViewRendering3D();
4196 if (r_refdef.view.clear || r_refdef.fogenabled)
4198 R_ClearScreen(r_refdef.fogenabled);
4199 if (r_timereport_active)
4200 R_TimeReport("viewclear");
4202 r_refdef.view.clear = true;
4204 // this produces a bloom texture to be used in R_BlendView() later
4206 R_HDR_RenderBloomTexture();
4208 r_refdef.view.showdebug = true;
4211 if (r_timereport_active)
4212 R_TimeReport("visibility");
4214 r_waterstate.numwaterplanes = 0;
4215 if (r_waterstate.enabled)
4216 R_RenderWaterPlanes();
4219 r_waterstate.numwaterplanes = 0;
4222 if (r_timereport_active)
4223 R_TimeReport("blendview");
4225 GL_Scissor(0, 0, vid.width, vid.height);
4226 GL_ScissorTest(false);
4230 void R_RenderWaterPlanes(void)
4232 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4234 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4235 if (r_timereport_active)
4236 R_TimeReport("waterworld");
4239 // don't let sound skip if going slow
4240 if (r_refdef.scene.extraupdate)
4243 R_DrawModelsAddWaterPlanes();
4244 if (r_timereport_active)
4245 R_TimeReport("watermodels");
4247 if (r_waterstate.numwaterplanes)
4249 R_Water_ProcessPlanes();
4250 if (r_timereport_active)
4251 R_TimeReport("waterscenes");
4255 extern void R_DrawLightningBeams (void);
4256 extern void VM_CL_AddPolygonsToMeshQueue (void);
4257 extern void R_DrawPortals (void);
4258 extern cvar_t cl_locs_show;
4259 static void R_DrawLocs(void);
4260 static void R_DrawEntityBBoxes(void);
4261 void R_RenderScene(void)
4263 r_refdef.stats.renders++;
4267 // don't let sound skip if going slow
4268 if (r_refdef.scene.extraupdate)
4271 R_MeshQueue_BeginScene();
4275 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);
4277 if (cl.csqc_vidvars.drawworld)
4279 // don't let sound skip if going slow
4280 if (r_refdef.scene.extraupdate)
4283 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4285 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4286 if (r_timereport_active)
4287 R_TimeReport("worldsky");
4290 if (R_DrawBrushModelsSky() && r_timereport_active)
4291 R_TimeReport("bmodelsky");
4294 R_AnimCache_CacheVisibleEntities();
4296 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4298 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4299 if (r_timereport_active)
4300 R_TimeReport("worlddepth");
4302 if (r_depthfirst.integer >= 2)
4304 R_DrawModelsDepth();
4305 if (r_timereport_active)
4306 R_TimeReport("modeldepth");
4309 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4311 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4312 if (r_timereport_active)
4313 R_TimeReport("world");
4316 // don't let sound skip if going slow
4317 if (r_refdef.scene.extraupdate)
4321 if (r_timereport_active)
4322 R_TimeReport("models");
4324 // don't let sound skip if going slow
4325 if (r_refdef.scene.extraupdate)
4328 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
4330 R_DrawModelShadows();
4332 R_ResetViewRendering3D();
4334 // don't let sound skip if going slow
4335 if (r_refdef.scene.extraupdate)
4339 R_ShadowVolumeLighting(false);
4340 if (r_timereport_active)
4341 R_TimeReport("rtlights");
4343 // don't let sound skip if going slow
4344 if (r_refdef.scene.extraupdate)
4347 if (cl.csqc_vidvars.drawworld)
4349 R_DrawLightningBeams();
4350 if (r_timereport_active)
4351 R_TimeReport("lightning");
4354 if (r_timereport_active)
4355 R_TimeReport("decals");
4358 if (r_timereport_active)
4359 R_TimeReport("particles");
4362 if (r_timereport_active)
4363 R_TimeReport("explosions");
4366 R_SetupGenericShader(true);
4367 VM_CL_AddPolygonsToMeshQueue();
4369 if (r_refdef.view.showdebug)
4371 if (cl_locs_show.integer)
4374 if (r_timereport_active)
4375 R_TimeReport("showlocs");
4378 if (r_drawportals.integer)
4381 if (r_timereport_active)
4382 R_TimeReport("portals");
4385 if (r_showbboxes.value > 0)
4387 R_DrawEntityBBoxes();
4388 if (r_timereport_active)
4389 R_TimeReport("bboxes");
4393 R_SetupGenericShader(true);
4394 R_MeshQueue_RenderTransparent();
4395 if (r_timereport_active)
4396 R_TimeReport("drawtrans");
4398 R_SetupGenericShader(true);
4400 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))
4402 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4403 if (r_timereport_active)
4404 R_TimeReport("worlddebug");
4405 R_DrawModelsDebug();
4406 if (r_timereport_active)
4407 R_TimeReport("modeldebug");
4410 R_SetupGenericShader(true);
4412 if (cl.csqc_vidvars.drawworld)
4415 if (r_timereport_active)
4416 R_TimeReport("coronas");
4419 // don't let sound skip if going slow
4420 if (r_refdef.scene.extraupdate)
4423 R_ResetViewRendering2D();
4426 static const unsigned short bboxelements[36] =
4436 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4439 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4440 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4441 GL_DepthMask(false);
4442 GL_DepthRange(0, 1);
4443 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4444 R_Mesh_Matrix(&identitymatrix);
4445 R_Mesh_ResetTextureState();
4447 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4448 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4449 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4450 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4451 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4452 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4453 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4454 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4455 R_FillColors(color4f, 8, cr, cg, cb, ca);
4456 if (r_refdef.fogenabled)
4458 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4460 f1 = FogPoint_World(v);
4462 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4463 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4464 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4467 R_Mesh_VertexPointer(vertex3f, 0, 0);
4468 R_Mesh_ColorPointer(color4f, 0, 0);
4469 R_Mesh_ResetTextureState();
4470 R_SetupGenericShader(false);
4471 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4474 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4478 prvm_edict_t *edict;
4479 prvm_prog_t *prog_save = prog;
4481 // this function draws bounding boxes of server entities
4485 GL_CullFace(GL_NONE);
4486 R_SetupGenericShader(false);
4490 for (i = 0;i < numsurfaces;i++)
4492 edict = PRVM_EDICT_NUM(surfacelist[i]);
4493 switch ((int)edict->fields.server->solid)
4495 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4496 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4497 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4498 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4499 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4500 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4502 color[3] *= r_showbboxes.value;
4503 color[3] = bound(0, color[3], 1);
4504 GL_DepthTest(!r_showdisabledepthtest.integer);
4505 GL_CullFace(r_refdef.view.cullface_front);
4506 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4512 static void R_DrawEntityBBoxes(void)
4515 prvm_edict_t *edict;
4517 prvm_prog_t *prog_save = prog;
4519 // this function draws bounding boxes of server entities
4525 for (i = 0;i < prog->num_edicts;i++)
4527 edict = PRVM_EDICT_NUM(i);
4528 if (edict->priv.server->free)
4530 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4531 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4533 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4535 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4536 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4542 unsigned short nomodelelements[24] =
4554 float nomodelvertex3f[6*3] =
4564 float nomodelcolor4f[6*4] =
4566 0.0f, 0.0f, 0.5f, 1.0f,
4567 0.0f, 0.0f, 0.5f, 1.0f,
4568 0.0f, 0.5f, 0.0f, 1.0f,
4569 0.0f, 0.5f, 0.0f, 1.0f,
4570 0.5f, 0.0f, 0.0f, 1.0f,
4571 0.5f, 0.0f, 0.0f, 1.0f
4574 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4579 // this is only called once per entity so numsurfaces is always 1, and
4580 // surfacelist is always {0}, so this code does not handle batches
4581 R_Mesh_Matrix(&ent->matrix);
4583 if (ent->flags & EF_ADDITIVE)
4585 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4586 GL_DepthMask(false);
4588 else if (ent->alpha < 1)
4590 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4591 GL_DepthMask(false);
4595 GL_BlendFunc(GL_ONE, GL_ZERO);
4598 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4599 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4600 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4601 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4602 R_SetupGenericShader(false);
4603 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4604 if (r_refdef.fogenabled)
4607 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4608 R_Mesh_ColorPointer(color4f, 0, 0);
4609 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4610 f1 = FogPoint_World(org);
4612 for (i = 0, c = color4f;i < 6;i++, c += 4)
4614 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4615 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4616 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4620 else if (ent->alpha != 1)
4622 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4623 R_Mesh_ColorPointer(color4f, 0, 0);
4624 for (i = 0, c = color4f;i < 6;i++, c += 4)
4628 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4629 R_Mesh_ResetTextureState();
4630 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4633 void R_DrawNoModel(entity_render_t *ent)
4636 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4637 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4638 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4640 // R_DrawNoModelCallback(ent, 0);
4643 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4645 vec3_t right1, right2, diff, normal;
4647 VectorSubtract (org2, org1, normal);
4649 // calculate 'right' vector for start
4650 VectorSubtract (r_refdef.view.origin, org1, diff);
4651 CrossProduct (normal, diff, right1);
4652 VectorNormalize (right1);
4654 // calculate 'right' vector for end
4655 VectorSubtract (r_refdef.view.origin, org2, diff);
4656 CrossProduct (normal, diff, right2);
4657 VectorNormalize (right2);
4659 vert[ 0] = org1[0] + width * right1[0];
4660 vert[ 1] = org1[1] + width * right1[1];
4661 vert[ 2] = org1[2] + width * right1[2];
4662 vert[ 3] = org1[0] - width * right1[0];
4663 vert[ 4] = org1[1] - width * right1[1];
4664 vert[ 5] = org1[2] - width * right1[2];
4665 vert[ 6] = org2[0] - width * right2[0];
4666 vert[ 7] = org2[1] - width * right2[1];
4667 vert[ 8] = org2[2] - width * right2[2];
4668 vert[ 9] = org2[0] + width * right2[0];
4669 vert[10] = org2[1] + width * right2[1];
4670 vert[11] = org2[2] + width * right2[2];
4673 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4675 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)
4677 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4681 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4682 fog = FogPoint_World(origin);
4684 R_Mesh_Matrix(&identitymatrix);
4685 GL_BlendFunc(blendfunc1, blendfunc2);
4687 GL_CullFace(GL_NONE);
4689 GL_DepthMask(false);
4690 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4691 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4692 GL_DepthTest(!depthdisable);
4694 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4695 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4696 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4697 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4698 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4699 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4700 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4701 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4702 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4703 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4704 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4705 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4707 R_Mesh_VertexPointer(vertex3f, 0, 0);
4708 R_Mesh_ColorPointer(NULL, 0, 0);
4709 R_Mesh_ResetTextureState();
4710 R_SetupGenericShader(true);
4711 R_Mesh_TexBind(0, R_GetTexture(texture));
4712 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4713 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4714 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4715 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4717 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4719 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4720 GL_BlendFunc(blendfunc1, GL_ONE);
4722 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4723 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4727 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4732 VectorSet(v, x, y, z);
4733 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4734 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4736 if (i == mesh->numvertices)
4738 if (mesh->numvertices < mesh->maxvertices)
4740 VectorCopy(v, vertex3f);
4741 mesh->numvertices++;
4743 return mesh->numvertices;
4749 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4753 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4754 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4755 e = mesh->element3i + mesh->numtriangles * 3;
4756 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4758 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4759 if (mesh->numtriangles < mesh->maxtriangles)
4764 mesh->numtriangles++;
4766 element[1] = element[2];
4770 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4774 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4775 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4776 e = mesh->element3i + mesh->numtriangles * 3;
4777 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4779 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4780 if (mesh->numtriangles < mesh->maxtriangles)
4785 mesh->numtriangles++;
4787 element[1] = element[2];
4791 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4792 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4794 int planenum, planenum2;
4797 mplane_t *plane, *plane2;
4799 double temppoints[2][256*3];
4800 // figure out how large a bounding box we need to properly compute this brush
4802 for (w = 0;w < numplanes;w++)
4803 maxdist = max(maxdist, planes[w].dist);
4804 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4805 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4806 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4810 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4811 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4813 if (planenum2 == planenum)
4815 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);
4818 if (tempnumpoints < 3)
4820 // generate elements forming a triangle fan for this polygon
4821 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4825 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)
4827 texturelayer_t *layer;
4828 layer = t->currentlayers + t->currentnumlayers++;
4830 layer->depthmask = depthmask;
4831 layer->blendfunc1 = blendfunc1;
4832 layer->blendfunc2 = blendfunc2;
4833 layer->texture = texture;
4834 layer->texmatrix = *matrix;
4835 layer->color[0] = r * r_refdef.view.colorscale;
4836 layer->color[1] = g * r_refdef.view.colorscale;
4837 layer->color[2] = b * r_refdef.view.colorscale;
4838 layer->color[3] = a;
4841 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4844 index = parms[2] + r_refdef.scene.time * parms[3];
4845 index -= floor(index);
4849 case Q3WAVEFUNC_NONE:
4850 case Q3WAVEFUNC_NOISE:
4851 case Q3WAVEFUNC_COUNT:
4854 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4855 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4856 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4857 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4858 case Q3WAVEFUNC_TRIANGLE:
4860 f = index - floor(index);
4871 return (float)(parms[0] + parms[1] * f);
4874 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
4879 matrix4x4_t matrix, temp;
4880 switch(tcmod->tcmod)
4884 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4885 matrix = r_waterscrollmatrix;
4887 matrix = identitymatrix;
4889 case Q3TCMOD_ENTITYTRANSLATE:
4890 // this is used in Q3 to allow the gamecode to control texcoord
4891 // scrolling on the entity, which is not supported in darkplaces yet.
4892 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4894 case Q3TCMOD_ROTATE:
4895 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4896 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4897 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4900 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4902 case Q3TCMOD_SCROLL:
4903 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4905 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4906 w = (int) tcmod->parms[0];
4907 h = (int) tcmod->parms[1];
4908 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4910 idx = (int) floor(f * w * h);
4911 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4913 case Q3TCMOD_STRETCH:
4914 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4915 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4917 case Q3TCMOD_TRANSFORM:
4918 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4919 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4920 VectorSet(tcmat + 6, 0 , 0 , 1);
4921 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4922 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4924 case Q3TCMOD_TURBULENT:
4925 // this is handled in the RSurf_PrepareVertices function
4926 matrix = identitymatrix;
4930 Matrix4x4_Concat(texmatrix, &matrix, &temp);
4933 texture_t *R_GetCurrentTexture(texture_t *t)
4936 const entity_render_t *ent = rsurface.entity;
4937 dp_model_t *model = ent->model;
4938 q3shaderinfo_layer_tcmod_t *tcmod;
4940 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
4941 return t->currentframe;
4942 t->update_lastrenderframe = r_frame;
4943 t->update_lastrenderentity = (void *)ent;
4945 // switch to an alternate material if this is a q1bsp animated material
4947 texture_t *texture = t;
4948 int s = ent->skinnum;
4949 if ((unsigned int)s >= (unsigned int)model->numskins)
4951 if (model->skinscenes)
4953 if (model->skinscenes[s].framecount > 1)
4954 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4956 s = model->skinscenes[s].firstframe;
4959 t = t + s * model->num_surfaces;
4962 // use an alternate animation if the entity's frame is not 0,
4963 // and only if the texture has an alternate animation
4964 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
4965 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4967 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4969 texture->currentframe = t;
4972 // update currentskinframe to be a qw skin or animation frame
4973 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"))
4975 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4977 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4978 if (developer_loading.integer)
4979 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4980 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);
4982 t->currentskinframe = r_qwskincache_skinframe[i];
4983 if (t->currentskinframe == NULL)
4984 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4986 else if (t->numskinframes >= 2)
4987 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4988 if (t->backgroundnumskinframes >= 2)
4989 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
4991 t->currentmaterialflags = t->basematerialflags;
4992 t->currentalpha = ent->alpha;
4993 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4994 t->currentalpha *= r_wateralpha.value;
4995 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4996 t->currentalpha *= t->r_water_wateralpha;
4997 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4998 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4999 if (!(ent->flags & RENDER_LIGHT))
5000 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5001 else if (rsurface.modeltexcoordlightmap2f == NULL)
5003 // pick a model lighting mode
5004 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5005 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5007 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5009 if (ent->effects & EF_ADDITIVE)
5010 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5011 else if (t->currentalpha < 1)
5012 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5013 if (ent->effects & EF_DOUBLESIDED)
5014 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5015 if (ent->effects & EF_NODEPTHTEST)
5016 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5017 if (ent->flags & RENDER_VIEWMODEL)
5018 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5019 if (t->backgroundnumskinframes)
5020 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5021 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5023 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5024 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5027 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5029 // there is no tcmod
5030 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5032 t->currenttexmatrix = r_waterscrollmatrix;
5033 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5037 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5038 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5041 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5042 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5043 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5044 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5046 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5047 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5048 t->glosstexture = r_texture_black;
5049 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5050 t->backgroundglosstexture = r_texture_black;
5051 t->specularpower = r_shadow_glossexponent.value;
5052 // TODO: store reference values for these in the texture?
5053 t->specularscale = 0;
5054 if (r_shadow_gloss.integer > 0)
5056 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5058 if (r_shadow_glossintensity.value > 0)
5060 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5061 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5062 t->specularscale = r_shadow_glossintensity.value;
5065 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5067 t->glosstexture = r_texture_white;
5068 t->backgroundglosstexture = r_texture_white;
5069 t->specularscale = r_shadow_gloss2intensity.value;
5073 // lightmaps mode looks bad with dlights using actual texturing, so turn
5074 // off the colormap and glossmap, but leave the normalmap on as it still
5075 // accurately represents the shading involved
5076 if (gl_lightmaps.integer)
5078 t->basetexture = r_texture_grey128;
5079 t->backgroundbasetexture = NULL;
5080 t->specularscale = 0;
5081 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5084 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5085 VectorClear(t->dlightcolor);
5086 t->currentnumlayers = 0;
5087 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5090 int blendfunc1, blendfunc2, depthmask;
5091 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5093 blendfunc1 = GL_SRC_ALPHA;
5094 blendfunc2 = GL_ONE;
5096 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5098 blendfunc1 = GL_SRC_ALPHA;
5099 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5101 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5103 blendfunc1 = t->customblendfunc[0];
5104 blendfunc2 = t->customblendfunc[1];
5108 blendfunc1 = GL_ONE;
5109 blendfunc2 = GL_ZERO;
5111 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5112 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5113 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5114 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5116 // fullbright is not affected by r_refdef.lightmapintensity
5117 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]);
5118 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5119 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]);
5120 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5121 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]);
5125 vec3_t ambientcolor;
5127 // set the color tint used for lights affecting this surface
5128 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5130 // q3bsp has no lightmap updates, so the lightstylevalue that
5131 // would normally be baked into the lightmap must be
5132 // applied to the color
5133 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5134 if (ent->model->type == mod_brushq3)
5135 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5136 colorscale *= r_refdef.lightmapintensity;
5137 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5138 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5139 // basic lit geometry
5140 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]);
5141 // add pants/shirt if needed
5142 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5143 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]);
5144 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5145 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]);
5146 // now add ambient passes if needed
5147 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5149 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]);
5150 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5151 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]);
5152 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5153 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]);
5156 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5157 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]);
5158 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5160 // if this is opaque use alpha blend which will darken the earlier
5163 // if this is an alpha blended material, all the earlier passes
5164 // were darkened by fog already, so we only need to add the fog
5165 // color ontop through the fog mask texture
5167 // if this is an additive blended material, all the earlier passes
5168 // were darkened by fog already, and we should not add fog color
5169 // (because the background was not darkened, there is no fog color
5170 // that was lost behind it).
5171 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]);
5175 return t->currentframe;
5178 rsurfacestate_t rsurface;
5180 void R_Mesh_ResizeArrays(int newvertices)
5183 if (rsurface.array_size >= newvertices)
5185 if (rsurface.array_modelvertex3f)
5186 Mem_Free(rsurface.array_modelvertex3f);
5187 rsurface.array_size = (newvertices + 1023) & ~1023;
5188 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5189 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5190 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5191 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5192 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5193 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5194 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5195 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5196 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5197 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5198 rsurface.array_color4f = base + rsurface.array_size * 27;
5199 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5202 void RSurf_ActiveWorldEntity(void)
5204 dp_model_t *model = r_refdef.scene.worldmodel;
5205 //if (rsurface.entity == r_refdef.scene.worldentity)
5207 rsurface.entity = r_refdef.scene.worldentity;
5208 if (rsurface.array_size < model->surfmesh.num_vertices)
5209 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5210 rsurface.matrix = identitymatrix;
5211 rsurface.inversematrix = identitymatrix;
5212 R_Mesh_Matrix(&identitymatrix);
5213 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5214 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5215 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5216 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5217 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5218 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5219 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5220 rsurface.frameblend[0].lerp = 1;
5221 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5222 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5223 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5224 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5225 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5226 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5227 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5228 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5229 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5230 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5231 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5232 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5233 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5234 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5235 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5236 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5237 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5238 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5239 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5240 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5241 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5242 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5243 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5244 rsurface.modelelement3i = model->surfmesh.data_element3i;
5245 rsurface.modelelement3s = model->surfmesh.data_element3s;
5246 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5247 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5248 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5249 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5250 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5251 rsurface.modelsurfaces = model->data_surfaces;
5252 rsurface.generatedvertex = false;
5253 rsurface.vertex3f = rsurface.modelvertex3f;
5254 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5255 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5256 rsurface.svector3f = rsurface.modelsvector3f;
5257 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5258 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5259 rsurface.tvector3f = rsurface.modeltvector3f;
5260 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5261 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5262 rsurface.normal3f = rsurface.modelnormal3f;
5263 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5264 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5265 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5268 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5270 dp_model_t *model = ent->model;
5271 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5273 rsurface.entity = (entity_render_t *)ent;
5274 if (rsurface.array_size < model->surfmesh.num_vertices)
5275 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5276 rsurface.matrix = ent->matrix;
5277 rsurface.inversematrix = ent->inversematrix;
5278 R_Mesh_Matrix(&rsurface.matrix);
5279 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5280 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5281 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5282 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5283 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5284 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5285 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5286 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5287 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5288 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5289 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5290 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5291 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5292 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5293 if (ent->model->brush.submodel)
5295 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5296 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5298 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5300 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5302 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5303 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5304 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5305 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5307 else if (wanttangents)
5309 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5310 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5311 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5312 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5313 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5315 else if (wantnormals)
5317 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5318 rsurface.modelsvector3f = NULL;
5319 rsurface.modeltvector3f = NULL;
5320 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5321 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5325 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5326 rsurface.modelsvector3f = NULL;
5327 rsurface.modeltvector3f = NULL;
5328 rsurface.modelnormal3f = NULL;
5329 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5331 rsurface.modelvertex3f_bufferobject = 0;
5332 rsurface.modelvertex3f_bufferoffset = 0;
5333 rsurface.modelsvector3f_bufferobject = 0;
5334 rsurface.modelsvector3f_bufferoffset = 0;
5335 rsurface.modeltvector3f_bufferobject = 0;
5336 rsurface.modeltvector3f_bufferoffset = 0;
5337 rsurface.modelnormal3f_bufferobject = 0;
5338 rsurface.modelnormal3f_bufferoffset = 0;
5339 rsurface.generatedvertex = true;
5343 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5344 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5345 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5346 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5347 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5348 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5349 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5350 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5351 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5352 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5353 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5354 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5355 rsurface.generatedvertex = false;
5357 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5358 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5359 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5360 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5361 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5362 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5363 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5364 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5365 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5366 rsurface.modelelement3i = model->surfmesh.data_element3i;
5367 rsurface.modelelement3s = model->surfmesh.data_element3s;
5368 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5369 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5370 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5371 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5372 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5373 rsurface.modelsurfaces = model->data_surfaces;
5374 rsurface.vertex3f = rsurface.modelvertex3f;
5375 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5376 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5377 rsurface.svector3f = rsurface.modelsvector3f;
5378 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5379 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5380 rsurface.tvector3f = rsurface.modeltvector3f;
5381 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5382 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5383 rsurface.normal3f = rsurface.modelnormal3f;
5384 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5385 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5386 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5389 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5390 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5393 int texturesurfaceindex;
5398 const float *v1, *in_tc;
5400 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5402 q3shaderinfo_deform_t *deform;
5403 // 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
5404 if (rsurface.generatedvertex)
5406 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5407 generatenormals = true;
5408 for (i = 0;i < Q3MAXDEFORMS;i++)
5410 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5412 generatetangents = true;
5413 generatenormals = true;
5415 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5416 generatenormals = true;
5418 if (generatenormals && !rsurface.modelnormal3f)
5420 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5421 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5422 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5423 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5425 if (generatetangents && !rsurface.modelsvector3f)
5427 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5428 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5429 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5430 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5431 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5432 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5433 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);
5436 rsurface.vertex3f = rsurface.modelvertex3f;
5437 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5438 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5439 rsurface.svector3f = rsurface.modelsvector3f;
5440 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5441 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5442 rsurface.tvector3f = rsurface.modeltvector3f;
5443 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5444 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5445 rsurface.normal3f = rsurface.modelnormal3f;
5446 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5447 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5448 // if vertices are deformed (sprite flares and things in maps, possibly
5449 // water waves, bulges and other deformations), generate them into
5450 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5451 // (may be static model data or generated data for an animated model, or
5452 // the previous deform pass)
5453 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5455 switch (deform->deform)
5458 case Q3DEFORM_PROJECTIONSHADOW:
5459 case Q3DEFORM_TEXT0:
5460 case Q3DEFORM_TEXT1:
5461 case Q3DEFORM_TEXT2:
5462 case Q3DEFORM_TEXT3:
5463 case Q3DEFORM_TEXT4:
5464 case Q3DEFORM_TEXT5:
5465 case Q3DEFORM_TEXT6:
5466 case Q3DEFORM_TEXT7:
5469 case Q3DEFORM_AUTOSPRITE:
5470 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5471 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5472 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5473 VectorNormalize(newforward);
5474 VectorNormalize(newright);
5475 VectorNormalize(newup);
5476 // make deformed versions of only the model vertices used by the specified surfaces
5477 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5479 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5480 // a single autosprite surface can contain multiple sprites...
5481 for (j = 0;j < surface->num_vertices - 3;j += 4)
5483 VectorClear(center);
5484 for (i = 0;i < 4;i++)
5485 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5486 VectorScale(center, 0.25f, center);
5487 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5488 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5489 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5490 for (i = 0;i < 4;i++)
5492 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5493 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5496 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);
5497 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);
5499 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5500 rsurface.vertex3f_bufferobject = 0;
5501 rsurface.vertex3f_bufferoffset = 0;
5502 rsurface.svector3f = rsurface.array_deformedsvector3f;
5503 rsurface.svector3f_bufferobject = 0;
5504 rsurface.svector3f_bufferoffset = 0;
5505 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5506 rsurface.tvector3f_bufferobject = 0;
5507 rsurface.tvector3f_bufferoffset = 0;
5508 rsurface.normal3f = rsurface.array_deformednormal3f;
5509 rsurface.normal3f_bufferobject = 0;
5510 rsurface.normal3f_bufferoffset = 0;
5512 case Q3DEFORM_AUTOSPRITE2:
5513 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5514 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5515 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5516 VectorNormalize(newforward);
5517 VectorNormalize(newright);
5518 VectorNormalize(newup);
5519 // make deformed versions of only the model vertices used by the specified surfaces
5520 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5522 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5523 const float *v1, *v2;
5533 memset(shortest, 0, sizeof(shortest));
5534 // a single autosprite surface can contain multiple sprites...
5535 for (j = 0;j < surface->num_vertices - 3;j += 4)
5537 VectorClear(center);
5538 for (i = 0;i < 4;i++)
5539 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5540 VectorScale(center, 0.25f, center);
5541 // find the two shortest edges, then use them to define the
5542 // axis vectors for rotating around the central axis
5543 for (i = 0;i < 6;i++)
5545 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5546 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5548 Debug_PolygonBegin(NULL, 0);
5549 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5550 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);
5551 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5554 l = VectorDistance2(v1, v2);
5555 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5557 l += (1.0f / 1024.0f);
5558 if (shortest[0].length2 > l || i == 0)
5560 shortest[1] = shortest[0];
5561 shortest[0].length2 = l;
5562 shortest[0].v1 = v1;
5563 shortest[0].v2 = v2;
5565 else if (shortest[1].length2 > l || i == 1)
5567 shortest[1].length2 = l;
5568 shortest[1].v1 = v1;
5569 shortest[1].v2 = v2;
5572 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5573 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5575 Debug_PolygonBegin(NULL, 0);
5576 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5577 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);
5578 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5581 // this calculates the right vector from the shortest edge
5582 // and the up vector from the edge midpoints
5583 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5584 VectorNormalize(right);
5585 VectorSubtract(end, start, up);
5586 VectorNormalize(up);
5587 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5588 VectorSubtract(rsurface.modelorg, center, forward);
5589 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5590 VectorNegate(forward, forward);
5591 VectorReflect(forward, 0, up, forward);
5592 VectorNormalize(forward);
5593 CrossProduct(up, forward, newright);
5594 VectorNormalize(newright);
5596 Debug_PolygonBegin(NULL, 0);
5597 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);
5598 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5599 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5603 Debug_PolygonBegin(NULL, 0);
5604 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5605 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5606 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5609 // rotate the quad around the up axis vector, this is made
5610 // especially easy by the fact we know the quad is flat,
5611 // so we only have to subtract the center position and
5612 // measure distance along the right vector, and then
5613 // multiply that by the newright vector and add back the
5615 // we also need to subtract the old position to undo the
5616 // displacement from the center, which we do with a
5617 // DotProduct, the subtraction/addition of center is also
5618 // optimized into DotProducts here
5619 l = DotProduct(right, center);
5620 for (i = 0;i < 4;i++)
5622 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5623 f = DotProduct(right, v1) - l;
5624 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5627 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);
5628 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);
5630 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5631 rsurface.vertex3f_bufferobject = 0;
5632 rsurface.vertex3f_bufferoffset = 0;
5633 rsurface.svector3f = rsurface.array_deformedsvector3f;
5634 rsurface.svector3f_bufferobject = 0;
5635 rsurface.svector3f_bufferoffset = 0;
5636 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5637 rsurface.tvector3f_bufferobject = 0;
5638 rsurface.tvector3f_bufferoffset = 0;
5639 rsurface.normal3f = rsurface.array_deformednormal3f;
5640 rsurface.normal3f_bufferobject = 0;
5641 rsurface.normal3f_bufferoffset = 0;
5643 case Q3DEFORM_NORMAL:
5644 // deform the normals to make reflections wavey
5645 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5647 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5648 for (j = 0;j < surface->num_vertices;j++)
5651 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5652 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5653 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5654 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5655 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5656 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5657 VectorNormalize(normal);
5659 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);
5661 rsurface.svector3f = rsurface.array_deformedsvector3f;
5662 rsurface.svector3f_bufferobject = 0;
5663 rsurface.svector3f_bufferoffset = 0;
5664 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5665 rsurface.tvector3f_bufferobject = 0;
5666 rsurface.tvector3f_bufferoffset = 0;
5667 rsurface.normal3f = rsurface.array_deformednormal3f;
5668 rsurface.normal3f_bufferobject = 0;
5669 rsurface.normal3f_bufferoffset = 0;
5672 // deform vertex array to make wavey water and flags and such
5673 waveparms[0] = deform->waveparms[0];
5674 waveparms[1] = deform->waveparms[1];
5675 waveparms[2] = deform->waveparms[2];
5676 waveparms[3] = deform->waveparms[3];
5677 // this is how a divisor of vertex influence on deformation
5678 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5679 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5680 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5682 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5683 for (j = 0;j < surface->num_vertices;j++)
5685 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5686 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5687 // if the wavefunc depends on time, evaluate it per-vertex
5690 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5691 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5693 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5696 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5697 rsurface.vertex3f_bufferobject = 0;
5698 rsurface.vertex3f_bufferoffset = 0;
5700 case Q3DEFORM_BULGE:
5701 // deform vertex array to make the surface have moving bulges
5702 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5704 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5705 for (j = 0;j < surface->num_vertices;j++)
5707 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5708 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5711 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5712 rsurface.vertex3f_bufferobject = 0;
5713 rsurface.vertex3f_bufferoffset = 0;
5716 // deform vertex array
5717 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5718 VectorScale(deform->parms, scale, waveparms);
5719 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5721 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5722 for (j = 0;j < surface->num_vertices;j++)
5723 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5725 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5726 rsurface.vertex3f_bufferobject = 0;
5727 rsurface.vertex3f_bufferoffset = 0;
5731 // generate texcoords based on the chosen texcoord source
5732 switch(rsurface.texture->tcgen.tcgen)
5735 case Q3TCGEN_TEXTURE:
5736 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5737 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5738 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5740 case Q3TCGEN_LIGHTMAP:
5741 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5742 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5743 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5745 case Q3TCGEN_VECTOR:
5746 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5748 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5749 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)
5751 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5752 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5755 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5756 rsurface.texcoordtexture2f_bufferobject = 0;
5757 rsurface.texcoordtexture2f_bufferoffset = 0;
5759 case Q3TCGEN_ENVIRONMENT:
5760 // make environment reflections using a spheremap
5761 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5763 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5764 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5765 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5766 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5767 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5769 // identical to Q3A's method, but executed in worldspace so
5770 // carried models can be shiny too
5772 float viewer[3], d, reflected[3], worldreflected[3];
5774 VectorSubtract(rsurface.modelorg, vertex, viewer);
5775 // VectorNormalize(viewer);
5777 d = DotProduct(normal, viewer);
5779 reflected[0] = normal[0]*2*d - viewer[0];
5780 reflected[1] = normal[1]*2*d - viewer[1];
5781 reflected[2] = normal[2]*2*d - viewer[2];
5782 // note: this is proportinal to viewer, so we can normalize later
5784 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
5785 VectorNormalize(worldreflected);
5787 // note: this sphere map only uses world x and z!
5788 // so positive and negative y will LOOK THE SAME.
5789 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
5790 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
5793 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5794 rsurface.texcoordtexture2f_bufferobject = 0;
5795 rsurface.texcoordtexture2f_bufferoffset = 0;
5798 // the only tcmod that needs software vertex processing is turbulent, so
5799 // check for it here and apply the changes if needed
5800 // and we only support that as the first one
5801 // (handling a mixture of turbulent and other tcmods would be problematic
5802 // without punting it entirely to a software path)
5803 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5805 amplitude = rsurface.texture->tcmods[0].parms[1];
5806 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5807 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5809 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5810 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)
5812 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5813 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5816 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5817 rsurface.texcoordtexture2f_bufferobject = 0;
5818 rsurface.texcoordtexture2f_bufferoffset = 0;
5820 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5821 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5822 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5823 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5826 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5829 const msurface_t *surface = texturesurfacelist[0];
5830 const msurface_t *surface2;
5835 // TODO: lock all array ranges before render, rather than on each surface
5836 if (texturenumsurfaces == 1)
5838 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5839 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);
5841 else if (r_batchmode.integer == 2)
5843 #define MAXBATCHTRIANGLES 4096
5844 int batchtriangles = 0;
5845 int batchelements[MAXBATCHTRIANGLES*3];
5846 for (i = 0;i < texturenumsurfaces;i = j)
5848 surface = texturesurfacelist[i];
5850 if (surface->num_triangles > MAXBATCHTRIANGLES)
5852 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);
5855 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5856 batchtriangles = surface->num_triangles;
5857 firstvertex = surface->num_firstvertex;
5858 endvertex = surface->num_firstvertex + surface->num_vertices;
5859 for (;j < texturenumsurfaces;j++)
5861 surface2 = texturesurfacelist[j];
5862 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5864 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5865 batchtriangles += surface2->num_triangles;
5866 firstvertex = min(firstvertex, surface2->num_firstvertex);
5867 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5869 surface2 = texturesurfacelist[j-1];
5870 numvertices = endvertex - firstvertex;
5871 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5874 else if (r_batchmode.integer == 1)
5876 for (i = 0;i < texturenumsurfaces;i = j)
5878 surface = texturesurfacelist[i];
5879 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5880 if (texturesurfacelist[j] != surface2)
5882 surface2 = texturesurfacelist[j-1];
5883 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5884 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5885 GL_LockArrays(surface->num_firstvertex, numvertices);
5886 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5891 for (i = 0;i < texturenumsurfaces;i++)
5893 surface = texturesurfacelist[i];
5894 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5895 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);
5900 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5902 int i, planeindex, vertexindex;
5906 r_waterstate_waterplane_t *p, *bestp;
5907 msurface_t *surface;
5908 if (r_waterstate.renderingscene)
5910 for (i = 0;i < texturenumsurfaces;i++)
5912 surface = texturesurfacelist[i];
5913 if (lightmaptexunit >= 0)
5914 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5915 if (deluxemaptexunit >= 0)
5916 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5917 // pick the closest matching water plane
5920 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5923 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5925 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5926 d += fabs(PlaneDiff(vert, &p->plane));
5928 if (bestd > d || !bestp)
5936 if (refractiontexunit >= 0)
5937 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5938 if (reflectiontexunit >= 0)
5939 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5943 if (refractiontexunit >= 0)
5944 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5945 if (reflectiontexunit >= 0)
5946 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5948 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5949 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);
5953 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5957 const msurface_t *surface = texturesurfacelist[0];
5958 const msurface_t *surface2;
5963 // TODO: lock all array ranges before render, rather than on each surface
5964 if (texturenumsurfaces == 1)
5966 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5967 if (deluxemaptexunit >= 0)
5968 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5969 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5970 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);
5972 else if (r_batchmode.integer == 2)
5974 #define MAXBATCHTRIANGLES 4096
5975 int batchtriangles = 0;
5976 int batchelements[MAXBATCHTRIANGLES*3];
5977 for (i = 0;i < texturenumsurfaces;i = j)
5979 surface = texturesurfacelist[i];
5980 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5981 if (deluxemaptexunit >= 0)
5982 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5984 if (surface->num_triangles > MAXBATCHTRIANGLES)
5986 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);
5989 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5990 batchtriangles = surface->num_triangles;
5991 firstvertex = surface->num_firstvertex;
5992 endvertex = surface->num_firstvertex + surface->num_vertices;
5993 for (;j < texturenumsurfaces;j++)
5995 surface2 = texturesurfacelist[j];
5996 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5998 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5999 batchtriangles += surface2->num_triangles;
6000 firstvertex = min(firstvertex, surface2->num_firstvertex);
6001 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6003 surface2 = texturesurfacelist[j-1];
6004 numvertices = endvertex - firstvertex;
6005 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6008 else if (r_batchmode.integer == 1)
6011 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6012 for (i = 0;i < texturenumsurfaces;i = j)
6014 surface = texturesurfacelist[i];
6015 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6016 if (texturesurfacelist[j] != surface2)
6018 Con_Printf(" %i", j - i);
6021 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6023 for (i = 0;i < texturenumsurfaces;i = j)
6025 surface = texturesurfacelist[i];
6026 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6027 if (deluxemaptexunit >= 0)
6028 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6029 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6030 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6033 Con_Printf(" %i", j - i);
6035 surface2 = texturesurfacelist[j-1];
6036 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6037 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6038 GL_LockArrays(surface->num_firstvertex, numvertices);
6039 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6047 for (i = 0;i < texturenumsurfaces;i++)
6049 surface = texturesurfacelist[i];
6050 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6051 if (deluxemaptexunit >= 0)
6052 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6053 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6054 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);
6059 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6062 int texturesurfaceindex;
6063 if (r_showsurfaces.integer == 2)
6065 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6067 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6068 for (j = 0;j < surface->num_triangles;j++)
6070 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6071 GL_Color(f, f, f, 1);
6072 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6078 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6080 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6081 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6082 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);
6083 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6084 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);
6089 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6091 int texturesurfaceindex;
6094 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6096 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6097 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)
6105 rsurface.lightmapcolor4f = rsurface.array_color4f;
6106 rsurface.lightmapcolor4f_bufferobject = 0;
6107 rsurface.lightmapcolor4f_bufferoffset = 0;
6110 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6112 int texturesurfaceindex;
6116 if (rsurface.lightmapcolor4f)
6118 // generate color arrays for the surfaces in this list
6119 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6121 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6122 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)
6124 f = FogPoint_Model(v);
6134 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6136 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6137 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)
6139 f = FogPoint_Model(v);
6147 rsurface.lightmapcolor4f = rsurface.array_color4f;
6148 rsurface.lightmapcolor4f_bufferobject = 0;
6149 rsurface.lightmapcolor4f_bufferoffset = 0;
6152 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6154 int texturesurfaceindex;
6158 if (!rsurface.lightmapcolor4f)
6160 // generate color arrays for the surfaces in this list
6161 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6163 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6164 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)
6166 f = FogPoint_Model(v);
6167 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6168 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6169 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6173 rsurface.lightmapcolor4f = rsurface.array_color4f;
6174 rsurface.lightmapcolor4f_bufferobject = 0;
6175 rsurface.lightmapcolor4f_bufferoffset = 0;
6178 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6180 int texturesurfaceindex;
6183 if (!rsurface.lightmapcolor4f)
6185 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6187 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6188 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)
6196 rsurface.lightmapcolor4f = rsurface.array_color4f;
6197 rsurface.lightmapcolor4f_bufferobject = 0;
6198 rsurface.lightmapcolor4f_bufferoffset = 0;
6201 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6203 int texturesurfaceindex;
6206 if (!rsurface.lightmapcolor4f)
6208 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6210 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6211 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)
6213 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6214 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6215 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6219 rsurface.lightmapcolor4f = rsurface.array_color4f;
6220 rsurface.lightmapcolor4f_bufferobject = 0;
6221 rsurface.lightmapcolor4f_bufferoffset = 0;
6224 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6227 rsurface.lightmapcolor4f = NULL;
6228 rsurface.lightmapcolor4f_bufferobject = 0;
6229 rsurface.lightmapcolor4f_bufferoffset = 0;
6230 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6231 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6232 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6233 GL_Color(r, g, b, a);
6234 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6237 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6239 // TODO: optimize applyfog && applycolor case
6240 // just apply fog if necessary, and tint the fog color array if necessary
6241 rsurface.lightmapcolor4f = NULL;
6242 rsurface.lightmapcolor4f_bufferobject = 0;
6243 rsurface.lightmapcolor4f_bufferoffset = 0;
6244 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6245 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6246 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6247 GL_Color(r, g, b, a);
6248 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6251 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6253 int texturesurfaceindex;
6257 if (texturesurfacelist[0]->lightmapinfo)
6259 // generate color arrays for the surfaces in this list
6260 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6262 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6263 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6265 if (surface->lightmapinfo->samples)
6267 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6268 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6269 VectorScale(lm, scale, c);
6270 if (surface->lightmapinfo->styles[1] != 255)
6272 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6274 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6275 VectorMA(c, scale, lm, c);
6276 if (surface->lightmapinfo->styles[2] != 255)
6279 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6280 VectorMA(c, scale, lm, c);
6281 if (surface->lightmapinfo->styles[3] != 255)
6284 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6285 VectorMA(c, scale, lm, c);
6295 rsurface.lightmapcolor4f = rsurface.array_color4f;
6296 rsurface.lightmapcolor4f_bufferobject = 0;
6297 rsurface.lightmapcolor4f_bufferoffset = 0;
6301 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6302 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6303 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6305 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6306 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6307 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6308 GL_Color(r, g, b, a);
6309 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6312 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6314 int texturesurfaceindex;
6317 float *v, *c, *c2, alpha;
6318 vec3_t ambientcolor;
6319 vec3_t diffusecolor;
6323 VectorCopy(rsurface.modellight_lightdir, lightdir);
6324 f = 0.5f * r_refdef.lightmapintensity;
6325 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6326 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6327 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6328 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6329 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6330 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6332 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6334 // generate color arrays for the surfaces in this list
6335 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6337 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6338 int numverts = surface->num_vertices;
6339 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6340 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6341 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6342 // q3-style directional shading
6343 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6345 if ((f = DotProduct(c2, lightdir)) > 0)
6346 VectorMA(ambientcolor, f, diffusecolor, c);
6348 VectorCopy(ambientcolor, c);
6356 rsurface.lightmapcolor4f = rsurface.array_color4f;
6357 rsurface.lightmapcolor4f_bufferobject = 0;
6358 rsurface.lightmapcolor4f_bufferoffset = 0;
6359 *applycolor = false;
6363 *r = ambientcolor[0];
6364 *g = ambientcolor[1];
6365 *b = ambientcolor[2];
6366 rsurface.lightmapcolor4f = NULL;
6367 rsurface.lightmapcolor4f_bufferobject = 0;
6368 rsurface.lightmapcolor4f_bufferoffset = 0;
6372 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6374 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6375 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6376 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6377 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6378 GL_Color(r, g, b, a);
6379 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6382 void RSurf_SetupDepthAndCulling(void)
6384 // submodels are biased to avoid z-fighting with world surfaces that they
6385 // may be exactly overlapping (avoids z-fighting artifacts on certain
6386 // doors and things in Quake maps)
6387 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6388 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6389 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6390 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6393 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6395 // transparent sky would be ridiculous
6396 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6398 R_SetupGenericShader(false);
6401 skyrendernow = false;
6402 // we have to force off the water clipping plane while rendering sky
6406 // restore entity matrix
6407 R_Mesh_Matrix(&rsurface.matrix);
6409 RSurf_SetupDepthAndCulling();
6411 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6412 // skymasking on them, and Quake3 never did sky masking (unlike
6413 // software Quake and software Quake2), so disable the sky masking
6414 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6415 // and skymasking also looks very bad when noclipping outside the
6416 // level, so don't use it then either.
6417 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6419 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6420 R_Mesh_ColorPointer(NULL, 0, 0);
6421 R_Mesh_ResetTextureState();
6422 if (skyrendermasked)
6424 R_SetupDepthOrShadowShader();
6425 // depth-only (masking)
6426 GL_ColorMask(0,0,0,0);
6427 // just to make sure that braindead drivers don't draw
6428 // anything despite that colormask...
6429 GL_BlendFunc(GL_ZERO, GL_ONE);
6433 R_SetupGenericShader(false);
6435 GL_BlendFunc(GL_ONE, GL_ZERO);
6437 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6438 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6439 if (skyrendermasked)
6440 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6442 R_Mesh_ResetTextureState();
6443 GL_Color(1, 1, 1, 1);
6446 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6448 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6451 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6452 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6453 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6454 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6455 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6456 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6457 if (rsurface.texture->backgroundcurrentskinframe)
6459 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6460 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6461 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6462 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6464 if(rsurface.texture->colormapping)
6466 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6467 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6469 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6470 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6471 R_Mesh_ColorPointer(NULL, 0, 0);
6473 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6475 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6477 // render background
6478 GL_BlendFunc(GL_ONE, GL_ZERO);
6480 GL_AlphaTest(false);
6482 GL_Color(1, 1, 1, 1);
6483 R_Mesh_ColorPointer(NULL, 0, 0);
6485 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6486 if (r_glsl_permutation)
6488 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6489 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6490 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6491 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6492 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6493 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6494 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);
6496 GL_LockArrays(0, 0);
6498 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6499 GL_DepthMask(false);
6500 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6501 R_Mesh_ColorPointer(NULL, 0, 0);
6503 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6504 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6505 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6508 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6509 if (!r_glsl_permutation)
6512 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6513 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6514 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6515 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6516 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6517 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6519 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6521 GL_BlendFunc(GL_ONE, GL_ZERO);
6523 GL_AlphaTest(false);
6527 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6528 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6529 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6532 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6534 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6535 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);
6537 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6541 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6542 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);
6544 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6546 GL_LockArrays(0, 0);
6549 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6551 // OpenGL 1.3 path - anything not completely ancient
6552 int texturesurfaceindex;
6553 qboolean applycolor;
6557 const texturelayer_t *layer;
6558 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6560 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6563 int layertexrgbscale;
6564 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6566 if (layerindex == 0)
6570 GL_AlphaTest(false);
6571 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6574 GL_DepthMask(layer->depthmask && writedepth);
6575 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6576 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6578 layertexrgbscale = 4;
6579 VectorScale(layer->color, 0.25f, layercolor);
6581 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6583 layertexrgbscale = 2;
6584 VectorScale(layer->color, 0.5f, layercolor);
6588 layertexrgbscale = 1;
6589 VectorScale(layer->color, 1.0f, layercolor);
6591 layercolor[3] = layer->color[3];
6592 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6593 R_Mesh_ColorPointer(NULL, 0, 0);
6594 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6595 switch (layer->type)
6597 case TEXTURELAYERTYPE_LITTEXTURE:
6598 memset(&m, 0, sizeof(m));
6599 m.tex[0] = R_GetTexture(r_texture_white);
6600 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6601 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6602 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6603 m.tex[1] = R_GetTexture(layer->texture);
6604 m.texmatrix[1] = layer->texmatrix;
6605 m.texrgbscale[1] = layertexrgbscale;
6606 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6607 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6608 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6609 R_Mesh_TextureState(&m);
6610 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6611 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6612 else if (rsurface.uselightmaptexture)
6613 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6615 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6617 case TEXTURELAYERTYPE_TEXTURE:
6618 memset(&m, 0, sizeof(m));
6619 m.tex[0] = R_GetTexture(layer->texture);
6620 m.texmatrix[0] = layer->texmatrix;
6621 m.texrgbscale[0] = layertexrgbscale;
6622 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6623 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6624 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6625 R_Mesh_TextureState(&m);
6626 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6628 case TEXTURELAYERTYPE_FOG:
6629 memset(&m, 0, sizeof(m));
6630 m.texrgbscale[0] = layertexrgbscale;
6633 m.tex[0] = R_GetTexture(layer->texture);
6634 m.texmatrix[0] = layer->texmatrix;
6635 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6636 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6637 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6639 R_Mesh_TextureState(&m);
6640 // generate a color array for the fog pass
6641 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6642 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6646 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6647 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)
6649 f = 1 - FogPoint_Model(v);
6650 c[0] = layercolor[0];
6651 c[1] = layercolor[1];
6652 c[2] = layercolor[2];
6653 c[3] = f * layercolor[3];
6656 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6659 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6661 GL_LockArrays(0, 0);
6664 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6666 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6667 GL_AlphaTest(false);
6671 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6673 // OpenGL 1.1 - crusty old voodoo path
6674 int texturesurfaceindex;
6678 const texturelayer_t *layer;
6679 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6681 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6683 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6685 if (layerindex == 0)
6689 GL_AlphaTest(false);
6690 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6693 GL_DepthMask(layer->depthmask && writedepth);
6694 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6695 R_Mesh_ColorPointer(NULL, 0, 0);
6696 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6697 switch (layer->type)
6699 case TEXTURELAYERTYPE_LITTEXTURE:
6700 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6702 // two-pass lit texture with 2x rgbscale
6703 // first the lightmap pass
6704 memset(&m, 0, sizeof(m));
6705 m.tex[0] = R_GetTexture(r_texture_white);
6706 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6707 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6708 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6709 R_Mesh_TextureState(&m);
6710 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6711 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6712 else if (rsurface.uselightmaptexture)
6713 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6715 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6716 GL_LockArrays(0, 0);
6717 // then apply the texture to it
6718 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6719 memset(&m, 0, sizeof(m));
6720 m.tex[0] = R_GetTexture(layer->texture);
6721 m.texmatrix[0] = layer->texmatrix;
6722 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6723 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6724 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6725 R_Mesh_TextureState(&m);
6726 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);
6730 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6731 memset(&m, 0, sizeof(m));
6732 m.tex[0] = R_GetTexture(layer->texture);
6733 m.texmatrix[0] = layer->texmatrix;
6734 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6735 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6736 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6737 R_Mesh_TextureState(&m);
6738 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6739 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);
6741 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);
6744 case TEXTURELAYERTYPE_TEXTURE:
6745 // singletexture unlit texture with transparency support
6746 memset(&m, 0, sizeof(m));
6747 m.tex[0] = R_GetTexture(layer->texture);
6748 m.texmatrix[0] = layer->texmatrix;
6749 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6750 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6751 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6752 R_Mesh_TextureState(&m);
6753 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);
6755 case TEXTURELAYERTYPE_FOG:
6756 // singletexture fogging
6757 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6760 memset(&m, 0, sizeof(m));
6761 m.tex[0] = R_GetTexture(layer->texture);
6762 m.texmatrix[0] = layer->texmatrix;
6763 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6764 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6765 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6766 R_Mesh_TextureState(&m);
6769 R_Mesh_ResetTextureState();
6770 // generate a color array for the fog pass
6771 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6775 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6776 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)
6778 f = 1 - FogPoint_Model(v);
6779 c[0] = layer->color[0];
6780 c[1] = layer->color[1];
6781 c[2] = layer->color[2];
6782 c[3] = f * layer->color[3];
6785 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6788 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6790 GL_LockArrays(0, 0);
6793 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6795 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6796 GL_AlphaTest(false);
6800 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6804 GL_AlphaTest(false);
6805 R_Mesh_ColorPointer(NULL, 0, 0);
6806 R_Mesh_ResetTextureState();
6807 R_SetupGenericShader(false);
6809 if(rsurface.texture && rsurface.texture->currentskinframe)
6811 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6812 c[3] *= rsurface.texture->currentalpha;
6822 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6824 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
6825 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
6826 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
6829 // brighten it up (as texture value 127 means "unlit")
6830 c[0] *= 2 * r_refdef.view.colorscale;
6831 c[1] *= 2 * r_refdef.view.colorscale;
6832 c[2] *= 2 * r_refdef.view.colorscale;
6834 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6835 c[3] *= r_wateralpha.value;
6837 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6839 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6840 GL_DepthMask(false);
6842 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6844 GL_BlendFunc(GL_ONE, GL_ONE);
6845 GL_DepthMask(false);
6847 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6849 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6850 GL_DepthMask(false);
6852 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6854 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6855 GL_DepthMask(false);
6859 GL_BlendFunc(GL_ONE, GL_ZERO);
6860 GL_DepthMask(writedepth);
6863 rsurface.lightmapcolor4f = NULL;
6865 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6867 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6869 rsurface.lightmapcolor4f = NULL;
6870 rsurface.lightmapcolor4f_bufferobject = 0;
6871 rsurface.lightmapcolor4f_bufferoffset = 0;
6873 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6875 qboolean applycolor = true;
6878 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6880 r_refdef.lightmapintensity = 1;
6881 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6882 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6886 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6888 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6889 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6890 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6893 if(!rsurface.lightmapcolor4f)
6894 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6896 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6897 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6898 if(r_refdef.fogenabled)
6899 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6901 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6902 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6905 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6908 RSurf_SetupDepthAndCulling();
6909 if (r_showsurfaces.integer == 3)
6910 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6911 else if (r_glsl.integer && gl_support_fragment_shader)
6912 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6913 else if (gl_combine.integer && r_textureunits.integer >= 2)
6914 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6916 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6920 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6923 RSurf_SetupDepthAndCulling();
6924 if (r_showsurfaces.integer == 3)
6925 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6926 else if (r_glsl.integer && gl_support_fragment_shader)
6927 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6928 else if (gl_combine.integer && r_textureunits.integer >= 2)
6929 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6931 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6935 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6938 int texturenumsurfaces, endsurface;
6940 msurface_t *surface;
6941 msurface_t *texturesurfacelist[1024];
6943 // if the model is static it doesn't matter what value we give for
6944 // wantnormals and wanttangents, so this logic uses only rules applicable
6945 // to a model, knowing that they are meaningless otherwise
6946 if (ent == r_refdef.scene.worldentity)
6947 RSurf_ActiveWorldEntity();
6948 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6949 RSurf_ActiveModelEntity(ent, false, false);
6951 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6953 for (i = 0;i < numsurfaces;i = j)
6956 surface = rsurface.modelsurfaces + surfacelist[i];
6957 texture = surface->texture;
6958 rsurface.texture = R_GetCurrentTexture(texture);
6959 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6960 // scan ahead until we find a different texture
6961 endsurface = min(i + 1024, numsurfaces);
6962 texturenumsurfaces = 0;
6963 texturesurfacelist[texturenumsurfaces++] = surface;
6964 for (;j < endsurface;j++)
6966 surface = rsurface.modelsurfaces + surfacelist[j];
6967 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6969 texturesurfacelist[texturenumsurfaces++] = surface;
6971 // render the range of surfaces
6972 if (ent == r_refdef.scene.worldentity)
6973 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6975 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6977 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6978 GL_AlphaTest(false);
6981 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6983 const entity_render_t *queueentity = r_refdef.scene.worldentity;
6987 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6989 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6991 RSurf_SetupDepthAndCulling();
6992 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6993 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6995 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6997 RSurf_SetupDepthAndCulling();
6998 GL_AlphaTest(false);
6999 R_Mesh_ColorPointer(NULL, 0, 0);
7000 R_Mesh_ResetTextureState();
7001 R_SetupGenericShader(false);
7002 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7004 GL_BlendFunc(GL_ONE, GL_ZERO);
7005 GL_Color(0, 0, 0, 1);
7006 GL_DepthTest(writedepth);
7007 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7009 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7011 RSurf_SetupDepthAndCulling();
7012 GL_AlphaTest(false);
7013 R_Mesh_ColorPointer(NULL, 0, 0);
7014 R_Mesh_ResetTextureState();
7015 R_SetupGenericShader(false);
7016 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7018 GL_BlendFunc(GL_ONE, GL_ZERO);
7020 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7022 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7023 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7024 else if (!rsurface.texture->currentnumlayers)
7026 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7028 // transparent surfaces get pushed off into the transparent queue
7029 int surfacelistindex;
7030 const msurface_t *surface;
7031 vec3_t tempcenter, center;
7032 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7034 surface = texturesurfacelist[surfacelistindex];
7035 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7036 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7037 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7038 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7039 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7044 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7045 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7050 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7054 // break the surface list down into batches by texture and use of lightmapping
7055 for (i = 0;i < numsurfaces;i = j)
7058 // texture is the base texture pointer, rsurface.texture is the
7059 // current frame/skin the texture is directing us to use (for example
7060 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7061 // use skin 1 instead)
7062 texture = surfacelist[i]->texture;
7063 rsurface.texture = R_GetCurrentTexture(texture);
7064 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7065 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7067 // if this texture is not the kind we want, skip ahead to the next one
7068 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7072 // simply scan ahead until we find a different texture or lightmap state
7073 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7075 // render the range of surfaces
7076 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7080 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7085 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7087 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7089 RSurf_SetupDepthAndCulling();
7090 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7091 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7093 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7095 RSurf_SetupDepthAndCulling();
7096 GL_AlphaTest(false);
7097 R_Mesh_ColorPointer(NULL, 0, 0);
7098 R_Mesh_ResetTextureState();
7099 R_SetupGenericShader(false);
7100 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7102 GL_BlendFunc(GL_ONE, GL_ZERO);
7103 GL_Color(0, 0, 0, 1);
7104 GL_DepthTest(writedepth);
7105 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7107 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7109 RSurf_SetupDepthAndCulling();
7110 GL_AlphaTest(false);
7111 R_Mesh_ColorPointer(NULL, 0, 0);
7112 R_Mesh_ResetTextureState();
7113 R_SetupGenericShader(false);
7114 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7116 GL_BlendFunc(GL_ONE, GL_ZERO);
7118 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7120 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7121 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7122 else if (!rsurface.texture->currentnumlayers)
7124 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7126 // transparent surfaces get pushed off into the transparent queue
7127 int surfacelistindex;
7128 const msurface_t *surface;
7129 vec3_t tempcenter, center;
7130 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7132 surface = texturesurfacelist[surfacelistindex];
7133 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7134 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7135 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7136 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7137 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7142 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7143 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7148 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7152 // break the surface list down into batches by texture and use of lightmapping
7153 for (i = 0;i < numsurfaces;i = j)
7156 // texture is the base texture pointer, rsurface.texture is the
7157 // current frame/skin the texture is directing us to use (for example
7158 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7159 // use skin 1 instead)
7160 texture = surfacelist[i]->texture;
7161 rsurface.texture = R_GetCurrentTexture(texture);
7162 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7163 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7165 // if this texture is not the kind we want, skip ahead to the next one
7166 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7170 // simply scan ahead until we find a different texture or lightmap state
7171 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7173 // render the range of surfaces
7174 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7178 float locboxvertex3f[6*4*3] =
7180 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7181 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7182 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7183 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7184 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7185 1,0,0, 0,0,0, 0,1,0, 1,1,0
7188 unsigned short locboxelements[6*2*3] =
7198 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7201 cl_locnode_t *loc = (cl_locnode_t *)ent;
7203 float vertex3f[6*4*3];
7205 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7206 GL_DepthMask(false);
7207 GL_DepthRange(0, 1);
7208 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7210 GL_CullFace(GL_NONE);
7211 R_Mesh_Matrix(&identitymatrix);
7213 R_Mesh_VertexPointer(vertex3f, 0, 0);
7214 R_Mesh_ColorPointer(NULL, 0, 0);
7215 R_Mesh_ResetTextureState();
7216 R_SetupGenericShader(false);
7219 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7220 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7221 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7222 surfacelist[0] < 0 ? 0.5f : 0.125f);
7224 if (VectorCompare(loc->mins, loc->maxs))
7226 VectorSet(size, 2, 2, 2);
7227 VectorMA(loc->mins, -0.5f, size, mins);
7231 VectorCopy(loc->mins, mins);
7232 VectorSubtract(loc->maxs, loc->mins, size);
7235 for (i = 0;i < 6*4*3;)
7236 for (j = 0;j < 3;j++, i++)
7237 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7239 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7242 void R_DrawLocs(void)
7245 cl_locnode_t *loc, *nearestloc;
7247 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7248 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7250 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7251 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7255 void R_DrawDebugModel(entity_render_t *ent)
7257 int i, j, k, l, flagsmask;
7258 const int *elements;
7260 msurface_t *surface;
7261 dp_model_t *model = ent->model;
7264 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7266 R_Mesh_ColorPointer(NULL, 0, 0);
7267 R_Mesh_ResetTextureState();
7268 R_SetupGenericShader(false);
7269 GL_DepthRange(0, 1);
7270 GL_DepthTest(!r_showdisabledepthtest.integer);
7271 GL_DepthMask(false);
7272 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7274 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7276 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7277 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7279 if (brush->colbrushf && brush->colbrushf->numtriangles)
7281 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7282 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);
7283 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7286 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7288 if (surface->num_collisiontriangles)
7290 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7291 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);
7292 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7297 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7299 if (r_showtris.integer || r_shownormals.integer)
7301 if (r_showdisabledepthtest.integer)
7303 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7304 GL_DepthMask(false);
7308 GL_BlendFunc(GL_ONE, GL_ZERO);
7311 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7313 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7315 rsurface.texture = R_GetCurrentTexture(surface->texture);
7316 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7318 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7319 if (r_showtris.value > 0)
7321 if (!rsurface.texture->currentlayers->depthmask)
7322 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7323 else if (ent == r_refdef.scene.worldentity)
7324 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7326 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7327 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7328 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7329 R_Mesh_ColorPointer(NULL, 0, 0);
7330 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7331 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7332 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7333 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);
7334 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7337 if (r_shownormals.value < 0)
7340 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7342 VectorCopy(rsurface.vertex3f + l * 3, v);
7343 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7344 qglVertex3f(v[0], v[1], v[2]);
7345 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7346 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7347 qglVertex3f(v[0], v[1], v[2]);
7352 if (r_shownormals.value > 0)
7355 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7357 VectorCopy(rsurface.vertex3f + l * 3, v);
7358 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7359 qglVertex3f(v[0], v[1], v[2]);
7360 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7361 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7362 qglVertex3f(v[0], v[1], v[2]);
7367 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7369 VectorCopy(rsurface.vertex3f + l * 3, v);
7370 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7371 qglVertex3f(v[0], v[1], v[2]);
7372 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7373 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7374 qglVertex3f(v[0], v[1], v[2]);
7379 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7381 VectorCopy(rsurface.vertex3f + l * 3, v);
7382 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7383 qglVertex3f(v[0], v[1], v[2]);
7384 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7385 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7386 qglVertex3f(v[0], v[1], v[2]);
7393 rsurface.texture = NULL;
7397 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7398 int r_maxsurfacelist = 0;
7399 msurface_t **r_surfacelist = NULL;
7400 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7402 int i, j, endj, f, flagsmask;
7404 dp_model_t *model = r_refdef.scene.worldmodel;
7405 msurface_t *surfaces;
7406 unsigned char *update;
7407 int numsurfacelist = 0;
7411 if (r_maxsurfacelist < model->num_surfaces)
7413 r_maxsurfacelist = model->num_surfaces;
7415 Mem_Free(r_surfacelist);
7416 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7419 RSurf_ActiveWorldEntity();
7421 surfaces = model->data_surfaces;
7422 update = model->brushq1.lightmapupdateflags;
7424 // update light styles on this submodel
7425 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7427 model_brush_lightstyleinfo_t *style;
7428 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7430 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7432 int *list = style->surfacelist;
7433 style->value = r_refdef.scene.lightstylevalue[style->style];
7434 for (j = 0;j < style->numsurfaces;j++)
7435 update[list[j]] = true;
7440 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7444 R_DrawDebugModel(r_refdef.scene.worldentity);
7445 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7451 rsurface.uselightmaptexture = false;
7452 rsurface.texture = NULL;
7453 rsurface.rtlight = NULL;
7455 // add visible surfaces to draw list
7456 for (i = 0;i < model->nummodelsurfaces;i++)
7458 j = model->sortedmodelsurfaces[i];
7459 if (r_refdef.viewcache.world_surfacevisible[j])
7460 r_surfacelist[numsurfacelist++] = surfaces + j;
7462 // update lightmaps if needed
7464 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7465 if (r_refdef.viewcache.world_surfacevisible[j])
7467 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7468 // don't do anything if there were no surfaces
7469 if (!numsurfacelist)
7471 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7474 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7475 GL_AlphaTest(false);
7477 // add to stats if desired
7478 if (r_speeds.integer && !skysurfaces && !depthonly)
7480 r_refdef.stats.world_surfaces += numsurfacelist;
7481 for (j = 0;j < numsurfacelist;j++)
7482 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7484 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7487 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7489 int i, j, endj, f, flagsmask;
7491 dp_model_t *model = ent->model;
7492 msurface_t *surfaces;
7493 unsigned char *update;
7494 int numsurfacelist = 0;
7498 if (r_maxsurfacelist < model->num_surfaces)
7500 r_maxsurfacelist = model->num_surfaces;
7502 Mem_Free(r_surfacelist);
7503 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7506 // if the model is static it doesn't matter what value we give for
7507 // wantnormals and wanttangents, so this logic uses only rules applicable
7508 // to a model, knowing that they are meaningless otherwise
7509 if (ent == r_refdef.scene.worldentity)
7510 RSurf_ActiveWorldEntity();
7511 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7512 RSurf_ActiveModelEntity(ent, false, false);
7514 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7516 surfaces = model->data_surfaces;
7517 update = model->brushq1.lightmapupdateflags;
7519 // update light styles
7520 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7522 model_brush_lightstyleinfo_t *style;
7523 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7525 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7527 int *list = style->surfacelist;
7528 style->value = r_refdef.scene.lightstylevalue[style->style];
7529 for (j = 0;j < style->numsurfaces;j++)
7530 update[list[j]] = true;
7535 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7539 R_DrawDebugModel(ent);
7540 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7546 rsurface.uselightmaptexture = false;
7547 rsurface.texture = NULL;
7548 rsurface.rtlight = NULL;
7550 // add visible surfaces to draw list
7551 for (i = 0;i < model->nummodelsurfaces;i++)
7552 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7553 // don't do anything if there were no surfaces
7554 if (!numsurfacelist)
7556 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7559 // update lightmaps if needed
7561 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7563 R_BuildLightMap(ent, surfaces + j);
7564 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7565 GL_AlphaTest(false);
7567 // add to stats if desired
7568 if (r_speeds.integer && !skysurfaces && !depthonly)
7570 r_refdef.stats.entities_surfaces += numsurfacelist;
7571 for (j = 0;j < numsurfacelist;j++)
7572 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7574 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity