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 frame-by-frame alpha control {0 to 1} - 0.7 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage; requires r_motionblur to have a value"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "velocity at which there is minimum blur"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "velocity at which there is full blur"};
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_vtime = {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 the alpha level of the motion blur variable"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.01", "randomizing coefficient to fix ghosting"};
46 cvar_t r_motionblur_debug = {0, "r_motionblur_debug", "0", "outputs current motionblur alpha value"};
48 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"};
49 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
50 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
51 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
52 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)"};
53 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
54 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
55 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"};
56 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"};
57 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
58 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"};
59 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"};
60 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"};
61 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
62 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
63 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
64 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
65 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
66 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
67 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
68 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
69 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
70 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
71 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
72 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
73 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"};
74 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
75 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
76 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"};
77 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"};
78 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
79 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
81 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
82 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
83 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
84 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
85 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
86 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
87 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
88 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
90 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)"};
92 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
93 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)"};
94 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)"};
95 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
96 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
97 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
98 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
99 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)"};
100 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)"};
101 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)"};
102 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)"};
103 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)"};
105 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)"};
106 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
107 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"};
108 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
109 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
111 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
112 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
113 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
114 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
116 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
117 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
118 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
119 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
120 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
121 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
122 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
124 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
125 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
126 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
127 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)"};
129 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"};
131 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"};
133 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
135 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
136 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
137 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"};
138 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
139 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
140 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
141 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
143 extern cvar_t v_glslgamma;
145 extern qboolean v_flipped_state;
147 static struct r_bloomstate_s
152 int bloomwidth, bloomheight;
154 int screentexturewidth, screentextureheight;
155 rtexture_t *texture_screen; // also used for motion blur if enabled!
157 int bloomtexturewidth, bloomtextureheight;
158 rtexture_t *texture_bloom;
160 // arrays for rendering the screen passes
161 float screentexcoord2f[8];
162 float bloomtexcoord2f[8];
163 float offsettexcoord2f[8];
167 r_waterstate_t r_waterstate;
169 // shadow volume bsp struct with automatically growing nodes buffer
172 rtexture_t *r_texture_blanknormalmap;
173 rtexture_t *r_texture_white;
174 rtexture_t *r_texture_grey128;
175 rtexture_t *r_texture_black;
176 rtexture_t *r_texture_notexture;
177 rtexture_t *r_texture_whitecube;
178 rtexture_t *r_texture_normalizationcube;
179 rtexture_t *r_texture_fogattenuation;
180 rtexture_t *r_texture_gammaramps;
181 unsigned int r_texture_gammaramps_serial;
182 //rtexture_t *r_texture_fogintensity;
184 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
185 unsigned int r_numqueries;
186 unsigned int r_maxqueries;
188 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
189 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
191 // vertex coordinates for a quad that covers the screen exactly
192 const static float r_screenvertex3f[12] =
200 extern void R_DrawModelShadows(void);
202 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
205 for (i = 0;i < verts;i++)
216 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
219 for (i = 0;i < verts;i++)
229 // FIXME: move this to client?
232 if (gamemode == GAME_NEHAHRA)
234 Cvar_Set("gl_fogenable", "0");
235 Cvar_Set("gl_fogdensity", "0.2");
236 Cvar_Set("gl_fogred", "0.3");
237 Cvar_Set("gl_foggreen", "0.3");
238 Cvar_Set("gl_fogblue", "0.3");
240 r_refdef.fog_density = 0;
241 r_refdef.fog_red = 0;
242 r_refdef.fog_green = 0;
243 r_refdef.fog_blue = 0;
244 r_refdef.fog_alpha = 1;
245 r_refdef.fog_start = 0;
246 r_refdef.fog_end = 0;
249 float FogForDistance(vec_t dist)
251 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
252 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
255 float FogPoint_World(const vec3_t p)
257 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
260 float FogPoint_Model(const vec3_t p)
262 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
265 static void R_BuildBlankTextures(void)
267 unsigned char data[4];
268 data[2] = 128; // normal X
269 data[1] = 128; // normal Y
270 data[0] = 255; // normal Z
271 data[3] = 128; // height
272 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
277 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
282 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
287 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
290 static void R_BuildNoTexture(void)
293 unsigned char pix[16][16][4];
294 // this makes a light grey/dark grey checkerboard texture
295 for (y = 0;y < 16;y++)
297 for (x = 0;x < 16;x++)
299 if ((y < 8) ^ (x < 8))
315 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
318 static void R_BuildWhiteCube(void)
320 unsigned char data[6*1*1*4];
321 memset(data, 255, sizeof(data));
322 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
325 static void R_BuildNormalizationCube(void)
329 vec_t s, t, intensity;
331 unsigned char data[6][NORMSIZE][NORMSIZE][4];
332 for (side = 0;side < 6;side++)
334 for (y = 0;y < NORMSIZE;y++)
336 for (x = 0;x < NORMSIZE;x++)
338 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
339 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
374 intensity = 127.0f / sqrt(DotProduct(v, v));
375 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
376 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
377 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
378 data[side][y][x][3] = 255;
382 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
385 static void R_BuildFogTexture(void)
389 unsigned char data1[FOGWIDTH][4];
390 //unsigned char data2[FOGWIDTH][4];
393 r_refdef.fogmasktable_start = r_refdef.fog_start;
394 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
395 r_refdef.fogmasktable_range = r_refdef.fogrange;
396 r_refdef.fogmasktable_density = r_refdef.fog_density;
398 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
399 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
401 d = (x * r - r_refdef.fogmasktable_start);
402 if(developer.integer >= 100)
403 Con_Printf("%f ", d);
405 if (r_fog_exp2.integer)
406 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
408 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
409 if(developer.integer >= 100)
410 Con_Printf(" : %f ", alpha);
411 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
412 if(developer.integer >= 100)
413 Con_Printf(" = %f\n", alpha);
414 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
417 for (x = 0;x < FOGWIDTH;x++)
419 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
424 //data2[x][0] = 255 - b;
425 //data2[x][1] = 255 - b;
426 //data2[x][2] = 255 - b;
429 if (r_texture_fogattenuation)
431 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
432 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
436 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);
437 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
441 static const char *builtinshaderstring =
442 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
443 "// written by Forest 'LordHavoc' Hale\n"
445 "// common definitions between vertex shader and fragment shader:\n"
447 "//#ifdef __GLSL_CG_DATA_TYPES\n"
448 "//# define myhalf half\n"
449 "//# define myhalf2 half2\n"
450 "//# define myhalf3 half3\n"
451 "//# define myhalf4 half4\n"
453 "# define myhalf float\n"
454 "# define myhalf2 vec2\n"
455 "# define myhalf3 vec3\n"
456 "# define myhalf4 vec4\n"
459 "#ifdef MODE_DEPTH_OR_SHADOW\n"
461 "# ifdef VERTEX_SHADER\n"
464 " gl_Position = ftransform();\n"
470 "#ifdef MODE_POSTPROCESS\n"
471 "# ifdef VERTEX_SHADER\n"
474 " gl_FrontColor = gl_Color;\n"
475 " gl_Position = ftransform();\n"
476 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
478 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
482 "# ifdef FRAGMENT_SHADER\n"
484 "uniform sampler2D Texture_First;\n"
486 "uniform sampler2D Texture_Second;\n"
488 "#ifdef USEGAMMARAMPS\n"
489 "uniform sampler2D Texture_GammaRamps;\n"
491 "#ifdef USESATURATION\n"
492 "uniform float Saturation;\n"
494 "#ifdef USEVERTEXTEXTUREBLEND\n"
495 "uniform vec4 TintColor;\n"
497 "#ifdef USECOLORMOD\n"
498 "uniform vec3 Gamma;\n"
500 "//uncomment these if you want to use them:\n"
501 "uniform vec4 UserVec1;\n"
502 "// uniform vec4 UserVec2;\n"
503 "// uniform vec4 UserVec3;\n"
504 "// uniform vec4 UserVec4;\n"
505 "// uniform float ClientTime;\n"
506 "uniform vec2 PixelSize;\n"
509 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
511 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
513 "#ifdef USEVERTEXTEXTUREBLEND\n"
514 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
517 "#ifdef USEPOSTPROCESSING\n"
518 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
519 "// 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"
520 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
521 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
522 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
523 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
524 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
525 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
528 "#ifdef USESATURATION\n"
529 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
530 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
531 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
532 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" // TODO: test this on ATI
535 "#ifdef USEGAMMARAMPS\n"
536 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
537 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
538 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
545 "#ifdef MODE_GENERIC\n"
546 "# ifdef VERTEX_SHADER\n"
549 " gl_FrontColor = gl_Color;\n"
550 "# ifdef USEDIFFUSE\n"
551 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
553 "# ifdef USESPECULAR\n"
554 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
556 " gl_Position = ftransform();\n"
559 "# ifdef FRAGMENT_SHADER\n"
561 "# ifdef USEDIFFUSE\n"
562 "uniform sampler2D Texture_First;\n"
564 "# ifdef USESPECULAR\n"
565 "uniform sampler2D Texture_Second;\n"
570 " gl_FragColor = gl_Color;\n"
571 "# ifdef USEDIFFUSE\n"
572 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
575 "# ifdef USESPECULAR\n"
576 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
578 "# ifdef USECOLORMAPPING\n"
579 " gl_FragColor *= tex2;\n"
582 " gl_FragColor += tex2;\n"
584 "# ifdef USEVERTEXTEXTUREBLEND\n"
585 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
590 "#else // !MODE_GENERIC\n"
592 "varying vec2 TexCoord;\n"
593 "varying vec2 TexCoordLightmap;\n"
595 "#ifdef MODE_LIGHTSOURCE\n"
596 "varying vec3 CubeVector;\n"
599 "#ifdef MODE_LIGHTSOURCE\n"
600 "varying vec3 LightVector;\n"
602 "#ifdef MODE_LIGHTDIRECTION\n"
603 "varying vec3 LightVector;\n"
606 "varying vec3 EyeVector;\n"
608 "varying vec3 EyeVectorModelSpace;\n"
611 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
612 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
613 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
615 "#ifdef MODE_WATER\n"
616 "varying vec4 ModelViewProjectionPosition;\n"
618 "#ifdef MODE_REFRACTION\n"
619 "varying vec4 ModelViewProjectionPosition;\n"
621 "#ifdef USEREFLECTION\n"
622 "varying vec4 ModelViewProjectionPosition;\n"
629 "// vertex shader specific:\n"
630 "#ifdef VERTEX_SHADER\n"
632 "uniform vec3 LightPosition;\n"
633 "uniform vec3 EyePosition;\n"
634 "uniform vec3 LightDir;\n"
636 "// 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"
640 " gl_FrontColor = gl_Color;\n"
641 " // copy the surface texcoord\n"
642 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
643 "#ifndef MODE_LIGHTSOURCE\n"
644 "# ifndef MODE_LIGHTDIRECTION\n"
645 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
649 "#ifdef MODE_LIGHTSOURCE\n"
650 " // transform vertex position into light attenuation/cubemap space\n"
651 " // (-1 to +1 across the light box)\n"
652 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
654 " // transform unnormalized light direction into tangent space\n"
655 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
656 " // normalize it per pixel)\n"
657 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
658 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
659 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
660 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
663 "#ifdef MODE_LIGHTDIRECTION\n"
664 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
665 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
666 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
669 " // transform unnormalized eye direction into tangent space\n"
671 " vec3 EyeVectorModelSpace;\n"
673 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
674 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
675 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
676 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
678 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
679 " VectorS = gl_MultiTexCoord1.xyz;\n"
680 " VectorT = gl_MultiTexCoord2.xyz;\n"
681 " VectorR = gl_MultiTexCoord3.xyz;\n"
684 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
685 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
686 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
687 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
690 "// transform vertex to camera space, using ftransform to match non-VS\n"
692 " gl_Position = ftransform();\n"
694 "#ifdef MODE_WATER\n"
695 " ModelViewProjectionPosition = gl_Position;\n"
697 "#ifdef MODE_REFRACTION\n"
698 " ModelViewProjectionPosition = gl_Position;\n"
700 "#ifdef USEREFLECTION\n"
701 " ModelViewProjectionPosition = gl_Position;\n"
705 "#endif // VERTEX_SHADER\n"
710 "// fragment shader specific:\n"
711 "#ifdef FRAGMENT_SHADER\n"
713 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
714 "uniform sampler2D Texture_Normal;\n"
715 "uniform sampler2D Texture_Color;\n"
716 "uniform sampler2D Texture_Gloss;\n"
717 "uniform sampler2D Texture_Glow;\n"
718 "uniform sampler2D Texture_SecondaryNormal;\n"
719 "uniform sampler2D Texture_SecondaryColor;\n"
720 "uniform sampler2D Texture_SecondaryGloss;\n"
721 "uniform sampler2D Texture_SecondaryGlow;\n"
722 "uniform sampler2D Texture_Pants;\n"
723 "uniform sampler2D Texture_Shirt;\n"
724 "uniform sampler2D Texture_FogMask;\n"
725 "uniform sampler2D Texture_Lightmap;\n"
726 "uniform sampler2D Texture_Deluxemap;\n"
727 "uniform sampler2D Texture_Refraction;\n"
728 "uniform sampler2D Texture_Reflection;\n"
729 "uniform sampler2D Texture_Attenuation;\n"
730 "uniform samplerCube Texture_Cube;\n"
732 "uniform myhalf3 LightColor;\n"
733 "uniform myhalf3 AmbientColor;\n"
734 "uniform myhalf3 DiffuseColor;\n"
735 "uniform myhalf3 SpecularColor;\n"
736 "uniform myhalf3 Color_Pants;\n"
737 "uniform myhalf3 Color_Shirt;\n"
738 "uniform myhalf3 FogColor;\n"
740 "uniform myhalf4 TintColor;\n"
743 "//#ifdef MODE_WATER\n"
744 "uniform vec4 DistortScaleRefractReflect;\n"
745 "uniform vec4 ScreenScaleRefractReflect;\n"
746 "uniform vec4 ScreenCenterRefractReflect;\n"
747 "uniform myhalf4 RefractColor;\n"
748 "uniform myhalf4 ReflectColor;\n"
749 "uniform myhalf ReflectFactor;\n"
750 "uniform myhalf ReflectOffset;\n"
752 "//# ifdef MODE_REFRACTION\n"
753 "//uniform vec4 DistortScaleRefractReflect;\n"
754 "//uniform vec4 ScreenScaleRefractReflect;\n"
755 "//uniform vec4 ScreenCenterRefractReflect;\n"
756 "//uniform myhalf4 RefractColor;\n"
757 "//# ifdef USEREFLECTION\n"
758 "//uniform myhalf4 ReflectColor;\n"
761 "//# ifdef USEREFLECTION\n"
762 "//uniform vec4 DistortScaleRefractReflect;\n"
763 "//uniform vec4 ScreenScaleRefractReflect;\n"
764 "//uniform vec4 ScreenCenterRefractReflect;\n"
765 "//uniform myhalf4 ReflectColor;\n"
770 "uniform myhalf GlowScale;\n"
771 "uniform myhalf SceneBrightness;\n"
772 "#ifdef USECONTRASTBOOST\n"
773 "uniform myhalf ContrastBoostCoeff;\n"
776 "uniform float OffsetMapping_Scale;\n"
777 "uniform float OffsetMapping_Bias;\n"
778 "uniform float FogRangeRecip;\n"
780 "uniform myhalf AmbientScale;\n"
781 "uniform myhalf DiffuseScale;\n"
782 "uniform myhalf SpecularScale;\n"
783 "uniform myhalf SpecularPower;\n"
785 "#ifdef USEOFFSETMAPPING\n"
786 "vec2 OffsetMapping(vec2 TexCoord)\n"
788 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
789 " // 14 sample relief mapping: linear search and then binary search\n"
790 " // this basically steps forward a small amount repeatedly until it finds\n"
791 " // itself inside solid, then jitters forward and back using decreasing\n"
792 " // amounts to find the impact\n"
793 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
794 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
795 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
796 " vec3 RT = vec3(TexCoord, 1);\n"
797 " OffsetVector *= 0.1;\n"
798 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
799 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
800 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
801 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
802 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
803 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
804 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
805 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
808 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
809 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
810 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
811 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
814 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
815 " // this basically moves forward the full distance, and then backs up based\n"
816 " // on height of samples\n"
817 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
818 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
819 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
820 " TexCoord += OffsetVector;\n"
821 " OffsetVector *= 0.333;\n"
822 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
823 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
824 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
825 " return TexCoord;\n"
828 "#endif // USEOFFSETMAPPING\n"
830 "#ifdef MODE_WATER\n"
835 "#ifdef USEOFFSETMAPPING\n"
836 " // apply offsetmapping\n"
837 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
838 "#define TexCoord TexCoordOffset\n"
841 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
842 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
843 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
844 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
845 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
848 "#else // !MODE_WATER\n"
849 "#ifdef MODE_REFRACTION\n"
851 "// refraction pass\n"
854 "#ifdef USEOFFSETMAPPING\n"
855 " // apply offsetmapping\n"
856 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
857 "#define TexCoord TexCoordOffset\n"
860 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
861 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
862 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
863 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
866 "#else // !MODE_REFRACTION\n"
869 "#ifdef USEOFFSETMAPPING\n"
870 " // apply offsetmapping\n"
871 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
872 "#define TexCoord TexCoordOffset\n"
875 " // combine the diffuse textures (base, pants, shirt)\n"
876 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
877 "#ifdef USECOLORMAPPING\n"
878 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
880 "#ifdef USEVERTEXTEXTUREBLEND\n"
881 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
882 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
883 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
884 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord)), color.rgb, terrainblend);\n"
886 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
889 "#ifdef USEDIFFUSE\n"
890 " // get the surface normal and the gloss color\n"
891 "# ifdef USEVERTEXTEXTUREBLEND\n"
892 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
893 "# ifdef USESPECULAR\n"
894 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
897 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
898 "# ifdef USESPECULAR\n"
899 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
906 "#ifdef MODE_LIGHTSOURCE\n"
909 " // calculate surface normal, light normal, and specular normal\n"
910 " // compute color intensity for the two textures (colormap and glossmap)\n"
911 " // scale by light color and attenuation as efficiently as possible\n"
912 " // (do as much scalar math as possible rather than vector math)\n"
913 "# ifdef USEDIFFUSE\n"
914 " // get the light normal\n"
915 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
917 "# ifdef USESPECULAR\n"
918 "# ifndef USEEXACTSPECULARMATH\n"
919 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
922 " // calculate directional shading\n"
923 "# ifdef USEEXACTSPECULARMATH\n"
924 " 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"
926 " 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"
929 "# ifdef USEDIFFUSE\n"
930 " // calculate directional shading\n"
931 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
933 " // calculate directionless shading\n"
934 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
938 "# ifdef USECUBEFILTER\n"
939 " // apply light cubemap filter\n"
940 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
941 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
943 "#endif // MODE_LIGHTSOURCE\n"
948 "#ifdef MODE_LIGHTDIRECTION\n"
949 " // directional model lighting\n"
950 "# ifdef USEDIFFUSE\n"
951 " // get the light normal\n"
952 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
954 "# ifdef USESPECULAR\n"
955 " // calculate directional shading\n"
956 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
957 "# ifdef USEEXACTSPECULARMATH\n"
958 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
960 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
961 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
964 "# ifdef USEDIFFUSE\n"
966 " // calculate directional shading\n"
967 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
969 " color.rgb *= AmbientColor;\n"
972 "#endif // MODE_LIGHTDIRECTION\n"
977 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
978 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
980 " // get the light normal\n"
981 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
982 " myhalf3 diffusenormal;\n"
983 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
984 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
985 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
986 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
987 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
988 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
989 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
990 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
991 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
992 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
993 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
994 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
995 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
996 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
997 "# ifdef USESPECULAR\n"
998 "# ifdef USEEXACTSPECULARMATH\n"
999 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1001 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1002 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1006 " // apply lightmap color\n"
1007 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1008 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1013 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1014 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1016 " // get the light normal\n"
1017 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1018 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1019 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1020 "# ifdef USESPECULAR\n"
1021 "# ifdef USEEXACTSPECULARMATH\n"
1022 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1024 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1025 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1029 " // apply lightmap color\n"
1030 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1031 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1036 "#ifdef MODE_LIGHTMAP\n"
1037 " // apply lightmap color\n"
1038 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1039 "#endif // MODE_LIGHTMAP\n"
1044 "#ifdef MODE_VERTEXCOLOR\n"
1045 " // apply lightmap color\n"
1046 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1047 "#endif // MODE_VERTEXCOLOR\n"
1052 "#ifdef MODE_FLATCOLOR\n"
1053 "#endif // MODE_FLATCOLOR\n"
1061 " color *= TintColor;\n"
1064 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1067 "#ifdef USECONTRASTBOOST\n"
1068 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1071 " color.rgb *= SceneBrightness;\n"
1073 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1075 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1078 " // 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"
1079 "#ifdef USEREFLECTION\n"
1080 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1081 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1082 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1083 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1086 " gl_FragColor = vec4(color);\n"
1088 "#endif // !MODE_REFRACTION\n"
1089 "#endif // !MODE_WATER\n"
1091 "#endif // FRAGMENT_SHADER\n"
1093 "#endif // !MODE_GENERIC\n"
1094 "#endif // !MODE_POSTPROCESS\n"
1095 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1098 typedef struct shaderpermutationinfo_s
1100 const char *pretext;
1103 shaderpermutationinfo_t;
1105 typedef struct shadermodeinfo_s
1107 const char *vertexfilename;
1108 const char *geometryfilename;
1109 const char *fragmentfilename;
1110 const char *pretext;
1115 typedef enum shaderpermutation_e
1117 SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
1118 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1119 SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
1120 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1121 SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
1122 SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
1123 SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
1124 SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
1125 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, // (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1126 SHADERPERMUTATION_REFLECTION = 1<<9, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1127 SHADERPERMUTATION_OFFSETMAPPING = 1<<10, // adjust texcoords to roughly simulate a displacement mapped surface
1128 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1129 SHADERPERMUTATION_GAMMARAMPS = 1<<12, // gamma (postprocessing only)
1130 SHADERPERMUTATION_POSTPROCESSING = 1<<13, // user defined postprocessing
1131 SHADERPERMUTATION_SATURATION = 1<<14, // user defined postprocessing
1132 SHADERPERMUTATION_LIMIT = 1<<15, // size of permutations array
1133 SHADERPERMUTATION_COUNT = 15 // size of shaderpermutationinfo array
1135 shaderpermutation_t;
1137 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1138 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1140 {"#define USEDIFFUSE\n", " diffuse"},
1141 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1142 {"#define USECOLORMAPPING\n", " colormapping"},
1143 {"#define USECONTRASTBOOST\n", " contrastboost"},
1144 {"#define USEFOG\n", " fog"},
1145 {"#define USECUBEFILTER\n", " cubefilter"},
1146 {"#define USEGLOW\n", " glow"},
1147 {"#define USESPECULAR\n", " specular"},
1148 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1149 {"#define USEREFLECTION\n", " reflection"},
1150 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1151 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1152 {"#define USEGAMMARAMPS\n", " gammaramps"},
1153 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1154 {"#define USESATURATION\n", " saturation"},
1157 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
1158 typedef enum shadermode_e
1160 SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
1161 SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
1162 SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
1163 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1164 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
1165 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1166 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1167 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1168 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1169 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
1170 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
1171 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1176 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1177 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1179 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1180 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1181 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1182 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1183 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1184 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1185 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1186 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1187 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1188 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1189 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1190 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1193 typedef struct r_glsl_permutation_s
1195 // indicates if we have tried compiling this permutation already
1197 // 0 if compilation failed
1199 // locations of detected uniforms in program object, or -1 if not found
1200 int loc_Texture_First;
1201 int loc_Texture_Second;
1202 int loc_Texture_GammaRamps;
1203 int loc_Texture_Normal;
1204 int loc_Texture_Color;
1205 int loc_Texture_Gloss;
1206 int loc_Texture_Glow;
1207 int loc_Texture_SecondaryNormal;
1208 int loc_Texture_SecondaryColor;
1209 int loc_Texture_SecondaryGloss;
1210 int loc_Texture_SecondaryGlow;
1211 int loc_Texture_Pants;
1212 int loc_Texture_Shirt;
1213 int loc_Texture_FogMask;
1214 int loc_Texture_Lightmap;
1215 int loc_Texture_Deluxemap;
1216 int loc_Texture_Attenuation;
1217 int loc_Texture_Cube;
1218 int loc_Texture_Refraction;
1219 int loc_Texture_Reflection;
1221 int loc_LightPosition;
1222 int loc_EyePosition;
1223 int loc_Color_Pants;
1224 int loc_Color_Shirt;
1225 int loc_FogRangeRecip;
1226 int loc_AmbientScale;
1227 int loc_DiffuseScale;
1228 int loc_SpecularScale;
1229 int loc_SpecularPower;
1231 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1232 int loc_OffsetMapping_Scale;
1234 int loc_AmbientColor;
1235 int loc_DiffuseColor;
1236 int loc_SpecularColor;
1238 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1239 int loc_GammaCoeff; // 1 / gamma
1240 int loc_DistortScaleRefractReflect;
1241 int loc_ScreenScaleRefractReflect;
1242 int loc_ScreenCenterRefractReflect;
1243 int loc_RefractColor;
1244 int loc_ReflectColor;
1245 int loc_ReflectFactor;
1246 int loc_ReflectOffset;
1255 r_glsl_permutation_t;
1257 // information about each possible shader permutation
1258 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1259 // currently selected permutation
1260 r_glsl_permutation_t *r_glsl_permutation;
1262 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1265 if (!filename || !filename[0])
1267 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1270 if (printfromdisknotice)
1271 Con_DPrint("from disk... ");
1272 return shaderstring;
1274 else if (!strcmp(filename, "glsl/default.glsl"))
1276 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1277 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1279 return shaderstring;
1282 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1285 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1286 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1287 int vertstrings_count = 0;
1288 int geomstrings_count = 0;
1289 int fragstrings_count = 0;
1290 char *vertexstring, *geometrystring, *fragmentstring;
1291 const char *vertstrings_list[32+3];
1292 const char *geomstrings_list[32+3];
1293 const char *fragstrings_list[32+3];
1294 char permutationname[256];
1301 permutationname[0] = 0;
1302 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1303 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1304 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1306 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1308 // the first pretext is which type of shader to compile as
1309 // (later these will all be bound together as a program object)
1310 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1311 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1312 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1314 // the second pretext is the mode (for example a light source)
1315 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1316 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1317 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1318 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1320 // now add all the permutation pretexts
1321 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1323 if (permutation & (1<<i))
1325 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1326 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1327 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1328 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1332 // keep line numbers correct
1333 vertstrings_list[vertstrings_count++] = "\n";
1334 geomstrings_list[geomstrings_count++] = "\n";
1335 fragstrings_list[fragstrings_count++] = "\n";
1339 // now append the shader text itself
1340 vertstrings_list[vertstrings_count++] = vertexstring;
1341 geomstrings_list[geomstrings_count++] = geometrystring;
1342 fragstrings_list[fragstrings_count++] = fragmentstring;
1344 // if any sources were NULL, clear the respective list
1346 vertstrings_count = 0;
1347 if (!geometrystring)
1348 geomstrings_count = 0;
1349 if (!fragmentstring)
1350 fragstrings_count = 0;
1352 // compile the shader program
1353 if (vertstrings_count + geomstrings_count + fragstrings_count)
1354 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1358 qglUseProgramObjectARB(p->program);CHECKGLERROR
1359 // look up all the uniform variable names we care about, so we don't
1360 // have to look them up every time we set them
1361 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1362 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1363 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1364 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1365 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1366 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1367 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1368 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1369 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1370 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1371 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1372 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1373 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1374 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1375 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1376 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1377 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1378 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1379 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1380 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1381 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1382 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1383 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1384 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1385 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1386 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1387 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1388 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1389 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1390 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1391 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1392 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1393 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1394 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1395 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1396 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1397 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1398 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1399 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1400 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1401 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1402 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1403 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1404 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1405 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1406 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1407 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1408 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1409 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1410 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1411 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1412 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1413 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1414 // initialize the samplers to refer to the texture units we use
1415 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1416 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1417 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1418 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1419 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1420 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1421 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1422 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1423 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1424 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1425 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1426 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1427 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1428 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1429 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1430 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1431 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1432 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1433 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1434 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1436 if (developer.integer)
1437 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1440 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1444 Mem_Free(vertexstring);
1446 Mem_Free(geometrystring);
1448 Mem_Free(fragmentstring);
1451 void R_GLSL_Restart_f(void)
1454 unsigned int permutation;
1455 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1456 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1457 if (r_glsl_permutations[mode][permutation].program)
1458 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1459 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1462 void R_GLSL_DumpShader_f(void)
1466 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1469 Con_Printf("failed to write to glsl/default.glsl\n");
1473 FS_Print(file, "// The engine may define the following macros:\n");
1474 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1475 for (i = 0;i < SHADERMODE_COUNT;i++)
1476 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1477 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1478 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1479 FS_Print(file, "\n");
1480 FS_Print(file, builtinshaderstring);
1483 Con_Printf("glsl/default.glsl written\n");
1486 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1488 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1489 if (r_glsl_permutation != perm)
1491 r_glsl_permutation = perm;
1492 if (!r_glsl_permutation->program)
1494 if (!r_glsl_permutation->compiled)
1495 R_GLSL_CompilePermutation(mode, permutation);
1496 if (!r_glsl_permutation->program)
1498 // remove features until we find a valid permutation
1500 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1502 // reduce i more quickly whenever it would not remove any bits
1503 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1504 if (!(permutation & j))
1507 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1508 if (!r_glsl_permutation->compiled)
1509 R_GLSL_CompilePermutation(mode, permutation);
1510 if (r_glsl_permutation->program)
1513 if (i >= SHADERPERMUTATION_COUNT)
1515 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");
1516 Cvar_SetValueQuick(&r_glsl, 0);
1517 R_GLSL_Restart_f(); // unload shaders
1518 return; // no bit left to clear
1523 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1527 void R_SetupGenericShader(qboolean usetexture)
1529 if (gl_support_fragment_shader)
1531 if (r_glsl.integer && r_glsl_usegeneric.integer)
1532 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1533 else if (r_glsl_permutation)
1535 r_glsl_permutation = NULL;
1536 qglUseProgramObjectARB(0);CHECKGLERROR
1541 void R_SetupGenericTwoTextureShader(int texturemode)
1543 if (gl_support_fragment_shader)
1545 if (r_glsl.integer && r_glsl_usegeneric.integer)
1546 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))));
1547 else if (r_glsl_permutation)
1549 r_glsl_permutation = NULL;
1550 qglUseProgramObjectARB(0);CHECKGLERROR
1553 if (!r_glsl_permutation)
1555 if (texturemode == GL_DECAL && gl_combine.integer)
1556 texturemode = GL_INTERPOLATE_ARB;
1557 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1561 void R_SetupDepthOrShadowShader(void)
1563 if (gl_support_fragment_shader)
1565 if (r_glsl.integer && r_glsl_usegeneric.integer)
1566 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1567 else if (r_glsl_permutation)
1569 r_glsl_permutation = NULL;
1570 qglUseProgramObjectARB(0);CHECKGLERROR
1575 extern rtexture_t *r_shadow_attenuationgradienttexture;
1576 extern rtexture_t *r_shadow_attenuation2dtexture;
1577 extern rtexture_t *r_shadow_attenuation3dtexture;
1578 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1580 // select a permutation of the lighting shader appropriate to this
1581 // combination of texture, entity, light source, and fogging, only use the
1582 // minimum features necessary to avoid wasting rendering time in the
1583 // fragment shader on features that are not being used
1584 unsigned int permutation = 0;
1585 unsigned int mode = 0;
1586 // TODO: implement geometry-shader based shadow volumes someday
1587 if (r_glsl_offsetmapping.integer)
1589 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1590 if (r_glsl_offsetmapping_reliefmapping.integer)
1591 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1593 if (rsurfacepass == RSURFPASS_BACKGROUND)
1595 // distorted background
1596 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1597 mode = SHADERMODE_WATER;
1599 mode = SHADERMODE_REFRACTION;
1601 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1604 mode = SHADERMODE_LIGHTSOURCE;
1605 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1606 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1607 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1608 permutation |= SHADERPERMUTATION_CUBEFILTER;
1609 if (diffusescale > 0)
1610 permutation |= SHADERPERMUTATION_DIFFUSE;
1611 if (specularscale > 0)
1612 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1613 if (r_refdef.fogenabled)
1614 permutation |= SHADERPERMUTATION_FOG;
1615 if (rsurface.texture->colormapping)
1616 permutation |= SHADERPERMUTATION_COLORMAPPING;
1617 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1618 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1620 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1622 // unshaded geometry (fullbright or ambient model lighting)
1623 mode = SHADERMODE_FLATCOLOR;
1624 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1625 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1626 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1627 permutation |= SHADERPERMUTATION_GLOW;
1628 if (r_refdef.fogenabled)
1629 permutation |= SHADERPERMUTATION_FOG;
1630 if (rsurface.texture->colormapping)
1631 permutation |= SHADERPERMUTATION_COLORMAPPING;
1632 if (r_glsl_offsetmapping.integer)
1634 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1635 if (r_glsl_offsetmapping_reliefmapping.integer)
1636 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1638 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1639 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1640 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1641 permutation |= SHADERPERMUTATION_REFLECTION;
1643 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1645 // directional model lighting
1646 mode = SHADERMODE_LIGHTDIRECTION;
1647 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1648 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1649 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1650 permutation |= SHADERPERMUTATION_GLOW;
1651 permutation |= SHADERPERMUTATION_DIFFUSE;
1652 if (specularscale > 0)
1653 permutation |= SHADERPERMUTATION_SPECULAR;
1654 if (r_refdef.fogenabled)
1655 permutation |= SHADERPERMUTATION_FOG;
1656 if (rsurface.texture->colormapping)
1657 permutation |= SHADERPERMUTATION_COLORMAPPING;
1658 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1659 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1660 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1661 permutation |= SHADERPERMUTATION_REFLECTION;
1663 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1665 // ambient model lighting
1666 mode = SHADERMODE_LIGHTDIRECTION;
1667 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1668 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1669 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1670 permutation |= SHADERPERMUTATION_GLOW;
1671 if (r_refdef.fogenabled)
1672 permutation |= SHADERPERMUTATION_FOG;
1673 if (rsurface.texture->colormapping)
1674 permutation |= SHADERPERMUTATION_COLORMAPPING;
1675 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1676 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1677 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1678 permutation |= SHADERPERMUTATION_REFLECTION;
1683 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1685 // deluxemapping (light direction texture)
1686 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1687 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1689 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1690 permutation |= SHADERPERMUTATION_DIFFUSE;
1691 if (specularscale > 0)
1692 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1694 else if (r_glsl_deluxemapping.integer >= 2)
1696 // fake deluxemapping (uniform light direction in tangentspace)
1697 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1698 permutation |= SHADERPERMUTATION_DIFFUSE;
1699 if (specularscale > 0)
1700 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1702 else if (rsurface.uselightmaptexture)
1704 // ordinary lightmapping (q1bsp, q3bsp)
1705 mode = SHADERMODE_LIGHTMAP;
1709 // ordinary vertex coloring (q3bsp)
1710 mode = SHADERMODE_VERTEXCOLOR;
1712 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1713 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1714 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1715 permutation |= SHADERPERMUTATION_GLOW;
1716 if (r_refdef.fogenabled)
1717 permutation |= SHADERPERMUTATION_FOG;
1718 if (rsurface.texture->colormapping)
1719 permutation |= SHADERPERMUTATION_COLORMAPPING;
1720 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1721 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1722 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1723 permutation |= SHADERPERMUTATION_REFLECTION;
1725 if(permutation & SHADERPERMUTATION_SPECULAR)
1726 if(r_shadow_glossexact.integer)
1727 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
1728 R_SetupShader_SetPermutation(mode, permutation);
1729 if (mode == SHADERMODE_LIGHTSOURCE)
1731 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1732 if (permutation & SHADERPERMUTATION_DIFFUSE)
1734 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1735 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1736 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1737 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1741 // ambient only is simpler
1742 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]);
1743 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1744 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1745 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1747 // additive passes are only darkened by fog, not tinted
1748 if (r_glsl_permutation->loc_FogColor >= 0)
1749 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1753 if (mode == SHADERMODE_LIGHTDIRECTION)
1755 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);
1756 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);
1757 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);
1758 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]);
1762 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
1763 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1764 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1766 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]);
1767 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1768 // additive passes are only darkened by fog, not tinted
1769 if (r_glsl_permutation->loc_FogColor >= 0)
1771 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1772 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1774 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1776 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);
1777 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]);
1778 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]);
1779 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1780 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1781 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1782 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1784 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1786 // The formula used is actually:
1787 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1788 // color.rgb *= SceneBrightness;
1790 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1791 // and do [[calculations]] here in the engine
1792 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1793 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1796 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1797 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1798 if (r_glsl_permutation->loc_Color_Pants >= 0)
1800 if (rsurface.texture->currentskinframe->pants)
1801 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1803 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1805 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1807 if (rsurface.texture->currentskinframe->shirt)
1808 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1810 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1812 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
1813 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
1815 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
1819 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1821 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1825 #define SKINFRAME_HASH 1024
1829 int loadsequence; // incremented each level change
1830 memexpandablearray_t array;
1831 skinframe_t *hash[SKINFRAME_HASH];
1834 r_skinframe_t r_skinframe;
1836 void R_SkinFrame_PrepareForPurge(void)
1838 r_skinframe.loadsequence++;
1839 // wrap it without hitting zero
1840 if (r_skinframe.loadsequence >= 200)
1841 r_skinframe.loadsequence = 1;
1844 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1848 // mark the skinframe as used for the purging code
1849 skinframe->loadsequence = r_skinframe.loadsequence;
1852 void R_SkinFrame_Purge(void)
1856 for (i = 0;i < SKINFRAME_HASH;i++)
1858 for (s = r_skinframe.hash[i];s;s = s->next)
1860 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1862 if (s->merged == s->base)
1864 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1865 R_PurgeTexture(s->stain );s->stain = NULL;
1866 R_PurgeTexture(s->merged);s->merged = NULL;
1867 R_PurgeTexture(s->base );s->base = NULL;
1868 R_PurgeTexture(s->pants );s->pants = NULL;
1869 R_PurgeTexture(s->shirt );s->shirt = NULL;
1870 R_PurgeTexture(s->nmap );s->nmap = NULL;
1871 R_PurgeTexture(s->gloss );s->gloss = NULL;
1872 R_PurgeTexture(s->glow );s->glow = NULL;
1873 R_PurgeTexture(s->fog );s->fog = NULL;
1874 s->loadsequence = 0;
1880 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1882 char basename[MAX_QPATH];
1884 Image_StripImageExtension(name, basename, sizeof(basename));
1886 if( last == NULL ) {
1888 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1889 item = r_skinframe.hash[hashindex];
1894 // linearly search through the hash bucket
1895 for( ; item ; item = item->next ) {
1896 if( !strcmp( item->basename, basename ) ) {
1903 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1907 char basename[MAX_QPATH];
1909 Image_StripImageExtension(name, basename, sizeof(basename));
1911 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1912 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1913 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1917 rtexture_t *dyntexture;
1918 // check whether its a dynamic texture
1919 dyntexture = CL_GetDynTexture( basename );
1920 if (!add && !dyntexture)
1922 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1923 memset(item, 0, sizeof(*item));
1924 strlcpy(item->basename, basename, sizeof(item->basename));
1925 item->base = dyntexture; // either NULL or dyntexture handle
1926 item->textureflags = textureflags;
1927 item->comparewidth = comparewidth;
1928 item->compareheight = compareheight;
1929 item->comparecrc = comparecrc;
1930 item->next = r_skinframe.hash[hashindex];
1931 r_skinframe.hash[hashindex] = item;
1933 else if( item->base == NULL )
1935 rtexture_t *dyntexture;
1936 // check whether its a dynamic texture
1937 // 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]
1938 dyntexture = CL_GetDynTexture( basename );
1939 item->base = dyntexture; // either NULL or dyntexture handle
1942 R_SkinFrame_MarkUsed(item);
1946 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
1948 unsigned long long avgcolor[5], wsum; \
1956 for(pix = 0; pix < cnt; ++pix) \
1959 for(comp = 0; comp < 3; ++comp) \
1961 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
1964 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1966 for(comp = 0; comp < 3; ++comp) \
1967 avgcolor[comp] += getpixel * w; \
1970 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1971 avgcolor[4] += getpixel; \
1973 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
1975 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
1976 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
1977 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
1978 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
1981 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
1983 // FIXME: it should be possible to disable loading various layers using
1984 // cvars, to prevent wasted loading time and memory usage if the user does
1986 qboolean loadnormalmap = true;
1987 qboolean loadgloss = true;
1988 qboolean loadpantsandshirt = true;
1989 qboolean loadglow = true;
1991 unsigned char *pixels;
1992 unsigned char *bumppixels;
1993 unsigned char *basepixels = NULL;
1994 int basepixels_width;
1995 int basepixels_height;
1996 skinframe_t *skinframe;
2000 if (cls.state == ca_dedicated)
2003 // return an existing skinframe if already loaded
2004 // if loading of the first image fails, don't make a new skinframe as it
2005 // would cause all future lookups of this to be missing
2006 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2007 if (skinframe && skinframe->base)
2010 basepixels = loadimagepixelsbgra(name, complain, true);
2011 if (basepixels == NULL)
2014 if (developer_loading.integer)
2015 Con_Printf("loading skin \"%s\"\n", name);
2017 // we've got some pixels to store, so really allocate this new texture now
2019 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2020 skinframe->stain = NULL;
2021 skinframe->merged = NULL;
2022 skinframe->base = r_texture_notexture;
2023 skinframe->pants = NULL;
2024 skinframe->shirt = NULL;
2025 skinframe->nmap = r_texture_blanknormalmap;
2026 skinframe->gloss = NULL;
2027 skinframe->glow = NULL;
2028 skinframe->fog = NULL;
2030 basepixels_width = image_width;
2031 basepixels_height = image_height;
2032 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);
2034 if (textureflags & TEXF_ALPHA)
2036 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2037 if (basepixels[j] < 255)
2039 if (j < basepixels_width * basepixels_height * 4)
2041 // has transparent pixels
2043 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2044 for (j = 0;j < image_width * image_height * 4;j += 4)
2049 pixels[j+3] = basepixels[j+3];
2051 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);
2056 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2057 //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]);
2059 // _norm is the name used by tenebrae and has been adopted as standard
2062 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2064 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);
2068 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2070 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2071 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2072 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);
2074 Mem_Free(bumppixels);
2076 else if (r_shadow_bumpscale_basetexture.value > 0)
2078 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2079 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2080 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);
2084 // _luma is supported for tenebrae compatibility
2085 // (I think it's a very stupid name, but oh well)
2086 // _glow is the preferred name
2087 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;}
2088 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;}
2089 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;}
2090 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;}
2093 Mem_Free(basepixels);
2098 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2101 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2104 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)
2109 for (i = 0;i < width*height;i++)
2110 if (((unsigned char *)&palette[in[i]])[3] > 0)
2112 if (i == width*height)
2115 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2118 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2119 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2122 unsigned char *temp1, *temp2;
2123 skinframe_t *skinframe;
2125 if (cls.state == ca_dedicated)
2128 // if already loaded just return it, otherwise make a new skinframe
2129 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2130 if (skinframe && skinframe->base)
2133 skinframe->stain = NULL;
2134 skinframe->merged = NULL;
2135 skinframe->base = r_texture_notexture;
2136 skinframe->pants = NULL;
2137 skinframe->shirt = NULL;
2138 skinframe->nmap = r_texture_blanknormalmap;
2139 skinframe->gloss = NULL;
2140 skinframe->glow = NULL;
2141 skinframe->fog = NULL;
2143 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2147 if (developer_loading.integer)
2148 Con_Printf("loading 32bit skin \"%s\"\n", name);
2150 if (r_shadow_bumpscale_basetexture.value > 0)
2152 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2153 temp2 = temp1 + width * height * 4;
2154 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2155 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2158 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2159 if (textureflags & TEXF_ALPHA)
2161 for (i = 3;i < width * height * 4;i += 4)
2162 if (skindata[i] < 255)
2164 if (i < width * height * 4)
2166 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2167 memcpy(fogpixels, skindata, width * height * 4);
2168 for (i = 0;i < width * height * 4;i += 4)
2169 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2170 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2171 Mem_Free(fogpixels);
2175 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2176 //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]);
2181 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2184 unsigned char *temp1, *temp2;
2185 unsigned int *palette;
2186 skinframe_t *skinframe;
2188 if (cls.state == ca_dedicated)
2191 // if already loaded just return it, otherwise make a new skinframe
2192 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2193 if (skinframe && skinframe->base)
2196 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2198 skinframe->stain = NULL;
2199 skinframe->merged = NULL;
2200 skinframe->base = r_texture_notexture;
2201 skinframe->pants = NULL;
2202 skinframe->shirt = NULL;
2203 skinframe->nmap = r_texture_blanknormalmap;
2204 skinframe->gloss = NULL;
2205 skinframe->glow = NULL;
2206 skinframe->fog = NULL;
2208 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2212 if (developer_loading.integer)
2213 Con_Printf("loading quake skin \"%s\"\n", name);
2215 if (r_shadow_bumpscale_basetexture.value > 0)
2217 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2218 temp2 = temp1 + width * height * 4;
2219 // use either a custom palette or the quake palette
2220 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2221 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2222 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2225 // use either a custom palette, or the quake palette
2226 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2227 if (loadglowtexture)
2228 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2229 if (loadpantsandshirt)
2231 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2232 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2234 if (skinframe->pants || skinframe->shirt)
2235 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
2236 if (textureflags & TEXF_ALPHA)
2238 for (i = 0;i < width * height;i++)
2239 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2241 if (i < width * height)
2242 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2245 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2246 //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]);
2251 skinframe_t *R_SkinFrame_LoadMissing(void)
2253 skinframe_t *skinframe;
2255 if (cls.state == ca_dedicated)
2258 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2259 skinframe->stain = NULL;
2260 skinframe->merged = NULL;
2261 skinframe->base = r_texture_notexture;
2262 skinframe->pants = NULL;
2263 skinframe->shirt = NULL;
2264 skinframe->nmap = r_texture_blanknormalmap;
2265 skinframe->gloss = NULL;
2266 skinframe->glow = NULL;
2267 skinframe->fog = NULL;
2269 skinframe->avgcolor[0] = rand() / RAND_MAX;
2270 skinframe->avgcolor[1] = rand() / RAND_MAX;
2271 skinframe->avgcolor[2] = rand() / RAND_MAX;
2272 skinframe->avgcolor[3] = 1;
2277 void gl_main_start(void)
2281 memset(r_queries, 0, sizeof(r_queries));
2283 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2284 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2286 // set up r_skinframe loading system for textures
2287 memset(&r_skinframe, 0, sizeof(r_skinframe));
2288 r_skinframe.loadsequence = 1;
2289 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2291 r_main_texturepool = R_AllocTexturePool();
2292 R_BuildBlankTextures();
2294 if (gl_texturecubemap)
2297 R_BuildNormalizationCube();
2299 r_texture_fogattenuation = NULL;
2300 r_texture_gammaramps = NULL;
2301 //r_texture_fogintensity = NULL;
2302 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2303 memset(&r_waterstate, 0, sizeof(r_waterstate));
2304 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2305 memset(&r_svbsp, 0, sizeof (r_svbsp));
2307 r_refdef.fogmasktable_density = 0;
2310 extern rtexture_t *loadingscreentexture;
2311 void gl_main_shutdown(void)
2314 qglDeleteQueriesARB(r_maxqueries, r_queries);
2318 memset(r_queries, 0, sizeof(r_queries));
2320 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2321 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2323 // clear out the r_skinframe state
2324 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2325 memset(&r_skinframe, 0, sizeof(r_skinframe));
2328 Mem_Free(r_svbsp.nodes);
2329 memset(&r_svbsp, 0, sizeof (r_svbsp));
2330 R_FreeTexturePool(&r_main_texturepool);
2331 loadingscreentexture = NULL;
2332 r_texture_blanknormalmap = NULL;
2333 r_texture_white = NULL;
2334 r_texture_grey128 = NULL;
2335 r_texture_black = NULL;
2336 r_texture_whitecube = NULL;
2337 r_texture_normalizationcube = NULL;
2338 r_texture_fogattenuation = NULL;
2339 r_texture_gammaramps = NULL;
2340 //r_texture_fogintensity = NULL;
2341 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2342 memset(&r_waterstate, 0, sizeof(r_waterstate));
2346 extern void CL_ParseEntityLump(char *entitystring);
2347 void gl_main_newmap(void)
2349 // FIXME: move this code to client
2351 char *entities, entname[MAX_QPATH];
2354 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2355 l = (int)strlen(entname) - 4;
2356 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2358 memcpy(entname + l, ".ent", 5);
2359 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2361 CL_ParseEntityLump(entities);
2366 if (cl.worldmodel->brush.entities)
2367 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2371 void GL_Main_Init(void)
2373 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2375 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2376 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2377 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2378 if (gamemode == GAME_NEHAHRA)
2380 Cvar_RegisterVariable (&gl_fogenable);
2381 Cvar_RegisterVariable (&gl_fogdensity);
2382 Cvar_RegisterVariable (&gl_fogred);
2383 Cvar_RegisterVariable (&gl_foggreen);
2384 Cvar_RegisterVariable (&gl_fogblue);
2385 Cvar_RegisterVariable (&gl_fogstart);
2386 Cvar_RegisterVariable (&gl_fogend);
2387 Cvar_RegisterVariable (&gl_skyclip);
2389 Cvar_RegisterVariable(&r_motionblur);
2390 Cvar_RegisterVariable(&r_motionblur_maxblur);
2391 Cvar_RegisterVariable(&r_motionblur_bmin);
2392 Cvar_RegisterVariable(&r_motionblur_vmin);
2393 Cvar_RegisterVariable(&r_motionblur_vmax);
2394 Cvar_RegisterVariable(&r_motionblur_vtime);
2395 Cvar_RegisterVariable(&r_motionblur_randomize);
2396 Cvar_RegisterVariable(&r_damageblur);
2397 Cvar_RegisterVariable(&r_motionblur_debug);
2398 Cvar_RegisterVariable(&r_depthfirst);
2399 Cvar_RegisterVariable(&r_useinfinitefarclip);
2400 Cvar_RegisterVariable(&r_nearclip);
2401 Cvar_RegisterVariable(&r_showbboxes);
2402 Cvar_RegisterVariable(&r_showsurfaces);
2403 Cvar_RegisterVariable(&r_showtris);
2404 Cvar_RegisterVariable(&r_shownormals);
2405 Cvar_RegisterVariable(&r_showlighting);
2406 Cvar_RegisterVariable(&r_showshadowvolumes);
2407 Cvar_RegisterVariable(&r_showcollisionbrushes);
2408 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2409 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2410 Cvar_RegisterVariable(&r_showdisabledepthtest);
2411 Cvar_RegisterVariable(&r_drawportals);
2412 Cvar_RegisterVariable(&r_drawentities);
2413 Cvar_RegisterVariable(&r_cullentities_trace);
2414 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2415 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2416 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2417 Cvar_RegisterVariable(&r_drawviewmodel);
2418 Cvar_RegisterVariable(&r_speeds);
2419 Cvar_RegisterVariable(&r_fullbrights);
2420 Cvar_RegisterVariable(&r_wateralpha);
2421 Cvar_RegisterVariable(&r_dynamic);
2422 Cvar_RegisterVariable(&r_fullbright);
2423 Cvar_RegisterVariable(&r_shadows);
2424 Cvar_RegisterVariable(&r_shadows_throwdistance);
2425 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2426 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2427 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2428 Cvar_RegisterVariable(&r_fog_exp2);
2429 Cvar_RegisterVariable(&r_drawfog);
2430 Cvar_RegisterVariable(&r_textureunits);
2431 Cvar_RegisterVariable(&r_glsl);
2432 Cvar_RegisterVariable(&r_glsl_contrastboost);
2433 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2434 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2435 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2436 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2437 Cvar_RegisterVariable(&r_glsl_postprocess);
2438 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2439 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2440 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2441 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2442 Cvar_RegisterVariable(&r_glsl_usegeneric);
2443 Cvar_RegisterVariable(&r_water);
2444 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2445 Cvar_RegisterVariable(&r_water_clippingplanebias);
2446 Cvar_RegisterVariable(&r_water_refractdistort);
2447 Cvar_RegisterVariable(&r_water_reflectdistort);
2448 Cvar_RegisterVariable(&r_lerpsprites);
2449 Cvar_RegisterVariable(&r_lerpmodels);
2450 Cvar_RegisterVariable(&r_lerplightstyles);
2451 Cvar_RegisterVariable(&r_waterscroll);
2452 Cvar_RegisterVariable(&r_bloom);
2453 Cvar_RegisterVariable(&r_bloom_colorscale);
2454 Cvar_RegisterVariable(&r_bloom_brighten);
2455 Cvar_RegisterVariable(&r_bloom_blur);
2456 Cvar_RegisterVariable(&r_bloom_resolution);
2457 Cvar_RegisterVariable(&r_bloom_colorexponent);
2458 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2459 Cvar_RegisterVariable(&r_hdr);
2460 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2461 Cvar_RegisterVariable(&r_hdr_glowintensity);
2462 Cvar_RegisterVariable(&r_hdr_range);
2463 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2464 Cvar_RegisterVariable(&developer_texturelogging);
2465 Cvar_RegisterVariable(&gl_lightmaps);
2466 Cvar_RegisterVariable(&r_test);
2467 Cvar_RegisterVariable(&r_batchmode);
2468 Cvar_RegisterVariable(&r_glsl_saturation);
2469 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2470 Cvar_SetValue("r_fullbrights", 0);
2471 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2473 Cvar_RegisterVariable(&r_track_sprites);
2474 Cvar_RegisterVariable(&r_track_sprites_flags);
2475 Cvar_RegisterVariable(&r_track_sprites_scalew);
2476 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2479 extern void R_Textures_Init(void);
2480 extern void GL_Draw_Init(void);
2481 extern void GL_Main_Init(void);
2482 extern void R_Shadow_Init(void);
2483 extern void R_Sky_Init(void);
2484 extern void GL_Surf_Init(void);
2485 extern void R_Particles_Init(void);
2486 extern void R_Explosion_Init(void);
2487 extern void gl_backend_init(void);
2488 extern void Sbar_Init(void);
2489 extern void R_LightningBeams_Init(void);
2490 extern void Mod_RenderInit(void);
2492 void Render_Init(void)
2504 R_LightningBeams_Init();
2513 extern char *ENGINE_EXTENSIONS;
2516 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2517 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2518 gl_version = (const char *)qglGetString(GL_VERSION);
2519 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2523 if (!gl_platformextensions)
2524 gl_platformextensions = "";
2526 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2527 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2528 Con_Printf("GL_VERSION: %s\n", gl_version);
2529 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2530 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2532 VID_CheckExtensions();
2534 // LordHavoc: report supported extensions
2535 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2537 // clear to black (loading plaque will be seen over this)
2539 qglClearColor(0,0,0,1);CHECKGLERROR
2540 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2543 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2547 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2549 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2552 p = r_refdef.view.frustum + i;
2557 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2561 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2565 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2569 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2573 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2577 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2581 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2585 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2593 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2597 for (i = 0;i < numplanes;i++)
2604 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2608 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2612 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2616 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2620 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2624 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2628 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2632 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2640 //==================================================================================
2642 static void R_View_UpdateEntityLighting (void)
2645 entity_render_t *ent;
2646 vec3_t tempdiffusenormal;
2648 for (i = 0;i < r_refdef.scene.numentities;i++)
2650 ent = r_refdef.scene.entities[i];
2652 // skip unseen models
2653 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
2657 if (ent->model && ent->model->brush.num_leafs)
2659 // TODO: use modellight for r_ambient settings on world?
2660 VectorSet(ent->modellight_ambient, 0, 0, 0);
2661 VectorSet(ent->modellight_diffuse, 0, 0, 0);
2662 VectorSet(ent->modellight_lightdir, 0, 0, 1);
2666 // fetch the lighting from the worldmodel data
2667 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));
2668 VectorClear(ent->modellight_diffuse);
2669 VectorClear(tempdiffusenormal);
2670 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
2673 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2674 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2677 VectorSet(ent->modellight_ambient, 1, 1, 1);
2679 // move the light direction into modelspace coordinates for lighting code
2680 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2681 if(VectorLength2(ent->modellight_lightdir) == 0)
2682 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2683 VectorNormalize(ent->modellight_lightdir);
2687 static void R_View_UpdateEntityVisible (void)
2690 entity_render_t *ent;
2692 if (!r_drawentities.integer)
2695 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2696 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2698 // worldmodel can check visibility
2699 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2700 for (i = 0;i < r_refdef.scene.numentities;i++)
2702 ent = r_refdef.scene.entities[i];
2703 if (!(ent->flags & renderimask))
2704 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)))
2705 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))
2706 r_refdef.viewcache.entityvisible[i] = true;
2708 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2710 for (i = 0;i < r_refdef.scene.numentities;i++)
2712 ent = r_refdef.scene.entities[i];
2713 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2715 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))
2716 ent->last_trace_visibility = realtime;
2717 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2718 r_refdef.viewcache.entityvisible[i] = 0;
2725 // no worldmodel or it can't check visibility
2726 for (i = 0;i < r_refdef.scene.numentities;i++)
2728 ent = r_refdef.scene.entities[i];
2729 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));
2734 // only used if skyrendermasked, and normally returns false
2735 int R_DrawBrushModelsSky (void)
2738 entity_render_t *ent;
2740 if (!r_drawentities.integer)
2744 for (i = 0;i < r_refdef.scene.numentities;i++)
2746 if (!r_refdef.viewcache.entityvisible[i])
2748 ent = r_refdef.scene.entities[i];
2749 if (!ent->model || !ent->model->DrawSky)
2751 ent->model->DrawSky(ent);
2757 static void R_DrawNoModel(entity_render_t *ent);
2758 static void R_DrawModels(void)
2761 entity_render_t *ent;
2763 if (!r_drawentities.integer)
2766 for (i = 0;i < r_refdef.scene.numentities;i++)
2768 if (!r_refdef.viewcache.entityvisible[i])
2770 ent = r_refdef.scene.entities[i];
2771 r_refdef.stats.entities++;
2772 if (ent->model && ent->model->Draw != NULL)
2773 ent->model->Draw(ent);
2779 static void R_DrawModelsDepth(void)
2782 entity_render_t *ent;
2784 if (!r_drawentities.integer)
2787 for (i = 0;i < r_refdef.scene.numentities;i++)
2789 if (!r_refdef.viewcache.entityvisible[i])
2791 ent = r_refdef.scene.entities[i];
2792 if (ent->model && ent->model->DrawDepth != NULL)
2793 ent->model->DrawDepth(ent);
2797 static void R_DrawModelsDebug(void)
2800 entity_render_t *ent;
2802 if (!r_drawentities.integer)
2805 for (i = 0;i < r_refdef.scene.numentities;i++)
2807 if (!r_refdef.viewcache.entityvisible[i])
2809 ent = r_refdef.scene.entities[i];
2810 if (ent->model && ent->model->DrawDebug != NULL)
2811 ent->model->DrawDebug(ent);
2815 static void R_DrawModelsAddWaterPlanes(void)
2818 entity_render_t *ent;
2820 if (!r_drawentities.integer)
2823 for (i = 0;i < r_refdef.scene.numentities;i++)
2825 if (!r_refdef.viewcache.entityvisible[i])
2827 ent = r_refdef.scene.entities[i];
2828 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2829 ent->model->DrawAddWaterPlanes(ent);
2833 static void R_View_SetFrustum(void)
2836 double slopex, slopey;
2837 vec3_t forward, left, up, origin;
2839 // we can't trust r_refdef.view.forward and friends in reflected scenes
2840 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2843 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2844 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2845 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2846 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2847 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2848 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2849 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2850 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2851 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2852 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2853 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2854 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2858 zNear = r_refdef.nearclip;
2859 nudge = 1.0 - 1.0 / (1<<23);
2860 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2861 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2862 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2863 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2864 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2865 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2866 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2867 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2873 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2874 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2875 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2876 r_refdef.view.frustum[0].dist = m[15] - m[12];
2878 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2879 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2880 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2881 r_refdef.view.frustum[1].dist = m[15] + m[12];
2883 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2884 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2885 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2886 r_refdef.view.frustum[2].dist = m[15] - m[13];
2888 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2889 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2890 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2891 r_refdef.view.frustum[3].dist = m[15] + m[13];
2893 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2894 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2895 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2896 r_refdef.view.frustum[4].dist = m[15] - m[14];
2898 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2899 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2900 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2901 r_refdef.view.frustum[5].dist = m[15] + m[14];
2904 if (r_refdef.view.useperspective)
2906 slopex = 1.0 / r_refdef.view.frustum_x;
2907 slopey = 1.0 / r_refdef.view.frustum_y;
2908 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2909 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
2910 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
2911 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
2912 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2914 // Leaving those out was a mistake, those were in the old code, and they
2915 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2916 // I couldn't reproduce it after adding those normalizations. --blub
2917 VectorNormalize(r_refdef.view.frustum[0].normal);
2918 VectorNormalize(r_refdef.view.frustum[1].normal);
2919 VectorNormalize(r_refdef.view.frustum[2].normal);
2920 VectorNormalize(r_refdef.view.frustum[3].normal);
2922 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2923 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2924 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2925 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2926 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2928 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2929 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2930 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2931 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2932 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2936 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2937 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2938 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2939 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2940 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2941 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2942 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2943 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2944 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2945 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2947 r_refdef.view.numfrustumplanes = 5;
2949 if (r_refdef.view.useclipplane)
2951 r_refdef.view.numfrustumplanes = 6;
2952 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2955 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2956 PlaneClassify(r_refdef.view.frustum + i);
2958 // LordHavoc: note to all quake engine coders, Quake had a special case
2959 // for 90 degrees which assumed a square view (wrong), so I removed it,
2960 // Quake2 has it disabled as well.
2962 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2963 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2964 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2965 //PlaneClassify(&frustum[0]);
2967 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2968 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2969 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2970 //PlaneClassify(&frustum[1]);
2972 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2973 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2974 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2975 //PlaneClassify(&frustum[2]);
2977 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2978 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2979 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2980 //PlaneClassify(&frustum[3]);
2983 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2984 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2985 //PlaneClassify(&frustum[4]);
2988 void R_View_Update(void)
2990 R_View_SetFrustum();
2991 R_View_WorldVisibility(r_refdef.view.useclipplane);
2992 R_View_UpdateEntityVisible();
2993 R_View_UpdateEntityLighting();
2996 void R_SetupView(qboolean allowwaterclippingplane)
2998 if (!r_refdef.view.useperspective)
2999 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);
3000 else if (gl_stencil && r_useinfinitefarclip.integer)
3001 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
3003 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
3005 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
3007 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3009 // LordHavoc: couldn't figure out how to make this approach the
3010 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3011 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3012 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3013 dist = r_refdef.view.clipplane.dist;
3014 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
3018 void R_ResetViewRendering2D(void)
3022 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3023 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3024 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
3025 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3026 GL_Color(1, 1, 1, 1);
3027 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3028 GL_BlendFunc(GL_ONE, GL_ZERO);
3029 GL_AlphaTest(false);
3030 GL_ScissorTest(false);
3031 GL_DepthMask(false);
3032 GL_DepthRange(0, 1);
3033 GL_DepthTest(false);
3034 R_Mesh_Matrix(&identitymatrix);
3035 R_Mesh_ResetTextureState();
3036 GL_PolygonOffset(0, 0);
3037 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3038 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3039 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3040 qglStencilMask(~0);CHECKGLERROR
3041 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3042 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3043 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3044 R_SetupGenericShader(true);
3047 void R_ResetViewRendering3D(void)
3051 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3052 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3054 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3055 GL_Color(1, 1, 1, 1);
3056 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3057 GL_BlendFunc(GL_ONE, GL_ZERO);
3058 GL_AlphaTest(false);
3059 GL_ScissorTest(true);
3061 GL_DepthRange(0, 1);
3063 R_Mesh_Matrix(&identitymatrix);
3064 R_Mesh_ResetTextureState();
3065 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3066 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3067 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3068 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3069 qglStencilMask(~0);CHECKGLERROR
3070 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3071 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3072 GL_CullFace(r_refdef.view.cullface_back);
3073 R_SetupGenericShader(true);
3076 void R_RenderScene(void);
3077 void R_RenderWaterPlanes(void);
3079 static void R_Water_StartFrame(void)
3082 int waterwidth, waterheight, texturewidth, textureheight;
3083 r_waterstate_waterplane_t *p;
3085 // set waterwidth and waterheight to the water resolution that will be
3086 // used (often less than the screen resolution for faster rendering)
3087 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3088 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3090 // calculate desired texture sizes
3091 // can't use water if the card does not support the texture size
3092 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3093 texturewidth = textureheight = waterwidth = waterheight = 0;
3094 else if (gl_support_arb_texture_non_power_of_two)
3096 texturewidth = waterwidth;
3097 textureheight = waterheight;
3101 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3102 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3105 // allocate textures as needed
3106 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3108 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3109 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3111 if (p->texture_refraction)
3112 R_FreeTexture(p->texture_refraction);
3113 p->texture_refraction = NULL;
3114 if (p->texture_reflection)
3115 R_FreeTexture(p->texture_reflection);
3116 p->texture_reflection = NULL;
3118 memset(&r_waterstate, 0, sizeof(r_waterstate));
3119 r_waterstate.waterwidth = waterwidth;
3120 r_waterstate.waterheight = waterheight;
3121 r_waterstate.texturewidth = texturewidth;
3122 r_waterstate.textureheight = textureheight;
3125 if (r_waterstate.waterwidth)
3127 r_waterstate.enabled = true;
3129 // set up variables that will be used in shader setup
3130 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3131 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3132 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3133 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3136 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3137 r_waterstate.numwaterplanes = 0;
3140 void R_Water_AddWaterPlane(msurface_t *surface)
3142 int triangleindex, planeindex;
3148 r_waterstate_waterplane_t *p;
3149 texture_t *t = R_GetCurrentTexture(surface->texture);
3150 // just use the first triangle with a valid normal for any decisions
3151 VectorClear(normal);
3152 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3154 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3155 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3156 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3157 TriangleNormal(vert[0], vert[1], vert[2], normal);
3158 if (VectorLength2(normal) >= 0.001)
3162 VectorCopy(normal, plane.normal);
3163 VectorNormalize(plane.normal);
3164 plane.dist = DotProduct(vert[0], plane.normal);
3165 PlaneClassify(&plane);
3166 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3168 // skip backfaces (except if nocullface is set)
3169 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3171 VectorNegate(plane.normal, plane.normal);
3173 PlaneClassify(&plane);
3177 // find a matching plane if there is one
3178 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3179 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3181 if (planeindex >= r_waterstate.maxwaterplanes)
3182 return; // nothing we can do, out of planes
3184 // if this triangle does not fit any known plane rendered this frame, add one
3185 if (planeindex >= r_waterstate.numwaterplanes)
3187 // store the new plane
3188 r_waterstate.numwaterplanes++;
3190 // clear materialflags and pvs
3191 p->materialflags = 0;
3192 p->pvsvalid = false;
3194 // merge this surface's materialflags into the waterplane
3195 p->materialflags |= t->currentmaterialflags;
3196 // merge this surface's PVS into the waterplane
3197 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3198 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3199 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3201 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3206 static void R_Water_ProcessPlanes(void)
3208 r_refdef_view_t originalview;
3209 r_refdef_view_t myview;
3211 r_waterstate_waterplane_t *p;
3213 originalview = r_refdef.view;
3215 // make sure enough textures are allocated
3216 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3218 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3220 if (!p->texture_refraction)
3221 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);
3222 if (!p->texture_refraction)
3226 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3228 if (!p->texture_reflection)
3229 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);
3230 if (!p->texture_reflection)
3236 r_refdef.view = originalview;
3237 r_refdef.view.showdebug = false;
3238 r_refdef.view.width = r_waterstate.waterwidth;
3239 r_refdef.view.height = r_waterstate.waterheight;
3240 r_refdef.view.useclipplane = true;
3241 myview = r_refdef.view;
3242 r_waterstate.renderingscene = true;
3243 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3245 // render the normal view scene and copy into texture
3246 // (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)
3247 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3249 r_refdef.view = myview;
3250 r_refdef.view.clipplane = p->plane;
3251 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3252 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3253 PlaneClassify(&r_refdef.view.clipplane);
3255 R_ResetViewRendering3D();
3256 R_ClearScreen(r_refdef.fogenabled);
3260 // copy view into the screen texture
3261 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3262 GL_ActiveTexture(0);
3264 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
3267 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3269 r_refdef.view = myview;
3270 // render reflected scene and copy into texture
3271 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3272 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3273 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3274 r_refdef.view.clipplane = p->plane;
3275 // reverse the cullface settings for this render
3276 r_refdef.view.cullface_front = GL_FRONT;
3277 r_refdef.view.cullface_back = GL_BACK;
3278 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3280 r_refdef.view.usecustompvs = true;
3282 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3284 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3287 R_ResetViewRendering3D();
3288 R_ClearScreen(r_refdef.fogenabled);
3292 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3293 GL_ActiveTexture(0);
3295 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
3298 r_waterstate.renderingscene = false;
3299 r_refdef.view = originalview;
3300 R_ResetViewRendering3D();
3301 R_ClearScreen(r_refdef.fogenabled);
3305 r_refdef.view = originalview;
3306 r_waterstate.renderingscene = false;
3307 Cvar_SetValueQuick(&r_water, 0);
3308 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3312 void R_Bloom_StartFrame(void)
3314 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3316 // set bloomwidth and bloomheight to the bloom resolution that will be
3317 // used (often less than the screen resolution for faster rendering)
3318 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3319 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3320 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3321 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3322 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3324 // calculate desired texture sizes
3325 if (gl_support_arb_texture_non_power_of_two)
3327 screentexturewidth = r_refdef.view.width;
3328 screentextureheight = r_refdef.view.height;
3329 bloomtexturewidth = r_bloomstate.bloomwidth;
3330 bloomtextureheight = r_bloomstate.bloomheight;
3334 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3335 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3336 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3337 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3340 if ((r_hdr.integer || r_bloom.integer || r_motionblur.value) && ((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))
3342 Cvar_SetValueQuick(&r_hdr, 0);
3343 Cvar_SetValueQuick(&r_bloom, 0);
3344 //Cvar_SetValueQuick(&r_motionblur, 0);
3347 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial))) && !r_bloom.integer && !r_hdr.integer && !r_motionblur.value)
3348 screentexturewidth = screentextureheight = 0;
3349 if (!r_hdr.integer && !r_bloom.integer)
3350 bloomtexturewidth = bloomtextureheight = 0;
3352 // allocate textures as needed
3353 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3355 if (r_bloomstate.texture_screen)
3356 R_FreeTexture(r_bloomstate.texture_screen);
3357 r_bloomstate.texture_screen = NULL;
3358 r_bloomstate.screentexturewidth = screentexturewidth;
3359 r_bloomstate.screentextureheight = screentextureheight;
3360 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3361 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);
3363 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3365 if (r_bloomstate.texture_bloom)
3366 R_FreeTexture(r_bloomstate.texture_bloom);
3367 r_bloomstate.texture_bloom = NULL;
3368 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3369 r_bloomstate.bloomtextureheight = bloomtextureheight;
3370 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3371 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);
3374 // set up a texcoord array for the full resolution screen image
3375 // (we have to keep this around to copy back during final render)
3376 r_bloomstate.screentexcoord2f[0] = 0;
3377 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3378 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3379 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3380 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3381 r_bloomstate.screentexcoord2f[5] = 0;
3382 r_bloomstate.screentexcoord2f[6] = 0;
3383 r_bloomstate.screentexcoord2f[7] = 0;
3385 // set up a texcoord array for the reduced resolution bloom image
3386 // (which will be additive blended over the screen image)
3387 r_bloomstate.bloomtexcoord2f[0] = 0;
3388 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3389 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3390 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3391 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3392 r_bloomstate.bloomtexcoord2f[5] = 0;
3393 r_bloomstate.bloomtexcoord2f[6] = 0;
3394 r_bloomstate.bloomtexcoord2f[7] = 0;
3396 if (r_hdr.integer || r_bloom.integer)
3398 r_bloomstate.enabled = true;
3399 r_bloomstate.hdr = r_hdr.integer != 0;
3403 void R_Bloom_CopyBloomTexture(float colorscale)
3405 r_refdef.stats.bloom++;
3407 // scale down screen texture to the bloom texture size
3409 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3410 GL_BlendFunc(GL_ONE, GL_ZERO);
3411 GL_Color(colorscale, colorscale, colorscale, 1);
3412 // TODO: optimize with multitexture or GLSL
3413 R_SetupGenericShader(true);
3414 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3415 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3416 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3417 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3419 // we now have a bloom image in the framebuffer
3420 // copy it into the bloom image texture for later processing
3421 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3422 GL_ActiveTexture(0);
3424 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
3425 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3428 void R_Bloom_CopyHDRTexture(void)
3430 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3431 GL_ActiveTexture(0);
3433 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
3434 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3437 void R_Bloom_MakeTexture(void)
3440 float xoffset, yoffset, r, brighten;
3442 r_refdef.stats.bloom++;
3444 R_ResetViewRendering2D();
3445 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3446 R_Mesh_ColorPointer(NULL, 0, 0);
3447 R_SetupGenericShader(true);
3449 // we have a bloom image in the framebuffer
3451 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3453 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3456 r = bound(0, r_bloom_colorexponent.value / x, 1);
3457 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3458 GL_Color(r, r, r, 1);
3459 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3460 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3461 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3462 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3464 // copy the vertically blurred bloom view to a texture
3465 GL_ActiveTexture(0);
3467 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
3468 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3471 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3472 brighten = r_bloom_brighten.value;
3474 brighten *= r_hdr_range.value;
3475 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3476 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3478 for (dir = 0;dir < 2;dir++)
3480 // blend on at multiple vertical offsets to achieve a vertical blur
3481 // TODO: do offset blends using GLSL
3482 GL_BlendFunc(GL_ONE, GL_ZERO);
3483 for (x = -range;x <= range;x++)
3485 if (!dir){xoffset = 0;yoffset = x;}
3486 else {xoffset = x;yoffset = 0;}
3487 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3488 yoffset /= (float)r_bloomstate.bloomtextureheight;
3489 // compute a texcoord array with the specified x and y offset
3490 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3491 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3492 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3493 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3494 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3495 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3496 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3497 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3498 // this r value looks like a 'dot' particle, fading sharply to
3499 // black at the edges
3500 // (probably not realistic but looks good enough)
3501 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3502 //r = (dir ? 1.0f : brighten)/(range*2+1);
3503 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3504 GL_Color(r, r, r, 1);
3505 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3506 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3507 GL_BlendFunc(GL_ONE, GL_ONE);
3510 // copy the vertically blurred bloom view to a texture
3511 GL_ActiveTexture(0);
3513 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
3514 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3517 // apply subtract last
3518 // (just like it would be in a GLSL shader)
3519 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3521 GL_BlendFunc(GL_ONE, GL_ZERO);
3522 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3523 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3524 GL_Color(1, 1, 1, 1);
3525 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3526 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3528 GL_BlendFunc(GL_ONE, GL_ONE);
3529 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3530 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3531 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3532 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3533 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3534 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3535 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3537 // copy the darkened bloom view to a texture
3538 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3539 GL_ActiveTexture(0);
3541 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
3542 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3546 void R_HDR_RenderBloomTexture(void)
3548 int oldwidth, oldheight;
3549 float oldcolorscale;
3551 oldcolorscale = r_refdef.view.colorscale;
3552 oldwidth = r_refdef.view.width;
3553 oldheight = r_refdef.view.height;
3554 r_refdef.view.width = r_bloomstate.bloomwidth;
3555 r_refdef.view.height = r_bloomstate.bloomheight;
3557 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3558 // TODO: add exposure compensation features
3559 // TODO: add fp16 framebuffer support
3561 r_refdef.view.showdebug = false;
3562 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3564 R_ResetViewRendering3D();
3566 R_ClearScreen(r_refdef.fogenabled);
3567 if (r_timereport_active)
3568 R_TimeReport("HDRclear");
3571 if (r_timereport_active)
3572 R_TimeReport("visibility");
3574 r_waterstate.numwaterplanes = 0;
3575 if (r_waterstate.enabled)
3576 R_RenderWaterPlanes();
3578 r_refdef.view.showdebug = true;
3580 r_waterstate.numwaterplanes = 0;
3582 R_ResetViewRendering2D();
3584 R_Bloom_CopyHDRTexture();
3585 R_Bloom_MakeTexture();
3587 // restore the view settings
3588 r_refdef.view.width = oldwidth;
3589 r_refdef.view.height = oldheight;
3590 r_refdef.view.colorscale = oldcolorscale;
3592 R_ResetViewRendering3D();
3594 R_ClearScreen(r_refdef.fogenabled);
3595 if (r_timereport_active)
3596 R_TimeReport("viewclear");
3599 static void R_BlendView(void)
3601 if (r_bloomstate.texture_screen)
3603 // make sure the buffer is available
3604 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
3606 R_ResetViewRendering2D();
3607 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3608 R_Mesh_ColorPointer(NULL, 0, 0);
3609 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3610 GL_ActiveTexture(0);CHECKGLERROR
3612 if(r_motionblur.value > 0 || r_damageblur.value > 0)
3614 // declare alpha variable
3617 static float avgspeed;
3619 speed = VectorLength(cl.movement_velocity);
3621 a = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vtime.value), 1);
3622 avgspeed = avgspeed * (1 - a) + speed * a;
3624 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
3625 speed = bound(0, speed, 1);
3626 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
3628 // calculate values into a standard alpha
3631 (r_motionblur.value * speed / 80)
3633 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
3636 max(0.0001, cl.time - cl.oldtime) // fps independent
3639 a *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
3640 a = bound(0, a, r_motionblur_maxblur.value);
3642 // developer debug of current value
3643 if (r_motionblur_debug.value) { Con_Printf("blur alpha = %f\n", a); }
3648 R_SetupGenericShader(true);
3649 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3650 GL_Color(1, 1, 1, a); // to do: add color changing support for damage blur
3651 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3652 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3653 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3654 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3658 // copy view into the screen texture
3659 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
3660 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3663 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3665 unsigned int permutation =
3666 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3667 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3668 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3669 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
3670 | (r_glsl_saturation.value != 1 ? SHADERPERMUTATION_SATURATION : 0);
3672 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3674 // render simple bloom effect
3675 // copy the screen and shrink it and darken it for the bloom process
3676 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3677 // make the bloom texture
3678 R_Bloom_MakeTexture();
3681 R_ResetViewRendering2D();
3682 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3683 R_Mesh_ColorPointer(NULL, 0, 0);
3684 GL_Color(1, 1, 1, 1);
3685 GL_BlendFunc(GL_ONE, GL_ZERO);
3686 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3687 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3688 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3689 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3690 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3691 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3692 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3693 if (r_glsl_permutation->loc_TintColor >= 0)
3694 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3695 if (r_glsl_permutation->loc_ClientTime >= 0)
3696 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3697 if (r_glsl_permutation->loc_PixelSize >= 0)
3698 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3699 if (r_glsl_permutation->loc_UserVec1 >= 0)
3701 float a=0, b=0, c=0, d=0;
3702 #if _MSC_VER >= 1400
3703 #define sscanf sscanf_s
3705 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3706 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3708 if (r_glsl_permutation->loc_UserVec2 >= 0)
3710 float a=0, b=0, c=0, d=0;
3711 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3712 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3714 if (r_glsl_permutation->loc_UserVec3 >= 0)
3716 float a=0, b=0, c=0, d=0;
3717 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3718 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3720 if (r_glsl_permutation->loc_UserVec4 >= 0)
3722 float a=0, b=0, c=0, d=0;
3723 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3724 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3726 if (r_glsl_permutation->loc_Saturation >= 0)
3727 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
3728 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3729 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3735 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3737 // render high dynamic range bloom effect
3738 // the bloom texture was made earlier this render, so we just need to
3739 // blend it onto the screen...
3740 R_ResetViewRendering2D();
3741 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3742 R_Mesh_ColorPointer(NULL, 0, 0);
3743 R_SetupGenericShader(true);
3744 GL_Color(1, 1, 1, 1);
3745 GL_BlendFunc(GL_ONE, GL_ONE);
3746 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3747 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3748 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3749 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3751 else if (r_bloomstate.texture_bloom)
3753 // render simple bloom effect
3754 // copy the screen and shrink it and darken it for the bloom process
3755 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3756 // make the bloom texture
3757 R_Bloom_MakeTexture();
3758 // put the original screen image back in place and blend the bloom
3760 R_ResetViewRendering2D();
3761 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3762 R_Mesh_ColorPointer(NULL, 0, 0);
3763 GL_Color(1, 1, 1, 1);
3764 GL_BlendFunc(GL_ONE, GL_ZERO);
3765 // do both in one pass if possible
3766 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3767 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3768 if (r_textureunits.integer >= 2 && gl_combine.integer)
3770 R_SetupGenericTwoTextureShader(GL_ADD);
3771 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3772 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3776 R_SetupGenericShader(true);
3777 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3778 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3779 // now blend on the bloom texture
3780 GL_BlendFunc(GL_ONE, GL_ONE);
3781 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3782 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3784 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3785 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3787 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3789 // apply a color tint to the whole view
3790 R_ResetViewRendering2D();
3791 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3792 R_Mesh_ColorPointer(NULL, 0, 0);
3793 R_SetupGenericShader(false);
3794 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3795 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3796 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3800 matrix4x4_t r_waterscrollmatrix;
3802 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3804 if (r_refdef.fog_density)
3806 r_refdef.fogcolor[0] = r_refdef.fog_red;
3807 r_refdef.fogcolor[1] = r_refdef.fog_green;
3808 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3812 VectorCopy(r_refdef.fogcolor, fogvec);
3813 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3815 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3816 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3817 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3818 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3820 // color.rgb *= ContrastBoost * SceneBrightness;
3821 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3822 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3823 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3824 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3829 void R_UpdateVariables(void)
3833 r_refdef.scene.ambient = r_ambient.value;
3835 r_refdef.farclip = 4096;
3836 if (r_refdef.scene.worldmodel)
3837 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3838 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3840 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3841 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3842 r_refdef.polygonfactor = 0;
3843 r_refdef.polygonoffset = 0;
3844 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3845 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3847 r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
3848 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3849 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3850 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3851 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3852 if (r_showsurfaces.integer)
3854 r_refdef.scene.rtworld = false;
3855 r_refdef.scene.rtworldshadows = false;
3856 r_refdef.scene.rtdlight = false;
3857 r_refdef.scene.rtdlightshadows = false;
3858 r_refdef.lightmapintensity = 0;
3861 if (gamemode == GAME_NEHAHRA)
3863 if (gl_fogenable.integer)
3865 r_refdef.oldgl_fogenable = true;
3866 r_refdef.fog_density = gl_fogdensity.value;
3867 r_refdef.fog_red = gl_fogred.value;
3868 r_refdef.fog_green = gl_foggreen.value;
3869 r_refdef.fog_blue = gl_fogblue.value;
3870 r_refdef.fog_alpha = 1;
3871 r_refdef.fog_start = 0;
3872 r_refdef.fog_end = gl_skyclip.value;
3874 else if (r_refdef.oldgl_fogenable)
3876 r_refdef.oldgl_fogenable = false;
3877 r_refdef.fog_density = 0;
3878 r_refdef.fog_red = 0;
3879 r_refdef.fog_green = 0;
3880 r_refdef.fog_blue = 0;
3881 r_refdef.fog_alpha = 0;
3882 r_refdef.fog_start = 0;
3883 r_refdef.fog_end = 0;
3887 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3888 r_refdef.fog_start = max(0, r_refdef.fog_start);
3889 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3891 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3893 if (r_refdef.fog_density && r_drawfog.integer)
3895 r_refdef.fogenabled = true;
3896 // this is the point where the fog reaches 0.9986 alpha, which we
3897 // consider a good enough cutoff point for the texture
3898 // (0.9986 * 256 == 255.6)
3899 if (r_fog_exp2.integer)
3900 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3902 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3903 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3904 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3905 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3906 // fog color was already set
3907 // update the fog texture
3908 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)
3909 R_BuildFogTexture();
3912 r_refdef.fogenabled = false;
3914 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
3916 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
3918 // build GLSL gamma texture
3919 #define RAMPWIDTH 256
3920 unsigned short ramp[RAMPWIDTH * 3];
3921 unsigned char rampbgr[RAMPWIDTH][4];
3924 r_texture_gammaramps_serial = vid_gammatables_serial;
3926 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
3927 for(i = 0; i < RAMPWIDTH; ++i)
3929 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3930 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3931 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
3934 if (r_texture_gammaramps)
3936 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
3940 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);
3946 // remove GLSL gamma texture
3950 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3951 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3957 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3958 if( scenetype != r_currentscenetype ) {
3959 // store the old scenetype
3960 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3961 r_currentscenetype = scenetype;
3962 // move in the new scene
3963 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3972 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3974 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3975 if( scenetype == r_currentscenetype ) {
3976 return &r_refdef.scene;
3978 return &r_scenes_store[ scenetype ];
3987 void R_RenderView(void)
3989 r_frame++; // used only by R_GetCurrentTexture
3990 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3992 if (r_refdef.view.isoverlay)
3994 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
3995 GL_Clear( GL_DEPTH_BUFFER_BIT );
3996 R_TimeReport("depthclear");
3998 r_refdef.view.showdebug = false;
4000 r_waterstate.enabled = false;
4001 r_waterstate.numwaterplanes = 0;
4009 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4010 return; //Host_Error ("R_RenderView: NULL worldmodel");
4012 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4014 // break apart the view matrix into vectors for various purposes
4015 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4016 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4017 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4018 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4019 // make an inverted copy of the view matrix for tracking sprites
4020 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4022 R_Shadow_UpdateWorldLightSelection();
4024 R_Bloom_StartFrame();
4025 R_Water_StartFrame();
4028 if (r_timereport_active)
4029 R_TimeReport("viewsetup");
4031 R_ResetViewRendering3D();
4033 if (r_refdef.view.clear || r_refdef.fogenabled)
4035 R_ClearScreen(r_refdef.fogenabled);
4036 if (r_timereport_active)
4037 R_TimeReport("viewclear");
4039 r_refdef.view.clear = true;
4041 // this produces a bloom texture to be used in R_BlendView() later
4043 R_HDR_RenderBloomTexture();
4045 r_refdef.view.showdebug = true;
4048 if (r_timereport_active)
4049 R_TimeReport("visibility");
4051 r_waterstate.numwaterplanes = 0;
4052 if (r_waterstate.enabled)
4053 R_RenderWaterPlanes();
4056 r_waterstate.numwaterplanes = 0;
4059 if (r_timereport_active)
4060 R_TimeReport("blendview");
4062 GL_Scissor(0, 0, vid.width, vid.height);
4063 GL_ScissorTest(false);
4067 void R_RenderWaterPlanes(void)
4069 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4071 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4072 if (r_timereport_active)
4073 R_TimeReport("waterworld");
4076 // don't let sound skip if going slow
4077 if (r_refdef.scene.extraupdate)
4080 R_DrawModelsAddWaterPlanes();
4081 if (r_timereport_active)
4082 R_TimeReport("watermodels");
4084 if (r_waterstate.numwaterplanes)
4086 R_Water_ProcessPlanes();
4087 if (r_timereport_active)
4088 R_TimeReport("waterscenes");
4092 extern void R_DrawLightningBeams (void);
4093 extern void VM_CL_AddPolygonsToMeshQueue (void);
4094 extern void R_DrawPortals (void);
4095 extern cvar_t cl_locs_show;
4096 static void R_DrawLocs(void);
4097 static void R_DrawEntityBBoxes(void);
4098 void R_RenderScene(void)
4100 r_refdef.stats.renders++;
4104 // don't let sound skip if going slow
4105 if (r_refdef.scene.extraupdate)
4108 R_MeshQueue_BeginScene();
4112 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);
4114 if (cl.csqc_vidvars.drawworld)
4116 // don't let sound skip if going slow
4117 if (r_refdef.scene.extraupdate)
4120 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4122 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4123 if (r_timereport_active)
4124 R_TimeReport("worldsky");
4127 if (R_DrawBrushModelsSky() && r_timereport_active)
4128 R_TimeReport("bmodelsky");
4131 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4133 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4134 if (r_timereport_active)
4135 R_TimeReport("worlddepth");
4137 if (r_depthfirst.integer >= 2)
4139 R_DrawModelsDepth();
4140 if (r_timereport_active)
4141 R_TimeReport("modeldepth");
4144 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4146 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4147 if (r_timereport_active)
4148 R_TimeReport("world");
4151 // don't let sound skip if going slow
4152 if (r_refdef.scene.extraupdate)
4156 if (r_timereport_active)
4157 R_TimeReport("models");
4159 // don't let sound skip if going slow
4160 if (r_refdef.scene.extraupdate)
4163 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
4165 R_DrawModelShadows();
4167 R_ResetViewRendering3D();
4169 // don't let sound skip if going slow
4170 if (r_refdef.scene.extraupdate)
4174 R_ShadowVolumeLighting(false);
4175 if (r_timereport_active)
4176 R_TimeReport("rtlights");
4178 // don't let sound skip if going slow
4179 if (r_refdef.scene.extraupdate)
4182 if (cl.csqc_vidvars.drawworld)
4184 R_DrawLightningBeams();
4185 if (r_timereport_active)
4186 R_TimeReport("lightning");
4189 if (r_timereport_active)
4190 R_TimeReport("decals");
4193 if (r_timereport_active)
4194 R_TimeReport("particles");
4197 if (r_timereport_active)
4198 R_TimeReport("explosions");
4201 R_SetupGenericShader(true);
4202 VM_CL_AddPolygonsToMeshQueue();
4204 if (r_refdef.view.showdebug)
4206 if (cl_locs_show.integer)
4209 if (r_timereport_active)
4210 R_TimeReport("showlocs");
4213 if (r_drawportals.integer)
4216 if (r_timereport_active)
4217 R_TimeReport("portals");
4220 if (r_showbboxes.value > 0)
4222 R_DrawEntityBBoxes();
4223 if (r_timereport_active)
4224 R_TimeReport("bboxes");
4228 R_SetupGenericShader(true);
4229 R_MeshQueue_RenderTransparent();
4230 if (r_timereport_active)
4231 R_TimeReport("drawtrans");
4233 R_SetupGenericShader(true);
4235 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))
4237 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4238 if (r_timereport_active)
4239 R_TimeReport("worlddebug");
4240 R_DrawModelsDebug();
4241 if (r_timereport_active)
4242 R_TimeReport("modeldebug");
4245 R_SetupGenericShader(true);
4247 if (cl.csqc_vidvars.drawworld)
4250 if (r_timereport_active)
4251 R_TimeReport("coronas");
4254 // don't let sound skip if going slow
4255 if (r_refdef.scene.extraupdate)
4258 R_ResetViewRendering2D();
4261 static const unsigned short bboxelements[36] =
4271 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4274 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4275 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4276 GL_DepthMask(false);
4277 GL_DepthRange(0, 1);
4278 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4279 R_Mesh_Matrix(&identitymatrix);
4280 R_Mesh_ResetTextureState();
4282 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4283 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4284 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4285 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4286 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4287 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4288 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4289 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4290 R_FillColors(color4f, 8, cr, cg, cb, ca);
4291 if (r_refdef.fogenabled)
4293 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4295 f1 = FogPoint_World(v);
4297 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4298 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4299 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4302 R_Mesh_VertexPointer(vertex3f, 0, 0);
4303 R_Mesh_ColorPointer(color4f, 0, 0);
4304 R_Mesh_ResetTextureState();
4305 R_SetupGenericShader(false);
4306 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4309 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4313 prvm_edict_t *edict;
4314 prvm_prog_t *prog_save = prog;
4316 // this function draws bounding boxes of server entities
4320 GL_CullFace(GL_NONE);
4321 R_SetupGenericShader(false);
4325 for (i = 0;i < numsurfaces;i++)
4327 edict = PRVM_EDICT_NUM(surfacelist[i]);
4328 switch ((int)edict->fields.server->solid)
4330 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4331 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4332 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4333 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4334 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4335 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4337 color[3] *= r_showbboxes.value;
4338 color[3] = bound(0, color[3], 1);
4339 GL_DepthTest(!r_showdisabledepthtest.integer);
4340 GL_CullFace(r_refdef.view.cullface_front);
4341 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4347 static void R_DrawEntityBBoxes(void)
4350 prvm_edict_t *edict;
4352 prvm_prog_t *prog_save = prog;
4354 // this function draws bounding boxes of server entities
4360 for (i = 0;i < prog->num_edicts;i++)
4362 edict = PRVM_EDICT_NUM(i);
4363 if (edict->priv.server->free)
4365 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4366 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4368 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4370 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4371 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4377 unsigned short nomodelelements[24] =
4389 float nomodelvertex3f[6*3] =
4399 float nomodelcolor4f[6*4] =
4401 0.0f, 0.0f, 0.5f, 1.0f,
4402 0.0f, 0.0f, 0.5f, 1.0f,
4403 0.0f, 0.5f, 0.0f, 1.0f,
4404 0.0f, 0.5f, 0.0f, 1.0f,
4405 0.5f, 0.0f, 0.0f, 1.0f,
4406 0.5f, 0.0f, 0.0f, 1.0f
4409 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4414 // this is only called once per entity so numsurfaces is always 1, and
4415 // surfacelist is always {0}, so this code does not handle batches
4416 R_Mesh_Matrix(&ent->matrix);
4418 if (ent->flags & EF_ADDITIVE)
4420 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4421 GL_DepthMask(false);
4423 else if (ent->alpha < 1)
4425 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4426 GL_DepthMask(false);
4430 GL_BlendFunc(GL_ONE, GL_ZERO);
4433 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4434 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4435 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4436 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4437 R_SetupGenericShader(false);
4438 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4439 if (r_refdef.fogenabled)
4442 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4443 R_Mesh_ColorPointer(color4f, 0, 0);
4444 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4445 f1 = FogPoint_World(org);
4447 for (i = 0, c = color4f;i < 6;i++, c += 4)
4449 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4450 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4451 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4455 else if (ent->alpha != 1)
4457 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4458 R_Mesh_ColorPointer(color4f, 0, 0);
4459 for (i = 0, c = color4f;i < 6;i++, c += 4)
4463 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4464 R_Mesh_ResetTextureState();
4465 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4468 void R_DrawNoModel(entity_render_t *ent)
4471 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4472 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4473 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4475 // R_DrawNoModelCallback(ent, 0);
4478 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4480 vec3_t right1, right2, diff, normal;
4482 VectorSubtract (org2, org1, normal);
4484 // calculate 'right' vector for start
4485 VectorSubtract (r_refdef.view.origin, org1, diff);
4486 CrossProduct (normal, diff, right1);
4487 VectorNormalize (right1);
4489 // calculate 'right' vector for end
4490 VectorSubtract (r_refdef.view.origin, org2, diff);
4491 CrossProduct (normal, diff, right2);
4492 VectorNormalize (right2);
4494 vert[ 0] = org1[0] + width * right1[0];
4495 vert[ 1] = org1[1] + width * right1[1];
4496 vert[ 2] = org1[2] + width * right1[2];
4497 vert[ 3] = org1[0] - width * right1[0];
4498 vert[ 4] = org1[1] - width * right1[1];
4499 vert[ 5] = org1[2] - width * right1[2];
4500 vert[ 6] = org2[0] - width * right2[0];
4501 vert[ 7] = org2[1] - width * right2[1];
4502 vert[ 8] = org2[2] - width * right2[2];
4503 vert[ 9] = org2[0] + width * right2[0];
4504 vert[10] = org2[1] + width * right2[1];
4505 vert[11] = org2[2] + width * right2[2];
4508 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4510 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)
4512 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4516 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4517 fog = FogPoint_World(origin);
4519 R_Mesh_Matrix(&identitymatrix);
4520 GL_BlendFunc(blendfunc1, blendfunc2);
4522 GL_CullFace(GL_NONE);
4524 GL_DepthMask(false);
4525 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4526 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4527 GL_DepthTest(!depthdisable);
4529 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4530 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4531 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4532 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4533 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4534 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4535 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4536 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4537 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4538 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4539 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4540 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4542 R_Mesh_VertexPointer(vertex3f, 0, 0);
4543 R_Mesh_ColorPointer(NULL, 0, 0);
4544 R_Mesh_ResetTextureState();
4545 R_SetupGenericShader(true);
4546 R_Mesh_TexBind(0, R_GetTexture(texture));
4547 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4548 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4549 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4550 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4552 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4554 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4555 GL_BlendFunc(blendfunc1, GL_ONE);
4557 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4558 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4562 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4567 VectorSet(v, x, y, z);
4568 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4569 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4571 if (i == mesh->numvertices)
4573 if (mesh->numvertices < mesh->maxvertices)
4575 VectorCopy(v, vertex3f);
4576 mesh->numvertices++;
4578 return mesh->numvertices;
4584 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4588 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4589 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4590 e = mesh->element3i + mesh->numtriangles * 3;
4591 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4593 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4594 if (mesh->numtriangles < mesh->maxtriangles)
4599 mesh->numtriangles++;
4601 element[1] = element[2];
4605 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4609 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4610 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4611 e = mesh->element3i + mesh->numtriangles * 3;
4612 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4614 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4615 if (mesh->numtriangles < mesh->maxtriangles)
4620 mesh->numtriangles++;
4622 element[1] = element[2];
4626 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4627 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4629 int planenum, planenum2;
4632 mplane_t *plane, *plane2;
4634 double temppoints[2][256*3];
4635 // figure out how large a bounding box we need to properly compute this brush
4637 for (w = 0;w < numplanes;w++)
4638 maxdist = max(maxdist, planes[w].dist);
4639 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4640 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4641 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4645 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4646 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4648 if (planenum2 == planenum)
4650 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);
4653 if (tempnumpoints < 3)
4655 // generate elements forming a triangle fan for this polygon
4656 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4660 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)
4662 texturelayer_t *layer;
4663 layer = t->currentlayers + t->currentnumlayers++;
4665 layer->depthmask = depthmask;
4666 layer->blendfunc1 = blendfunc1;
4667 layer->blendfunc2 = blendfunc2;
4668 layer->texture = texture;
4669 layer->texmatrix = *matrix;
4670 layer->color[0] = r * r_refdef.view.colorscale;
4671 layer->color[1] = g * r_refdef.view.colorscale;
4672 layer->color[2] = b * r_refdef.view.colorscale;
4673 layer->color[3] = a;
4676 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4679 index = parms[2] + r_refdef.scene.time * parms[3];
4680 index -= floor(index);
4684 case Q3WAVEFUNC_NONE:
4685 case Q3WAVEFUNC_NOISE:
4686 case Q3WAVEFUNC_COUNT:
4689 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4690 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4691 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4692 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4693 case Q3WAVEFUNC_TRIANGLE:
4695 f = index - floor(index);
4706 return (float)(parms[0] + parms[1] * f);
4709 texture_t *R_GetCurrentTexture(texture_t *t)
4713 const entity_render_t *ent = rsurface.entity;
4714 dp_model_t *model = ent->model;
4717 q3shaderinfo_layer_tcmod_t *tcmod;
4719 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
4720 return t->currentframe;
4721 t->update_lastrenderframe = r_frame;
4722 t->update_lastrenderentity = (void *)ent;
4724 // switch to an alternate material if this is a q1bsp animated material
4726 texture_t *texture = t;
4727 int s = ent->skinnum;
4728 if ((unsigned int)s >= (unsigned int)model->numskins)
4730 if (model->skinscenes)
4732 if (model->skinscenes[s].framecount > 1)
4733 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4735 s = model->skinscenes[s].firstframe;
4738 t = t + s * model->num_surfaces;
4741 // use an alternate animation if the entity's frame is not 0,
4742 // and only if the texture has an alternate animation
4743 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
4744 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4746 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4748 texture->currentframe = t;
4751 // update currentskinframe to be a qw skin or animation frame
4752 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"))
4754 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4756 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4757 if (developer_loading.integer)
4758 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4759 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);
4761 t->currentskinframe = r_qwskincache_skinframe[i];
4762 if (t->currentskinframe == NULL)
4763 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4765 else if (t->numskinframes >= 2)
4766 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4767 if (t->backgroundnumskinframes >= 2)
4768 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
4770 t->currentmaterialflags = t->basematerialflags;
4771 t->currentalpha = ent->alpha;
4772 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4773 t->currentalpha *= r_wateralpha.value;
4774 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4775 t->currentalpha *= t->r_water_wateralpha;
4776 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4777 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4778 if (!(ent->flags & RENDER_LIGHT))
4779 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4780 else if (rsurface.modeltexcoordlightmap2f == NULL)
4782 // pick a model lighting mode
4783 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4784 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4786 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4788 if (ent->effects & EF_ADDITIVE)
4789 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4790 else if (t->currentalpha < 1)
4791 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4792 if (ent->effects & EF_DOUBLESIDED)
4793 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4794 if (ent->effects & EF_NODEPTHTEST)
4795 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4796 if (ent->flags & RENDER_VIEWMODEL)
4797 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4798 if (t->backgroundnumskinframes)
4799 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4800 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4802 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4803 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4806 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4808 // there is no tcmod
4809 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4810 t->currenttexmatrix = r_waterscrollmatrix;
4812 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4815 switch(tcmod->tcmod)
4819 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4820 matrix = r_waterscrollmatrix;
4822 matrix = identitymatrix;
4824 case Q3TCMOD_ENTITYTRANSLATE:
4825 // this is used in Q3 to allow the gamecode to control texcoord
4826 // scrolling on the entity, which is not supported in darkplaces yet.
4827 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4829 case Q3TCMOD_ROTATE:
4830 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4831 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4832 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4835 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4837 case Q3TCMOD_SCROLL:
4838 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4840 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4841 w = (int) tcmod->parms[0];
4842 h = (int) tcmod->parms[1];
4843 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4845 idx = (int) floor(f * w * h);
4846 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4848 case Q3TCMOD_STRETCH:
4849 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4850 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4852 case Q3TCMOD_TRANSFORM:
4853 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4854 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4855 VectorSet(tcmat + 6, 0 , 0 , 1);
4856 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4857 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4859 case Q3TCMOD_TURBULENT:
4860 // this is handled in the RSurf_PrepareVertices function
4861 matrix = identitymatrix;
4864 // either replace or concatenate the transformation
4866 t->currenttexmatrix = matrix;
4869 matrix4x4_t temp = t->currenttexmatrix;
4870 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4874 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4875 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4876 t->glosstexture = r_texture_black;
4877 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4878 t->backgroundglosstexture = r_texture_black;
4879 t->specularpower = r_shadow_glossexponent.value;
4880 // TODO: store reference values for these in the texture?
4881 t->specularscale = 0;
4882 if (r_shadow_gloss.integer > 0)
4884 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4886 if (r_shadow_glossintensity.value > 0)
4888 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4889 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4890 t->specularscale = r_shadow_glossintensity.value;
4893 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4895 t->glosstexture = r_texture_white;
4896 t->backgroundglosstexture = r_texture_white;
4897 t->specularscale = r_shadow_gloss2intensity.value;
4901 // lightmaps mode looks bad with dlights using actual texturing, so turn
4902 // off the colormap and glossmap, but leave the normalmap on as it still
4903 // accurately represents the shading involved
4904 if (gl_lightmaps.integer)
4906 t->basetexture = r_texture_grey128;
4907 t->backgroundbasetexture = NULL;
4908 t->specularscale = 0;
4909 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
4912 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4913 VectorClear(t->dlightcolor);
4914 t->currentnumlayers = 0;
4915 if (t->currentmaterialflags & MATERIALFLAG_WALL)
4918 int blendfunc1, blendfunc2, depthmask;
4919 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4921 blendfunc1 = GL_SRC_ALPHA;
4922 blendfunc2 = GL_ONE;
4924 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4926 blendfunc1 = GL_SRC_ALPHA;
4927 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4929 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4931 blendfunc1 = t->customblendfunc[0];
4932 blendfunc2 = t->customblendfunc[1];
4936 blendfunc1 = GL_ONE;
4937 blendfunc2 = GL_ZERO;
4939 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4940 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4941 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4942 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4944 // fullbright is not affected by r_refdef.lightmapintensity
4945 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]);
4946 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4947 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]);
4948 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4949 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]);
4953 vec3_t ambientcolor;
4955 // set the color tint used for lights affecting this surface
4956 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4958 // q3bsp has no lightmap updates, so the lightstylevalue that
4959 // would normally be baked into the lightmap must be
4960 // applied to the color
4961 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4962 if (ent->model->type == mod_brushq3)
4963 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4964 colorscale *= r_refdef.lightmapintensity;
4965 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
4966 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4967 // basic lit geometry
4968 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]);
4969 // add pants/shirt if needed
4970 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4971 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]);
4972 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4973 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]);
4974 // now add ambient passes if needed
4975 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4977 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]);
4978 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4979 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]);
4980 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4981 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]);
4984 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4985 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]);
4986 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4988 // if this is opaque use alpha blend which will darken the earlier
4991 // if this is an alpha blended material, all the earlier passes
4992 // were darkened by fog already, so we only need to add the fog
4993 // color ontop through the fog mask texture
4995 // if this is an additive blended material, all the earlier passes
4996 // were darkened by fog already, and we should not add fog color
4997 // (because the background was not darkened, there is no fog color
4998 // that was lost behind it).
4999 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]);
5003 return t->currentframe;
5006 rsurfacestate_t rsurface;
5008 void R_Mesh_ResizeArrays(int newvertices)
5011 if (rsurface.array_size >= newvertices)
5013 if (rsurface.array_modelvertex3f)
5014 Mem_Free(rsurface.array_modelvertex3f);
5015 rsurface.array_size = (newvertices + 1023) & ~1023;
5016 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5017 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5018 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5019 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5020 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5021 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5022 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5023 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5024 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5025 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5026 rsurface.array_color4f = base + rsurface.array_size * 27;
5027 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5030 void RSurf_ActiveWorldEntity(void)
5032 dp_model_t *model = r_refdef.scene.worldmodel;
5033 //if (rsurface.entity == r_refdef.scene.worldentity)
5035 rsurface.entity = r_refdef.scene.worldentity;
5036 if (rsurface.array_size < model->surfmesh.num_vertices)
5037 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5038 rsurface.matrix = identitymatrix;
5039 rsurface.inversematrix = identitymatrix;
5040 R_Mesh_Matrix(&identitymatrix);
5041 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5042 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5043 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5044 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5045 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5046 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5047 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5048 rsurface.frameblend[0].lerp = 1;
5049 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5050 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5051 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5052 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5053 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5054 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5055 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5056 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5057 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5058 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5059 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5060 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5061 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5062 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5063 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5064 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5065 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5066 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5067 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5068 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5069 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5070 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5071 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5072 rsurface.modelelement3i = model->surfmesh.data_element3i;
5073 rsurface.modelelement3s = model->surfmesh.data_element3s;
5074 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5075 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5076 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5077 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5078 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5079 rsurface.modelsurfaces = model->data_surfaces;
5080 rsurface.generatedvertex = false;
5081 rsurface.vertex3f = rsurface.modelvertex3f;
5082 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5083 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5084 rsurface.svector3f = rsurface.modelsvector3f;
5085 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5086 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5087 rsurface.tvector3f = rsurface.modeltvector3f;
5088 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5089 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5090 rsurface.normal3f = rsurface.modelnormal3f;
5091 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5092 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5093 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5096 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5098 dp_model_t *model = ent->model;
5099 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5101 rsurface.entity = (entity_render_t *)ent;
5102 if (rsurface.array_size < model->surfmesh.num_vertices)
5103 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5104 rsurface.matrix = ent->matrix;
5105 rsurface.inversematrix = ent->inversematrix;
5106 R_Mesh_Matrix(&rsurface.matrix);
5107 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5108 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5109 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5110 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5111 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5112 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5113 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5114 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5115 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5116 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5117 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5118 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5119 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5120 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5121 if (ent->model->brush.submodel)
5123 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5124 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5126 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5130 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5131 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5132 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5133 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5134 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5136 else if (wantnormals)
5138 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5139 rsurface.modelsvector3f = NULL;
5140 rsurface.modeltvector3f = NULL;
5141 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5142 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5146 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5147 rsurface.modelsvector3f = NULL;
5148 rsurface.modeltvector3f = NULL;
5149 rsurface.modelnormal3f = NULL;
5150 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5152 rsurface.modelvertex3f_bufferobject = 0;
5153 rsurface.modelvertex3f_bufferoffset = 0;
5154 rsurface.modelsvector3f_bufferobject = 0;
5155 rsurface.modelsvector3f_bufferoffset = 0;
5156 rsurface.modeltvector3f_bufferobject = 0;
5157 rsurface.modeltvector3f_bufferoffset = 0;
5158 rsurface.modelnormal3f_bufferobject = 0;
5159 rsurface.modelnormal3f_bufferoffset = 0;
5160 rsurface.generatedvertex = true;
5164 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5165 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5166 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5167 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5168 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5169 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5170 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5171 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5172 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5173 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5174 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5175 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5176 rsurface.generatedvertex = false;
5178 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5179 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5180 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5181 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5182 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5183 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5184 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5185 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5186 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5187 rsurface.modelelement3i = model->surfmesh.data_element3i;
5188 rsurface.modelelement3s = model->surfmesh.data_element3s;
5189 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5190 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5191 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5192 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5193 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5194 rsurface.modelsurfaces = model->data_surfaces;
5195 rsurface.vertex3f = rsurface.modelvertex3f;
5196 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5197 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5198 rsurface.svector3f = rsurface.modelsvector3f;
5199 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5200 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5201 rsurface.tvector3f = rsurface.modeltvector3f;
5202 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5203 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5204 rsurface.normal3f = rsurface.modelnormal3f;
5205 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5206 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5207 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5210 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5211 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5214 int texturesurfaceindex;
5219 const float *v1, *in_tc;
5221 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5223 q3shaderinfo_deform_t *deform;
5224 // 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
5225 if (rsurface.generatedvertex)
5227 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5228 generatenormals = true;
5229 for (i = 0;i < Q3MAXDEFORMS;i++)
5231 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5233 generatetangents = true;
5234 generatenormals = true;
5236 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5237 generatenormals = true;
5239 if (generatenormals && !rsurface.modelnormal3f)
5241 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5242 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5243 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5244 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5246 if (generatetangents && !rsurface.modelsvector3f)
5248 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5249 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5250 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5251 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5252 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5253 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5254 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);
5257 rsurface.vertex3f = rsurface.modelvertex3f;
5258 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5259 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5260 rsurface.svector3f = rsurface.modelsvector3f;
5261 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5262 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5263 rsurface.tvector3f = rsurface.modeltvector3f;
5264 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5265 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5266 rsurface.normal3f = rsurface.modelnormal3f;
5267 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5268 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5269 // if vertices are deformed (sprite flares and things in maps, possibly
5270 // water waves, bulges and other deformations), generate them into
5271 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5272 // (may be static model data or generated data for an animated model, or
5273 // the previous deform pass)
5274 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5276 switch (deform->deform)
5279 case Q3DEFORM_PROJECTIONSHADOW:
5280 case Q3DEFORM_TEXT0:
5281 case Q3DEFORM_TEXT1:
5282 case Q3DEFORM_TEXT2:
5283 case Q3DEFORM_TEXT3:
5284 case Q3DEFORM_TEXT4:
5285 case Q3DEFORM_TEXT5:
5286 case Q3DEFORM_TEXT6:
5287 case Q3DEFORM_TEXT7:
5290 case Q3DEFORM_AUTOSPRITE:
5291 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5292 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5293 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5294 VectorNormalize(newforward);
5295 VectorNormalize(newright);
5296 VectorNormalize(newup);
5297 // make deformed versions of only the model vertices used by the specified surfaces
5298 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5300 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5301 // a single autosprite surface can contain multiple sprites...
5302 for (j = 0;j < surface->num_vertices - 3;j += 4)
5304 VectorClear(center);
5305 for (i = 0;i < 4;i++)
5306 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5307 VectorScale(center, 0.25f, center);
5308 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5309 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5310 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5311 for (i = 0;i < 4;i++)
5313 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5314 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5317 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);
5318 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);
5320 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5321 rsurface.vertex3f_bufferobject = 0;
5322 rsurface.vertex3f_bufferoffset = 0;
5323 rsurface.svector3f = rsurface.array_deformedsvector3f;
5324 rsurface.svector3f_bufferobject = 0;
5325 rsurface.svector3f_bufferoffset = 0;
5326 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5327 rsurface.tvector3f_bufferobject = 0;
5328 rsurface.tvector3f_bufferoffset = 0;
5329 rsurface.normal3f = rsurface.array_deformednormal3f;
5330 rsurface.normal3f_bufferobject = 0;
5331 rsurface.normal3f_bufferoffset = 0;
5333 case Q3DEFORM_AUTOSPRITE2:
5334 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5335 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5336 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5337 VectorNormalize(newforward);
5338 VectorNormalize(newright);
5339 VectorNormalize(newup);
5340 // make deformed versions of only the model vertices used by the specified surfaces
5341 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5343 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5344 const float *v1, *v2;
5354 memset(shortest, 0, sizeof(shortest));
5355 // a single autosprite surface can contain multiple sprites...
5356 for (j = 0;j < surface->num_vertices - 3;j += 4)
5358 VectorClear(center);
5359 for (i = 0;i < 4;i++)
5360 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5361 VectorScale(center, 0.25f, center);
5362 // find the two shortest edges, then use them to define the
5363 // axis vectors for rotating around the central axis
5364 for (i = 0;i < 6;i++)
5366 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5367 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5369 Debug_PolygonBegin(NULL, 0);
5370 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5371 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);
5372 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5375 l = VectorDistance2(v1, v2);
5376 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5378 l += (1.0f / 1024.0f);
5379 if (shortest[0].length2 > l || i == 0)
5381 shortest[1] = shortest[0];
5382 shortest[0].length2 = l;
5383 shortest[0].v1 = v1;
5384 shortest[0].v2 = v2;
5386 else if (shortest[1].length2 > l || i == 1)
5388 shortest[1].length2 = l;
5389 shortest[1].v1 = v1;
5390 shortest[1].v2 = v2;
5393 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5394 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5396 Debug_PolygonBegin(NULL, 0);
5397 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5398 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);
5399 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5402 // this calculates the right vector from the shortest edge
5403 // and the up vector from the edge midpoints
5404 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5405 VectorNormalize(right);
5406 VectorSubtract(end, start, up);
5407 VectorNormalize(up);
5408 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5409 //VectorSubtract(rsurface.modelorg, center, forward);
5410 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5411 VectorNegate(forward, forward);
5412 VectorReflect(forward, 0, up, forward);
5413 VectorNormalize(forward);
5414 CrossProduct(up, forward, newright);
5415 VectorNormalize(newright);
5417 Debug_PolygonBegin(NULL, 0);
5418 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);
5419 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5420 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5424 Debug_PolygonBegin(NULL, 0);
5425 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5426 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5427 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5430 // rotate the quad around the up axis vector, this is made
5431 // especially easy by the fact we know the quad is flat,
5432 // so we only have to subtract the center position and
5433 // measure distance along the right vector, and then
5434 // multiply that by the newright vector and add back the
5436 // we also need to subtract the old position to undo the
5437 // displacement from the center, which we do with a
5438 // DotProduct, the subtraction/addition of center is also
5439 // optimized into DotProducts here
5440 l = DotProduct(right, center);
5441 for (i = 0;i < 4;i++)
5443 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5444 f = DotProduct(right, v1) - l;
5445 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5448 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);
5449 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);
5451 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5452 rsurface.vertex3f_bufferobject = 0;
5453 rsurface.vertex3f_bufferoffset = 0;
5454 rsurface.svector3f = rsurface.array_deformedsvector3f;
5455 rsurface.svector3f_bufferobject = 0;
5456 rsurface.svector3f_bufferoffset = 0;
5457 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5458 rsurface.tvector3f_bufferobject = 0;
5459 rsurface.tvector3f_bufferoffset = 0;
5460 rsurface.normal3f = rsurface.array_deformednormal3f;
5461 rsurface.normal3f_bufferobject = 0;
5462 rsurface.normal3f_bufferoffset = 0;
5464 case Q3DEFORM_NORMAL:
5465 // deform the normals to make reflections wavey
5466 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5468 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5469 for (j = 0;j < surface->num_vertices;j++)
5472 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5473 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5474 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5475 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5476 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5477 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5478 VectorNormalize(normal);
5480 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);
5482 rsurface.svector3f = rsurface.array_deformedsvector3f;
5483 rsurface.svector3f_bufferobject = 0;
5484 rsurface.svector3f_bufferoffset = 0;
5485 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5486 rsurface.tvector3f_bufferobject = 0;
5487 rsurface.tvector3f_bufferoffset = 0;
5488 rsurface.normal3f = rsurface.array_deformednormal3f;
5489 rsurface.normal3f_bufferobject = 0;
5490 rsurface.normal3f_bufferoffset = 0;
5493 // deform vertex array to make wavey water and flags and such
5494 waveparms[0] = deform->waveparms[0];
5495 waveparms[1] = deform->waveparms[1];
5496 waveparms[2] = deform->waveparms[2];
5497 waveparms[3] = deform->waveparms[3];
5498 // this is how a divisor of vertex influence on deformation
5499 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5500 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5501 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5503 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5504 for (j = 0;j < surface->num_vertices;j++)
5506 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5507 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5508 // if the wavefunc depends on time, evaluate it per-vertex
5511 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5512 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5514 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5517 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5518 rsurface.vertex3f_bufferobject = 0;
5519 rsurface.vertex3f_bufferoffset = 0;
5521 case Q3DEFORM_BULGE:
5522 // deform vertex array to make the surface have moving bulges
5523 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5525 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5526 for (j = 0;j < surface->num_vertices;j++)
5528 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5529 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5532 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5533 rsurface.vertex3f_bufferobject = 0;
5534 rsurface.vertex3f_bufferoffset = 0;
5537 // deform vertex array
5538 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5539 VectorScale(deform->parms, scale, waveparms);
5540 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5542 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5543 for (j = 0;j < surface->num_vertices;j++)
5544 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5546 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5547 rsurface.vertex3f_bufferobject = 0;
5548 rsurface.vertex3f_bufferoffset = 0;
5552 // generate texcoords based on the chosen texcoord source
5553 switch(rsurface.texture->tcgen.tcgen)
5556 case Q3TCGEN_TEXTURE:
5557 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5558 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5559 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5561 case Q3TCGEN_LIGHTMAP:
5562 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5563 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5564 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5566 case Q3TCGEN_VECTOR:
5567 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5569 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5570 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)
5572 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5573 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5576 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5577 rsurface.texcoordtexture2f_bufferobject = 0;
5578 rsurface.texcoordtexture2f_bufferoffset = 0;
5580 case Q3TCGEN_ENVIRONMENT:
5581 // make environment reflections using a spheremap
5582 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5584 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5585 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5586 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5587 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5588 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5590 // identical to Q3A's method, but executed in worldspace so
5591 // carried models can be shiny too
5593 float viewer[3], d, reflected[3], worldreflected[3];
5595 VectorSubtract(rsurface.modelorg, vertex, viewer);
5596 // VectorNormalize(viewer);
5598 d = DotProduct(normal, viewer);
5600 reflected[0] = normal[0]*2*d - viewer[0];
5601 reflected[1] = normal[1]*2*d - viewer[1];
5602 reflected[2] = normal[2]*2*d - viewer[2];
5603 // note: this is proportinal to viewer, so we can normalize later
5605 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
5606 VectorNormalize(worldreflected);
5608 // note: this sphere map only uses world x and z!
5609 // so positive and negative y will LOOK THE SAME.
5610 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
5611 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
5614 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5615 rsurface.texcoordtexture2f_bufferobject = 0;
5616 rsurface.texcoordtexture2f_bufferoffset = 0;
5619 // the only tcmod that needs software vertex processing is turbulent, so
5620 // check for it here and apply the changes if needed
5621 // and we only support that as the first one
5622 // (handling a mixture of turbulent and other tcmods would be problematic
5623 // without punting it entirely to a software path)
5624 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5626 amplitude = rsurface.texture->tcmods[0].parms[1];
5627 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5628 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5630 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5631 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)
5633 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5634 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5637 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5638 rsurface.texcoordtexture2f_bufferobject = 0;
5639 rsurface.texcoordtexture2f_bufferoffset = 0;
5641 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5642 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5643 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5644 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5647 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5650 const msurface_t *surface = texturesurfacelist[0];
5651 const msurface_t *surface2;
5656 // TODO: lock all array ranges before render, rather than on each surface
5657 if (texturenumsurfaces == 1)
5659 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5660 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);
5662 else if (r_batchmode.integer == 2)
5664 #define MAXBATCHTRIANGLES 4096
5665 int batchtriangles = 0;
5666 int batchelements[MAXBATCHTRIANGLES*3];
5667 for (i = 0;i < texturenumsurfaces;i = j)
5669 surface = texturesurfacelist[i];
5671 if (surface->num_triangles > MAXBATCHTRIANGLES)
5673 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);
5676 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5677 batchtriangles = surface->num_triangles;
5678 firstvertex = surface->num_firstvertex;
5679 endvertex = surface->num_firstvertex + surface->num_vertices;
5680 for (;j < texturenumsurfaces;j++)
5682 surface2 = texturesurfacelist[j];
5683 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5685 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5686 batchtriangles += surface2->num_triangles;
5687 firstvertex = min(firstvertex, surface2->num_firstvertex);
5688 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5690 surface2 = texturesurfacelist[j-1];
5691 numvertices = endvertex - firstvertex;
5692 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5695 else if (r_batchmode.integer == 1)
5697 for (i = 0;i < texturenumsurfaces;i = j)
5699 surface = texturesurfacelist[i];
5700 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5701 if (texturesurfacelist[j] != surface2)
5703 surface2 = texturesurfacelist[j-1];
5704 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5705 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5706 GL_LockArrays(surface->num_firstvertex, numvertices);
5707 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5712 for (i = 0;i < texturenumsurfaces;i++)
5714 surface = texturesurfacelist[i];
5715 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5716 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);
5721 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5723 int i, planeindex, vertexindex;
5727 r_waterstate_waterplane_t *p, *bestp;
5728 msurface_t *surface;
5729 if (r_waterstate.renderingscene)
5731 for (i = 0;i < texturenumsurfaces;i++)
5733 surface = texturesurfacelist[i];
5734 if (lightmaptexunit >= 0)
5735 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5736 if (deluxemaptexunit >= 0)
5737 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5738 // pick the closest matching water plane
5741 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5744 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5746 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5747 d += fabs(PlaneDiff(vert, &p->plane));
5749 if (bestd > d || !bestp)
5757 if (refractiontexunit >= 0)
5758 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5759 if (reflectiontexunit >= 0)
5760 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5764 if (refractiontexunit >= 0)
5765 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5766 if (reflectiontexunit >= 0)
5767 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5769 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5770 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);
5774 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5778 const msurface_t *surface = texturesurfacelist[0];
5779 const msurface_t *surface2;
5784 // TODO: lock all array ranges before render, rather than on each surface
5785 if (texturenumsurfaces == 1)
5787 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5788 if (deluxemaptexunit >= 0)
5789 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5790 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5791 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);
5793 else if (r_batchmode.integer == 2)
5795 #define MAXBATCHTRIANGLES 4096
5796 int batchtriangles = 0;
5797 int batchelements[MAXBATCHTRIANGLES*3];
5798 for (i = 0;i < texturenumsurfaces;i = j)
5800 surface = texturesurfacelist[i];
5801 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5802 if (deluxemaptexunit >= 0)
5803 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5805 if (surface->num_triangles > MAXBATCHTRIANGLES)
5807 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);
5810 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5811 batchtriangles = surface->num_triangles;
5812 firstvertex = surface->num_firstvertex;
5813 endvertex = surface->num_firstvertex + surface->num_vertices;
5814 for (;j < texturenumsurfaces;j++)
5816 surface2 = texturesurfacelist[j];
5817 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5819 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5820 batchtriangles += surface2->num_triangles;
5821 firstvertex = min(firstvertex, surface2->num_firstvertex);
5822 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5824 surface2 = texturesurfacelist[j-1];
5825 numvertices = endvertex - firstvertex;
5826 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5829 else if (r_batchmode.integer == 1)
5832 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5833 for (i = 0;i < texturenumsurfaces;i = j)
5835 surface = texturesurfacelist[i];
5836 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5837 if (texturesurfacelist[j] != surface2)
5839 Con_Printf(" %i", j - i);
5842 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5844 for (i = 0;i < texturenumsurfaces;i = j)
5846 surface = texturesurfacelist[i];
5847 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5848 if (deluxemaptexunit >= 0)
5849 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5850 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5851 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5854 Con_Printf(" %i", j - i);
5856 surface2 = texturesurfacelist[j-1];
5857 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5858 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5859 GL_LockArrays(surface->num_firstvertex, numvertices);
5860 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5868 for (i = 0;i < texturenumsurfaces;i++)
5870 surface = texturesurfacelist[i];
5871 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5872 if (deluxemaptexunit >= 0)
5873 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5874 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5875 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);
5880 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5883 int texturesurfaceindex;
5884 if (r_showsurfaces.integer == 2)
5886 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5888 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5889 for (j = 0;j < surface->num_triangles;j++)
5891 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5892 GL_Color(f, f, f, 1);
5893 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5899 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5901 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5902 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5903 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);
5904 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5905 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);
5910 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
5912 int texturesurfaceindex;
5915 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5917 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5918 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)
5926 rsurface.lightmapcolor4f = rsurface.array_color4f;
5927 rsurface.lightmapcolor4f_bufferobject = 0;
5928 rsurface.lightmapcolor4f_bufferoffset = 0;
5931 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5933 int texturesurfaceindex;
5937 if (rsurface.lightmapcolor4f)
5939 // generate color arrays for the surfaces in this list
5940 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5942 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5943 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)
5945 f = FogPoint_Model(v);
5955 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5957 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5958 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)
5960 f = FogPoint_Model(v);
5968 rsurface.lightmapcolor4f = rsurface.array_color4f;
5969 rsurface.lightmapcolor4f_bufferobject = 0;
5970 rsurface.lightmapcolor4f_bufferoffset = 0;
5973 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
5975 int texturesurfaceindex;
5979 if (!rsurface.lightmapcolor4f)
5981 // generate color arrays for the surfaces in this list
5982 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5984 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5985 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)
5987 f = FogPoint_Model(v);
5988 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
5989 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
5990 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
5994 rsurface.lightmapcolor4f = rsurface.array_color4f;
5995 rsurface.lightmapcolor4f_bufferobject = 0;
5996 rsurface.lightmapcolor4f_bufferoffset = 0;
5999 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6001 int texturesurfaceindex;
6004 if (!rsurface.lightmapcolor4f)
6006 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6008 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6009 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)
6017 rsurface.lightmapcolor4f = rsurface.array_color4f;
6018 rsurface.lightmapcolor4f_bufferobject = 0;
6019 rsurface.lightmapcolor4f_bufferoffset = 0;
6022 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6024 int texturesurfaceindex;
6027 if (!rsurface.lightmapcolor4f)
6029 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6031 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6032 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)
6034 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6035 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6036 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6040 rsurface.lightmapcolor4f = rsurface.array_color4f;
6041 rsurface.lightmapcolor4f_bufferobject = 0;
6042 rsurface.lightmapcolor4f_bufferoffset = 0;
6045 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6048 rsurface.lightmapcolor4f = NULL;
6049 rsurface.lightmapcolor4f_bufferobject = 0;
6050 rsurface.lightmapcolor4f_bufferoffset = 0;
6051 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6052 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6053 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6054 GL_Color(r, g, b, a);
6055 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6058 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6060 // TODO: optimize applyfog && applycolor case
6061 // just apply fog if necessary, and tint the fog color array if necessary
6062 rsurface.lightmapcolor4f = NULL;
6063 rsurface.lightmapcolor4f_bufferobject = 0;
6064 rsurface.lightmapcolor4f_bufferoffset = 0;
6065 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6066 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6067 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6068 GL_Color(r, g, b, a);
6069 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6072 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6074 int texturesurfaceindex;
6078 if (texturesurfacelist[0]->lightmapinfo)
6080 // generate color arrays for the surfaces in this list
6081 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6083 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6084 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6086 if (surface->lightmapinfo->samples)
6088 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6089 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6090 VectorScale(lm, scale, c);
6091 if (surface->lightmapinfo->styles[1] != 255)
6093 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6095 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6096 VectorMA(c, scale, lm, c);
6097 if (surface->lightmapinfo->styles[2] != 255)
6100 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6101 VectorMA(c, scale, lm, c);
6102 if (surface->lightmapinfo->styles[3] != 255)
6105 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6106 VectorMA(c, scale, lm, c);
6116 rsurface.lightmapcolor4f = rsurface.array_color4f;
6117 rsurface.lightmapcolor4f_bufferobject = 0;
6118 rsurface.lightmapcolor4f_bufferoffset = 0;
6122 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6123 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6124 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6126 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6127 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6128 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6129 GL_Color(r, g, b, a);
6130 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6133 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6135 int texturesurfaceindex;
6138 float *v, *c, *c2, alpha;
6139 vec3_t ambientcolor;
6140 vec3_t diffusecolor;
6144 VectorCopy(rsurface.modellight_lightdir, lightdir);
6145 f = 0.5f * r_refdef.lightmapintensity;
6146 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6147 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6148 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6149 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6150 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6151 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6153 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6155 // generate color arrays for the surfaces in this list
6156 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6158 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6159 int numverts = surface->num_vertices;
6160 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6161 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6162 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6163 // q3-style directional shading
6164 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6166 if ((f = DotProduct(c2, lightdir)) > 0)
6167 VectorMA(ambientcolor, f, diffusecolor, c);
6169 VectorCopy(ambientcolor, c);
6177 rsurface.lightmapcolor4f = rsurface.array_color4f;
6178 rsurface.lightmapcolor4f_bufferobject = 0;
6179 rsurface.lightmapcolor4f_bufferoffset = 0;
6180 *applycolor = false;
6184 *r = ambientcolor[0];
6185 *g = ambientcolor[1];
6186 *b = ambientcolor[2];
6187 rsurface.lightmapcolor4f = NULL;
6188 rsurface.lightmapcolor4f_bufferobject = 0;
6189 rsurface.lightmapcolor4f_bufferoffset = 0;
6193 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6195 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6196 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6197 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6198 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6199 GL_Color(r, g, b, a);
6200 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6203 void RSurf_SetupDepthAndCulling(void)
6205 // submodels are biased to avoid z-fighting with world surfaces that they
6206 // may be exactly overlapping (avoids z-fighting artifacts on certain
6207 // doors and things in Quake maps)
6208 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6209 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6210 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6211 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6214 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6216 // transparent sky would be ridiculous
6217 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6219 R_SetupGenericShader(false);
6222 skyrendernow = false;
6223 // we have to force off the water clipping plane while rendering sky
6227 // restore entity matrix
6228 R_Mesh_Matrix(&rsurface.matrix);
6230 RSurf_SetupDepthAndCulling();
6232 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6233 // skymasking on them, and Quake3 never did sky masking (unlike
6234 // software Quake and software Quake2), so disable the sky masking
6235 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6236 // and skymasking also looks very bad when noclipping outside the
6237 // level, so don't use it then either.
6238 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6240 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6241 R_Mesh_ColorPointer(NULL, 0, 0);
6242 R_Mesh_ResetTextureState();
6243 if (skyrendermasked)
6245 R_SetupDepthOrShadowShader();
6246 // depth-only (masking)
6247 GL_ColorMask(0,0,0,0);
6248 // just to make sure that braindead drivers don't draw
6249 // anything despite that colormask...
6250 GL_BlendFunc(GL_ZERO, GL_ONE);
6254 R_SetupGenericShader(false);
6256 GL_BlendFunc(GL_ONE, GL_ZERO);
6258 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6259 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6260 if (skyrendermasked)
6261 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6263 R_Mesh_ResetTextureState();
6264 GL_Color(1, 1, 1, 1);
6267 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6269 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6272 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6273 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6274 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6275 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6276 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6277 if (rsurface.texture->backgroundcurrentskinframe)
6279 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6280 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6281 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6282 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6284 if(rsurface.texture->colormapping)
6286 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6287 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6289 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6290 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6291 R_Mesh_ColorPointer(NULL, 0, 0);
6293 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6295 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6297 // render background
6298 GL_BlendFunc(GL_ONE, GL_ZERO);
6300 GL_AlphaTest(false);
6302 GL_Color(1, 1, 1, 1);
6303 R_Mesh_ColorPointer(NULL, 0, 0);
6305 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6306 if (r_glsl_permutation)
6308 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6309 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6310 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6311 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6312 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6313 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6314 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);
6316 GL_LockArrays(0, 0);
6318 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6319 GL_DepthMask(false);
6320 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6321 R_Mesh_ColorPointer(NULL, 0, 0);
6323 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6324 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6325 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6328 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6329 if (!r_glsl_permutation)
6332 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6333 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6334 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6335 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6336 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6337 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6339 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6341 GL_BlendFunc(GL_ONE, GL_ZERO);
6343 GL_AlphaTest(false);
6347 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6348 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6349 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6352 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6354 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6355 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);
6357 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6361 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6362 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);
6364 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6366 GL_LockArrays(0, 0);
6369 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6371 // OpenGL 1.3 path - anything not completely ancient
6372 int texturesurfaceindex;
6373 qboolean applycolor;
6377 const texturelayer_t *layer;
6378 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6380 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6383 int layertexrgbscale;
6384 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6386 if (layerindex == 0)
6390 GL_AlphaTest(false);
6391 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6394 GL_DepthMask(layer->depthmask && writedepth);
6395 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6396 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6398 layertexrgbscale = 4;
6399 VectorScale(layer->color, 0.25f, layercolor);
6401 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6403 layertexrgbscale = 2;
6404 VectorScale(layer->color, 0.5f, layercolor);
6408 layertexrgbscale = 1;
6409 VectorScale(layer->color, 1.0f, layercolor);
6411 layercolor[3] = layer->color[3];
6412 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6413 R_Mesh_ColorPointer(NULL, 0, 0);
6414 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6415 switch (layer->type)
6417 case TEXTURELAYERTYPE_LITTEXTURE:
6418 memset(&m, 0, sizeof(m));
6419 m.tex[0] = R_GetTexture(r_texture_white);
6420 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6421 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6422 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6423 m.tex[1] = R_GetTexture(layer->texture);
6424 m.texmatrix[1] = layer->texmatrix;
6425 m.texrgbscale[1] = layertexrgbscale;
6426 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6427 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6428 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6429 R_Mesh_TextureState(&m);
6430 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6431 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6432 else if (rsurface.uselightmaptexture)
6433 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6435 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6437 case TEXTURELAYERTYPE_TEXTURE:
6438 memset(&m, 0, sizeof(m));
6439 m.tex[0] = R_GetTexture(layer->texture);
6440 m.texmatrix[0] = layer->texmatrix;
6441 m.texrgbscale[0] = layertexrgbscale;
6442 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6443 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6444 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6445 R_Mesh_TextureState(&m);
6446 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6448 case TEXTURELAYERTYPE_FOG:
6449 memset(&m, 0, sizeof(m));
6450 m.texrgbscale[0] = layertexrgbscale;
6453 m.tex[0] = R_GetTexture(layer->texture);
6454 m.texmatrix[0] = layer->texmatrix;
6455 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6456 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6457 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6459 R_Mesh_TextureState(&m);
6460 // generate a color array for the fog pass
6461 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6462 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6466 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6467 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)
6469 f = 1 - FogPoint_Model(v);
6470 c[0] = layercolor[0];
6471 c[1] = layercolor[1];
6472 c[2] = layercolor[2];
6473 c[3] = f * layercolor[3];
6476 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6479 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6481 GL_LockArrays(0, 0);
6484 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6486 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6487 GL_AlphaTest(false);
6491 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6493 // OpenGL 1.1 - crusty old voodoo path
6494 int texturesurfaceindex;
6498 const texturelayer_t *layer;
6499 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6501 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6503 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6505 if (layerindex == 0)
6509 GL_AlphaTest(false);
6510 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6513 GL_DepthMask(layer->depthmask && writedepth);
6514 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6515 R_Mesh_ColorPointer(NULL, 0, 0);
6516 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6517 switch (layer->type)
6519 case TEXTURELAYERTYPE_LITTEXTURE:
6520 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6522 // two-pass lit texture with 2x rgbscale
6523 // first the lightmap pass
6524 memset(&m, 0, sizeof(m));
6525 m.tex[0] = R_GetTexture(r_texture_white);
6526 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6527 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6528 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6529 R_Mesh_TextureState(&m);
6530 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6531 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6532 else if (rsurface.uselightmaptexture)
6533 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6535 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6536 GL_LockArrays(0, 0);
6537 // then apply the texture to it
6538 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6539 memset(&m, 0, sizeof(m));
6540 m.tex[0] = R_GetTexture(layer->texture);
6541 m.texmatrix[0] = layer->texmatrix;
6542 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6543 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6544 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6545 R_Mesh_TextureState(&m);
6546 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);
6550 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6551 memset(&m, 0, sizeof(m));
6552 m.tex[0] = R_GetTexture(layer->texture);
6553 m.texmatrix[0] = layer->texmatrix;
6554 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6555 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6556 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6557 R_Mesh_TextureState(&m);
6558 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6559 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);
6561 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);
6564 case TEXTURELAYERTYPE_TEXTURE:
6565 // singletexture unlit texture with transparency support
6566 memset(&m, 0, sizeof(m));
6567 m.tex[0] = R_GetTexture(layer->texture);
6568 m.texmatrix[0] = layer->texmatrix;
6569 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6570 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6571 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6572 R_Mesh_TextureState(&m);
6573 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);
6575 case TEXTURELAYERTYPE_FOG:
6576 // singletexture fogging
6577 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6580 memset(&m, 0, sizeof(m));
6581 m.tex[0] = R_GetTexture(layer->texture);
6582 m.texmatrix[0] = layer->texmatrix;
6583 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6584 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6585 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6586 R_Mesh_TextureState(&m);
6589 R_Mesh_ResetTextureState();
6590 // generate a color array for the fog pass
6591 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6595 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6596 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)
6598 f = 1 - FogPoint_Model(v);
6599 c[0] = layer->color[0];
6600 c[1] = layer->color[1];
6601 c[2] = layer->color[2];
6602 c[3] = f * layer->color[3];
6605 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6608 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6610 GL_LockArrays(0, 0);
6613 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6615 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6616 GL_AlphaTest(false);
6620 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6624 GL_AlphaTest(false);
6625 R_Mesh_ColorPointer(NULL, 0, 0);
6626 R_Mesh_ResetTextureState();
6627 R_SetupGenericShader(false);
6629 if(rsurface.texture && rsurface.texture->currentskinframe)
6630 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6639 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6641 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
6642 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
6643 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
6646 // brighten it up (as texture value 127 means "unlit")
6647 c[0] *= 2 * r_refdef.view.colorscale;
6648 c[1] *= 2 * r_refdef.view.colorscale;
6649 c[2] *= 2 * r_refdef.view.colorscale;
6651 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6652 c[3] *= r_wateralpha.value;
6654 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6656 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6657 GL_DepthMask(false);
6659 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6661 GL_BlendFunc(GL_ONE, GL_ONE);
6662 GL_DepthMask(false);
6664 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6666 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6667 GL_DepthMask(false);
6669 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6671 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6672 GL_DepthMask(false);
6676 GL_BlendFunc(GL_ONE, GL_ZERO);
6677 GL_DepthMask(writedepth);
6680 rsurface.lightmapcolor4f = NULL;
6682 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6684 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6686 rsurface.lightmapcolor4f = NULL;
6687 rsurface.lightmapcolor4f_bufferobject = 0;
6688 rsurface.lightmapcolor4f_bufferoffset = 0;
6690 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6692 qboolean applycolor = true;
6695 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6697 r_refdef.lightmapintensity = 1;
6698 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6699 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6703 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6705 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6706 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6707 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6710 if(!rsurface.lightmapcolor4f)
6711 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6713 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6714 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6715 if(r_refdef.fogenabled)
6716 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6718 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6719 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6722 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6725 RSurf_SetupDepthAndCulling();
6726 if (r_showsurfaces.integer == 3)
6727 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6728 else if (r_glsl.integer && gl_support_fragment_shader)
6729 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6730 else if (gl_combine.integer && r_textureunits.integer >= 2)
6731 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6733 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6737 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6740 RSurf_SetupDepthAndCulling();
6741 if (r_showsurfaces.integer == 3)
6742 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6743 else if (r_glsl.integer && gl_support_fragment_shader)
6744 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6745 else if (gl_combine.integer && r_textureunits.integer >= 2)
6746 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6748 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6752 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6755 int texturenumsurfaces, endsurface;
6757 msurface_t *surface;
6758 msurface_t *texturesurfacelist[1024];
6760 // if the model is static it doesn't matter what value we give for
6761 // wantnormals and wanttangents, so this logic uses only rules applicable
6762 // to a model, knowing that they are meaningless otherwise
6763 if (ent == r_refdef.scene.worldentity)
6764 RSurf_ActiveWorldEntity();
6765 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6766 RSurf_ActiveModelEntity(ent, false, false);
6768 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6770 for (i = 0;i < numsurfaces;i = j)
6773 surface = rsurface.modelsurfaces + surfacelist[i];
6774 texture = surface->texture;
6775 rsurface.texture = R_GetCurrentTexture(texture);
6776 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6777 // scan ahead until we find a different texture
6778 endsurface = min(i + 1024, numsurfaces);
6779 texturenumsurfaces = 0;
6780 texturesurfacelist[texturenumsurfaces++] = surface;
6781 for (;j < endsurface;j++)
6783 surface = rsurface.modelsurfaces + surfacelist[j];
6784 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6786 texturesurfacelist[texturenumsurfaces++] = surface;
6788 // render the range of surfaces
6789 if (ent == r_refdef.scene.worldentity)
6790 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6792 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6794 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6795 GL_AlphaTest(false);
6798 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6800 const entity_render_t *queueentity = r_refdef.scene.worldentity;
6804 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6806 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6808 RSurf_SetupDepthAndCulling();
6809 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6810 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6812 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6814 RSurf_SetupDepthAndCulling();
6815 GL_AlphaTest(false);
6816 R_Mesh_ColorPointer(NULL, 0, 0);
6817 R_Mesh_ResetTextureState();
6818 R_SetupGenericShader(false);
6819 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6821 GL_BlendFunc(GL_ONE, GL_ZERO);
6822 GL_Color(0, 0, 0, 1);
6823 GL_DepthTest(writedepth);
6824 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6826 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6828 RSurf_SetupDepthAndCulling();
6829 GL_AlphaTest(false);
6830 R_Mesh_ColorPointer(NULL, 0, 0);
6831 R_Mesh_ResetTextureState();
6832 R_SetupGenericShader(false);
6833 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6835 GL_BlendFunc(GL_ONE, GL_ZERO);
6837 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6839 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6840 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6841 else if (!rsurface.texture->currentnumlayers)
6843 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6845 // transparent surfaces get pushed off into the transparent queue
6846 int surfacelistindex;
6847 const msurface_t *surface;
6848 vec3_t tempcenter, center;
6849 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6851 surface = texturesurfacelist[surfacelistindex];
6852 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6853 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6854 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6855 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6856 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6861 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6862 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6867 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6871 // break the surface list down into batches by texture and use of lightmapping
6872 for (i = 0;i < numsurfaces;i = j)
6875 // texture is the base texture pointer, rsurface.texture is the
6876 // current frame/skin the texture is directing us to use (for example
6877 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6878 // use skin 1 instead)
6879 texture = surfacelist[i]->texture;
6880 rsurface.texture = R_GetCurrentTexture(texture);
6881 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6882 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6884 // if this texture is not the kind we want, skip ahead to the next one
6885 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6889 // simply scan ahead until we find a different texture or lightmap state
6890 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6892 // render the range of surfaces
6893 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6897 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6902 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6904 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6906 RSurf_SetupDepthAndCulling();
6907 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6908 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6910 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6912 RSurf_SetupDepthAndCulling();
6913 GL_AlphaTest(false);
6914 R_Mesh_ColorPointer(NULL, 0, 0);
6915 R_Mesh_ResetTextureState();
6916 R_SetupGenericShader(false);
6917 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6919 GL_BlendFunc(GL_ONE, GL_ZERO);
6920 GL_Color(0, 0, 0, 1);
6921 GL_DepthTest(writedepth);
6922 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6924 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6926 RSurf_SetupDepthAndCulling();
6927 GL_AlphaTest(false);
6928 R_Mesh_ColorPointer(NULL, 0, 0);
6929 R_Mesh_ResetTextureState();
6930 R_SetupGenericShader(false);
6931 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6933 GL_BlendFunc(GL_ONE, GL_ZERO);
6935 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6937 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6938 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6939 else if (!rsurface.texture->currentnumlayers)
6941 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6943 // transparent surfaces get pushed off into the transparent queue
6944 int surfacelistindex;
6945 const msurface_t *surface;
6946 vec3_t tempcenter, center;
6947 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6949 surface = texturesurfacelist[surfacelistindex];
6950 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6951 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6952 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6953 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6954 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6959 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6960 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6965 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6969 // break the surface list down into batches by texture and use of lightmapping
6970 for (i = 0;i < numsurfaces;i = j)
6973 // texture is the base texture pointer, rsurface.texture is the
6974 // current frame/skin the texture is directing us to use (for example
6975 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6976 // use skin 1 instead)
6977 texture = surfacelist[i]->texture;
6978 rsurface.texture = R_GetCurrentTexture(texture);
6979 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6980 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6982 // if this texture is not the kind we want, skip ahead to the next one
6983 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6987 // simply scan ahead until we find a different texture or lightmap state
6988 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6990 // render the range of surfaces
6991 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6995 float locboxvertex3f[6*4*3] =
6997 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6998 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6999 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7000 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7001 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7002 1,0,0, 0,0,0, 0,1,0, 1,1,0
7005 unsigned short locboxelements[6*2*3] =
7015 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7018 cl_locnode_t *loc = (cl_locnode_t *)ent;
7020 float vertex3f[6*4*3];
7022 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7023 GL_DepthMask(false);
7024 GL_DepthRange(0, 1);
7025 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7027 GL_CullFace(GL_NONE);
7028 R_Mesh_Matrix(&identitymatrix);
7030 R_Mesh_VertexPointer(vertex3f, 0, 0);
7031 R_Mesh_ColorPointer(NULL, 0, 0);
7032 R_Mesh_ResetTextureState();
7033 R_SetupGenericShader(false);
7036 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7037 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7038 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7039 surfacelist[0] < 0 ? 0.5f : 0.125f);
7041 if (VectorCompare(loc->mins, loc->maxs))
7043 VectorSet(size, 2, 2, 2);
7044 VectorMA(loc->mins, -0.5f, size, mins);
7048 VectorCopy(loc->mins, mins);
7049 VectorSubtract(loc->maxs, loc->mins, size);
7052 for (i = 0;i < 6*4*3;)
7053 for (j = 0;j < 3;j++, i++)
7054 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7056 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7059 void R_DrawLocs(void)
7062 cl_locnode_t *loc, *nearestloc;
7064 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7065 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7067 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7068 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7072 void R_DrawDebugModel(entity_render_t *ent)
7074 int i, j, k, l, flagsmask;
7075 const int *elements;
7077 msurface_t *surface;
7078 dp_model_t *model = ent->model;
7081 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7083 R_Mesh_ColorPointer(NULL, 0, 0);
7084 R_Mesh_ResetTextureState();
7085 R_SetupGenericShader(false);
7086 GL_DepthRange(0, 1);
7087 GL_DepthTest(!r_showdisabledepthtest.integer);
7088 GL_DepthMask(false);
7089 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7091 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7093 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7094 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7096 if (brush->colbrushf && brush->colbrushf->numtriangles)
7098 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7099 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);
7100 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7103 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7105 if (surface->num_collisiontriangles)
7107 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7108 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);
7109 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7114 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7116 if (r_showtris.integer || r_shownormals.integer)
7118 if (r_showdisabledepthtest.integer)
7120 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7121 GL_DepthMask(false);
7125 GL_BlendFunc(GL_ONE, GL_ZERO);
7128 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7130 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7132 rsurface.texture = R_GetCurrentTexture(surface->texture);
7133 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7135 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7136 if (r_showtris.value > 0)
7138 if (!rsurface.texture->currentlayers->depthmask)
7139 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7140 else if (ent == r_refdef.scene.worldentity)
7141 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7143 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7144 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7145 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7146 R_Mesh_ColorPointer(NULL, 0, 0);
7147 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7148 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7149 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7150 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);
7151 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7154 if (r_shownormals.value < 0)
7157 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7159 VectorCopy(rsurface.vertex3f + l * 3, v);
7160 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7161 qglVertex3f(v[0], v[1], v[2]);
7162 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7163 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7164 qglVertex3f(v[0], v[1], v[2]);
7169 if (r_shownormals.value > 0)
7172 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7174 VectorCopy(rsurface.vertex3f + l * 3, v);
7175 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7176 qglVertex3f(v[0], v[1], v[2]);
7177 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7178 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7179 qglVertex3f(v[0], v[1], v[2]);
7184 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7186 VectorCopy(rsurface.vertex3f + l * 3, v);
7187 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7188 qglVertex3f(v[0], v[1], v[2]);
7189 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7190 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7191 qglVertex3f(v[0], v[1], v[2]);
7196 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7198 VectorCopy(rsurface.vertex3f + l * 3, v);
7199 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7200 qglVertex3f(v[0], v[1], v[2]);
7201 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7202 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7203 qglVertex3f(v[0], v[1], v[2]);
7210 rsurface.texture = NULL;
7214 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7215 int r_maxsurfacelist = 0;
7216 msurface_t **r_surfacelist = NULL;
7217 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7219 int i, j, endj, f, flagsmask;
7221 dp_model_t *model = r_refdef.scene.worldmodel;
7222 msurface_t *surfaces;
7223 unsigned char *update;
7224 int numsurfacelist = 0;
7228 if (r_maxsurfacelist < model->num_surfaces)
7230 r_maxsurfacelist = model->num_surfaces;
7232 Mem_Free(r_surfacelist);
7233 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7236 RSurf_ActiveWorldEntity();
7238 surfaces = model->data_surfaces;
7239 update = model->brushq1.lightmapupdateflags;
7241 // update light styles on this submodel
7242 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7244 model_brush_lightstyleinfo_t *style;
7245 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7247 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7249 int *list = style->surfacelist;
7250 style->value = r_refdef.scene.lightstylevalue[style->style];
7251 for (j = 0;j < style->numsurfaces;j++)
7252 update[list[j]] = true;
7257 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7261 R_DrawDebugModel(r_refdef.scene.worldentity);
7262 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7268 rsurface.uselightmaptexture = false;
7269 rsurface.texture = NULL;
7270 rsurface.rtlight = NULL;
7272 // add visible surfaces to draw list
7273 for (i = 0;i < model->nummodelsurfaces;i++)
7275 j = model->sortedmodelsurfaces[i];
7276 if (r_refdef.viewcache.world_surfacevisible[j])
7277 r_surfacelist[numsurfacelist++] = surfaces + j;
7279 // update lightmaps if needed
7281 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7282 if (r_refdef.viewcache.world_surfacevisible[j])
7284 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7285 // don't do anything if there were no surfaces
7286 if (!numsurfacelist)
7288 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7291 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7292 GL_AlphaTest(false);
7294 // add to stats if desired
7295 if (r_speeds.integer && !skysurfaces && !depthonly)
7297 r_refdef.stats.world_surfaces += numsurfacelist;
7298 for (j = 0;j < numsurfacelist;j++)
7299 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7301 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7304 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7306 int i, j, endj, f, flagsmask;
7308 dp_model_t *model = ent->model;
7309 msurface_t *surfaces;
7310 unsigned char *update;
7311 int numsurfacelist = 0;
7315 if (r_maxsurfacelist < model->num_surfaces)
7317 r_maxsurfacelist = model->num_surfaces;
7319 Mem_Free(r_surfacelist);
7320 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7323 // if the model is static it doesn't matter what value we give for
7324 // wantnormals and wanttangents, so this logic uses only rules applicable
7325 // to a model, knowing that they are meaningless otherwise
7326 if (ent == r_refdef.scene.worldentity)
7327 RSurf_ActiveWorldEntity();
7328 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
7329 RSurf_ActiveModelEntity(ent, false, false);
7331 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7333 surfaces = model->data_surfaces;
7334 update = model->brushq1.lightmapupdateflags;
7336 // update light styles
7337 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7339 model_brush_lightstyleinfo_t *style;
7340 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7342 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7344 int *list = style->surfacelist;
7345 style->value = r_refdef.scene.lightstylevalue[style->style];
7346 for (j = 0;j < style->numsurfaces;j++)
7347 update[list[j]] = true;
7352 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7356 R_DrawDebugModel(ent);
7357 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7363 rsurface.uselightmaptexture = false;
7364 rsurface.texture = NULL;
7365 rsurface.rtlight = NULL;
7367 // add visible surfaces to draw list
7368 for (i = 0;i < model->nummodelsurfaces;i++)
7369 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7370 // don't do anything if there were no surfaces
7371 if (!numsurfacelist)
7373 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7376 // update lightmaps if needed
7378 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7380 R_BuildLightMap(ent, surfaces + j);
7381 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7382 GL_AlphaTest(false);
7384 // add to stats if desired
7385 if (r_speeds.integer && !skysurfaces && !depthonly)
7387 r_refdef.stats.entities_surfaces += numsurfacelist;
7388 for (j = 0;j < numsurfacelist;j++)
7389 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7391 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity