2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
38 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
42 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
43 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
44 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
46 cvar_t r_motionblur_debug = {0, "r_motionblur_debug", "0", "outputs current motionblur alpha value"};
48 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
50 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
51 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
52 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
53 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
54 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
55 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
56 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
57 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
58 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
59 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
60 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
61 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
62 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
63 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
64 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
65 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
66 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
67 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
68 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
69 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
70 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
71 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
72 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
73 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
74 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
75 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows DOWN, otherwise use the model lighting"};
76 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
77 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
78 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
79 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
80 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
81 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
83 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
84 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
85 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
86 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
87 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
88 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
89 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
90 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
92 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
94 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
95 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
96 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
97 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
98 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
99 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
100 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
101 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
102 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
103 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
104 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
105 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
107 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
108 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
109 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
110 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
111 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
113 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
114 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
115 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
116 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
118 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
119 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
120 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
121 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
122 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
123 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
124 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
126 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
127 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
128 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
129 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
131 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
133 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
135 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
137 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
138 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
139 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
140 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
141 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
142 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
143 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
145 extern cvar_t v_glslgamma;
147 extern qboolean v_flipped_state;
149 static struct r_bloomstate_s
154 int bloomwidth, bloomheight;
156 int screentexturewidth, screentextureheight;
157 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
159 int bloomtexturewidth, bloomtextureheight;
160 rtexture_t *texture_bloom;
162 // arrays for rendering the screen passes
163 float screentexcoord2f[8];
164 float bloomtexcoord2f[8];
165 float offsettexcoord2f[8];
169 r_waterstate_t r_waterstate;
171 /// shadow volume bsp struct with automatically growing nodes buffer
174 rtexture_t *r_texture_blanknormalmap;
175 rtexture_t *r_texture_white;
176 rtexture_t *r_texture_grey128;
177 rtexture_t *r_texture_black;
178 rtexture_t *r_texture_notexture;
179 rtexture_t *r_texture_whitecube;
180 rtexture_t *r_texture_normalizationcube;
181 rtexture_t *r_texture_fogattenuation;
182 rtexture_t *r_texture_gammaramps;
183 unsigned int r_texture_gammaramps_serial;
184 //rtexture_t *r_texture_fogintensity;
186 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
187 unsigned int r_numqueries;
188 unsigned int r_maxqueries;
190 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
191 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
193 /// vertex coordinates for a quad that covers the screen exactly
194 const static float r_screenvertex3f[12] =
202 extern void R_DrawModelShadows(void);
204 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
207 for (i = 0;i < verts;i++)
218 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
221 for (i = 0;i < verts;i++)
231 // FIXME: move this to client?
234 if (gamemode == GAME_NEHAHRA)
236 Cvar_Set("gl_fogenable", "0");
237 Cvar_Set("gl_fogdensity", "0.2");
238 Cvar_Set("gl_fogred", "0.3");
239 Cvar_Set("gl_foggreen", "0.3");
240 Cvar_Set("gl_fogblue", "0.3");
242 r_refdef.fog_density = 0;
243 r_refdef.fog_red = 0;
244 r_refdef.fog_green = 0;
245 r_refdef.fog_blue = 0;
246 r_refdef.fog_alpha = 1;
247 r_refdef.fog_start = 0;
248 r_refdef.fog_end = 0;
251 float FogForDistance(vec_t dist)
253 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
254 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
257 float FogPoint_World(const vec3_t p)
259 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
262 float FogPoint_Model(const vec3_t p)
264 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
267 static void R_BuildBlankTextures(void)
269 unsigned char data[4];
270 data[2] = 128; // normal X
271 data[1] = 128; // normal Y
272 data[0] = 255; // normal Z
273 data[3] = 128; // height
274 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
279 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
284 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
289 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
292 static void R_BuildNoTexture(void)
295 unsigned char pix[16][16][4];
296 // this makes a light grey/dark grey checkerboard texture
297 for (y = 0;y < 16;y++)
299 for (x = 0;x < 16;x++)
301 if ((y < 8) ^ (x < 8))
317 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
320 static void R_BuildWhiteCube(void)
322 unsigned char data[6*1*1*4];
323 memset(data, 255, sizeof(data));
324 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
327 static void R_BuildNormalizationCube(void)
331 vec_t s, t, intensity;
333 unsigned char data[6][NORMSIZE][NORMSIZE][4];
334 for (side = 0;side < 6;side++)
336 for (y = 0;y < NORMSIZE;y++)
338 for (x = 0;x < NORMSIZE;x++)
340 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
341 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
376 intensity = 127.0f / sqrt(DotProduct(v, v));
377 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
378 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
379 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
380 data[side][y][x][3] = 255;
384 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
387 static void R_BuildFogTexture(void)
391 unsigned char data1[FOGWIDTH][4];
392 //unsigned char data2[FOGWIDTH][4];
395 r_refdef.fogmasktable_start = r_refdef.fog_start;
396 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
397 r_refdef.fogmasktable_range = r_refdef.fogrange;
398 r_refdef.fogmasktable_density = r_refdef.fog_density;
400 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
401 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
403 d = (x * r - r_refdef.fogmasktable_start);
404 if(developer.integer >= 100)
405 Con_Printf("%f ", d);
407 if (r_fog_exp2.integer)
408 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
410 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
411 if(developer.integer >= 100)
412 Con_Printf(" : %f ", alpha);
413 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
414 if(developer.integer >= 100)
415 Con_Printf(" = %f\n", alpha);
416 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
419 for (x = 0;x < FOGWIDTH;x++)
421 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
426 //data2[x][0] = 255 - b;
427 //data2[x][1] = 255 - b;
428 //data2[x][2] = 255 - b;
431 if (r_texture_fogattenuation)
433 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
434 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
438 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
439 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
443 static const char *builtinshaderstring =
444 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
445 "// written by Forest 'LordHavoc' Hale\n"
447 "// common definitions between vertex shader and fragment shader:\n"
449 "//#ifdef __GLSL_CG_DATA_TYPES\n"
450 "//# define myhalf half\n"
451 "//# define myhalf2 half2\n"
452 "//# define myhalf3 half3\n"
453 "//# define myhalf4 half4\n"
455 "# define myhalf float\n"
456 "# define myhalf2 vec2\n"
457 "# define myhalf3 vec3\n"
458 "# define myhalf4 vec4\n"
461 "#ifdef MODE_DEPTH_OR_SHADOW\n"
463 "# ifdef VERTEX_SHADER\n"
466 " gl_Position = ftransform();\n"
472 "#ifdef MODE_POSTPROCESS\n"
473 "# ifdef VERTEX_SHADER\n"
476 " gl_FrontColor = gl_Color;\n"
477 " gl_Position = ftransform();\n"
478 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
480 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
484 "# ifdef FRAGMENT_SHADER\n"
486 "uniform sampler2D Texture_First;\n"
488 "uniform sampler2D Texture_Second;\n"
490 "#ifdef USEGAMMARAMPS\n"
491 "uniform sampler2D Texture_GammaRamps;\n"
493 "#ifdef USESATURATION\n"
494 "uniform float Saturation;\n"
496 "#ifdef USEVERTEXTEXTUREBLEND\n"
497 "uniform vec4 TintColor;\n"
499 "#ifdef USECOLORMOD\n"
500 "uniform vec3 Gamma;\n"
502 "//uncomment these if you want to use them:\n"
503 "uniform vec4 UserVec1;\n"
504 "// uniform vec4 UserVec2;\n"
505 "// uniform vec4 UserVec3;\n"
506 "// uniform vec4 UserVec4;\n"
507 "// uniform float ClientTime;\n"
508 "uniform vec2 PixelSize;\n"
511 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
513 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
515 "#ifdef USEVERTEXTEXTUREBLEND\n"
516 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
519 "#ifdef USEPOSTPROCESSING\n"
520 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
521 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
522 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
523 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
524 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
525 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
526 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
527 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
530 "#ifdef USESATURATION\n"
531 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
532 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
533 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
534 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" // TODO: test this on ATI
537 "#ifdef USEGAMMARAMPS\n"
538 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
539 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
540 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
547 "#ifdef MODE_GENERIC\n"
548 "# ifdef VERTEX_SHADER\n"
551 " gl_FrontColor = gl_Color;\n"
552 "# ifdef USEDIFFUSE\n"
553 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
555 "# ifdef USESPECULAR\n"
556 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
558 " gl_Position = ftransform();\n"
561 "# ifdef FRAGMENT_SHADER\n"
563 "# ifdef USEDIFFUSE\n"
564 "uniform sampler2D Texture_First;\n"
566 "# ifdef USESPECULAR\n"
567 "uniform sampler2D Texture_Second;\n"
572 " gl_FragColor = gl_Color;\n"
573 "# ifdef USEDIFFUSE\n"
574 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
577 "# ifdef USESPECULAR\n"
578 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
580 "# ifdef USECOLORMAPPING\n"
581 " gl_FragColor *= tex2;\n"
584 " gl_FragColor += tex2;\n"
586 "# ifdef USEVERTEXTEXTUREBLEND\n"
587 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
592 "#else // !MODE_GENERIC\n"
594 "varying vec2 TexCoord;\n"
595 "#ifdef USEVERTEXTEXTUREBLEND\n"
596 "varying vec2 TexCoord2;\n"
598 "varying vec2 TexCoordLightmap;\n"
600 "#ifdef MODE_LIGHTSOURCE\n"
601 "varying vec3 CubeVector;\n"
604 "#ifdef MODE_LIGHTSOURCE\n"
605 "varying vec3 LightVector;\n"
607 "#ifdef MODE_LIGHTDIRECTION\n"
608 "varying vec3 LightVector;\n"
611 "varying vec3 EyeVector;\n"
613 "varying vec3 EyeVectorModelSpace;\n"
616 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
617 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
618 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
620 "#ifdef MODE_WATER\n"
621 "varying vec4 ModelViewProjectionPosition;\n"
623 "#ifdef MODE_REFRACTION\n"
624 "varying vec4 ModelViewProjectionPosition;\n"
626 "#ifdef USEREFLECTION\n"
627 "varying vec4 ModelViewProjectionPosition;\n"
634 "// vertex shader specific:\n"
635 "#ifdef VERTEX_SHADER\n"
637 "uniform vec3 LightPosition;\n"
638 "uniform vec3 EyePosition;\n"
639 "uniform vec3 LightDir;\n"
641 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
645 " gl_FrontColor = gl_Color;\n"
646 " // copy the surface texcoord\n"
647 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
648 "#ifdef USEVERTEXTEXTUREBLEND\n"
649 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
651 "#ifndef MODE_LIGHTSOURCE\n"
652 "# ifndef MODE_LIGHTDIRECTION\n"
653 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
657 "#ifdef MODE_LIGHTSOURCE\n"
658 " // transform vertex position into light attenuation/cubemap space\n"
659 " // (-1 to +1 across the light box)\n"
660 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
662 " // transform unnormalized light direction into tangent space\n"
663 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
664 " // normalize it per pixel)\n"
665 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
666 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
667 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
668 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
671 "#ifdef MODE_LIGHTDIRECTION\n"
672 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
673 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
674 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
677 " // transform unnormalized eye direction into tangent space\n"
679 " vec3 EyeVectorModelSpace;\n"
681 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
682 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
683 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
684 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
686 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
687 " VectorS = gl_MultiTexCoord1.xyz;\n"
688 " VectorT = gl_MultiTexCoord2.xyz;\n"
689 " VectorR = gl_MultiTexCoord3.xyz;\n"
692 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
693 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
694 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
695 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
698 "// transform vertex to camera space, using ftransform to match non-VS\n"
700 " gl_Position = ftransform();\n"
702 "#ifdef MODE_WATER\n"
703 " ModelViewProjectionPosition = gl_Position;\n"
705 "#ifdef MODE_REFRACTION\n"
706 " ModelViewProjectionPosition = gl_Position;\n"
708 "#ifdef USEREFLECTION\n"
709 " ModelViewProjectionPosition = gl_Position;\n"
713 "#endif // VERTEX_SHADER\n"
718 "// fragment shader specific:\n"
719 "#ifdef FRAGMENT_SHADER\n"
721 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
722 "uniform sampler2D Texture_Normal;\n"
723 "uniform sampler2D Texture_Color;\n"
724 "uniform sampler2D Texture_Gloss;\n"
725 "uniform sampler2D Texture_Glow;\n"
726 "uniform sampler2D Texture_SecondaryNormal;\n"
727 "uniform sampler2D Texture_SecondaryColor;\n"
728 "uniform sampler2D Texture_SecondaryGloss;\n"
729 "uniform sampler2D Texture_SecondaryGlow;\n"
730 "uniform sampler2D Texture_Pants;\n"
731 "uniform sampler2D Texture_Shirt;\n"
732 "uniform sampler2D Texture_FogMask;\n"
733 "uniform sampler2D Texture_Lightmap;\n"
734 "uniform sampler2D Texture_Deluxemap;\n"
735 "uniform sampler2D Texture_Refraction;\n"
736 "uniform sampler2D Texture_Reflection;\n"
737 "uniform sampler2D Texture_Attenuation;\n"
738 "uniform samplerCube Texture_Cube;\n"
740 "uniform myhalf3 LightColor;\n"
741 "uniform myhalf3 AmbientColor;\n"
742 "uniform myhalf3 DiffuseColor;\n"
743 "uniform myhalf3 SpecularColor;\n"
744 "uniform myhalf3 Color_Pants;\n"
745 "uniform myhalf3 Color_Shirt;\n"
746 "uniform myhalf3 FogColor;\n"
748 "uniform myhalf4 TintColor;\n"
751 "//#ifdef MODE_WATER\n"
752 "uniform vec4 DistortScaleRefractReflect;\n"
753 "uniform vec4 ScreenScaleRefractReflect;\n"
754 "uniform vec4 ScreenCenterRefractReflect;\n"
755 "uniform myhalf4 RefractColor;\n"
756 "uniform myhalf4 ReflectColor;\n"
757 "uniform myhalf ReflectFactor;\n"
758 "uniform myhalf ReflectOffset;\n"
760 "//# ifdef MODE_REFRACTION\n"
761 "//uniform vec4 DistortScaleRefractReflect;\n"
762 "//uniform vec4 ScreenScaleRefractReflect;\n"
763 "//uniform vec4 ScreenCenterRefractReflect;\n"
764 "//uniform myhalf4 RefractColor;\n"
765 "//# ifdef USEREFLECTION\n"
766 "//uniform myhalf4 ReflectColor;\n"
769 "//# ifdef USEREFLECTION\n"
770 "//uniform vec4 DistortScaleRefractReflect;\n"
771 "//uniform vec4 ScreenScaleRefractReflect;\n"
772 "//uniform vec4 ScreenCenterRefractReflect;\n"
773 "//uniform myhalf4 ReflectColor;\n"
778 "uniform myhalf GlowScale;\n"
779 "uniform myhalf SceneBrightness;\n"
780 "#ifdef USECONTRASTBOOST\n"
781 "uniform myhalf ContrastBoostCoeff;\n"
784 "uniform float OffsetMapping_Scale;\n"
785 "uniform float OffsetMapping_Bias;\n"
786 "uniform float FogRangeRecip;\n"
788 "uniform myhalf AmbientScale;\n"
789 "uniform myhalf DiffuseScale;\n"
790 "uniform myhalf SpecularScale;\n"
791 "uniform myhalf SpecularPower;\n"
793 "#ifdef USEOFFSETMAPPING\n"
794 "vec2 OffsetMapping(vec2 TexCoord)\n"
796 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
797 " // 14 sample relief mapping: linear search and then binary search\n"
798 " // this basically steps forward a small amount repeatedly until it finds\n"
799 " // itself inside solid, then jitters forward and back using decreasing\n"
800 " // amounts to find the impact\n"
801 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
802 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
803 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
804 " vec3 RT = vec3(TexCoord, 1);\n"
805 " OffsetVector *= 0.1;\n"
806 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
807 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
808 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
809 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
810 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
811 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
812 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
813 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
814 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
815 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
816 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
817 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
818 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
819 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
822 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
823 " // this basically moves forward the full distance, and then backs up based\n"
824 " // on height of samples\n"
825 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
826 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
827 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
828 " TexCoord += OffsetVector;\n"
829 " OffsetVector *= 0.333;\n"
830 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
831 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
832 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
833 " return TexCoord;\n"
836 "#endif // USEOFFSETMAPPING\n"
838 "#ifdef MODE_WATER\n"
843 "#ifdef USEOFFSETMAPPING\n"
844 " // apply offsetmapping\n"
845 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
846 "#define TexCoord TexCoordOffset\n"
849 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
850 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
851 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
852 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
853 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
856 "#else // !MODE_WATER\n"
857 "#ifdef MODE_REFRACTION\n"
859 "// refraction pass\n"
862 "#ifdef USEOFFSETMAPPING\n"
863 " // apply offsetmapping\n"
864 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
865 "#define TexCoord TexCoordOffset\n"
868 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
869 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
870 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
871 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
874 "#else // !MODE_REFRACTION\n"
877 "#ifdef USEOFFSETMAPPING\n"
878 " // apply offsetmapping\n"
879 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
880 "#define TexCoord TexCoordOffset\n"
883 " // combine the diffuse textures (base, pants, shirt)\n"
884 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
885 "#ifdef USECOLORMAPPING\n"
886 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
888 "#ifdef USEVERTEXTEXTUREBLEND\n"
889 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
890 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
891 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
892 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
894 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
897 "#ifdef USEDIFFUSE\n"
898 " // get the surface normal and the gloss color\n"
899 "# ifdef USEVERTEXTEXTUREBLEND\n"
900 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
901 "# ifdef USESPECULAR\n"
902 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
905 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
906 "# ifdef USESPECULAR\n"
907 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
914 "#ifdef MODE_LIGHTSOURCE\n"
917 " // calculate surface normal, light normal, and specular normal\n"
918 " // compute color intensity for the two textures (colormap and glossmap)\n"
919 " // scale by light color and attenuation as efficiently as possible\n"
920 " // (do as much scalar math as possible rather than vector math)\n"
921 "# ifdef USEDIFFUSE\n"
922 " // get the light normal\n"
923 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
925 "# ifdef USESPECULAR\n"
926 "# ifndef USEEXACTSPECULARMATH\n"
927 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
930 " // calculate directional shading\n"
931 "# ifdef USEEXACTSPECULARMATH\n"
932 " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n"
934 " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * glosscolor);\n"
937 "# ifdef USEDIFFUSE\n"
938 " // calculate directional shading\n"
939 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
941 " // calculate directionless shading\n"
942 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
946 "# ifdef USECUBEFILTER\n"
947 " // apply light cubemap filter\n"
948 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
949 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
951 "#endif // MODE_LIGHTSOURCE\n"
956 "#ifdef MODE_LIGHTDIRECTION\n"
957 " // directional model lighting\n"
958 "# ifdef USEDIFFUSE\n"
959 " // get the light normal\n"
960 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
962 "# ifdef USESPECULAR\n"
963 " // calculate directional shading\n"
964 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
965 "# ifdef USEEXACTSPECULARMATH\n"
966 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
968 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
969 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
972 "# ifdef USEDIFFUSE\n"
974 " // calculate directional shading\n"
975 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
977 " color.rgb *= AmbientColor;\n"
980 "#endif // MODE_LIGHTDIRECTION\n"
985 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
986 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
988 " // get the light normal\n"
989 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
990 " myhalf3 diffusenormal;\n"
991 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
992 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
993 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
994 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
995 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
996 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
997 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
998 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
999 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1000 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1001 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1002 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1003 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1004 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1005 "# ifdef USESPECULAR\n"
1006 "# ifdef USEEXACTSPECULARMATH\n"
1007 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1009 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1010 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1014 " // apply lightmap color\n"
1015 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1016 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1021 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1022 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1024 " // get the light normal\n"
1025 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1026 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1027 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1028 "# ifdef USESPECULAR\n"
1029 "# ifdef USEEXACTSPECULARMATH\n"
1030 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1032 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1033 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1037 " // apply lightmap color\n"
1038 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1039 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1044 "#ifdef MODE_LIGHTMAP\n"
1045 " // apply lightmap color\n"
1046 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1047 "#endif // MODE_LIGHTMAP\n"
1052 "#ifdef MODE_VERTEXCOLOR\n"
1053 " // apply lightmap color\n"
1054 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1055 "#endif // MODE_VERTEXCOLOR\n"
1060 "#ifdef MODE_FLATCOLOR\n"
1061 "#endif // MODE_FLATCOLOR\n"
1069 " color *= TintColor;\n"
1072 "#ifdef USEVERTEXTEXTUREBLEND\n"
1073 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1075 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1079 "#ifdef USECONTRASTBOOST\n"
1080 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1083 " color.rgb *= SceneBrightness;\n"
1085 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1087 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1090 " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1091 "#ifdef USEREFLECTION\n"
1092 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1093 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1094 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1095 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1098 " gl_FragColor = vec4(color);\n"
1100 "#endif // !MODE_REFRACTION\n"
1101 "#endif // !MODE_WATER\n"
1103 "#endif // FRAGMENT_SHADER\n"
1105 "#endif // !MODE_GENERIC\n"
1106 "#endif // !MODE_POSTPROCESS\n"
1107 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1110 typedef struct shaderpermutationinfo_s
1112 const char *pretext;
1115 shaderpermutationinfo_t;
1117 typedef struct shadermodeinfo_s
1119 const char *vertexfilename;
1120 const char *geometryfilename;
1121 const char *fragmentfilename;
1122 const char *pretext;
1127 typedef enum shaderpermutation_e
1129 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1130 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1131 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1132 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, ///< r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1133 SHADERPERMUTATION_FOG = 1<<4, ///< tint the color by fog color or black if using additive blend mode
1134 SHADERPERMUTATION_CUBEFILTER = 1<<5, ///< (lightsource) use cubemap light filter
1135 SHADERPERMUTATION_GLOW = 1<<6, ///< (lightmap) blend in an additive glow texture
1136 SHADERPERMUTATION_SPECULAR = 1<<7, ///< (lightsource or deluxemapping) render specular effects
1137 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1138 SHADERPERMUTATION_REFLECTION = 1<<9, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1139 SHADERPERMUTATION_OFFSETMAPPING = 1<<10, ///< adjust texcoords to roughly simulate a displacement mapped surface
1140 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1141 SHADERPERMUTATION_GAMMARAMPS = 1<<12, ///< gamma (postprocessing only)
1142 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing
1143 SHADERPERMUTATION_SATURATION = 1<<14, ///< user defined postprocessing
1144 SHADERPERMUTATION_LIMIT = 1<<15, ///< size of permutations array
1145 SHADERPERMUTATION_COUNT = 15 ///< size of shaderpermutationinfo array
1147 shaderpermutation_t;
1149 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1150 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1152 {"#define USEDIFFUSE\n", " diffuse"},
1153 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1154 {"#define USECOLORMAPPING\n", " colormapping"},
1155 {"#define USECONTRASTBOOST\n", " contrastboost"},
1156 {"#define USEFOG\n", " fog"},
1157 {"#define USECUBEFILTER\n", " cubefilter"},
1158 {"#define USEGLOW\n", " glow"},
1159 {"#define USESPECULAR\n", " specular"},
1160 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1161 {"#define USEREFLECTION\n", " reflection"},
1162 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1163 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1164 {"#define USEGAMMARAMPS\n", " gammaramps"},
1165 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1166 {"#define USESATURATION\n", " saturation"},
1169 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1170 typedef enum shadermode_e
1172 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1173 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1174 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1175 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1176 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1177 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1178 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1179 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1180 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1181 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1182 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1183 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1188 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1189 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1191 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1192 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1193 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1194 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1195 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1196 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1197 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1198 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1199 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1200 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1201 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1202 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1205 typedef struct r_glsl_permutation_s
1207 /// indicates if we have tried compiling this permutation already
1209 /// 0 if compilation failed
1211 /// locations of detected uniforms in program object, or -1 if not found
1212 int loc_Texture_First;
1213 int loc_Texture_Second;
1214 int loc_Texture_GammaRamps;
1215 int loc_Texture_Normal;
1216 int loc_Texture_Color;
1217 int loc_Texture_Gloss;
1218 int loc_Texture_Glow;
1219 int loc_Texture_SecondaryNormal;
1220 int loc_Texture_SecondaryColor;
1221 int loc_Texture_SecondaryGloss;
1222 int loc_Texture_SecondaryGlow;
1223 int loc_Texture_Pants;
1224 int loc_Texture_Shirt;
1225 int loc_Texture_FogMask;
1226 int loc_Texture_Lightmap;
1227 int loc_Texture_Deluxemap;
1228 int loc_Texture_Attenuation;
1229 int loc_Texture_Cube;
1230 int loc_Texture_Refraction;
1231 int loc_Texture_Reflection;
1233 int loc_LightPosition;
1234 int loc_EyePosition;
1235 int loc_Color_Pants;
1236 int loc_Color_Shirt;
1237 int loc_FogRangeRecip;
1238 int loc_AmbientScale;
1239 int loc_DiffuseScale;
1240 int loc_SpecularScale;
1241 int loc_SpecularPower;
1243 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1244 int loc_OffsetMapping_Scale;
1246 int loc_AmbientColor;
1247 int loc_DiffuseColor;
1248 int loc_SpecularColor;
1250 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1251 int loc_GammaCoeff; ///< 1 / gamma
1252 int loc_DistortScaleRefractReflect;
1253 int loc_ScreenScaleRefractReflect;
1254 int loc_ScreenCenterRefractReflect;
1255 int loc_RefractColor;
1256 int loc_ReflectColor;
1257 int loc_ReflectFactor;
1258 int loc_ReflectOffset;
1267 r_glsl_permutation_t;
1269 /// information about each possible shader permutation
1270 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1271 /// currently selected permutation
1272 r_glsl_permutation_t *r_glsl_permutation;
1274 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1277 if (!filename || !filename[0])
1279 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1282 if (printfromdisknotice)
1283 Con_DPrint("from disk... ");
1284 return shaderstring;
1286 else if (!strcmp(filename, "glsl/default.glsl"))
1288 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1289 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1291 return shaderstring;
1294 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1297 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1298 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1299 int vertstrings_count = 0;
1300 int geomstrings_count = 0;
1301 int fragstrings_count = 0;
1302 char *vertexstring, *geometrystring, *fragmentstring;
1303 const char *vertstrings_list[32+3];
1304 const char *geomstrings_list[32+3];
1305 const char *fragstrings_list[32+3];
1306 char permutationname[256];
1313 permutationname[0] = 0;
1314 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1315 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1316 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1318 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1320 // the first pretext is which type of shader to compile as
1321 // (later these will all be bound together as a program object)
1322 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1323 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1324 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1326 // the second pretext is the mode (for example a light source)
1327 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1328 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1329 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1330 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1332 // now add all the permutation pretexts
1333 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1335 if (permutation & (1<<i))
1337 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1338 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1339 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1340 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1344 // keep line numbers correct
1345 vertstrings_list[vertstrings_count++] = "\n";
1346 geomstrings_list[geomstrings_count++] = "\n";
1347 fragstrings_list[fragstrings_count++] = "\n";
1351 // now append the shader text itself
1352 vertstrings_list[vertstrings_count++] = vertexstring;
1353 geomstrings_list[geomstrings_count++] = geometrystring;
1354 fragstrings_list[fragstrings_count++] = fragmentstring;
1356 // if any sources were NULL, clear the respective list
1358 vertstrings_count = 0;
1359 if (!geometrystring)
1360 geomstrings_count = 0;
1361 if (!fragmentstring)
1362 fragstrings_count = 0;
1364 // compile the shader program
1365 if (vertstrings_count + geomstrings_count + fragstrings_count)
1366 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1370 qglUseProgramObjectARB(p->program);CHECKGLERROR
1371 // look up all the uniform variable names we care about, so we don't
1372 // have to look them up every time we set them
1373 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1374 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1375 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1376 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1377 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1378 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1379 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1380 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1381 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1382 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1383 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1384 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1385 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1386 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1387 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1388 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1389 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1390 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1391 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1392 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1393 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1394 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1395 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1396 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1397 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1398 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1399 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1400 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1401 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1402 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1403 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1404 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1405 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1406 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1407 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1408 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1409 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1410 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1411 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1412 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1413 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1414 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1415 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1416 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1417 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1418 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1419 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1420 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1421 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1422 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1423 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1424 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1425 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1426 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1427 // initialize the samplers to refer to the texture units we use
1428 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1429 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1430 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1431 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1432 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1433 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1434 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1435 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1436 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1437 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1438 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1439 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1440 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1441 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1442 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1443 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1444 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1445 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1446 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1447 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1449 if (developer.integer)
1450 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1453 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1457 Mem_Free(vertexstring);
1459 Mem_Free(geometrystring);
1461 Mem_Free(fragmentstring);
1464 void R_GLSL_Restart_f(void)
1467 unsigned int permutation;
1468 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1469 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1470 if (r_glsl_permutations[mode][permutation].program)
1471 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1472 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1475 void R_GLSL_DumpShader_f(void)
1479 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1482 Con_Printf("failed to write to glsl/default.glsl\n");
1486 FS_Print(file, "// The engine may define the following macros:\n");
1487 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1488 for (i = 0;i < SHADERMODE_COUNT;i++)
1489 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1490 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1491 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1492 FS_Print(file, "\n");
1493 FS_Print(file, builtinshaderstring);
1496 Con_Printf("glsl/default.glsl written\n");
1499 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1501 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1502 if (r_glsl_permutation != perm)
1504 r_glsl_permutation = perm;
1505 if (!r_glsl_permutation->program)
1507 if (!r_glsl_permutation->compiled)
1508 R_GLSL_CompilePermutation(mode, permutation);
1509 if (!r_glsl_permutation->program)
1511 // remove features until we find a valid permutation
1513 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1515 // reduce i more quickly whenever it would not remove any bits
1516 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1517 if (!(permutation & j))
1520 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1521 if (!r_glsl_permutation->compiled)
1522 R_GLSL_CompilePermutation(mode, permutation);
1523 if (r_glsl_permutation->program)
1526 if (i >= SHADERPERMUTATION_COUNT)
1528 Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n");
1529 Cvar_SetValueQuick(&r_glsl, 0);
1530 R_GLSL_Restart_f(); // unload shaders
1531 return; // no bit left to clear
1536 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1540 void R_SetupGenericShader(qboolean usetexture)
1542 if (gl_support_fragment_shader)
1544 if (r_glsl.integer && r_glsl_usegeneric.integer)
1545 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1546 else if (r_glsl_permutation)
1548 r_glsl_permutation = NULL;
1549 qglUseProgramObjectARB(0);CHECKGLERROR
1554 void R_SetupGenericTwoTextureShader(int texturemode)
1556 if (gl_support_fragment_shader)
1558 if (r_glsl.integer && r_glsl_usegeneric.integer)
1559 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1560 else if (r_glsl_permutation)
1562 r_glsl_permutation = NULL;
1563 qglUseProgramObjectARB(0);CHECKGLERROR
1566 if (!r_glsl_permutation)
1568 if (texturemode == GL_DECAL && gl_combine.integer)
1569 texturemode = GL_INTERPOLATE_ARB;
1570 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1574 void R_SetupDepthOrShadowShader(void)
1576 if (gl_support_fragment_shader)
1578 if (r_glsl.integer && r_glsl_usegeneric.integer)
1579 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1580 else if (r_glsl_permutation)
1582 r_glsl_permutation = NULL;
1583 qglUseProgramObjectARB(0);CHECKGLERROR
1588 extern rtexture_t *r_shadow_attenuationgradienttexture;
1589 extern rtexture_t *r_shadow_attenuation2dtexture;
1590 extern rtexture_t *r_shadow_attenuation3dtexture;
1591 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1593 // select a permutation of the lighting shader appropriate to this
1594 // combination of texture, entity, light source, and fogging, only use the
1595 // minimum features necessary to avoid wasting rendering time in the
1596 // fragment shader on features that are not being used
1597 unsigned int permutation = 0;
1598 unsigned int mode = 0;
1599 // TODO: implement geometry-shader based shadow volumes someday
1600 if (r_glsl_offsetmapping.integer)
1602 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1603 if (r_glsl_offsetmapping_reliefmapping.integer)
1604 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1606 if (rsurfacepass == RSURFPASS_BACKGROUND)
1608 // distorted background
1609 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1610 mode = SHADERMODE_WATER;
1612 mode = SHADERMODE_REFRACTION;
1614 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1617 mode = SHADERMODE_LIGHTSOURCE;
1618 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1619 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1620 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1621 permutation |= SHADERPERMUTATION_CUBEFILTER;
1622 if (diffusescale > 0)
1623 permutation |= SHADERPERMUTATION_DIFFUSE;
1624 if (specularscale > 0)
1625 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1626 if (r_refdef.fogenabled)
1627 permutation |= SHADERPERMUTATION_FOG;
1628 if (rsurface.texture->colormapping)
1629 permutation |= SHADERPERMUTATION_COLORMAPPING;
1630 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1631 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1633 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1635 // unshaded geometry (fullbright or ambient model lighting)
1636 mode = SHADERMODE_FLATCOLOR;
1637 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1638 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1639 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1640 permutation |= SHADERPERMUTATION_GLOW;
1641 if (r_refdef.fogenabled)
1642 permutation |= SHADERPERMUTATION_FOG;
1643 if (rsurface.texture->colormapping)
1644 permutation |= SHADERPERMUTATION_COLORMAPPING;
1645 if (r_glsl_offsetmapping.integer)
1647 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1648 if (r_glsl_offsetmapping_reliefmapping.integer)
1649 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1651 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1652 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1653 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1654 permutation |= SHADERPERMUTATION_REFLECTION;
1656 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1658 // directional model lighting
1659 mode = SHADERMODE_LIGHTDIRECTION;
1660 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1661 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1662 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1663 permutation |= SHADERPERMUTATION_GLOW;
1664 permutation |= SHADERPERMUTATION_DIFFUSE;
1665 if (specularscale > 0)
1666 permutation |= SHADERPERMUTATION_SPECULAR;
1667 if (r_refdef.fogenabled)
1668 permutation |= SHADERPERMUTATION_FOG;
1669 if (rsurface.texture->colormapping)
1670 permutation |= SHADERPERMUTATION_COLORMAPPING;
1671 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1672 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1673 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1674 permutation |= SHADERPERMUTATION_REFLECTION;
1676 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1678 // ambient model lighting
1679 mode = SHADERMODE_LIGHTDIRECTION;
1680 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1681 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1682 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1683 permutation |= SHADERPERMUTATION_GLOW;
1684 if (r_refdef.fogenabled)
1685 permutation |= SHADERPERMUTATION_FOG;
1686 if (rsurface.texture->colormapping)
1687 permutation |= SHADERPERMUTATION_COLORMAPPING;
1688 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1689 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1690 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1691 permutation |= SHADERPERMUTATION_REFLECTION;
1696 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1698 // deluxemapping (light direction texture)
1699 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1700 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1702 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1703 permutation |= SHADERPERMUTATION_DIFFUSE;
1704 if (specularscale > 0)
1705 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1707 else if (r_glsl_deluxemapping.integer >= 2)
1709 // fake deluxemapping (uniform light direction in tangentspace)
1710 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1711 permutation |= SHADERPERMUTATION_DIFFUSE;
1712 if (specularscale > 0)
1713 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1715 else if (rsurface.uselightmaptexture)
1717 // ordinary lightmapping (q1bsp, q3bsp)
1718 mode = SHADERMODE_LIGHTMAP;
1722 // ordinary vertex coloring (q3bsp)
1723 mode = SHADERMODE_VERTEXCOLOR;
1725 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1726 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1727 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1728 permutation |= SHADERPERMUTATION_GLOW;
1729 if (r_refdef.fogenabled)
1730 permutation |= SHADERPERMUTATION_FOG;
1731 if (rsurface.texture->colormapping)
1732 permutation |= SHADERPERMUTATION_COLORMAPPING;
1733 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1734 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1735 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1736 permutation |= SHADERPERMUTATION_REFLECTION;
1738 if(permutation & SHADERPERMUTATION_SPECULAR)
1739 if(r_shadow_glossexact.integer)
1740 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
1741 R_SetupShader_SetPermutation(mode, permutation);
1742 if (mode == SHADERMODE_LIGHTSOURCE)
1744 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1745 if (permutation & SHADERPERMUTATION_DIFFUSE)
1747 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1748 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1749 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1750 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1754 // ambient only is simpler
1755 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale, rsurface.texture->lightmapcolor[3]);
1756 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1757 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1758 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1760 // additive passes are only darkened by fog, not tinted
1761 if (r_glsl_permutation->loc_FogColor >= 0)
1762 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1766 if (mode == SHADERMODE_LIGHTDIRECTION)
1768 if (r_glsl_permutation->loc_AmbientColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale * 0.5f, rsurface.modellight_ambient[1] * ambientscale * 0.5f, rsurface.modellight_ambient[2] * ambientscale * 0.5f);
1769 if (r_glsl_permutation->loc_DiffuseColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale * 0.5f, rsurface.modellight_diffuse[1] * diffusescale * 0.5f, rsurface.modellight_diffuse[2] * diffusescale * 0.5f);
1770 if (r_glsl_permutation->loc_SpecularColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * 0.5f, rsurface.modellight_diffuse[1] * specularscale * 0.5f, rsurface.modellight_diffuse[2] * specularscale * 0.5f);
1771 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1775 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
1776 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1777 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1779 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
1780 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1781 // additive passes are only darkened by fog, not tinted
1782 if (r_glsl_permutation->loc_FogColor >= 0)
1784 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1785 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1787 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1789 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
1790 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
1791 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
1792 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1793 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1794 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1795 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1797 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1799 // The formula used is actually:
1800 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1801 // color.rgb *= SceneBrightness;
1803 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1804 // and do [[calculations]] here in the engine
1805 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1806 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1809 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1810 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1811 if (r_glsl_permutation->loc_Color_Pants >= 0)
1813 if (rsurface.texture->currentskinframe->pants)
1814 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1816 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1818 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1820 if (rsurface.texture->currentskinframe->shirt)
1821 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1823 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1825 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
1826 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
1828 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
1832 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1834 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1838 #define SKINFRAME_HASH 1024
1842 int loadsequence; // incremented each level change
1843 memexpandablearray_t array;
1844 skinframe_t *hash[SKINFRAME_HASH];
1847 r_skinframe_t r_skinframe;
1849 void R_SkinFrame_PrepareForPurge(void)
1851 r_skinframe.loadsequence++;
1852 // wrap it without hitting zero
1853 if (r_skinframe.loadsequence >= 200)
1854 r_skinframe.loadsequence = 1;
1857 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1861 // mark the skinframe as used for the purging code
1862 skinframe->loadsequence = r_skinframe.loadsequence;
1865 void R_SkinFrame_Purge(void)
1869 for (i = 0;i < SKINFRAME_HASH;i++)
1871 for (s = r_skinframe.hash[i];s;s = s->next)
1873 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1875 if (s->merged == s->base)
1877 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1878 R_PurgeTexture(s->stain );s->stain = NULL;
1879 R_PurgeTexture(s->merged);s->merged = NULL;
1880 R_PurgeTexture(s->base );s->base = NULL;
1881 R_PurgeTexture(s->pants );s->pants = NULL;
1882 R_PurgeTexture(s->shirt );s->shirt = NULL;
1883 R_PurgeTexture(s->nmap );s->nmap = NULL;
1884 R_PurgeTexture(s->gloss );s->gloss = NULL;
1885 R_PurgeTexture(s->glow );s->glow = NULL;
1886 R_PurgeTexture(s->fog );s->fog = NULL;
1887 s->loadsequence = 0;
1893 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1895 char basename[MAX_QPATH];
1897 Image_StripImageExtension(name, basename, sizeof(basename));
1899 if( last == NULL ) {
1901 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1902 item = r_skinframe.hash[hashindex];
1907 // linearly search through the hash bucket
1908 for( ; item ; item = item->next ) {
1909 if( !strcmp( item->basename, basename ) ) {
1916 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1920 char basename[MAX_QPATH];
1922 Image_StripImageExtension(name, basename, sizeof(basename));
1924 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1925 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1926 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1930 rtexture_t *dyntexture;
1931 // check whether its a dynamic texture
1932 dyntexture = CL_GetDynTexture( basename );
1933 if (!add && !dyntexture)
1935 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1936 memset(item, 0, sizeof(*item));
1937 strlcpy(item->basename, basename, sizeof(item->basename));
1938 item->base = dyntexture; // either NULL or dyntexture handle
1939 item->textureflags = textureflags;
1940 item->comparewidth = comparewidth;
1941 item->compareheight = compareheight;
1942 item->comparecrc = comparecrc;
1943 item->next = r_skinframe.hash[hashindex];
1944 r_skinframe.hash[hashindex] = item;
1946 else if( item->base == NULL )
1948 rtexture_t *dyntexture;
1949 // check whether its a dynamic texture
1950 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
1951 dyntexture = CL_GetDynTexture( basename );
1952 item->base = dyntexture; // either NULL or dyntexture handle
1955 R_SkinFrame_MarkUsed(item);
1959 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
1961 unsigned long long avgcolor[5], wsum; \
1969 for(pix = 0; pix < cnt; ++pix) \
1972 for(comp = 0; comp < 3; ++comp) \
1974 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
1977 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1979 for(comp = 0; comp < 3; ++comp) \
1980 avgcolor[comp] += getpixel * w; \
1983 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1984 avgcolor[4] += getpixel; \
1986 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
1988 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
1989 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
1990 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
1991 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
1994 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
1996 // FIXME: it should be possible to disable loading various layers using
1997 // cvars, to prevent wasted loading time and memory usage if the user does
1999 qboolean loadnormalmap = true;
2000 qboolean loadgloss = true;
2001 qboolean loadpantsandshirt = true;
2002 qboolean loadglow = true;
2004 unsigned char *pixels;
2005 unsigned char *bumppixels;
2006 unsigned char *basepixels = NULL;
2007 int basepixels_width;
2008 int basepixels_height;
2009 skinframe_t *skinframe;
2013 if (cls.state == ca_dedicated)
2016 // return an existing skinframe if already loaded
2017 // if loading of the first image fails, don't make a new skinframe as it
2018 // would cause all future lookups of this to be missing
2019 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2020 if (skinframe && skinframe->base)
2023 basepixels = loadimagepixelsbgra(name, complain, true);
2024 if (basepixels == NULL)
2027 if (developer_loading.integer)
2028 Con_Printf("loading skin \"%s\"\n", name);
2030 // we've got some pixels to store, so really allocate this new texture now
2032 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2033 skinframe->stain = NULL;
2034 skinframe->merged = NULL;
2035 skinframe->base = r_texture_notexture;
2036 skinframe->pants = NULL;
2037 skinframe->shirt = NULL;
2038 skinframe->nmap = r_texture_blanknormalmap;
2039 skinframe->gloss = NULL;
2040 skinframe->glow = NULL;
2041 skinframe->fog = NULL;
2043 basepixels_width = image_width;
2044 basepixels_height = image_height;
2045 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2047 if (textureflags & TEXF_ALPHA)
2049 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2050 if (basepixels[j] < 255)
2052 if (j < basepixels_width * basepixels_height * 4)
2054 // has transparent pixels
2056 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2057 for (j = 0;j < image_width * image_height * 4;j += 4)
2062 pixels[j+3] = basepixels[j+3];
2064 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2069 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2070 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2072 // _norm is the name used by tenebrae and has been adopted as standard
2075 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2077 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2081 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2083 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2084 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2085 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2087 Mem_Free(bumppixels);
2089 else if (r_shadow_bumpscale_basetexture.value > 0)
2091 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2092 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2093 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2097 // _luma is supported for tenebrae compatibility
2098 // (I think it's a very stupid name, but oh well)
2099 // _glow is the preferred name
2100 if (loadglow && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) != NULL || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2101 if (loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2102 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2103 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2106 Mem_Free(basepixels);
2111 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2114 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2117 static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
2122 for (i = 0;i < width*height;i++)
2123 if (((unsigned char *)&palette[in[i]])[3] > 0)
2125 if (i == width*height)
2128 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2131 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2132 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2135 unsigned char *temp1, *temp2;
2136 skinframe_t *skinframe;
2138 if (cls.state == ca_dedicated)
2141 // if already loaded just return it, otherwise make a new skinframe
2142 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2143 if (skinframe && skinframe->base)
2146 skinframe->stain = NULL;
2147 skinframe->merged = NULL;
2148 skinframe->base = r_texture_notexture;
2149 skinframe->pants = NULL;
2150 skinframe->shirt = NULL;
2151 skinframe->nmap = r_texture_blanknormalmap;
2152 skinframe->gloss = NULL;
2153 skinframe->glow = NULL;
2154 skinframe->fog = NULL;
2156 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2160 if (developer_loading.integer)
2161 Con_Printf("loading 32bit skin \"%s\"\n", name);
2163 if (r_shadow_bumpscale_basetexture.value > 0)
2165 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2166 temp2 = temp1 + width * height * 4;
2167 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2168 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2171 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2172 if (textureflags & TEXF_ALPHA)
2174 for (i = 3;i < width * height * 4;i += 4)
2175 if (skindata[i] < 255)
2177 if (i < width * height * 4)
2179 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2180 memcpy(fogpixels, skindata, width * height * 4);
2181 for (i = 0;i < width * height * 4;i += 4)
2182 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2183 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2184 Mem_Free(fogpixels);
2188 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2189 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2194 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2197 unsigned char *temp1, *temp2;
2198 unsigned int *palette;
2199 skinframe_t *skinframe;
2201 if (cls.state == ca_dedicated)
2204 // if already loaded just return it, otherwise make a new skinframe
2205 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2206 if (skinframe && skinframe->base)
2209 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2211 skinframe->stain = NULL;
2212 skinframe->merged = NULL;
2213 skinframe->base = r_texture_notexture;
2214 skinframe->pants = NULL;
2215 skinframe->shirt = NULL;
2216 skinframe->nmap = r_texture_blanknormalmap;
2217 skinframe->gloss = NULL;
2218 skinframe->glow = NULL;
2219 skinframe->fog = NULL;
2221 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2225 if (developer_loading.integer)
2226 Con_Printf("loading quake skin \"%s\"\n", name);
2228 if (r_shadow_bumpscale_basetexture.value > 0)
2230 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2231 temp2 = temp1 + width * height * 4;
2232 // use either a custom palette or the quake palette
2233 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2234 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2235 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2238 // use either a custom palette, or the quake palette
2239 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2240 if (loadglowtexture)
2241 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2242 if (loadpantsandshirt)
2244 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2245 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2247 if (skinframe->pants || skinframe->shirt)
2248 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename), loadglowtexture ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap, skinframe->textureflags, false); // no special colors
2249 if (textureflags & TEXF_ALPHA)
2251 for (i = 0;i < width * height;i++)
2252 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2254 if (i < width * height)
2255 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2258 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2259 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2264 skinframe_t *R_SkinFrame_LoadMissing(void)
2266 skinframe_t *skinframe;
2268 if (cls.state == ca_dedicated)
2271 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2272 skinframe->stain = NULL;
2273 skinframe->merged = NULL;
2274 skinframe->base = r_texture_notexture;
2275 skinframe->pants = NULL;
2276 skinframe->shirt = NULL;
2277 skinframe->nmap = r_texture_blanknormalmap;
2278 skinframe->gloss = NULL;
2279 skinframe->glow = NULL;
2280 skinframe->fog = NULL;
2282 skinframe->avgcolor[0] = rand() / RAND_MAX;
2283 skinframe->avgcolor[1] = rand() / RAND_MAX;
2284 skinframe->avgcolor[2] = rand() / RAND_MAX;
2285 skinframe->avgcolor[3] = 1;
2290 void gl_main_start(void)
2294 memset(r_queries, 0, sizeof(r_queries));
2296 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2297 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2299 // set up r_skinframe loading system for textures
2300 memset(&r_skinframe, 0, sizeof(r_skinframe));
2301 r_skinframe.loadsequence = 1;
2302 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2304 r_main_texturepool = R_AllocTexturePool();
2305 R_BuildBlankTextures();
2307 if (gl_texturecubemap)
2310 R_BuildNormalizationCube();
2312 r_texture_fogattenuation = NULL;
2313 r_texture_gammaramps = NULL;
2314 //r_texture_fogintensity = NULL;
2315 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2316 memset(&r_waterstate, 0, sizeof(r_waterstate));
2317 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2318 memset(&r_svbsp, 0, sizeof (r_svbsp));
2320 r_refdef.fogmasktable_density = 0;
2323 extern rtexture_t *loadingscreentexture;
2324 void gl_main_shutdown(void)
2327 qglDeleteQueriesARB(r_maxqueries, r_queries);
2331 memset(r_queries, 0, sizeof(r_queries));
2333 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2334 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2336 // clear out the r_skinframe state
2337 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2338 memset(&r_skinframe, 0, sizeof(r_skinframe));
2341 Mem_Free(r_svbsp.nodes);
2342 memset(&r_svbsp, 0, sizeof (r_svbsp));
2343 R_FreeTexturePool(&r_main_texturepool);
2344 loadingscreentexture = NULL;
2345 r_texture_blanknormalmap = NULL;
2346 r_texture_white = NULL;
2347 r_texture_grey128 = NULL;
2348 r_texture_black = NULL;
2349 r_texture_whitecube = NULL;
2350 r_texture_normalizationcube = NULL;
2351 r_texture_fogattenuation = NULL;
2352 r_texture_gammaramps = NULL;
2353 //r_texture_fogintensity = NULL;
2354 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2355 memset(&r_waterstate, 0, sizeof(r_waterstate));
2359 extern void CL_ParseEntityLump(char *entitystring);
2360 void gl_main_newmap(void)
2362 // FIXME: move this code to client
2364 char *entities, entname[MAX_QPATH];
2367 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2368 l = (int)strlen(entname) - 4;
2369 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2371 memcpy(entname + l, ".ent", 5);
2372 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2374 CL_ParseEntityLump(entities);
2379 if (cl.worldmodel->brush.entities)
2380 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2384 void GL_Main_Init(void)
2386 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2388 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2389 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2390 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2391 if (gamemode == GAME_NEHAHRA)
2393 Cvar_RegisterVariable (&gl_fogenable);
2394 Cvar_RegisterVariable (&gl_fogdensity);
2395 Cvar_RegisterVariable (&gl_fogred);
2396 Cvar_RegisterVariable (&gl_foggreen);
2397 Cvar_RegisterVariable (&gl_fogblue);
2398 Cvar_RegisterVariable (&gl_fogstart);
2399 Cvar_RegisterVariable (&gl_fogend);
2400 Cvar_RegisterVariable (&gl_skyclip);
2402 Cvar_RegisterVariable(&r_motionblur);
2403 Cvar_RegisterVariable(&r_motionblur_maxblur);
2404 Cvar_RegisterVariable(&r_motionblur_bmin);
2405 Cvar_RegisterVariable(&r_motionblur_vmin);
2406 Cvar_RegisterVariable(&r_motionblur_vmax);
2407 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2408 Cvar_RegisterVariable(&r_motionblur_randomize);
2409 Cvar_RegisterVariable(&r_damageblur);
2410 Cvar_RegisterVariable(&r_animcache);
2411 Cvar_RegisterVariable(&r_motionblur_debug);
2412 Cvar_RegisterVariable(&r_depthfirst);
2413 Cvar_RegisterVariable(&r_useinfinitefarclip);
2414 Cvar_RegisterVariable(&r_nearclip);
2415 Cvar_RegisterVariable(&r_showbboxes);
2416 Cvar_RegisterVariable(&r_showsurfaces);
2417 Cvar_RegisterVariable(&r_showtris);
2418 Cvar_RegisterVariable(&r_shownormals);
2419 Cvar_RegisterVariable(&r_showlighting);
2420 Cvar_RegisterVariable(&r_showshadowvolumes);
2421 Cvar_RegisterVariable(&r_showcollisionbrushes);
2422 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2423 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2424 Cvar_RegisterVariable(&r_showdisabledepthtest);
2425 Cvar_RegisterVariable(&r_drawportals);
2426 Cvar_RegisterVariable(&r_drawentities);
2427 Cvar_RegisterVariable(&r_cullentities_trace);
2428 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2429 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2430 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2431 Cvar_RegisterVariable(&r_drawviewmodel);
2432 Cvar_RegisterVariable(&r_speeds);
2433 Cvar_RegisterVariable(&r_fullbrights);
2434 Cvar_RegisterVariable(&r_wateralpha);
2435 Cvar_RegisterVariable(&r_dynamic);
2436 Cvar_RegisterVariable(&r_fullbright);
2437 Cvar_RegisterVariable(&r_shadows);
2438 Cvar_RegisterVariable(&r_shadows_throwdistance);
2439 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2440 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2441 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2442 Cvar_RegisterVariable(&r_fog_exp2);
2443 Cvar_RegisterVariable(&r_drawfog);
2444 Cvar_RegisterVariable(&r_textureunits);
2445 Cvar_RegisterVariable(&r_glsl);
2446 Cvar_RegisterVariable(&r_glsl_contrastboost);
2447 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2448 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2449 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2450 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2451 Cvar_RegisterVariable(&r_glsl_postprocess);
2452 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2453 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2454 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2455 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2456 Cvar_RegisterVariable(&r_glsl_usegeneric);
2457 Cvar_RegisterVariable(&r_water);
2458 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2459 Cvar_RegisterVariable(&r_water_clippingplanebias);
2460 Cvar_RegisterVariable(&r_water_refractdistort);
2461 Cvar_RegisterVariable(&r_water_reflectdistort);
2462 Cvar_RegisterVariable(&r_lerpsprites);
2463 Cvar_RegisterVariable(&r_lerpmodels);
2464 Cvar_RegisterVariable(&r_lerplightstyles);
2465 Cvar_RegisterVariable(&r_waterscroll);
2466 Cvar_RegisterVariable(&r_bloom);
2467 Cvar_RegisterVariable(&r_bloom_colorscale);
2468 Cvar_RegisterVariable(&r_bloom_brighten);
2469 Cvar_RegisterVariable(&r_bloom_blur);
2470 Cvar_RegisterVariable(&r_bloom_resolution);
2471 Cvar_RegisterVariable(&r_bloom_colorexponent);
2472 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2473 Cvar_RegisterVariable(&r_hdr);
2474 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2475 Cvar_RegisterVariable(&r_hdr_glowintensity);
2476 Cvar_RegisterVariable(&r_hdr_range);
2477 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2478 Cvar_RegisterVariable(&developer_texturelogging);
2479 Cvar_RegisterVariable(&gl_lightmaps);
2480 Cvar_RegisterVariable(&r_test);
2481 Cvar_RegisterVariable(&r_batchmode);
2482 Cvar_RegisterVariable(&r_glsl_saturation);
2483 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2484 Cvar_SetValue("r_fullbrights", 0);
2485 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2487 Cvar_RegisterVariable(&r_track_sprites);
2488 Cvar_RegisterVariable(&r_track_sprites_flags);
2489 Cvar_RegisterVariable(&r_track_sprites_scalew);
2490 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2493 extern void R_Textures_Init(void);
2494 extern void GL_Draw_Init(void);
2495 extern void GL_Main_Init(void);
2496 extern void R_Shadow_Init(void);
2497 extern void R_Sky_Init(void);
2498 extern void GL_Surf_Init(void);
2499 extern void R_Particles_Init(void);
2500 extern void R_Explosion_Init(void);
2501 extern void gl_backend_init(void);
2502 extern void Sbar_Init(void);
2503 extern void R_LightningBeams_Init(void);
2504 extern void Mod_RenderInit(void);
2506 void Render_Init(void)
2518 R_LightningBeams_Init();
2527 extern char *ENGINE_EXTENSIONS;
2530 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2531 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2532 gl_version = (const char *)qglGetString(GL_VERSION);
2533 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2537 if (!gl_platformextensions)
2538 gl_platformextensions = "";
2540 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2541 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2542 Con_Printf("GL_VERSION: %s\n", gl_version);
2543 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2544 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2546 VID_CheckExtensions();
2548 // LordHavoc: report supported extensions
2549 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2551 // clear to black (loading plaque will be seen over this)
2553 qglClearColor(0,0,0,1);CHECKGLERROR
2554 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2557 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2561 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2563 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2566 p = r_refdef.view.frustum + i;
2571 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2575 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2579 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2583 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2587 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2591 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2595 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2599 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2607 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2611 for (i = 0;i < numplanes;i++)
2618 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2622 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2626 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2630 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2634 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2638 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2642 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2646 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2654 //==================================================================================
2657 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
2658 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
2659 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
2671 static anim_cache_t r_animCache[MAX_EDICTS];
2672 static int r_numAnimCache;
2674 void R_EmptyAnimCache(void)
2677 for (idx=0 ; idx<r_numAnimCache ; idx++)
2679 r_animCache[idx].numVerts = 0;
2680 Mem_Free(r_animCache[idx].vertexes);
2681 r_animCache[idx].vertexes = NULL;
2682 r_animCache[idx].normals = NULL;
2683 r_animCache[idx].sVectors = NULL;
2684 r_animCache[idx].tVectors = NULL;
2689 void R_ResizeAnimCache(const int cacheIdx, const int numVerts)
2693 anim_cache_t *cache = &r_animCache[cacheIdx];
2695 if (cache->numVerts >= numVerts)
2698 // Release existing memory
2699 if (cache->vertexes)
2700 Mem_Free(cache->vertexes);
2702 // Pad by 1024 verts
2703 cache->numVerts = (numVerts + 1023) & ~1023;
2704 arraySize = cache->numVerts * 3;
2706 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
2707 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
2708 r_animCache[cacheIdx].vertexes = base;
2709 r_animCache[cacheIdx].normals = base + arraySize;
2710 r_animCache[cacheIdx].sVectors = base + arraySize*2;
2711 r_animCache[cacheIdx].tVectors = base + arraySize*3;
2713 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
2716 void R_RunAnimCache(void)
2718 int entIdx, cacheIdx;
2719 entity_render_t *ent;
2721 qboolean bWantNormals;
2722 qboolean bWantTangents;
2724 // Only proceed if desired
2725 if (!r_animcache.integer || !r_drawentities.integer)
2728 if (r_numAnimCache != 0)
2732 // Clear any existing animcacheindex references
2733 for (entIdx=0 ; entIdx<r_refdef.scene.numentities ; entIdx++)
2735 ent = r_refdef.scene.entities[entIdx];
2736 ent->animcacheindex = 0;
2742 // Generate new cache
2744 for (entIdx=0 ; entIdx<r_refdef.scene.numentities ; entIdx++)
2746 ent = r_refdef.scene.entities[entIdx];
2748 if (!r_refdef.viewcache.entityvisible[entIdx])
2750 ent->animcacheindex = 0;
2755 if (model && model->Draw != NULL
2756 && model->surfmesh.isanimated && model->AnimateVertices && (ent->frameblend[0].lerp != 1 || ent->frameblend[0].subframe != 0))
2758 R_ResizeAnimCache(cacheIdx, model->surfmesh.num_vertices);
2760 // FIXME: Some stable way of determining if normals/tangets aren't going to be needed would be good for optimizing this
2761 // Need to consider deformvertexes and tcgens that need normals and/or tangents (otherwise they'll slow-path generate them later), as well as some rendering settings
2762 bWantNormals = true;
2763 bWantTangents = true;//bWantNormals && (r_glsl.integer && gl_support_fragment_shader);
2764 model->AnimateVertices(
2765 model, ent->frameblend,
2766 r_animCache[cacheIdx].vertexes,
2767 bWantNormals ? r_animCache[cacheIdx].normals : NULL,
2768 bWantTangents ? r_animCache[cacheIdx].sVectors : NULL,
2769 bWantTangents ? r_animCache[cacheIdx].tVectors : NULL
2773 ent->animcacheindex = cacheIdx;
2777 ent->animcacheindex = 0;
2781 // Increase our limit if necessary
2782 r_numAnimCache = max(r_numAnimCache, cacheIdx);
2785 //==================================================================================
2787 static void R_View_UpdateEntityLighting (void)
2790 entity_render_t *ent;
2791 vec3_t tempdiffusenormal;
2793 for (i = 0;i < r_refdef.scene.numentities;i++)
2795 ent = r_refdef.scene.entities[i];
2797 // skip unseen models
2798 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
2802 if (ent->model && ent->model->brush.num_leafs)
2804 // TODO: use modellight for r_ambient settings on world?
2805 VectorSet(ent->modellight_ambient, 0, 0, 0);
2806 VectorSet(ent->modellight_diffuse, 0, 0, 0);
2807 VectorSet(ent->modellight_lightdir, 0, 0, 1);
2811 // fetch the lighting from the worldmodel data
2812 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));
2813 VectorClear(ent->modellight_diffuse);
2814 VectorClear(tempdiffusenormal);
2815 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
2818 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2819 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2822 VectorSet(ent->modellight_ambient, 1, 1, 1);
2824 // move the light direction into modelspace coordinates for lighting code
2825 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2826 if(VectorLength2(ent->modellight_lightdir) == 0)
2827 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2828 VectorNormalize(ent->modellight_lightdir);
2832 static void R_View_UpdateEntityVisible (void)
2835 entity_render_t *ent;
2837 if (!r_drawentities.integer)
2840 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2841 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2843 // worldmodel can check visibility
2844 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2845 for (i = 0;i < r_refdef.scene.numentities;i++)
2847 ent = r_refdef.scene.entities[i];
2848 if (!(ent->flags & renderimask))
2849 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)))
2850 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))
2851 r_refdef.viewcache.entityvisible[i] = true;
2853 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2855 for (i = 0;i < r_refdef.scene.numentities;i++)
2857 ent = r_refdef.scene.entities[i];
2858 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2860 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))
2861 ent->last_trace_visibility = realtime;
2862 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2863 r_refdef.viewcache.entityvisible[i] = 0;
2870 // no worldmodel or it can't check visibility
2871 for (i = 0;i < r_refdef.scene.numentities;i++)
2873 ent = r_refdef.scene.entities[i];
2874 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));
2879 /// only used if skyrendermasked, and normally returns false
2880 int R_DrawBrushModelsSky (void)
2883 entity_render_t *ent;
2885 if (!r_drawentities.integer)
2889 for (i = 0;i < r_refdef.scene.numentities;i++)
2891 if (!r_refdef.viewcache.entityvisible[i])
2893 ent = r_refdef.scene.entities[i];
2894 if (!ent->model || !ent->model->DrawSky)
2896 ent->model->DrawSky(ent);
2902 static void R_DrawNoModel(entity_render_t *ent);
2903 static void R_DrawModels(void)
2906 entity_render_t *ent;
2908 if (!r_drawentities.integer)
2911 for (i = 0;i < r_refdef.scene.numentities;i++)
2913 if (!r_refdef.viewcache.entityvisible[i])
2915 ent = r_refdef.scene.entities[i];
2916 r_refdef.stats.entities++;
2917 if (ent->model && ent->model->Draw != NULL)
2918 ent->model->Draw(ent);
2924 static void R_DrawModelsDepth(void)
2927 entity_render_t *ent;
2929 if (!r_drawentities.integer)
2932 for (i = 0;i < r_refdef.scene.numentities;i++)
2934 if (!r_refdef.viewcache.entityvisible[i])
2936 ent = r_refdef.scene.entities[i];
2937 if (ent->model && ent->model->DrawDepth != NULL)
2938 ent->model->DrawDepth(ent);
2942 static void R_DrawModelsDebug(void)
2945 entity_render_t *ent;
2947 if (!r_drawentities.integer)
2950 for (i = 0;i < r_refdef.scene.numentities;i++)
2952 if (!r_refdef.viewcache.entityvisible[i])
2954 ent = r_refdef.scene.entities[i];
2955 if (ent->model && ent->model->DrawDebug != NULL)
2956 ent->model->DrawDebug(ent);
2960 static void R_DrawModelsAddWaterPlanes(void)
2963 entity_render_t *ent;
2965 if (!r_drawentities.integer)
2968 for (i = 0;i < r_refdef.scene.numentities;i++)
2970 if (!r_refdef.viewcache.entityvisible[i])
2972 ent = r_refdef.scene.entities[i];
2973 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2974 ent->model->DrawAddWaterPlanes(ent);
2978 static void R_View_SetFrustum(void)
2981 double slopex, slopey;
2982 vec3_t forward, left, up, origin;
2984 // we can't trust r_refdef.view.forward and friends in reflected scenes
2985 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2988 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2989 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2990 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2991 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2992 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2993 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2994 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2995 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2996 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2997 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2998 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2999 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3003 zNear = r_refdef.nearclip;
3004 nudge = 1.0 - 1.0 / (1<<23);
3005 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3006 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3007 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3008 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3009 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3010 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3011 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3012 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3018 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3019 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3020 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3021 r_refdef.view.frustum[0].dist = m[15] - m[12];
3023 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3024 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3025 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3026 r_refdef.view.frustum[1].dist = m[15] + m[12];
3028 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3029 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3030 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3031 r_refdef.view.frustum[2].dist = m[15] - m[13];
3033 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3034 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3035 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3036 r_refdef.view.frustum[3].dist = m[15] + m[13];
3038 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3039 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3040 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3041 r_refdef.view.frustum[4].dist = m[15] - m[14];
3043 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3044 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3045 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3046 r_refdef.view.frustum[5].dist = m[15] + m[14];
3049 if (r_refdef.view.useperspective)
3051 slopex = 1.0 / r_refdef.view.frustum_x;
3052 slopey = 1.0 / r_refdef.view.frustum_y;
3053 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3054 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3055 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3056 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3057 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3059 // Leaving those out was a mistake, those were in the old code, and they
3060 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3061 // I couldn't reproduce it after adding those normalizations. --blub
3062 VectorNormalize(r_refdef.view.frustum[0].normal);
3063 VectorNormalize(r_refdef.view.frustum[1].normal);
3064 VectorNormalize(r_refdef.view.frustum[2].normal);
3065 VectorNormalize(r_refdef.view.frustum[3].normal);
3067 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3068 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
3069 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
3070 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
3071 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
3073 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3074 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3075 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3076 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3077 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3081 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3082 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3083 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3084 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3085 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3086 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3087 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3088 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3089 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3090 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3092 r_refdef.view.numfrustumplanes = 5;
3094 if (r_refdef.view.useclipplane)
3096 r_refdef.view.numfrustumplanes = 6;
3097 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3100 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3101 PlaneClassify(r_refdef.view.frustum + i);
3103 // LordHavoc: note to all quake engine coders, Quake had a special case
3104 // for 90 degrees which assumed a square view (wrong), so I removed it,
3105 // Quake2 has it disabled as well.
3107 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3108 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3109 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3110 //PlaneClassify(&frustum[0]);
3112 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3113 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3114 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3115 //PlaneClassify(&frustum[1]);
3117 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3118 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3119 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3120 //PlaneClassify(&frustum[2]);
3122 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3123 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3124 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3125 //PlaneClassify(&frustum[3]);
3128 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3129 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3130 //PlaneClassify(&frustum[4]);
3133 void R_View_Update(void)
3135 R_View_SetFrustum();
3136 R_View_WorldVisibility(r_refdef.view.useclipplane);
3137 R_View_UpdateEntityVisible();
3138 R_View_UpdateEntityLighting();
3141 void R_SetupView(qboolean allowwaterclippingplane)
3143 if (!r_refdef.view.useperspective)
3144 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);
3145 else if (gl_stencil && r_useinfinitefarclip.integer)
3146 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
3148 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
3150 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
3152 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3154 // LordHavoc: couldn't figure out how to make this approach the
3155 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3156 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3157 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3158 dist = r_refdef.view.clipplane.dist;
3159 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
3163 void R_ResetViewRendering2D(void)
3167 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3168 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3169 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
3170 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3171 GL_Color(1, 1, 1, 1);
3172 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3173 GL_BlendFunc(GL_ONE, GL_ZERO);
3174 GL_AlphaTest(false);
3175 GL_ScissorTest(false);
3176 GL_DepthMask(false);
3177 GL_DepthRange(0, 1);
3178 GL_DepthTest(false);
3179 R_Mesh_Matrix(&identitymatrix);
3180 R_Mesh_ResetTextureState();
3181 GL_PolygonOffset(0, 0);
3182 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3183 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3184 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3185 qglStencilMask(~0);CHECKGLERROR
3186 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3187 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3188 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3189 R_SetupGenericShader(true);
3192 void R_ResetViewRendering3D(void)
3196 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3197 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3199 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3200 GL_Color(1, 1, 1, 1);
3201 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3202 GL_BlendFunc(GL_ONE, GL_ZERO);
3203 GL_AlphaTest(false);
3204 GL_ScissorTest(true);
3206 GL_DepthRange(0, 1);
3208 R_Mesh_Matrix(&identitymatrix);
3209 R_Mesh_ResetTextureState();
3210 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3211 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3212 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3213 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3214 qglStencilMask(~0);CHECKGLERROR
3215 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3216 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3217 GL_CullFace(r_refdef.view.cullface_back);
3218 R_SetupGenericShader(true);
3221 void R_RenderScene(void);
3222 void R_RenderWaterPlanes(void);
3224 static void R_Water_StartFrame(void)
3227 int waterwidth, waterheight, texturewidth, textureheight;
3228 r_waterstate_waterplane_t *p;
3230 // set waterwidth and waterheight to the water resolution that will be
3231 // used (often less than the screen resolution for faster rendering)
3232 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3233 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3235 // calculate desired texture sizes
3236 // can't use water if the card does not support the texture size
3237 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3238 texturewidth = textureheight = waterwidth = waterheight = 0;
3239 else if (gl_support_arb_texture_non_power_of_two)
3241 texturewidth = waterwidth;
3242 textureheight = waterheight;
3246 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3247 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3250 // allocate textures as needed
3251 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3253 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3254 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3256 if (p->texture_refraction)
3257 R_FreeTexture(p->texture_refraction);
3258 p->texture_refraction = NULL;
3259 if (p->texture_reflection)
3260 R_FreeTexture(p->texture_reflection);
3261 p->texture_reflection = NULL;
3263 memset(&r_waterstate, 0, sizeof(r_waterstate));
3264 r_waterstate.waterwidth = waterwidth;
3265 r_waterstate.waterheight = waterheight;
3266 r_waterstate.texturewidth = texturewidth;
3267 r_waterstate.textureheight = textureheight;
3270 if (r_waterstate.waterwidth)
3272 r_waterstate.enabled = true;
3274 // set up variables that will be used in shader setup
3275 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3276 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3277 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3278 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3281 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3282 r_waterstate.numwaterplanes = 0;
3285 void R_Water_AddWaterPlane(msurface_t *surface)
3287 int triangleindex, planeindex;
3293 r_waterstate_waterplane_t *p;
3294 texture_t *t = R_GetCurrentTexture(surface->texture);
3295 // just use the first triangle with a valid normal for any decisions
3296 VectorClear(normal);
3297 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3299 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3300 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3301 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3302 TriangleNormal(vert[0], vert[1], vert[2], normal);
3303 if (VectorLength2(normal) >= 0.001)
3307 VectorCopy(normal, plane.normal);
3308 VectorNormalize(plane.normal);
3309 plane.dist = DotProduct(vert[0], plane.normal);
3310 PlaneClassify(&plane);
3311 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3313 // skip backfaces (except if nocullface is set)
3314 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3316 VectorNegate(plane.normal, plane.normal);
3318 PlaneClassify(&plane);
3322 // find a matching plane if there is one
3323 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3324 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3326 if (planeindex >= r_waterstate.maxwaterplanes)
3327 return; // nothing we can do, out of planes
3329 // if this triangle does not fit any known plane rendered this frame, add one
3330 if (planeindex >= r_waterstate.numwaterplanes)
3332 // store the new plane
3333 r_waterstate.numwaterplanes++;
3335 // clear materialflags and pvs
3336 p->materialflags = 0;
3337 p->pvsvalid = false;
3339 // merge this surface's materialflags into the waterplane
3340 p->materialflags |= t->currentmaterialflags;
3341 // merge this surface's PVS into the waterplane
3342 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3343 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3344 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3346 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3351 static void R_Water_ProcessPlanes(void)
3353 r_refdef_view_t originalview;
3354 r_refdef_view_t myview;
3356 r_waterstate_waterplane_t *p;
3358 originalview = r_refdef.view;
3360 // make sure enough textures are allocated
3361 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3363 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3365 if (!p->texture_refraction)
3366 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);
3367 if (!p->texture_refraction)
3371 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3373 if (!p->texture_reflection)
3374 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);
3375 if (!p->texture_reflection)
3381 r_refdef.view = originalview;
3382 r_refdef.view.showdebug = false;
3383 r_refdef.view.width = r_waterstate.waterwidth;
3384 r_refdef.view.height = r_waterstate.waterheight;
3385 r_refdef.view.useclipplane = true;
3386 myview = r_refdef.view;
3387 r_waterstate.renderingscene = true;
3388 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3390 // render the normal view scene and copy into texture
3391 // (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)
3392 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3394 r_refdef.view = myview;
3395 r_refdef.view.clipplane = p->plane;
3396 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3397 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3398 PlaneClassify(&r_refdef.view.clipplane);
3400 R_ResetViewRendering3D();
3401 R_ClearScreen(r_refdef.fogenabled);
3405 // copy view into the screen texture
3406 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3407 GL_ActiveTexture(0);
3409 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
3412 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3414 r_refdef.view = myview;
3415 // render reflected scene and copy into texture
3416 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3417 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3418 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3419 r_refdef.view.clipplane = p->plane;
3420 // reverse the cullface settings for this render
3421 r_refdef.view.cullface_front = GL_FRONT;
3422 r_refdef.view.cullface_back = GL_BACK;
3423 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3425 r_refdef.view.usecustompvs = true;
3427 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3429 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3432 R_ResetViewRendering3D();
3433 R_ClearScreen(r_refdef.fogenabled);
3437 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3438 GL_ActiveTexture(0);
3440 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
3443 r_waterstate.renderingscene = false;
3444 r_refdef.view = originalview;
3445 R_ResetViewRendering3D();
3446 R_ClearScreen(r_refdef.fogenabled);
3450 r_refdef.view = originalview;
3451 r_waterstate.renderingscene = false;
3452 Cvar_SetValueQuick(&r_water, 0);
3453 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3457 void R_Bloom_StartFrame(void)
3459 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3461 // set bloomwidth and bloomheight to the bloom resolution that will be
3462 // used (often less than the screen resolution for faster rendering)
3463 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3464 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3465 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3466 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3467 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3469 // calculate desired texture sizes
3470 if (gl_support_arb_texture_non_power_of_two)
3472 screentexturewidth = r_refdef.view.width;
3473 screentextureheight = r_refdef.view.height;
3474 bloomtexturewidth = r_bloomstate.bloomwidth;
3475 bloomtextureheight = r_bloomstate.bloomheight;
3479 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3480 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3481 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3482 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3485 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))
3487 Cvar_SetValueQuick(&r_hdr, 0);
3488 Cvar_SetValueQuick(&r_bloom, 0);
3489 Cvar_SetValueQuick(&r_motionblur, 0);
3490 Cvar_SetValueQuick(&r_damageblur, 0);
3493 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)))
3494 screentexturewidth = screentextureheight = 0;
3495 if (!r_hdr.integer && !r_bloom.integer)
3496 bloomtexturewidth = bloomtextureheight = 0;
3498 // allocate textures as needed
3499 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3501 if (r_bloomstate.texture_screen)
3502 R_FreeTexture(r_bloomstate.texture_screen);
3503 r_bloomstate.texture_screen = NULL;
3504 r_bloomstate.screentexturewidth = screentexturewidth;
3505 r_bloomstate.screentextureheight = screentextureheight;
3506 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3507 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);
3509 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3511 if (r_bloomstate.texture_bloom)
3512 R_FreeTexture(r_bloomstate.texture_bloom);
3513 r_bloomstate.texture_bloom = NULL;
3514 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3515 r_bloomstate.bloomtextureheight = bloomtextureheight;
3516 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3517 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);
3520 // set up a texcoord array for the full resolution screen image
3521 // (we have to keep this around to copy back during final render)
3522 r_bloomstate.screentexcoord2f[0] = 0;
3523 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3524 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3525 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3526 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3527 r_bloomstate.screentexcoord2f[5] = 0;
3528 r_bloomstate.screentexcoord2f[6] = 0;
3529 r_bloomstate.screentexcoord2f[7] = 0;
3531 // set up a texcoord array for the reduced resolution bloom image
3532 // (which will be additive blended over the screen image)
3533 r_bloomstate.bloomtexcoord2f[0] = 0;
3534 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3535 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3536 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3537 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3538 r_bloomstate.bloomtexcoord2f[5] = 0;
3539 r_bloomstate.bloomtexcoord2f[6] = 0;
3540 r_bloomstate.bloomtexcoord2f[7] = 0;
3542 if (r_hdr.integer || r_bloom.integer)
3544 r_bloomstate.enabled = true;
3545 r_bloomstate.hdr = r_hdr.integer != 0;
3549 void R_Bloom_CopyBloomTexture(float colorscale)
3551 r_refdef.stats.bloom++;
3553 // scale down screen texture to the bloom texture size
3555 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3556 GL_BlendFunc(GL_ONE, GL_ZERO);
3557 GL_Color(colorscale, colorscale, colorscale, 1);
3558 // TODO: optimize with multitexture or GLSL
3559 R_SetupGenericShader(true);
3560 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3561 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3562 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3563 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3565 // we now have a bloom image in the framebuffer
3566 // copy it into the bloom image texture for later processing
3567 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3568 GL_ActiveTexture(0);
3570 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
3571 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3574 void R_Bloom_CopyHDRTexture(void)
3576 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3577 GL_ActiveTexture(0);
3579 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
3580 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3583 void R_Bloom_MakeTexture(void)
3586 float xoffset, yoffset, r, brighten;
3588 r_refdef.stats.bloom++;
3590 R_ResetViewRendering2D();
3591 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3592 R_Mesh_ColorPointer(NULL, 0, 0);
3593 R_SetupGenericShader(true);
3595 // we have a bloom image in the framebuffer
3597 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3599 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3602 r = bound(0, r_bloom_colorexponent.value / x, 1);
3603 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3604 GL_Color(r, r, r, 1);
3605 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3606 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3607 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3608 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3610 // copy the vertically blurred bloom view to a texture
3611 GL_ActiveTexture(0);
3613 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
3614 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3617 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3618 brighten = r_bloom_brighten.value;
3620 brighten *= r_hdr_range.value;
3621 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3622 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3624 for (dir = 0;dir < 2;dir++)
3626 // blend on at multiple vertical offsets to achieve a vertical blur
3627 // TODO: do offset blends using GLSL
3628 GL_BlendFunc(GL_ONE, GL_ZERO);
3629 for (x = -range;x <= range;x++)
3631 if (!dir){xoffset = 0;yoffset = x;}
3632 else {xoffset = x;yoffset = 0;}
3633 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3634 yoffset /= (float)r_bloomstate.bloomtextureheight;
3635 // compute a texcoord array with the specified x and y offset
3636 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3637 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3638 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3639 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3640 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3641 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3642 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3643 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3644 // this r value looks like a 'dot' particle, fading sharply to
3645 // black at the edges
3646 // (probably not realistic but looks good enough)
3647 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3648 //r = (dir ? 1.0f : brighten)/(range*2+1);
3649 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3650 GL_Color(r, r, r, 1);
3651 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3652 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3653 GL_BlendFunc(GL_ONE, GL_ONE);
3656 // copy the vertically blurred bloom view to a texture
3657 GL_ActiveTexture(0);
3659 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
3660 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3663 // apply subtract last
3664 // (just like it would be in a GLSL shader)
3665 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3667 GL_BlendFunc(GL_ONE, GL_ZERO);
3668 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3669 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3670 GL_Color(1, 1, 1, 1);
3671 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3672 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3674 GL_BlendFunc(GL_ONE, GL_ONE);
3675 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3676 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3677 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3678 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3679 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3680 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3681 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3683 // copy the darkened bloom view to a texture
3684 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3685 GL_ActiveTexture(0);
3687 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
3688 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3692 void R_HDR_RenderBloomTexture(void)
3694 int oldwidth, oldheight;
3695 float oldcolorscale;
3697 oldcolorscale = r_refdef.view.colorscale;
3698 oldwidth = r_refdef.view.width;
3699 oldheight = r_refdef.view.height;
3700 r_refdef.view.width = r_bloomstate.bloomwidth;
3701 r_refdef.view.height = r_bloomstate.bloomheight;
3703 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3704 // TODO: add exposure compensation features
3705 // TODO: add fp16 framebuffer support
3707 r_refdef.view.showdebug = false;
3708 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3710 R_ResetViewRendering3D();
3712 R_ClearScreen(r_refdef.fogenabled);
3713 if (r_timereport_active)
3714 R_TimeReport("HDRclear");
3717 if (r_timereport_active)
3718 R_TimeReport("visibility");
3720 r_waterstate.numwaterplanes = 0;
3721 if (r_waterstate.enabled)
3722 R_RenderWaterPlanes();
3724 r_refdef.view.showdebug = true;
3726 r_waterstate.numwaterplanes = 0;
3728 R_ResetViewRendering2D();
3730 R_Bloom_CopyHDRTexture();
3731 R_Bloom_MakeTexture();
3733 // restore the view settings
3734 r_refdef.view.width = oldwidth;
3735 r_refdef.view.height = oldheight;
3736 r_refdef.view.colorscale = oldcolorscale;
3738 R_ResetViewRendering3D();
3740 R_ClearScreen(r_refdef.fogenabled);
3741 if (r_timereport_active)
3742 R_TimeReport("viewclear");
3745 static void R_BlendView(void)
3747 if (r_bloomstate.texture_screen)
3749 // make sure the buffer is available
3750 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
3752 R_ResetViewRendering2D();
3753 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3754 R_Mesh_ColorPointer(NULL, 0, 0);
3755 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3756 GL_ActiveTexture(0);CHECKGLERROR
3758 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
3760 // declare alpha variable
3763 static float avgspeed;
3765 speed = VectorLength(cl.movement_velocity);
3767 a = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
3768 avgspeed = avgspeed * (1 - a) + speed * a;
3770 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
3771 speed = bound(0, speed, 1);
3772 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
3774 // calculate values into a standard alpha
3777 (r_motionblur.value * speed / 80)
3779 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
3782 max(0.0001, cl.time - cl.oldtime) // fps independent
3785 a *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
3786 a = bound(0, a, r_motionblur_maxblur.value);
3788 // developer debug of current value
3789 if (r_motionblur_debug.value) { Con_Printf("blur alpha = %f\n", a); }
3794 R_SetupGenericShader(true);
3795 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3796 GL_Color(1, 1, 1, a); // to do: add color changing support for damage blur
3797 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3798 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3799 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3800 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3804 // copy view into the screen texture
3805 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
3806 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3809 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3811 unsigned int permutation =
3812 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3813 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3814 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3815 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
3816 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
3818 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3820 // render simple bloom effect
3821 // copy the screen and shrink it and darken it for the bloom process
3822 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3823 // make the bloom texture
3824 R_Bloom_MakeTexture();
3827 R_ResetViewRendering2D();
3828 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3829 R_Mesh_ColorPointer(NULL, 0, 0);
3830 GL_Color(1, 1, 1, 1);
3831 GL_BlendFunc(GL_ONE, GL_ZERO);
3832 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3833 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3834 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3835 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3836 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3837 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3838 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3839 if (r_glsl_permutation->loc_TintColor >= 0)
3840 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3841 if (r_glsl_permutation->loc_ClientTime >= 0)
3842 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3843 if (r_glsl_permutation->loc_PixelSize >= 0)
3844 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3845 if (r_glsl_permutation->loc_UserVec1 >= 0)
3847 float a=0, b=0, c=0, d=0;
3848 #if _MSC_VER >= 1400
3849 #define sscanf sscanf_s
3851 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3852 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3854 if (r_glsl_permutation->loc_UserVec2 >= 0)
3856 float a=0, b=0, c=0, d=0;
3857 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3858 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3860 if (r_glsl_permutation->loc_UserVec3 >= 0)
3862 float a=0, b=0, c=0, d=0;
3863 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3864 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3866 if (r_glsl_permutation->loc_UserVec4 >= 0)
3868 float a=0, b=0, c=0, d=0;
3869 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3870 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3872 if (r_glsl_permutation->loc_Saturation >= 0)
3873 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
3874 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3875 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3881 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3883 // render high dynamic range bloom effect
3884 // the bloom texture was made earlier this render, so we just need to
3885 // blend it onto the screen...
3886 R_ResetViewRendering2D();
3887 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3888 R_Mesh_ColorPointer(NULL, 0, 0);
3889 R_SetupGenericShader(true);
3890 GL_Color(1, 1, 1, 1);
3891 GL_BlendFunc(GL_ONE, GL_ONE);
3892 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3893 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3894 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3895 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3897 else if (r_bloomstate.texture_bloom)
3899 // render simple bloom effect
3900 // copy the screen and shrink it and darken it for the bloom process
3901 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3902 // make the bloom texture
3903 R_Bloom_MakeTexture();
3904 // put the original screen image back in place and blend the bloom
3906 R_ResetViewRendering2D();
3907 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3908 R_Mesh_ColorPointer(NULL, 0, 0);
3909 GL_Color(1, 1, 1, 1);
3910 GL_BlendFunc(GL_ONE, GL_ZERO);
3911 // do both in one pass if possible
3912 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3913 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3914 if (r_textureunits.integer >= 2 && gl_combine.integer)
3916 R_SetupGenericTwoTextureShader(GL_ADD);
3917 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3918 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3922 R_SetupGenericShader(true);
3923 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3924 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3925 // now blend on the bloom texture
3926 GL_BlendFunc(GL_ONE, GL_ONE);
3927 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3928 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3930 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3931 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3933 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3935 // apply a color tint to the whole view
3936 R_ResetViewRendering2D();
3937 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3938 R_Mesh_ColorPointer(NULL, 0, 0);
3939 R_SetupGenericShader(false);
3940 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3941 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3942 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3946 matrix4x4_t r_waterscrollmatrix;
3948 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3950 if (r_refdef.fog_density)
3952 r_refdef.fogcolor[0] = r_refdef.fog_red;
3953 r_refdef.fogcolor[1] = r_refdef.fog_green;
3954 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3958 VectorCopy(r_refdef.fogcolor, fogvec);
3959 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3961 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3962 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3963 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3964 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3966 // color.rgb *= ContrastBoost * SceneBrightness;
3967 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3968 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3969 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3970 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3975 void R_UpdateVariables(void)
3979 r_refdef.scene.ambient = r_ambient.value;
3981 r_refdef.farclip = 4096;
3982 if (r_refdef.scene.worldmodel)
3983 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3984 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3986 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3987 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3988 r_refdef.polygonfactor = 0;
3989 r_refdef.polygonoffset = 0;
3990 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3991 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3993 r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
3994 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3995 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3996 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3997 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3998 if (r_showsurfaces.integer)
4000 r_refdef.scene.rtworld = false;
4001 r_refdef.scene.rtworldshadows = false;
4002 r_refdef.scene.rtdlight = false;
4003 r_refdef.scene.rtdlightshadows = false;
4004 r_refdef.lightmapintensity = 0;
4007 if (gamemode == GAME_NEHAHRA)
4009 if (gl_fogenable.integer)
4011 r_refdef.oldgl_fogenable = true;
4012 r_refdef.fog_density = gl_fogdensity.value;
4013 r_refdef.fog_red = gl_fogred.value;
4014 r_refdef.fog_green = gl_foggreen.value;
4015 r_refdef.fog_blue = gl_fogblue.value;
4016 r_refdef.fog_alpha = 1;
4017 r_refdef.fog_start = 0;
4018 r_refdef.fog_end = gl_skyclip.value;
4020 else if (r_refdef.oldgl_fogenable)
4022 r_refdef.oldgl_fogenable = false;
4023 r_refdef.fog_density = 0;
4024 r_refdef.fog_red = 0;
4025 r_refdef.fog_green = 0;
4026 r_refdef.fog_blue = 0;
4027 r_refdef.fog_alpha = 0;
4028 r_refdef.fog_start = 0;
4029 r_refdef.fog_end = 0;
4033 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4034 r_refdef.fog_start = max(0, r_refdef.fog_start);
4035 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4037 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4039 if (r_refdef.fog_density && r_drawfog.integer)
4041 r_refdef.fogenabled = true;
4042 // this is the point where the fog reaches 0.9986 alpha, which we
4043 // consider a good enough cutoff point for the texture
4044 // (0.9986 * 256 == 255.6)
4045 if (r_fog_exp2.integer)
4046 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4048 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4049 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4050 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4051 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4052 // fog color was already set
4053 // update the fog texture
4054 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)
4055 R_BuildFogTexture();
4058 r_refdef.fogenabled = false;
4060 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4062 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4064 // build GLSL gamma texture
4065 #define RAMPWIDTH 256
4066 unsigned short ramp[RAMPWIDTH * 3];
4067 unsigned char rampbgr[RAMPWIDTH][4];
4070 r_texture_gammaramps_serial = vid_gammatables_serial;
4072 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4073 for(i = 0; i < RAMPWIDTH; ++i)
4075 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4076 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4077 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4080 if (r_texture_gammaramps)
4082 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4086 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);
4092 // remove GLSL gamma texture
4096 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4097 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4103 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4104 if( scenetype != r_currentscenetype ) {
4105 // store the old scenetype
4106 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4107 r_currentscenetype = scenetype;
4108 // move in the new scene
4109 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4118 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4120 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4121 if( scenetype == r_currentscenetype ) {
4122 return &r_refdef.scene;
4124 return &r_scenes_store[ scenetype ];
4133 void R_RenderView(void)
4135 r_frame++; // used only by R_GetCurrentTexture
4136 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4138 if (r_refdef.view.isoverlay)
4140 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4141 GL_Clear( GL_DEPTH_BUFFER_BIT );
4142 R_TimeReport("depthclear");
4144 r_refdef.view.showdebug = false;
4146 r_waterstate.enabled = false;
4147 r_waterstate.numwaterplanes = 0;
4155 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4156 return; //Host_Error ("R_RenderView: NULL worldmodel");
4158 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4160 // break apart the view matrix into vectors for various purposes
4161 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4162 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4163 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4164 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4165 // make an inverted copy of the view matrix for tracking sprites
4166 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4168 R_Shadow_UpdateWorldLightSelection();
4170 R_Bloom_StartFrame();
4171 R_Water_StartFrame();
4174 if (r_timereport_active)
4175 R_TimeReport("viewsetup");
4177 R_ResetViewRendering3D();
4179 if (r_refdef.view.clear || r_refdef.fogenabled)
4181 R_ClearScreen(r_refdef.fogenabled);
4182 if (r_timereport_active)
4183 R_TimeReport("viewclear");
4185 r_refdef.view.clear = true;
4187 // this produces a bloom texture to be used in R_BlendView() later
4189 R_HDR_RenderBloomTexture();
4191 r_refdef.view.showdebug = true;
4194 if (r_timereport_active)
4195 R_TimeReport("visibility");
4197 r_waterstate.numwaterplanes = 0;
4198 if (r_waterstate.enabled)
4199 R_RenderWaterPlanes();
4202 r_waterstate.numwaterplanes = 0;
4205 if (r_timereport_active)
4206 R_TimeReport("blendview");
4208 GL_Scissor(0, 0, vid.width, vid.height);
4209 GL_ScissorTest(false);
4213 void R_RenderWaterPlanes(void)
4215 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4217 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4218 if (r_timereport_active)
4219 R_TimeReport("waterworld");
4222 // don't let sound skip if going slow
4223 if (r_refdef.scene.extraupdate)
4226 R_DrawModelsAddWaterPlanes();
4227 if (r_timereport_active)
4228 R_TimeReport("watermodels");
4230 if (r_waterstate.numwaterplanes)
4232 R_Water_ProcessPlanes();
4233 if (r_timereport_active)
4234 R_TimeReport("waterscenes");
4238 extern void R_DrawLightningBeams (void);
4239 extern void VM_CL_AddPolygonsToMeshQueue (void);
4240 extern void R_DrawPortals (void);
4241 extern cvar_t cl_locs_show;
4242 static void R_DrawLocs(void);
4243 static void R_DrawEntityBBoxes(void);
4244 void R_RenderScene(void)
4246 r_refdef.stats.renders++;
4250 // don't let sound skip if going slow
4251 if (r_refdef.scene.extraupdate)
4254 R_MeshQueue_BeginScene();
4258 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);
4260 if (cl.csqc_vidvars.drawworld)
4262 // don't let sound skip if going slow
4263 if (r_refdef.scene.extraupdate)
4266 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4268 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4269 if (r_timereport_active)
4270 R_TimeReport("worldsky");
4273 if (R_DrawBrushModelsSky() && r_timereport_active)
4274 R_TimeReport("bmodelsky");
4277 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4279 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4280 if (r_timereport_active)
4281 R_TimeReport("worlddepth");
4283 if (r_depthfirst.integer >= 2)
4285 R_DrawModelsDepth();
4286 if (r_timereport_active)
4287 R_TimeReport("modeldepth");
4290 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4292 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4293 if (r_timereport_active)
4294 R_TimeReport("world");
4297 // don't let sound skip if going slow
4298 if (r_refdef.scene.extraupdate)
4303 if (r_timereport_active)
4304 R_TimeReport("models");
4306 // don't let sound skip if going slow
4307 if (r_refdef.scene.extraupdate)
4310 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
4312 R_DrawModelShadows();
4314 R_ResetViewRendering3D();
4316 // don't let sound skip if going slow
4317 if (r_refdef.scene.extraupdate)
4321 R_ShadowVolumeLighting(false);
4322 if (r_timereport_active)
4323 R_TimeReport("rtlights");
4325 // don't let sound skip if going slow
4326 if (r_refdef.scene.extraupdate)
4329 if (cl.csqc_vidvars.drawworld)
4331 R_DrawLightningBeams();
4332 if (r_timereport_active)
4333 R_TimeReport("lightning");
4336 if (r_timereport_active)
4337 R_TimeReport("decals");
4340 if (r_timereport_active)
4341 R_TimeReport("particles");
4344 if (r_timereport_active)
4345 R_TimeReport("explosions");
4348 R_SetupGenericShader(true);
4349 VM_CL_AddPolygonsToMeshQueue();
4351 if (r_refdef.view.showdebug)
4353 if (cl_locs_show.integer)
4356 if (r_timereport_active)
4357 R_TimeReport("showlocs");
4360 if (r_drawportals.integer)
4363 if (r_timereport_active)
4364 R_TimeReport("portals");
4367 if (r_showbboxes.value > 0)
4369 R_DrawEntityBBoxes();
4370 if (r_timereport_active)
4371 R_TimeReport("bboxes");
4375 R_SetupGenericShader(true);
4376 R_MeshQueue_RenderTransparent();
4377 if (r_timereport_active)
4378 R_TimeReport("drawtrans");
4380 R_SetupGenericShader(true);
4382 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))
4384 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4385 if (r_timereport_active)
4386 R_TimeReport("worlddebug");
4387 R_DrawModelsDebug();
4388 if (r_timereport_active)
4389 R_TimeReport("modeldebug");
4392 R_SetupGenericShader(true);
4394 if (cl.csqc_vidvars.drawworld)
4397 if (r_timereport_active)
4398 R_TimeReport("coronas");
4401 // don't let sound skip if going slow
4402 if (r_refdef.scene.extraupdate)
4405 R_ResetViewRendering2D();
4408 static const unsigned short bboxelements[36] =
4418 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4421 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4422 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4423 GL_DepthMask(false);
4424 GL_DepthRange(0, 1);
4425 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4426 R_Mesh_Matrix(&identitymatrix);
4427 R_Mesh_ResetTextureState();
4429 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4430 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4431 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4432 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4433 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4434 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4435 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4436 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4437 R_FillColors(color4f, 8, cr, cg, cb, ca);
4438 if (r_refdef.fogenabled)
4440 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4442 f1 = FogPoint_World(v);
4444 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4445 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4446 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4449 R_Mesh_VertexPointer(vertex3f, 0, 0);
4450 R_Mesh_ColorPointer(color4f, 0, 0);
4451 R_Mesh_ResetTextureState();
4452 R_SetupGenericShader(false);
4453 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4456 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4460 prvm_edict_t *edict;
4461 prvm_prog_t *prog_save = prog;
4463 // this function draws bounding boxes of server entities
4467 GL_CullFace(GL_NONE);
4468 R_SetupGenericShader(false);
4472 for (i = 0;i < numsurfaces;i++)
4474 edict = PRVM_EDICT_NUM(surfacelist[i]);
4475 switch ((int)edict->fields.server->solid)
4477 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4478 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4479 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4480 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4481 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4482 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4484 color[3] *= r_showbboxes.value;
4485 color[3] = bound(0, color[3], 1);
4486 GL_DepthTest(!r_showdisabledepthtest.integer);
4487 GL_CullFace(r_refdef.view.cullface_front);
4488 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4494 static void R_DrawEntityBBoxes(void)
4497 prvm_edict_t *edict;
4499 prvm_prog_t *prog_save = prog;
4501 // this function draws bounding boxes of server entities
4507 for (i = 0;i < prog->num_edicts;i++)
4509 edict = PRVM_EDICT_NUM(i);
4510 if (edict->priv.server->free)
4512 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4513 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4515 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4517 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4518 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4524 unsigned short nomodelelements[24] =
4536 float nomodelvertex3f[6*3] =
4546 float nomodelcolor4f[6*4] =
4548 0.0f, 0.0f, 0.5f, 1.0f,
4549 0.0f, 0.0f, 0.5f, 1.0f,
4550 0.0f, 0.5f, 0.0f, 1.0f,
4551 0.0f, 0.5f, 0.0f, 1.0f,
4552 0.5f, 0.0f, 0.0f, 1.0f,
4553 0.5f, 0.0f, 0.0f, 1.0f
4556 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4561 // this is only called once per entity so numsurfaces is always 1, and
4562 // surfacelist is always {0}, so this code does not handle batches
4563 R_Mesh_Matrix(&ent->matrix);
4565 if (ent->flags & EF_ADDITIVE)
4567 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4568 GL_DepthMask(false);
4570 else if (ent->alpha < 1)
4572 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4573 GL_DepthMask(false);
4577 GL_BlendFunc(GL_ONE, GL_ZERO);
4580 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4581 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4582 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4583 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4584 R_SetupGenericShader(false);
4585 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4586 if (r_refdef.fogenabled)
4589 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4590 R_Mesh_ColorPointer(color4f, 0, 0);
4591 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4592 f1 = FogPoint_World(org);
4594 for (i = 0, c = color4f;i < 6;i++, c += 4)
4596 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4597 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4598 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4602 else if (ent->alpha != 1)
4604 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4605 R_Mesh_ColorPointer(color4f, 0, 0);
4606 for (i = 0, c = color4f;i < 6;i++, c += 4)
4610 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4611 R_Mesh_ResetTextureState();
4612 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4615 void R_DrawNoModel(entity_render_t *ent)
4618 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4619 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4620 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4622 // R_DrawNoModelCallback(ent, 0);
4625 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4627 vec3_t right1, right2, diff, normal;
4629 VectorSubtract (org2, org1, normal);
4631 // calculate 'right' vector for start
4632 VectorSubtract (r_refdef.view.origin, org1, diff);
4633 CrossProduct (normal, diff, right1);
4634 VectorNormalize (right1);
4636 // calculate 'right' vector for end
4637 VectorSubtract (r_refdef.view.origin, org2, diff);
4638 CrossProduct (normal, diff, right2);
4639 VectorNormalize (right2);
4641 vert[ 0] = org1[0] + width * right1[0];
4642 vert[ 1] = org1[1] + width * right1[1];
4643 vert[ 2] = org1[2] + width * right1[2];
4644 vert[ 3] = org1[0] - width * right1[0];
4645 vert[ 4] = org1[1] - width * right1[1];
4646 vert[ 5] = org1[2] - width * right1[2];
4647 vert[ 6] = org2[0] - width * right2[0];
4648 vert[ 7] = org2[1] - width * right2[1];
4649 vert[ 8] = org2[2] - width * right2[2];
4650 vert[ 9] = org2[0] + width * right2[0];
4651 vert[10] = org2[1] + width * right2[1];
4652 vert[11] = org2[2] + width * right2[2];
4655 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4657 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)
4659 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4663 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4664 fog = FogPoint_World(origin);
4666 R_Mesh_Matrix(&identitymatrix);
4667 GL_BlendFunc(blendfunc1, blendfunc2);
4669 GL_CullFace(GL_NONE);
4671 GL_DepthMask(false);
4672 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4673 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4674 GL_DepthTest(!depthdisable);
4676 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4677 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4678 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4679 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4680 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4681 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4682 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4683 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4684 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4685 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4686 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4687 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4689 R_Mesh_VertexPointer(vertex3f, 0, 0);
4690 R_Mesh_ColorPointer(NULL, 0, 0);
4691 R_Mesh_ResetTextureState();
4692 R_SetupGenericShader(true);
4693 R_Mesh_TexBind(0, R_GetTexture(texture));
4694 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4695 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4696 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4697 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4699 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4701 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4702 GL_BlendFunc(blendfunc1, GL_ONE);
4704 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4705 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4709 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4714 VectorSet(v, x, y, z);
4715 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4716 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4718 if (i == mesh->numvertices)
4720 if (mesh->numvertices < mesh->maxvertices)
4722 VectorCopy(v, vertex3f);
4723 mesh->numvertices++;
4725 return mesh->numvertices;
4731 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4735 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4736 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4737 e = mesh->element3i + mesh->numtriangles * 3;
4738 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4740 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4741 if (mesh->numtriangles < mesh->maxtriangles)
4746 mesh->numtriangles++;
4748 element[1] = element[2];
4752 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4756 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4757 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4758 e = mesh->element3i + mesh->numtriangles * 3;
4759 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4761 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4762 if (mesh->numtriangles < mesh->maxtriangles)
4767 mesh->numtriangles++;
4769 element[1] = element[2];
4773 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4774 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4776 int planenum, planenum2;
4779 mplane_t *plane, *plane2;
4781 double temppoints[2][256*3];
4782 // figure out how large a bounding box we need to properly compute this brush
4784 for (w = 0;w < numplanes;w++)
4785 maxdist = max(maxdist, planes[w].dist);
4786 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4787 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4788 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4792 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4793 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4795 if (planenum2 == planenum)
4797 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);
4800 if (tempnumpoints < 3)
4802 // generate elements forming a triangle fan for this polygon
4803 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4807 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)
4809 texturelayer_t *layer;
4810 layer = t->currentlayers + t->currentnumlayers++;
4812 layer->depthmask = depthmask;
4813 layer->blendfunc1 = blendfunc1;
4814 layer->blendfunc2 = blendfunc2;
4815 layer->texture = texture;
4816 layer->texmatrix = *matrix;
4817 layer->color[0] = r * r_refdef.view.colorscale;
4818 layer->color[1] = g * r_refdef.view.colorscale;
4819 layer->color[2] = b * r_refdef.view.colorscale;
4820 layer->color[3] = a;
4823 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4826 index = parms[2] + r_refdef.scene.time * parms[3];
4827 index -= floor(index);
4831 case Q3WAVEFUNC_NONE:
4832 case Q3WAVEFUNC_NOISE:
4833 case Q3WAVEFUNC_COUNT:
4836 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4837 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4838 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4839 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4840 case Q3WAVEFUNC_TRIANGLE:
4842 f = index - floor(index);
4853 return (float)(parms[0] + parms[1] * f);
4856 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
4861 matrix4x4_t matrix, temp;
4862 switch(tcmod->tcmod)
4866 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4867 matrix = r_waterscrollmatrix;
4869 matrix = identitymatrix;
4871 case Q3TCMOD_ENTITYTRANSLATE:
4872 // this is used in Q3 to allow the gamecode to control texcoord
4873 // scrolling on the entity, which is not supported in darkplaces yet.
4874 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4876 case Q3TCMOD_ROTATE:
4877 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4878 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4879 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4882 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4884 case Q3TCMOD_SCROLL:
4885 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4887 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4888 w = (int) tcmod->parms[0];
4889 h = (int) tcmod->parms[1];
4890 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4892 idx = (int) floor(f * w * h);
4893 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4895 case Q3TCMOD_STRETCH:
4896 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4897 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4899 case Q3TCMOD_TRANSFORM:
4900 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4901 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4902 VectorSet(tcmat + 6, 0 , 0 , 1);
4903 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4904 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4906 case Q3TCMOD_TURBULENT:
4907 // this is handled in the RSurf_PrepareVertices function
4908 matrix = identitymatrix;
4912 Matrix4x4_Concat(texmatrix, &matrix, &temp);
4915 texture_t *R_GetCurrentTexture(texture_t *t)
4918 const entity_render_t *ent = rsurface.entity;
4919 dp_model_t *model = ent->model;
4920 q3shaderinfo_layer_tcmod_t *tcmod;
4922 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
4923 return t->currentframe;
4924 t->update_lastrenderframe = r_frame;
4925 t->update_lastrenderentity = (void *)ent;
4927 // switch to an alternate material if this is a q1bsp animated material
4929 texture_t *texture = t;
4930 int s = ent->skinnum;
4931 if ((unsigned int)s >= (unsigned int)model->numskins)
4933 if (model->skinscenes)
4935 if (model->skinscenes[s].framecount > 1)
4936 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4938 s = model->skinscenes[s].firstframe;
4941 t = t + s * model->num_surfaces;
4944 // use an alternate animation if the entity's frame is not 0,
4945 // and only if the texture has an alternate animation
4946 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
4947 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4949 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4951 texture->currentframe = t;
4954 // update currentskinframe to be a qw skin or animation frame
4955 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"))
4957 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4959 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4960 if (developer_loading.integer)
4961 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4962 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);
4964 t->currentskinframe = r_qwskincache_skinframe[i];
4965 if (t->currentskinframe == NULL)
4966 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4968 else if (t->numskinframes >= 2)
4969 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4970 if (t->backgroundnumskinframes >= 2)
4971 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
4973 t->currentmaterialflags = t->basematerialflags;
4974 t->currentalpha = ent->alpha;
4975 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4976 t->currentalpha *= r_wateralpha.value;
4977 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4978 t->currentalpha *= t->r_water_wateralpha;
4979 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4980 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4981 if (!(ent->flags & RENDER_LIGHT))
4982 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4983 else if (rsurface.modeltexcoordlightmap2f == NULL)
4985 // pick a model lighting mode
4986 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4987 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4989 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4991 if (ent->effects & EF_ADDITIVE)
4992 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4993 else if (t->currentalpha < 1)
4994 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4995 if (ent->effects & EF_DOUBLESIDED)
4996 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4997 if (ent->effects & EF_NODEPTHTEST)
4998 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4999 if (ent->flags & RENDER_VIEWMODEL)
5000 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5001 if (t->backgroundnumskinframes)
5002 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5003 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5005 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5006 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5009 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5011 // there is no tcmod
5012 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5014 t->currenttexmatrix = r_waterscrollmatrix;
5015 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5019 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5020 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5023 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5024 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5025 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5026 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5028 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5029 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5030 t->glosstexture = r_texture_black;
5031 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5032 t->backgroundglosstexture = r_texture_black;
5033 t->specularpower = r_shadow_glossexponent.value;
5034 // TODO: store reference values for these in the texture?
5035 t->specularscale = 0;
5036 if (r_shadow_gloss.integer > 0)
5038 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5040 if (r_shadow_glossintensity.value > 0)
5042 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5043 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5044 t->specularscale = r_shadow_glossintensity.value;
5047 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5049 t->glosstexture = r_texture_white;
5050 t->backgroundglosstexture = r_texture_white;
5051 t->specularscale = r_shadow_gloss2intensity.value;
5055 // lightmaps mode looks bad with dlights using actual texturing, so turn
5056 // off the colormap and glossmap, but leave the normalmap on as it still
5057 // accurately represents the shading involved
5058 if (gl_lightmaps.integer)
5060 t->basetexture = r_texture_grey128;
5061 t->backgroundbasetexture = NULL;
5062 t->specularscale = 0;
5063 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5066 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5067 VectorClear(t->dlightcolor);
5068 t->currentnumlayers = 0;
5069 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5072 int blendfunc1, blendfunc2, depthmask;
5073 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5075 blendfunc1 = GL_SRC_ALPHA;
5076 blendfunc2 = GL_ONE;
5078 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5080 blendfunc1 = GL_SRC_ALPHA;
5081 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5083 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5085 blendfunc1 = t->customblendfunc[0];
5086 blendfunc2 = t->customblendfunc[1];
5090 blendfunc1 = GL_ONE;
5091 blendfunc2 = GL_ZERO;
5093 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5094 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5095 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5096 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5098 // fullbright is not affected by r_refdef.lightmapintensity
5099 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]);
5100 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5101 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]);
5102 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5103 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]);
5107 vec3_t ambientcolor;
5109 // set the color tint used for lights affecting this surface
5110 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5112 // q3bsp has no lightmap updates, so the lightstylevalue that
5113 // would normally be baked into the lightmap must be
5114 // applied to the color
5115 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5116 if (ent->model->type == mod_brushq3)
5117 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5118 colorscale *= r_refdef.lightmapintensity;
5119 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5120 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5121 // basic lit geometry
5122 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]);
5123 // add pants/shirt if needed
5124 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5125 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]);
5126 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5127 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]);
5128 // now add ambient passes if needed
5129 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5131 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]);
5132 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5133 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]);
5134 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5135 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]);
5138 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5139 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]);
5140 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5142 // if this is opaque use alpha blend which will darken the earlier
5145 // if this is an alpha blended material, all the earlier passes
5146 // were darkened by fog already, so we only need to add the fog
5147 // color ontop through the fog mask texture
5149 // if this is an additive blended material, all the earlier passes
5150 // were darkened by fog already, and we should not add fog color
5151 // (because the background was not darkened, there is no fog color
5152 // that was lost behind it).
5153 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]);
5157 return t->currentframe;
5160 rsurfacestate_t rsurface;
5162 void R_Mesh_ResizeArrays(int newvertices)
5165 if (rsurface.array_size >= newvertices)
5167 if (rsurface.array_modelvertex3f)
5168 Mem_Free(rsurface.array_modelvertex3f);
5169 rsurface.array_size = (newvertices + 1023) & ~1023;
5170 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5171 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5172 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5173 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5174 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5175 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5176 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5177 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5178 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5179 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5180 rsurface.array_color4f = base + rsurface.array_size * 27;
5181 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5184 void RSurf_ActiveWorldEntity(void)
5186 dp_model_t *model = r_refdef.scene.worldmodel;
5187 //if (rsurface.entity == r_refdef.scene.worldentity)
5189 rsurface.entity = r_refdef.scene.worldentity;
5190 if (rsurface.array_size < model->surfmesh.num_vertices)
5191 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5192 rsurface.matrix = identitymatrix;
5193 rsurface.inversematrix = identitymatrix;
5194 R_Mesh_Matrix(&identitymatrix);
5195 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5196 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5197 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5198 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5199 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5200 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5201 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5202 rsurface.frameblend[0].lerp = 1;
5203 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5204 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5205 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5206 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5207 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5208 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5209 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5210 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5211 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5212 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5213 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5214 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5215 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5216 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5217 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5218 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5219 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5220 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5221 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5222 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5223 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5224 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5225 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5226 rsurface.modelelement3i = model->surfmesh.data_element3i;
5227 rsurface.modelelement3s = model->surfmesh.data_element3s;
5228 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5229 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5230 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5231 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5232 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5233 rsurface.modelsurfaces = model->data_surfaces;
5234 rsurface.generatedvertex = false;
5235 rsurface.vertex3f = rsurface.modelvertex3f;
5236 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5237 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5238 rsurface.svector3f = rsurface.modelsvector3f;
5239 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5240 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5241 rsurface.tvector3f = rsurface.modeltvector3f;
5242 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5243 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5244 rsurface.normal3f = rsurface.modelnormal3f;
5245 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5246 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5247 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5250 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5252 dp_model_t *model = ent->model;
5253 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5255 rsurface.entity = (entity_render_t *)ent;
5256 if (rsurface.array_size < model->surfmesh.num_vertices)
5257 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5258 rsurface.matrix = ent->matrix;
5259 rsurface.inversematrix = ent->inversematrix;
5260 R_Mesh_Matrix(&rsurface.matrix);
5261 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5262 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5263 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5264 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5265 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5266 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5267 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5268 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5269 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5270 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5271 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5272 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5273 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5274 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5275 if (ent->model->brush.submodel)
5277 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5278 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5280 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5282 if (ent->animcacheindex != 0)
5284 rsurface.modelvertex3f = r_animCache[ent->animcacheindex-1].vertexes;
5285 rsurface.modelsvector3f = wanttangents ? r_animCache[ent->animcacheindex-1].sVectors : NULL;
5286 rsurface.modeltvector3f = wanttangents ? r_animCache[ent->animcacheindex-1].tVectors : NULL;
5287 rsurface.modelnormal3f = wantnormals ? r_animCache[ent->animcacheindex-1].normals : NULL;
5289 else if (wanttangents)
5291 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5292 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5293 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5294 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5295 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5297 else if (wantnormals)
5299 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5300 rsurface.modelsvector3f = NULL;
5301 rsurface.modeltvector3f = NULL;
5302 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5303 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5307 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5308 rsurface.modelsvector3f = NULL;
5309 rsurface.modeltvector3f = NULL;
5310 rsurface.modelnormal3f = NULL;
5311 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5313 rsurface.modelvertex3f_bufferobject = 0;
5314 rsurface.modelvertex3f_bufferoffset = 0;
5315 rsurface.modelsvector3f_bufferobject = 0;
5316 rsurface.modelsvector3f_bufferoffset = 0;
5317 rsurface.modeltvector3f_bufferobject = 0;
5318 rsurface.modeltvector3f_bufferoffset = 0;
5319 rsurface.modelnormal3f_bufferobject = 0;
5320 rsurface.modelnormal3f_bufferoffset = 0;
5321 rsurface.generatedvertex = true;
5325 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5326 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5327 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5328 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5329 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5330 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5331 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5332 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5333 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5334 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5335 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5336 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5337 rsurface.generatedvertex = false;
5339 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5340 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5341 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5342 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5343 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5344 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5345 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5346 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5347 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5348 rsurface.modelelement3i = model->surfmesh.data_element3i;
5349 rsurface.modelelement3s = model->surfmesh.data_element3s;
5350 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5351 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5352 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5353 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5354 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5355 rsurface.modelsurfaces = model->data_surfaces;
5356 rsurface.vertex3f = rsurface.modelvertex3f;
5357 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5358 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5359 rsurface.svector3f = rsurface.modelsvector3f;
5360 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5361 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5362 rsurface.tvector3f = rsurface.modeltvector3f;
5363 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5364 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5365 rsurface.normal3f = rsurface.modelnormal3f;
5366 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5367 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5368 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5371 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5372 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5375 int texturesurfaceindex;
5380 const float *v1, *in_tc;
5382 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5384 q3shaderinfo_deform_t *deform;
5385 // 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
5386 if (rsurface.generatedvertex)
5388 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5389 generatenormals = true;
5390 for (i = 0;i < Q3MAXDEFORMS;i++)
5392 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5394 generatetangents = true;
5395 generatenormals = true;
5397 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5398 generatenormals = true;
5400 if (generatenormals && !rsurface.modelnormal3f)
5402 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5403 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5404 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5405 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5407 if (generatetangents && !rsurface.modelsvector3f)
5409 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5410 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5411 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5412 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5413 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5414 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5415 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);
5418 rsurface.vertex3f = rsurface.modelvertex3f;
5419 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5420 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5421 rsurface.svector3f = rsurface.modelsvector3f;
5422 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5423 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5424 rsurface.tvector3f = rsurface.modeltvector3f;
5425 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5426 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5427 rsurface.normal3f = rsurface.modelnormal3f;
5428 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5429 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5430 // if vertices are deformed (sprite flares and things in maps, possibly
5431 // water waves, bulges and other deformations), generate them into
5432 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5433 // (may be static model data or generated data for an animated model, or
5434 // the previous deform pass)
5435 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5437 switch (deform->deform)
5440 case Q3DEFORM_PROJECTIONSHADOW:
5441 case Q3DEFORM_TEXT0:
5442 case Q3DEFORM_TEXT1:
5443 case Q3DEFORM_TEXT2:
5444 case Q3DEFORM_TEXT3:
5445 case Q3DEFORM_TEXT4:
5446 case Q3DEFORM_TEXT5:
5447 case Q3DEFORM_TEXT6:
5448 case Q3DEFORM_TEXT7:
5451 case Q3DEFORM_AUTOSPRITE:
5452 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5453 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5454 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5455 VectorNormalize(newforward);
5456 VectorNormalize(newright);
5457 VectorNormalize(newup);
5458 // make deformed versions of only the model vertices used by the specified surfaces
5459 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5461 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5462 // a single autosprite surface can contain multiple sprites...
5463 for (j = 0;j < surface->num_vertices - 3;j += 4)
5465 VectorClear(center);
5466 for (i = 0;i < 4;i++)
5467 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5468 VectorScale(center, 0.25f, center);
5469 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5470 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5471 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5472 for (i = 0;i < 4;i++)
5474 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5475 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5478 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);
5479 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);
5481 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5482 rsurface.vertex3f_bufferobject = 0;
5483 rsurface.vertex3f_bufferoffset = 0;
5484 rsurface.svector3f = rsurface.array_deformedsvector3f;
5485 rsurface.svector3f_bufferobject = 0;
5486 rsurface.svector3f_bufferoffset = 0;
5487 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5488 rsurface.tvector3f_bufferobject = 0;
5489 rsurface.tvector3f_bufferoffset = 0;
5490 rsurface.normal3f = rsurface.array_deformednormal3f;
5491 rsurface.normal3f_bufferobject = 0;
5492 rsurface.normal3f_bufferoffset = 0;
5494 case Q3DEFORM_AUTOSPRITE2:
5495 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5496 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5497 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5498 VectorNormalize(newforward);
5499 VectorNormalize(newright);
5500 VectorNormalize(newup);
5501 // make deformed versions of only the model vertices used by the specified surfaces
5502 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5504 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5505 const float *v1, *v2;
5515 memset(shortest, 0, sizeof(shortest));
5516 // a single autosprite surface can contain multiple sprites...
5517 for (j = 0;j < surface->num_vertices - 3;j += 4)
5519 VectorClear(center);
5520 for (i = 0;i < 4;i++)
5521 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5522 VectorScale(center, 0.25f, center);
5523 // find the two shortest edges, then use them to define the
5524 // axis vectors for rotating around the central axis
5525 for (i = 0;i < 6;i++)
5527 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5528 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5530 Debug_PolygonBegin(NULL, 0);
5531 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5532 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);
5533 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5536 l = VectorDistance2(v1, v2);
5537 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5539 l += (1.0f / 1024.0f);
5540 if (shortest[0].length2 > l || i == 0)
5542 shortest[1] = shortest[0];
5543 shortest[0].length2 = l;
5544 shortest[0].v1 = v1;
5545 shortest[0].v2 = v2;
5547 else if (shortest[1].length2 > l || i == 1)
5549 shortest[1].length2 = l;
5550 shortest[1].v1 = v1;
5551 shortest[1].v2 = v2;
5554 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5555 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5557 Debug_PolygonBegin(NULL, 0);
5558 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5559 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);
5560 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5563 // this calculates the right vector from the shortest edge
5564 // and the up vector from the edge midpoints
5565 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5566 VectorNormalize(right);
5567 VectorSubtract(end, start, up);
5568 VectorNormalize(up);
5569 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5570 VectorSubtract(rsurface.modelorg, center, forward);
5571 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5572 VectorNegate(forward, forward);
5573 VectorReflect(forward, 0, up, forward);
5574 VectorNormalize(forward);
5575 CrossProduct(up, forward, newright);
5576 VectorNormalize(newright);
5578 Debug_PolygonBegin(NULL, 0);
5579 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);
5580 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5581 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5585 Debug_PolygonBegin(NULL, 0);
5586 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5587 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5588 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5591 // rotate the quad around the up axis vector, this is made
5592 // especially easy by the fact we know the quad is flat,
5593 // so we only have to subtract the center position and
5594 // measure distance along the right vector, and then
5595 // multiply that by the newright vector and add back the
5597 // we also need to subtract the old position to undo the
5598 // displacement from the center, which we do with a
5599 // DotProduct, the subtraction/addition of center is also
5600 // optimized into DotProducts here
5601 l = DotProduct(right, center);
5602 for (i = 0;i < 4;i++)
5604 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5605 f = DotProduct(right, v1) - l;
5606 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5609 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);
5610 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);
5612 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5613 rsurface.vertex3f_bufferobject = 0;
5614 rsurface.vertex3f_bufferoffset = 0;
5615 rsurface.svector3f = rsurface.array_deformedsvector3f;
5616 rsurface.svector3f_bufferobject = 0;
5617 rsurface.svector3f_bufferoffset = 0;
5618 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5619 rsurface.tvector3f_bufferobject = 0;
5620 rsurface.tvector3f_bufferoffset = 0;
5621 rsurface.normal3f = rsurface.array_deformednormal3f;
5622 rsurface.normal3f_bufferobject = 0;
5623 rsurface.normal3f_bufferoffset = 0;
5625 case Q3DEFORM_NORMAL:
5626 // deform the normals to make reflections wavey
5627 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5629 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5630 for (j = 0;j < surface->num_vertices;j++)
5633 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5634 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5635 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5636 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5637 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5638 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5639 VectorNormalize(normal);
5641 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);
5643 rsurface.svector3f = rsurface.array_deformedsvector3f;
5644 rsurface.svector3f_bufferobject = 0;
5645 rsurface.svector3f_bufferoffset = 0;
5646 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5647 rsurface.tvector3f_bufferobject = 0;
5648 rsurface.tvector3f_bufferoffset = 0;
5649 rsurface.normal3f = rsurface.array_deformednormal3f;
5650 rsurface.normal3f_bufferobject = 0;
5651 rsurface.normal3f_bufferoffset = 0;
5654 // deform vertex array to make wavey water and flags and such
5655 waveparms[0] = deform->waveparms[0];
5656 waveparms[1] = deform->waveparms[1];
5657 waveparms[2] = deform->waveparms[2];
5658 waveparms[3] = deform->waveparms[3];
5659 // this is how a divisor of vertex influence on deformation
5660 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5661 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5662 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5664 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5665 for (j = 0;j < surface->num_vertices;j++)
5667 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5668 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5669 // if the wavefunc depends on time, evaluate it per-vertex
5672 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5673 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5675 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5678 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5679 rsurface.vertex3f_bufferobject = 0;
5680 rsurface.vertex3f_bufferoffset = 0;
5682 case Q3DEFORM_BULGE:
5683 // deform vertex array to make the surface have moving bulges
5684 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5686 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5687 for (j = 0;j < surface->num_vertices;j++)
5689 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5690 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5693 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5694 rsurface.vertex3f_bufferobject = 0;
5695 rsurface.vertex3f_bufferoffset = 0;
5698 // deform vertex array
5699 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5700 VectorScale(deform->parms, scale, waveparms);
5701 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5703 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5704 for (j = 0;j < surface->num_vertices;j++)
5705 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5707 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5708 rsurface.vertex3f_bufferobject = 0;
5709 rsurface.vertex3f_bufferoffset = 0;
5713 // generate texcoords based on the chosen texcoord source
5714 switch(rsurface.texture->tcgen.tcgen)
5717 case Q3TCGEN_TEXTURE:
5718 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5719 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5720 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5722 case Q3TCGEN_LIGHTMAP:
5723 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5724 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5725 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5727 case Q3TCGEN_VECTOR:
5728 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5730 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5731 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)
5733 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5734 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5737 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5738 rsurface.texcoordtexture2f_bufferobject = 0;
5739 rsurface.texcoordtexture2f_bufferoffset = 0;
5741 case Q3TCGEN_ENVIRONMENT:
5742 // make environment reflections using a spheremap
5743 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5745 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5746 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5747 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5748 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5749 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5751 // identical to Q3A's method, but executed in worldspace so
5752 // carried models can be shiny too
5754 float viewer[3], d, reflected[3], worldreflected[3];
5756 VectorSubtract(rsurface.modelorg, vertex, viewer);
5757 // VectorNormalize(viewer);
5759 d = DotProduct(normal, viewer);
5761 reflected[0] = normal[0]*2*d - viewer[0];
5762 reflected[1] = normal[1]*2*d - viewer[1];
5763 reflected[2] = normal[2]*2*d - viewer[2];
5764 // note: this is proportinal to viewer, so we can normalize later
5766 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
5767 VectorNormalize(worldreflected);
5769 // note: this sphere map only uses world x and z!
5770 // so positive and negative y will LOOK THE SAME.
5771 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
5772 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
5775 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5776 rsurface.texcoordtexture2f_bufferobject = 0;
5777 rsurface.texcoordtexture2f_bufferoffset = 0;
5780 // the only tcmod that needs software vertex processing is turbulent, so
5781 // check for it here and apply the changes if needed
5782 // and we only support that as the first one
5783 // (handling a mixture of turbulent and other tcmods would be problematic
5784 // without punting it entirely to a software path)
5785 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5787 amplitude = rsurface.texture->tcmods[0].parms[1];
5788 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5789 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5791 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5792 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)
5794 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5795 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5798 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5799 rsurface.texcoordtexture2f_bufferobject = 0;
5800 rsurface.texcoordtexture2f_bufferoffset = 0;
5802 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5803 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5804 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5805 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5808 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5811 const msurface_t *surface = texturesurfacelist[0];
5812 const msurface_t *surface2;
5817 // TODO: lock all array ranges before render, rather than on each surface
5818 if (texturenumsurfaces == 1)
5820 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5821 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);
5823 else if (r_batchmode.integer == 2)
5825 #define MAXBATCHTRIANGLES 4096
5826 int batchtriangles = 0;
5827 int batchelements[MAXBATCHTRIANGLES*3];
5828 for (i = 0;i < texturenumsurfaces;i = j)
5830 surface = texturesurfacelist[i];
5832 if (surface->num_triangles > MAXBATCHTRIANGLES)
5834 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 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5838 batchtriangles = surface->num_triangles;
5839 firstvertex = surface->num_firstvertex;
5840 endvertex = surface->num_firstvertex + surface->num_vertices;
5841 for (;j < texturenumsurfaces;j++)
5843 surface2 = texturesurfacelist[j];
5844 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5846 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5847 batchtriangles += surface2->num_triangles;
5848 firstvertex = min(firstvertex, surface2->num_firstvertex);
5849 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5851 surface2 = texturesurfacelist[j-1];
5852 numvertices = endvertex - firstvertex;
5853 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5856 else if (r_batchmode.integer == 1)
5858 for (i = 0;i < texturenumsurfaces;i = j)
5860 surface = texturesurfacelist[i];
5861 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5862 if (texturesurfacelist[j] != surface2)
5864 surface2 = texturesurfacelist[j-1];
5865 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5866 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5867 GL_LockArrays(surface->num_firstvertex, numvertices);
5868 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5873 for (i = 0;i < texturenumsurfaces;i++)
5875 surface = texturesurfacelist[i];
5876 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5877 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);
5882 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5884 int i, planeindex, vertexindex;
5888 r_waterstate_waterplane_t *p, *bestp;
5889 msurface_t *surface;
5890 if (r_waterstate.renderingscene)
5892 for (i = 0;i < texturenumsurfaces;i++)
5894 surface = texturesurfacelist[i];
5895 if (lightmaptexunit >= 0)
5896 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5897 if (deluxemaptexunit >= 0)
5898 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5899 // pick the closest matching water plane
5902 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5905 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5907 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5908 d += fabs(PlaneDiff(vert, &p->plane));
5910 if (bestd > d || !bestp)
5918 if (refractiontexunit >= 0)
5919 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5920 if (reflectiontexunit >= 0)
5921 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5925 if (refractiontexunit >= 0)
5926 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5927 if (reflectiontexunit >= 0)
5928 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5930 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5931 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);
5935 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5939 const msurface_t *surface = texturesurfacelist[0];
5940 const msurface_t *surface2;
5945 // TODO: lock all array ranges before render, rather than on each surface
5946 if (texturenumsurfaces == 1)
5948 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5949 if (deluxemaptexunit >= 0)
5950 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5951 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5952 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);
5954 else if (r_batchmode.integer == 2)
5956 #define MAXBATCHTRIANGLES 4096
5957 int batchtriangles = 0;
5958 int batchelements[MAXBATCHTRIANGLES*3];
5959 for (i = 0;i < texturenumsurfaces;i = j)
5961 surface = texturesurfacelist[i];
5962 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5963 if (deluxemaptexunit >= 0)
5964 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5966 if (surface->num_triangles > MAXBATCHTRIANGLES)
5968 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);
5971 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5972 batchtriangles = surface->num_triangles;
5973 firstvertex = surface->num_firstvertex;
5974 endvertex = surface->num_firstvertex + surface->num_vertices;
5975 for (;j < texturenumsurfaces;j++)
5977 surface2 = texturesurfacelist[j];
5978 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5980 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5981 batchtriangles += surface2->num_triangles;
5982 firstvertex = min(firstvertex, surface2->num_firstvertex);
5983 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5985 surface2 = texturesurfacelist[j-1];
5986 numvertices = endvertex - firstvertex;
5987 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5990 else if (r_batchmode.integer == 1)
5993 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5994 for (i = 0;i < texturenumsurfaces;i = j)
5996 surface = texturesurfacelist[i];
5997 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5998 if (texturesurfacelist[j] != surface2)
6000 Con_Printf(" %i", j - i);
6003 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6005 for (i = 0;i < texturenumsurfaces;i = j)
6007 surface = texturesurfacelist[i];
6008 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6009 if (deluxemaptexunit >= 0)
6010 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6011 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6012 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6015 Con_Printf(" %i", j - i);
6017 surface2 = texturesurfacelist[j-1];
6018 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6019 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6020 GL_LockArrays(surface->num_firstvertex, numvertices);
6021 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6029 for (i = 0;i < texturenumsurfaces;i++)
6031 surface = texturesurfacelist[i];
6032 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6033 if (deluxemaptexunit >= 0)
6034 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6035 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6036 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);
6041 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6044 int texturesurfaceindex;
6045 if (r_showsurfaces.integer == 2)
6047 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6049 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6050 for (j = 0;j < surface->num_triangles;j++)
6052 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6053 GL_Color(f, f, f, 1);
6054 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6060 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6062 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6063 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6064 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);
6065 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6066 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);
6071 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6073 int texturesurfaceindex;
6076 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6078 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6079 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)
6087 rsurface.lightmapcolor4f = rsurface.array_color4f;
6088 rsurface.lightmapcolor4f_bufferobject = 0;
6089 rsurface.lightmapcolor4f_bufferoffset = 0;
6092 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6094 int texturesurfaceindex;
6098 if (rsurface.lightmapcolor4f)
6100 // generate color arrays for the surfaces in this list
6101 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6103 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6104 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)
6106 f = FogPoint_Model(v);
6116 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6118 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6119 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)
6121 f = FogPoint_Model(v);
6129 rsurface.lightmapcolor4f = rsurface.array_color4f;
6130 rsurface.lightmapcolor4f_bufferobject = 0;
6131 rsurface.lightmapcolor4f_bufferoffset = 0;
6134 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6136 int texturesurfaceindex;
6140 if (!rsurface.lightmapcolor4f)
6142 // generate color arrays for the surfaces in this list
6143 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6145 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6146 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)
6148 f = FogPoint_Model(v);
6149 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6150 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6151 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6155 rsurface.lightmapcolor4f = rsurface.array_color4f;
6156 rsurface.lightmapcolor4f_bufferobject = 0;
6157 rsurface.lightmapcolor4f_bufferoffset = 0;
6160 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6162 int texturesurfaceindex;
6165 if (!rsurface.lightmapcolor4f)
6167 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6169 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6170 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)
6178 rsurface.lightmapcolor4f = rsurface.array_color4f;
6179 rsurface.lightmapcolor4f_bufferobject = 0;
6180 rsurface.lightmapcolor4f_bufferoffset = 0;
6183 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6185 int texturesurfaceindex;
6188 if (!rsurface.lightmapcolor4f)
6190 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6192 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6193 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)
6195 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6196 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6197 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6201 rsurface.lightmapcolor4f = rsurface.array_color4f;
6202 rsurface.lightmapcolor4f_bufferobject = 0;
6203 rsurface.lightmapcolor4f_bufferoffset = 0;
6206 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6209 rsurface.lightmapcolor4f = NULL;
6210 rsurface.lightmapcolor4f_bufferobject = 0;
6211 rsurface.lightmapcolor4f_bufferoffset = 0;
6212 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6213 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6214 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6215 GL_Color(r, g, b, a);
6216 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6219 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6221 // TODO: optimize applyfog && applycolor case
6222 // just apply fog if necessary, and tint the fog color array if necessary
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_Simple(texturenumsurfaces, texturesurfacelist);
6233 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6235 int texturesurfaceindex;
6239 if (texturesurfacelist[0]->lightmapinfo)
6241 // generate color arrays for the surfaces in this list
6242 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6244 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6245 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6247 if (surface->lightmapinfo->samples)
6249 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6250 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6251 VectorScale(lm, scale, c);
6252 if (surface->lightmapinfo->styles[1] != 255)
6254 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6256 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6257 VectorMA(c, scale, lm, c);
6258 if (surface->lightmapinfo->styles[2] != 255)
6261 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6262 VectorMA(c, scale, lm, c);
6263 if (surface->lightmapinfo->styles[3] != 255)
6266 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6267 VectorMA(c, scale, lm, c);
6277 rsurface.lightmapcolor4f = rsurface.array_color4f;
6278 rsurface.lightmapcolor4f_bufferobject = 0;
6279 rsurface.lightmapcolor4f_bufferoffset = 0;
6283 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6284 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6285 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6287 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6288 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6289 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6290 GL_Color(r, g, b, a);
6291 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6294 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6296 int texturesurfaceindex;
6299 float *v, *c, *c2, alpha;
6300 vec3_t ambientcolor;
6301 vec3_t diffusecolor;
6305 VectorCopy(rsurface.modellight_lightdir, lightdir);
6306 f = 0.5f * r_refdef.lightmapintensity;
6307 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6308 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6309 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6310 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6311 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6312 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6314 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6316 // generate color arrays for the surfaces in this list
6317 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6319 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6320 int numverts = surface->num_vertices;
6321 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6322 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6323 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6324 // q3-style directional shading
6325 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6327 if ((f = DotProduct(c2, lightdir)) > 0)
6328 VectorMA(ambientcolor, f, diffusecolor, c);
6330 VectorCopy(ambientcolor, c);
6338 rsurface.lightmapcolor4f = rsurface.array_color4f;
6339 rsurface.lightmapcolor4f_bufferobject = 0;
6340 rsurface.lightmapcolor4f_bufferoffset = 0;
6341 *applycolor = false;
6345 *r = ambientcolor[0];
6346 *g = ambientcolor[1];
6347 *b = ambientcolor[2];
6348 rsurface.lightmapcolor4f = NULL;
6349 rsurface.lightmapcolor4f_bufferobject = 0;
6350 rsurface.lightmapcolor4f_bufferoffset = 0;
6354 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6356 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6357 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6358 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6359 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6360 GL_Color(r, g, b, a);
6361 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6364 void RSurf_SetupDepthAndCulling(void)
6366 // submodels are biased to avoid z-fighting with world surfaces that they
6367 // may be exactly overlapping (avoids z-fighting artifacts on certain
6368 // doors and things in Quake maps)
6369 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6370 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6371 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6372 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6375 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6377 // transparent sky would be ridiculous
6378 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6380 R_SetupGenericShader(false);
6383 skyrendernow = false;
6384 // we have to force off the water clipping plane while rendering sky
6388 // restore entity matrix
6389 R_Mesh_Matrix(&rsurface.matrix);
6391 RSurf_SetupDepthAndCulling();
6393 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6394 // skymasking on them, and Quake3 never did sky masking (unlike
6395 // software Quake and software Quake2), so disable the sky masking
6396 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6397 // and skymasking also looks very bad when noclipping outside the
6398 // level, so don't use it then either.
6399 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6401 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6402 R_Mesh_ColorPointer(NULL, 0, 0);
6403 R_Mesh_ResetTextureState();
6404 if (skyrendermasked)
6406 R_SetupDepthOrShadowShader();
6407 // depth-only (masking)
6408 GL_ColorMask(0,0,0,0);
6409 // just to make sure that braindead drivers don't draw
6410 // anything despite that colormask...
6411 GL_BlendFunc(GL_ZERO, GL_ONE);
6415 R_SetupGenericShader(false);
6417 GL_BlendFunc(GL_ONE, GL_ZERO);
6419 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6420 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6421 if (skyrendermasked)
6422 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6424 R_Mesh_ResetTextureState();
6425 GL_Color(1, 1, 1, 1);
6428 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6430 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6433 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6434 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6435 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6436 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6437 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6438 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6439 if (rsurface.texture->backgroundcurrentskinframe)
6441 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6442 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6443 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6444 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6446 if(rsurface.texture->colormapping)
6448 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6449 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6451 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6452 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6453 R_Mesh_ColorPointer(NULL, 0, 0);
6455 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6457 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6459 // render background
6460 GL_BlendFunc(GL_ONE, GL_ZERO);
6462 GL_AlphaTest(false);
6464 GL_Color(1, 1, 1, 1);
6465 R_Mesh_ColorPointer(NULL, 0, 0);
6467 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6468 if (r_glsl_permutation)
6470 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6471 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6472 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6473 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6474 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6475 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6476 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);
6478 GL_LockArrays(0, 0);
6480 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6481 GL_DepthMask(false);
6482 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6483 R_Mesh_ColorPointer(NULL, 0, 0);
6485 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6486 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6487 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6490 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6491 if (!r_glsl_permutation)
6494 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6495 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6496 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6497 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6498 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6499 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6501 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6503 GL_BlendFunc(GL_ONE, GL_ZERO);
6505 GL_AlphaTest(false);
6509 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6510 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6511 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6514 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6516 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6517 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);
6519 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6523 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6524 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);
6526 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6528 GL_LockArrays(0, 0);
6531 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6533 // OpenGL 1.3 path - anything not completely ancient
6534 int texturesurfaceindex;
6535 qboolean applycolor;
6539 const texturelayer_t *layer;
6540 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6542 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6545 int layertexrgbscale;
6546 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6548 if (layerindex == 0)
6552 GL_AlphaTest(false);
6553 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6556 GL_DepthMask(layer->depthmask && writedepth);
6557 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6558 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6560 layertexrgbscale = 4;
6561 VectorScale(layer->color, 0.25f, layercolor);
6563 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6565 layertexrgbscale = 2;
6566 VectorScale(layer->color, 0.5f, layercolor);
6570 layertexrgbscale = 1;
6571 VectorScale(layer->color, 1.0f, layercolor);
6573 layercolor[3] = layer->color[3];
6574 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6575 R_Mesh_ColorPointer(NULL, 0, 0);
6576 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6577 switch (layer->type)
6579 case TEXTURELAYERTYPE_LITTEXTURE:
6580 memset(&m, 0, sizeof(m));
6581 m.tex[0] = R_GetTexture(r_texture_white);
6582 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6583 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6584 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6585 m.tex[1] = R_GetTexture(layer->texture);
6586 m.texmatrix[1] = layer->texmatrix;
6587 m.texrgbscale[1] = layertexrgbscale;
6588 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6589 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6590 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6591 R_Mesh_TextureState(&m);
6592 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6593 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6594 else if (rsurface.uselightmaptexture)
6595 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6597 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6599 case TEXTURELAYERTYPE_TEXTURE:
6600 memset(&m, 0, sizeof(m));
6601 m.tex[0] = R_GetTexture(layer->texture);
6602 m.texmatrix[0] = layer->texmatrix;
6603 m.texrgbscale[0] = layertexrgbscale;
6604 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6605 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6606 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6607 R_Mesh_TextureState(&m);
6608 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6610 case TEXTURELAYERTYPE_FOG:
6611 memset(&m, 0, sizeof(m));
6612 m.texrgbscale[0] = layertexrgbscale;
6615 m.tex[0] = R_GetTexture(layer->texture);
6616 m.texmatrix[0] = layer->texmatrix;
6617 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6618 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6619 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6621 R_Mesh_TextureState(&m);
6622 // generate a color array for the fog pass
6623 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6624 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6628 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6629 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)
6631 f = 1 - FogPoint_Model(v);
6632 c[0] = layercolor[0];
6633 c[1] = layercolor[1];
6634 c[2] = layercolor[2];
6635 c[3] = f * layercolor[3];
6638 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6641 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6643 GL_LockArrays(0, 0);
6646 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6648 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6649 GL_AlphaTest(false);
6653 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6655 // OpenGL 1.1 - crusty old voodoo path
6656 int texturesurfaceindex;
6660 const texturelayer_t *layer;
6661 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6663 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6665 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6667 if (layerindex == 0)
6671 GL_AlphaTest(false);
6672 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6675 GL_DepthMask(layer->depthmask && writedepth);
6676 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6677 R_Mesh_ColorPointer(NULL, 0, 0);
6678 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6679 switch (layer->type)
6681 case TEXTURELAYERTYPE_LITTEXTURE:
6682 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6684 // two-pass lit texture with 2x rgbscale
6685 // first the lightmap pass
6686 memset(&m, 0, sizeof(m));
6687 m.tex[0] = R_GetTexture(r_texture_white);
6688 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6689 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6690 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6691 R_Mesh_TextureState(&m);
6692 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6693 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6694 else if (rsurface.uselightmaptexture)
6695 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6697 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6698 GL_LockArrays(0, 0);
6699 // then apply the texture to it
6700 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6701 memset(&m, 0, sizeof(m));
6702 m.tex[0] = R_GetTexture(layer->texture);
6703 m.texmatrix[0] = layer->texmatrix;
6704 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6705 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6706 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6707 R_Mesh_TextureState(&m);
6708 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);
6712 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6713 memset(&m, 0, sizeof(m));
6714 m.tex[0] = R_GetTexture(layer->texture);
6715 m.texmatrix[0] = layer->texmatrix;
6716 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6717 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6718 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6719 R_Mesh_TextureState(&m);
6720 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6721 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);
6723 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);
6726 case TEXTURELAYERTYPE_TEXTURE:
6727 // singletexture unlit texture with transparency support
6728 memset(&m, 0, sizeof(m));
6729 m.tex[0] = R_GetTexture(layer->texture);
6730 m.texmatrix[0] = layer->texmatrix;
6731 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6732 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6733 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6734 R_Mesh_TextureState(&m);
6735 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);
6737 case TEXTURELAYERTYPE_FOG:
6738 // singletexture fogging
6739 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
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);
6751 R_Mesh_ResetTextureState();
6752 // generate a color array for the fog pass
6753 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6757 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6758 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)
6760 f = 1 - FogPoint_Model(v);
6761 c[0] = layer->color[0];
6762 c[1] = layer->color[1];
6763 c[2] = layer->color[2];
6764 c[3] = f * layer->color[3];
6767 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6770 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6772 GL_LockArrays(0, 0);
6775 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6777 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6778 GL_AlphaTest(false);
6782 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6786 GL_AlphaTest(false);
6787 R_Mesh_ColorPointer(NULL, 0, 0);
6788 R_Mesh_ResetTextureState();
6789 R_SetupGenericShader(false);
6791 if(rsurface.texture && rsurface.texture->currentskinframe)
6793 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6794 c[3] *= rsurface.texture->currentalpha;
6804 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6806 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
6807 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
6808 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
6811 // brighten it up (as texture value 127 means "unlit")
6812 c[0] *= 2 * r_refdef.view.colorscale;
6813 c[1] *= 2 * r_refdef.view.colorscale;
6814 c[2] *= 2 * r_refdef.view.colorscale;
6816 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6817 c[3] *= r_wateralpha.value;
6819 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6821 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6822 GL_DepthMask(false);
6824 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6826 GL_BlendFunc(GL_ONE, GL_ONE);
6827 GL_DepthMask(false);
6829 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6831 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6832 GL_DepthMask(false);
6834 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6836 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6837 GL_DepthMask(false);
6841 GL_BlendFunc(GL_ONE, GL_ZERO);
6842 GL_DepthMask(writedepth);
6845 rsurface.lightmapcolor4f = NULL;
6847 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6849 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6851 rsurface.lightmapcolor4f = NULL;
6852 rsurface.lightmapcolor4f_bufferobject = 0;
6853 rsurface.lightmapcolor4f_bufferoffset = 0;
6855 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6857 qboolean applycolor = true;
6860 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6862 r_refdef.lightmapintensity = 1;
6863 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6864 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6868 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6870 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6871 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6872 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6875 if(!rsurface.lightmapcolor4f)
6876 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6878 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6879 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6880 if(r_refdef.fogenabled)
6881 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6883 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6884 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6887 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6890 RSurf_SetupDepthAndCulling();
6891 if (r_showsurfaces.integer == 3)
6892 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6893 else if (r_glsl.integer && gl_support_fragment_shader)
6894 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6895 else if (gl_combine.integer && r_textureunits.integer >= 2)
6896 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6898 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6902 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6905 RSurf_SetupDepthAndCulling();
6906 if (r_showsurfaces.integer == 3)
6907 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6908 else if (r_glsl.integer && gl_support_fragment_shader)
6909 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6910 else if (gl_combine.integer && r_textureunits.integer >= 2)
6911 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6913 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6917 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6920 int texturenumsurfaces, endsurface;
6922 msurface_t *surface;
6923 msurface_t *texturesurfacelist[1024];
6925 // if the model is static it doesn't matter what value we give for
6926 // wantnormals and wanttangents, so this logic uses only rules applicable
6927 // to a model, knowing that they are meaningless otherwise
6928 if (ent == r_refdef.scene.worldentity)
6929 RSurf_ActiveWorldEntity();
6930 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6931 RSurf_ActiveModelEntity(ent, false, false);
6933 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6935 for (i = 0;i < numsurfaces;i = j)
6938 surface = rsurface.modelsurfaces + surfacelist[i];
6939 texture = surface->texture;
6940 rsurface.texture = R_GetCurrentTexture(texture);
6941 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6942 // scan ahead until we find a different texture
6943 endsurface = min(i + 1024, numsurfaces);
6944 texturenumsurfaces = 0;
6945 texturesurfacelist[texturenumsurfaces++] = surface;
6946 for (;j < endsurface;j++)
6948 surface = rsurface.modelsurfaces + surfacelist[j];
6949 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6951 texturesurfacelist[texturenumsurfaces++] = surface;
6953 // render the range of surfaces
6954 if (ent == r_refdef.scene.worldentity)
6955 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6957 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6959 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6960 GL_AlphaTest(false);
6963 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6965 const entity_render_t *queueentity = r_refdef.scene.worldentity;
6969 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6971 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6973 RSurf_SetupDepthAndCulling();
6974 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6975 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6977 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6979 RSurf_SetupDepthAndCulling();
6980 GL_AlphaTest(false);
6981 R_Mesh_ColorPointer(NULL, 0, 0);
6982 R_Mesh_ResetTextureState();
6983 R_SetupGenericShader(false);
6984 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6986 GL_BlendFunc(GL_ONE, GL_ZERO);
6987 GL_Color(0, 0, 0, 1);
6988 GL_DepthTest(writedepth);
6989 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6991 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
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);
7002 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7004 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7005 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7006 else if (!rsurface.texture->currentnumlayers)
7008 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7010 // transparent surfaces get pushed off into the transparent queue
7011 int surfacelistindex;
7012 const msurface_t *surface;
7013 vec3_t tempcenter, center;
7014 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7016 surface = texturesurfacelist[surfacelistindex];
7017 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7018 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7019 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7020 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7021 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7026 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7027 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7032 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7036 // break the surface list down into batches by texture and use of lightmapping
7037 for (i = 0;i < numsurfaces;i = j)
7040 // texture is the base texture pointer, rsurface.texture is the
7041 // current frame/skin the texture is directing us to use (for example
7042 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7043 // use skin 1 instead)
7044 texture = surfacelist[i]->texture;
7045 rsurface.texture = R_GetCurrentTexture(texture);
7046 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7047 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7049 // if this texture is not the kind we want, skip ahead to the next one
7050 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7054 // simply scan ahead until we find a different texture or lightmap state
7055 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7057 // render the range of surfaces
7058 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7062 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7067 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7069 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7071 RSurf_SetupDepthAndCulling();
7072 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7073 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7075 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7077 RSurf_SetupDepthAndCulling();
7078 GL_AlphaTest(false);
7079 R_Mesh_ColorPointer(NULL, 0, 0);
7080 R_Mesh_ResetTextureState();
7081 R_SetupGenericShader(false);
7082 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7084 GL_BlendFunc(GL_ONE, GL_ZERO);
7085 GL_Color(0, 0, 0, 1);
7086 GL_DepthTest(writedepth);
7087 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7089 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
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);
7100 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7102 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7103 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7104 else if (!rsurface.texture->currentnumlayers)
7106 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7108 // transparent surfaces get pushed off into the transparent queue
7109 int surfacelistindex;
7110 const msurface_t *surface;
7111 vec3_t tempcenter, center;
7112 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7114 surface = texturesurfacelist[surfacelistindex];
7115 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7116 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7117 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7118 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7119 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7124 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7125 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7130 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7134 // break the surface list down into batches by texture and use of lightmapping
7135 for (i = 0;i < numsurfaces;i = j)
7138 // texture is the base texture pointer, rsurface.texture is the
7139 // current frame/skin the texture is directing us to use (for example
7140 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7141 // use skin 1 instead)
7142 texture = surfacelist[i]->texture;
7143 rsurface.texture = R_GetCurrentTexture(texture);
7144 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7145 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7147 // if this texture is not the kind we want, skip ahead to the next one
7148 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7152 // simply scan ahead until we find a different texture or lightmap state
7153 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7155 // render the range of surfaces
7156 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7160 float locboxvertex3f[6*4*3] =
7162 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7163 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7164 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7165 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7166 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7167 1,0,0, 0,0,0, 0,1,0, 1,1,0
7170 unsigned short locboxelements[6*2*3] =
7180 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7183 cl_locnode_t *loc = (cl_locnode_t *)ent;
7185 float vertex3f[6*4*3];
7187 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7188 GL_DepthMask(false);
7189 GL_DepthRange(0, 1);
7190 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7192 GL_CullFace(GL_NONE);
7193 R_Mesh_Matrix(&identitymatrix);
7195 R_Mesh_VertexPointer(vertex3f, 0, 0);
7196 R_Mesh_ColorPointer(NULL, 0, 0);
7197 R_Mesh_ResetTextureState();
7198 R_SetupGenericShader(false);
7201 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7202 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7203 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7204 surfacelist[0] < 0 ? 0.5f : 0.125f);
7206 if (VectorCompare(loc->mins, loc->maxs))
7208 VectorSet(size, 2, 2, 2);
7209 VectorMA(loc->mins, -0.5f, size, mins);
7213 VectorCopy(loc->mins, mins);
7214 VectorSubtract(loc->maxs, loc->mins, size);
7217 for (i = 0;i < 6*4*3;)
7218 for (j = 0;j < 3;j++, i++)
7219 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7221 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7224 void R_DrawLocs(void)
7227 cl_locnode_t *loc, *nearestloc;
7229 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7230 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7232 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7233 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7237 void R_DrawDebugModel(entity_render_t *ent)
7239 int i, j, k, l, flagsmask;
7240 const int *elements;
7242 msurface_t *surface;
7243 dp_model_t *model = ent->model;
7246 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7248 R_Mesh_ColorPointer(NULL, 0, 0);
7249 R_Mesh_ResetTextureState();
7250 R_SetupGenericShader(false);
7251 GL_DepthRange(0, 1);
7252 GL_DepthTest(!r_showdisabledepthtest.integer);
7253 GL_DepthMask(false);
7254 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7256 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7258 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7259 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7261 if (brush->colbrushf && brush->colbrushf->numtriangles)
7263 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7264 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);
7265 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7268 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7270 if (surface->num_collisiontriangles)
7272 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7273 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);
7274 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7279 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7281 if (r_showtris.integer || r_shownormals.integer)
7283 if (r_showdisabledepthtest.integer)
7285 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7286 GL_DepthMask(false);
7290 GL_BlendFunc(GL_ONE, GL_ZERO);
7293 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7295 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7297 rsurface.texture = R_GetCurrentTexture(surface->texture);
7298 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7300 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7301 if (r_showtris.value > 0)
7303 if (!rsurface.texture->currentlayers->depthmask)
7304 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7305 else if (ent == r_refdef.scene.worldentity)
7306 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7308 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7309 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7310 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7311 R_Mesh_ColorPointer(NULL, 0, 0);
7312 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7313 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7314 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7315 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);
7316 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7319 if (r_shownormals.value < 0)
7322 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7324 VectorCopy(rsurface.vertex3f + l * 3, v);
7325 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7326 qglVertex3f(v[0], v[1], v[2]);
7327 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7328 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7329 qglVertex3f(v[0], v[1], v[2]);
7334 if (r_shownormals.value > 0)
7337 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7339 VectorCopy(rsurface.vertex3f + l * 3, v);
7340 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7341 qglVertex3f(v[0], v[1], v[2]);
7342 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7343 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7344 qglVertex3f(v[0], v[1], v[2]);
7349 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7351 VectorCopy(rsurface.vertex3f + l * 3, v);
7352 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7353 qglVertex3f(v[0], v[1], v[2]);
7354 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7355 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7356 qglVertex3f(v[0], v[1], v[2]);
7361 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7363 VectorCopy(rsurface.vertex3f + l * 3, v);
7364 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7365 qglVertex3f(v[0], v[1], v[2]);
7366 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7367 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7368 qglVertex3f(v[0], v[1], v[2]);
7375 rsurface.texture = NULL;
7379 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7380 int r_maxsurfacelist = 0;
7381 msurface_t **r_surfacelist = NULL;
7382 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7384 int i, j, endj, f, flagsmask;
7386 dp_model_t *model = r_refdef.scene.worldmodel;
7387 msurface_t *surfaces;
7388 unsigned char *update;
7389 int numsurfacelist = 0;
7393 if (r_maxsurfacelist < model->num_surfaces)
7395 r_maxsurfacelist = model->num_surfaces;
7397 Mem_Free(r_surfacelist);
7398 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7401 RSurf_ActiveWorldEntity();
7403 surfaces = model->data_surfaces;
7404 update = model->brushq1.lightmapupdateflags;
7406 // update light styles on this submodel
7407 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7409 model_brush_lightstyleinfo_t *style;
7410 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7412 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7414 int *list = style->surfacelist;
7415 style->value = r_refdef.scene.lightstylevalue[style->style];
7416 for (j = 0;j < style->numsurfaces;j++)
7417 update[list[j]] = true;
7422 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7426 R_DrawDebugModel(r_refdef.scene.worldentity);
7427 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7433 rsurface.uselightmaptexture = false;
7434 rsurface.texture = NULL;
7435 rsurface.rtlight = NULL;
7437 // add visible surfaces to draw list
7438 for (i = 0;i < model->nummodelsurfaces;i++)
7440 j = model->sortedmodelsurfaces[i];
7441 if (r_refdef.viewcache.world_surfacevisible[j])
7442 r_surfacelist[numsurfacelist++] = surfaces + j;
7444 // update lightmaps if needed
7446 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7447 if (r_refdef.viewcache.world_surfacevisible[j])
7449 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7450 // don't do anything if there were no surfaces
7451 if (!numsurfacelist)
7453 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7456 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7457 GL_AlphaTest(false);
7459 // add to stats if desired
7460 if (r_speeds.integer && !skysurfaces && !depthonly)
7462 r_refdef.stats.world_surfaces += numsurfacelist;
7463 for (j = 0;j < numsurfacelist;j++)
7464 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7466 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7469 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7471 int i, j, endj, f, flagsmask;
7473 dp_model_t *model = ent->model;
7474 msurface_t *surfaces;
7475 unsigned char *update;
7476 int numsurfacelist = 0;
7480 if (r_maxsurfacelist < model->num_surfaces)
7482 r_maxsurfacelist = model->num_surfaces;
7484 Mem_Free(r_surfacelist);
7485 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7488 // if the model is static it doesn't matter what value we give for
7489 // wantnormals and wanttangents, so this logic uses only rules applicable
7490 // to a model, knowing that they are meaningless otherwise
7491 if (ent == r_refdef.scene.worldentity)
7492 RSurf_ActiveWorldEntity();
7493 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
7494 RSurf_ActiveModelEntity(ent, false, false);
7496 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7498 surfaces = model->data_surfaces;
7499 update = model->brushq1.lightmapupdateflags;
7501 // update light styles
7502 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7504 model_brush_lightstyleinfo_t *style;
7505 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7507 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7509 int *list = style->surfacelist;
7510 style->value = r_refdef.scene.lightstylevalue[style->style];
7511 for (j = 0;j < style->numsurfaces;j++)
7512 update[list[j]] = true;
7517 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7521 R_DrawDebugModel(ent);
7522 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7528 rsurface.uselightmaptexture = false;
7529 rsurface.texture = NULL;
7530 rsurface.rtlight = NULL;
7532 // add visible surfaces to draw list
7533 for (i = 0;i < model->nummodelsurfaces;i++)
7534 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7535 // don't do anything if there were no surfaces
7536 if (!numsurfacelist)
7538 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7541 // update lightmaps if needed
7543 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7545 R_BuildLightMap(ent, surfaces + j);
7546 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7547 GL_AlphaTest(false);
7549 // add to stats if desired
7550 if (r_speeds.integer && !skysurfaces && !depthonly)
7552 r_refdef.stats.entities_surfaces += numsurfacelist;
7553 for (j = 0;j < numsurfacelist;j++)
7554 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7556 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity