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; /// \note 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 "#ifdef USEVERTEXTEXTUREBLEND\n"
594 "varying vec2 TexCoord2;\n"
596 "varying vec2 TexCoordLightmap;\n"
598 "#ifdef MODE_LIGHTSOURCE\n"
599 "varying vec3 CubeVector;\n"
602 "#ifdef MODE_LIGHTSOURCE\n"
603 "varying vec3 LightVector;\n"
605 "#ifdef MODE_LIGHTDIRECTION\n"
606 "varying vec3 LightVector;\n"
609 "varying vec3 EyeVector;\n"
611 "varying vec3 EyeVectorModelSpace;\n"
614 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
615 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
616 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
618 "#ifdef MODE_WATER\n"
619 "varying vec4 ModelViewProjectionPosition;\n"
621 "#ifdef MODE_REFRACTION\n"
622 "varying vec4 ModelViewProjectionPosition;\n"
624 "#ifdef USEREFLECTION\n"
625 "varying vec4 ModelViewProjectionPosition;\n"
632 "// vertex shader specific:\n"
633 "#ifdef VERTEX_SHADER\n"
635 "uniform vec3 LightPosition;\n"
636 "uniform vec3 EyePosition;\n"
637 "uniform vec3 LightDir;\n"
639 "// 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"
643 " gl_FrontColor = gl_Color;\n"
644 " // copy the surface texcoord\n"
645 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
646 "#ifdef USEVERTEXTEXTUREBLEND\n"
647 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
649 "#ifndef MODE_LIGHTSOURCE\n"
650 "# ifndef MODE_LIGHTDIRECTION\n"
651 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
655 "#ifdef MODE_LIGHTSOURCE\n"
656 " // transform vertex position into light attenuation/cubemap space\n"
657 " // (-1 to +1 across the light box)\n"
658 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
660 " // transform unnormalized light direction into tangent space\n"
661 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
662 " // normalize it per pixel)\n"
663 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
664 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
665 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
666 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
669 "#ifdef MODE_LIGHTDIRECTION\n"
670 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
671 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
672 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
675 " // transform unnormalized eye direction into tangent space\n"
677 " vec3 EyeVectorModelSpace;\n"
679 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
680 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
681 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
682 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
684 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
685 " VectorS = gl_MultiTexCoord1.xyz;\n"
686 " VectorT = gl_MultiTexCoord2.xyz;\n"
687 " VectorR = gl_MultiTexCoord3.xyz;\n"
690 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
691 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
692 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
693 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
696 "// transform vertex to camera space, using ftransform to match non-VS\n"
698 " gl_Position = ftransform();\n"
700 "#ifdef MODE_WATER\n"
701 " ModelViewProjectionPosition = gl_Position;\n"
703 "#ifdef MODE_REFRACTION\n"
704 " ModelViewProjectionPosition = gl_Position;\n"
706 "#ifdef USEREFLECTION\n"
707 " ModelViewProjectionPosition = gl_Position;\n"
711 "#endif // VERTEX_SHADER\n"
716 "// fragment shader specific:\n"
717 "#ifdef FRAGMENT_SHADER\n"
719 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
720 "uniform sampler2D Texture_Normal;\n"
721 "uniform sampler2D Texture_Color;\n"
722 "uniform sampler2D Texture_Gloss;\n"
723 "uniform sampler2D Texture_Glow;\n"
724 "uniform sampler2D Texture_SecondaryNormal;\n"
725 "uniform sampler2D Texture_SecondaryColor;\n"
726 "uniform sampler2D Texture_SecondaryGloss;\n"
727 "uniform sampler2D Texture_SecondaryGlow;\n"
728 "uniform sampler2D Texture_Pants;\n"
729 "uniform sampler2D Texture_Shirt;\n"
730 "uniform sampler2D Texture_FogMask;\n"
731 "uniform sampler2D Texture_Lightmap;\n"
732 "uniform sampler2D Texture_Deluxemap;\n"
733 "uniform sampler2D Texture_Refraction;\n"
734 "uniform sampler2D Texture_Reflection;\n"
735 "uniform sampler2D Texture_Attenuation;\n"
736 "uniform samplerCube Texture_Cube;\n"
738 "uniform myhalf3 LightColor;\n"
739 "uniform myhalf3 AmbientColor;\n"
740 "uniform myhalf3 DiffuseColor;\n"
741 "uniform myhalf3 SpecularColor;\n"
742 "uniform myhalf3 Color_Pants;\n"
743 "uniform myhalf3 Color_Shirt;\n"
744 "uniform myhalf3 FogColor;\n"
746 "uniform myhalf4 TintColor;\n"
749 "//#ifdef MODE_WATER\n"
750 "uniform vec4 DistortScaleRefractReflect;\n"
751 "uniform vec4 ScreenScaleRefractReflect;\n"
752 "uniform vec4 ScreenCenterRefractReflect;\n"
753 "uniform myhalf4 RefractColor;\n"
754 "uniform myhalf4 ReflectColor;\n"
755 "uniform myhalf ReflectFactor;\n"
756 "uniform myhalf ReflectOffset;\n"
758 "//# ifdef MODE_REFRACTION\n"
759 "//uniform vec4 DistortScaleRefractReflect;\n"
760 "//uniform vec4 ScreenScaleRefractReflect;\n"
761 "//uniform vec4 ScreenCenterRefractReflect;\n"
762 "//uniform myhalf4 RefractColor;\n"
763 "//# ifdef USEREFLECTION\n"
764 "//uniform myhalf4 ReflectColor;\n"
767 "//# ifdef USEREFLECTION\n"
768 "//uniform vec4 DistortScaleRefractReflect;\n"
769 "//uniform vec4 ScreenScaleRefractReflect;\n"
770 "//uniform vec4 ScreenCenterRefractReflect;\n"
771 "//uniform myhalf4 ReflectColor;\n"
776 "uniform myhalf GlowScale;\n"
777 "uniform myhalf SceneBrightness;\n"
778 "#ifdef USECONTRASTBOOST\n"
779 "uniform myhalf ContrastBoostCoeff;\n"
782 "uniform float OffsetMapping_Scale;\n"
783 "uniform float OffsetMapping_Bias;\n"
784 "uniform float FogRangeRecip;\n"
786 "uniform myhalf AmbientScale;\n"
787 "uniform myhalf DiffuseScale;\n"
788 "uniform myhalf SpecularScale;\n"
789 "uniform myhalf SpecularPower;\n"
791 "#ifdef USEOFFSETMAPPING\n"
792 "vec2 OffsetMapping(vec2 TexCoord)\n"
794 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
795 " // 14 sample relief mapping: linear search and then binary search\n"
796 " // this basically steps forward a small amount repeatedly until it finds\n"
797 " // itself inside solid, then jitters forward and back using decreasing\n"
798 " // amounts to find the impact\n"
799 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
800 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
801 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
802 " vec3 RT = vec3(TexCoord, 1);\n"
803 " OffsetVector *= 0.1;\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);\n"
808 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
809 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
810 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
811 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
812 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
813 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
814 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
815 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
816 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
817 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
820 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
821 " // this basically moves forward the full distance, and then backs up based\n"
822 " // on height of samples\n"
823 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
824 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
825 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
826 " TexCoord += OffsetVector;\n"
827 " OffsetVector *= 0.333;\n"
828 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
829 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
830 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
831 " return TexCoord;\n"
834 "#endif // USEOFFSETMAPPING\n"
836 "#ifdef MODE_WATER\n"
841 "#ifdef USEOFFSETMAPPING\n"
842 " // apply offsetmapping\n"
843 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
844 "#define TexCoord TexCoordOffset\n"
847 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
848 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
849 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
850 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
851 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
854 "#else // !MODE_WATER\n"
855 "#ifdef MODE_REFRACTION\n"
857 "// refraction pass\n"
860 "#ifdef USEOFFSETMAPPING\n"
861 " // apply offsetmapping\n"
862 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
863 "#define TexCoord TexCoordOffset\n"
866 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
867 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
868 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
869 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
872 "#else // !MODE_REFRACTION\n"
875 "#ifdef USEOFFSETMAPPING\n"
876 " // apply offsetmapping\n"
877 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
878 "#define TexCoord TexCoordOffset\n"
881 " // combine the diffuse textures (base, pants, shirt)\n"
882 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
883 "#ifdef USECOLORMAPPING\n"
884 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
886 "#ifdef USEVERTEXTEXTUREBLEND\n"
887 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
888 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
889 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
890 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
892 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
895 "#ifdef USEDIFFUSE\n"
896 " // get the surface normal and the gloss color\n"
897 "# ifdef USEVERTEXTEXTUREBLEND\n"
898 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
899 "# ifdef USESPECULAR\n"
900 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
903 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
904 "# ifdef USESPECULAR\n"
905 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
912 "#ifdef MODE_LIGHTSOURCE\n"
915 " // calculate surface normal, light normal, and specular normal\n"
916 " // compute color intensity for the two textures (colormap and glossmap)\n"
917 " // scale by light color and attenuation as efficiently as possible\n"
918 " // (do as much scalar math as possible rather than vector math)\n"
919 "# ifdef USEDIFFUSE\n"
920 " // get the light normal\n"
921 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
923 "# ifdef USESPECULAR\n"
924 "# ifndef USEEXACTSPECULARMATH\n"
925 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
928 " // calculate directional shading\n"
929 "# ifdef USEEXACTSPECULARMATH\n"
930 " 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"
932 " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * glosscolor);\n"
935 "# ifdef USEDIFFUSE\n"
936 " // calculate directional shading\n"
937 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
939 " // calculate directionless shading\n"
940 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
944 "# ifdef USECUBEFILTER\n"
945 " // apply light cubemap filter\n"
946 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
947 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
949 "#endif // MODE_LIGHTSOURCE\n"
954 "#ifdef MODE_LIGHTDIRECTION\n"
955 " // directional model lighting\n"
956 "# ifdef USEDIFFUSE\n"
957 " // get the light normal\n"
958 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
960 "# ifdef USESPECULAR\n"
961 " // calculate directional shading\n"
962 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
963 "# ifdef USEEXACTSPECULARMATH\n"
964 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
966 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
967 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
970 "# ifdef USEDIFFUSE\n"
972 " // calculate directional shading\n"
973 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
975 " color.rgb *= AmbientColor;\n"
978 "#endif // MODE_LIGHTDIRECTION\n"
983 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
984 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
986 " // get the light normal\n"
987 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
988 " myhalf3 diffusenormal;\n"
989 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
990 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
991 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
992 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
993 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
994 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
995 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
996 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
997 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
998 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
999 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1000 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1001 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1002 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1003 "# ifdef USESPECULAR\n"
1004 "# ifdef USEEXACTSPECULARMATH\n"
1005 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1007 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1008 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1012 " // apply lightmap color\n"
1013 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1014 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1019 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1020 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1022 " // get the light normal\n"
1023 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1024 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1025 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1026 "# ifdef USESPECULAR\n"
1027 "# ifdef USEEXACTSPECULARMATH\n"
1028 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1030 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1031 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1035 " // apply lightmap color\n"
1036 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1037 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1042 "#ifdef MODE_LIGHTMAP\n"
1043 " // apply lightmap color\n"
1044 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1045 "#endif // MODE_LIGHTMAP\n"
1050 "#ifdef MODE_VERTEXCOLOR\n"
1051 " // apply lightmap color\n"
1052 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1053 "#endif // MODE_VERTEXCOLOR\n"
1058 "#ifdef MODE_FLATCOLOR\n"
1059 "#endif // MODE_FLATCOLOR\n"
1067 " color *= TintColor;\n"
1070 "#ifdef USEVERTEXTEXTUREBLEND\n"
1071 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1073 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1077 "#ifdef USECONTRASTBOOST\n"
1078 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1081 " color.rgb *= SceneBrightness;\n"
1083 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1085 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1088 " // 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"
1089 "#ifdef USEREFLECTION\n"
1090 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1091 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1092 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1093 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1096 " gl_FragColor = vec4(color);\n"
1098 "#endif // !MODE_REFRACTION\n"
1099 "#endif // !MODE_WATER\n"
1101 "#endif // FRAGMENT_SHADER\n"
1103 "#endif // !MODE_GENERIC\n"
1104 "#endif // !MODE_POSTPROCESS\n"
1105 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1108 typedef struct shaderpermutationinfo_s
1110 const char *pretext;
1113 shaderpermutationinfo_t;
1115 typedef struct shadermodeinfo_s
1117 const char *vertexfilename;
1118 const char *geometryfilename;
1119 const char *fragmentfilename;
1120 const char *pretext;
1125 typedef enum shaderpermutation_e
1127 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1128 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1129 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1130 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, ///< r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1131 SHADERPERMUTATION_FOG = 1<<4, ///< tint the color by fog color or black if using additive blend mode
1132 SHADERPERMUTATION_CUBEFILTER = 1<<5, ///< (lightsource) use cubemap light filter
1133 SHADERPERMUTATION_GLOW = 1<<6, ///< (lightmap) blend in an additive glow texture
1134 SHADERPERMUTATION_SPECULAR = 1<<7, ///< (lightsource or deluxemapping) render specular effects
1135 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1136 SHADERPERMUTATION_REFLECTION = 1<<9, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1137 SHADERPERMUTATION_OFFSETMAPPING = 1<<10, ///< adjust texcoords to roughly simulate a displacement mapped surface
1138 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1139 SHADERPERMUTATION_GAMMARAMPS = 1<<12, ///< gamma (postprocessing only)
1140 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing
1141 SHADERPERMUTATION_SATURATION = 1<<14, ///< user defined postprocessing
1142 SHADERPERMUTATION_LIMIT = 1<<15, ///< size of permutations array
1143 SHADERPERMUTATION_COUNT = 15 ///< size of shaderpermutationinfo array
1145 shaderpermutation_t;
1147 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1148 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1150 {"#define USEDIFFUSE\n", " diffuse"},
1151 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1152 {"#define USECOLORMAPPING\n", " colormapping"},
1153 {"#define USECONTRASTBOOST\n", " contrastboost"},
1154 {"#define USEFOG\n", " fog"},
1155 {"#define USECUBEFILTER\n", " cubefilter"},
1156 {"#define USEGLOW\n", " glow"},
1157 {"#define USESPECULAR\n", " specular"},
1158 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1159 {"#define USEREFLECTION\n", " reflection"},
1160 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1161 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1162 {"#define USEGAMMARAMPS\n", " gammaramps"},
1163 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1164 {"#define USESATURATION\n", " saturation"},
1167 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1168 typedef enum shadermode_e
1170 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1171 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1172 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1173 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1174 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1175 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1176 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1177 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1178 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1179 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1180 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1181 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1186 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1187 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1189 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1190 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1191 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1192 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1193 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1194 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1195 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1196 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1197 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1198 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1199 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1200 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1203 typedef struct r_glsl_permutation_s
1205 /// indicates if we have tried compiling this permutation already
1207 /// 0 if compilation failed
1209 /// locations of detected uniforms in program object, or -1 if not found
1210 int loc_Texture_First;
1211 int loc_Texture_Second;
1212 int loc_Texture_GammaRamps;
1213 int loc_Texture_Normal;
1214 int loc_Texture_Color;
1215 int loc_Texture_Gloss;
1216 int loc_Texture_Glow;
1217 int loc_Texture_SecondaryNormal;
1218 int loc_Texture_SecondaryColor;
1219 int loc_Texture_SecondaryGloss;
1220 int loc_Texture_SecondaryGlow;
1221 int loc_Texture_Pants;
1222 int loc_Texture_Shirt;
1223 int loc_Texture_FogMask;
1224 int loc_Texture_Lightmap;
1225 int loc_Texture_Deluxemap;
1226 int loc_Texture_Attenuation;
1227 int loc_Texture_Cube;
1228 int loc_Texture_Refraction;
1229 int loc_Texture_Reflection;
1231 int loc_LightPosition;
1232 int loc_EyePosition;
1233 int loc_Color_Pants;
1234 int loc_Color_Shirt;
1235 int loc_FogRangeRecip;
1236 int loc_AmbientScale;
1237 int loc_DiffuseScale;
1238 int loc_SpecularScale;
1239 int loc_SpecularPower;
1241 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1242 int loc_OffsetMapping_Scale;
1244 int loc_AmbientColor;
1245 int loc_DiffuseColor;
1246 int loc_SpecularColor;
1248 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1249 int loc_GammaCoeff; ///< 1 / gamma
1250 int loc_DistortScaleRefractReflect;
1251 int loc_ScreenScaleRefractReflect;
1252 int loc_ScreenCenterRefractReflect;
1253 int loc_RefractColor;
1254 int loc_ReflectColor;
1255 int loc_ReflectFactor;
1256 int loc_ReflectOffset;
1265 r_glsl_permutation_t;
1267 /// information about each possible shader permutation
1268 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1269 /// currently selected permutation
1270 r_glsl_permutation_t *r_glsl_permutation;
1272 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1275 if (!filename || !filename[0])
1277 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1280 if (printfromdisknotice)
1281 Con_DPrint("from disk... ");
1282 return shaderstring;
1284 else if (!strcmp(filename, "glsl/default.glsl"))
1286 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1287 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1289 return shaderstring;
1292 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1295 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1296 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1297 int vertstrings_count = 0;
1298 int geomstrings_count = 0;
1299 int fragstrings_count = 0;
1300 char *vertexstring, *geometrystring, *fragmentstring;
1301 const char *vertstrings_list[32+3];
1302 const char *geomstrings_list[32+3];
1303 const char *fragstrings_list[32+3];
1304 char permutationname[256];
1311 permutationname[0] = 0;
1312 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1313 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1314 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1316 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1318 // the first pretext is which type of shader to compile as
1319 // (later these will all be bound together as a program object)
1320 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1321 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1322 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1324 // the second pretext is the mode (for example a light source)
1325 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1326 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1327 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1328 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1330 // now add all the permutation pretexts
1331 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1333 if (permutation & (1<<i))
1335 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1336 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1337 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1338 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1342 // keep line numbers correct
1343 vertstrings_list[vertstrings_count++] = "\n";
1344 geomstrings_list[geomstrings_count++] = "\n";
1345 fragstrings_list[fragstrings_count++] = "\n";
1349 // now append the shader text itself
1350 vertstrings_list[vertstrings_count++] = vertexstring;
1351 geomstrings_list[geomstrings_count++] = geometrystring;
1352 fragstrings_list[fragstrings_count++] = fragmentstring;
1354 // if any sources were NULL, clear the respective list
1356 vertstrings_count = 0;
1357 if (!geometrystring)
1358 geomstrings_count = 0;
1359 if (!fragmentstring)
1360 fragstrings_count = 0;
1362 // compile the shader program
1363 if (vertstrings_count + geomstrings_count + fragstrings_count)
1364 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1368 qglUseProgramObjectARB(p->program);CHECKGLERROR
1369 // look up all the uniform variable names we care about, so we don't
1370 // have to look them up every time we set them
1371 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1372 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1373 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1374 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1375 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1376 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1377 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1378 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1379 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1380 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1381 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1382 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1383 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1384 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1385 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1386 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1387 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1388 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1389 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1390 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1391 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1392 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1393 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1394 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1395 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1396 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1397 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1398 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1399 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1400 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1401 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1402 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1403 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1404 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1405 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1406 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1407 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1408 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1409 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1410 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1411 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1412 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1413 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1414 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1415 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1416 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1417 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1418 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1419 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1420 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1421 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1422 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1423 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1424 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1425 // initialize the samplers to refer to the texture units we use
1426 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1427 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1428 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1429 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1430 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1431 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1432 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1433 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1434 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1435 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1436 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1437 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1438 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1439 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1440 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1441 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1442 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1443 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1444 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1445 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1447 if (developer.integer)
1448 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1451 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1455 Mem_Free(vertexstring);
1457 Mem_Free(geometrystring);
1459 Mem_Free(fragmentstring);
1462 void R_GLSL_Restart_f(void)
1465 unsigned int permutation;
1466 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1467 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1468 if (r_glsl_permutations[mode][permutation].program)
1469 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1470 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1473 void R_GLSL_DumpShader_f(void)
1477 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1480 Con_Printf("failed to write to glsl/default.glsl\n");
1484 FS_Print(file, "// The engine may define the following macros:\n");
1485 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1486 for (i = 0;i < SHADERMODE_COUNT;i++)
1487 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1488 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1489 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1490 FS_Print(file, "\n");
1491 FS_Print(file, builtinshaderstring);
1494 Con_Printf("glsl/default.glsl written\n");
1497 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1499 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1500 if (r_glsl_permutation != perm)
1502 r_glsl_permutation = perm;
1503 if (!r_glsl_permutation->program)
1505 if (!r_glsl_permutation->compiled)
1506 R_GLSL_CompilePermutation(mode, permutation);
1507 if (!r_glsl_permutation->program)
1509 // remove features until we find a valid permutation
1511 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1513 // reduce i more quickly whenever it would not remove any bits
1514 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1515 if (!(permutation & j))
1518 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1519 if (!r_glsl_permutation->compiled)
1520 R_GLSL_CompilePermutation(mode, permutation);
1521 if (r_glsl_permutation->program)
1524 if (i >= SHADERPERMUTATION_COUNT)
1526 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");
1527 Cvar_SetValueQuick(&r_glsl, 0);
1528 R_GLSL_Restart_f(); // unload shaders
1529 return; // no bit left to clear
1534 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1538 void R_SetupGenericShader(qboolean usetexture)
1540 if (gl_support_fragment_shader)
1542 if (r_glsl.integer && r_glsl_usegeneric.integer)
1543 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1544 else if (r_glsl_permutation)
1546 r_glsl_permutation = NULL;
1547 qglUseProgramObjectARB(0);CHECKGLERROR
1552 void R_SetupGenericTwoTextureShader(int texturemode)
1554 if (gl_support_fragment_shader)
1556 if (r_glsl.integer && r_glsl_usegeneric.integer)
1557 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))));
1558 else if (r_glsl_permutation)
1560 r_glsl_permutation = NULL;
1561 qglUseProgramObjectARB(0);CHECKGLERROR
1564 if (!r_glsl_permutation)
1566 if (texturemode == GL_DECAL && gl_combine.integer)
1567 texturemode = GL_INTERPOLATE_ARB;
1568 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1572 void R_SetupDepthOrShadowShader(void)
1574 if (gl_support_fragment_shader)
1576 if (r_glsl.integer && r_glsl_usegeneric.integer)
1577 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1578 else if (r_glsl_permutation)
1580 r_glsl_permutation = NULL;
1581 qglUseProgramObjectARB(0);CHECKGLERROR
1586 extern rtexture_t *r_shadow_attenuationgradienttexture;
1587 extern rtexture_t *r_shadow_attenuation2dtexture;
1588 extern rtexture_t *r_shadow_attenuation3dtexture;
1589 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1591 // select a permutation of the lighting shader appropriate to this
1592 // combination of texture, entity, light source, and fogging, only use the
1593 // minimum features necessary to avoid wasting rendering time in the
1594 // fragment shader on features that are not being used
1595 unsigned int permutation = 0;
1596 unsigned int mode = 0;
1597 // TODO: implement geometry-shader based shadow volumes someday
1598 if (r_glsl_offsetmapping.integer)
1600 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1601 if (r_glsl_offsetmapping_reliefmapping.integer)
1602 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1604 if (rsurfacepass == RSURFPASS_BACKGROUND)
1606 // distorted background
1607 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1608 mode = SHADERMODE_WATER;
1610 mode = SHADERMODE_REFRACTION;
1612 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1615 mode = SHADERMODE_LIGHTSOURCE;
1616 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1617 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1618 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1619 permutation |= SHADERPERMUTATION_CUBEFILTER;
1620 if (diffusescale > 0)
1621 permutation |= SHADERPERMUTATION_DIFFUSE;
1622 if (specularscale > 0)
1623 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1624 if (r_refdef.fogenabled)
1625 permutation |= SHADERPERMUTATION_FOG;
1626 if (rsurface.texture->colormapping)
1627 permutation |= SHADERPERMUTATION_COLORMAPPING;
1628 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1629 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1631 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1633 // unshaded geometry (fullbright or ambient model lighting)
1634 mode = SHADERMODE_FLATCOLOR;
1635 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1636 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1637 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1638 permutation |= SHADERPERMUTATION_GLOW;
1639 if (r_refdef.fogenabled)
1640 permutation |= SHADERPERMUTATION_FOG;
1641 if (rsurface.texture->colormapping)
1642 permutation |= SHADERPERMUTATION_COLORMAPPING;
1643 if (r_glsl_offsetmapping.integer)
1645 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1646 if (r_glsl_offsetmapping_reliefmapping.integer)
1647 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1649 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1650 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1651 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1652 permutation |= SHADERPERMUTATION_REFLECTION;
1654 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1656 // directional model lighting
1657 mode = SHADERMODE_LIGHTDIRECTION;
1658 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1659 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1660 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1661 permutation |= SHADERPERMUTATION_GLOW;
1662 permutation |= SHADERPERMUTATION_DIFFUSE;
1663 if (specularscale > 0)
1664 permutation |= SHADERPERMUTATION_SPECULAR;
1665 if (r_refdef.fogenabled)
1666 permutation |= SHADERPERMUTATION_FOG;
1667 if (rsurface.texture->colormapping)
1668 permutation |= SHADERPERMUTATION_COLORMAPPING;
1669 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1670 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1671 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1672 permutation |= SHADERPERMUTATION_REFLECTION;
1674 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1676 // ambient model lighting
1677 mode = SHADERMODE_LIGHTDIRECTION;
1678 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1679 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1680 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1681 permutation |= SHADERPERMUTATION_GLOW;
1682 if (r_refdef.fogenabled)
1683 permutation |= SHADERPERMUTATION_FOG;
1684 if (rsurface.texture->colormapping)
1685 permutation |= SHADERPERMUTATION_COLORMAPPING;
1686 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1687 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1688 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1689 permutation |= SHADERPERMUTATION_REFLECTION;
1694 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1696 // deluxemapping (light direction texture)
1697 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1698 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1700 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1701 permutation |= SHADERPERMUTATION_DIFFUSE;
1702 if (specularscale > 0)
1703 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1705 else if (r_glsl_deluxemapping.integer >= 2)
1707 // fake deluxemapping (uniform light direction in tangentspace)
1708 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1709 permutation |= SHADERPERMUTATION_DIFFUSE;
1710 if (specularscale > 0)
1711 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1713 else if (rsurface.uselightmaptexture)
1715 // ordinary lightmapping (q1bsp, q3bsp)
1716 mode = SHADERMODE_LIGHTMAP;
1720 // ordinary vertex coloring (q3bsp)
1721 mode = SHADERMODE_VERTEXCOLOR;
1723 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1724 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1725 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1726 permutation |= SHADERPERMUTATION_GLOW;
1727 if (r_refdef.fogenabled)
1728 permutation |= SHADERPERMUTATION_FOG;
1729 if (rsurface.texture->colormapping)
1730 permutation |= SHADERPERMUTATION_COLORMAPPING;
1731 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1732 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1733 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1734 permutation |= SHADERPERMUTATION_REFLECTION;
1736 if(permutation & SHADERPERMUTATION_SPECULAR)
1737 if(r_shadow_glossexact.integer)
1738 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
1739 R_SetupShader_SetPermutation(mode, permutation);
1740 if (mode == SHADERMODE_LIGHTSOURCE)
1742 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1743 if (permutation & SHADERPERMUTATION_DIFFUSE)
1745 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1746 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1747 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1748 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1752 // ambient only is simpler
1753 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]);
1754 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1755 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1756 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1758 // additive passes are only darkened by fog, not tinted
1759 if (r_glsl_permutation->loc_FogColor >= 0)
1760 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1764 if (mode == SHADERMODE_LIGHTDIRECTION)
1766 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);
1767 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);
1768 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);
1769 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]);
1773 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
1774 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1775 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1777 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]);
1778 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1779 // additive passes are only darkened by fog, not tinted
1780 if (r_glsl_permutation->loc_FogColor >= 0)
1782 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1783 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1785 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1787 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);
1788 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]);
1789 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]);
1790 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1791 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1792 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1793 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1795 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1797 // The formula used is actually:
1798 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1799 // color.rgb *= SceneBrightness;
1801 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1802 // and do [[calculations]] here in the engine
1803 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1804 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1807 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1808 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1809 if (r_glsl_permutation->loc_Color_Pants >= 0)
1811 if (rsurface.texture->currentskinframe->pants)
1812 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1814 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1816 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1818 if (rsurface.texture->currentskinframe->shirt)
1819 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1821 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1823 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
1824 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
1826 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
1830 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1832 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1836 #define SKINFRAME_HASH 1024
1840 int loadsequence; // incremented each level change
1841 memexpandablearray_t array;
1842 skinframe_t *hash[SKINFRAME_HASH];
1845 r_skinframe_t r_skinframe;
1847 void R_SkinFrame_PrepareForPurge(void)
1849 r_skinframe.loadsequence++;
1850 // wrap it without hitting zero
1851 if (r_skinframe.loadsequence >= 200)
1852 r_skinframe.loadsequence = 1;
1855 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1859 // mark the skinframe as used for the purging code
1860 skinframe->loadsequence = r_skinframe.loadsequence;
1863 void R_SkinFrame_Purge(void)
1867 for (i = 0;i < SKINFRAME_HASH;i++)
1869 for (s = r_skinframe.hash[i];s;s = s->next)
1871 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1873 if (s->merged == s->base)
1875 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1876 R_PurgeTexture(s->stain );s->stain = NULL;
1877 R_PurgeTexture(s->merged);s->merged = NULL;
1878 R_PurgeTexture(s->base );s->base = NULL;
1879 R_PurgeTexture(s->pants );s->pants = NULL;
1880 R_PurgeTexture(s->shirt );s->shirt = NULL;
1881 R_PurgeTexture(s->nmap );s->nmap = NULL;
1882 R_PurgeTexture(s->gloss );s->gloss = NULL;
1883 R_PurgeTexture(s->glow );s->glow = NULL;
1884 R_PurgeTexture(s->fog );s->fog = NULL;
1885 s->loadsequence = 0;
1891 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1893 char basename[MAX_QPATH];
1895 Image_StripImageExtension(name, basename, sizeof(basename));
1897 if( last == NULL ) {
1899 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1900 item = r_skinframe.hash[hashindex];
1905 // linearly search through the hash bucket
1906 for( ; item ; item = item->next ) {
1907 if( !strcmp( item->basename, basename ) ) {
1914 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1918 char basename[MAX_QPATH];
1920 Image_StripImageExtension(name, basename, sizeof(basename));
1922 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1923 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1924 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1928 rtexture_t *dyntexture;
1929 // check whether its a dynamic texture
1930 dyntexture = CL_GetDynTexture( basename );
1931 if (!add && !dyntexture)
1933 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1934 memset(item, 0, sizeof(*item));
1935 strlcpy(item->basename, basename, sizeof(item->basename));
1936 item->base = dyntexture; // either NULL or dyntexture handle
1937 item->textureflags = textureflags;
1938 item->comparewidth = comparewidth;
1939 item->compareheight = compareheight;
1940 item->comparecrc = comparecrc;
1941 item->next = r_skinframe.hash[hashindex];
1942 r_skinframe.hash[hashindex] = item;
1944 else if( item->base == NULL )
1946 rtexture_t *dyntexture;
1947 // check whether its a dynamic texture
1948 // 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]
1949 dyntexture = CL_GetDynTexture( basename );
1950 item->base = dyntexture; // either NULL or dyntexture handle
1953 R_SkinFrame_MarkUsed(item);
1957 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
1959 unsigned long long avgcolor[5], wsum; \
1967 for(pix = 0; pix < cnt; ++pix) \
1970 for(comp = 0; comp < 3; ++comp) \
1972 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
1975 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1977 for(comp = 0; comp < 3; ++comp) \
1978 avgcolor[comp] += getpixel * w; \
1981 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1982 avgcolor[4] += getpixel; \
1984 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
1986 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
1987 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
1988 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
1989 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
1992 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
1994 // FIXME: it should be possible to disable loading various layers using
1995 // cvars, to prevent wasted loading time and memory usage if the user does
1997 qboolean loadnormalmap = true;
1998 qboolean loadgloss = true;
1999 qboolean loadpantsandshirt = true;
2000 qboolean loadglow = true;
2002 unsigned char *pixels;
2003 unsigned char *bumppixels;
2004 unsigned char *basepixels = NULL;
2005 int basepixels_width;
2006 int basepixels_height;
2007 skinframe_t *skinframe;
2011 if (cls.state == ca_dedicated)
2014 // return an existing skinframe if already loaded
2015 // if loading of the first image fails, don't make a new skinframe as it
2016 // would cause all future lookups of this to be missing
2017 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2018 if (skinframe && skinframe->base)
2021 basepixels = loadimagepixelsbgra(name, complain, true);
2022 if (basepixels == NULL)
2025 if (developer_loading.integer)
2026 Con_Printf("loading skin \"%s\"\n", name);
2028 // we've got some pixels to store, so really allocate this new texture now
2030 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2031 skinframe->stain = NULL;
2032 skinframe->merged = NULL;
2033 skinframe->base = r_texture_notexture;
2034 skinframe->pants = NULL;
2035 skinframe->shirt = NULL;
2036 skinframe->nmap = r_texture_blanknormalmap;
2037 skinframe->gloss = NULL;
2038 skinframe->glow = NULL;
2039 skinframe->fog = NULL;
2041 basepixels_width = image_width;
2042 basepixels_height = image_height;
2043 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);
2045 if (textureflags & TEXF_ALPHA)
2047 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2048 if (basepixels[j] < 255)
2050 if (j < basepixels_width * basepixels_height * 4)
2052 // has transparent pixels
2054 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2055 for (j = 0;j < image_width * image_height * 4;j += 4)
2060 pixels[j+3] = basepixels[j+3];
2062 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);
2067 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2068 //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]);
2070 // _norm is the name used by tenebrae and has been adopted as standard
2073 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2075 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);
2079 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2081 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2082 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2083 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);
2085 Mem_Free(bumppixels);
2087 else if (r_shadow_bumpscale_basetexture.value > 0)
2089 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2090 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2091 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);
2095 // _luma is supported for tenebrae compatibility
2096 // (I think it's a very stupid name, but oh well)
2097 // _glow is the preferred name
2098 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;}
2099 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;}
2100 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;}
2101 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;}
2104 Mem_Free(basepixels);
2109 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2112 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2115 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)
2120 for (i = 0;i < width*height;i++)
2121 if (((unsigned char *)&palette[in[i]])[3] > 0)
2123 if (i == width*height)
2126 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2129 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2130 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2133 unsigned char *temp1, *temp2;
2134 skinframe_t *skinframe;
2136 if (cls.state == ca_dedicated)
2139 // if already loaded just return it, otherwise make a new skinframe
2140 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2141 if (skinframe && skinframe->base)
2144 skinframe->stain = NULL;
2145 skinframe->merged = NULL;
2146 skinframe->base = r_texture_notexture;
2147 skinframe->pants = NULL;
2148 skinframe->shirt = NULL;
2149 skinframe->nmap = r_texture_blanknormalmap;
2150 skinframe->gloss = NULL;
2151 skinframe->glow = NULL;
2152 skinframe->fog = NULL;
2154 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2158 if (developer_loading.integer)
2159 Con_Printf("loading 32bit skin \"%s\"\n", name);
2161 if (r_shadow_bumpscale_basetexture.value > 0)
2163 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2164 temp2 = temp1 + width * height * 4;
2165 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2166 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2169 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2170 if (textureflags & TEXF_ALPHA)
2172 for (i = 3;i < width * height * 4;i += 4)
2173 if (skindata[i] < 255)
2175 if (i < width * height * 4)
2177 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2178 memcpy(fogpixels, skindata, width * height * 4);
2179 for (i = 0;i < width * height * 4;i += 4)
2180 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2181 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2182 Mem_Free(fogpixels);
2186 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2187 //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]);
2192 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2195 unsigned char *temp1, *temp2;
2196 unsigned int *palette;
2197 skinframe_t *skinframe;
2199 if (cls.state == ca_dedicated)
2202 // if already loaded just return it, otherwise make a new skinframe
2203 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2204 if (skinframe && skinframe->base)
2207 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2209 skinframe->stain = NULL;
2210 skinframe->merged = NULL;
2211 skinframe->base = r_texture_notexture;
2212 skinframe->pants = NULL;
2213 skinframe->shirt = NULL;
2214 skinframe->nmap = r_texture_blanknormalmap;
2215 skinframe->gloss = NULL;
2216 skinframe->glow = NULL;
2217 skinframe->fog = NULL;
2219 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2223 if (developer_loading.integer)
2224 Con_Printf("loading quake skin \"%s\"\n", name);
2226 if (r_shadow_bumpscale_basetexture.value > 0)
2228 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2229 temp2 = temp1 + width * height * 4;
2230 // use either a custom palette or the quake palette
2231 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2232 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2233 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2236 // use either a custom palette, or the quake palette
2237 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2238 if (loadglowtexture)
2239 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2240 if (loadpantsandshirt)
2242 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2243 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2245 if (skinframe->pants || skinframe->shirt)
2246 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
2247 if (textureflags & TEXF_ALPHA)
2249 for (i = 0;i < width * height;i++)
2250 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2252 if (i < width * height)
2253 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2256 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2257 //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]);
2262 skinframe_t *R_SkinFrame_LoadMissing(void)
2264 skinframe_t *skinframe;
2266 if (cls.state == ca_dedicated)
2269 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2270 skinframe->stain = NULL;
2271 skinframe->merged = NULL;
2272 skinframe->base = r_texture_notexture;
2273 skinframe->pants = NULL;
2274 skinframe->shirt = NULL;
2275 skinframe->nmap = r_texture_blanknormalmap;
2276 skinframe->gloss = NULL;
2277 skinframe->glow = NULL;
2278 skinframe->fog = NULL;
2280 skinframe->avgcolor[0] = rand() / RAND_MAX;
2281 skinframe->avgcolor[1] = rand() / RAND_MAX;
2282 skinframe->avgcolor[2] = rand() / RAND_MAX;
2283 skinframe->avgcolor[3] = 1;
2288 void gl_main_start(void)
2292 memset(r_queries, 0, sizeof(r_queries));
2294 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2295 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2297 // set up r_skinframe loading system for textures
2298 memset(&r_skinframe, 0, sizeof(r_skinframe));
2299 r_skinframe.loadsequence = 1;
2300 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2302 r_main_texturepool = R_AllocTexturePool();
2303 R_BuildBlankTextures();
2305 if (gl_texturecubemap)
2308 R_BuildNormalizationCube();
2310 r_texture_fogattenuation = NULL;
2311 r_texture_gammaramps = NULL;
2312 //r_texture_fogintensity = NULL;
2313 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2314 memset(&r_waterstate, 0, sizeof(r_waterstate));
2315 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2316 memset(&r_svbsp, 0, sizeof (r_svbsp));
2318 r_refdef.fogmasktable_density = 0;
2321 extern rtexture_t *loadingscreentexture;
2322 void gl_main_shutdown(void)
2325 qglDeleteQueriesARB(r_maxqueries, r_queries);
2329 memset(r_queries, 0, sizeof(r_queries));
2331 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2332 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2334 // clear out the r_skinframe state
2335 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2336 memset(&r_skinframe, 0, sizeof(r_skinframe));
2339 Mem_Free(r_svbsp.nodes);
2340 memset(&r_svbsp, 0, sizeof (r_svbsp));
2341 R_FreeTexturePool(&r_main_texturepool);
2342 loadingscreentexture = NULL;
2343 r_texture_blanknormalmap = NULL;
2344 r_texture_white = NULL;
2345 r_texture_grey128 = NULL;
2346 r_texture_black = NULL;
2347 r_texture_whitecube = NULL;
2348 r_texture_normalizationcube = NULL;
2349 r_texture_fogattenuation = NULL;
2350 r_texture_gammaramps = NULL;
2351 //r_texture_fogintensity = NULL;
2352 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2353 memset(&r_waterstate, 0, sizeof(r_waterstate));
2357 extern void CL_ParseEntityLump(char *entitystring);
2358 void gl_main_newmap(void)
2360 // FIXME: move this code to client
2362 char *entities, entname[MAX_QPATH];
2365 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2366 l = (int)strlen(entname) - 4;
2367 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2369 memcpy(entname + l, ".ent", 5);
2370 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2372 CL_ParseEntityLump(entities);
2377 if (cl.worldmodel->brush.entities)
2378 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2382 void GL_Main_Init(void)
2384 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2386 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2387 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2388 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2389 if (gamemode == GAME_NEHAHRA)
2391 Cvar_RegisterVariable (&gl_fogenable);
2392 Cvar_RegisterVariable (&gl_fogdensity);
2393 Cvar_RegisterVariable (&gl_fogred);
2394 Cvar_RegisterVariable (&gl_foggreen);
2395 Cvar_RegisterVariable (&gl_fogblue);
2396 Cvar_RegisterVariable (&gl_fogstart);
2397 Cvar_RegisterVariable (&gl_fogend);
2398 Cvar_RegisterVariable (&gl_skyclip);
2400 Cvar_RegisterVariable(&r_motionblur);
2401 Cvar_RegisterVariable(&r_motionblur_maxblur);
2402 Cvar_RegisterVariable(&r_motionblur_bmin);
2403 Cvar_RegisterVariable(&r_motionblur_vmin);
2404 Cvar_RegisterVariable(&r_motionblur_vmax);
2405 Cvar_RegisterVariable(&r_motionblur_vtime);
2406 Cvar_RegisterVariable(&r_motionblur_randomize);
2407 Cvar_RegisterVariable(&r_damageblur);
2408 Cvar_RegisterVariable(&r_motionblur_debug);
2409 Cvar_RegisterVariable(&r_depthfirst);
2410 Cvar_RegisterVariable(&r_useinfinitefarclip);
2411 Cvar_RegisterVariable(&r_nearclip);
2412 Cvar_RegisterVariable(&r_showbboxes);
2413 Cvar_RegisterVariable(&r_showsurfaces);
2414 Cvar_RegisterVariable(&r_showtris);
2415 Cvar_RegisterVariable(&r_shownormals);
2416 Cvar_RegisterVariable(&r_showlighting);
2417 Cvar_RegisterVariable(&r_showshadowvolumes);
2418 Cvar_RegisterVariable(&r_showcollisionbrushes);
2419 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2420 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2421 Cvar_RegisterVariable(&r_showdisabledepthtest);
2422 Cvar_RegisterVariable(&r_drawportals);
2423 Cvar_RegisterVariable(&r_drawentities);
2424 Cvar_RegisterVariable(&r_cullentities_trace);
2425 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2426 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2427 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2428 Cvar_RegisterVariable(&r_drawviewmodel);
2429 Cvar_RegisterVariable(&r_speeds);
2430 Cvar_RegisterVariable(&r_fullbrights);
2431 Cvar_RegisterVariable(&r_wateralpha);
2432 Cvar_RegisterVariable(&r_dynamic);
2433 Cvar_RegisterVariable(&r_fullbright);
2434 Cvar_RegisterVariable(&r_shadows);
2435 Cvar_RegisterVariable(&r_shadows_throwdistance);
2436 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2437 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2438 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2439 Cvar_RegisterVariable(&r_fog_exp2);
2440 Cvar_RegisterVariable(&r_drawfog);
2441 Cvar_RegisterVariable(&r_textureunits);
2442 Cvar_RegisterVariable(&r_glsl);
2443 Cvar_RegisterVariable(&r_glsl_contrastboost);
2444 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2445 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2446 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2447 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2448 Cvar_RegisterVariable(&r_glsl_postprocess);
2449 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2450 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2451 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2452 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2453 Cvar_RegisterVariable(&r_glsl_usegeneric);
2454 Cvar_RegisterVariable(&r_water);
2455 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2456 Cvar_RegisterVariable(&r_water_clippingplanebias);
2457 Cvar_RegisterVariable(&r_water_refractdistort);
2458 Cvar_RegisterVariable(&r_water_reflectdistort);
2459 Cvar_RegisterVariable(&r_lerpsprites);
2460 Cvar_RegisterVariable(&r_lerpmodels);
2461 Cvar_RegisterVariable(&r_lerplightstyles);
2462 Cvar_RegisterVariable(&r_waterscroll);
2463 Cvar_RegisterVariable(&r_bloom);
2464 Cvar_RegisterVariable(&r_bloom_colorscale);
2465 Cvar_RegisterVariable(&r_bloom_brighten);
2466 Cvar_RegisterVariable(&r_bloom_blur);
2467 Cvar_RegisterVariable(&r_bloom_resolution);
2468 Cvar_RegisterVariable(&r_bloom_colorexponent);
2469 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2470 Cvar_RegisterVariable(&r_hdr);
2471 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2472 Cvar_RegisterVariable(&r_hdr_glowintensity);
2473 Cvar_RegisterVariable(&r_hdr_range);
2474 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2475 Cvar_RegisterVariable(&developer_texturelogging);
2476 Cvar_RegisterVariable(&gl_lightmaps);
2477 Cvar_RegisterVariable(&r_test);
2478 Cvar_RegisterVariable(&r_batchmode);
2479 Cvar_RegisterVariable(&r_glsl_saturation);
2480 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2481 Cvar_SetValue("r_fullbrights", 0);
2482 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2484 Cvar_RegisterVariable(&r_track_sprites);
2485 Cvar_RegisterVariable(&r_track_sprites_flags);
2486 Cvar_RegisterVariable(&r_track_sprites_scalew);
2487 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2490 extern void R_Textures_Init(void);
2491 extern void GL_Draw_Init(void);
2492 extern void GL_Main_Init(void);
2493 extern void R_Shadow_Init(void);
2494 extern void R_Sky_Init(void);
2495 extern void GL_Surf_Init(void);
2496 extern void R_Particles_Init(void);
2497 extern void R_Explosion_Init(void);
2498 extern void gl_backend_init(void);
2499 extern void Sbar_Init(void);
2500 extern void R_LightningBeams_Init(void);
2501 extern void Mod_RenderInit(void);
2503 void Render_Init(void)
2515 R_LightningBeams_Init();
2524 extern char *ENGINE_EXTENSIONS;
2527 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2528 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2529 gl_version = (const char *)qglGetString(GL_VERSION);
2530 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2534 if (!gl_platformextensions)
2535 gl_platformextensions = "";
2537 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2538 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2539 Con_Printf("GL_VERSION: %s\n", gl_version);
2540 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2541 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2543 VID_CheckExtensions();
2545 // LordHavoc: report supported extensions
2546 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2548 // clear to black (loading plaque will be seen over this)
2550 qglClearColor(0,0,0,1);CHECKGLERROR
2551 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2554 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2558 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2560 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2563 p = r_refdef.view.frustum + i;
2568 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2572 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2576 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2580 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2584 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2588 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2592 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2596 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2604 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2608 for (i = 0;i < numplanes;i++)
2615 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2619 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2623 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2627 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2631 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2635 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2639 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2643 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2651 //==================================================================================
2653 static void R_View_UpdateEntityLighting (void)
2656 entity_render_t *ent;
2657 vec3_t tempdiffusenormal;
2659 for (i = 0;i < r_refdef.scene.numentities;i++)
2661 ent = r_refdef.scene.entities[i];
2663 // skip unseen models
2664 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
2668 if (ent->model && ent->model->brush.num_leafs)
2670 // TODO: use modellight for r_ambient settings on world?
2671 VectorSet(ent->modellight_ambient, 0, 0, 0);
2672 VectorSet(ent->modellight_diffuse, 0, 0, 0);
2673 VectorSet(ent->modellight_lightdir, 0, 0, 1);
2677 // fetch the lighting from the worldmodel data
2678 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));
2679 VectorClear(ent->modellight_diffuse);
2680 VectorClear(tempdiffusenormal);
2681 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
2684 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2685 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2688 VectorSet(ent->modellight_ambient, 1, 1, 1);
2690 // move the light direction into modelspace coordinates for lighting code
2691 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2692 if(VectorLength2(ent->modellight_lightdir) == 0)
2693 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2694 VectorNormalize(ent->modellight_lightdir);
2698 static void R_View_UpdateEntityVisible (void)
2701 entity_render_t *ent;
2703 if (!r_drawentities.integer)
2706 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2707 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2709 // worldmodel can check visibility
2710 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2711 for (i = 0;i < r_refdef.scene.numentities;i++)
2713 ent = r_refdef.scene.entities[i];
2714 if (!(ent->flags & renderimask))
2715 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)))
2716 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))
2717 r_refdef.viewcache.entityvisible[i] = true;
2719 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2721 for (i = 0;i < r_refdef.scene.numentities;i++)
2723 ent = r_refdef.scene.entities[i];
2724 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2726 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))
2727 ent->last_trace_visibility = realtime;
2728 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2729 r_refdef.viewcache.entityvisible[i] = 0;
2736 // no worldmodel or it can't check visibility
2737 for (i = 0;i < r_refdef.scene.numentities;i++)
2739 ent = r_refdef.scene.entities[i];
2740 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));
2745 /// only used if skyrendermasked, and normally returns false
2746 int R_DrawBrushModelsSky (void)
2749 entity_render_t *ent;
2751 if (!r_drawentities.integer)
2755 for (i = 0;i < r_refdef.scene.numentities;i++)
2757 if (!r_refdef.viewcache.entityvisible[i])
2759 ent = r_refdef.scene.entities[i];
2760 if (!ent->model || !ent->model->DrawSky)
2762 ent->model->DrawSky(ent);
2768 static void R_DrawNoModel(entity_render_t *ent);
2769 static void R_DrawModels(void)
2772 entity_render_t *ent;
2774 if (!r_drawentities.integer)
2777 for (i = 0;i < r_refdef.scene.numentities;i++)
2779 if (!r_refdef.viewcache.entityvisible[i])
2781 ent = r_refdef.scene.entities[i];
2782 r_refdef.stats.entities++;
2783 if (ent->model && ent->model->Draw != NULL)
2784 ent->model->Draw(ent);
2790 static void R_DrawModelsDepth(void)
2793 entity_render_t *ent;
2795 if (!r_drawentities.integer)
2798 for (i = 0;i < r_refdef.scene.numentities;i++)
2800 if (!r_refdef.viewcache.entityvisible[i])
2802 ent = r_refdef.scene.entities[i];
2803 if (ent->model && ent->model->DrawDepth != NULL)
2804 ent->model->DrawDepth(ent);
2808 static void R_DrawModelsDebug(void)
2811 entity_render_t *ent;
2813 if (!r_drawentities.integer)
2816 for (i = 0;i < r_refdef.scene.numentities;i++)
2818 if (!r_refdef.viewcache.entityvisible[i])
2820 ent = r_refdef.scene.entities[i];
2821 if (ent->model && ent->model->DrawDebug != NULL)
2822 ent->model->DrawDebug(ent);
2826 static void R_DrawModelsAddWaterPlanes(void)
2829 entity_render_t *ent;
2831 if (!r_drawentities.integer)
2834 for (i = 0;i < r_refdef.scene.numentities;i++)
2836 if (!r_refdef.viewcache.entityvisible[i])
2838 ent = r_refdef.scene.entities[i];
2839 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2840 ent->model->DrawAddWaterPlanes(ent);
2844 static void R_View_SetFrustum(void)
2847 double slopex, slopey;
2848 vec3_t forward, left, up, origin;
2850 // we can't trust r_refdef.view.forward and friends in reflected scenes
2851 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2854 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2855 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2856 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2857 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2858 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2859 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2860 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2861 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2862 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2863 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2864 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2865 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2869 zNear = r_refdef.nearclip;
2870 nudge = 1.0 - 1.0 / (1<<23);
2871 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2872 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2873 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2874 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2875 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2876 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2877 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2878 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2884 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2885 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2886 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2887 r_refdef.view.frustum[0].dist = m[15] - m[12];
2889 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2890 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2891 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2892 r_refdef.view.frustum[1].dist = m[15] + m[12];
2894 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2895 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2896 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2897 r_refdef.view.frustum[2].dist = m[15] - m[13];
2899 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2900 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2901 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2902 r_refdef.view.frustum[3].dist = m[15] + m[13];
2904 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2905 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2906 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2907 r_refdef.view.frustum[4].dist = m[15] - m[14];
2909 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2910 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2911 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2912 r_refdef.view.frustum[5].dist = m[15] + m[14];
2915 if (r_refdef.view.useperspective)
2917 slopex = 1.0 / r_refdef.view.frustum_x;
2918 slopey = 1.0 / r_refdef.view.frustum_y;
2919 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2920 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
2921 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
2922 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
2923 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2925 // Leaving those out was a mistake, those were in the old code, and they
2926 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2927 // I couldn't reproduce it after adding those normalizations. --blub
2928 VectorNormalize(r_refdef.view.frustum[0].normal);
2929 VectorNormalize(r_refdef.view.frustum[1].normal);
2930 VectorNormalize(r_refdef.view.frustum[2].normal);
2931 VectorNormalize(r_refdef.view.frustum[3].normal);
2933 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2934 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2935 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2936 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2937 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2939 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2940 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2941 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2942 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2943 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2947 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2948 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2949 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2950 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2951 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2952 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2953 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2954 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2955 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2956 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2958 r_refdef.view.numfrustumplanes = 5;
2960 if (r_refdef.view.useclipplane)
2962 r_refdef.view.numfrustumplanes = 6;
2963 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2966 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2967 PlaneClassify(r_refdef.view.frustum + i);
2969 // LordHavoc: note to all quake engine coders, Quake had a special case
2970 // for 90 degrees which assumed a square view (wrong), so I removed it,
2971 // Quake2 has it disabled as well.
2973 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2974 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2975 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2976 //PlaneClassify(&frustum[0]);
2978 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2979 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2980 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2981 //PlaneClassify(&frustum[1]);
2983 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2984 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2985 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2986 //PlaneClassify(&frustum[2]);
2988 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2989 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2990 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2991 //PlaneClassify(&frustum[3]);
2994 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2995 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2996 //PlaneClassify(&frustum[4]);
2999 void R_View_Update(void)
3001 R_View_SetFrustum();
3002 R_View_WorldVisibility(r_refdef.view.useclipplane);
3003 R_View_UpdateEntityVisible();
3004 R_View_UpdateEntityLighting();
3007 void R_SetupView(qboolean allowwaterclippingplane)
3009 if (!r_refdef.view.useperspective)
3010 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);
3011 else if (gl_stencil && r_useinfinitefarclip.integer)
3012 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
3014 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
3016 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
3018 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3020 // LordHavoc: couldn't figure out how to make this approach the
3021 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3022 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3023 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3024 dist = r_refdef.view.clipplane.dist;
3025 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
3029 void R_ResetViewRendering2D(void)
3033 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3034 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3035 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
3036 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3037 GL_Color(1, 1, 1, 1);
3038 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3039 GL_BlendFunc(GL_ONE, GL_ZERO);
3040 GL_AlphaTest(false);
3041 GL_ScissorTest(false);
3042 GL_DepthMask(false);
3043 GL_DepthRange(0, 1);
3044 GL_DepthTest(false);
3045 R_Mesh_Matrix(&identitymatrix);
3046 R_Mesh_ResetTextureState();
3047 GL_PolygonOffset(0, 0);
3048 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3049 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3050 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3051 qglStencilMask(~0);CHECKGLERROR
3052 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3053 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3054 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3055 R_SetupGenericShader(true);
3058 void R_ResetViewRendering3D(void)
3062 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3063 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3065 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3066 GL_Color(1, 1, 1, 1);
3067 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3068 GL_BlendFunc(GL_ONE, GL_ZERO);
3069 GL_AlphaTest(false);
3070 GL_ScissorTest(true);
3072 GL_DepthRange(0, 1);
3074 R_Mesh_Matrix(&identitymatrix);
3075 R_Mesh_ResetTextureState();
3076 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3077 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3078 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3079 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3080 qglStencilMask(~0);CHECKGLERROR
3081 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3082 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3083 GL_CullFace(r_refdef.view.cullface_back);
3084 R_SetupGenericShader(true);
3087 void R_RenderScene(void);
3088 void R_RenderWaterPlanes(void);
3090 static void R_Water_StartFrame(void)
3093 int waterwidth, waterheight, texturewidth, textureheight;
3094 r_waterstate_waterplane_t *p;
3096 // set waterwidth and waterheight to the water resolution that will be
3097 // used (often less than the screen resolution for faster rendering)
3098 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3099 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3101 // calculate desired texture sizes
3102 // can't use water if the card does not support the texture size
3103 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3104 texturewidth = textureheight = waterwidth = waterheight = 0;
3105 else if (gl_support_arb_texture_non_power_of_two)
3107 texturewidth = waterwidth;
3108 textureheight = waterheight;
3112 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3113 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3116 // allocate textures as needed
3117 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3119 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3120 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3122 if (p->texture_refraction)
3123 R_FreeTexture(p->texture_refraction);
3124 p->texture_refraction = NULL;
3125 if (p->texture_reflection)
3126 R_FreeTexture(p->texture_reflection);
3127 p->texture_reflection = NULL;
3129 memset(&r_waterstate, 0, sizeof(r_waterstate));
3130 r_waterstate.waterwidth = waterwidth;
3131 r_waterstate.waterheight = waterheight;
3132 r_waterstate.texturewidth = texturewidth;
3133 r_waterstate.textureheight = textureheight;
3136 if (r_waterstate.waterwidth)
3138 r_waterstate.enabled = true;
3140 // set up variables that will be used in shader setup
3141 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3142 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3143 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3144 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3147 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3148 r_waterstate.numwaterplanes = 0;
3151 void R_Water_AddWaterPlane(msurface_t *surface)
3153 int triangleindex, planeindex;
3159 r_waterstate_waterplane_t *p;
3160 texture_t *t = R_GetCurrentTexture(surface->texture);
3161 // just use the first triangle with a valid normal for any decisions
3162 VectorClear(normal);
3163 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3165 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3166 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3167 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3168 TriangleNormal(vert[0], vert[1], vert[2], normal);
3169 if (VectorLength2(normal) >= 0.001)
3173 VectorCopy(normal, plane.normal);
3174 VectorNormalize(plane.normal);
3175 plane.dist = DotProduct(vert[0], plane.normal);
3176 PlaneClassify(&plane);
3177 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3179 // skip backfaces (except if nocullface is set)
3180 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3182 VectorNegate(plane.normal, plane.normal);
3184 PlaneClassify(&plane);
3188 // find a matching plane if there is one
3189 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3190 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3192 if (planeindex >= r_waterstate.maxwaterplanes)
3193 return; // nothing we can do, out of planes
3195 // if this triangle does not fit any known plane rendered this frame, add one
3196 if (planeindex >= r_waterstate.numwaterplanes)
3198 // store the new plane
3199 r_waterstate.numwaterplanes++;
3201 // clear materialflags and pvs
3202 p->materialflags = 0;
3203 p->pvsvalid = false;
3205 // merge this surface's materialflags into the waterplane
3206 p->materialflags |= t->currentmaterialflags;
3207 // merge this surface's PVS into the waterplane
3208 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3209 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3210 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3212 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3217 static void R_Water_ProcessPlanes(void)
3219 r_refdef_view_t originalview;
3220 r_refdef_view_t myview;
3222 r_waterstate_waterplane_t *p;
3224 originalview = r_refdef.view;
3226 // make sure enough textures are allocated
3227 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3229 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3231 if (!p->texture_refraction)
3232 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);
3233 if (!p->texture_refraction)
3237 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3239 if (!p->texture_reflection)
3240 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);
3241 if (!p->texture_reflection)
3247 r_refdef.view = originalview;
3248 r_refdef.view.showdebug = false;
3249 r_refdef.view.width = r_waterstate.waterwidth;
3250 r_refdef.view.height = r_waterstate.waterheight;
3251 r_refdef.view.useclipplane = true;
3252 myview = r_refdef.view;
3253 r_waterstate.renderingscene = true;
3254 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3256 // render the normal view scene and copy into texture
3257 // (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)
3258 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3260 r_refdef.view = myview;
3261 r_refdef.view.clipplane = p->plane;
3262 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3263 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3264 PlaneClassify(&r_refdef.view.clipplane);
3266 R_ResetViewRendering3D();
3267 R_ClearScreen(r_refdef.fogenabled);
3271 // copy view into the screen texture
3272 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3273 GL_ActiveTexture(0);
3275 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
3278 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3280 r_refdef.view = myview;
3281 // render reflected scene and copy into texture
3282 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3283 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3284 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3285 r_refdef.view.clipplane = p->plane;
3286 // reverse the cullface settings for this render
3287 r_refdef.view.cullface_front = GL_FRONT;
3288 r_refdef.view.cullface_back = GL_BACK;
3289 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3291 r_refdef.view.usecustompvs = true;
3293 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3295 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3298 R_ResetViewRendering3D();
3299 R_ClearScreen(r_refdef.fogenabled);
3303 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3304 GL_ActiveTexture(0);
3306 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
3309 r_waterstate.renderingscene = false;
3310 r_refdef.view = originalview;
3311 R_ResetViewRendering3D();
3312 R_ClearScreen(r_refdef.fogenabled);
3316 r_refdef.view = originalview;
3317 r_waterstate.renderingscene = false;
3318 Cvar_SetValueQuick(&r_water, 0);
3319 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3323 void R_Bloom_StartFrame(void)
3325 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3327 // set bloomwidth and bloomheight to the bloom resolution that will be
3328 // used (often less than the screen resolution for faster rendering)
3329 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3330 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3331 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3332 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3333 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3335 // calculate desired texture sizes
3336 if (gl_support_arb_texture_non_power_of_two)
3338 screentexturewidth = r_refdef.view.width;
3339 screentextureheight = r_refdef.view.height;
3340 bloomtexturewidth = r_bloomstate.bloomwidth;
3341 bloomtextureheight = r_bloomstate.bloomheight;
3345 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3346 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3347 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3348 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3351 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))
3353 Cvar_SetValueQuick(&r_hdr, 0);
3354 Cvar_SetValueQuick(&r_bloom, 0);
3355 //Cvar_SetValueQuick(&r_motionblur, 0);
3358 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial))) && !r_bloom.integer && !r_hdr.integer && !r_motionblur.value)
3359 screentexturewidth = screentextureheight = 0;
3360 if (!r_hdr.integer && !r_bloom.integer)
3361 bloomtexturewidth = bloomtextureheight = 0;
3363 // allocate textures as needed
3364 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3366 if (r_bloomstate.texture_screen)
3367 R_FreeTexture(r_bloomstate.texture_screen);
3368 r_bloomstate.texture_screen = NULL;
3369 r_bloomstate.screentexturewidth = screentexturewidth;
3370 r_bloomstate.screentextureheight = screentextureheight;
3371 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3372 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);
3374 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3376 if (r_bloomstate.texture_bloom)
3377 R_FreeTexture(r_bloomstate.texture_bloom);
3378 r_bloomstate.texture_bloom = NULL;
3379 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3380 r_bloomstate.bloomtextureheight = bloomtextureheight;
3381 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3382 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);
3385 // set up a texcoord array for the full resolution screen image
3386 // (we have to keep this around to copy back during final render)
3387 r_bloomstate.screentexcoord2f[0] = 0;
3388 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3389 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3390 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3391 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3392 r_bloomstate.screentexcoord2f[5] = 0;
3393 r_bloomstate.screentexcoord2f[6] = 0;
3394 r_bloomstate.screentexcoord2f[7] = 0;
3396 // set up a texcoord array for the reduced resolution bloom image
3397 // (which will be additive blended over the screen image)
3398 r_bloomstate.bloomtexcoord2f[0] = 0;
3399 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3400 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3401 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3402 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3403 r_bloomstate.bloomtexcoord2f[5] = 0;
3404 r_bloomstate.bloomtexcoord2f[6] = 0;
3405 r_bloomstate.bloomtexcoord2f[7] = 0;
3407 if (r_hdr.integer || r_bloom.integer)
3409 r_bloomstate.enabled = true;
3410 r_bloomstate.hdr = r_hdr.integer != 0;
3414 void R_Bloom_CopyBloomTexture(float colorscale)
3416 r_refdef.stats.bloom++;
3418 // scale down screen texture to the bloom texture size
3420 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3421 GL_BlendFunc(GL_ONE, GL_ZERO);
3422 GL_Color(colorscale, colorscale, colorscale, 1);
3423 // TODO: optimize with multitexture or GLSL
3424 R_SetupGenericShader(true);
3425 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3426 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3427 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3428 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3430 // we now have a bloom image in the framebuffer
3431 // copy it into the bloom image texture for later processing
3432 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3433 GL_ActiveTexture(0);
3435 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
3436 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3439 void R_Bloom_CopyHDRTexture(void)
3441 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3442 GL_ActiveTexture(0);
3444 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
3445 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3448 void R_Bloom_MakeTexture(void)
3451 float xoffset, yoffset, r, brighten;
3453 r_refdef.stats.bloom++;
3455 R_ResetViewRendering2D();
3456 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3457 R_Mesh_ColorPointer(NULL, 0, 0);
3458 R_SetupGenericShader(true);
3460 // we have a bloom image in the framebuffer
3462 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3464 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3467 r = bound(0, r_bloom_colorexponent.value / x, 1);
3468 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3469 GL_Color(r, r, r, 1);
3470 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3471 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3472 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3473 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3475 // copy the vertically blurred bloom view to a texture
3476 GL_ActiveTexture(0);
3478 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3479 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3482 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3483 brighten = r_bloom_brighten.value;
3485 brighten *= r_hdr_range.value;
3486 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3487 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3489 for (dir = 0;dir < 2;dir++)
3491 // blend on at multiple vertical offsets to achieve a vertical blur
3492 // TODO: do offset blends using GLSL
3493 GL_BlendFunc(GL_ONE, GL_ZERO);
3494 for (x = -range;x <= range;x++)
3496 if (!dir){xoffset = 0;yoffset = x;}
3497 else {xoffset = x;yoffset = 0;}
3498 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3499 yoffset /= (float)r_bloomstate.bloomtextureheight;
3500 // compute a texcoord array with the specified x and y offset
3501 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3502 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3503 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3504 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3505 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3506 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3507 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3508 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3509 // this r value looks like a 'dot' particle, fading sharply to
3510 // black at the edges
3511 // (probably not realistic but looks good enough)
3512 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3513 //r = (dir ? 1.0f : brighten)/(range*2+1);
3514 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3515 GL_Color(r, r, r, 1);
3516 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3517 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3518 GL_BlendFunc(GL_ONE, GL_ONE);
3521 // copy the vertically blurred bloom view to a texture
3522 GL_ActiveTexture(0);
3524 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
3525 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3528 // apply subtract last
3529 // (just like it would be in a GLSL shader)
3530 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3532 GL_BlendFunc(GL_ONE, GL_ZERO);
3533 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3534 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3535 GL_Color(1, 1, 1, 1);
3536 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3537 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3539 GL_BlendFunc(GL_ONE, GL_ONE);
3540 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3541 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3542 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3543 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3544 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3545 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3546 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3548 // copy the darkened bloom view to a texture
3549 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3550 GL_ActiveTexture(0);
3552 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
3553 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3557 void R_HDR_RenderBloomTexture(void)
3559 int oldwidth, oldheight;
3560 float oldcolorscale;
3562 oldcolorscale = r_refdef.view.colorscale;
3563 oldwidth = r_refdef.view.width;
3564 oldheight = r_refdef.view.height;
3565 r_refdef.view.width = r_bloomstate.bloomwidth;
3566 r_refdef.view.height = r_bloomstate.bloomheight;
3568 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3569 // TODO: add exposure compensation features
3570 // TODO: add fp16 framebuffer support
3572 r_refdef.view.showdebug = false;
3573 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3575 R_ResetViewRendering3D();
3577 R_ClearScreen(r_refdef.fogenabled);
3578 if (r_timereport_active)
3579 R_TimeReport("HDRclear");
3582 if (r_timereport_active)
3583 R_TimeReport("visibility");
3585 r_waterstate.numwaterplanes = 0;
3586 if (r_waterstate.enabled)
3587 R_RenderWaterPlanes();
3589 r_refdef.view.showdebug = true;
3591 r_waterstate.numwaterplanes = 0;
3593 R_ResetViewRendering2D();
3595 R_Bloom_CopyHDRTexture();
3596 R_Bloom_MakeTexture();
3598 // restore the view settings
3599 r_refdef.view.width = oldwidth;
3600 r_refdef.view.height = oldheight;
3601 r_refdef.view.colorscale = oldcolorscale;
3603 R_ResetViewRendering3D();
3605 R_ClearScreen(r_refdef.fogenabled);
3606 if (r_timereport_active)
3607 R_TimeReport("viewclear");
3610 static void R_BlendView(void)
3612 if (r_bloomstate.texture_screen)
3614 // make sure the buffer is available
3615 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
3617 R_ResetViewRendering2D();
3618 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3619 R_Mesh_ColorPointer(NULL, 0, 0);
3620 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3621 GL_ActiveTexture(0);CHECKGLERROR
3623 if(r_motionblur.value > 0 || r_damageblur.value > 0)
3625 // declare alpha variable
3628 static float avgspeed;
3630 speed = VectorLength(cl.movement_velocity);
3632 a = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vtime.value), 1);
3633 avgspeed = avgspeed * (1 - a) + speed * a;
3635 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
3636 speed = bound(0, speed, 1);
3637 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
3639 // calculate values into a standard alpha
3642 (r_motionblur.value * speed / 80)
3644 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
3647 max(0.0001, cl.time - cl.oldtime) // fps independent
3650 a *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
3651 a = bound(0, a, r_motionblur_maxblur.value);
3653 // developer debug of current value
3654 if (r_motionblur_debug.value) { Con_Printf("blur alpha = %f\n", a); }
3659 R_SetupGenericShader(true);
3660 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3661 GL_Color(1, 1, 1, a); // to do: add color changing support for damage blur
3662 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3663 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3664 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3665 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3669 // copy view into the screen texture
3670 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
3671 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3674 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3676 unsigned int permutation =
3677 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3678 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3679 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3680 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
3681 | (r_glsl_saturation.value != 1 ? SHADERPERMUTATION_SATURATION : 0);
3683 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3685 // render simple bloom effect
3686 // copy the screen and shrink it and darken it for the bloom process
3687 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3688 // make the bloom texture
3689 R_Bloom_MakeTexture();
3692 R_ResetViewRendering2D();
3693 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3694 R_Mesh_ColorPointer(NULL, 0, 0);
3695 GL_Color(1, 1, 1, 1);
3696 GL_BlendFunc(GL_ONE, GL_ZERO);
3697 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3698 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3699 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3700 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3701 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3702 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3703 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3704 if (r_glsl_permutation->loc_TintColor >= 0)
3705 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3706 if (r_glsl_permutation->loc_ClientTime >= 0)
3707 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3708 if (r_glsl_permutation->loc_PixelSize >= 0)
3709 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3710 if (r_glsl_permutation->loc_UserVec1 >= 0)
3712 float a=0, b=0, c=0, d=0;
3713 #if _MSC_VER >= 1400
3714 #define sscanf sscanf_s
3716 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3717 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3719 if (r_glsl_permutation->loc_UserVec2 >= 0)
3721 float a=0, b=0, c=0, d=0;
3722 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3723 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3725 if (r_glsl_permutation->loc_UserVec3 >= 0)
3727 float a=0, b=0, c=0, d=0;
3728 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3729 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3731 if (r_glsl_permutation->loc_UserVec4 >= 0)
3733 float a=0, b=0, c=0, d=0;
3734 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3735 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3737 if (r_glsl_permutation->loc_Saturation >= 0)
3738 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
3739 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3740 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3746 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3748 // render high dynamic range bloom effect
3749 // the bloom texture was made earlier this render, so we just need to
3750 // blend it onto the screen...
3751 R_ResetViewRendering2D();
3752 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3753 R_Mesh_ColorPointer(NULL, 0, 0);
3754 R_SetupGenericShader(true);
3755 GL_Color(1, 1, 1, 1);
3756 GL_BlendFunc(GL_ONE, GL_ONE);
3757 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3758 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3759 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3760 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3762 else if (r_bloomstate.texture_bloom)
3764 // render simple bloom effect
3765 // copy the screen and shrink it and darken it for the bloom process
3766 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3767 // make the bloom texture
3768 R_Bloom_MakeTexture();
3769 // put the original screen image back in place and blend the bloom
3771 R_ResetViewRendering2D();
3772 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3773 R_Mesh_ColorPointer(NULL, 0, 0);
3774 GL_Color(1, 1, 1, 1);
3775 GL_BlendFunc(GL_ONE, GL_ZERO);
3776 // do both in one pass if possible
3777 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3778 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3779 if (r_textureunits.integer >= 2 && gl_combine.integer)
3781 R_SetupGenericTwoTextureShader(GL_ADD);
3782 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3783 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3787 R_SetupGenericShader(true);
3788 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3789 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3790 // now blend on the bloom texture
3791 GL_BlendFunc(GL_ONE, GL_ONE);
3792 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3793 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3795 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3796 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3798 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3800 // apply a color tint to the whole view
3801 R_ResetViewRendering2D();
3802 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3803 R_Mesh_ColorPointer(NULL, 0, 0);
3804 R_SetupGenericShader(false);
3805 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3806 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3807 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3811 matrix4x4_t r_waterscrollmatrix;
3813 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3815 if (r_refdef.fog_density)
3817 r_refdef.fogcolor[0] = r_refdef.fog_red;
3818 r_refdef.fogcolor[1] = r_refdef.fog_green;
3819 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3823 VectorCopy(r_refdef.fogcolor, fogvec);
3824 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3826 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3827 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3828 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3829 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3831 // color.rgb *= ContrastBoost * SceneBrightness;
3832 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3833 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3834 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3835 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3840 void R_UpdateVariables(void)
3844 r_refdef.scene.ambient = r_ambient.value;
3846 r_refdef.farclip = 4096;
3847 if (r_refdef.scene.worldmodel)
3848 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3849 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3851 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3852 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3853 r_refdef.polygonfactor = 0;
3854 r_refdef.polygonoffset = 0;
3855 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3856 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3858 r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
3859 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3860 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3861 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3862 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3863 if (r_showsurfaces.integer)
3865 r_refdef.scene.rtworld = false;
3866 r_refdef.scene.rtworldshadows = false;
3867 r_refdef.scene.rtdlight = false;
3868 r_refdef.scene.rtdlightshadows = false;
3869 r_refdef.lightmapintensity = 0;
3872 if (gamemode == GAME_NEHAHRA)
3874 if (gl_fogenable.integer)
3876 r_refdef.oldgl_fogenable = true;
3877 r_refdef.fog_density = gl_fogdensity.value;
3878 r_refdef.fog_red = gl_fogred.value;
3879 r_refdef.fog_green = gl_foggreen.value;
3880 r_refdef.fog_blue = gl_fogblue.value;
3881 r_refdef.fog_alpha = 1;
3882 r_refdef.fog_start = 0;
3883 r_refdef.fog_end = gl_skyclip.value;
3885 else if (r_refdef.oldgl_fogenable)
3887 r_refdef.oldgl_fogenable = false;
3888 r_refdef.fog_density = 0;
3889 r_refdef.fog_red = 0;
3890 r_refdef.fog_green = 0;
3891 r_refdef.fog_blue = 0;
3892 r_refdef.fog_alpha = 0;
3893 r_refdef.fog_start = 0;
3894 r_refdef.fog_end = 0;
3898 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3899 r_refdef.fog_start = max(0, r_refdef.fog_start);
3900 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3902 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3904 if (r_refdef.fog_density && r_drawfog.integer)
3906 r_refdef.fogenabled = true;
3907 // this is the point where the fog reaches 0.9986 alpha, which we
3908 // consider a good enough cutoff point for the texture
3909 // (0.9986 * 256 == 255.6)
3910 if (r_fog_exp2.integer)
3911 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3913 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3914 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3915 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3916 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3917 // fog color was already set
3918 // update the fog texture
3919 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)
3920 R_BuildFogTexture();
3923 r_refdef.fogenabled = false;
3925 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
3927 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
3929 // build GLSL gamma texture
3930 #define RAMPWIDTH 256
3931 unsigned short ramp[RAMPWIDTH * 3];
3932 unsigned char rampbgr[RAMPWIDTH][4];
3935 r_texture_gammaramps_serial = vid_gammatables_serial;
3937 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
3938 for(i = 0; i < RAMPWIDTH; ++i)
3940 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3941 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3942 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
3945 if (r_texture_gammaramps)
3947 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
3951 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);
3957 // remove GLSL gamma texture
3961 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3962 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3968 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3969 if( scenetype != r_currentscenetype ) {
3970 // store the old scenetype
3971 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3972 r_currentscenetype = scenetype;
3973 // move in the new scene
3974 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3983 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3985 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3986 if( scenetype == r_currentscenetype ) {
3987 return &r_refdef.scene;
3989 return &r_scenes_store[ scenetype ];
3998 void R_RenderView(void)
4000 r_frame++; // used only by R_GetCurrentTexture
4001 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4003 if (r_refdef.view.isoverlay)
4005 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4006 GL_Clear( GL_DEPTH_BUFFER_BIT );
4007 R_TimeReport("depthclear");
4009 r_refdef.view.showdebug = false;
4011 r_waterstate.enabled = false;
4012 r_waterstate.numwaterplanes = 0;
4020 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4021 return; //Host_Error ("R_RenderView: NULL worldmodel");
4023 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4025 // break apart the view matrix into vectors for various purposes
4026 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4027 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4028 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4029 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4030 // make an inverted copy of the view matrix for tracking sprites
4031 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4033 R_Shadow_UpdateWorldLightSelection();
4035 R_Bloom_StartFrame();
4036 R_Water_StartFrame();
4039 if (r_timereport_active)
4040 R_TimeReport("viewsetup");
4042 R_ResetViewRendering3D();
4044 if (r_refdef.view.clear || r_refdef.fogenabled)
4046 R_ClearScreen(r_refdef.fogenabled);
4047 if (r_timereport_active)
4048 R_TimeReport("viewclear");
4050 r_refdef.view.clear = true;
4052 // this produces a bloom texture to be used in R_BlendView() later
4054 R_HDR_RenderBloomTexture();
4056 r_refdef.view.showdebug = true;
4059 if (r_timereport_active)
4060 R_TimeReport("visibility");
4062 r_waterstate.numwaterplanes = 0;
4063 if (r_waterstate.enabled)
4064 R_RenderWaterPlanes();
4067 r_waterstate.numwaterplanes = 0;
4070 if (r_timereport_active)
4071 R_TimeReport("blendview");
4073 GL_Scissor(0, 0, vid.width, vid.height);
4074 GL_ScissorTest(false);
4078 void R_RenderWaterPlanes(void)
4080 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4082 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4083 if (r_timereport_active)
4084 R_TimeReport("waterworld");
4087 // don't let sound skip if going slow
4088 if (r_refdef.scene.extraupdate)
4091 R_DrawModelsAddWaterPlanes();
4092 if (r_timereport_active)
4093 R_TimeReport("watermodels");
4095 if (r_waterstate.numwaterplanes)
4097 R_Water_ProcessPlanes();
4098 if (r_timereport_active)
4099 R_TimeReport("waterscenes");
4103 extern void R_DrawLightningBeams (void);
4104 extern void VM_CL_AddPolygonsToMeshQueue (void);
4105 extern void R_DrawPortals (void);
4106 extern cvar_t cl_locs_show;
4107 static void R_DrawLocs(void);
4108 static void R_DrawEntityBBoxes(void);
4109 void R_RenderScene(void)
4111 r_refdef.stats.renders++;
4115 // don't let sound skip if going slow
4116 if (r_refdef.scene.extraupdate)
4119 R_MeshQueue_BeginScene();
4123 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);
4125 if (cl.csqc_vidvars.drawworld)
4127 // don't let sound skip if going slow
4128 if (r_refdef.scene.extraupdate)
4131 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4133 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4134 if (r_timereport_active)
4135 R_TimeReport("worldsky");
4138 if (R_DrawBrushModelsSky() && r_timereport_active)
4139 R_TimeReport("bmodelsky");
4142 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4144 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4145 if (r_timereport_active)
4146 R_TimeReport("worlddepth");
4148 if (r_depthfirst.integer >= 2)
4150 R_DrawModelsDepth();
4151 if (r_timereport_active)
4152 R_TimeReport("modeldepth");
4155 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4157 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4158 if (r_timereport_active)
4159 R_TimeReport("world");
4162 // don't let sound skip if going slow
4163 if (r_refdef.scene.extraupdate)
4167 if (r_timereport_active)
4168 R_TimeReport("models");
4170 // don't let sound skip if going slow
4171 if (r_refdef.scene.extraupdate)
4174 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
4176 R_DrawModelShadows();
4178 R_ResetViewRendering3D();
4180 // don't let sound skip if going slow
4181 if (r_refdef.scene.extraupdate)
4185 R_ShadowVolumeLighting(false);
4186 if (r_timereport_active)
4187 R_TimeReport("rtlights");
4189 // don't let sound skip if going slow
4190 if (r_refdef.scene.extraupdate)
4193 if (cl.csqc_vidvars.drawworld)
4195 R_DrawLightningBeams();
4196 if (r_timereport_active)
4197 R_TimeReport("lightning");
4200 if (r_timereport_active)
4201 R_TimeReport("decals");
4204 if (r_timereport_active)
4205 R_TimeReport("particles");
4208 if (r_timereport_active)
4209 R_TimeReport("explosions");
4212 R_SetupGenericShader(true);
4213 VM_CL_AddPolygonsToMeshQueue();
4215 if (r_refdef.view.showdebug)
4217 if (cl_locs_show.integer)
4220 if (r_timereport_active)
4221 R_TimeReport("showlocs");
4224 if (r_drawportals.integer)
4227 if (r_timereport_active)
4228 R_TimeReport("portals");
4231 if (r_showbboxes.value > 0)
4233 R_DrawEntityBBoxes();
4234 if (r_timereport_active)
4235 R_TimeReport("bboxes");
4239 R_SetupGenericShader(true);
4240 R_MeshQueue_RenderTransparent();
4241 if (r_timereport_active)
4242 R_TimeReport("drawtrans");
4244 R_SetupGenericShader(true);
4246 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))
4248 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4249 if (r_timereport_active)
4250 R_TimeReport("worlddebug");
4251 R_DrawModelsDebug();
4252 if (r_timereport_active)
4253 R_TimeReport("modeldebug");
4256 R_SetupGenericShader(true);
4258 if (cl.csqc_vidvars.drawworld)
4261 if (r_timereport_active)
4262 R_TimeReport("coronas");
4265 // don't let sound skip if going slow
4266 if (r_refdef.scene.extraupdate)
4269 R_ResetViewRendering2D();
4272 static const unsigned short bboxelements[36] =
4282 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4285 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4286 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4287 GL_DepthMask(false);
4288 GL_DepthRange(0, 1);
4289 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4290 R_Mesh_Matrix(&identitymatrix);
4291 R_Mesh_ResetTextureState();
4293 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4294 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4295 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4296 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4297 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4298 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4299 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4300 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4301 R_FillColors(color4f, 8, cr, cg, cb, ca);
4302 if (r_refdef.fogenabled)
4304 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4306 f1 = FogPoint_World(v);
4308 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4309 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4310 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4313 R_Mesh_VertexPointer(vertex3f, 0, 0);
4314 R_Mesh_ColorPointer(color4f, 0, 0);
4315 R_Mesh_ResetTextureState();
4316 R_SetupGenericShader(false);
4317 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4320 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4324 prvm_edict_t *edict;
4325 prvm_prog_t *prog_save = prog;
4327 // this function draws bounding boxes of server entities
4331 GL_CullFace(GL_NONE);
4332 R_SetupGenericShader(false);
4336 for (i = 0;i < numsurfaces;i++)
4338 edict = PRVM_EDICT_NUM(surfacelist[i]);
4339 switch ((int)edict->fields.server->solid)
4341 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4342 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4343 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4344 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4345 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4346 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4348 color[3] *= r_showbboxes.value;
4349 color[3] = bound(0, color[3], 1);
4350 GL_DepthTest(!r_showdisabledepthtest.integer);
4351 GL_CullFace(r_refdef.view.cullface_front);
4352 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4358 static void R_DrawEntityBBoxes(void)
4361 prvm_edict_t *edict;
4363 prvm_prog_t *prog_save = prog;
4365 // this function draws bounding boxes of server entities
4371 for (i = 0;i < prog->num_edicts;i++)
4373 edict = PRVM_EDICT_NUM(i);
4374 if (edict->priv.server->free)
4376 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4377 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4379 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4381 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4382 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4388 unsigned short nomodelelements[24] =
4400 float nomodelvertex3f[6*3] =
4410 float nomodelcolor4f[6*4] =
4412 0.0f, 0.0f, 0.5f, 1.0f,
4413 0.0f, 0.0f, 0.5f, 1.0f,
4414 0.0f, 0.5f, 0.0f, 1.0f,
4415 0.0f, 0.5f, 0.0f, 1.0f,
4416 0.5f, 0.0f, 0.0f, 1.0f,
4417 0.5f, 0.0f, 0.0f, 1.0f
4420 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4425 // this is only called once per entity so numsurfaces is always 1, and
4426 // surfacelist is always {0}, so this code does not handle batches
4427 R_Mesh_Matrix(&ent->matrix);
4429 if (ent->flags & EF_ADDITIVE)
4431 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4432 GL_DepthMask(false);
4434 else if (ent->alpha < 1)
4436 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4437 GL_DepthMask(false);
4441 GL_BlendFunc(GL_ONE, GL_ZERO);
4444 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4445 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4446 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4447 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4448 R_SetupGenericShader(false);
4449 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4450 if (r_refdef.fogenabled)
4453 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4454 R_Mesh_ColorPointer(color4f, 0, 0);
4455 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4456 f1 = FogPoint_World(org);
4458 for (i = 0, c = color4f;i < 6;i++, c += 4)
4460 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4461 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4462 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4466 else if (ent->alpha != 1)
4468 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4469 R_Mesh_ColorPointer(color4f, 0, 0);
4470 for (i = 0, c = color4f;i < 6;i++, c += 4)
4474 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4475 R_Mesh_ResetTextureState();
4476 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4479 void R_DrawNoModel(entity_render_t *ent)
4482 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4483 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4484 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4486 // R_DrawNoModelCallback(ent, 0);
4489 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4491 vec3_t right1, right2, diff, normal;
4493 VectorSubtract (org2, org1, normal);
4495 // calculate 'right' vector for start
4496 VectorSubtract (r_refdef.view.origin, org1, diff);
4497 CrossProduct (normal, diff, right1);
4498 VectorNormalize (right1);
4500 // calculate 'right' vector for end
4501 VectorSubtract (r_refdef.view.origin, org2, diff);
4502 CrossProduct (normal, diff, right2);
4503 VectorNormalize (right2);
4505 vert[ 0] = org1[0] + width * right1[0];
4506 vert[ 1] = org1[1] + width * right1[1];
4507 vert[ 2] = org1[2] + width * right1[2];
4508 vert[ 3] = org1[0] - width * right1[0];
4509 vert[ 4] = org1[1] - width * right1[1];
4510 vert[ 5] = org1[2] - width * right1[2];
4511 vert[ 6] = org2[0] - width * right2[0];
4512 vert[ 7] = org2[1] - width * right2[1];
4513 vert[ 8] = org2[2] - width * right2[2];
4514 vert[ 9] = org2[0] + width * right2[0];
4515 vert[10] = org2[1] + width * right2[1];
4516 vert[11] = org2[2] + width * right2[2];
4519 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4521 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)
4523 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4527 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4528 fog = FogPoint_World(origin);
4530 R_Mesh_Matrix(&identitymatrix);
4531 GL_BlendFunc(blendfunc1, blendfunc2);
4533 GL_CullFace(GL_NONE);
4535 GL_DepthMask(false);
4536 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4537 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4538 GL_DepthTest(!depthdisable);
4540 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4541 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4542 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4543 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4544 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4545 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4546 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4547 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4548 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4549 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4550 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4551 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4553 R_Mesh_VertexPointer(vertex3f, 0, 0);
4554 R_Mesh_ColorPointer(NULL, 0, 0);
4555 R_Mesh_ResetTextureState();
4556 R_SetupGenericShader(true);
4557 R_Mesh_TexBind(0, R_GetTexture(texture));
4558 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4559 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4560 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4561 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4563 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4565 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4566 GL_BlendFunc(blendfunc1, GL_ONE);
4568 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4569 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4573 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4578 VectorSet(v, x, y, z);
4579 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4580 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4582 if (i == mesh->numvertices)
4584 if (mesh->numvertices < mesh->maxvertices)
4586 VectorCopy(v, vertex3f);
4587 mesh->numvertices++;
4589 return mesh->numvertices;
4595 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4599 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4600 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4601 e = mesh->element3i + mesh->numtriangles * 3;
4602 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4604 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4605 if (mesh->numtriangles < mesh->maxtriangles)
4610 mesh->numtriangles++;
4612 element[1] = element[2];
4616 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4620 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4621 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4622 e = mesh->element3i + mesh->numtriangles * 3;
4623 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4625 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4626 if (mesh->numtriangles < mesh->maxtriangles)
4631 mesh->numtriangles++;
4633 element[1] = element[2];
4637 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4638 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4640 int planenum, planenum2;
4643 mplane_t *plane, *plane2;
4645 double temppoints[2][256*3];
4646 // figure out how large a bounding box we need to properly compute this brush
4648 for (w = 0;w < numplanes;w++)
4649 maxdist = max(maxdist, planes[w].dist);
4650 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4651 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4652 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4656 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4657 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4659 if (planenum2 == planenum)
4661 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);
4664 if (tempnumpoints < 3)
4666 // generate elements forming a triangle fan for this polygon
4667 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4671 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)
4673 texturelayer_t *layer;
4674 layer = t->currentlayers + t->currentnumlayers++;
4676 layer->depthmask = depthmask;
4677 layer->blendfunc1 = blendfunc1;
4678 layer->blendfunc2 = blendfunc2;
4679 layer->texture = texture;
4680 layer->texmatrix = *matrix;
4681 layer->color[0] = r * r_refdef.view.colorscale;
4682 layer->color[1] = g * r_refdef.view.colorscale;
4683 layer->color[2] = b * r_refdef.view.colorscale;
4684 layer->color[3] = a;
4687 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4690 index = parms[2] + r_refdef.scene.time * parms[3];
4691 index -= floor(index);
4695 case Q3WAVEFUNC_NONE:
4696 case Q3WAVEFUNC_NOISE:
4697 case Q3WAVEFUNC_COUNT:
4700 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4701 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4702 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4703 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4704 case Q3WAVEFUNC_TRIANGLE:
4706 f = index - floor(index);
4717 return (float)(parms[0] + parms[1] * f);
4720 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
4725 matrix4x4_t matrix, temp;
4726 switch(tcmod->tcmod)
4730 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4731 matrix = r_waterscrollmatrix;
4733 matrix = identitymatrix;
4735 case Q3TCMOD_ENTITYTRANSLATE:
4736 // this is used in Q3 to allow the gamecode to control texcoord
4737 // scrolling on the entity, which is not supported in darkplaces yet.
4738 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4740 case Q3TCMOD_ROTATE:
4741 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4742 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4743 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4746 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4748 case Q3TCMOD_SCROLL:
4749 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4751 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4752 w = (int) tcmod->parms[0];
4753 h = (int) tcmod->parms[1];
4754 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4756 idx = (int) floor(f * w * h);
4757 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4759 case Q3TCMOD_STRETCH:
4760 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4761 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4763 case Q3TCMOD_TRANSFORM:
4764 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4765 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4766 VectorSet(tcmat + 6, 0 , 0 , 1);
4767 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4768 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4770 case Q3TCMOD_TURBULENT:
4771 // this is handled in the RSurf_PrepareVertices function
4772 matrix = identitymatrix;
4776 Matrix4x4_Concat(texmatrix, &matrix, &temp);
4779 texture_t *R_GetCurrentTexture(texture_t *t)
4782 const entity_render_t *ent = rsurface.entity;
4783 dp_model_t *model = ent->model;
4784 q3shaderinfo_layer_tcmod_t *tcmod;
4786 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
4787 return t->currentframe;
4788 t->update_lastrenderframe = r_frame;
4789 t->update_lastrenderentity = (void *)ent;
4791 // switch to an alternate material if this is a q1bsp animated material
4793 texture_t *texture = t;
4794 int s = ent->skinnum;
4795 if ((unsigned int)s >= (unsigned int)model->numskins)
4797 if (model->skinscenes)
4799 if (model->skinscenes[s].framecount > 1)
4800 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4802 s = model->skinscenes[s].firstframe;
4805 t = t + s * model->num_surfaces;
4808 // use an alternate animation if the entity's frame is not 0,
4809 // and only if the texture has an alternate animation
4810 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
4811 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4813 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4815 texture->currentframe = t;
4818 // update currentskinframe to be a qw skin or animation frame
4819 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"))
4821 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4823 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4824 if (developer_loading.integer)
4825 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4826 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);
4828 t->currentskinframe = r_qwskincache_skinframe[i];
4829 if (t->currentskinframe == NULL)
4830 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4832 else if (t->numskinframes >= 2)
4833 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4834 if (t->backgroundnumskinframes >= 2)
4835 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
4837 t->currentmaterialflags = t->basematerialflags;
4838 t->currentalpha = ent->alpha;
4839 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4840 t->currentalpha *= r_wateralpha.value;
4841 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4842 t->currentalpha *= t->r_water_wateralpha;
4843 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4844 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4845 if (!(ent->flags & RENDER_LIGHT))
4846 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4847 else if (rsurface.modeltexcoordlightmap2f == NULL)
4849 // pick a model lighting mode
4850 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4851 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4853 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4855 if (ent->effects & EF_ADDITIVE)
4856 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4857 else if (t->currentalpha < 1)
4858 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4859 if (ent->effects & EF_DOUBLESIDED)
4860 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4861 if (ent->effects & EF_NODEPTHTEST)
4862 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4863 if (ent->flags & RENDER_VIEWMODEL)
4864 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4865 if (t->backgroundnumskinframes)
4866 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4867 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4869 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4870 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4873 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4875 // there is no tcmod
4876 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4878 t->currenttexmatrix = r_waterscrollmatrix;
4879 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
4883 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
4884 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
4887 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4888 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
4889 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4890 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
4892 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4893 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4894 t->glosstexture = r_texture_black;
4895 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4896 t->backgroundglosstexture = r_texture_black;
4897 t->specularpower = r_shadow_glossexponent.value;
4898 // TODO: store reference values for these in the texture?
4899 t->specularscale = 0;
4900 if (r_shadow_gloss.integer > 0)
4902 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4904 if (r_shadow_glossintensity.value > 0)
4906 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4907 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4908 t->specularscale = r_shadow_glossintensity.value;
4911 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4913 t->glosstexture = r_texture_white;
4914 t->backgroundglosstexture = r_texture_white;
4915 t->specularscale = r_shadow_gloss2intensity.value;
4919 // lightmaps mode looks bad with dlights using actual texturing, so turn
4920 // off the colormap and glossmap, but leave the normalmap on as it still
4921 // accurately represents the shading involved
4922 if (gl_lightmaps.integer)
4924 t->basetexture = r_texture_grey128;
4925 t->backgroundbasetexture = NULL;
4926 t->specularscale = 0;
4927 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
4930 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4931 VectorClear(t->dlightcolor);
4932 t->currentnumlayers = 0;
4933 if (t->currentmaterialflags & MATERIALFLAG_WALL)
4936 int blendfunc1, blendfunc2, depthmask;
4937 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4939 blendfunc1 = GL_SRC_ALPHA;
4940 blendfunc2 = GL_ONE;
4942 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4944 blendfunc1 = GL_SRC_ALPHA;
4945 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4947 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4949 blendfunc1 = t->customblendfunc[0];
4950 blendfunc2 = t->customblendfunc[1];
4954 blendfunc1 = GL_ONE;
4955 blendfunc2 = GL_ZERO;
4957 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4958 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4959 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4960 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4962 // fullbright is not affected by r_refdef.lightmapintensity
4963 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]);
4964 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4965 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]);
4966 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4967 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]);
4971 vec3_t ambientcolor;
4973 // set the color tint used for lights affecting this surface
4974 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4976 // q3bsp has no lightmap updates, so the lightstylevalue that
4977 // would normally be baked into the lightmap must be
4978 // applied to the color
4979 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4980 if (ent->model->type == mod_brushq3)
4981 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4982 colorscale *= r_refdef.lightmapintensity;
4983 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
4984 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4985 // basic lit geometry
4986 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]);
4987 // add pants/shirt if needed
4988 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4989 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]);
4990 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4991 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]);
4992 // now add ambient passes if needed
4993 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4995 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]);
4996 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4997 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]);
4998 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4999 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]);
5002 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5003 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]);
5004 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5006 // if this is opaque use alpha blend which will darken the earlier
5009 // if this is an alpha blended material, all the earlier passes
5010 // were darkened by fog already, so we only need to add the fog
5011 // color ontop through the fog mask texture
5013 // if this is an additive blended material, all the earlier passes
5014 // were darkened by fog already, and we should not add fog color
5015 // (because the background was not darkened, there is no fog color
5016 // that was lost behind it).
5017 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]);
5021 return t->currentframe;
5024 rsurfacestate_t rsurface;
5026 void R_Mesh_ResizeArrays(int newvertices)
5029 if (rsurface.array_size >= newvertices)
5031 if (rsurface.array_modelvertex3f)
5032 Mem_Free(rsurface.array_modelvertex3f);
5033 rsurface.array_size = (newvertices + 1023) & ~1023;
5034 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5035 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5036 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5037 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5038 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5039 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5040 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5041 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5042 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5043 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5044 rsurface.array_color4f = base + rsurface.array_size * 27;
5045 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5048 void RSurf_ActiveWorldEntity(void)
5050 dp_model_t *model = r_refdef.scene.worldmodel;
5051 //if (rsurface.entity == r_refdef.scene.worldentity)
5053 rsurface.entity = r_refdef.scene.worldentity;
5054 if (rsurface.array_size < model->surfmesh.num_vertices)
5055 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5056 rsurface.matrix = identitymatrix;
5057 rsurface.inversematrix = identitymatrix;
5058 R_Mesh_Matrix(&identitymatrix);
5059 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5060 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5061 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5062 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5063 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5064 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5065 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5066 rsurface.frameblend[0].lerp = 1;
5067 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5068 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5069 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5070 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5071 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5072 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5073 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5074 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5075 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5076 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5077 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5078 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5079 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5080 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5081 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5082 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5083 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5084 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5085 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5086 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5087 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5088 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5089 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5090 rsurface.modelelement3i = model->surfmesh.data_element3i;
5091 rsurface.modelelement3s = model->surfmesh.data_element3s;
5092 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5093 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5094 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5095 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5096 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5097 rsurface.modelsurfaces = model->data_surfaces;
5098 rsurface.generatedvertex = false;
5099 rsurface.vertex3f = rsurface.modelvertex3f;
5100 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5101 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5102 rsurface.svector3f = rsurface.modelsvector3f;
5103 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5104 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5105 rsurface.tvector3f = rsurface.modeltvector3f;
5106 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5107 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5108 rsurface.normal3f = rsurface.modelnormal3f;
5109 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5110 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5111 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5114 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5116 dp_model_t *model = ent->model;
5117 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5119 rsurface.entity = (entity_render_t *)ent;
5120 if (rsurface.array_size < model->surfmesh.num_vertices)
5121 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5122 rsurface.matrix = ent->matrix;
5123 rsurface.inversematrix = ent->inversematrix;
5124 R_Mesh_Matrix(&rsurface.matrix);
5125 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5126 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5127 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5128 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5129 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5130 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5131 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5132 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5133 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5134 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5135 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5136 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5137 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5138 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5139 if (ent->model->brush.submodel)
5141 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5142 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5144 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5148 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5149 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5150 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5151 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5152 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5154 else if (wantnormals)
5156 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5157 rsurface.modelsvector3f = NULL;
5158 rsurface.modeltvector3f = NULL;
5159 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5160 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5164 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5165 rsurface.modelsvector3f = NULL;
5166 rsurface.modeltvector3f = NULL;
5167 rsurface.modelnormal3f = NULL;
5168 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5170 rsurface.modelvertex3f_bufferobject = 0;
5171 rsurface.modelvertex3f_bufferoffset = 0;
5172 rsurface.modelsvector3f_bufferobject = 0;
5173 rsurface.modelsvector3f_bufferoffset = 0;
5174 rsurface.modeltvector3f_bufferobject = 0;
5175 rsurface.modeltvector3f_bufferoffset = 0;
5176 rsurface.modelnormal3f_bufferobject = 0;
5177 rsurface.modelnormal3f_bufferoffset = 0;
5178 rsurface.generatedvertex = true;
5182 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5183 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5184 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5185 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5186 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5187 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5188 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5189 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5190 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5191 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5192 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5193 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5194 rsurface.generatedvertex = false;
5196 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5197 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5198 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5199 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5200 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5201 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5202 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5203 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5204 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5205 rsurface.modelelement3i = model->surfmesh.data_element3i;
5206 rsurface.modelelement3s = model->surfmesh.data_element3s;
5207 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5208 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5209 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5210 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5211 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5212 rsurface.modelsurfaces = model->data_surfaces;
5213 rsurface.vertex3f = rsurface.modelvertex3f;
5214 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5215 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5216 rsurface.svector3f = rsurface.modelsvector3f;
5217 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5218 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5219 rsurface.tvector3f = rsurface.modeltvector3f;
5220 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5221 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5222 rsurface.normal3f = rsurface.modelnormal3f;
5223 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5224 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5225 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5228 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5229 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5232 int texturesurfaceindex;
5237 const float *v1, *in_tc;
5239 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5241 q3shaderinfo_deform_t *deform;
5242 // 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
5243 if (rsurface.generatedvertex)
5245 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5246 generatenormals = true;
5247 for (i = 0;i < Q3MAXDEFORMS;i++)
5249 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5251 generatetangents = true;
5252 generatenormals = true;
5254 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5255 generatenormals = true;
5257 if (generatenormals && !rsurface.modelnormal3f)
5259 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5260 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5261 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5262 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5264 if (generatetangents && !rsurface.modelsvector3f)
5266 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5267 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5268 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5269 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5270 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5271 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5272 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);
5275 rsurface.vertex3f = rsurface.modelvertex3f;
5276 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5277 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5278 rsurface.svector3f = rsurface.modelsvector3f;
5279 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5280 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5281 rsurface.tvector3f = rsurface.modeltvector3f;
5282 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5283 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5284 rsurface.normal3f = rsurface.modelnormal3f;
5285 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5286 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5287 // if vertices are deformed (sprite flares and things in maps, possibly
5288 // water waves, bulges and other deformations), generate them into
5289 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5290 // (may be static model data or generated data for an animated model, or
5291 // the previous deform pass)
5292 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5294 switch (deform->deform)
5297 case Q3DEFORM_PROJECTIONSHADOW:
5298 case Q3DEFORM_TEXT0:
5299 case Q3DEFORM_TEXT1:
5300 case Q3DEFORM_TEXT2:
5301 case Q3DEFORM_TEXT3:
5302 case Q3DEFORM_TEXT4:
5303 case Q3DEFORM_TEXT5:
5304 case Q3DEFORM_TEXT6:
5305 case Q3DEFORM_TEXT7:
5308 case Q3DEFORM_AUTOSPRITE:
5309 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5310 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5311 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5312 VectorNormalize(newforward);
5313 VectorNormalize(newright);
5314 VectorNormalize(newup);
5315 // make deformed versions of only the model vertices used by the specified surfaces
5316 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5318 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5319 // a single autosprite surface can contain multiple sprites...
5320 for (j = 0;j < surface->num_vertices - 3;j += 4)
5322 VectorClear(center);
5323 for (i = 0;i < 4;i++)
5324 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5325 VectorScale(center, 0.25f, center);
5326 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5327 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5328 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5329 for (i = 0;i < 4;i++)
5331 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5332 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5335 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);
5336 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);
5338 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5339 rsurface.vertex3f_bufferobject = 0;
5340 rsurface.vertex3f_bufferoffset = 0;
5341 rsurface.svector3f = rsurface.array_deformedsvector3f;
5342 rsurface.svector3f_bufferobject = 0;
5343 rsurface.svector3f_bufferoffset = 0;
5344 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5345 rsurface.tvector3f_bufferobject = 0;
5346 rsurface.tvector3f_bufferoffset = 0;
5347 rsurface.normal3f = rsurface.array_deformednormal3f;
5348 rsurface.normal3f_bufferobject = 0;
5349 rsurface.normal3f_bufferoffset = 0;
5351 case Q3DEFORM_AUTOSPRITE2:
5352 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5353 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5354 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5355 VectorNormalize(newforward);
5356 VectorNormalize(newright);
5357 VectorNormalize(newup);
5358 // make deformed versions of only the model vertices used by the specified surfaces
5359 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5361 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5362 const float *v1, *v2;
5372 memset(shortest, 0, sizeof(shortest));
5373 // a single autosprite surface can contain multiple sprites...
5374 for (j = 0;j < surface->num_vertices - 3;j += 4)
5376 VectorClear(center);
5377 for (i = 0;i < 4;i++)
5378 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5379 VectorScale(center, 0.25f, center);
5380 // find the two shortest edges, then use them to define the
5381 // axis vectors for rotating around the central axis
5382 for (i = 0;i < 6;i++)
5384 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5385 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5387 Debug_PolygonBegin(NULL, 0);
5388 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5389 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);
5390 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5393 l = VectorDistance2(v1, v2);
5394 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5396 l += (1.0f / 1024.0f);
5397 if (shortest[0].length2 > l || i == 0)
5399 shortest[1] = shortest[0];
5400 shortest[0].length2 = l;
5401 shortest[0].v1 = v1;
5402 shortest[0].v2 = v2;
5404 else if (shortest[1].length2 > l || i == 1)
5406 shortest[1].length2 = l;
5407 shortest[1].v1 = v1;
5408 shortest[1].v2 = v2;
5411 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5412 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5414 Debug_PolygonBegin(NULL, 0);
5415 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5416 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);
5417 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5420 // this calculates the right vector from the shortest edge
5421 // and the up vector from the edge midpoints
5422 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5423 VectorNormalize(right);
5424 VectorSubtract(end, start, up);
5425 VectorNormalize(up);
5426 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5427 //VectorSubtract(rsurface.modelorg, center, forward);
5428 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5429 VectorNegate(forward, forward);
5430 VectorReflect(forward, 0, up, forward);
5431 VectorNormalize(forward);
5432 CrossProduct(up, forward, newright);
5433 VectorNormalize(newright);
5435 Debug_PolygonBegin(NULL, 0);
5436 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);
5437 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5438 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5442 Debug_PolygonBegin(NULL, 0);
5443 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5444 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5445 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5448 // rotate the quad around the up axis vector, this is made
5449 // especially easy by the fact we know the quad is flat,
5450 // so we only have to subtract the center position and
5451 // measure distance along the right vector, and then
5452 // multiply that by the newright vector and add back the
5454 // we also need to subtract the old position to undo the
5455 // displacement from the center, which we do with a
5456 // DotProduct, the subtraction/addition of center is also
5457 // optimized into DotProducts here
5458 l = DotProduct(right, center);
5459 for (i = 0;i < 4;i++)
5461 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5462 f = DotProduct(right, v1) - l;
5463 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5466 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);
5467 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);
5469 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5470 rsurface.vertex3f_bufferobject = 0;
5471 rsurface.vertex3f_bufferoffset = 0;
5472 rsurface.svector3f = rsurface.array_deformedsvector3f;
5473 rsurface.svector3f_bufferobject = 0;
5474 rsurface.svector3f_bufferoffset = 0;
5475 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5476 rsurface.tvector3f_bufferobject = 0;
5477 rsurface.tvector3f_bufferoffset = 0;
5478 rsurface.normal3f = rsurface.array_deformednormal3f;
5479 rsurface.normal3f_bufferobject = 0;
5480 rsurface.normal3f_bufferoffset = 0;
5482 case Q3DEFORM_NORMAL:
5483 // deform the normals to make reflections wavey
5484 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5486 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5487 for (j = 0;j < surface->num_vertices;j++)
5490 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5491 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5492 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5493 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5494 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5495 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5496 VectorNormalize(normal);
5498 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);
5500 rsurface.svector3f = rsurface.array_deformedsvector3f;
5501 rsurface.svector3f_bufferobject = 0;
5502 rsurface.svector3f_bufferoffset = 0;
5503 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5504 rsurface.tvector3f_bufferobject = 0;
5505 rsurface.tvector3f_bufferoffset = 0;
5506 rsurface.normal3f = rsurface.array_deformednormal3f;
5507 rsurface.normal3f_bufferobject = 0;
5508 rsurface.normal3f_bufferoffset = 0;
5511 // deform vertex array to make wavey water and flags and such
5512 waveparms[0] = deform->waveparms[0];
5513 waveparms[1] = deform->waveparms[1];
5514 waveparms[2] = deform->waveparms[2];
5515 waveparms[3] = deform->waveparms[3];
5516 // this is how a divisor of vertex influence on deformation
5517 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5518 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5519 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5521 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5522 for (j = 0;j < surface->num_vertices;j++)
5524 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5525 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5526 // if the wavefunc depends on time, evaluate it per-vertex
5529 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5530 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5532 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5535 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5536 rsurface.vertex3f_bufferobject = 0;
5537 rsurface.vertex3f_bufferoffset = 0;
5539 case Q3DEFORM_BULGE:
5540 // deform vertex array to make the surface have moving bulges
5541 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5543 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5544 for (j = 0;j < surface->num_vertices;j++)
5546 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5547 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5550 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5551 rsurface.vertex3f_bufferobject = 0;
5552 rsurface.vertex3f_bufferoffset = 0;
5555 // deform vertex array
5556 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5557 VectorScale(deform->parms, scale, waveparms);
5558 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5560 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5561 for (j = 0;j < surface->num_vertices;j++)
5562 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5564 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5565 rsurface.vertex3f_bufferobject = 0;
5566 rsurface.vertex3f_bufferoffset = 0;
5570 // generate texcoords based on the chosen texcoord source
5571 switch(rsurface.texture->tcgen.tcgen)
5574 case Q3TCGEN_TEXTURE:
5575 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5576 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5577 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5579 case Q3TCGEN_LIGHTMAP:
5580 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5581 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5582 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5584 case Q3TCGEN_VECTOR:
5585 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5587 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5588 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)
5590 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5591 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5594 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5595 rsurface.texcoordtexture2f_bufferobject = 0;
5596 rsurface.texcoordtexture2f_bufferoffset = 0;
5598 case Q3TCGEN_ENVIRONMENT:
5599 // make environment reflections using a spheremap
5600 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5602 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5603 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5604 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5605 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5606 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5608 // identical to Q3A's method, but executed in worldspace so
5609 // carried models can be shiny too
5611 float viewer[3], d, reflected[3], worldreflected[3];
5613 VectorSubtract(rsurface.modelorg, vertex, viewer);
5614 // VectorNormalize(viewer);
5616 d = DotProduct(normal, viewer);
5618 reflected[0] = normal[0]*2*d - viewer[0];
5619 reflected[1] = normal[1]*2*d - viewer[1];
5620 reflected[2] = normal[2]*2*d - viewer[2];
5621 // note: this is proportinal to viewer, so we can normalize later
5623 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
5624 VectorNormalize(worldreflected);
5626 // note: this sphere map only uses world x and z!
5627 // so positive and negative y will LOOK THE SAME.
5628 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
5629 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
5632 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5633 rsurface.texcoordtexture2f_bufferobject = 0;
5634 rsurface.texcoordtexture2f_bufferoffset = 0;
5637 // the only tcmod that needs software vertex processing is turbulent, so
5638 // check for it here and apply the changes if needed
5639 // and we only support that as the first one
5640 // (handling a mixture of turbulent and other tcmods would be problematic
5641 // without punting it entirely to a software path)
5642 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5644 amplitude = rsurface.texture->tcmods[0].parms[1];
5645 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5646 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5648 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5649 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)
5651 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5652 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5655 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5656 rsurface.texcoordtexture2f_bufferobject = 0;
5657 rsurface.texcoordtexture2f_bufferoffset = 0;
5659 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5660 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5661 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5662 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5665 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5668 const msurface_t *surface = texturesurfacelist[0];
5669 const msurface_t *surface2;
5674 // TODO: lock all array ranges before render, rather than on each surface
5675 if (texturenumsurfaces == 1)
5677 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5678 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);
5680 else if (r_batchmode.integer == 2)
5682 #define MAXBATCHTRIANGLES 4096
5683 int batchtriangles = 0;
5684 int batchelements[MAXBATCHTRIANGLES*3];
5685 for (i = 0;i < texturenumsurfaces;i = j)
5687 surface = texturesurfacelist[i];
5689 if (surface->num_triangles > MAXBATCHTRIANGLES)
5691 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);
5694 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5695 batchtriangles = surface->num_triangles;
5696 firstvertex = surface->num_firstvertex;
5697 endvertex = surface->num_firstvertex + surface->num_vertices;
5698 for (;j < texturenumsurfaces;j++)
5700 surface2 = texturesurfacelist[j];
5701 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5703 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5704 batchtriangles += surface2->num_triangles;
5705 firstvertex = min(firstvertex, surface2->num_firstvertex);
5706 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5708 surface2 = texturesurfacelist[j-1];
5709 numvertices = endvertex - firstvertex;
5710 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5713 else if (r_batchmode.integer == 1)
5715 for (i = 0;i < texturenumsurfaces;i = j)
5717 surface = texturesurfacelist[i];
5718 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5719 if (texturesurfacelist[j] != surface2)
5721 surface2 = texturesurfacelist[j-1];
5722 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5723 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5724 GL_LockArrays(surface->num_firstvertex, numvertices);
5725 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5730 for (i = 0;i < texturenumsurfaces;i++)
5732 surface = texturesurfacelist[i];
5733 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5734 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);
5739 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5741 int i, planeindex, vertexindex;
5745 r_waterstate_waterplane_t *p, *bestp;
5746 msurface_t *surface;
5747 if (r_waterstate.renderingscene)
5749 for (i = 0;i < texturenumsurfaces;i++)
5751 surface = texturesurfacelist[i];
5752 if (lightmaptexunit >= 0)
5753 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5754 if (deluxemaptexunit >= 0)
5755 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5756 // pick the closest matching water plane
5759 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5762 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5764 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5765 d += fabs(PlaneDiff(vert, &p->plane));
5767 if (bestd > d || !bestp)
5775 if (refractiontexunit >= 0)
5776 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5777 if (reflectiontexunit >= 0)
5778 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5782 if (refractiontexunit >= 0)
5783 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5784 if (reflectiontexunit >= 0)
5785 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5787 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5788 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);
5792 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5796 const msurface_t *surface = texturesurfacelist[0];
5797 const msurface_t *surface2;
5802 // TODO: lock all array ranges before render, rather than on each surface
5803 if (texturenumsurfaces == 1)
5805 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5806 if (deluxemaptexunit >= 0)
5807 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5808 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5809 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);
5811 else if (r_batchmode.integer == 2)
5813 #define MAXBATCHTRIANGLES 4096
5814 int batchtriangles = 0;
5815 int batchelements[MAXBATCHTRIANGLES*3];
5816 for (i = 0;i < texturenumsurfaces;i = j)
5818 surface = texturesurfacelist[i];
5819 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5820 if (deluxemaptexunit >= 0)
5821 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5823 if (surface->num_triangles > MAXBATCHTRIANGLES)
5825 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);
5828 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5829 batchtriangles = surface->num_triangles;
5830 firstvertex = surface->num_firstvertex;
5831 endvertex = surface->num_firstvertex + surface->num_vertices;
5832 for (;j < texturenumsurfaces;j++)
5834 surface2 = texturesurfacelist[j];
5835 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5837 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5838 batchtriangles += surface2->num_triangles;
5839 firstvertex = min(firstvertex, surface2->num_firstvertex);
5840 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5842 surface2 = texturesurfacelist[j-1];
5843 numvertices = endvertex - firstvertex;
5844 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5847 else if (r_batchmode.integer == 1)
5850 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5851 for (i = 0;i < texturenumsurfaces;i = j)
5853 surface = texturesurfacelist[i];
5854 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5855 if (texturesurfacelist[j] != surface2)
5857 Con_Printf(" %i", j - i);
5860 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5862 for (i = 0;i < texturenumsurfaces;i = j)
5864 surface = texturesurfacelist[i];
5865 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5866 if (deluxemaptexunit >= 0)
5867 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5868 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5869 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5872 Con_Printf(" %i", j - i);
5874 surface2 = texturesurfacelist[j-1];
5875 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5876 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5877 GL_LockArrays(surface->num_firstvertex, numvertices);
5878 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5886 for (i = 0;i < texturenumsurfaces;i++)
5888 surface = texturesurfacelist[i];
5889 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5890 if (deluxemaptexunit >= 0)
5891 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5892 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5893 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);
5898 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5901 int texturesurfaceindex;
5902 if (r_showsurfaces.integer == 2)
5904 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5906 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5907 for (j = 0;j < surface->num_triangles;j++)
5909 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5910 GL_Color(f, f, f, 1);
5911 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5917 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5919 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5920 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5921 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);
5922 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5923 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);
5928 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
5930 int texturesurfaceindex;
5933 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5935 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5936 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)
5944 rsurface.lightmapcolor4f = rsurface.array_color4f;
5945 rsurface.lightmapcolor4f_bufferobject = 0;
5946 rsurface.lightmapcolor4f_bufferoffset = 0;
5949 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5951 int texturesurfaceindex;
5955 if (rsurface.lightmapcolor4f)
5957 // generate color arrays for the surfaces in this list
5958 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5960 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5961 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)
5963 f = FogPoint_Model(v);
5973 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5975 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5976 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)
5978 f = FogPoint_Model(v);
5986 rsurface.lightmapcolor4f = rsurface.array_color4f;
5987 rsurface.lightmapcolor4f_bufferobject = 0;
5988 rsurface.lightmapcolor4f_bufferoffset = 0;
5991 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
5993 int texturesurfaceindex;
5997 if (!rsurface.lightmapcolor4f)
5999 // generate color arrays for the surfaces in this list
6000 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6002 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6003 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)
6005 f = FogPoint_Model(v);
6006 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6007 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6008 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6012 rsurface.lightmapcolor4f = rsurface.array_color4f;
6013 rsurface.lightmapcolor4f_bufferobject = 0;
6014 rsurface.lightmapcolor4f_bufferoffset = 0;
6017 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6019 int texturesurfaceindex;
6022 if (!rsurface.lightmapcolor4f)
6024 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6026 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6027 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)
6035 rsurface.lightmapcolor4f = rsurface.array_color4f;
6036 rsurface.lightmapcolor4f_bufferobject = 0;
6037 rsurface.lightmapcolor4f_bufferoffset = 0;
6040 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6042 int texturesurfaceindex;
6045 if (!rsurface.lightmapcolor4f)
6047 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6049 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6050 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)
6052 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6053 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6054 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6058 rsurface.lightmapcolor4f = rsurface.array_color4f;
6059 rsurface.lightmapcolor4f_bufferobject = 0;
6060 rsurface.lightmapcolor4f_bufferoffset = 0;
6063 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6066 rsurface.lightmapcolor4f = NULL;
6067 rsurface.lightmapcolor4f_bufferobject = 0;
6068 rsurface.lightmapcolor4f_bufferoffset = 0;
6069 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6070 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6071 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6072 GL_Color(r, g, b, a);
6073 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6076 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6078 // TODO: optimize applyfog && applycolor case
6079 // just apply fog if necessary, and tint the fog color array if necessary
6080 rsurface.lightmapcolor4f = NULL;
6081 rsurface.lightmapcolor4f_bufferobject = 0;
6082 rsurface.lightmapcolor4f_bufferoffset = 0;
6083 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6084 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6085 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6086 GL_Color(r, g, b, a);
6087 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6090 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6092 int texturesurfaceindex;
6096 if (texturesurfacelist[0]->lightmapinfo)
6098 // generate color arrays for the surfaces in this list
6099 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6101 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6102 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6104 if (surface->lightmapinfo->samples)
6106 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6107 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6108 VectorScale(lm, scale, c);
6109 if (surface->lightmapinfo->styles[1] != 255)
6111 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6113 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6114 VectorMA(c, scale, lm, c);
6115 if (surface->lightmapinfo->styles[2] != 255)
6118 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6119 VectorMA(c, scale, lm, c);
6120 if (surface->lightmapinfo->styles[3] != 255)
6123 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6124 VectorMA(c, scale, lm, c);
6134 rsurface.lightmapcolor4f = rsurface.array_color4f;
6135 rsurface.lightmapcolor4f_bufferobject = 0;
6136 rsurface.lightmapcolor4f_bufferoffset = 0;
6140 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6141 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6142 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6144 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6145 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6146 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6147 GL_Color(r, g, b, a);
6148 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6151 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6153 int texturesurfaceindex;
6156 float *v, *c, *c2, alpha;
6157 vec3_t ambientcolor;
6158 vec3_t diffusecolor;
6162 VectorCopy(rsurface.modellight_lightdir, lightdir);
6163 f = 0.5f * r_refdef.lightmapintensity;
6164 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6165 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6166 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6167 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6168 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6169 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6171 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6173 // generate color arrays for the surfaces in this list
6174 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6176 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6177 int numverts = surface->num_vertices;
6178 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6179 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6180 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6181 // q3-style directional shading
6182 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6184 if ((f = DotProduct(c2, lightdir)) > 0)
6185 VectorMA(ambientcolor, f, diffusecolor, c);
6187 VectorCopy(ambientcolor, c);
6195 rsurface.lightmapcolor4f = rsurface.array_color4f;
6196 rsurface.lightmapcolor4f_bufferobject = 0;
6197 rsurface.lightmapcolor4f_bufferoffset = 0;
6198 *applycolor = false;
6202 *r = ambientcolor[0];
6203 *g = ambientcolor[1];
6204 *b = ambientcolor[2];
6205 rsurface.lightmapcolor4f = NULL;
6206 rsurface.lightmapcolor4f_bufferobject = 0;
6207 rsurface.lightmapcolor4f_bufferoffset = 0;
6211 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6213 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6214 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6215 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6216 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6217 GL_Color(r, g, b, a);
6218 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6221 void RSurf_SetupDepthAndCulling(void)
6223 // submodels are biased to avoid z-fighting with world surfaces that they
6224 // may be exactly overlapping (avoids z-fighting artifacts on certain
6225 // doors and things in Quake maps)
6226 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6227 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6228 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6229 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6232 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6234 // transparent sky would be ridiculous
6235 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6237 R_SetupGenericShader(false);
6240 skyrendernow = false;
6241 // we have to force off the water clipping plane while rendering sky
6245 // restore entity matrix
6246 R_Mesh_Matrix(&rsurface.matrix);
6248 RSurf_SetupDepthAndCulling();
6250 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6251 // skymasking on them, and Quake3 never did sky masking (unlike
6252 // software Quake and software Quake2), so disable the sky masking
6253 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6254 // and skymasking also looks very bad when noclipping outside the
6255 // level, so don't use it then either.
6256 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6258 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6259 R_Mesh_ColorPointer(NULL, 0, 0);
6260 R_Mesh_ResetTextureState();
6261 if (skyrendermasked)
6263 R_SetupDepthOrShadowShader();
6264 // depth-only (masking)
6265 GL_ColorMask(0,0,0,0);
6266 // just to make sure that braindead drivers don't draw
6267 // anything despite that colormask...
6268 GL_BlendFunc(GL_ZERO, GL_ONE);
6272 R_SetupGenericShader(false);
6274 GL_BlendFunc(GL_ONE, GL_ZERO);
6276 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6277 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6278 if (skyrendermasked)
6279 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6281 R_Mesh_ResetTextureState();
6282 GL_Color(1, 1, 1, 1);
6285 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6287 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6290 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6291 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6292 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6293 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6294 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6295 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6296 if (rsurface.texture->backgroundcurrentskinframe)
6298 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6299 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6300 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6301 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6303 if(rsurface.texture->colormapping)
6305 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6306 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6308 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6309 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6310 R_Mesh_ColorPointer(NULL, 0, 0);
6312 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6314 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6316 // render background
6317 GL_BlendFunc(GL_ONE, GL_ZERO);
6319 GL_AlphaTest(false);
6321 GL_Color(1, 1, 1, 1);
6322 R_Mesh_ColorPointer(NULL, 0, 0);
6324 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6325 if (r_glsl_permutation)
6327 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6328 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6329 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6330 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6331 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6332 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6333 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);
6335 GL_LockArrays(0, 0);
6337 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6338 GL_DepthMask(false);
6339 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6340 R_Mesh_ColorPointer(NULL, 0, 0);
6342 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6343 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6344 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6347 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6348 if (!r_glsl_permutation)
6351 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6352 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6353 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6354 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6355 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6356 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6358 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6360 GL_BlendFunc(GL_ONE, GL_ZERO);
6362 GL_AlphaTest(false);
6366 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6367 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6368 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6371 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6373 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6374 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);
6376 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6380 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6381 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);
6383 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6385 GL_LockArrays(0, 0);
6388 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6390 // OpenGL 1.3 path - anything not completely ancient
6391 int texturesurfaceindex;
6392 qboolean applycolor;
6396 const texturelayer_t *layer;
6397 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6399 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6402 int layertexrgbscale;
6403 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6405 if (layerindex == 0)
6409 GL_AlphaTest(false);
6410 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6413 GL_DepthMask(layer->depthmask && writedepth);
6414 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6415 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6417 layertexrgbscale = 4;
6418 VectorScale(layer->color, 0.25f, layercolor);
6420 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6422 layertexrgbscale = 2;
6423 VectorScale(layer->color, 0.5f, layercolor);
6427 layertexrgbscale = 1;
6428 VectorScale(layer->color, 1.0f, layercolor);
6430 layercolor[3] = layer->color[3];
6431 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6432 R_Mesh_ColorPointer(NULL, 0, 0);
6433 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6434 switch (layer->type)
6436 case TEXTURELAYERTYPE_LITTEXTURE:
6437 memset(&m, 0, sizeof(m));
6438 m.tex[0] = R_GetTexture(r_texture_white);
6439 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6440 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6441 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6442 m.tex[1] = R_GetTexture(layer->texture);
6443 m.texmatrix[1] = layer->texmatrix;
6444 m.texrgbscale[1] = layertexrgbscale;
6445 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6446 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6447 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6448 R_Mesh_TextureState(&m);
6449 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6450 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6451 else if (rsurface.uselightmaptexture)
6452 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6454 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6456 case TEXTURELAYERTYPE_TEXTURE:
6457 memset(&m, 0, sizeof(m));
6458 m.tex[0] = R_GetTexture(layer->texture);
6459 m.texmatrix[0] = layer->texmatrix;
6460 m.texrgbscale[0] = layertexrgbscale;
6461 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6462 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6463 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6464 R_Mesh_TextureState(&m);
6465 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6467 case TEXTURELAYERTYPE_FOG:
6468 memset(&m, 0, sizeof(m));
6469 m.texrgbscale[0] = layertexrgbscale;
6472 m.tex[0] = R_GetTexture(layer->texture);
6473 m.texmatrix[0] = layer->texmatrix;
6474 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6475 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6476 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6478 R_Mesh_TextureState(&m);
6479 // generate a color array for the fog pass
6480 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6481 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6485 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6486 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)
6488 f = 1 - FogPoint_Model(v);
6489 c[0] = layercolor[0];
6490 c[1] = layercolor[1];
6491 c[2] = layercolor[2];
6492 c[3] = f * layercolor[3];
6495 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6498 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6500 GL_LockArrays(0, 0);
6503 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6505 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6506 GL_AlphaTest(false);
6510 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6512 // OpenGL 1.1 - crusty old voodoo path
6513 int texturesurfaceindex;
6517 const texturelayer_t *layer;
6518 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6520 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6522 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6524 if (layerindex == 0)
6528 GL_AlphaTest(false);
6529 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6532 GL_DepthMask(layer->depthmask && writedepth);
6533 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6534 R_Mesh_ColorPointer(NULL, 0, 0);
6535 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6536 switch (layer->type)
6538 case TEXTURELAYERTYPE_LITTEXTURE:
6539 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6541 // two-pass lit texture with 2x rgbscale
6542 // first the lightmap pass
6543 memset(&m, 0, sizeof(m));
6544 m.tex[0] = R_GetTexture(r_texture_white);
6545 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6546 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6547 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6548 R_Mesh_TextureState(&m);
6549 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6550 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6551 else if (rsurface.uselightmaptexture)
6552 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6554 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6555 GL_LockArrays(0, 0);
6556 // then apply the texture to it
6557 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6558 memset(&m, 0, sizeof(m));
6559 m.tex[0] = R_GetTexture(layer->texture);
6560 m.texmatrix[0] = layer->texmatrix;
6561 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6562 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6563 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6564 R_Mesh_TextureState(&m);
6565 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);
6569 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6570 memset(&m, 0, sizeof(m));
6571 m.tex[0] = R_GetTexture(layer->texture);
6572 m.texmatrix[0] = layer->texmatrix;
6573 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6574 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6575 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6576 R_Mesh_TextureState(&m);
6577 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6578 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);
6580 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);
6583 case TEXTURELAYERTYPE_TEXTURE:
6584 // singletexture unlit texture with transparency support
6585 memset(&m, 0, sizeof(m));
6586 m.tex[0] = R_GetTexture(layer->texture);
6587 m.texmatrix[0] = layer->texmatrix;
6588 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6589 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6590 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6591 R_Mesh_TextureState(&m);
6592 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);
6594 case TEXTURELAYERTYPE_FOG:
6595 // singletexture fogging
6596 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6599 memset(&m, 0, sizeof(m));
6600 m.tex[0] = R_GetTexture(layer->texture);
6601 m.texmatrix[0] = layer->texmatrix;
6602 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6603 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6604 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6605 R_Mesh_TextureState(&m);
6608 R_Mesh_ResetTextureState();
6609 // generate a color array for the fog pass
6610 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6614 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6615 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)
6617 f = 1 - FogPoint_Model(v);
6618 c[0] = layer->color[0];
6619 c[1] = layer->color[1];
6620 c[2] = layer->color[2];
6621 c[3] = f * layer->color[3];
6624 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6627 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6629 GL_LockArrays(0, 0);
6632 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6634 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6635 GL_AlphaTest(false);
6639 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6643 GL_AlphaTest(false);
6644 R_Mesh_ColorPointer(NULL, 0, 0);
6645 R_Mesh_ResetTextureState();
6646 R_SetupGenericShader(false);
6648 if(rsurface.texture && rsurface.texture->currentskinframe)
6649 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6658 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6660 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
6661 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
6662 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
6665 // brighten it up (as texture value 127 means "unlit")
6666 c[0] *= 2 * r_refdef.view.colorscale;
6667 c[1] *= 2 * r_refdef.view.colorscale;
6668 c[2] *= 2 * r_refdef.view.colorscale;
6670 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6671 c[3] *= r_wateralpha.value;
6673 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6675 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6676 GL_DepthMask(false);
6678 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6680 GL_BlendFunc(GL_ONE, GL_ONE);
6681 GL_DepthMask(false);
6683 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6685 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6686 GL_DepthMask(false);
6688 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6690 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6691 GL_DepthMask(false);
6695 GL_BlendFunc(GL_ONE, GL_ZERO);
6696 GL_DepthMask(writedepth);
6699 rsurface.lightmapcolor4f = NULL;
6701 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6703 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6705 rsurface.lightmapcolor4f = NULL;
6706 rsurface.lightmapcolor4f_bufferobject = 0;
6707 rsurface.lightmapcolor4f_bufferoffset = 0;
6709 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6711 qboolean applycolor = true;
6714 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6716 r_refdef.lightmapintensity = 1;
6717 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6718 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6722 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6724 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6725 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6726 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6729 if(!rsurface.lightmapcolor4f)
6730 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6732 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6733 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6734 if(r_refdef.fogenabled)
6735 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6737 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6738 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6741 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6744 RSurf_SetupDepthAndCulling();
6745 if (r_showsurfaces.integer == 3)
6746 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6747 else if (r_glsl.integer && gl_support_fragment_shader)
6748 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6749 else if (gl_combine.integer && r_textureunits.integer >= 2)
6750 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6752 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6756 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6759 RSurf_SetupDepthAndCulling();
6760 if (r_showsurfaces.integer == 3)
6761 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6762 else if (r_glsl.integer && gl_support_fragment_shader)
6763 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6764 else if (gl_combine.integer && r_textureunits.integer >= 2)
6765 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6767 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6771 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6774 int texturenumsurfaces, endsurface;
6776 msurface_t *surface;
6777 msurface_t *texturesurfacelist[1024];
6779 // if the model is static it doesn't matter what value we give for
6780 // wantnormals and wanttangents, so this logic uses only rules applicable
6781 // to a model, knowing that they are meaningless otherwise
6782 if (ent == r_refdef.scene.worldentity)
6783 RSurf_ActiveWorldEntity();
6784 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6785 RSurf_ActiveModelEntity(ent, false, false);
6787 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6789 for (i = 0;i < numsurfaces;i = j)
6792 surface = rsurface.modelsurfaces + surfacelist[i];
6793 texture = surface->texture;
6794 rsurface.texture = R_GetCurrentTexture(texture);
6795 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6796 // scan ahead until we find a different texture
6797 endsurface = min(i + 1024, numsurfaces);
6798 texturenumsurfaces = 0;
6799 texturesurfacelist[texturenumsurfaces++] = surface;
6800 for (;j < endsurface;j++)
6802 surface = rsurface.modelsurfaces + surfacelist[j];
6803 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6805 texturesurfacelist[texturenumsurfaces++] = surface;
6807 // render the range of surfaces
6808 if (ent == r_refdef.scene.worldentity)
6809 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6811 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6813 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6814 GL_AlphaTest(false);
6817 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6819 const entity_render_t *queueentity = r_refdef.scene.worldentity;
6823 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6825 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6827 RSurf_SetupDepthAndCulling();
6828 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6829 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6831 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6833 RSurf_SetupDepthAndCulling();
6834 GL_AlphaTest(false);
6835 R_Mesh_ColorPointer(NULL, 0, 0);
6836 R_Mesh_ResetTextureState();
6837 R_SetupGenericShader(false);
6838 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6840 GL_BlendFunc(GL_ONE, GL_ZERO);
6841 GL_Color(0, 0, 0, 1);
6842 GL_DepthTest(writedepth);
6843 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6845 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6847 RSurf_SetupDepthAndCulling();
6848 GL_AlphaTest(false);
6849 R_Mesh_ColorPointer(NULL, 0, 0);
6850 R_Mesh_ResetTextureState();
6851 R_SetupGenericShader(false);
6852 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6854 GL_BlendFunc(GL_ONE, GL_ZERO);
6856 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6858 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6859 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6860 else if (!rsurface.texture->currentnumlayers)
6862 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6864 // transparent surfaces get pushed off into the transparent queue
6865 int surfacelistindex;
6866 const msurface_t *surface;
6867 vec3_t tempcenter, center;
6868 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6870 surface = texturesurfacelist[surfacelistindex];
6871 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6872 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6873 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6874 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6875 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6880 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6881 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6886 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6890 // break the surface list down into batches by texture and use of lightmapping
6891 for (i = 0;i < numsurfaces;i = j)
6894 // texture is the base texture pointer, rsurface.texture is the
6895 // current frame/skin the texture is directing us to use (for example
6896 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6897 // use skin 1 instead)
6898 texture = surfacelist[i]->texture;
6899 rsurface.texture = R_GetCurrentTexture(texture);
6900 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6901 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6903 // if this texture is not the kind we want, skip ahead to the next one
6904 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6908 // simply scan ahead until we find a different texture or lightmap state
6909 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6911 // render the range of surfaces
6912 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6916 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6921 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6923 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6925 RSurf_SetupDepthAndCulling();
6926 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6927 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6929 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6931 RSurf_SetupDepthAndCulling();
6932 GL_AlphaTest(false);
6933 R_Mesh_ColorPointer(NULL, 0, 0);
6934 R_Mesh_ResetTextureState();
6935 R_SetupGenericShader(false);
6936 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6938 GL_BlendFunc(GL_ONE, GL_ZERO);
6939 GL_Color(0, 0, 0, 1);
6940 GL_DepthTest(writedepth);
6941 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6943 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6945 RSurf_SetupDepthAndCulling();
6946 GL_AlphaTest(false);
6947 R_Mesh_ColorPointer(NULL, 0, 0);
6948 R_Mesh_ResetTextureState();
6949 R_SetupGenericShader(false);
6950 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6952 GL_BlendFunc(GL_ONE, GL_ZERO);
6954 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6956 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6957 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6958 else if (!rsurface.texture->currentnumlayers)
6960 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6962 // transparent surfaces get pushed off into the transparent queue
6963 int surfacelistindex;
6964 const msurface_t *surface;
6965 vec3_t tempcenter, center;
6966 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6968 surface = texturesurfacelist[surfacelistindex];
6969 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6970 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6971 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6972 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6973 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6978 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6979 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6984 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6988 // break the surface list down into batches by texture and use of lightmapping
6989 for (i = 0;i < numsurfaces;i = j)
6992 // texture is the base texture pointer, rsurface.texture is the
6993 // current frame/skin the texture is directing us to use (for example
6994 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6995 // use skin 1 instead)
6996 texture = surfacelist[i]->texture;
6997 rsurface.texture = R_GetCurrentTexture(texture);
6998 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6999 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7001 // if this texture is not the kind we want, skip ahead to the next one
7002 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7006 // simply scan ahead until we find a different texture or lightmap state
7007 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7009 // render the range of surfaces
7010 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7014 float locboxvertex3f[6*4*3] =
7016 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7017 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7018 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7019 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7020 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7021 1,0,0, 0,0,0, 0,1,0, 1,1,0
7024 unsigned short locboxelements[6*2*3] =
7034 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7037 cl_locnode_t *loc = (cl_locnode_t *)ent;
7039 float vertex3f[6*4*3];
7041 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7042 GL_DepthMask(false);
7043 GL_DepthRange(0, 1);
7044 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7046 GL_CullFace(GL_NONE);
7047 R_Mesh_Matrix(&identitymatrix);
7049 R_Mesh_VertexPointer(vertex3f, 0, 0);
7050 R_Mesh_ColorPointer(NULL, 0, 0);
7051 R_Mesh_ResetTextureState();
7052 R_SetupGenericShader(false);
7055 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7056 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7057 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7058 surfacelist[0] < 0 ? 0.5f : 0.125f);
7060 if (VectorCompare(loc->mins, loc->maxs))
7062 VectorSet(size, 2, 2, 2);
7063 VectorMA(loc->mins, -0.5f, size, mins);
7067 VectorCopy(loc->mins, mins);
7068 VectorSubtract(loc->maxs, loc->mins, size);
7071 for (i = 0;i < 6*4*3;)
7072 for (j = 0;j < 3;j++, i++)
7073 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7075 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7078 void R_DrawLocs(void)
7081 cl_locnode_t *loc, *nearestloc;
7083 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7084 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7086 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7087 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7091 void R_DrawDebugModel(entity_render_t *ent)
7093 int i, j, k, l, flagsmask;
7094 const int *elements;
7096 msurface_t *surface;
7097 dp_model_t *model = ent->model;
7100 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7102 R_Mesh_ColorPointer(NULL, 0, 0);
7103 R_Mesh_ResetTextureState();
7104 R_SetupGenericShader(false);
7105 GL_DepthRange(0, 1);
7106 GL_DepthTest(!r_showdisabledepthtest.integer);
7107 GL_DepthMask(false);
7108 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7110 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7112 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7113 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7115 if (brush->colbrushf && brush->colbrushf->numtriangles)
7117 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7118 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);
7119 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7122 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7124 if (surface->num_collisiontriangles)
7126 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7127 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);
7128 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7133 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7135 if (r_showtris.integer || r_shownormals.integer)
7137 if (r_showdisabledepthtest.integer)
7139 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7140 GL_DepthMask(false);
7144 GL_BlendFunc(GL_ONE, GL_ZERO);
7147 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7149 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7151 rsurface.texture = R_GetCurrentTexture(surface->texture);
7152 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7154 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7155 if (r_showtris.value > 0)
7157 if (!rsurface.texture->currentlayers->depthmask)
7158 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7159 else if (ent == r_refdef.scene.worldentity)
7160 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7162 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7163 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7164 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7165 R_Mesh_ColorPointer(NULL, 0, 0);
7166 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7167 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7168 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7169 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);
7170 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7173 if (r_shownormals.value < 0)
7176 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7178 VectorCopy(rsurface.vertex3f + l * 3, v);
7179 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7180 qglVertex3f(v[0], v[1], v[2]);
7181 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7182 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7183 qglVertex3f(v[0], v[1], v[2]);
7188 if (r_shownormals.value > 0)
7191 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7193 VectorCopy(rsurface.vertex3f + l * 3, v);
7194 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7195 qglVertex3f(v[0], v[1], v[2]);
7196 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7197 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7198 qglVertex3f(v[0], v[1], v[2]);
7203 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7205 VectorCopy(rsurface.vertex3f + l * 3, v);
7206 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7207 qglVertex3f(v[0], v[1], v[2]);
7208 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7209 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7210 qglVertex3f(v[0], v[1], v[2]);
7215 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7217 VectorCopy(rsurface.vertex3f + l * 3, v);
7218 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7219 qglVertex3f(v[0], v[1], v[2]);
7220 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7221 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7222 qglVertex3f(v[0], v[1], v[2]);
7229 rsurface.texture = NULL;
7233 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7234 int r_maxsurfacelist = 0;
7235 msurface_t **r_surfacelist = NULL;
7236 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7238 int i, j, endj, f, flagsmask;
7240 dp_model_t *model = r_refdef.scene.worldmodel;
7241 msurface_t *surfaces;
7242 unsigned char *update;
7243 int numsurfacelist = 0;
7247 if (r_maxsurfacelist < model->num_surfaces)
7249 r_maxsurfacelist = model->num_surfaces;
7251 Mem_Free(r_surfacelist);
7252 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7255 RSurf_ActiveWorldEntity();
7257 surfaces = model->data_surfaces;
7258 update = model->brushq1.lightmapupdateflags;
7260 // update light styles on this submodel
7261 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7263 model_brush_lightstyleinfo_t *style;
7264 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7266 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7268 int *list = style->surfacelist;
7269 style->value = r_refdef.scene.lightstylevalue[style->style];
7270 for (j = 0;j < style->numsurfaces;j++)
7271 update[list[j]] = true;
7276 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7280 R_DrawDebugModel(r_refdef.scene.worldentity);
7281 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7287 rsurface.uselightmaptexture = false;
7288 rsurface.texture = NULL;
7289 rsurface.rtlight = NULL;
7291 // add visible surfaces to draw list
7292 for (i = 0;i < model->nummodelsurfaces;i++)
7294 j = model->sortedmodelsurfaces[i];
7295 if (r_refdef.viewcache.world_surfacevisible[j])
7296 r_surfacelist[numsurfacelist++] = surfaces + j;
7298 // update lightmaps if needed
7300 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7301 if (r_refdef.viewcache.world_surfacevisible[j])
7303 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7304 // don't do anything if there were no surfaces
7305 if (!numsurfacelist)
7307 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7310 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7311 GL_AlphaTest(false);
7313 // add to stats if desired
7314 if (r_speeds.integer && !skysurfaces && !depthonly)
7316 r_refdef.stats.world_surfaces += numsurfacelist;
7317 for (j = 0;j < numsurfacelist;j++)
7318 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7320 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7323 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7325 int i, j, endj, f, flagsmask;
7327 dp_model_t *model = ent->model;
7328 msurface_t *surfaces;
7329 unsigned char *update;
7330 int numsurfacelist = 0;
7334 if (r_maxsurfacelist < model->num_surfaces)
7336 r_maxsurfacelist = model->num_surfaces;
7338 Mem_Free(r_surfacelist);
7339 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7342 // if the model is static it doesn't matter what value we give for
7343 // wantnormals and wanttangents, so this logic uses only rules applicable
7344 // to a model, knowing that they are meaningless otherwise
7345 if (ent == r_refdef.scene.worldentity)
7346 RSurf_ActiveWorldEntity();
7347 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
7348 RSurf_ActiveModelEntity(ent, false, false);
7350 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7352 surfaces = model->data_surfaces;
7353 update = model->brushq1.lightmapupdateflags;
7355 // update light styles
7356 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7358 model_brush_lightstyleinfo_t *style;
7359 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7361 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7363 int *list = style->surfacelist;
7364 style->value = r_refdef.scene.lightstylevalue[style->style];
7365 for (j = 0;j < style->numsurfaces;j++)
7366 update[list[j]] = true;
7371 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7375 R_DrawDebugModel(ent);
7376 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7382 rsurface.uselightmaptexture = false;
7383 rsurface.texture = NULL;
7384 rsurface.rtlight = NULL;
7386 // add visible surfaces to draw list
7387 for (i = 0;i < model->nummodelsurfaces;i++)
7388 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7389 // don't do anything if there were no surfaces
7390 if (!numsurfacelist)
7392 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7395 // update lightmaps if needed
7397 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7399 R_BuildLightMap(ent, surfaces + j);
7400 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7401 GL_AlphaTest(false);
7403 // add to stats if desired
7404 if (r_speeds.integer && !skysurfaces && !depthonly)
7406 r_refdef.stats.entities_surfaces += numsurfacelist;
7407 for (j = 0;j < numsurfacelist;j++)
7408 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7410 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity