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"
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
32 static int r_frame = 0; ///< used only by R_GetCurrentTexture
39 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
40 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
41 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
42 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
43 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)"};
44 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
45 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
46 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
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_depthfirst);
2412 Cvar_RegisterVariable(&r_useinfinitefarclip);
2413 Cvar_RegisterVariable(&r_nearclip);
2414 Cvar_RegisterVariable(&r_showbboxes);
2415 Cvar_RegisterVariable(&r_showsurfaces);
2416 Cvar_RegisterVariable(&r_showtris);
2417 Cvar_RegisterVariable(&r_shownormals);
2418 Cvar_RegisterVariable(&r_showlighting);
2419 Cvar_RegisterVariable(&r_showshadowvolumes);
2420 Cvar_RegisterVariable(&r_showcollisionbrushes);
2421 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2422 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2423 Cvar_RegisterVariable(&r_showdisabledepthtest);
2424 Cvar_RegisterVariable(&r_drawportals);
2425 Cvar_RegisterVariable(&r_drawentities);
2426 Cvar_RegisterVariable(&r_cullentities_trace);
2427 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2428 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2429 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2430 Cvar_RegisterVariable(&r_drawviewmodel);
2431 Cvar_RegisterVariable(&r_speeds);
2432 Cvar_RegisterVariable(&r_fullbrights);
2433 Cvar_RegisterVariable(&r_wateralpha);
2434 Cvar_RegisterVariable(&r_dynamic);
2435 Cvar_RegisterVariable(&r_fullbright);
2436 Cvar_RegisterVariable(&r_shadows);
2437 Cvar_RegisterVariable(&r_shadows_throwdistance);
2438 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2439 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2440 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2441 Cvar_RegisterVariable(&r_fog_exp2);
2442 Cvar_RegisterVariable(&r_drawfog);
2443 Cvar_RegisterVariable(&r_textureunits);
2444 Cvar_RegisterVariable(&r_glsl);
2445 Cvar_RegisterVariable(&r_glsl_contrastboost);
2446 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2447 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2448 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2449 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2450 Cvar_RegisterVariable(&r_glsl_postprocess);
2451 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2452 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2453 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2454 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2455 Cvar_RegisterVariable(&r_glsl_usegeneric);
2456 Cvar_RegisterVariable(&r_water);
2457 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2458 Cvar_RegisterVariable(&r_water_clippingplanebias);
2459 Cvar_RegisterVariable(&r_water_refractdistort);
2460 Cvar_RegisterVariable(&r_water_reflectdistort);
2461 Cvar_RegisterVariable(&r_lerpsprites);
2462 Cvar_RegisterVariable(&r_lerpmodels);
2463 Cvar_RegisterVariable(&r_lerplightstyles);
2464 Cvar_RegisterVariable(&r_waterscroll);
2465 Cvar_RegisterVariable(&r_bloom);
2466 Cvar_RegisterVariable(&r_bloom_colorscale);
2467 Cvar_RegisterVariable(&r_bloom_brighten);
2468 Cvar_RegisterVariable(&r_bloom_blur);
2469 Cvar_RegisterVariable(&r_bloom_resolution);
2470 Cvar_RegisterVariable(&r_bloom_colorexponent);
2471 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2472 Cvar_RegisterVariable(&r_hdr);
2473 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2474 Cvar_RegisterVariable(&r_hdr_glowintensity);
2475 Cvar_RegisterVariable(&r_hdr_range);
2476 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2477 Cvar_RegisterVariable(&developer_texturelogging);
2478 Cvar_RegisterVariable(&gl_lightmaps);
2479 Cvar_RegisterVariable(&r_test);
2480 Cvar_RegisterVariable(&r_batchmode);
2481 Cvar_RegisterVariable(&r_glsl_saturation);
2482 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2483 Cvar_SetValue("r_fullbrights", 0);
2484 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2486 Cvar_RegisterVariable(&r_track_sprites);
2487 Cvar_RegisterVariable(&r_track_sprites_flags);
2488 Cvar_RegisterVariable(&r_track_sprites_scalew);
2489 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2492 extern void R_Textures_Init(void);
2493 extern void GL_Draw_Init(void);
2494 extern void GL_Main_Init(void);
2495 extern void R_Shadow_Init(void);
2496 extern void R_Sky_Init(void);
2497 extern void GL_Surf_Init(void);
2498 extern void R_Particles_Init(void);
2499 extern void R_Explosion_Init(void);
2500 extern void gl_backend_init(void);
2501 extern void Sbar_Init(void);
2502 extern void R_LightningBeams_Init(void);
2503 extern void Mod_RenderInit(void);
2504 extern void Font_Init(void);
2506 void Render_Init(void)
2519 R_LightningBeams_Init();
2528 extern char *ENGINE_EXTENSIONS;
2531 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2532 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2533 gl_version = (const char *)qglGetString(GL_VERSION);
2534 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2538 if (!gl_platformextensions)
2539 gl_platformextensions = "";
2541 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2542 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2543 Con_Printf("GL_VERSION: %s\n", gl_version);
2544 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2545 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2547 VID_CheckExtensions();
2549 // LordHavoc: report supported extensions
2550 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2552 // clear to black (loading plaque will be seen over this)
2554 qglClearColor(0,0,0,1);CHECKGLERROR
2555 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2558 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2562 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2564 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2567 p = r_refdef.view.frustum + i;
2572 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2576 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2580 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2584 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2588 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2592 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2596 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2600 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2608 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2612 for (i = 0;i < numplanes;i++)
2619 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2623 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2627 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2631 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2635 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2639 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2643 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2647 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2655 //==================================================================================
2657 // LordHavoc: animcache written by Echon, refactored and reformatted by me
2660 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
2661 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
2662 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
2665 typedef struct r_animcache_entity_s
2672 qboolean wantnormals;
2673 qboolean wanttangents;
2675 r_animcache_entity_t;
2677 typedef struct r_animcache_s
2679 r_animcache_entity_t entity[MAX_EDICTS*2];
2685 static r_animcache_t r_animcachestate;
2687 void R_AnimCache_Free(void)
2690 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
2692 r_animcachestate.entity[idx].maxvertices = 0;
2693 Mem_Free(r_animcachestate.entity[idx].vertex3f);
2694 r_animcachestate.entity[idx].vertex3f = NULL;
2695 r_animcachestate.entity[idx].normal3f = NULL;
2696 r_animcachestate.entity[idx].svector3f = NULL;
2697 r_animcachestate.entity[idx].tvector3f = NULL;
2699 r_animcachestate.currentindex = 0;
2700 r_animcachestate.maxindex = 0;
2703 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
2707 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
2709 if (cache->maxvertices >= numvertices)
2712 // Release existing memory
2713 if (cache->vertex3f)
2714 Mem_Free(cache->vertex3f);
2716 // Pad by 1024 verts
2717 cache->maxvertices = (numvertices + 1023) & ~1023;
2718 arraySize = cache->maxvertices * 3;
2720 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
2721 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
2722 r_animcachestate.entity[cacheIdx].vertex3f = base;
2723 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
2724 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
2725 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
2727 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
2730 void R_AnimCache_NewFrame(void)
2734 if (r_animcache.integer && r_drawentities.integer)
2735 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
2736 else if (r_animcachestate.maxindex)
2739 r_animcachestate.currentindex = 0;
2741 for (i = 0;i < r_refdef.scene.numentities;i++)
2742 r_refdef.scene.entities[i]->animcacheindex = -1;
2745 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2747 dp_model_t *model = ent->model;
2748 r_animcache_entity_t *c;
2749 // see if it's already cached this frame
2750 if (ent->animcacheindex >= 0)
2752 // add normals/tangents if needed
2753 c = r_animcachestate.entity + ent->animcacheindex;
2755 wantnormals = false;
2756 if (c->wanttangents)
2757 wanttangents = false;
2758 if (wantnormals || wanttangents)
2759 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
2763 // see if this ent is worth caching
2764 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
2766 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
2768 // assign it a cache entry and make sure the arrays are big enough
2769 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
2770 ent->animcacheindex = r_animcachestate.currentindex++;
2771 c = r_animcachestate.entity + ent->animcacheindex;
2772 c->wantnormals = wantnormals;
2773 c->wanttangents = wanttangents;
2774 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
2779 void R_AnimCache_CacheVisibleEntities(void)
2782 qboolean wantnormals;
2783 qboolean wanttangents;
2785 if (!r_animcachestate.maxindex)
2788 wantnormals = !r_showsurfaces.integer;
2789 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
2791 // TODO: thread this?
2793 for (i = 0;i < r_refdef.scene.numentities;i++)
2795 if (!r_refdef.viewcache.entityvisible[i])
2797 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
2801 //==================================================================================
2803 static void R_View_UpdateEntityLighting (void)
2806 entity_render_t *ent;
2807 vec3_t tempdiffusenormal;
2809 for (i = 0;i < r_refdef.scene.numentities;i++)
2811 ent = r_refdef.scene.entities[i];
2813 // skip unseen models
2814 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
2818 if (ent->model && ent->model->brush.num_leafs)
2820 // TODO: use modellight for r_ambient settings on world?
2821 VectorSet(ent->modellight_ambient, 0, 0, 0);
2822 VectorSet(ent->modellight_diffuse, 0, 0, 0);
2823 VectorSet(ent->modellight_lightdir, 0, 0, 1);
2827 // fetch the lighting from the worldmodel data
2828 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));
2829 VectorClear(ent->modellight_diffuse);
2830 VectorClear(tempdiffusenormal);
2831 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
2834 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2835 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2838 VectorSet(ent->modellight_ambient, 1, 1, 1);
2840 // move the light direction into modelspace coordinates for lighting code
2841 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2842 if(VectorLength2(ent->modellight_lightdir) == 0)
2843 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2844 VectorNormalize(ent->modellight_lightdir);
2848 static void R_View_UpdateEntityVisible (void)
2851 entity_render_t *ent;
2853 if (!r_drawentities.integer)
2856 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2857 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2859 // worldmodel can check visibility
2860 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2861 for (i = 0;i < r_refdef.scene.numentities;i++)
2863 ent = r_refdef.scene.entities[i];
2864 if (!(ent->flags & renderimask))
2865 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)))
2866 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))
2867 r_refdef.viewcache.entityvisible[i] = true;
2869 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2871 for (i = 0;i < r_refdef.scene.numentities;i++)
2873 ent = r_refdef.scene.entities[i];
2874 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2876 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))
2877 ent->last_trace_visibility = realtime;
2878 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2879 r_refdef.viewcache.entityvisible[i] = 0;
2886 // no worldmodel or it can't check visibility
2887 for (i = 0;i < r_refdef.scene.numentities;i++)
2889 ent = r_refdef.scene.entities[i];
2890 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));
2895 /// only used if skyrendermasked, and normally returns false
2896 int R_DrawBrushModelsSky (void)
2899 entity_render_t *ent;
2901 if (!r_drawentities.integer)
2905 for (i = 0;i < r_refdef.scene.numentities;i++)
2907 if (!r_refdef.viewcache.entityvisible[i])
2909 ent = r_refdef.scene.entities[i];
2910 if (!ent->model || !ent->model->DrawSky)
2912 ent->model->DrawSky(ent);
2918 static void R_DrawNoModel(entity_render_t *ent);
2919 static void R_DrawModels(void)
2922 entity_render_t *ent;
2924 if (!r_drawentities.integer)
2927 for (i = 0;i < r_refdef.scene.numentities;i++)
2929 if (!r_refdef.viewcache.entityvisible[i])
2931 ent = r_refdef.scene.entities[i];
2932 r_refdef.stats.entities++;
2933 if (ent->model && ent->model->Draw != NULL)
2934 ent->model->Draw(ent);
2940 static void R_DrawModelsDepth(void)
2943 entity_render_t *ent;
2945 if (!r_drawentities.integer)
2948 for (i = 0;i < r_refdef.scene.numentities;i++)
2950 if (!r_refdef.viewcache.entityvisible[i])
2952 ent = r_refdef.scene.entities[i];
2953 if (ent->model && ent->model->DrawDepth != NULL)
2954 ent->model->DrawDepth(ent);
2958 static void R_DrawModelsDebug(void)
2961 entity_render_t *ent;
2963 if (!r_drawentities.integer)
2966 for (i = 0;i < r_refdef.scene.numentities;i++)
2968 if (!r_refdef.viewcache.entityvisible[i])
2970 ent = r_refdef.scene.entities[i];
2971 if (ent->model && ent->model->DrawDebug != NULL)
2972 ent->model->DrawDebug(ent);
2976 static void R_DrawModelsAddWaterPlanes(void)
2979 entity_render_t *ent;
2981 if (!r_drawentities.integer)
2984 for (i = 0;i < r_refdef.scene.numentities;i++)
2986 if (!r_refdef.viewcache.entityvisible[i])
2988 ent = r_refdef.scene.entities[i];
2989 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2990 ent->model->DrawAddWaterPlanes(ent);
2994 static void R_View_SetFrustum(void)
2997 double slopex, slopey;
2998 vec3_t forward, left, up, origin;
3000 // we can't trust r_refdef.view.forward and friends in reflected scenes
3001 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3004 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3005 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3006 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3007 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3008 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3009 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3010 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3011 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3012 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3013 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3014 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3015 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3019 zNear = r_refdef.nearclip;
3020 nudge = 1.0 - 1.0 / (1<<23);
3021 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3022 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3023 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3024 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3025 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3026 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3027 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3028 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3034 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3035 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3036 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3037 r_refdef.view.frustum[0].dist = m[15] - m[12];
3039 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3040 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3041 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3042 r_refdef.view.frustum[1].dist = m[15] + m[12];
3044 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3045 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3046 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3047 r_refdef.view.frustum[2].dist = m[15] - m[13];
3049 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3050 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3051 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3052 r_refdef.view.frustum[3].dist = m[15] + m[13];
3054 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3055 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3056 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3057 r_refdef.view.frustum[4].dist = m[15] - m[14];
3059 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3060 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3061 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3062 r_refdef.view.frustum[5].dist = m[15] + m[14];
3065 if (r_refdef.view.useperspective)
3067 slopex = 1.0 / r_refdef.view.frustum_x;
3068 slopey = 1.0 / r_refdef.view.frustum_y;
3069 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3070 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3071 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3072 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3073 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3075 // Leaving those out was a mistake, those were in the old code, and they
3076 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3077 // I couldn't reproduce it after adding those normalizations. --blub
3078 VectorNormalize(r_refdef.view.frustum[0].normal);
3079 VectorNormalize(r_refdef.view.frustum[1].normal);
3080 VectorNormalize(r_refdef.view.frustum[2].normal);
3081 VectorNormalize(r_refdef.view.frustum[3].normal);
3083 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3084 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
3085 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
3086 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
3087 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
3089 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3090 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3091 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3092 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3093 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3097 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3098 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3099 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3100 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3101 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3102 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3103 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3104 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3105 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3106 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3108 r_refdef.view.numfrustumplanes = 5;
3110 if (r_refdef.view.useclipplane)
3112 r_refdef.view.numfrustumplanes = 6;
3113 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3116 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3117 PlaneClassify(r_refdef.view.frustum + i);
3119 // LordHavoc: note to all quake engine coders, Quake had a special case
3120 // for 90 degrees which assumed a square view (wrong), so I removed it,
3121 // Quake2 has it disabled as well.
3123 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3124 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3125 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3126 //PlaneClassify(&frustum[0]);
3128 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3129 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3130 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3131 //PlaneClassify(&frustum[1]);
3133 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3134 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3135 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3136 //PlaneClassify(&frustum[2]);
3138 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3139 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3140 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3141 //PlaneClassify(&frustum[3]);
3144 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3145 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3146 //PlaneClassify(&frustum[4]);
3149 void R_View_Update(void)
3151 R_View_SetFrustum();
3152 R_View_WorldVisibility(r_refdef.view.useclipplane);
3153 R_View_UpdateEntityVisible();
3154 R_View_UpdateEntityLighting();
3157 void R_SetupView(qboolean allowwaterclippingplane)
3159 if (!r_refdef.view.useperspective)
3160 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);
3161 else if (gl_stencil && r_useinfinitefarclip.integer)
3162 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
3164 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
3166 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
3168 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3170 // LordHavoc: couldn't figure out how to make this approach the
3171 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3172 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3173 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3174 dist = r_refdef.view.clipplane.dist;
3175 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
3179 void R_ResetViewRendering2D(void)
3183 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3184 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3185 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
3186 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3187 GL_Color(1, 1, 1, 1);
3188 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3189 GL_BlendFunc(GL_ONE, GL_ZERO);
3190 GL_AlphaTest(false);
3191 GL_ScissorTest(false);
3192 GL_DepthMask(false);
3193 GL_DepthRange(0, 1);
3194 GL_DepthTest(false);
3195 R_Mesh_Matrix(&identitymatrix);
3196 R_Mesh_ResetTextureState();
3197 GL_PolygonOffset(0, 0);
3198 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3199 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3200 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3201 qglStencilMask(~0);CHECKGLERROR
3202 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3203 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3204 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3205 R_SetupGenericShader(true);
3208 void R_ResetViewRendering3D(void)
3212 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3213 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3215 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3216 GL_Color(1, 1, 1, 1);
3217 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3218 GL_BlendFunc(GL_ONE, GL_ZERO);
3219 GL_AlphaTest(false);
3220 GL_ScissorTest(true);
3222 GL_DepthRange(0, 1);
3224 R_Mesh_Matrix(&identitymatrix);
3225 R_Mesh_ResetTextureState();
3226 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3227 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3228 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3229 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3230 qglStencilMask(~0);CHECKGLERROR
3231 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3232 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3233 GL_CullFace(r_refdef.view.cullface_back);
3234 R_SetupGenericShader(true);
3237 void R_RenderScene(void);
3238 void R_RenderWaterPlanes(void);
3240 static void R_Water_StartFrame(void)
3243 int waterwidth, waterheight, texturewidth, textureheight;
3244 r_waterstate_waterplane_t *p;
3246 // set waterwidth and waterheight to the water resolution that will be
3247 // used (often less than the screen resolution for faster rendering)
3248 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3249 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3251 // calculate desired texture sizes
3252 // can't use water if the card does not support the texture size
3253 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3254 texturewidth = textureheight = waterwidth = waterheight = 0;
3255 else if (gl_support_arb_texture_non_power_of_two)
3257 texturewidth = waterwidth;
3258 textureheight = waterheight;
3262 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3263 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3266 // allocate textures as needed
3267 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3269 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3270 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3272 if (p->texture_refraction)
3273 R_FreeTexture(p->texture_refraction);
3274 p->texture_refraction = NULL;
3275 if (p->texture_reflection)
3276 R_FreeTexture(p->texture_reflection);
3277 p->texture_reflection = NULL;
3279 memset(&r_waterstate, 0, sizeof(r_waterstate));
3280 r_waterstate.waterwidth = waterwidth;
3281 r_waterstate.waterheight = waterheight;
3282 r_waterstate.texturewidth = texturewidth;
3283 r_waterstate.textureheight = textureheight;
3286 if (r_waterstate.waterwidth)
3288 r_waterstate.enabled = true;
3290 // set up variables that will be used in shader setup
3291 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3292 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3293 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3294 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3297 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3298 r_waterstate.numwaterplanes = 0;
3301 void R_Water_AddWaterPlane(msurface_t *surface)
3303 int triangleindex, planeindex;
3309 r_waterstate_waterplane_t *p;
3310 texture_t *t = R_GetCurrentTexture(surface->texture);
3311 // just use the first triangle with a valid normal for any decisions
3312 VectorClear(normal);
3313 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3315 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3316 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3317 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3318 TriangleNormal(vert[0], vert[1], vert[2], normal);
3319 if (VectorLength2(normal) >= 0.001)
3323 VectorCopy(normal, plane.normal);
3324 VectorNormalize(plane.normal);
3325 plane.dist = DotProduct(vert[0], plane.normal);
3326 PlaneClassify(&plane);
3327 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3329 // skip backfaces (except if nocullface is set)
3330 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3332 VectorNegate(plane.normal, plane.normal);
3334 PlaneClassify(&plane);
3338 // find a matching plane if there is one
3339 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3340 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3342 if (planeindex >= r_waterstate.maxwaterplanes)
3343 return; // nothing we can do, out of planes
3345 // if this triangle does not fit any known plane rendered this frame, add one
3346 if (planeindex >= r_waterstate.numwaterplanes)
3348 // store the new plane
3349 r_waterstate.numwaterplanes++;
3351 // clear materialflags and pvs
3352 p->materialflags = 0;
3353 p->pvsvalid = false;
3355 // merge this surface's materialflags into the waterplane
3356 p->materialflags |= t->currentmaterialflags;
3357 // merge this surface's PVS into the waterplane
3358 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3359 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3360 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3362 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3367 static void R_Water_ProcessPlanes(void)
3369 r_refdef_view_t originalview;
3370 r_refdef_view_t myview;
3372 r_waterstate_waterplane_t *p;
3374 originalview = r_refdef.view;
3376 // make sure enough textures are allocated
3377 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3379 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3381 if (!p->texture_refraction)
3382 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);
3383 if (!p->texture_refraction)
3387 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3389 if (!p->texture_reflection)
3390 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);
3391 if (!p->texture_reflection)
3397 r_refdef.view = originalview;
3398 r_refdef.view.showdebug = false;
3399 r_refdef.view.width = r_waterstate.waterwidth;
3400 r_refdef.view.height = r_waterstate.waterheight;
3401 r_refdef.view.useclipplane = true;
3402 myview = r_refdef.view;
3403 r_waterstate.renderingscene = true;
3404 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3406 // render the normal view scene and copy into texture
3407 // (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)
3408 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3410 r_refdef.view = myview;
3411 r_refdef.view.clipplane = p->plane;
3412 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3413 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3414 PlaneClassify(&r_refdef.view.clipplane);
3416 R_ResetViewRendering3D();
3417 R_ClearScreen(r_refdef.fogenabled);
3421 // copy view into the screen texture
3422 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3423 GL_ActiveTexture(0);
3425 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
3428 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3430 r_refdef.view = myview;
3431 // render reflected scene and copy into texture
3432 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3433 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3434 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3435 r_refdef.view.clipplane = p->plane;
3436 // reverse the cullface settings for this render
3437 r_refdef.view.cullface_front = GL_FRONT;
3438 r_refdef.view.cullface_back = GL_BACK;
3439 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3441 r_refdef.view.usecustompvs = true;
3443 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3445 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3448 R_ResetViewRendering3D();
3449 R_ClearScreen(r_refdef.fogenabled);
3453 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3454 GL_ActiveTexture(0);
3456 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
3459 r_waterstate.renderingscene = false;
3460 r_refdef.view = originalview;
3461 R_ResetViewRendering3D();
3462 R_ClearScreen(r_refdef.fogenabled);
3466 r_refdef.view = originalview;
3467 r_waterstate.renderingscene = false;
3468 Cvar_SetValueQuick(&r_water, 0);
3469 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3473 void R_Bloom_StartFrame(void)
3475 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3477 // set bloomwidth and bloomheight to the bloom resolution that will be
3478 // used (often less than the screen resolution for faster rendering)
3479 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3480 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3481 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3482 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3483 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3485 // calculate desired texture sizes
3486 if (gl_support_arb_texture_non_power_of_two)
3488 screentexturewidth = r_refdef.view.width;
3489 screentextureheight = r_refdef.view.height;
3490 bloomtexturewidth = r_bloomstate.bloomwidth;
3491 bloomtextureheight = r_bloomstate.bloomheight;
3495 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3496 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3497 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3498 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3501 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))
3503 Cvar_SetValueQuick(&r_hdr, 0);
3504 Cvar_SetValueQuick(&r_bloom, 0);
3505 Cvar_SetValueQuick(&r_motionblur, 0);
3506 Cvar_SetValueQuick(&r_damageblur, 0);
3509 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)))
3510 screentexturewidth = screentextureheight = 0;
3511 if (!r_hdr.integer && !r_bloom.integer)
3512 bloomtexturewidth = bloomtextureheight = 0;
3514 // allocate textures as needed
3515 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3517 if (r_bloomstate.texture_screen)
3518 R_FreeTexture(r_bloomstate.texture_screen);
3519 r_bloomstate.texture_screen = NULL;
3520 r_bloomstate.screentexturewidth = screentexturewidth;
3521 r_bloomstate.screentextureheight = screentextureheight;
3522 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3523 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);
3525 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3527 if (r_bloomstate.texture_bloom)
3528 R_FreeTexture(r_bloomstate.texture_bloom);
3529 r_bloomstate.texture_bloom = NULL;
3530 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3531 r_bloomstate.bloomtextureheight = bloomtextureheight;
3532 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3533 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);
3536 // set up a texcoord array for the full resolution screen image
3537 // (we have to keep this around to copy back during final render)
3538 r_bloomstate.screentexcoord2f[0] = 0;
3539 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3540 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3541 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3542 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3543 r_bloomstate.screentexcoord2f[5] = 0;
3544 r_bloomstate.screentexcoord2f[6] = 0;
3545 r_bloomstate.screentexcoord2f[7] = 0;
3547 // set up a texcoord array for the reduced resolution bloom image
3548 // (which will be additive blended over the screen image)
3549 r_bloomstate.bloomtexcoord2f[0] = 0;
3550 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3551 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3552 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3553 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3554 r_bloomstate.bloomtexcoord2f[5] = 0;
3555 r_bloomstate.bloomtexcoord2f[6] = 0;
3556 r_bloomstate.bloomtexcoord2f[7] = 0;
3558 if (r_hdr.integer || r_bloom.integer)
3560 r_bloomstate.enabled = true;
3561 r_bloomstate.hdr = r_hdr.integer != 0;
3565 void R_Bloom_CopyBloomTexture(float colorscale)
3567 r_refdef.stats.bloom++;
3569 // scale down screen texture to the bloom texture size
3571 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3572 GL_BlendFunc(GL_ONE, GL_ZERO);
3573 GL_Color(colorscale, colorscale, colorscale, 1);
3574 // TODO: optimize with multitexture or GLSL
3575 R_SetupGenericShader(true);
3576 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3577 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3578 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3579 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3581 // we now have a bloom image in the framebuffer
3582 // copy it into the bloom image texture for later processing
3583 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3584 GL_ActiveTexture(0);
3586 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
3587 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3590 void R_Bloom_CopyHDRTexture(void)
3592 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3593 GL_ActiveTexture(0);
3595 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
3596 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3599 void R_Bloom_MakeTexture(void)
3602 float xoffset, yoffset, r, brighten;
3604 r_refdef.stats.bloom++;
3606 R_ResetViewRendering2D();
3607 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3608 R_Mesh_ColorPointer(NULL, 0, 0);
3609 R_SetupGenericShader(true);
3611 // we have a bloom image in the framebuffer
3613 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3615 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3618 r = bound(0, r_bloom_colorexponent.value / x, 1);
3619 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3620 GL_Color(r, r, r, 1);
3621 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3622 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3623 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3624 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3626 // copy the vertically blurred bloom view to a texture
3627 GL_ActiveTexture(0);
3629 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
3630 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3633 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3634 brighten = r_bloom_brighten.value;
3636 brighten *= r_hdr_range.value;
3637 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3638 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3640 for (dir = 0;dir < 2;dir++)
3642 // blend on at multiple vertical offsets to achieve a vertical blur
3643 // TODO: do offset blends using GLSL
3644 GL_BlendFunc(GL_ONE, GL_ZERO);
3645 for (x = -range;x <= range;x++)
3647 if (!dir){xoffset = 0;yoffset = x;}
3648 else {xoffset = x;yoffset = 0;}
3649 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3650 yoffset /= (float)r_bloomstate.bloomtextureheight;
3651 // compute a texcoord array with the specified x and y offset
3652 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3653 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3654 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3655 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3656 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3657 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3658 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3659 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3660 // this r value looks like a 'dot' particle, fading sharply to
3661 // black at the edges
3662 // (probably not realistic but looks good enough)
3663 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3664 //r = (dir ? 1.0f : brighten)/(range*2+1);
3665 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3666 GL_Color(r, r, r, 1);
3667 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3668 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3669 GL_BlendFunc(GL_ONE, GL_ONE);
3672 // copy the vertically blurred bloom view to a texture
3673 GL_ActiveTexture(0);
3675 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
3676 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3679 // apply subtract last
3680 // (just like it would be in a GLSL shader)
3681 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3683 GL_BlendFunc(GL_ONE, GL_ZERO);
3684 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3685 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3686 GL_Color(1, 1, 1, 1);
3687 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3688 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3690 GL_BlendFunc(GL_ONE, GL_ONE);
3691 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3692 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3693 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3694 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3695 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3696 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3697 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3699 // copy the darkened bloom view to a texture
3700 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3701 GL_ActiveTexture(0);
3703 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
3704 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3708 void R_HDR_RenderBloomTexture(void)
3710 int oldwidth, oldheight;
3711 float oldcolorscale;
3713 oldcolorscale = r_refdef.view.colorscale;
3714 oldwidth = r_refdef.view.width;
3715 oldheight = r_refdef.view.height;
3716 r_refdef.view.width = r_bloomstate.bloomwidth;
3717 r_refdef.view.height = r_bloomstate.bloomheight;
3719 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3720 // TODO: add exposure compensation features
3721 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
3723 r_refdef.view.showdebug = false;
3724 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3726 R_ResetViewRendering3D();
3728 R_ClearScreen(r_refdef.fogenabled);
3729 if (r_timereport_active)
3730 R_TimeReport("HDRclear");
3733 if (r_timereport_active)
3734 R_TimeReport("visibility");
3736 r_waterstate.numwaterplanes = 0;
3737 if (r_waterstate.enabled)
3738 R_RenderWaterPlanes();
3740 r_refdef.view.showdebug = true;
3742 r_waterstate.numwaterplanes = 0;
3744 R_ResetViewRendering2D();
3746 R_Bloom_CopyHDRTexture();
3747 R_Bloom_MakeTexture();
3749 // restore the view settings
3750 r_refdef.view.width = oldwidth;
3751 r_refdef.view.height = oldheight;
3752 r_refdef.view.colorscale = oldcolorscale;
3754 R_ResetViewRendering3D();
3756 R_ClearScreen(r_refdef.fogenabled);
3757 if (r_timereport_active)
3758 R_TimeReport("viewclear");
3761 static void R_BlendView(void)
3763 if (r_bloomstate.texture_screen)
3765 // make sure the buffer is available
3766 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
3768 R_ResetViewRendering2D();
3769 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3770 R_Mesh_ColorPointer(NULL, 0, 0);
3771 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3772 GL_ActiveTexture(0);CHECKGLERROR
3774 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
3776 // declare variables
3778 static float avgspeed;
3780 speed = VectorLength(cl.movement_velocity);
3782 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
3783 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
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
3790 cl.motionbluralpha = 1 - exp(-
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 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
3801 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
3803 if (cl.motionbluralpha > 0)
3805 R_SetupGenericShader(true);
3806 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3807 GL_Color(1, 1, 1, cl.motionbluralpha);
3808 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3809 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3810 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3811 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3815 // copy view into the screen texture
3816 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
3817 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3820 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3822 unsigned int permutation =
3823 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3824 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3825 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3826 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
3827 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
3829 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3831 // render simple bloom effect
3832 // copy the screen and shrink it and darken it for the bloom process
3833 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3834 // make the bloom texture
3835 R_Bloom_MakeTexture();
3838 R_ResetViewRendering2D();
3839 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3840 R_Mesh_ColorPointer(NULL, 0, 0);
3841 GL_Color(1, 1, 1, 1);
3842 GL_BlendFunc(GL_ONE, GL_ZERO);
3843 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3844 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3845 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3846 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3847 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3848 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3849 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3850 if (r_glsl_permutation->loc_TintColor >= 0)
3851 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3852 if (r_glsl_permutation->loc_ClientTime >= 0)
3853 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3854 if (r_glsl_permutation->loc_PixelSize >= 0)
3855 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3856 if (r_glsl_permutation->loc_UserVec1 >= 0)
3858 float a=0, b=0, c=0, d=0;
3859 #if _MSC_VER >= 1400
3860 #define sscanf sscanf_s
3862 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3863 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3865 if (r_glsl_permutation->loc_UserVec2 >= 0)
3867 float a=0, b=0, c=0, d=0;
3868 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3869 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3871 if (r_glsl_permutation->loc_UserVec3 >= 0)
3873 float a=0, b=0, c=0, d=0;
3874 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3875 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3877 if (r_glsl_permutation->loc_UserVec4 >= 0)
3879 float a=0, b=0, c=0, d=0;
3880 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3881 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3883 if (r_glsl_permutation->loc_Saturation >= 0)
3884 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
3885 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3886 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3892 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3894 // render high dynamic range bloom effect
3895 // the bloom texture was made earlier this render, so we just need to
3896 // blend it onto the screen...
3897 R_ResetViewRendering2D();
3898 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3899 R_Mesh_ColorPointer(NULL, 0, 0);
3900 R_SetupGenericShader(true);
3901 GL_Color(1, 1, 1, 1);
3902 GL_BlendFunc(GL_ONE, GL_ONE);
3903 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3904 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3905 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3906 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3908 else if (r_bloomstate.texture_bloom)
3910 // render simple bloom effect
3911 // copy the screen and shrink it and darken it for the bloom process
3912 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3913 // make the bloom texture
3914 R_Bloom_MakeTexture();
3915 // put the original screen image back in place and blend the bloom
3917 R_ResetViewRendering2D();
3918 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3919 R_Mesh_ColorPointer(NULL, 0, 0);
3920 GL_Color(1, 1, 1, 1);
3921 GL_BlendFunc(GL_ONE, GL_ZERO);
3922 // do both in one pass if possible
3923 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3924 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3925 if (r_textureunits.integer >= 2 && gl_combine.integer)
3927 R_SetupGenericTwoTextureShader(GL_ADD);
3928 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3929 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3933 R_SetupGenericShader(true);
3934 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3935 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3936 // now blend on the bloom texture
3937 GL_BlendFunc(GL_ONE, GL_ONE);
3938 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3939 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3941 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3942 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3944 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3946 // apply a color tint to the whole view
3947 R_ResetViewRendering2D();
3948 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3949 R_Mesh_ColorPointer(NULL, 0, 0);
3950 R_SetupGenericShader(false);
3951 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3952 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3953 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3957 matrix4x4_t r_waterscrollmatrix;
3959 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3961 if (r_refdef.fog_density)
3963 r_refdef.fogcolor[0] = r_refdef.fog_red;
3964 r_refdef.fogcolor[1] = r_refdef.fog_green;
3965 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3969 VectorCopy(r_refdef.fogcolor, fogvec);
3970 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3972 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3973 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3974 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3975 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3977 // color.rgb *= ContrastBoost * SceneBrightness;
3978 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3979 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3980 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3981 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3986 void R_UpdateVariables(void)
3990 r_refdef.scene.ambient = r_ambient.value;
3992 r_refdef.farclip = 4096;
3993 if (r_refdef.scene.worldmodel)
3994 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3995 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3997 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3998 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3999 r_refdef.polygonfactor = 0;
4000 r_refdef.polygonoffset = 0;
4001 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4002 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4004 r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
4005 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4006 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4007 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4008 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4009 if (r_showsurfaces.integer)
4011 r_refdef.scene.rtworld = false;
4012 r_refdef.scene.rtworldshadows = false;
4013 r_refdef.scene.rtdlight = false;
4014 r_refdef.scene.rtdlightshadows = false;
4015 r_refdef.lightmapintensity = 0;
4018 if (gamemode == GAME_NEHAHRA)
4020 if (gl_fogenable.integer)
4022 r_refdef.oldgl_fogenable = true;
4023 r_refdef.fog_density = gl_fogdensity.value;
4024 r_refdef.fog_red = gl_fogred.value;
4025 r_refdef.fog_green = gl_foggreen.value;
4026 r_refdef.fog_blue = gl_fogblue.value;
4027 r_refdef.fog_alpha = 1;
4028 r_refdef.fog_start = 0;
4029 r_refdef.fog_end = gl_skyclip.value;
4031 else if (r_refdef.oldgl_fogenable)
4033 r_refdef.oldgl_fogenable = false;
4034 r_refdef.fog_density = 0;
4035 r_refdef.fog_red = 0;
4036 r_refdef.fog_green = 0;
4037 r_refdef.fog_blue = 0;
4038 r_refdef.fog_alpha = 0;
4039 r_refdef.fog_start = 0;
4040 r_refdef.fog_end = 0;
4044 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4045 r_refdef.fog_start = max(0, r_refdef.fog_start);
4046 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4048 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4050 if (r_refdef.fog_density && r_drawfog.integer)
4052 r_refdef.fogenabled = true;
4053 // this is the point where the fog reaches 0.9986 alpha, which we
4054 // consider a good enough cutoff point for the texture
4055 // (0.9986 * 256 == 255.6)
4056 if (r_fog_exp2.integer)
4057 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4059 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4060 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4061 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4062 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4063 // fog color was already set
4064 // update the fog texture
4065 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)
4066 R_BuildFogTexture();
4069 r_refdef.fogenabled = false;
4071 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4073 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4075 // build GLSL gamma texture
4076 #define RAMPWIDTH 256
4077 unsigned short ramp[RAMPWIDTH * 3];
4078 unsigned char rampbgr[RAMPWIDTH][4];
4081 r_texture_gammaramps_serial = vid_gammatables_serial;
4083 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4084 for(i = 0; i < RAMPWIDTH; ++i)
4086 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4087 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4088 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4091 if (r_texture_gammaramps)
4093 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4097 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);
4103 // remove GLSL gamma texture
4107 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4108 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4114 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4115 if( scenetype != r_currentscenetype ) {
4116 // store the old scenetype
4117 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4118 r_currentscenetype = scenetype;
4119 // move in the new scene
4120 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4129 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4131 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4132 if( scenetype == r_currentscenetype ) {
4133 return &r_refdef.scene;
4135 return &r_scenes_store[ scenetype ];
4144 void R_RenderView(void)
4146 r_frame++; // used only by R_GetCurrentTexture
4147 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4149 R_AnimCache_NewFrame();
4151 if (r_refdef.view.isoverlay)
4153 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4154 GL_Clear( GL_DEPTH_BUFFER_BIT );
4155 R_TimeReport("depthclear");
4157 r_refdef.view.showdebug = false;
4159 r_waterstate.enabled = false;
4160 r_waterstate.numwaterplanes = 0;
4168 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4169 return; //Host_Error ("R_RenderView: NULL worldmodel");
4171 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4173 // break apart the view matrix into vectors for various purposes
4174 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4175 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4176 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4177 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4178 // make an inverted copy of the view matrix for tracking sprites
4179 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4181 R_Shadow_UpdateWorldLightSelection();
4183 R_Bloom_StartFrame();
4184 R_Water_StartFrame();
4187 if (r_timereport_active)
4188 R_TimeReport("viewsetup");
4190 R_ResetViewRendering3D();
4192 if (r_refdef.view.clear || r_refdef.fogenabled)
4194 R_ClearScreen(r_refdef.fogenabled);
4195 if (r_timereport_active)
4196 R_TimeReport("viewclear");
4198 r_refdef.view.clear = true;
4200 // this produces a bloom texture to be used in R_BlendView() later
4202 R_HDR_RenderBloomTexture();
4204 r_refdef.view.showdebug = true;
4207 if (r_timereport_active)
4208 R_TimeReport("visibility");
4210 r_waterstate.numwaterplanes = 0;
4211 if (r_waterstate.enabled)
4212 R_RenderWaterPlanes();
4215 r_waterstate.numwaterplanes = 0;
4218 if (r_timereport_active)
4219 R_TimeReport("blendview");
4221 GL_Scissor(0, 0, vid.width, vid.height);
4222 GL_ScissorTest(false);
4226 void R_RenderWaterPlanes(void)
4228 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4230 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4231 if (r_timereport_active)
4232 R_TimeReport("waterworld");
4235 // don't let sound skip if going slow
4236 if (r_refdef.scene.extraupdate)
4239 R_DrawModelsAddWaterPlanes();
4240 if (r_timereport_active)
4241 R_TimeReport("watermodels");
4243 if (r_waterstate.numwaterplanes)
4245 R_Water_ProcessPlanes();
4246 if (r_timereport_active)
4247 R_TimeReport("waterscenes");
4251 extern void R_DrawLightningBeams (void);
4252 extern void VM_CL_AddPolygonsToMeshQueue (void);
4253 extern void R_DrawPortals (void);
4254 extern cvar_t cl_locs_show;
4255 static void R_DrawLocs(void);
4256 static void R_DrawEntityBBoxes(void);
4257 void R_RenderScene(void)
4259 r_refdef.stats.renders++;
4263 // don't let sound skip if going slow
4264 if (r_refdef.scene.extraupdate)
4267 R_MeshQueue_BeginScene();
4271 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);
4273 if (cl.csqc_vidvars.drawworld)
4275 // don't let sound skip if going slow
4276 if (r_refdef.scene.extraupdate)
4279 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4281 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4282 if (r_timereport_active)
4283 R_TimeReport("worldsky");
4286 if (R_DrawBrushModelsSky() && r_timereport_active)
4287 R_TimeReport("bmodelsky");
4290 R_AnimCache_CacheVisibleEntities();
4292 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4294 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4295 if (r_timereport_active)
4296 R_TimeReport("worlddepth");
4298 if (r_depthfirst.integer >= 2)
4300 R_DrawModelsDepth();
4301 if (r_timereport_active)
4302 R_TimeReport("modeldepth");
4305 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4307 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4308 if (r_timereport_active)
4309 R_TimeReport("world");
4312 // don't let sound skip if going slow
4313 if (r_refdef.scene.extraupdate)
4317 if (r_timereport_active)
4318 R_TimeReport("models");
4320 // don't let sound skip if going slow
4321 if (r_refdef.scene.extraupdate)
4324 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
4326 R_DrawModelShadows();
4328 R_ResetViewRendering3D();
4330 // don't let sound skip if going slow
4331 if (r_refdef.scene.extraupdate)
4335 R_ShadowVolumeLighting(false);
4336 if (r_timereport_active)
4337 R_TimeReport("rtlights");
4339 // don't let sound skip if going slow
4340 if (r_refdef.scene.extraupdate)
4343 if (cl.csqc_vidvars.drawworld)
4345 R_DrawLightningBeams();
4346 if (r_timereport_active)
4347 R_TimeReport("lightning");
4350 if (r_timereport_active)
4351 R_TimeReport("decals");
4354 if (r_timereport_active)
4355 R_TimeReport("particles");
4358 if (r_timereport_active)
4359 R_TimeReport("explosions");
4362 R_SetupGenericShader(true);
4363 VM_CL_AddPolygonsToMeshQueue();
4365 if (r_refdef.view.showdebug)
4367 if (cl_locs_show.integer)
4370 if (r_timereport_active)
4371 R_TimeReport("showlocs");
4374 if (r_drawportals.integer)
4377 if (r_timereport_active)
4378 R_TimeReport("portals");
4381 if (r_showbboxes.value > 0)
4383 R_DrawEntityBBoxes();
4384 if (r_timereport_active)
4385 R_TimeReport("bboxes");
4389 R_SetupGenericShader(true);
4390 R_MeshQueue_RenderTransparent();
4391 if (r_timereport_active)
4392 R_TimeReport("drawtrans");
4394 R_SetupGenericShader(true);
4396 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))
4398 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4399 if (r_timereport_active)
4400 R_TimeReport("worlddebug");
4401 R_DrawModelsDebug();
4402 if (r_timereport_active)
4403 R_TimeReport("modeldebug");
4406 R_SetupGenericShader(true);
4408 if (cl.csqc_vidvars.drawworld)
4411 if (r_timereport_active)
4412 R_TimeReport("coronas");
4415 // don't let sound skip if going slow
4416 if (r_refdef.scene.extraupdate)
4419 R_ResetViewRendering2D();
4422 static const unsigned short bboxelements[36] =
4432 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4435 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4436 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4437 GL_DepthMask(false);
4438 GL_DepthRange(0, 1);
4439 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4440 R_Mesh_Matrix(&identitymatrix);
4441 R_Mesh_ResetTextureState();
4443 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4444 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4445 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4446 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4447 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4448 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4449 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4450 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4451 R_FillColors(color4f, 8, cr, cg, cb, ca);
4452 if (r_refdef.fogenabled)
4454 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4456 f1 = FogPoint_World(v);
4458 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4459 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4460 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4463 R_Mesh_VertexPointer(vertex3f, 0, 0);
4464 R_Mesh_ColorPointer(color4f, 0, 0);
4465 R_Mesh_ResetTextureState();
4466 R_SetupGenericShader(false);
4467 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4470 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4474 prvm_edict_t *edict;
4475 prvm_prog_t *prog_save = prog;
4477 // this function draws bounding boxes of server entities
4481 GL_CullFace(GL_NONE);
4482 R_SetupGenericShader(false);
4486 for (i = 0;i < numsurfaces;i++)
4488 edict = PRVM_EDICT_NUM(surfacelist[i]);
4489 switch ((int)edict->fields.server->solid)
4491 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4492 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4493 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4494 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4495 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4496 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4498 color[3] *= r_showbboxes.value;
4499 color[3] = bound(0, color[3], 1);
4500 GL_DepthTest(!r_showdisabledepthtest.integer);
4501 GL_CullFace(r_refdef.view.cullface_front);
4502 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4508 static void R_DrawEntityBBoxes(void)
4511 prvm_edict_t *edict;
4513 prvm_prog_t *prog_save = prog;
4515 // this function draws bounding boxes of server entities
4521 for (i = 0;i < prog->num_edicts;i++)
4523 edict = PRVM_EDICT_NUM(i);
4524 if (edict->priv.server->free)
4526 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4527 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4529 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4531 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4532 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4538 unsigned short nomodelelements[24] =
4550 float nomodelvertex3f[6*3] =
4560 float nomodelcolor4f[6*4] =
4562 0.0f, 0.0f, 0.5f, 1.0f,
4563 0.0f, 0.0f, 0.5f, 1.0f,
4564 0.0f, 0.5f, 0.0f, 1.0f,
4565 0.0f, 0.5f, 0.0f, 1.0f,
4566 0.5f, 0.0f, 0.0f, 1.0f,
4567 0.5f, 0.0f, 0.0f, 1.0f
4570 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4575 // this is only called once per entity so numsurfaces is always 1, and
4576 // surfacelist is always {0}, so this code does not handle batches
4577 R_Mesh_Matrix(&ent->matrix);
4579 if (ent->flags & EF_ADDITIVE)
4581 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4582 GL_DepthMask(false);
4584 else if (ent->alpha < 1)
4586 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4587 GL_DepthMask(false);
4591 GL_BlendFunc(GL_ONE, GL_ZERO);
4594 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4595 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4596 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4597 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4598 R_SetupGenericShader(false);
4599 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4600 if (r_refdef.fogenabled)
4603 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4604 R_Mesh_ColorPointer(color4f, 0, 0);
4605 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4606 f1 = FogPoint_World(org);
4608 for (i = 0, c = color4f;i < 6;i++, c += 4)
4610 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4611 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4612 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4616 else if (ent->alpha != 1)
4618 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4619 R_Mesh_ColorPointer(color4f, 0, 0);
4620 for (i = 0, c = color4f;i < 6;i++, c += 4)
4624 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4625 R_Mesh_ResetTextureState();
4626 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4629 void R_DrawNoModel(entity_render_t *ent)
4632 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4633 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4634 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4636 // R_DrawNoModelCallback(ent, 0);
4639 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4641 vec3_t right1, right2, diff, normal;
4643 VectorSubtract (org2, org1, normal);
4645 // calculate 'right' vector for start
4646 VectorSubtract (r_refdef.view.origin, org1, diff);
4647 CrossProduct (normal, diff, right1);
4648 VectorNormalize (right1);
4650 // calculate 'right' vector for end
4651 VectorSubtract (r_refdef.view.origin, org2, diff);
4652 CrossProduct (normal, diff, right2);
4653 VectorNormalize (right2);
4655 vert[ 0] = org1[0] + width * right1[0];
4656 vert[ 1] = org1[1] + width * right1[1];
4657 vert[ 2] = org1[2] + width * right1[2];
4658 vert[ 3] = org1[0] - width * right1[0];
4659 vert[ 4] = org1[1] - width * right1[1];
4660 vert[ 5] = org1[2] - width * right1[2];
4661 vert[ 6] = org2[0] - width * right2[0];
4662 vert[ 7] = org2[1] - width * right2[1];
4663 vert[ 8] = org2[2] - width * right2[2];
4664 vert[ 9] = org2[0] + width * right2[0];
4665 vert[10] = org2[1] + width * right2[1];
4666 vert[11] = org2[2] + width * right2[2];
4669 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4671 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)
4673 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4677 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4678 fog = FogPoint_World(origin);
4680 R_Mesh_Matrix(&identitymatrix);
4681 GL_BlendFunc(blendfunc1, blendfunc2);
4683 GL_CullFace(GL_NONE);
4685 GL_DepthMask(false);
4686 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4687 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4688 GL_DepthTest(!depthdisable);
4690 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4691 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4692 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4693 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4694 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4695 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4696 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4697 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4698 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4699 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4700 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4701 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4703 R_Mesh_VertexPointer(vertex3f, 0, 0);
4704 R_Mesh_ColorPointer(NULL, 0, 0);
4705 R_Mesh_ResetTextureState();
4706 R_SetupGenericShader(true);
4707 R_Mesh_TexBind(0, R_GetTexture(texture));
4708 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4709 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4710 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4711 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4713 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4715 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4716 GL_BlendFunc(blendfunc1, GL_ONE);
4718 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4719 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4723 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4728 VectorSet(v, x, y, z);
4729 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4730 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4732 if (i == mesh->numvertices)
4734 if (mesh->numvertices < mesh->maxvertices)
4736 VectorCopy(v, vertex3f);
4737 mesh->numvertices++;
4739 return mesh->numvertices;
4745 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4749 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4750 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4751 e = mesh->element3i + mesh->numtriangles * 3;
4752 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4754 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4755 if (mesh->numtriangles < mesh->maxtriangles)
4760 mesh->numtriangles++;
4762 element[1] = element[2];
4766 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4770 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4771 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4772 e = mesh->element3i + mesh->numtriangles * 3;
4773 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4775 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4776 if (mesh->numtriangles < mesh->maxtriangles)
4781 mesh->numtriangles++;
4783 element[1] = element[2];
4787 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4788 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4790 int planenum, planenum2;
4793 mplane_t *plane, *plane2;
4795 double temppoints[2][256*3];
4796 // figure out how large a bounding box we need to properly compute this brush
4798 for (w = 0;w < numplanes;w++)
4799 maxdist = max(maxdist, planes[w].dist);
4800 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4801 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4802 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4806 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4807 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4809 if (planenum2 == planenum)
4811 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);
4814 if (tempnumpoints < 3)
4816 // generate elements forming a triangle fan for this polygon
4817 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4821 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)
4823 texturelayer_t *layer;
4824 layer = t->currentlayers + t->currentnumlayers++;
4826 layer->depthmask = depthmask;
4827 layer->blendfunc1 = blendfunc1;
4828 layer->blendfunc2 = blendfunc2;
4829 layer->texture = texture;
4830 layer->texmatrix = *matrix;
4831 layer->color[0] = r * r_refdef.view.colorscale;
4832 layer->color[1] = g * r_refdef.view.colorscale;
4833 layer->color[2] = b * r_refdef.view.colorscale;
4834 layer->color[3] = a;
4837 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4840 index = parms[2] + r_refdef.scene.time * parms[3];
4841 index -= floor(index);
4845 case Q3WAVEFUNC_NONE:
4846 case Q3WAVEFUNC_NOISE:
4847 case Q3WAVEFUNC_COUNT:
4850 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4851 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4852 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4853 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4854 case Q3WAVEFUNC_TRIANGLE:
4856 f = index - floor(index);
4867 return (float)(parms[0] + parms[1] * f);
4870 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
4875 matrix4x4_t matrix, temp;
4876 switch(tcmod->tcmod)
4880 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4881 matrix = r_waterscrollmatrix;
4883 matrix = identitymatrix;
4885 case Q3TCMOD_ENTITYTRANSLATE:
4886 // this is used in Q3 to allow the gamecode to control texcoord
4887 // scrolling on the entity, which is not supported in darkplaces yet.
4888 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4890 case Q3TCMOD_ROTATE:
4891 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4892 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4893 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4896 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4898 case Q3TCMOD_SCROLL:
4899 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4901 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4902 w = (int) tcmod->parms[0];
4903 h = (int) tcmod->parms[1];
4904 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4906 idx = (int) floor(f * w * h);
4907 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4909 case Q3TCMOD_STRETCH:
4910 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4911 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4913 case Q3TCMOD_TRANSFORM:
4914 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4915 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4916 VectorSet(tcmat + 6, 0 , 0 , 1);
4917 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4918 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4920 case Q3TCMOD_TURBULENT:
4921 // this is handled in the RSurf_PrepareVertices function
4922 matrix = identitymatrix;
4926 Matrix4x4_Concat(texmatrix, &matrix, &temp);
4929 texture_t *R_GetCurrentTexture(texture_t *t)
4932 const entity_render_t *ent = rsurface.entity;
4933 dp_model_t *model = ent->model;
4934 q3shaderinfo_layer_tcmod_t *tcmod;
4936 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
4937 return t->currentframe;
4938 t->update_lastrenderframe = r_frame;
4939 t->update_lastrenderentity = (void *)ent;
4941 // switch to an alternate material if this is a q1bsp animated material
4943 texture_t *texture = t;
4944 int s = ent->skinnum;
4945 if ((unsigned int)s >= (unsigned int)model->numskins)
4947 if (model->skinscenes)
4949 if (model->skinscenes[s].framecount > 1)
4950 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4952 s = model->skinscenes[s].firstframe;
4955 t = t + s * model->num_surfaces;
4958 // use an alternate animation if the entity's frame is not 0,
4959 // and only if the texture has an alternate animation
4960 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
4961 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4963 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4965 texture->currentframe = t;
4968 // update currentskinframe to be a qw skin or animation frame
4969 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"))
4971 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4973 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4974 if (developer_loading.integer)
4975 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4976 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);
4978 t->currentskinframe = r_qwskincache_skinframe[i];
4979 if (t->currentskinframe == NULL)
4980 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4982 else if (t->numskinframes >= 2)
4983 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4984 if (t->backgroundnumskinframes >= 2)
4985 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
4987 t->currentmaterialflags = t->basematerialflags;
4988 t->currentalpha = ent->alpha;
4989 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4990 t->currentalpha *= r_wateralpha.value;
4991 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4992 t->currentalpha *= t->r_water_wateralpha;
4993 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4994 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4995 if (!(ent->flags & RENDER_LIGHT))
4996 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4997 else if (rsurface.modeltexcoordlightmap2f == NULL)
4999 // pick a model lighting mode
5000 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5001 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5003 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5005 if (ent->effects & EF_ADDITIVE)
5006 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5007 else if (t->currentalpha < 1)
5008 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5009 if (ent->effects & EF_DOUBLESIDED)
5010 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5011 if (ent->effects & EF_NODEPTHTEST)
5012 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5013 if (ent->flags & RENDER_VIEWMODEL)
5014 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5015 if (t->backgroundnumskinframes)
5016 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5017 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5019 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5020 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5023 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5025 // there is no tcmod
5026 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5028 t->currenttexmatrix = r_waterscrollmatrix;
5029 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5033 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5034 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5037 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5038 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5039 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5040 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5042 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5043 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5044 t->glosstexture = r_texture_black;
5045 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5046 t->backgroundglosstexture = r_texture_black;
5047 t->specularpower = r_shadow_glossexponent.value;
5048 // TODO: store reference values for these in the texture?
5049 t->specularscale = 0;
5050 if (r_shadow_gloss.integer > 0)
5052 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5054 if (r_shadow_glossintensity.value > 0)
5056 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5057 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5058 t->specularscale = r_shadow_glossintensity.value;
5061 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5063 t->glosstexture = r_texture_white;
5064 t->backgroundglosstexture = r_texture_white;
5065 t->specularscale = r_shadow_gloss2intensity.value;
5069 // lightmaps mode looks bad with dlights using actual texturing, so turn
5070 // off the colormap and glossmap, but leave the normalmap on as it still
5071 // accurately represents the shading involved
5072 if (gl_lightmaps.integer)
5074 t->basetexture = r_texture_grey128;
5075 t->backgroundbasetexture = NULL;
5076 t->specularscale = 0;
5077 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5080 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5081 VectorClear(t->dlightcolor);
5082 t->currentnumlayers = 0;
5083 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5086 int blendfunc1, blendfunc2, depthmask;
5087 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5089 blendfunc1 = GL_SRC_ALPHA;
5090 blendfunc2 = GL_ONE;
5092 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5094 blendfunc1 = GL_SRC_ALPHA;
5095 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5097 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5099 blendfunc1 = t->customblendfunc[0];
5100 blendfunc2 = t->customblendfunc[1];
5104 blendfunc1 = GL_ONE;
5105 blendfunc2 = GL_ZERO;
5107 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5108 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5109 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5110 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5112 // fullbright is not affected by r_refdef.lightmapintensity
5113 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]);
5114 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5115 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]);
5116 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5117 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]);
5121 vec3_t ambientcolor;
5123 // set the color tint used for lights affecting this surface
5124 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5126 // q3bsp has no lightmap updates, so the lightstylevalue that
5127 // would normally be baked into the lightmap must be
5128 // applied to the color
5129 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5130 if (ent->model->type == mod_brushq3)
5131 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5132 colorscale *= r_refdef.lightmapintensity;
5133 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5134 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5135 // basic lit geometry
5136 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]);
5137 // add pants/shirt if needed
5138 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5139 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]);
5140 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5141 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]);
5142 // now add ambient passes if needed
5143 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5145 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]);
5146 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5147 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]);
5148 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5149 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]);
5152 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5153 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]);
5154 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5156 // if this is opaque use alpha blend which will darken the earlier
5159 // if this is an alpha blended material, all the earlier passes
5160 // were darkened by fog already, so we only need to add the fog
5161 // color ontop through the fog mask texture
5163 // if this is an additive blended material, all the earlier passes
5164 // were darkened by fog already, and we should not add fog color
5165 // (because the background was not darkened, there is no fog color
5166 // that was lost behind it).
5167 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]);
5171 return t->currentframe;
5174 rsurfacestate_t rsurface;
5176 void R_Mesh_ResizeArrays(int newvertices)
5179 if (rsurface.array_size >= newvertices)
5181 if (rsurface.array_modelvertex3f)
5182 Mem_Free(rsurface.array_modelvertex3f);
5183 rsurface.array_size = (newvertices + 1023) & ~1023;
5184 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5185 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5186 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5187 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5188 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5189 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5190 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5191 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5192 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5193 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5194 rsurface.array_color4f = base + rsurface.array_size * 27;
5195 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5198 void RSurf_ActiveWorldEntity(void)
5200 dp_model_t *model = r_refdef.scene.worldmodel;
5201 //if (rsurface.entity == r_refdef.scene.worldentity)
5203 rsurface.entity = r_refdef.scene.worldentity;
5204 if (rsurface.array_size < model->surfmesh.num_vertices)
5205 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5206 rsurface.matrix = identitymatrix;
5207 rsurface.inversematrix = identitymatrix;
5208 R_Mesh_Matrix(&identitymatrix);
5209 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5210 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5211 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5212 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5213 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5214 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5215 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5216 rsurface.frameblend[0].lerp = 1;
5217 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5218 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5219 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5220 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5221 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5222 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5223 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5224 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5225 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5226 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5227 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5228 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5229 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5230 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5231 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5232 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5233 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5234 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5235 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5236 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5237 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5238 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5239 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5240 rsurface.modelelement3i = model->surfmesh.data_element3i;
5241 rsurface.modelelement3s = model->surfmesh.data_element3s;
5242 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5243 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5244 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5245 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5246 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5247 rsurface.modelsurfaces = model->data_surfaces;
5248 rsurface.generatedvertex = false;
5249 rsurface.vertex3f = rsurface.modelvertex3f;
5250 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5251 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5252 rsurface.svector3f = rsurface.modelsvector3f;
5253 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5254 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5255 rsurface.tvector3f = rsurface.modeltvector3f;
5256 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5257 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5258 rsurface.normal3f = rsurface.modelnormal3f;
5259 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5260 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5261 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5264 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5266 dp_model_t *model = ent->model;
5267 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5269 rsurface.entity = (entity_render_t *)ent;
5270 if (rsurface.array_size < model->surfmesh.num_vertices)
5271 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5272 rsurface.matrix = ent->matrix;
5273 rsurface.inversematrix = ent->inversematrix;
5274 R_Mesh_Matrix(&rsurface.matrix);
5275 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5276 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5277 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5278 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5279 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5280 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5281 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5282 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5283 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5284 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5285 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5286 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5287 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5288 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5289 if (ent->model->brush.submodel)
5291 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5292 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5294 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5296 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5298 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5299 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5300 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5301 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5303 else if (wanttangents)
5305 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5306 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5307 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5308 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5309 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5311 else if (wantnormals)
5313 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5314 rsurface.modelsvector3f = NULL;
5315 rsurface.modeltvector3f = NULL;
5316 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5317 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5321 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5322 rsurface.modelsvector3f = NULL;
5323 rsurface.modeltvector3f = NULL;
5324 rsurface.modelnormal3f = NULL;
5325 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5327 rsurface.modelvertex3f_bufferobject = 0;
5328 rsurface.modelvertex3f_bufferoffset = 0;
5329 rsurface.modelsvector3f_bufferobject = 0;
5330 rsurface.modelsvector3f_bufferoffset = 0;
5331 rsurface.modeltvector3f_bufferobject = 0;
5332 rsurface.modeltvector3f_bufferoffset = 0;
5333 rsurface.modelnormal3f_bufferobject = 0;
5334 rsurface.modelnormal3f_bufferoffset = 0;
5335 rsurface.generatedvertex = true;
5339 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5340 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5341 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5342 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5343 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5344 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5345 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5346 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5347 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5348 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5349 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5350 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5351 rsurface.generatedvertex = false;
5353 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5354 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5355 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5356 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5357 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5358 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5359 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5360 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5361 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5362 rsurface.modelelement3i = model->surfmesh.data_element3i;
5363 rsurface.modelelement3s = model->surfmesh.data_element3s;
5364 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5365 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5366 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5367 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5368 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5369 rsurface.modelsurfaces = model->data_surfaces;
5370 rsurface.vertex3f = rsurface.modelvertex3f;
5371 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5372 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5373 rsurface.svector3f = rsurface.modelsvector3f;
5374 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5375 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5376 rsurface.tvector3f = rsurface.modeltvector3f;
5377 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5378 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5379 rsurface.normal3f = rsurface.modelnormal3f;
5380 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5381 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5382 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5385 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5386 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5389 int texturesurfaceindex;
5394 const float *v1, *in_tc;
5396 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5398 q3shaderinfo_deform_t *deform;
5399 // 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
5400 if (rsurface.generatedvertex)
5402 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5403 generatenormals = true;
5404 for (i = 0;i < Q3MAXDEFORMS;i++)
5406 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5408 generatetangents = true;
5409 generatenormals = true;
5411 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5412 generatenormals = true;
5414 if (generatenormals && !rsurface.modelnormal3f)
5416 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5417 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5418 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5419 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5421 if (generatetangents && !rsurface.modelsvector3f)
5423 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5424 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5425 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5426 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5427 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5428 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5429 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);
5432 rsurface.vertex3f = rsurface.modelvertex3f;
5433 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5434 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5435 rsurface.svector3f = rsurface.modelsvector3f;
5436 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5437 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5438 rsurface.tvector3f = rsurface.modeltvector3f;
5439 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5440 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5441 rsurface.normal3f = rsurface.modelnormal3f;
5442 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5443 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5444 // if vertices are deformed (sprite flares and things in maps, possibly
5445 // water waves, bulges and other deformations), generate them into
5446 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5447 // (may be static model data or generated data for an animated model, or
5448 // the previous deform pass)
5449 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5451 switch (deform->deform)
5454 case Q3DEFORM_PROJECTIONSHADOW:
5455 case Q3DEFORM_TEXT0:
5456 case Q3DEFORM_TEXT1:
5457 case Q3DEFORM_TEXT2:
5458 case Q3DEFORM_TEXT3:
5459 case Q3DEFORM_TEXT4:
5460 case Q3DEFORM_TEXT5:
5461 case Q3DEFORM_TEXT6:
5462 case Q3DEFORM_TEXT7:
5465 case Q3DEFORM_AUTOSPRITE:
5466 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5467 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5468 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5469 VectorNormalize(newforward);
5470 VectorNormalize(newright);
5471 VectorNormalize(newup);
5472 // make deformed versions of only the model vertices used by the specified surfaces
5473 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5475 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5476 // a single autosprite surface can contain multiple sprites...
5477 for (j = 0;j < surface->num_vertices - 3;j += 4)
5479 VectorClear(center);
5480 for (i = 0;i < 4;i++)
5481 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5482 VectorScale(center, 0.25f, center);
5483 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5484 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5485 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5486 for (i = 0;i < 4;i++)
5488 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5489 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5492 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);
5493 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);
5495 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5496 rsurface.vertex3f_bufferobject = 0;
5497 rsurface.vertex3f_bufferoffset = 0;
5498 rsurface.svector3f = rsurface.array_deformedsvector3f;
5499 rsurface.svector3f_bufferobject = 0;
5500 rsurface.svector3f_bufferoffset = 0;
5501 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5502 rsurface.tvector3f_bufferobject = 0;
5503 rsurface.tvector3f_bufferoffset = 0;
5504 rsurface.normal3f = rsurface.array_deformednormal3f;
5505 rsurface.normal3f_bufferobject = 0;
5506 rsurface.normal3f_bufferoffset = 0;
5508 case Q3DEFORM_AUTOSPRITE2:
5509 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5510 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5511 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5512 VectorNormalize(newforward);
5513 VectorNormalize(newright);
5514 VectorNormalize(newup);
5515 // make deformed versions of only the model vertices used by the specified surfaces
5516 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5518 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5519 const float *v1, *v2;
5529 memset(shortest, 0, sizeof(shortest));
5530 // a single autosprite surface can contain multiple sprites...
5531 for (j = 0;j < surface->num_vertices - 3;j += 4)
5533 VectorClear(center);
5534 for (i = 0;i < 4;i++)
5535 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5536 VectorScale(center, 0.25f, center);
5537 // find the two shortest edges, then use them to define the
5538 // axis vectors for rotating around the central axis
5539 for (i = 0;i < 6;i++)
5541 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5542 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5544 Debug_PolygonBegin(NULL, 0);
5545 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5546 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);
5547 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5550 l = VectorDistance2(v1, v2);
5551 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5553 l += (1.0f / 1024.0f);
5554 if (shortest[0].length2 > l || i == 0)
5556 shortest[1] = shortest[0];
5557 shortest[0].length2 = l;
5558 shortest[0].v1 = v1;
5559 shortest[0].v2 = v2;
5561 else if (shortest[1].length2 > l || i == 1)
5563 shortest[1].length2 = l;
5564 shortest[1].v1 = v1;
5565 shortest[1].v2 = v2;
5568 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5569 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5571 Debug_PolygonBegin(NULL, 0);
5572 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5573 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);
5574 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5577 // this calculates the right vector from the shortest edge
5578 // and the up vector from the edge midpoints
5579 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5580 VectorNormalize(right);
5581 VectorSubtract(end, start, up);
5582 VectorNormalize(up);
5583 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5584 VectorSubtract(rsurface.modelorg, center, forward);
5585 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5586 VectorNegate(forward, forward);
5587 VectorReflect(forward, 0, up, forward);
5588 VectorNormalize(forward);
5589 CrossProduct(up, forward, newright);
5590 VectorNormalize(newright);
5592 Debug_PolygonBegin(NULL, 0);
5593 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);
5594 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5595 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5599 Debug_PolygonBegin(NULL, 0);
5600 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5601 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5602 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5605 // rotate the quad around the up axis vector, this is made
5606 // especially easy by the fact we know the quad is flat,
5607 // so we only have to subtract the center position and
5608 // measure distance along the right vector, and then
5609 // multiply that by the newright vector and add back the
5611 // we also need to subtract the old position to undo the
5612 // displacement from the center, which we do with a
5613 // DotProduct, the subtraction/addition of center is also
5614 // optimized into DotProducts here
5615 l = DotProduct(right, center);
5616 for (i = 0;i < 4;i++)
5618 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5619 f = DotProduct(right, v1) - l;
5620 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5623 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);
5624 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);
5626 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5627 rsurface.vertex3f_bufferobject = 0;
5628 rsurface.vertex3f_bufferoffset = 0;
5629 rsurface.svector3f = rsurface.array_deformedsvector3f;
5630 rsurface.svector3f_bufferobject = 0;
5631 rsurface.svector3f_bufferoffset = 0;
5632 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5633 rsurface.tvector3f_bufferobject = 0;
5634 rsurface.tvector3f_bufferoffset = 0;
5635 rsurface.normal3f = rsurface.array_deformednormal3f;
5636 rsurface.normal3f_bufferobject = 0;
5637 rsurface.normal3f_bufferoffset = 0;
5639 case Q3DEFORM_NORMAL:
5640 // deform the normals to make reflections wavey
5641 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5643 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5644 for (j = 0;j < surface->num_vertices;j++)
5647 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5648 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5649 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5650 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5651 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5652 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5653 VectorNormalize(normal);
5655 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);
5657 rsurface.svector3f = rsurface.array_deformedsvector3f;
5658 rsurface.svector3f_bufferobject = 0;
5659 rsurface.svector3f_bufferoffset = 0;
5660 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5661 rsurface.tvector3f_bufferobject = 0;
5662 rsurface.tvector3f_bufferoffset = 0;
5663 rsurface.normal3f = rsurface.array_deformednormal3f;
5664 rsurface.normal3f_bufferobject = 0;
5665 rsurface.normal3f_bufferoffset = 0;
5668 // deform vertex array to make wavey water and flags and such
5669 waveparms[0] = deform->waveparms[0];
5670 waveparms[1] = deform->waveparms[1];
5671 waveparms[2] = deform->waveparms[2];
5672 waveparms[3] = deform->waveparms[3];
5673 // this is how a divisor of vertex influence on deformation
5674 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5675 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5676 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5678 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5679 for (j = 0;j < surface->num_vertices;j++)
5681 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5682 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5683 // if the wavefunc depends on time, evaluate it per-vertex
5686 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5687 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5689 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5692 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5693 rsurface.vertex3f_bufferobject = 0;
5694 rsurface.vertex3f_bufferoffset = 0;
5696 case Q3DEFORM_BULGE:
5697 // deform vertex array to make the surface have moving bulges
5698 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5700 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5701 for (j = 0;j < surface->num_vertices;j++)
5703 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5704 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5707 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5708 rsurface.vertex3f_bufferobject = 0;
5709 rsurface.vertex3f_bufferoffset = 0;
5712 // deform vertex array
5713 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5714 VectorScale(deform->parms, scale, waveparms);
5715 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5717 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5718 for (j = 0;j < surface->num_vertices;j++)
5719 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5721 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5722 rsurface.vertex3f_bufferobject = 0;
5723 rsurface.vertex3f_bufferoffset = 0;
5727 // generate texcoords based on the chosen texcoord source
5728 switch(rsurface.texture->tcgen.tcgen)
5731 case Q3TCGEN_TEXTURE:
5732 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5733 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5734 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5736 case Q3TCGEN_LIGHTMAP:
5737 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5738 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5739 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5741 case Q3TCGEN_VECTOR:
5742 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5744 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5745 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)
5747 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5748 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5751 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5752 rsurface.texcoordtexture2f_bufferobject = 0;
5753 rsurface.texcoordtexture2f_bufferoffset = 0;
5755 case Q3TCGEN_ENVIRONMENT:
5756 // make environment reflections using a spheremap
5757 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5759 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5760 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5761 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5762 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5763 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5765 // identical to Q3A's method, but executed in worldspace so
5766 // carried models can be shiny too
5768 float viewer[3], d, reflected[3], worldreflected[3];
5770 VectorSubtract(rsurface.modelorg, vertex, viewer);
5771 // VectorNormalize(viewer);
5773 d = DotProduct(normal, viewer);
5775 reflected[0] = normal[0]*2*d - viewer[0];
5776 reflected[1] = normal[1]*2*d - viewer[1];
5777 reflected[2] = normal[2]*2*d - viewer[2];
5778 // note: this is proportinal to viewer, so we can normalize later
5780 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
5781 VectorNormalize(worldreflected);
5783 // note: this sphere map only uses world x and z!
5784 // so positive and negative y will LOOK THE SAME.
5785 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
5786 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
5789 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5790 rsurface.texcoordtexture2f_bufferobject = 0;
5791 rsurface.texcoordtexture2f_bufferoffset = 0;
5794 // the only tcmod that needs software vertex processing is turbulent, so
5795 // check for it here and apply the changes if needed
5796 // and we only support that as the first one
5797 // (handling a mixture of turbulent and other tcmods would be problematic
5798 // without punting it entirely to a software path)
5799 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5801 amplitude = rsurface.texture->tcmods[0].parms[1];
5802 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5803 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5805 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5806 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)
5808 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5809 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5812 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5813 rsurface.texcoordtexture2f_bufferobject = 0;
5814 rsurface.texcoordtexture2f_bufferoffset = 0;
5816 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5817 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5818 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5819 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5822 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5825 const msurface_t *surface = texturesurfacelist[0];
5826 const msurface_t *surface2;
5831 // TODO: lock all array ranges before render, rather than on each surface
5832 if (texturenumsurfaces == 1)
5834 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5835 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);
5837 else if (r_batchmode.integer == 2)
5839 #define MAXBATCHTRIANGLES 4096
5840 int batchtriangles = 0;
5841 int batchelements[MAXBATCHTRIANGLES*3];
5842 for (i = 0;i < texturenumsurfaces;i = j)
5844 surface = texturesurfacelist[i];
5846 if (surface->num_triangles > MAXBATCHTRIANGLES)
5848 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);
5851 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5852 batchtriangles = surface->num_triangles;
5853 firstvertex = surface->num_firstvertex;
5854 endvertex = surface->num_firstvertex + surface->num_vertices;
5855 for (;j < texturenumsurfaces;j++)
5857 surface2 = texturesurfacelist[j];
5858 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5860 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5861 batchtriangles += surface2->num_triangles;
5862 firstvertex = min(firstvertex, surface2->num_firstvertex);
5863 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5865 surface2 = texturesurfacelist[j-1];
5866 numvertices = endvertex - firstvertex;
5867 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5870 else if (r_batchmode.integer == 1)
5872 for (i = 0;i < texturenumsurfaces;i = j)
5874 surface = texturesurfacelist[i];
5875 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5876 if (texturesurfacelist[j] != surface2)
5878 surface2 = texturesurfacelist[j-1];
5879 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5880 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5881 GL_LockArrays(surface->num_firstvertex, numvertices);
5882 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5887 for (i = 0;i < texturenumsurfaces;i++)
5889 surface = texturesurfacelist[i];
5890 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5891 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);
5896 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5898 int i, planeindex, vertexindex;
5902 r_waterstate_waterplane_t *p, *bestp;
5903 msurface_t *surface;
5904 if (r_waterstate.renderingscene)
5906 for (i = 0;i < texturenumsurfaces;i++)
5908 surface = texturesurfacelist[i];
5909 if (lightmaptexunit >= 0)
5910 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5911 if (deluxemaptexunit >= 0)
5912 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5913 // pick the closest matching water plane
5916 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5919 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5921 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5922 d += fabs(PlaneDiff(vert, &p->plane));
5924 if (bestd > d || !bestp)
5932 if (refractiontexunit >= 0)
5933 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5934 if (reflectiontexunit >= 0)
5935 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5939 if (refractiontexunit >= 0)
5940 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5941 if (reflectiontexunit >= 0)
5942 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5944 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5945 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);
5949 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5953 const msurface_t *surface = texturesurfacelist[0];
5954 const msurface_t *surface2;
5959 // TODO: lock all array ranges before render, rather than on each surface
5960 if (texturenumsurfaces == 1)
5962 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5963 if (deluxemaptexunit >= 0)
5964 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5965 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5966 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);
5968 else if (r_batchmode.integer == 2)
5970 #define MAXBATCHTRIANGLES 4096
5971 int batchtriangles = 0;
5972 int batchelements[MAXBATCHTRIANGLES*3];
5973 for (i = 0;i < texturenumsurfaces;i = j)
5975 surface = texturesurfacelist[i];
5976 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5977 if (deluxemaptexunit >= 0)
5978 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5980 if (surface->num_triangles > MAXBATCHTRIANGLES)
5982 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);
5985 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5986 batchtriangles = surface->num_triangles;
5987 firstvertex = surface->num_firstvertex;
5988 endvertex = surface->num_firstvertex + surface->num_vertices;
5989 for (;j < texturenumsurfaces;j++)
5991 surface2 = texturesurfacelist[j];
5992 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5994 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5995 batchtriangles += surface2->num_triangles;
5996 firstvertex = min(firstvertex, surface2->num_firstvertex);
5997 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5999 surface2 = texturesurfacelist[j-1];
6000 numvertices = endvertex - firstvertex;
6001 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6004 else if (r_batchmode.integer == 1)
6007 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6008 for (i = 0;i < texturenumsurfaces;i = j)
6010 surface = texturesurfacelist[i];
6011 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6012 if (texturesurfacelist[j] != surface2)
6014 Con_Printf(" %i", j - i);
6017 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6019 for (i = 0;i < texturenumsurfaces;i = j)
6021 surface = texturesurfacelist[i];
6022 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6023 if (deluxemaptexunit >= 0)
6024 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6025 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6026 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6029 Con_Printf(" %i", j - i);
6031 surface2 = texturesurfacelist[j-1];
6032 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6033 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6034 GL_LockArrays(surface->num_firstvertex, numvertices);
6035 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6043 for (i = 0;i < texturenumsurfaces;i++)
6045 surface = texturesurfacelist[i];
6046 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6047 if (deluxemaptexunit >= 0)
6048 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6049 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6050 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);
6055 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6058 int texturesurfaceindex;
6059 if (r_showsurfaces.integer == 2)
6061 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6063 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6064 for (j = 0;j < surface->num_triangles;j++)
6066 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6067 GL_Color(f, f, f, 1);
6068 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6074 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6076 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6077 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6078 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);
6079 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6080 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);
6085 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6087 int texturesurfaceindex;
6090 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6092 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6093 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)
6101 rsurface.lightmapcolor4f = rsurface.array_color4f;
6102 rsurface.lightmapcolor4f_bufferobject = 0;
6103 rsurface.lightmapcolor4f_bufferoffset = 0;
6106 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6108 int texturesurfaceindex;
6112 if (rsurface.lightmapcolor4f)
6114 // generate color arrays for the surfaces in this list
6115 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6117 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6118 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)
6120 f = FogPoint_Model(v);
6130 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6132 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6133 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)
6135 f = FogPoint_Model(v);
6143 rsurface.lightmapcolor4f = rsurface.array_color4f;
6144 rsurface.lightmapcolor4f_bufferobject = 0;
6145 rsurface.lightmapcolor4f_bufferoffset = 0;
6148 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6150 int texturesurfaceindex;
6154 if (!rsurface.lightmapcolor4f)
6156 // generate color arrays for the surfaces in this list
6157 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6159 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6160 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)
6162 f = FogPoint_Model(v);
6163 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6164 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6165 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6169 rsurface.lightmapcolor4f = rsurface.array_color4f;
6170 rsurface.lightmapcolor4f_bufferobject = 0;
6171 rsurface.lightmapcolor4f_bufferoffset = 0;
6174 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6176 int texturesurfaceindex;
6179 if (!rsurface.lightmapcolor4f)
6181 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6183 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6184 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)
6192 rsurface.lightmapcolor4f = rsurface.array_color4f;
6193 rsurface.lightmapcolor4f_bufferobject = 0;
6194 rsurface.lightmapcolor4f_bufferoffset = 0;
6197 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6199 int texturesurfaceindex;
6202 if (!rsurface.lightmapcolor4f)
6204 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6206 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6207 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)
6209 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6210 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6211 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6215 rsurface.lightmapcolor4f = rsurface.array_color4f;
6216 rsurface.lightmapcolor4f_bufferobject = 0;
6217 rsurface.lightmapcolor4f_bufferoffset = 0;
6220 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6223 rsurface.lightmapcolor4f = NULL;
6224 rsurface.lightmapcolor4f_bufferobject = 0;
6225 rsurface.lightmapcolor4f_bufferoffset = 0;
6226 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6227 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6228 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6229 GL_Color(r, g, b, a);
6230 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6233 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6235 // TODO: optimize applyfog && applycolor case
6236 // just apply fog if necessary, and tint the fog color array if necessary
6237 rsurface.lightmapcolor4f = NULL;
6238 rsurface.lightmapcolor4f_bufferobject = 0;
6239 rsurface.lightmapcolor4f_bufferoffset = 0;
6240 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6241 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6242 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6243 GL_Color(r, g, b, a);
6244 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6247 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6249 int texturesurfaceindex;
6253 if (texturesurfacelist[0]->lightmapinfo)
6255 // generate color arrays for the surfaces in this list
6256 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6258 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6259 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6261 if (surface->lightmapinfo->samples)
6263 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6264 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6265 VectorScale(lm, scale, c);
6266 if (surface->lightmapinfo->styles[1] != 255)
6268 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6270 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6271 VectorMA(c, scale, lm, c);
6272 if (surface->lightmapinfo->styles[2] != 255)
6275 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6276 VectorMA(c, scale, lm, c);
6277 if (surface->lightmapinfo->styles[3] != 255)
6280 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6281 VectorMA(c, scale, lm, c);
6291 rsurface.lightmapcolor4f = rsurface.array_color4f;
6292 rsurface.lightmapcolor4f_bufferobject = 0;
6293 rsurface.lightmapcolor4f_bufferoffset = 0;
6297 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6298 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6299 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6301 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6302 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6303 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6304 GL_Color(r, g, b, a);
6305 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6308 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6310 int texturesurfaceindex;
6313 float *v, *c, *c2, alpha;
6314 vec3_t ambientcolor;
6315 vec3_t diffusecolor;
6319 VectorCopy(rsurface.modellight_lightdir, lightdir);
6320 f = 0.5f * r_refdef.lightmapintensity;
6321 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6322 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6323 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6324 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6325 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6326 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6328 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6330 // generate color arrays for the surfaces in this list
6331 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6333 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6334 int numverts = surface->num_vertices;
6335 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6336 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6337 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6338 // q3-style directional shading
6339 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6341 if ((f = DotProduct(c2, lightdir)) > 0)
6342 VectorMA(ambientcolor, f, diffusecolor, c);
6344 VectorCopy(ambientcolor, c);
6352 rsurface.lightmapcolor4f = rsurface.array_color4f;
6353 rsurface.lightmapcolor4f_bufferobject = 0;
6354 rsurface.lightmapcolor4f_bufferoffset = 0;
6355 *applycolor = false;
6359 *r = ambientcolor[0];
6360 *g = ambientcolor[1];
6361 *b = ambientcolor[2];
6362 rsurface.lightmapcolor4f = NULL;
6363 rsurface.lightmapcolor4f_bufferobject = 0;
6364 rsurface.lightmapcolor4f_bufferoffset = 0;
6368 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6370 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6371 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6372 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6373 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6374 GL_Color(r, g, b, a);
6375 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6378 void RSurf_SetupDepthAndCulling(void)
6380 // submodels are biased to avoid z-fighting with world surfaces that they
6381 // may be exactly overlapping (avoids z-fighting artifacts on certain
6382 // doors and things in Quake maps)
6383 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6384 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6385 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6386 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6389 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6391 // transparent sky would be ridiculous
6392 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6394 R_SetupGenericShader(false);
6397 skyrendernow = false;
6398 // we have to force off the water clipping plane while rendering sky
6402 // restore entity matrix
6403 R_Mesh_Matrix(&rsurface.matrix);
6405 RSurf_SetupDepthAndCulling();
6407 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6408 // skymasking on them, and Quake3 never did sky masking (unlike
6409 // software Quake and software Quake2), so disable the sky masking
6410 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6411 // and skymasking also looks very bad when noclipping outside the
6412 // level, so don't use it then either.
6413 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6415 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6416 R_Mesh_ColorPointer(NULL, 0, 0);
6417 R_Mesh_ResetTextureState();
6418 if (skyrendermasked)
6420 R_SetupDepthOrShadowShader();
6421 // depth-only (masking)
6422 GL_ColorMask(0,0,0,0);
6423 // just to make sure that braindead drivers don't draw
6424 // anything despite that colormask...
6425 GL_BlendFunc(GL_ZERO, GL_ONE);
6429 R_SetupGenericShader(false);
6431 GL_BlendFunc(GL_ONE, GL_ZERO);
6433 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6434 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6435 if (skyrendermasked)
6436 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6438 R_Mesh_ResetTextureState();
6439 GL_Color(1, 1, 1, 1);
6442 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6444 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6447 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6448 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6449 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6450 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6451 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6452 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6453 if (rsurface.texture->backgroundcurrentskinframe)
6455 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6456 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6457 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6458 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6460 if(rsurface.texture->colormapping)
6462 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6463 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6465 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6466 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6467 R_Mesh_ColorPointer(NULL, 0, 0);
6469 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6471 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6473 // render background
6474 GL_BlendFunc(GL_ONE, GL_ZERO);
6476 GL_AlphaTest(false);
6478 GL_Color(1, 1, 1, 1);
6479 R_Mesh_ColorPointer(NULL, 0, 0);
6481 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6482 if (r_glsl_permutation)
6484 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6485 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6486 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6487 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6488 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6489 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6490 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);
6492 GL_LockArrays(0, 0);
6494 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6495 GL_DepthMask(false);
6496 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6497 R_Mesh_ColorPointer(NULL, 0, 0);
6499 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6500 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6501 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6504 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6505 if (!r_glsl_permutation)
6508 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6509 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6510 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6511 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6512 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6513 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6515 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6517 GL_BlendFunc(GL_ONE, GL_ZERO);
6519 GL_AlphaTest(false);
6523 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6524 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6525 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6528 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6530 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6531 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);
6533 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6537 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6538 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);
6540 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6542 GL_LockArrays(0, 0);
6545 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6547 // OpenGL 1.3 path - anything not completely ancient
6548 int texturesurfaceindex;
6549 qboolean applycolor;
6553 const texturelayer_t *layer;
6554 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6556 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6559 int layertexrgbscale;
6560 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6562 if (layerindex == 0)
6566 GL_AlphaTest(false);
6567 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6570 GL_DepthMask(layer->depthmask && writedepth);
6571 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6572 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6574 layertexrgbscale = 4;
6575 VectorScale(layer->color, 0.25f, layercolor);
6577 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6579 layertexrgbscale = 2;
6580 VectorScale(layer->color, 0.5f, layercolor);
6584 layertexrgbscale = 1;
6585 VectorScale(layer->color, 1.0f, layercolor);
6587 layercolor[3] = layer->color[3];
6588 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6589 R_Mesh_ColorPointer(NULL, 0, 0);
6590 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6591 switch (layer->type)
6593 case TEXTURELAYERTYPE_LITTEXTURE:
6594 memset(&m, 0, sizeof(m));
6595 m.tex[0] = R_GetTexture(r_texture_white);
6596 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6597 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6598 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6599 m.tex[1] = R_GetTexture(layer->texture);
6600 m.texmatrix[1] = layer->texmatrix;
6601 m.texrgbscale[1] = layertexrgbscale;
6602 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6603 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6604 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6605 R_Mesh_TextureState(&m);
6606 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6607 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6608 else if (rsurface.uselightmaptexture)
6609 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6611 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6613 case TEXTURELAYERTYPE_TEXTURE:
6614 memset(&m, 0, sizeof(m));
6615 m.tex[0] = R_GetTexture(layer->texture);
6616 m.texmatrix[0] = layer->texmatrix;
6617 m.texrgbscale[0] = layertexrgbscale;
6618 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6619 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6620 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6621 R_Mesh_TextureState(&m);
6622 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6624 case TEXTURELAYERTYPE_FOG:
6625 memset(&m, 0, sizeof(m));
6626 m.texrgbscale[0] = layertexrgbscale;
6629 m.tex[0] = R_GetTexture(layer->texture);
6630 m.texmatrix[0] = layer->texmatrix;
6631 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6632 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6633 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6635 R_Mesh_TextureState(&m);
6636 // generate a color array for the fog pass
6637 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6638 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6642 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6643 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)
6645 f = 1 - FogPoint_Model(v);
6646 c[0] = layercolor[0];
6647 c[1] = layercolor[1];
6648 c[2] = layercolor[2];
6649 c[3] = f * layercolor[3];
6652 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6655 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6657 GL_LockArrays(0, 0);
6660 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6662 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6663 GL_AlphaTest(false);
6667 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6669 // OpenGL 1.1 - crusty old voodoo path
6670 int texturesurfaceindex;
6674 const texturelayer_t *layer;
6675 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6677 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6679 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6681 if (layerindex == 0)
6685 GL_AlphaTest(false);
6686 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6689 GL_DepthMask(layer->depthmask && writedepth);
6690 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6691 R_Mesh_ColorPointer(NULL, 0, 0);
6692 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6693 switch (layer->type)
6695 case TEXTURELAYERTYPE_LITTEXTURE:
6696 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6698 // two-pass lit texture with 2x rgbscale
6699 // first the lightmap pass
6700 memset(&m, 0, sizeof(m));
6701 m.tex[0] = R_GetTexture(r_texture_white);
6702 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6703 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6704 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6705 R_Mesh_TextureState(&m);
6706 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6707 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6708 else if (rsurface.uselightmaptexture)
6709 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6711 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6712 GL_LockArrays(0, 0);
6713 // then apply the texture to it
6714 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6715 memset(&m, 0, sizeof(m));
6716 m.tex[0] = R_GetTexture(layer->texture);
6717 m.texmatrix[0] = layer->texmatrix;
6718 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6719 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6720 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6721 R_Mesh_TextureState(&m);
6722 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);
6726 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6727 memset(&m, 0, sizeof(m));
6728 m.tex[0] = R_GetTexture(layer->texture);
6729 m.texmatrix[0] = layer->texmatrix;
6730 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6731 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6732 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6733 R_Mesh_TextureState(&m);
6734 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6735 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);
6737 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);
6740 case TEXTURELAYERTYPE_TEXTURE:
6741 // singletexture unlit texture with transparency support
6742 memset(&m, 0, sizeof(m));
6743 m.tex[0] = R_GetTexture(layer->texture);
6744 m.texmatrix[0] = layer->texmatrix;
6745 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6746 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6747 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6748 R_Mesh_TextureState(&m);
6749 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);
6751 case TEXTURELAYERTYPE_FOG:
6752 // singletexture fogging
6753 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6756 memset(&m, 0, sizeof(m));
6757 m.tex[0] = R_GetTexture(layer->texture);
6758 m.texmatrix[0] = layer->texmatrix;
6759 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6760 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6761 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6762 R_Mesh_TextureState(&m);
6765 R_Mesh_ResetTextureState();
6766 // generate a color array for the fog pass
6767 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6771 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6772 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)
6774 f = 1 - FogPoint_Model(v);
6775 c[0] = layer->color[0];
6776 c[1] = layer->color[1];
6777 c[2] = layer->color[2];
6778 c[3] = f * layer->color[3];
6781 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6784 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6786 GL_LockArrays(0, 0);
6789 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6791 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6792 GL_AlphaTest(false);
6796 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6800 GL_AlphaTest(false);
6801 R_Mesh_ColorPointer(NULL, 0, 0);
6802 R_Mesh_ResetTextureState();
6803 R_SetupGenericShader(false);
6805 if(rsurface.texture && rsurface.texture->currentskinframe)
6807 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6808 c[3] *= rsurface.texture->currentalpha;
6818 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6820 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
6821 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
6822 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
6825 // brighten it up (as texture value 127 means "unlit")
6826 c[0] *= 2 * r_refdef.view.colorscale;
6827 c[1] *= 2 * r_refdef.view.colorscale;
6828 c[2] *= 2 * r_refdef.view.colorscale;
6830 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6831 c[3] *= r_wateralpha.value;
6833 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6835 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6836 GL_DepthMask(false);
6838 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6840 GL_BlendFunc(GL_ONE, GL_ONE);
6841 GL_DepthMask(false);
6843 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6845 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6846 GL_DepthMask(false);
6848 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6850 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6851 GL_DepthMask(false);
6855 GL_BlendFunc(GL_ONE, GL_ZERO);
6856 GL_DepthMask(writedepth);
6859 rsurface.lightmapcolor4f = NULL;
6861 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6863 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6865 rsurface.lightmapcolor4f = NULL;
6866 rsurface.lightmapcolor4f_bufferobject = 0;
6867 rsurface.lightmapcolor4f_bufferoffset = 0;
6869 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6871 qboolean applycolor = true;
6874 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6876 r_refdef.lightmapintensity = 1;
6877 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6878 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6882 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6884 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6885 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6886 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6889 if(!rsurface.lightmapcolor4f)
6890 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6892 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6893 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6894 if(r_refdef.fogenabled)
6895 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6897 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6898 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6901 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6904 RSurf_SetupDepthAndCulling();
6905 if (r_showsurfaces.integer == 3)
6906 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6907 else if (r_glsl.integer && gl_support_fragment_shader)
6908 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6909 else if (gl_combine.integer && r_textureunits.integer >= 2)
6910 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6912 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6916 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6919 RSurf_SetupDepthAndCulling();
6920 if (r_showsurfaces.integer == 3)
6921 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6922 else if (r_glsl.integer && gl_support_fragment_shader)
6923 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6924 else if (gl_combine.integer && r_textureunits.integer >= 2)
6925 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6927 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6931 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6934 int texturenumsurfaces, endsurface;
6936 msurface_t *surface;
6937 msurface_t *texturesurfacelist[1024];
6939 // if the model is static it doesn't matter what value we give for
6940 // wantnormals and wanttangents, so this logic uses only rules applicable
6941 // to a model, knowing that they are meaningless otherwise
6942 if (ent == r_refdef.scene.worldentity)
6943 RSurf_ActiveWorldEntity();
6944 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6945 RSurf_ActiveModelEntity(ent, false, false);
6947 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6949 for (i = 0;i < numsurfaces;i = j)
6952 surface = rsurface.modelsurfaces + surfacelist[i];
6953 texture = surface->texture;
6954 rsurface.texture = R_GetCurrentTexture(texture);
6955 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6956 // scan ahead until we find a different texture
6957 endsurface = min(i + 1024, numsurfaces);
6958 texturenumsurfaces = 0;
6959 texturesurfacelist[texturenumsurfaces++] = surface;
6960 for (;j < endsurface;j++)
6962 surface = rsurface.modelsurfaces + surfacelist[j];
6963 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6965 texturesurfacelist[texturenumsurfaces++] = surface;
6967 // render the range of surfaces
6968 if (ent == r_refdef.scene.worldentity)
6969 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6971 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6973 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6974 GL_AlphaTest(false);
6977 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6979 const entity_render_t *queueentity = r_refdef.scene.worldentity;
6983 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6985 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6987 RSurf_SetupDepthAndCulling();
6988 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6989 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6991 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6993 RSurf_SetupDepthAndCulling();
6994 GL_AlphaTest(false);
6995 R_Mesh_ColorPointer(NULL, 0, 0);
6996 R_Mesh_ResetTextureState();
6997 R_SetupGenericShader(false);
6998 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7000 GL_BlendFunc(GL_ONE, GL_ZERO);
7001 GL_Color(0, 0, 0, 1);
7002 GL_DepthTest(writedepth);
7003 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7005 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7007 RSurf_SetupDepthAndCulling();
7008 GL_AlphaTest(false);
7009 R_Mesh_ColorPointer(NULL, 0, 0);
7010 R_Mesh_ResetTextureState();
7011 R_SetupGenericShader(false);
7012 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7014 GL_BlendFunc(GL_ONE, GL_ZERO);
7016 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7018 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7019 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7020 else if (!rsurface.texture->currentnumlayers)
7022 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7024 // transparent surfaces get pushed off into the transparent queue
7025 int surfacelistindex;
7026 const msurface_t *surface;
7027 vec3_t tempcenter, center;
7028 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7030 surface = texturesurfacelist[surfacelistindex];
7031 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7032 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7033 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7034 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7035 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7040 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7041 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7046 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7050 // break the surface list down into batches by texture and use of lightmapping
7051 for (i = 0;i < numsurfaces;i = j)
7054 // texture is the base texture pointer, rsurface.texture is the
7055 // current frame/skin the texture is directing us to use (for example
7056 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7057 // use skin 1 instead)
7058 texture = surfacelist[i]->texture;
7059 rsurface.texture = R_GetCurrentTexture(texture);
7060 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7061 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7063 // if this texture is not the kind we want, skip ahead to the next one
7064 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7068 // simply scan ahead until we find a different texture or lightmap state
7069 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7071 // render the range of surfaces
7072 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7076 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7081 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7083 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7085 RSurf_SetupDepthAndCulling();
7086 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7087 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7089 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7091 RSurf_SetupDepthAndCulling();
7092 GL_AlphaTest(false);
7093 R_Mesh_ColorPointer(NULL, 0, 0);
7094 R_Mesh_ResetTextureState();
7095 R_SetupGenericShader(false);
7096 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7098 GL_BlendFunc(GL_ONE, GL_ZERO);
7099 GL_Color(0, 0, 0, 1);
7100 GL_DepthTest(writedepth);
7101 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7103 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7105 RSurf_SetupDepthAndCulling();
7106 GL_AlphaTest(false);
7107 R_Mesh_ColorPointer(NULL, 0, 0);
7108 R_Mesh_ResetTextureState();
7109 R_SetupGenericShader(false);
7110 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7112 GL_BlendFunc(GL_ONE, GL_ZERO);
7114 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7116 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7117 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7118 else if (!rsurface.texture->currentnumlayers)
7120 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7122 // transparent surfaces get pushed off into the transparent queue
7123 int surfacelistindex;
7124 const msurface_t *surface;
7125 vec3_t tempcenter, center;
7126 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7128 surface = texturesurfacelist[surfacelistindex];
7129 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7130 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7131 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7132 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7133 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7138 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7139 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7144 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7148 // break the surface list down into batches by texture and use of lightmapping
7149 for (i = 0;i < numsurfaces;i = j)
7152 // texture is the base texture pointer, rsurface.texture is the
7153 // current frame/skin the texture is directing us to use (for example
7154 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7155 // use skin 1 instead)
7156 texture = surfacelist[i]->texture;
7157 rsurface.texture = R_GetCurrentTexture(texture);
7158 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7159 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7161 // if this texture is not the kind we want, skip ahead to the next one
7162 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7166 // simply scan ahead until we find a different texture or lightmap state
7167 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7169 // render the range of surfaces
7170 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7174 float locboxvertex3f[6*4*3] =
7176 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7177 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7178 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7179 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7180 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7181 1,0,0, 0,0,0, 0,1,0, 1,1,0
7184 unsigned short locboxelements[6*2*3] =
7194 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7197 cl_locnode_t *loc = (cl_locnode_t *)ent;
7199 float vertex3f[6*4*3];
7201 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7202 GL_DepthMask(false);
7203 GL_DepthRange(0, 1);
7204 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7206 GL_CullFace(GL_NONE);
7207 R_Mesh_Matrix(&identitymatrix);
7209 R_Mesh_VertexPointer(vertex3f, 0, 0);
7210 R_Mesh_ColorPointer(NULL, 0, 0);
7211 R_Mesh_ResetTextureState();
7212 R_SetupGenericShader(false);
7215 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7216 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7217 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7218 surfacelist[0] < 0 ? 0.5f : 0.125f);
7220 if (VectorCompare(loc->mins, loc->maxs))
7222 VectorSet(size, 2, 2, 2);
7223 VectorMA(loc->mins, -0.5f, size, mins);
7227 VectorCopy(loc->mins, mins);
7228 VectorSubtract(loc->maxs, loc->mins, size);
7231 for (i = 0;i < 6*4*3;)
7232 for (j = 0;j < 3;j++, i++)
7233 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7235 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7238 void R_DrawLocs(void)
7241 cl_locnode_t *loc, *nearestloc;
7243 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7244 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7246 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7247 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7251 void R_DrawDebugModel(entity_render_t *ent)
7253 int i, j, k, l, flagsmask;
7254 const int *elements;
7256 msurface_t *surface;
7257 dp_model_t *model = ent->model;
7260 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7262 R_Mesh_ColorPointer(NULL, 0, 0);
7263 R_Mesh_ResetTextureState();
7264 R_SetupGenericShader(false);
7265 GL_DepthRange(0, 1);
7266 GL_DepthTest(!r_showdisabledepthtest.integer);
7267 GL_DepthMask(false);
7268 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7270 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7272 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7273 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7275 if (brush->colbrushf && brush->colbrushf->numtriangles)
7277 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7278 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);
7279 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7282 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7284 if (surface->num_collisiontriangles)
7286 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7287 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);
7288 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7293 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7295 if (r_showtris.integer || r_shownormals.integer)
7297 if (r_showdisabledepthtest.integer)
7299 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7300 GL_DepthMask(false);
7304 GL_BlendFunc(GL_ONE, GL_ZERO);
7307 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7309 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7311 rsurface.texture = R_GetCurrentTexture(surface->texture);
7312 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7314 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7315 if (r_showtris.value > 0)
7317 if (!rsurface.texture->currentlayers->depthmask)
7318 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7319 else if (ent == r_refdef.scene.worldentity)
7320 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7322 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7323 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7324 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7325 R_Mesh_ColorPointer(NULL, 0, 0);
7326 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7327 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7328 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7329 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);
7330 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7333 if (r_shownormals.value < 0)
7336 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7338 VectorCopy(rsurface.vertex3f + l * 3, v);
7339 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7340 qglVertex3f(v[0], v[1], v[2]);
7341 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7342 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7343 qglVertex3f(v[0], v[1], v[2]);
7348 if (r_shownormals.value > 0)
7351 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7353 VectorCopy(rsurface.vertex3f + l * 3, v);
7354 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7355 qglVertex3f(v[0], v[1], v[2]);
7356 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7357 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7358 qglVertex3f(v[0], v[1], v[2]);
7363 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7365 VectorCopy(rsurface.vertex3f + l * 3, v);
7366 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7367 qglVertex3f(v[0], v[1], v[2]);
7368 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7369 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7370 qglVertex3f(v[0], v[1], v[2]);
7375 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7377 VectorCopy(rsurface.vertex3f + l * 3, v);
7378 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7379 qglVertex3f(v[0], v[1], v[2]);
7380 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7381 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7382 qglVertex3f(v[0], v[1], v[2]);
7389 rsurface.texture = NULL;
7393 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7394 int r_maxsurfacelist = 0;
7395 msurface_t **r_surfacelist = NULL;
7396 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7398 int i, j, endj, f, flagsmask;
7400 dp_model_t *model = r_refdef.scene.worldmodel;
7401 msurface_t *surfaces;
7402 unsigned char *update;
7403 int numsurfacelist = 0;
7407 if (r_maxsurfacelist < model->num_surfaces)
7409 r_maxsurfacelist = model->num_surfaces;
7411 Mem_Free(r_surfacelist);
7412 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7415 RSurf_ActiveWorldEntity();
7417 surfaces = model->data_surfaces;
7418 update = model->brushq1.lightmapupdateflags;
7420 // update light styles on this submodel
7421 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7423 model_brush_lightstyleinfo_t *style;
7424 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7426 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7428 int *list = style->surfacelist;
7429 style->value = r_refdef.scene.lightstylevalue[style->style];
7430 for (j = 0;j < style->numsurfaces;j++)
7431 update[list[j]] = true;
7436 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7440 R_DrawDebugModel(r_refdef.scene.worldentity);
7441 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7447 rsurface.uselightmaptexture = false;
7448 rsurface.texture = NULL;
7449 rsurface.rtlight = NULL;
7451 // add visible surfaces to draw list
7452 for (i = 0;i < model->nummodelsurfaces;i++)
7454 j = model->sortedmodelsurfaces[i];
7455 if (r_refdef.viewcache.world_surfacevisible[j])
7456 r_surfacelist[numsurfacelist++] = surfaces + j;
7458 // update lightmaps if needed
7460 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7461 if (r_refdef.viewcache.world_surfacevisible[j])
7463 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7464 // don't do anything if there were no surfaces
7465 if (!numsurfacelist)
7467 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7470 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7471 GL_AlphaTest(false);
7473 // add to stats if desired
7474 if (r_speeds.integer && !skysurfaces && !depthonly)
7476 r_refdef.stats.world_surfaces += numsurfacelist;
7477 for (j = 0;j < numsurfacelist;j++)
7478 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7480 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7483 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7485 int i, j, endj, f, flagsmask;
7487 dp_model_t *model = ent->model;
7488 msurface_t *surfaces;
7489 unsigned char *update;
7490 int numsurfacelist = 0;
7494 if (r_maxsurfacelist < model->num_surfaces)
7496 r_maxsurfacelist = model->num_surfaces;
7498 Mem_Free(r_surfacelist);
7499 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7502 // if the model is static it doesn't matter what value we give for
7503 // wantnormals and wanttangents, so this logic uses only rules applicable
7504 // to a model, knowing that they are meaningless otherwise
7505 if (ent == r_refdef.scene.worldentity)
7506 RSurf_ActiveWorldEntity();
7507 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7508 RSurf_ActiveModelEntity(ent, false, false);
7510 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7512 surfaces = model->data_surfaces;
7513 update = model->brushq1.lightmapupdateflags;
7515 // update light styles
7516 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7518 model_brush_lightstyleinfo_t *style;
7519 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7521 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7523 int *list = style->surfacelist;
7524 style->value = r_refdef.scene.lightstylevalue[style->style];
7525 for (j = 0;j < style->numsurfaces;j++)
7526 update[list[j]] = true;
7531 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7535 R_DrawDebugModel(ent);
7536 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7542 rsurface.uselightmaptexture = false;
7543 rsurface.texture = NULL;
7544 rsurface.rtlight = NULL;
7546 // add visible surfaces to draw list
7547 for (i = 0;i < model->nummodelsurfaces;i++)
7548 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7549 // don't do anything if there were no surfaces
7550 if (!numsurfacelist)
7552 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7555 // update lightmaps if needed
7557 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7559 R_BuildLightMap(ent, surfaces + j);
7560 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7561 GL_AlphaTest(false);
7563 // add to stats if desired
7564 if (r_speeds.integer && !skysurfaces && !depthonly)
7566 r_refdef.stats.entities_surfaces += numsurfacelist;
7567 for (j = 0;j < numsurfacelist;j++)
7568 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7570 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity