2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
38 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
42 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
43 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
44 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
47 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
49 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"};
50 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
51 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
52 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
53 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)"};
54 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
55 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
56 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"};
57 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"};
58 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
59 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"};
60 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"};
61 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"};
62 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
63 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
64 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
65 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
66 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
67 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
68 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
69 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
70 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
71 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
72 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
73 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
74 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 in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
75 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
76 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
77 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
78 cvar_t r_shadows_drawafterrtlightning = {CVAR_SAVE, "r_shadows_drawafterrtlightning", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
79 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
80 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
81 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"};
82 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"};
83 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
84 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
86 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
87 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
88 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
89 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
90 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
91 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
92 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
93 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
95 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)"};
97 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
98 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)"};
99 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)"};
100 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
101 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
102 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
103 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
104 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)"};
105 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)"};
106 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)"};
107 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)"};
108 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)"};
110 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)"};
111 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
112 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"};
113 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
114 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
116 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
117 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
118 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
119 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
121 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
122 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
123 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
124 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
125 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
126 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
127 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
129 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
130 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
131 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
132 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)"};
134 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"};
136 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"};
138 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
140 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
141 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
142 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"};
143 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
144 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
145 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
146 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
148 extern cvar_t v_glslgamma;
150 extern qboolean v_flipped_state;
152 static struct r_bloomstate_s
157 int bloomwidth, bloomheight;
159 int screentexturewidth, screentextureheight;
160 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
162 int bloomtexturewidth, bloomtextureheight;
163 rtexture_t *texture_bloom;
165 // arrays for rendering the screen passes
166 float screentexcoord2f[8];
167 float bloomtexcoord2f[8];
168 float offsettexcoord2f[8];
172 r_waterstate_t r_waterstate;
174 /// shadow volume bsp struct with automatically growing nodes buffer
177 rtexture_t *r_texture_blanknormalmap;
178 rtexture_t *r_texture_white;
179 rtexture_t *r_texture_grey128;
180 rtexture_t *r_texture_black;
181 rtexture_t *r_texture_notexture;
182 rtexture_t *r_texture_whitecube;
183 rtexture_t *r_texture_normalizationcube;
184 rtexture_t *r_texture_fogattenuation;
185 rtexture_t *r_texture_gammaramps;
186 unsigned int r_texture_gammaramps_serial;
187 //rtexture_t *r_texture_fogintensity;
189 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
190 unsigned int r_numqueries;
191 unsigned int r_maxqueries;
193 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
194 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
196 /// vertex coordinates for a quad that covers the screen exactly
197 const static float r_screenvertex3f[12] =
205 extern void R_DrawModelShadows(void);
207 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
210 for (i = 0;i < verts;i++)
221 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
224 for (i = 0;i < verts;i++)
234 // FIXME: move this to client?
237 if (gamemode == GAME_NEHAHRA)
239 Cvar_Set("gl_fogenable", "0");
240 Cvar_Set("gl_fogdensity", "0.2");
241 Cvar_Set("gl_fogred", "0.3");
242 Cvar_Set("gl_foggreen", "0.3");
243 Cvar_Set("gl_fogblue", "0.3");
245 r_refdef.fog_density = 0;
246 r_refdef.fog_red = 0;
247 r_refdef.fog_green = 0;
248 r_refdef.fog_blue = 0;
249 r_refdef.fog_alpha = 1;
250 r_refdef.fog_start = 0;
251 r_refdef.fog_end = 0;
254 float FogForDistance(vec_t dist)
256 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
257 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
260 float FogPoint_World(const vec3_t p)
262 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
265 float FogPoint_Model(const vec3_t p)
267 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
270 static void R_BuildBlankTextures(void)
272 unsigned char data[4];
273 data[2] = 128; // normal X
274 data[1] = 128; // normal Y
275 data[0] = 255; // normal Z
276 data[3] = 128; // height
277 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
282 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
287 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
292 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
295 static void R_BuildNoTexture(void)
298 unsigned char pix[16][16][4];
299 // this makes a light grey/dark grey checkerboard texture
300 for (y = 0;y < 16;y++)
302 for (x = 0;x < 16;x++)
304 if ((y < 8) ^ (x < 8))
320 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
323 static void R_BuildWhiteCube(void)
325 unsigned char data[6*1*1*4];
326 memset(data, 255, sizeof(data));
327 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
330 static void R_BuildNormalizationCube(void)
334 vec_t s, t, intensity;
336 unsigned char data[6][NORMSIZE][NORMSIZE][4];
337 for (side = 0;side < 6;side++)
339 for (y = 0;y < NORMSIZE;y++)
341 for (x = 0;x < NORMSIZE;x++)
343 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
344 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
379 intensity = 127.0f / sqrt(DotProduct(v, v));
380 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
381 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
382 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
383 data[side][y][x][3] = 255;
387 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
390 static void R_BuildFogTexture(void)
394 unsigned char data1[FOGWIDTH][4];
395 //unsigned char data2[FOGWIDTH][4];
398 r_refdef.fogmasktable_start = r_refdef.fog_start;
399 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
400 r_refdef.fogmasktable_range = r_refdef.fogrange;
401 r_refdef.fogmasktable_density = r_refdef.fog_density;
403 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
404 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
406 d = (x * r - r_refdef.fogmasktable_start);
407 if(developer.integer >= 100)
408 Con_Printf("%f ", d);
410 if (r_fog_exp2.integer)
411 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
413 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
414 if(developer.integer >= 100)
415 Con_Printf(" : %f ", alpha);
416 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
417 if(developer.integer >= 100)
418 Con_Printf(" = %f\n", alpha);
419 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
422 for (x = 0;x < FOGWIDTH;x++)
424 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
429 //data2[x][0] = 255 - b;
430 //data2[x][1] = 255 - b;
431 //data2[x][2] = 255 - b;
434 if (r_texture_fogattenuation)
436 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
437 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
441 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);
442 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
446 static const char *builtinshaderstring =
447 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
448 "// written by Forest 'LordHavoc' Hale\n"
450 "// common definitions between vertex shader and fragment shader:\n"
452 "//#ifdef __GLSL_CG_DATA_TYPES\n"
453 "//# define myhalf half\n"
454 "//# define myhalf2 half2\n"
455 "//# define myhalf3 half3\n"
456 "//# define myhalf4 half4\n"
458 "# define myhalf float\n"
459 "# define myhalf2 vec2\n"
460 "# define myhalf3 vec3\n"
461 "# define myhalf4 vec4\n"
464 "#ifdef MODE_DEPTH_OR_SHADOW\n"
466 "# ifdef VERTEX_SHADER\n"
469 " gl_Position = ftransform();\n"
475 "#ifdef MODE_POSTPROCESS\n"
476 "# ifdef VERTEX_SHADER\n"
479 " gl_FrontColor = gl_Color;\n"
480 " gl_Position = ftransform();\n"
481 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
483 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
487 "# ifdef FRAGMENT_SHADER\n"
489 "uniform sampler2D Texture_First;\n"
491 "uniform sampler2D Texture_Second;\n"
493 "#ifdef USEGAMMARAMPS\n"
494 "uniform sampler2D Texture_GammaRamps;\n"
496 "#ifdef USESATURATION\n"
497 "uniform float Saturation;\n"
499 "#ifdef USEVERTEXTEXTUREBLEND\n"
500 "uniform vec4 TintColor;\n"
502 "#ifdef USECOLORMOD\n"
503 "uniform vec3 Gamma;\n"
505 "//uncomment these if you want to use them:\n"
506 "uniform vec4 UserVec1;\n"
507 "// uniform vec4 UserVec2;\n"
508 "// uniform vec4 UserVec3;\n"
509 "// uniform vec4 UserVec4;\n"
510 "// uniform float ClientTime;\n"
511 "uniform vec2 PixelSize;\n"
514 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
516 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
518 "#ifdef USEVERTEXTEXTUREBLEND\n"
519 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
522 "#ifdef USEPOSTPROCESSING\n"
523 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
524 "// 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"
525 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
526 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
527 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
528 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
529 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
530 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
533 "#ifdef USESATURATION\n"
534 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
535 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
536 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
537 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" // TODO: test this on ATI
540 "#ifdef USEGAMMARAMPS\n"
541 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
542 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
543 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
550 "#ifdef MODE_GENERIC\n"
551 "# ifdef VERTEX_SHADER\n"
554 " gl_FrontColor = gl_Color;\n"
555 "# ifdef USEDIFFUSE\n"
556 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
558 "# ifdef USESPECULAR\n"
559 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
561 " gl_Position = ftransform();\n"
564 "# ifdef FRAGMENT_SHADER\n"
566 "# ifdef USEDIFFUSE\n"
567 "uniform sampler2D Texture_First;\n"
569 "# ifdef USESPECULAR\n"
570 "uniform sampler2D Texture_Second;\n"
575 " gl_FragColor = gl_Color;\n"
576 "# ifdef USEDIFFUSE\n"
577 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
580 "# ifdef USESPECULAR\n"
581 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
583 "# ifdef USECOLORMAPPING\n"
584 " gl_FragColor *= tex2;\n"
587 " gl_FragColor += tex2;\n"
589 "# ifdef USEVERTEXTEXTUREBLEND\n"
590 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
595 "#else // !MODE_GENERIC\n"
597 "varying vec2 TexCoord;\n"
598 "#ifdef USEVERTEXTEXTUREBLEND\n"
599 "varying vec2 TexCoord2;\n"
601 "varying vec2 TexCoordLightmap;\n"
603 "#ifdef MODE_LIGHTSOURCE\n"
604 "varying vec3 CubeVector;\n"
607 "#ifdef MODE_LIGHTSOURCE\n"
608 "varying vec3 LightVector;\n"
610 "#ifdef MODE_LIGHTDIRECTION\n"
611 "varying vec3 LightVector;\n"
614 "varying vec3 EyeVector;\n"
616 "varying vec3 EyeVectorModelSpace;\n"
619 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
620 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
621 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
623 "#ifdef MODE_WATER\n"
624 "varying vec4 ModelViewProjectionPosition;\n"
626 "#ifdef MODE_REFRACTION\n"
627 "varying vec4 ModelViewProjectionPosition;\n"
629 "#ifdef USEREFLECTION\n"
630 "varying vec4 ModelViewProjectionPosition;\n"
637 "// vertex shader specific:\n"
638 "#ifdef VERTEX_SHADER\n"
640 "uniform vec3 LightPosition;\n"
641 "uniform vec3 EyePosition;\n"
642 "uniform vec3 LightDir;\n"
644 "// 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"
648 " gl_FrontColor = gl_Color;\n"
649 " // copy the surface texcoord\n"
650 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
651 "#ifdef USEVERTEXTEXTUREBLEND\n"
652 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
654 "#ifndef MODE_LIGHTSOURCE\n"
655 "# ifndef MODE_LIGHTDIRECTION\n"
656 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
660 "#ifdef MODE_LIGHTSOURCE\n"
661 " // transform vertex position into light attenuation/cubemap space\n"
662 " // (-1 to +1 across the light box)\n"
663 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
665 " // transform unnormalized light direction into tangent space\n"
666 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
667 " // normalize it per pixel)\n"
668 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
669 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
670 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
671 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
674 "#ifdef MODE_LIGHTDIRECTION\n"
675 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
676 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
677 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
680 " // transform unnormalized eye direction into tangent space\n"
682 " vec3 EyeVectorModelSpace;\n"
684 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
685 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
686 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
687 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
689 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
690 " VectorS = gl_MultiTexCoord1.xyz;\n"
691 " VectorT = gl_MultiTexCoord2.xyz;\n"
692 " VectorR = gl_MultiTexCoord3.xyz;\n"
695 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
696 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
697 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
698 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
701 "// transform vertex to camera space, using ftransform to match non-VS\n"
703 " gl_Position = ftransform();\n"
705 "#ifdef MODE_WATER\n"
706 " ModelViewProjectionPosition = gl_Position;\n"
708 "#ifdef MODE_REFRACTION\n"
709 " ModelViewProjectionPosition = gl_Position;\n"
711 "#ifdef USEREFLECTION\n"
712 " ModelViewProjectionPosition = gl_Position;\n"
716 "#endif // VERTEX_SHADER\n"
721 "// fragment shader specific:\n"
722 "#ifdef FRAGMENT_SHADER\n"
724 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
725 "uniform sampler2D Texture_Normal;\n"
726 "uniform sampler2D Texture_Color;\n"
727 "uniform sampler2D Texture_Gloss;\n"
728 "uniform sampler2D Texture_Glow;\n"
729 "uniform sampler2D Texture_SecondaryNormal;\n"
730 "uniform sampler2D Texture_SecondaryColor;\n"
731 "uniform sampler2D Texture_SecondaryGloss;\n"
732 "uniform sampler2D Texture_SecondaryGlow;\n"
733 "uniform sampler2D Texture_Pants;\n"
734 "uniform sampler2D Texture_Shirt;\n"
735 "uniform sampler2D Texture_FogMask;\n"
736 "uniform sampler2D Texture_Lightmap;\n"
737 "uniform sampler2D Texture_Deluxemap;\n"
738 "uniform sampler2D Texture_Refraction;\n"
739 "uniform sampler2D Texture_Reflection;\n"
740 "uniform sampler2D Texture_Attenuation;\n"
741 "uniform samplerCube Texture_Cube;\n"
743 "uniform myhalf3 LightColor;\n"
744 "uniform myhalf3 AmbientColor;\n"
745 "uniform myhalf3 DiffuseColor;\n"
746 "uniform myhalf3 SpecularColor;\n"
747 "uniform myhalf3 Color_Pants;\n"
748 "uniform myhalf3 Color_Shirt;\n"
749 "uniform myhalf3 FogColor;\n"
751 "uniform myhalf4 TintColor;\n"
754 "//#ifdef MODE_WATER\n"
755 "uniform vec4 DistortScaleRefractReflect;\n"
756 "uniform vec4 ScreenScaleRefractReflect;\n"
757 "uniform vec4 ScreenCenterRefractReflect;\n"
758 "uniform myhalf4 RefractColor;\n"
759 "uniform myhalf4 ReflectColor;\n"
760 "uniform myhalf ReflectFactor;\n"
761 "uniform myhalf ReflectOffset;\n"
763 "//# ifdef MODE_REFRACTION\n"
764 "//uniform vec4 DistortScaleRefractReflect;\n"
765 "//uniform vec4 ScreenScaleRefractReflect;\n"
766 "//uniform vec4 ScreenCenterRefractReflect;\n"
767 "//uniform myhalf4 RefractColor;\n"
768 "//# ifdef USEREFLECTION\n"
769 "//uniform myhalf4 ReflectColor;\n"
772 "//# ifdef USEREFLECTION\n"
773 "//uniform vec4 DistortScaleRefractReflect;\n"
774 "//uniform vec4 ScreenScaleRefractReflect;\n"
775 "//uniform vec4 ScreenCenterRefractReflect;\n"
776 "//uniform myhalf4 ReflectColor;\n"
781 "uniform myhalf GlowScale;\n"
782 "uniform myhalf SceneBrightness;\n"
783 "#ifdef USECONTRASTBOOST\n"
784 "uniform myhalf ContrastBoostCoeff;\n"
787 "uniform float OffsetMapping_Scale;\n"
788 "uniform float OffsetMapping_Bias;\n"
789 "uniform float FogRangeRecip;\n"
791 "uniform myhalf AmbientScale;\n"
792 "uniform myhalf DiffuseScale;\n"
793 "uniform myhalf SpecularScale;\n"
794 "uniform myhalf SpecularPower;\n"
796 "#ifdef USEOFFSETMAPPING\n"
797 "vec2 OffsetMapping(vec2 TexCoord)\n"
799 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
800 " // 14 sample relief mapping: linear search and then binary search\n"
801 " // this basically steps forward a small amount repeatedly until it finds\n"
802 " // itself inside solid, then jitters forward and back using decreasing\n"
803 " // amounts to find the impact\n"
804 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
805 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
806 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
807 " vec3 RT = vec3(TexCoord, 1);\n"
808 " OffsetVector *= 0.1;\n"
809 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
810 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
811 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
812 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
813 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
814 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
815 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
816 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
817 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
818 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
819 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
820 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
821 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
822 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
825 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
826 " // this basically moves forward the full distance, and then backs up based\n"
827 " // on height of samples\n"
828 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
829 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
830 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
831 " TexCoord += OffsetVector;\n"
832 " OffsetVector *= 0.333;\n"
833 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
834 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
835 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
836 " return TexCoord;\n"
839 "#endif // USEOFFSETMAPPING\n"
841 "#ifdef MODE_WATER\n"
846 "#ifdef USEOFFSETMAPPING\n"
847 " // apply offsetmapping\n"
848 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
849 "#define TexCoord TexCoordOffset\n"
852 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
853 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
854 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
855 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
856 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
859 "#else // !MODE_WATER\n"
860 "#ifdef MODE_REFRACTION\n"
862 "// refraction pass\n"
865 "#ifdef USEOFFSETMAPPING\n"
866 " // apply offsetmapping\n"
867 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
868 "#define TexCoord TexCoordOffset\n"
871 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
872 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
873 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
874 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
877 "#else // !MODE_REFRACTION\n"
880 "#ifdef USEOFFSETMAPPING\n"
881 " // apply offsetmapping\n"
882 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
883 "#define TexCoord TexCoordOffset\n"
886 " // combine the diffuse textures (base, pants, shirt)\n"
887 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
888 "#ifdef USECOLORMAPPING\n"
889 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
891 "#ifdef USEVERTEXTEXTUREBLEND\n"
892 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
893 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
894 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
895 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
897 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
900 "#ifdef USEDIFFUSE\n"
901 " // get the surface normal and the gloss color\n"
902 "# ifdef USEVERTEXTEXTUREBLEND\n"
903 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
904 "# ifdef USESPECULAR\n"
905 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
908 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
909 "# ifdef USESPECULAR\n"
910 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
917 "#ifdef MODE_LIGHTSOURCE\n"
920 " // calculate surface normal, light normal, and specular normal\n"
921 " // compute color intensity for the two textures (colormap and glossmap)\n"
922 " // scale by light color and attenuation as efficiently as possible\n"
923 " // (do as much scalar math as possible rather than vector math)\n"
924 "# ifdef USEDIFFUSE\n"
925 " // get the light normal\n"
926 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
928 "# ifdef USESPECULAR\n"
929 "# ifndef USEEXACTSPECULARMATH\n"
930 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
933 " // calculate directional shading\n"
934 "# ifdef USEEXACTSPECULARMATH\n"
935 " 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"
937 " 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"
940 "# ifdef USEDIFFUSE\n"
941 " // calculate directional shading\n"
942 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
944 " // calculate directionless shading\n"
945 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
949 "# ifdef USECUBEFILTER\n"
950 " // apply light cubemap filter\n"
951 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
952 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
954 "#endif // MODE_LIGHTSOURCE\n"
959 "#ifdef MODE_LIGHTDIRECTION\n"
960 " // directional model lighting\n"
961 "# ifdef USEDIFFUSE\n"
962 " // get the light normal\n"
963 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
965 "# ifdef USESPECULAR\n"
966 " // calculate directional shading\n"
967 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
968 "# ifdef USEEXACTSPECULARMATH\n"
969 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
971 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
972 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
975 "# ifdef USEDIFFUSE\n"
977 " // calculate directional shading\n"
978 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
980 " color.rgb *= AmbientColor;\n"
983 "#endif // MODE_LIGHTDIRECTION\n"
988 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
989 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
991 " // get the light normal\n"
992 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
993 " myhalf3 diffusenormal;\n"
994 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
995 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
996 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
997 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
998 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
999 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1000 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1001 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1002 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1003 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1004 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1005 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1006 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1007 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1008 "# ifdef USESPECULAR\n"
1009 "# ifdef USEEXACTSPECULARMATH\n"
1010 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1012 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1013 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1017 " // apply lightmap color\n"
1018 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1019 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1024 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1025 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1027 " // get the light normal\n"
1028 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1029 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1030 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1031 "# ifdef USESPECULAR\n"
1032 "# ifdef USEEXACTSPECULARMATH\n"
1033 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1035 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1036 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1040 " // apply lightmap color\n"
1041 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1042 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1047 "#ifdef MODE_LIGHTMAP\n"
1048 " // apply lightmap color\n"
1049 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1050 "#endif // MODE_LIGHTMAP\n"
1055 "#ifdef MODE_VERTEXCOLOR\n"
1056 " // apply lightmap color\n"
1057 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1058 "#endif // MODE_VERTEXCOLOR\n"
1063 "#ifdef MODE_FLATCOLOR\n"
1064 "#endif // MODE_FLATCOLOR\n"
1072 " color *= TintColor;\n"
1075 "#ifdef USEVERTEXTEXTUREBLEND\n"
1076 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1078 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1082 "#ifdef USECONTRASTBOOST\n"
1083 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1086 " color.rgb *= SceneBrightness;\n"
1088 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1090 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1093 " // 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"
1094 "#ifdef USEREFLECTION\n"
1095 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1096 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1097 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1098 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1101 " gl_FragColor = vec4(color);\n"
1103 "#endif // !MODE_REFRACTION\n"
1104 "#endif // !MODE_WATER\n"
1106 "#endif // FRAGMENT_SHADER\n"
1108 "#endif // !MODE_GENERIC\n"
1109 "#endif // !MODE_POSTPROCESS\n"
1110 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1113 typedef struct shaderpermutationinfo_s
1115 const char *pretext;
1118 shaderpermutationinfo_t;
1120 typedef struct shadermodeinfo_s
1122 const char *vertexfilename;
1123 const char *geometryfilename;
1124 const char *fragmentfilename;
1125 const char *pretext;
1130 typedef enum shaderpermutation_e
1132 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1133 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1134 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1135 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, ///< r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1136 SHADERPERMUTATION_FOG = 1<<4, ///< tint the color by fog color or black if using additive blend mode
1137 SHADERPERMUTATION_CUBEFILTER = 1<<5, ///< (lightsource) use cubemap light filter
1138 SHADERPERMUTATION_GLOW = 1<<6, ///< (lightmap) blend in an additive glow texture
1139 SHADERPERMUTATION_SPECULAR = 1<<7, ///< (lightsource or deluxemapping) render specular effects
1140 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1141 SHADERPERMUTATION_REFLECTION = 1<<9, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1142 SHADERPERMUTATION_OFFSETMAPPING = 1<<10, ///< adjust texcoords to roughly simulate a displacement mapped surface
1143 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1144 SHADERPERMUTATION_GAMMARAMPS = 1<<12, ///< gamma (postprocessing only)
1145 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing
1146 SHADERPERMUTATION_SATURATION = 1<<14, ///< user defined postprocessing
1147 SHADERPERMUTATION_LIMIT = 1<<15, ///< size of permutations array
1148 SHADERPERMUTATION_COUNT = 15 ///< size of shaderpermutationinfo array
1150 shaderpermutation_t;
1152 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1153 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1155 {"#define USEDIFFUSE\n", " diffuse"},
1156 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1157 {"#define USECOLORMAPPING\n", " colormapping"},
1158 {"#define USECONTRASTBOOST\n", " contrastboost"},
1159 {"#define USEFOG\n", " fog"},
1160 {"#define USECUBEFILTER\n", " cubefilter"},
1161 {"#define USEGLOW\n", " glow"},
1162 {"#define USESPECULAR\n", " specular"},
1163 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1164 {"#define USEREFLECTION\n", " reflection"},
1165 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1166 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1167 {"#define USEGAMMARAMPS\n", " gammaramps"},
1168 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1169 {"#define USESATURATION\n", " saturation"},
1172 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1173 typedef enum shadermode_e
1175 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1176 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1177 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1178 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1179 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1180 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1181 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1182 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1183 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1184 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1185 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1186 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1191 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1192 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1194 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1195 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1196 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1197 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1198 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1199 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1200 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1201 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1202 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1203 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1204 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1205 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1208 typedef struct r_glsl_permutation_s
1210 /// indicates if we have tried compiling this permutation already
1212 /// 0 if compilation failed
1214 /// locations of detected uniforms in program object, or -1 if not found
1215 int loc_Texture_First;
1216 int loc_Texture_Second;
1217 int loc_Texture_GammaRamps;
1218 int loc_Texture_Normal;
1219 int loc_Texture_Color;
1220 int loc_Texture_Gloss;
1221 int loc_Texture_Glow;
1222 int loc_Texture_SecondaryNormal;
1223 int loc_Texture_SecondaryColor;
1224 int loc_Texture_SecondaryGloss;
1225 int loc_Texture_SecondaryGlow;
1226 int loc_Texture_Pants;
1227 int loc_Texture_Shirt;
1228 int loc_Texture_FogMask;
1229 int loc_Texture_Lightmap;
1230 int loc_Texture_Deluxemap;
1231 int loc_Texture_Attenuation;
1232 int loc_Texture_Cube;
1233 int loc_Texture_Refraction;
1234 int loc_Texture_Reflection;
1236 int loc_LightPosition;
1237 int loc_EyePosition;
1238 int loc_Color_Pants;
1239 int loc_Color_Shirt;
1240 int loc_FogRangeRecip;
1241 int loc_AmbientScale;
1242 int loc_DiffuseScale;
1243 int loc_SpecularScale;
1244 int loc_SpecularPower;
1246 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1247 int loc_OffsetMapping_Scale;
1249 int loc_AmbientColor;
1250 int loc_DiffuseColor;
1251 int loc_SpecularColor;
1253 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1254 int loc_GammaCoeff; ///< 1 / gamma
1255 int loc_DistortScaleRefractReflect;
1256 int loc_ScreenScaleRefractReflect;
1257 int loc_ScreenCenterRefractReflect;
1258 int loc_RefractColor;
1259 int loc_ReflectColor;
1260 int loc_ReflectFactor;
1261 int loc_ReflectOffset;
1270 r_glsl_permutation_t;
1272 /// information about each possible shader permutation
1273 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1274 /// currently selected permutation
1275 r_glsl_permutation_t *r_glsl_permutation;
1277 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1280 if (!filename || !filename[0])
1282 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1285 if (printfromdisknotice)
1286 Con_DPrint("from disk... ");
1287 return shaderstring;
1289 else if (!strcmp(filename, "glsl/default.glsl"))
1291 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1292 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1294 return shaderstring;
1297 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1300 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1301 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1302 int vertstrings_count = 0;
1303 int geomstrings_count = 0;
1304 int fragstrings_count = 0;
1305 char *vertexstring, *geometrystring, *fragmentstring;
1306 const char *vertstrings_list[32+3];
1307 const char *geomstrings_list[32+3];
1308 const char *fragstrings_list[32+3];
1309 char permutationname[256];
1316 permutationname[0] = 0;
1317 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1318 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1319 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1321 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1323 // the first pretext is which type of shader to compile as
1324 // (later these will all be bound together as a program object)
1325 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1326 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1327 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1329 // the second pretext is the mode (for example a light source)
1330 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1331 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1332 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1333 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1335 // now add all the permutation pretexts
1336 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1338 if (permutation & (1<<i))
1340 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1341 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1342 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1343 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1347 // keep line numbers correct
1348 vertstrings_list[vertstrings_count++] = "\n";
1349 geomstrings_list[geomstrings_count++] = "\n";
1350 fragstrings_list[fragstrings_count++] = "\n";
1354 // now append the shader text itself
1355 vertstrings_list[vertstrings_count++] = vertexstring;
1356 geomstrings_list[geomstrings_count++] = geometrystring;
1357 fragstrings_list[fragstrings_count++] = fragmentstring;
1359 // if any sources were NULL, clear the respective list
1361 vertstrings_count = 0;
1362 if (!geometrystring)
1363 geomstrings_count = 0;
1364 if (!fragmentstring)
1365 fragstrings_count = 0;
1367 // compile the shader program
1368 if (vertstrings_count + geomstrings_count + fragstrings_count)
1369 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1373 qglUseProgramObjectARB(p->program);CHECKGLERROR
1374 // look up all the uniform variable names we care about, so we don't
1375 // have to look them up every time we set them
1376 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1377 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1378 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1379 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1380 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1381 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1382 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1383 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1384 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1385 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1386 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1387 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1388 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1389 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1390 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1391 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1392 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1393 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1394 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1395 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1396 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1397 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1398 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1399 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1400 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1401 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1402 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1403 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1404 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1405 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1406 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1407 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1408 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1409 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1410 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1411 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1412 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1413 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1414 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1415 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1416 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1417 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1418 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1419 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1420 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1421 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1422 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1423 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1424 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1425 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1426 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1427 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1428 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1429 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1430 // initialize the samplers to refer to the texture units we use
1431 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1432 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1433 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1434 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1435 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1436 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1437 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1438 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1439 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1440 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1441 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1442 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1443 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1444 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1445 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1446 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1447 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1448 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1449 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1450 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1452 if (developer.integer)
1453 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1456 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1460 Mem_Free(vertexstring);
1462 Mem_Free(geometrystring);
1464 Mem_Free(fragmentstring);
1467 void R_GLSL_Restart_f(void)
1470 unsigned int permutation;
1471 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1472 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1473 if (r_glsl_permutations[mode][permutation].program)
1474 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1475 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1478 void R_GLSL_DumpShader_f(void)
1482 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1485 Con_Printf("failed to write to glsl/default.glsl\n");
1489 FS_Print(file, "// The engine may define the following macros:\n");
1490 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1491 for (i = 0;i < SHADERMODE_COUNT;i++)
1492 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1493 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1494 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1495 FS_Print(file, "\n");
1496 FS_Print(file, builtinshaderstring);
1499 Con_Printf("glsl/default.glsl written\n");
1502 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1504 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1505 if (r_glsl_permutation != perm)
1507 r_glsl_permutation = perm;
1508 if (!r_glsl_permutation->program)
1510 if (!r_glsl_permutation->compiled)
1511 R_GLSL_CompilePermutation(mode, permutation);
1512 if (!r_glsl_permutation->program)
1514 // remove features until we find a valid permutation
1516 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1518 // reduce i more quickly whenever it would not remove any bits
1519 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1520 if (!(permutation & j))
1523 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1524 if (!r_glsl_permutation->compiled)
1525 R_GLSL_CompilePermutation(mode, permutation);
1526 if (r_glsl_permutation->program)
1529 if (i >= SHADERPERMUTATION_COUNT)
1531 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");
1532 Cvar_SetValueQuick(&r_glsl, 0);
1533 R_GLSL_Restart_f(); // unload shaders
1534 return; // no bit left to clear
1539 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1543 void R_SetupGenericShader(qboolean usetexture)
1545 if (gl_support_fragment_shader)
1547 if (r_glsl.integer && r_glsl_usegeneric.integer)
1548 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1549 else if (r_glsl_permutation)
1551 r_glsl_permutation = NULL;
1552 qglUseProgramObjectARB(0);CHECKGLERROR
1557 void R_SetupGenericTwoTextureShader(int texturemode)
1559 if (gl_support_fragment_shader)
1561 if (r_glsl.integer && r_glsl_usegeneric.integer)
1562 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))));
1563 else if (r_glsl_permutation)
1565 r_glsl_permutation = NULL;
1566 qglUseProgramObjectARB(0);CHECKGLERROR
1569 if (!r_glsl_permutation)
1571 if (texturemode == GL_DECAL && gl_combine.integer)
1572 texturemode = GL_INTERPOLATE_ARB;
1573 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1577 void R_SetupDepthOrShadowShader(void)
1579 if (gl_support_fragment_shader)
1581 if (r_glsl.integer && r_glsl_usegeneric.integer)
1582 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1583 else if (r_glsl_permutation)
1585 r_glsl_permutation = NULL;
1586 qglUseProgramObjectARB(0);CHECKGLERROR
1591 extern rtexture_t *r_shadow_attenuationgradienttexture;
1592 extern rtexture_t *r_shadow_attenuation2dtexture;
1593 extern rtexture_t *r_shadow_attenuation3dtexture;
1594 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1596 // select a permutation of the lighting shader appropriate to this
1597 // combination of texture, entity, light source, and fogging, only use the
1598 // minimum features necessary to avoid wasting rendering time in the
1599 // fragment shader on features that are not being used
1600 unsigned int permutation = 0;
1601 unsigned int mode = 0;
1602 // TODO: implement geometry-shader based shadow volumes someday
1603 if (r_glsl_offsetmapping.integer)
1605 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1606 if (r_glsl_offsetmapping_reliefmapping.integer)
1607 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1609 if (rsurfacepass == RSURFPASS_BACKGROUND)
1611 // distorted background
1612 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1613 mode = SHADERMODE_WATER;
1615 mode = SHADERMODE_REFRACTION;
1617 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1620 mode = SHADERMODE_LIGHTSOURCE;
1621 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1622 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1623 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1624 permutation |= SHADERPERMUTATION_CUBEFILTER;
1625 if (diffusescale > 0)
1626 permutation |= SHADERPERMUTATION_DIFFUSE;
1627 if (specularscale > 0)
1628 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1629 if (r_refdef.fogenabled)
1630 permutation |= SHADERPERMUTATION_FOG;
1631 if (rsurface.texture->colormapping)
1632 permutation |= SHADERPERMUTATION_COLORMAPPING;
1633 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1634 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1636 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1638 // unshaded geometry (fullbright or ambient model lighting)
1639 mode = SHADERMODE_FLATCOLOR;
1640 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1641 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1642 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1643 permutation |= SHADERPERMUTATION_GLOW;
1644 if (r_refdef.fogenabled)
1645 permutation |= SHADERPERMUTATION_FOG;
1646 if (rsurface.texture->colormapping)
1647 permutation |= SHADERPERMUTATION_COLORMAPPING;
1648 if (r_glsl_offsetmapping.integer)
1650 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1651 if (r_glsl_offsetmapping_reliefmapping.integer)
1652 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1654 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1655 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1656 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1657 permutation |= SHADERPERMUTATION_REFLECTION;
1659 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1661 // directional model lighting
1662 mode = SHADERMODE_LIGHTDIRECTION;
1663 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1664 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1665 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1666 permutation |= SHADERPERMUTATION_GLOW;
1667 permutation |= SHADERPERMUTATION_DIFFUSE;
1668 if (specularscale > 0)
1669 permutation |= SHADERPERMUTATION_SPECULAR;
1670 if (r_refdef.fogenabled)
1671 permutation |= SHADERPERMUTATION_FOG;
1672 if (rsurface.texture->colormapping)
1673 permutation |= SHADERPERMUTATION_COLORMAPPING;
1674 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1675 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1676 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1677 permutation |= SHADERPERMUTATION_REFLECTION;
1679 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1681 // ambient model lighting
1682 mode = SHADERMODE_LIGHTDIRECTION;
1683 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1684 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1685 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1686 permutation |= SHADERPERMUTATION_GLOW;
1687 if (r_refdef.fogenabled)
1688 permutation |= SHADERPERMUTATION_FOG;
1689 if (rsurface.texture->colormapping)
1690 permutation |= SHADERPERMUTATION_COLORMAPPING;
1691 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1692 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1693 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1694 permutation |= SHADERPERMUTATION_REFLECTION;
1699 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1701 // deluxemapping (light direction texture)
1702 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1703 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1705 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1706 permutation |= SHADERPERMUTATION_DIFFUSE;
1707 if (specularscale > 0)
1708 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1710 else if (r_glsl_deluxemapping.integer >= 2)
1712 // fake deluxemapping (uniform light direction in tangentspace)
1713 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1714 permutation |= SHADERPERMUTATION_DIFFUSE;
1715 if (specularscale > 0)
1716 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1718 else if (rsurface.uselightmaptexture)
1720 // ordinary lightmapping (q1bsp, q3bsp)
1721 mode = SHADERMODE_LIGHTMAP;
1725 // ordinary vertex coloring (q3bsp)
1726 mode = SHADERMODE_VERTEXCOLOR;
1728 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1729 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1730 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1731 permutation |= SHADERPERMUTATION_GLOW;
1732 if (r_refdef.fogenabled)
1733 permutation |= SHADERPERMUTATION_FOG;
1734 if (rsurface.texture->colormapping)
1735 permutation |= SHADERPERMUTATION_COLORMAPPING;
1736 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1737 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1738 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1739 permutation |= SHADERPERMUTATION_REFLECTION;
1741 if(permutation & SHADERPERMUTATION_SPECULAR)
1742 if(r_shadow_glossexact.integer)
1743 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
1744 R_SetupShader_SetPermutation(mode, permutation);
1745 if (mode == SHADERMODE_LIGHTSOURCE)
1747 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1748 if (permutation & SHADERPERMUTATION_DIFFUSE)
1750 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1751 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1752 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1753 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1757 // ambient only is simpler
1758 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]);
1759 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1760 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1761 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1763 // additive passes are only darkened by fog, not tinted
1764 if (r_glsl_permutation->loc_FogColor >= 0)
1765 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1769 if (mode == SHADERMODE_LIGHTDIRECTION)
1771 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);
1772 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);
1773 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);
1774 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]);
1778 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
1779 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1780 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1782 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]);
1783 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1784 // additive passes are only darkened by fog, not tinted
1785 if (r_glsl_permutation->loc_FogColor >= 0)
1787 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1788 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1790 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1792 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);
1793 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]);
1794 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]);
1795 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1796 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1797 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1798 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1800 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1802 // The formula used is actually:
1803 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1804 // color.rgb *= SceneBrightness;
1806 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1807 // and do [[calculations]] here in the engine
1808 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1809 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1812 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1813 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1814 if (r_glsl_permutation->loc_Color_Pants >= 0)
1816 if (rsurface.texture->currentskinframe->pants)
1817 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1819 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1821 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1823 if (rsurface.texture->currentskinframe->shirt)
1824 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1826 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1828 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
1829 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
1831 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
1835 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1837 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1841 #define SKINFRAME_HASH 1024
1845 int loadsequence; // incremented each level change
1846 memexpandablearray_t array;
1847 skinframe_t *hash[SKINFRAME_HASH];
1850 r_skinframe_t r_skinframe;
1852 void R_SkinFrame_PrepareForPurge(void)
1854 r_skinframe.loadsequence++;
1855 // wrap it without hitting zero
1856 if (r_skinframe.loadsequence >= 200)
1857 r_skinframe.loadsequence = 1;
1860 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1864 // mark the skinframe as used for the purging code
1865 skinframe->loadsequence = r_skinframe.loadsequence;
1868 void R_SkinFrame_Purge(void)
1872 for (i = 0;i < SKINFRAME_HASH;i++)
1874 for (s = r_skinframe.hash[i];s;s = s->next)
1876 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1878 if (s->merged == s->base)
1880 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1881 R_PurgeTexture(s->stain );s->stain = NULL;
1882 R_PurgeTexture(s->merged);s->merged = NULL;
1883 R_PurgeTexture(s->base );s->base = NULL;
1884 R_PurgeTexture(s->pants );s->pants = NULL;
1885 R_PurgeTexture(s->shirt );s->shirt = NULL;
1886 R_PurgeTexture(s->nmap );s->nmap = NULL;
1887 R_PurgeTexture(s->gloss );s->gloss = NULL;
1888 R_PurgeTexture(s->glow );s->glow = NULL;
1889 R_PurgeTexture(s->fog );s->fog = NULL;
1890 s->loadsequence = 0;
1896 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1898 char basename[MAX_QPATH];
1900 Image_StripImageExtension(name, basename, sizeof(basename));
1902 if( last == NULL ) {
1904 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1905 item = r_skinframe.hash[hashindex];
1910 // linearly search through the hash bucket
1911 for( ; item ; item = item->next ) {
1912 if( !strcmp( item->basename, basename ) ) {
1919 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1923 char basename[MAX_QPATH];
1925 Image_StripImageExtension(name, basename, sizeof(basename));
1927 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1928 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1929 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1933 rtexture_t *dyntexture;
1934 // check whether its a dynamic texture
1935 dyntexture = CL_GetDynTexture( basename );
1936 if (!add && !dyntexture)
1938 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1939 memset(item, 0, sizeof(*item));
1940 strlcpy(item->basename, basename, sizeof(item->basename));
1941 item->base = dyntexture; // either NULL or dyntexture handle
1942 item->textureflags = textureflags;
1943 item->comparewidth = comparewidth;
1944 item->compareheight = compareheight;
1945 item->comparecrc = comparecrc;
1946 item->next = r_skinframe.hash[hashindex];
1947 r_skinframe.hash[hashindex] = item;
1949 else if( item->base == NULL )
1951 rtexture_t *dyntexture;
1952 // check whether its a dynamic texture
1953 // 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]
1954 dyntexture = CL_GetDynTexture( basename );
1955 item->base = dyntexture; // either NULL or dyntexture handle
1958 R_SkinFrame_MarkUsed(item);
1962 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
1964 unsigned long long avgcolor[5], wsum; \
1972 for(pix = 0; pix < cnt; ++pix) \
1975 for(comp = 0; comp < 3; ++comp) \
1977 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
1980 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1982 for(comp = 0; comp < 3; ++comp) \
1983 avgcolor[comp] += getpixel * w; \
1986 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1987 avgcolor[4] += getpixel; \
1989 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
1991 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
1992 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
1993 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
1994 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
1997 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
1999 // FIXME: it should be possible to disable loading various layers using
2000 // cvars, to prevent wasted loading time and memory usage if the user does
2002 qboolean loadnormalmap = true;
2003 qboolean loadgloss = true;
2004 qboolean loadpantsandshirt = true;
2005 qboolean loadglow = true;
2007 unsigned char *pixels;
2008 unsigned char *bumppixels;
2009 unsigned char *basepixels = NULL;
2010 int basepixels_width;
2011 int basepixels_height;
2012 skinframe_t *skinframe;
2016 if (cls.state == ca_dedicated)
2019 // return an existing skinframe if already loaded
2020 // if loading of the first image fails, don't make a new skinframe as it
2021 // would cause all future lookups of this to be missing
2022 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2023 if (skinframe && skinframe->base)
2026 basepixels = loadimagepixelsbgra(name, complain, true);
2027 if (basepixels == NULL)
2030 if (developer_loading.integer)
2031 Con_Printf("loading skin \"%s\"\n", name);
2033 // we've got some pixels to store, so really allocate this new texture now
2035 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2036 skinframe->stain = NULL;
2037 skinframe->merged = NULL;
2038 skinframe->base = r_texture_notexture;
2039 skinframe->pants = NULL;
2040 skinframe->shirt = NULL;
2041 skinframe->nmap = r_texture_blanknormalmap;
2042 skinframe->gloss = NULL;
2043 skinframe->glow = NULL;
2044 skinframe->fog = NULL;
2046 basepixels_width = image_width;
2047 basepixels_height = image_height;
2048 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);
2050 if (textureflags & TEXF_ALPHA)
2052 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2053 if (basepixels[j] < 255)
2055 if (j < basepixels_width * basepixels_height * 4)
2057 // has transparent pixels
2059 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2060 for (j = 0;j < image_width * image_height * 4;j += 4)
2065 pixels[j+3] = basepixels[j+3];
2067 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);
2072 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2073 //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]);
2075 // _norm is the name used by tenebrae and has been adopted as standard
2078 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2080 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);
2084 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2086 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2087 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2088 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);
2090 Mem_Free(bumppixels);
2092 else if (r_shadow_bumpscale_basetexture.value > 0)
2094 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2095 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2096 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);
2100 // _luma is supported for tenebrae compatibility
2101 // (I think it's a very stupid name, but oh well)
2102 // _glow is the preferred name
2103 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;}
2104 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;}
2105 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;}
2106 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;}
2109 Mem_Free(basepixels);
2114 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2117 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2120 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)
2125 for (i = 0;i < width*height;i++)
2126 if (((unsigned char *)&palette[in[i]])[3] > 0)
2128 if (i == width*height)
2131 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2134 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2135 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2138 unsigned char *temp1, *temp2;
2139 skinframe_t *skinframe;
2141 if (cls.state == ca_dedicated)
2144 // if already loaded just return it, otherwise make a new skinframe
2145 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2146 if (skinframe && skinframe->base)
2149 skinframe->stain = NULL;
2150 skinframe->merged = NULL;
2151 skinframe->base = r_texture_notexture;
2152 skinframe->pants = NULL;
2153 skinframe->shirt = NULL;
2154 skinframe->nmap = r_texture_blanknormalmap;
2155 skinframe->gloss = NULL;
2156 skinframe->glow = NULL;
2157 skinframe->fog = NULL;
2159 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2163 if (developer_loading.integer)
2164 Con_Printf("loading 32bit skin \"%s\"\n", name);
2166 if (r_shadow_bumpscale_basetexture.value > 0)
2168 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2169 temp2 = temp1 + width * height * 4;
2170 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2171 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2174 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2175 if (textureflags & TEXF_ALPHA)
2177 for (i = 3;i < width * height * 4;i += 4)
2178 if (skindata[i] < 255)
2180 if (i < width * height * 4)
2182 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2183 memcpy(fogpixels, skindata, width * height * 4);
2184 for (i = 0;i < width * height * 4;i += 4)
2185 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2186 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2187 Mem_Free(fogpixels);
2191 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2192 //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]);
2197 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2200 unsigned char *temp1, *temp2;
2201 unsigned int *palette;
2202 skinframe_t *skinframe;
2204 if (cls.state == ca_dedicated)
2207 // if already loaded just return it, otherwise make a new skinframe
2208 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2209 if (skinframe && skinframe->base)
2212 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2214 skinframe->stain = NULL;
2215 skinframe->merged = NULL;
2216 skinframe->base = r_texture_notexture;
2217 skinframe->pants = NULL;
2218 skinframe->shirt = NULL;
2219 skinframe->nmap = r_texture_blanknormalmap;
2220 skinframe->gloss = NULL;
2221 skinframe->glow = NULL;
2222 skinframe->fog = NULL;
2224 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2228 if (developer_loading.integer)
2229 Con_Printf("loading quake skin \"%s\"\n", name);
2231 if (r_shadow_bumpscale_basetexture.value > 0)
2233 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2234 temp2 = temp1 + width * height * 4;
2235 // use either a custom palette or the quake palette
2236 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2237 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2238 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2241 // use either a custom palette, or the quake palette
2242 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2243 if (loadglowtexture)
2244 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2245 if (loadpantsandshirt)
2247 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2248 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2250 if (skinframe->pants || skinframe->shirt)
2251 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
2252 if (textureflags & TEXF_ALPHA)
2254 for (i = 0;i < width * height;i++)
2255 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2257 if (i < width * height)
2258 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2261 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2262 //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]);
2267 skinframe_t *R_SkinFrame_LoadMissing(void)
2269 skinframe_t *skinframe;
2271 if (cls.state == ca_dedicated)
2274 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2275 skinframe->stain = NULL;
2276 skinframe->merged = NULL;
2277 skinframe->base = r_texture_notexture;
2278 skinframe->pants = NULL;
2279 skinframe->shirt = NULL;
2280 skinframe->nmap = r_texture_blanknormalmap;
2281 skinframe->gloss = NULL;
2282 skinframe->glow = NULL;
2283 skinframe->fog = NULL;
2285 skinframe->avgcolor[0] = rand() / RAND_MAX;
2286 skinframe->avgcolor[1] = rand() / RAND_MAX;
2287 skinframe->avgcolor[2] = rand() / RAND_MAX;
2288 skinframe->avgcolor[3] = 1;
2293 void gl_main_start(void)
2297 memset(r_queries, 0, sizeof(r_queries));
2299 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2300 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2302 // set up r_skinframe loading system for textures
2303 memset(&r_skinframe, 0, sizeof(r_skinframe));
2304 r_skinframe.loadsequence = 1;
2305 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2307 r_main_texturepool = R_AllocTexturePool();
2308 R_BuildBlankTextures();
2310 if (gl_texturecubemap)
2313 R_BuildNormalizationCube();
2315 r_texture_fogattenuation = NULL;
2316 r_texture_gammaramps = NULL;
2317 //r_texture_fogintensity = NULL;
2318 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2319 memset(&r_waterstate, 0, sizeof(r_waterstate));
2320 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2321 memset(&r_svbsp, 0, sizeof (r_svbsp));
2323 r_refdef.fogmasktable_density = 0;
2326 extern rtexture_t *loadingscreentexture;
2327 void gl_main_shutdown(void)
2330 qglDeleteQueriesARB(r_maxqueries, r_queries);
2334 memset(r_queries, 0, sizeof(r_queries));
2336 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2337 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2339 // clear out the r_skinframe state
2340 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2341 memset(&r_skinframe, 0, sizeof(r_skinframe));
2344 Mem_Free(r_svbsp.nodes);
2345 memset(&r_svbsp, 0, sizeof (r_svbsp));
2346 R_FreeTexturePool(&r_main_texturepool);
2347 loadingscreentexture = NULL;
2348 r_texture_blanknormalmap = NULL;
2349 r_texture_white = NULL;
2350 r_texture_grey128 = NULL;
2351 r_texture_black = NULL;
2352 r_texture_whitecube = NULL;
2353 r_texture_normalizationcube = NULL;
2354 r_texture_fogattenuation = NULL;
2355 r_texture_gammaramps = NULL;
2356 //r_texture_fogintensity = NULL;
2357 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2358 memset(&r_waterstate, 0, sizeof(r_waterstate));
2362 extern void CL_ParseEntityLump(char *entitystring);
2363 void gl_main_newmap(void)
2365 // FIXME: move this code to client
2367 char *entities, entname[MAX_QPATH];
2370 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2371 l = (int)strlen(entname) - 4;
2372 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2374 memcpy(entname + l, ".ent", 5);
2375 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2377 CL_ParseEntityLump(entities);
2382 if (cl.worldmodel->brush.entities)
2383 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2387 void GL_Main_Init(void)
2389 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2391 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2392 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2393 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2394 if (gamemode == GAME_NEHAHRA)
2396 Cvar_RegisterVariable (&gl_fogenable);
2397 Cvar_RegisterVariable (&gl_fogdensity);
2398 Cvar_RegisterVariable (&gl_fogred);
2399 Cvar_RegisterVariable (&gl_foggreen);
2400 Cvar_RegisterVariable (&gl_fogblue);
2401 Cvar_RegisterVariable (&gl_fogstart);
2402 Cvar_RegisterVariable (&gl_fogend);
2403 Cvar_RegisterVariable (&gl_skyclip);
2405 Cvar_RegisterVariable(&r_motionblur);
2406 Cvar_RegisterVariable(&r_motionblur_maxblur);
2407 Cvar_RegisterVariable(&r_motionblur_bmin);
2408 Cvar_RegisterVariable(&r_motionblur_vmin);
2409 Cvar_RegisterVariable(&r_motionblur_vmax);
2410 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2411 Cvar_RegisterVariable(&r_motionblur_randomize);
2412 Cvar_RegisterVariable(&r_damageblur);
2413 Cvar_RegisterVariable(&r_animcache);
2414 Cvar_RegisterVariable(&r_depthfirst);
2415 Cvar_RegisterVariable(&r_useinfinitefarclip);
2416 Cvar_RegisterVariable(&r_nearclip);
2417 Cvar_RegisterVariable(&r_showbboxes);
2418 Cvar_RegisterVariable(&r_showsurfaces);
2419 Cvar_RegisterVariable(&r_showtris);
2420 Cvar_RegisterVariable(&r_shownormals);
2421 Cvar_RegisterVariable(&r_showlighting);
2422 Cvar_RegisterVariable(&r_showshadowvolumes);
2423 Cvar_RegisterVariable(&r_showcollisionbrushes);
2424 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2425 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2426 Cvar_RegisterVariable(&r_showdisabledepthtest);
2427 Cvar_RegisterVariable(&r_drawportals);
2428 Cvar_RegisterVariable(&r_drawentities);
2429 Cvar_RegisterVariable(&r_cullentities_trace);
2430 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2431 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2432 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2433 Cvar_RegisterVariable(&r_drawviewmodel);
2434 Cvar_RegisterVariable(&r_speeds);
2435 Cvar_RegisterVariable(&r_fullbrights);
2436 Cvar_RegisterVariable(&r_wateralpha);
2437 Cvar_RegisterVariable(&r_dynamic);
2438 Cvar_RegisterVariable(&r_fullbright);
2439 Cvar_RegisterVariable(&r_shadows);
2440 Cvar_RegisterVariable(&r_shadows_darken);
2441 Cvar_RegisterVariable(&r_shadows_drawafterrtlightning);
2442 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
2443 Cvar_RegisterVariable(&r_shadows_throwdistance);
2444 Cvar_RegisterVariable(&r_shadows_throwdirection);
2445 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2446 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2447 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2448 Cvar_RegisterVariable(&r_fog_exp2);
2449 Cvar_RegisterVariable(&r_drawfog);
2450 Cvar_RegisterVariable(&r_textureunits);
2451 Cvar_RegisterVariable(&r_glsl);
2452 Cvar_RegisterVariable(&r_glsl_contrastboost);
2453 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2454 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2455 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2456 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2457 Cvar_RegisterVariable(&r_glsl_postprocess);
2458 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2459 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2460 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2461 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2462 Cvar_RegisterVariable(&r_glsl_usegeneric);
2463 Cvar_RegisterVariable(&r_water);
2464 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2465 Cvar_RegisterVariable(&r_water_clippingplanebias);
2466 Cvar_RegisterVariable(&r_water_refractdistort);
2467 Cvar_RegisterVariable(&r_water_reflectdistort);
2468 Cvar_RegisterVariable(&r_lerpsprites);
2469 Cvar_RegisterVariable(&r_lerpmodels);
2470 Cvar_RegisterVariable(&r_lerplightstyles);
2471 Cvar_RegisterVariable(&r_waterscroll);
2472 Cvar_RegisterVariable(&r_bloom);
2473 Cvar_RegisterVariable(&r_bloom_colorscale);
2474 Cvar_RegisterVariable(&r_bloom_brighten);
2475 Cvar_RegisterVariable(&r_bloom_blur);
2476 Cvar_RegisterVariable(&r_bloom_resolution);
2477 Cvar_RegisterVariable(&r_bloom_colorexponent);
2478 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2479 Cvar_RegisterVariable(&r_hdr);
2480 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2481 Cvar_RegisterVariable(&r_hdr_glowintensity);
2482 Cvar_RegisterVariable(&r_hdr_range);
2483 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2484 Cvar_RegisterVariable(&developer_texturelogging);
2485 Cvar_RegisterVariable(&gl_lightmaps);
2486 Cvar_RegisterVariable(&r_test);
2487 Cvar_RegisterVariable(&r_batchmode);
2488 Cvar_RegisterVariable(&r_glsl_saturation);
2489 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2490 Cvar_SetValue("r_fullbrights", 0);
2491 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2493 Cvar_RegisterVariable(&r_track_sprites);
2494 Cvar_RegisterVariable(&r_track_sprites_flags);
2495 Cvar_RegisterVariable(&r_track_sprites_scalew);
2496 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2499 extern void R_Textures_Init(void);
2500 extern void GL_Draw_Init(void);
2501 extern void GL_Main_Init(void);
2502 extern void R_Shadow_Init(void);
2503 extern void R_Sky_Init(void);
2504 extern void GL_Surf_Init(void);
2505 extern void R_Particles_Init(void);
2506 extern void R_Explosion_Init(void);
2507 extern void gl_backend_init(void);
2508 extern void Sbar_Init(void);
2509 extern void R_LightningBeams_Init(void);
2510 extern void Mod_RenderInit(void);
2512 void Render_Init(void)
2524 R_LightningBeams_Init();
2533 extern char *ENGINE_EXTENSIONS;
2536 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2537 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2538 gl_version = (const char *)qglGetString(GL_VERSION);
2539 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2543 if (!gl_platformextensions)
2544 gl_platformextensions = "";
2546 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2547 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2548 Con_Printf("GL_VERSION: %s\n", gl_version);
2549 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2550 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2552 VID_CheckExtensions();
2554 // LordHavoc: report supported extensions
2555 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2557 // clear to black (loading plaque will be seen over this)
2559 qglClearColor(0,0,0,1);CHECKGLERROR
2560 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2563 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2567 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2569 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2572 p = r_refdef.view.frustum + i;
2577 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2581 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2585 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2589 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2593 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2597 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2601 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2605 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2613 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2617 for (i = 0;i < numplanes;i++)
2624 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2628 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2632 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2636 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2640 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2644 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2648 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2652 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2660 //==================================================================================
2662 // LordHavoc: animcache written by Echon, refactored and reformatted by me
2665 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
2666 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
2667 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
2670 typedef struct r_animcache_entity_s
2677 qboolean wantnormals;
2678 qboolean wanttangents;
2680 r_animcache_entity_t;
2682 typedef struct r_animcache_s
2684 r_animcache_entity_t entity[MAX_EDICTS*2];
2690 static r_animcache_t r_animcachestate;
2692 void R_AnimCache_Free(void)
2695 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
2697 r_animcachestate.entity[idx].maxvertices = 0;
2698 Mem_Free(r_animcachestate.entity[idx].vertex3f);
2699 r_animcachestate.entity[idx].vertex3f = NULL;
2700 r_animcachestate.entity[idx].normal3f = NULL;
2701 r_animcachestate.entity[idx].svector3f = NULL;
2702 r_animcachestate.entity[idx].tvector3f = NULL;
2704 r_animcachestate.currentindex = 0;
2705 r_animcachestate.maxindex = 0;
2708 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
2712 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
2714 if (cache->maxvertices >= numvertices)
2717 // Release existing memory
2718 if (cache->vertex3f)
2719 Mem_Free(cache->vertex3f);
2721 // Pad by 1024 verts
2722 cache->maxvertices = (numvertices + 1023) & ~1023;
2723 arraySize = cache->maxvertices * 3;
2725 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
2726 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
2727 r_animcachestate.entity[cacheIdx].vertex3f = base;
2728 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
2729 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
2730 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
2732 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
2735 void R_AnimCache_NewFrame(void)
2739 if (r_animcache.integer && r_drawentities.integer)
2740 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
2741 else if (r_animcachestate.maxindex)
2744 r_animcachestate.currentindex = 0;
2746 for (i = 0;i < r_refdef.scene.numentities;i++)
2747 r_refdef.scene.entities[i]->animcacheindex = -1;
2750 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2752 dp_model_t *model = ent->model;
2753 r_animcache_entity_t *c;
2754 // see if it's already cached this frame
2755 if (ent->animcacheindex >= 0)
2757 // add normals/tangents if needed
2758 c = r_animcachestate.entity + ent->animcacheindex;
2760 wantnormals = false;
2761 if (c->wanttangents)
2762 wanttangents = false;
2763 if (wantnormals || wanttangents)
2764 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
2768 // see if this ent is worth caching
2769 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
2771 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
2773 // assign it a cache entry and make sure the arrays are big enough
2774 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
2775 ent->animcacheindex = r_animcachestate.currentindex++;
2776 c = r_animcachestate.entity + ent->animcacheindex;
2777 c->wantnormals = wantnormals;
2778 c->wanttangents = wanttangents;
2779 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
2784 void R_AnimCache_CacheVisibleEntities(void)
2787 qboolean wantnormals;
2788 qboolean wanttangents;
2790 if (!r_animcachestate.maxindex)
2793 wantnormals = !r_showsurfaces.integer;
2794 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
2796 // TODO: thread this?
2798 for (i = 0;i < r_refdef.scene.numentities;i++)
2800 if (!r_refdef.viewcache.entityvisible[i])
2802 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
2806 //==================================================================================
2808 static void R_View_UpdateEntityLighting (void)
2811 entity_render_t *ent;
2812 vec3_t tempdiffusenormal;
2814 for (i = 0;i < r_refdef.scene.numentities;i++)
2816 ent = r_refdef.scene.entities[i];
2818 // skip unseen models
2819 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
2823 if (ent->model && ent->model->brush.num_leafs)
2825 // TODO: use modellight for r_ambient settings on world?
2826 VectorSet(ent->modellight_ambient, 0, 0, 0);
2827 VectorSet(ent->modellight_diffuse, 0, 0, 0);
2828 VectorSet(ent->modellight_lightdir, 0, 0, 1);
2832 // fetch the lighting from the worldmodel data
2833 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));
2834 VectorClear(ent->modellight_diffuse);
2835 VectorClear(tempdiffusenormal);
2836 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
2839 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2840 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2843 VectorSet(ent->modellight_ambient, 1, 1, 1);
2845 // move the light direction into modelspace coordinates for lighting code
2846 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2847 if(VectorLength2(ent->modellight_lightdir) == 0)
2848 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2849 VectorNormalize(ent->modellight_lightdir);
2853 static void R_View_UpdateEntityVisible (void)
2856 entity_render_t *ent;
2858 if (!r_drawentities.integer)
2861 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2862 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2864 // worldmodel can check visibility
2865 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2866 for (i = 0;i < r_refdef.scene.numentities;i++)
2868 ent = r_refdef.scene.entities[i];
2869 if (!(ent->flags & renderimask))
2870 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)))
2871 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))
2872 r_refdef.viewcache.entityvisible[i] = true;
2874 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2876 for (i = 0;i < r_refdef.scene.numentities;i++)
2878 ent = r_refdef.scene.entities[i];
2879 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2881 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))
2882 ent->last_trace_visibility = realtime;
2883 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2884 r_refdef.viewcache.entityvisible[i] = 0;
2891 // no worldmodel or it can't check visibility
2892 for (i = 0;i < r_refdef.scene.numentities;i++)
2894 ent = r_refdef.scene.entities[i];
2895 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));
2900 /// only used if skyrendermasked, and normally returns false
2901 int R_DrawBrushModelsSky (void)
2904 entity_render_t *ent;
2906 if (!r_drawentities.integer)
2910 for (i = 0;i < r_refdef.scene.numentities;i++)
2912 if (!r_refdef.viewcache.entityvisible[i])
2914 ent = r_refdef.scene.entities[i];
2915 if (!ent->model || !ent->model->DrawSky)
2917 ent->model->DrawSky(ent);
2923 static void R_DrawNoModel(entity_render_t *ent);
2924 static void R_DrawModels(void)
2927 entity_render_t *ent;
2929 if (!r_drawentities.integer)
2932 for (i = 0;i < r_refdef.scene.numentities;i++)
2934 if (!r_refdef.viewcache.entityvisible[i])
2936 ent = r_refdef.scene.entities[i];
2937 r_refdef.stats.entities++;
2938 if (ent->model && ent->model->Draw != NULL)
2939 ent->model->Draw(ent);
2945 static void R_DrawModelsDepth(void)
2948 entity_render_t *ent;
2950 if (!r_drawentities.integer)
2953 for (i = 0;i < r_refdef.scene.numentities;i++)
2955 if (!r_refdef.viewcache.entityvisible[i])
2957 ent = r_refdef.scene.entities[i];
2958 if (ent->model && ent->model->DrawDepth != NULL)
2959 ent->model->DrawDepth(ent);
2963 static void R_DrawModelsDebug(void)
2966 entity_render_t *ent;
2968 if (!r_drawentities.integer)
2971 for (i = 0;i < r_refdef.scene.numentities;i++)
2973 if (!r_refdef.viewcache.entityvisible[i])
2975 ent = r_refdef.scene.entities[i];
2976 if (ent->model && ent->model->DrawDebug != NULL)
2977 ent->model->DrawDebug(ent);
2981 static void R_DrawModelsAddWaterPlanes(void)
2984 entity_render_t *ent;
2986 if (!r_drawentities.integer)
2989 for (i = 0;i < r_refdef.scene.numentities;i++)
2991 if (!r_refdef.viewcache.entityvisible[i])
2993 ent = r_refdef.scene.entities[i];
2994 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2995 ent->model->DrawAddWaterPlanes(ent);
2999 static void R_View_SetFrustum(void)
3002 double slopex, slopey;
3003 vec3_t forward, left, up, origin;
3005 // we can't trust r_refdef.view.forward and friends in reflected scenes
3006 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3009 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3010 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3011 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3012 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3013 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3014 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3015 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3016 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3017 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3018 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3019 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3020 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3024 zNear = r_refdef.nearclip;
3025 nudge = 1.0 - 1.0 / (1<<23);
3026 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3027 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3028 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3029 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3030 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3031 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3032 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3033 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3039 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3040 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3041 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3042 r_refdef.view.frustum[0].dist = m[15] - m[12];
3044 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3045 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3046 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3047 r_refdef.view.frustum[1].dist = m[15] + m[12];
3049 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3050 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3051 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3052 r_refdef.view.frustum[2].dist = m[15] - m[13];
3054 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3055 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3056 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3057 r_refdef.view.frustum[3].dist = m[15] + m[13];
3059 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3060 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3061 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3062 r_refdef.view.frustum[4].dist = m[15] - m[14];
3064 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3065 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3066 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3067 r_refdef.view.frustum[5].dist = m[15] + m[14];
3070 if (r_refdef.view.useperspective)
3072 slopex = 1.0 / r_refdef.view.frustum_x;
3073 slopey = 1.0 / r_refdef.view.frustum_y;
3074 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3075 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3076 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3077 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3078 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3080 // Leaving those out was a mistake, those were in the old code, and they
3081 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3082 // I couldn't reproduce it after adding those normalizations. --blub
3083 VectorNormalize(r_refdef.view.frustum[0].normal);
3084 VectorNormalize(r_refdef.view.frustum[1].normal);
3085 VectorNormalize(r_refdef.view.frustum[2].normal);
3086 VectorNormalize(r_refdef.view.frustum[3].normal);
3088 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3089 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
3090 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
3091 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
3092 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
3094 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3095 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3096 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3097 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3098 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3102 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3103 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3104 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3105 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3106 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3107 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3108 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3109 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3110 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3111 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3113 r_refdef.view.numfrustumplanes = 5;
3115 if (r_refdef.view.useclipplane)
3117 r_refdef.view.numfrustumplanes = 6;
3118 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3121 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3122 PlaneClassify(r_refdef.view.frustum + i);
3124 // LordHavoc: note to all quake engine coders, Quake had a special case
3125 // for 90 degrees which assumed a square view (wrong), so I removed it,
3126 // Quake2 has it disabled as well.
3128 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3129 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3130 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3131 //PlaneClassify(&frustum[0]);
3133 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3134 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3135 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3136 //PlaneClassify(&frustum[1]);
3138 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3139 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3140 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3141 //PlaneClassify(&frustum[2]);
3143 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3144 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3145 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3146 //PlaneClassify(&frustum[3]);
3149 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3150 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3151 //PlaneClassify(&frustum[4]);
3154 void R_View_Update(void)
3156 R_View_SetFrustum();
3157 R_View_WorldVisibility(r_refdef.view.useclipplane);
3158 R_View_UpdateEntityVisible();
3159 R_View_UpdateEntityLighting();
3162 void R_SetupView(qboolean allowwaterclippingplane)
3164 if (!r_refdef.view.useperspective)
3165 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);
3166 else if (gl_stencil && r_useinfinitefarclip.integer)
3167 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
3169 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
3171 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
3173 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3175 // LordHavoc: couldn't figure out how to make this approach the
3176 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3177 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3178 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3179 dist = r_refdef.view.clipplane.dist;
3180 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
3184 void R_ResetViewRendering2D(void)
3188 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3189 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3190 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
3191 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3192 GL_Color(1, 1, 1, 1);
3193 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3194 GL_BlendFunc(GL_ONE, GL_ZERO);
3195 GL_AlphaTest(false);
3196 GL_ScissorTest(false);
3197 GL_DepthMask(false);
3198 GL_DepthRange(0, 1);
3199 GL_DepthTest(false);
3200 R_Mesh_Matrix(&identitymatrix);
3201 R_Mesh_ResetTextureState();
3202 GL_PolygonOffset(0, 0);
3203 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3204 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3205 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3206 qglStencilMask(~0);CHECKGLERROR
3207 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3208 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3209 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3210 R_SetupGenericShader(true);
3213 void R_ResetViewRendering3D(void)
3217 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3218 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3220 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3221 GL_Color(1, 1, 1, 1);
3222 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3223 GL_BlendFunc(GL_ONE, GL_ZERO);
3224 GL_AlphaTest(false);
3225 GL_ScissorTest(true);
3227 GL_DepthRange(0, 1);
3229 R_Mesh_Matrix(&identitymatrix);
3230 R_Mesh_ResetTextureState();
3231 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3232 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3233 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3234 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3235 qglStencilMask(~0);CHECKGLERROR
3236 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3237 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3238 GL_CullFace(r_refdef.view.cullface_back);
3239 R_SetupGenericShader(true);
3242 void R_RenderScene(void);
3243 void R_RenderWaterPlanes(void);
3245 static void R_Water_StartFrame(void)
3248 int waterwidth, waterheight, texturewidth, textureheight;
3249 r_waterstate_waterplane_t *p;
3251 // set waterwidth and waterheight to the water resolution that will be
3252 // used (often less than the screen resolution for faster rendering)
3253 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3254 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3256 // calculate desired texture sizes
3257 // can't use water if the card does not support the texture size
3258 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3259 texturewidth = textureheight = waterwidth = waterheight = 0;
3260 else if (gl_support_arb_texture_non_power_of_two)
3262 texturewidth = waterwidth;
3263 textureheight = waterheight;
3267 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3268 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3271 // allocate textures as needed
3272 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3274 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3275 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3277 if (p->texture_refraction)
3278 R_FreeTexture(p->texture_refraction);
3279 p->texture_refraction = NULL;
3280 if (p->texture_reflection)
3281 R_FreeTexture(p->texture_reflection);
3282 p->texture_reflection = NULL;
3284 memset(&r_waterstate, 0, sizeof(r_waterstate));
3285 r_waterstate.waterwidth = waterwidth;
3286 r_waterstate.waterheight = waterheight;
3287 r_waterstate.texturewidth = texturewidth;
3288 r_waterstate.textureheight = textureheight;
3291 if (r_waterstate.waterwidth)
3293 r_waterstate.enabled = true;
3295 // set up variables that will be used in shader setup
3296 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3297 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3298 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3299 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3302 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3303 r_waterstate.numwaterplanes = 0;
3306 void R_Water_AddWaterPlane(msurface_t *surface)
3308 int triangleindex, planeindex;
3314 r_waterstate_waterplane_t *p;
3315 texture_t *t = R_GetCurrentTexture(surface->texture);
3316 // just use the first triangle with a valid normal for any decisions
3317 VectorClear(normal);
3318 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3320 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3321 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3322 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3323 TriangleNormal(vert[0], vert[1], vert[2], normal);
3324 if (VectorLength2(normal) >= 0.001)
3328 VectorCopy(normal, plane.normal);
3329 VectorNormalize(plane.normal);
3330 plane.dist = DotProduct(vert[0], plane.normal);
3331 PlaneClassify(&plane);
3332 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3334 // skip backfaces (except if nocullface is set)
3335 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3337 VectorNegate(plane.normal, plane.normal);
3339 PlaneClassify(&plane);
3343 // find a matching plane if there is one
3344 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3345 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3347 if (planeindex >= r_waterstate.maxwaterplanes)
3348 return; // nothing we can do, out of planes
3350 // if this triangle does not fit any known plane rendered this frame, add one
3351 if (planeindex >= r_waterstate.numwaterplanes)
3353 // store the new plane
3354 r_waterstate.numwaterplanes++;
3356 // clear materialflags and pvs
3357 p->materialflags = 0;
3358 p->pvsvalid = false;
3360 // merge this surface's materialflags into the waterplane
3361 p->materialflags |= t->currentmaterialflags;
3362 // merge this surface's PVS into the waterplane
3363 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3364 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3365 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3367 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3372 static void R_Water_ProcessPlanes(void)
3374 r_refdef_view_t originalview;
3375 r_refdef_view_t myview;
3377 r_waterstate_waterplane_t *p;
3379 originalview = r_refdef.view;
3381 // make sure enough textures are allocated
3382 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3384 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3386 if (!p->texture_refraction)
3387 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);
3388 if (!p->texture_refraction)
3392 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3394 if (!p->texture_reflection)
3395 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);
3396 if (!p->texture_reflection)
3402 r_refdef.view = originalview;
3403 r_refdef.view.showdebug = false;
3404 r_refdef.view.width = r_waterstate.waterwidth;
3405 r_refdef.view.height = r_waterstate.waterheight;
3406 r_refdef.view.useclipplane = true;
3407 myview = r_refdef.view;
3408 r_waterstate.renderingscene = true;
3409 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3411 // render the normal view scene and copy into texture
3412 // (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)
3413 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3415 r_refdef.view = myview;
3416 r_refdef.view.clipplane = p->plane;
3417 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3418 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3419 PlaneClassify(&r_refdef.view.clipplane);
3421 R_ResetViewRendering3D();
3422 R_ClearScreen(r_refdef.fogenabled);
3426 // copy view into the screen texture
3427 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3428 GL_ActiveTexture(0);
3430 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
3433 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3435 r_refdef.view = myview;
3436 // render reflected scene and copy into texture
3437 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3438 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3439 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3440 r_refdef.view.clipplane = p->plane;
3441 // reverse the cullface settings for this render
3442 r_refdef.view.cullface_front = GL_FRONT;
3443 r_refdef.view.cullface_back = GL_BACK;
3444 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3446 r_refdef.view.usecustompvs = true;
3448 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3450 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3453 R_ResetViewRendering3D();
3454 R_ClearScreen(r_refdef.fogenabled);
3458 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3459 GL_ActiveTexture(0);
3461 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
3464 r_waterstate.renderingscene = false;
3465 r_refdef.view = originalview;
3466 R_ResetViewRendering3D();
3467 R_ClearScreen(r_refdef.fogenabled);
3471 r_refdef.view = originalview;
3472 r_waterstate.renderingscene = false;
3473 Cvar_SetValueQuick(&r_water, 0);
3474 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3478 void R_Bloom_StartFrame(void)
3480 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3482 // set bloomwidth and bloomheight to the bloom resolution that will be
3483 // used (often less than the screen resolution for faster rendering)
3484 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3485 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3486 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3487 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3488 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3490 // calculate desired texture sizes
3491 if (gl_support_arb_texture_non_power_of_two)
3493 screentexturewidth = r_refdef.view.width;
3494 screentextureheight = r_refdef.view.height;
3495 bloomtexturewidth = r_bloomstate.bloomwidth;
3496 bloomtextureheight = r_bloomstate.bloomheight;
3500 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3501 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3502 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3503 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3506 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
3508 Cvar_SetValueQuick(&r_hdr, 0);
3509 Cvar_SetValueQuick(&r_bloom, 0);
3510 Cvar_SetValueQuick(&r_motionblur, 0);
3511 Cvar_SetValueQuick(&r_damageblur, 0);
3514 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
3515 screentexturewidth = screentextureheight = 0;
3516 if (!r_hdr.integer && !r_bloom.integer)
3517 bloomtexturewidth = bloomtextureheight = 0;
3519 // allocate textures as needed
3520 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3522 if (r_bloomstate.texture_screen)
3523 R_FreeTexture(r_bloomstate.texture_screen);
3524 r_bloomstate.texture_screen = NULL;
3525 r_bloomstate.screentexturewidth = screentexturewidth;
3526 r_bloomstate.screentextureheight = screentextureheight;
3527 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3528 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);
3530 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3532 if (r_bloomstate.texture_bloom)
3533 R_FreeTexture(r_bloomstate.texture_bloom);
3534 r_bloomstate.texture_bloom = NULL;
3535 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3536 r_bloomstate.bloomtextureheight = bloomtextureheight;
3537 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3538 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);
3541 // set up a texcoord array for the full resolution screen image
3542 // (we have to keep this around to copy back during final render)
3543 r_bloomstate.screentexcoord2f[0] = 0;
3544 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3545 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3546 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3547 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3548 r_bloomstate.screentexcoord2f[5] = 0;
3549 r_bloomstate.screentexcoord2f[6] = 0;
3550 r_bloomstate.screentexcoord2f[7] = 0;
3552 // set up a texcoord array for the reduced resolution bloom image
3553 // (which will be additive blended over the screen image)
3554 r_bloomstate.bloomtexcoord2f[0] = 0;
3555 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3556 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3557 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3558 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3559 r_bloomstate.bloomtexcoord2f[5] = 0;
3560 r_bloomstate.bloomtexcoord2f[6] = 0;
3561 r_bloomstate.bloomtexcoord2f[7] = 0;
3563 if (r_hdr.integer || r_bloom.integer)
3565 r_bloomstate.enabled = true;
3566 r_bloomstate.hdr = r_hdr.integer != 0;
3570 void R_Bloom_CopyBloomTexture(float colorscale)
3572 r_refdef.stats.bloom++;
3574 // scale down screen texture to the bloom texture size
3576 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3577 GL_BlendFunc(GL_ONE, GL_ZERO);
3578 GL_Color(colorscale, colorscale, colorscale, 1);
3579 // TODO: optimize with multitexture or GLSL
3580 R_SetupGenericShader(true);
3581 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3582 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3583 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3584 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3586 // we now have a bloom image in the framebuffer
3587 // copy it into the bloom image texture for later processing
3588 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3589 GL_ActiveTexture(0);
3591 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
3592 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3595 void R_Bloom_CopyHDRTexture(void)
3597 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3598 GL_ActiveTexture(0);
3600 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
3601 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3604 void R_Bloom_MakeTexture(void)
3607 float xoffset, yoffset, r, brighten;
3609 r_refdef.stats.bloom++;
3611 R_ResetViewRendering2D();
3612 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3613 R_Mesh_ColorPointer(NULL, 0, 0);
3614 R_SetupGenericShader(true);
3616 // we have a bloom image in the framebuffer
3618 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3620 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3623 r = bound(0, r_bloom_colorexponent.value / x, 1);
3624 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3625 GL_Color(r, r, r, 1);
3626 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3627 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3628 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3629 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3631 // copy the vertically blurred bloom view to a texture
3632 GL_ActiveTexture(0);
3634 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
3635 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3638 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3639 brighten = r_bloom_brighten.value;
3641 brighten *= r_hdr_range.value;
3642 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3643 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3645 for (dir = 0;dir < 2;dir++)
3647 // blend on at multiple vertical offsets to achieve a vertical blur
3648 // TODO: do offset blends using GLSL
3649 GL_BlendFunc(GL_ONE, GL_ZERO);
3650 for (x = -range;x <= range;x++)
3652 if (!dir){xoffset = 0;yoffset = x;}
3653 else {xoffset = x;yoffset = 0;}
3654 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3655 yoffset /= (float)r_bloomstate.bloomtextureheight;
3656 // compute a texcoord array with the specified x and y offset
3657 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3658 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3659 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3660 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3661 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3662 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3663 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3664 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3665 // this r value looks like a 'dot' particle, fading sharply to
3666 // black at the edges
3667 // (probably not realistic but looks good enough)
3668 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3669 //r = (dir ? 1.0f : brighten)/(range*2+1);
3670 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3671 GL_Color(r, r, r, 1);
3672 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3673 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3674 GL_BlendFunc(GL_ONE, GL_ONE);
3677 // copy the vertically blurred bloom view to a texture
3678 GL_ActiveTexture(0);
3680 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
3681 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3684 // apply subtract last
3685 // (just like it would be in a GLSL shader)
3686 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3688 GL_BlendFunc(GL_ONE, GL_ZERO);
3689 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3690 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3691 GL_Color(1, 1, 1, 1);
3692 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3693 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3695 GL_BlendFunc(GL_ONE, GL_ONE);
3696 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3697 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3698 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3699 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3700 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3701 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3702 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3704 // copy the darkened bloom view to a texture
3705 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3706 GL_ActiveTexture(0);
3708 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
3709 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3713 void R_HDR_RenderBloomTexture(void)
3715 int oldwidth, oldheight;
3716 float oldcolorscale;
3718 oldcolorscale = r_refdef.view.colorscale;
3719 oldwidth = r_refdef.view.width;
3720 oldheight = r_refdef.view.height;
3721 r_refdef.view.width = r_bloomstate.bloomwidth;
3722 r_refdef.view.height = r_bloomstate.bloomheight;
3724 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3725 // TODO: add exposure compensation features
3726 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
3728 r_refdef.view.showdebug = false;
3729 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3731 R_ResetViewRendering3D();
3733 R_ClearScreen(r_refdef.fogenabled);
3734 if (r_timereport_active)
3735 R_TimeReport("HDRclear");
3738 if (r_timereport_active)
3739 R_TimeReport("visibility");
3741 r_waterstate.numwaterplanes = 0;
3742 if (r_waterstate.enabled)
3743 R_RenderWaterPlanes();
3745 r_refdef.view.showdebug = true;
3747 r_waterstate.numwaterplanes = 0;
3749 R_ResetViewRendering2D();
3751 R_Bloom_CopyHDRTexture();
3752 R_Bloom_MakeTexture();
3754 // restore the view settings
3755 r_refdef.view.width = oldwidth;
3756 r_refdef.view.height = oldheight;
3757 r_refdef.view.colorscale = oldcolorscale;
3759 R_ResetViewRendering3D();
3761 R_ClearScreen(r_refdef.fogenabled);
3762 if (r_timereport_active)
3763 R_TimeReport("viewclear");
3766 static void R_BlendView(void)
3768 if (r_bloomstate.texture_screen)
3770 // make sure the buffer is available
3771 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
3773 R_ResetViewRendering2D();
3774 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3775 R_Mesh_ColorPointer(NULL, 0, 0);
3776 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3777 GL_ActiveTexture(0);CHECKGLERROR
3779 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
3781 // declare variables
3783 static float avgspeed;
3785 speed = VectorLength(cl.movement_velocity);
3787 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
3788 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
3790 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
3791 speed = bound(0, speed, 1);
3792 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
3794 // calculate values into a standard alpha
3795 cl.motionbluralpha = 1 - exp(-
3797 (r_motionblur.value * speed / 80)
3799 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
3802 max(0.0001, cl.time - cl.oldtime) // fps independent
3805 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
3806 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
3808 if (cl.motionbluralpha > 0)
3810 R_SetupGenericShader(true);
3811 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3812 GL_Color(1, 1, 1, cl.motionbluralpha);
3813 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3814 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3815 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3816 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3820 // copy view into the screen texture
3821 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
3822 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3825 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3827 unsigned int permutation =
3828 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3829 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3830 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3831 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
3832 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
3834 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3836 // render simple bloom effect
3837 // copy the screen and shrink it and darken it for the bloom process
3838 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3839 // make the bloom texture
3840 R_Bloom_MakeTexture();
3843 R_ResetViewRendering2D();
3844 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3845 R_Mesh_ColorPointer(NULL, 0, 0);
3846 GL_Color(1, 1, 1, 1);
3847 GL_BlendFunc(GL_ONE, GL_ZERO);
3848 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3849 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3850 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3851 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3852 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3853 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3854 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3855 if (r_glsl_permutation->loc_TintColor >= 0)
3856 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3857 if (r_glsl_permutation->loc_ClientTime >= 0)
3858 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3859 if (r_glsl_permutation->loc_PixelSize >= 0)
3860 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3861 if (r_glsl_permutation->loc_UserVec1 >= 0)
3863 float a=0, b=0, c=0, d=0;
3864 #if _MSC_VER >= 1400
3865 #define sscanf sscanf_s
3867 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3868 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3870 if (r_glsl_permutation->loc_UserVec2 >= 0)
3872 float a=0, b=0, c=0, d=0;
3873 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3874 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3876 if (r_glsl_permutation->loc_UserVec3 >= 0)
3878 float a=0, b=0, c=0, d=0;
3879 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3880 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3882 if (r_glsl_permutation->loc_UserVec4 >= 0)
3884 float a=0, b=0, c=0, d=0;
3885 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3886 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3888 if (r_glsl_permutation->loc_Saturation >= 0)
3889 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
3890 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3891 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3897 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3899 // render high dynamic range bloom effect
3900 // the bloom texture was made earlier this render, so we just need to
3901 // blend it onto the screen...
3902 R_ResetViewRendering2D();
3903 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3904 R_Mesh_ColorPointer(NULL, 0, 0);
3905 R_SetupGenericShader(true);
3906 GL_Color(1, 1, 1, 1);
3907 GL_BlendFunc(GL_ONE, GL_ONE);
3908 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3909 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3910 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3911 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3913 else if (r_bloomstate.texture_bloom)
3915 // render simple bloom effect
3916 // copy the screen and shrink it and darken it for the bloom process
3917 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3918 // make the bloom texture
3919 R_Bloom_MakeTexture();
3920 // put the original screen image back in place and blend the bloom
3922 R_ResetViewRendering2D();
3923 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3924 R_Mesh_ColorPointer(NULL, 0, 0);
3925 GL_Color(1, 1, 1, 1);
3926 GL_BlendFunc(GL_ONE, GL_ZERO);
3927 // do both in one pass if possible
3928 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3929 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3930 if (r_textureunits.integer >= 2 && gl_combine.integer)
3932 R_SetupGenericTwoTextureShader(GL_ADD);
3933 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3934 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3938 R_SetupGenericShader(true);
3939 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3940 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3941 // now blend on the bloom texture
3942 GL_BlendFunc(GL_ONE, GL_ONE);
3943 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3944 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3946 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3947 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3949 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3951 // apply a color tint to the whole view
3952 R_ResetViewRendering2D();
3953 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3954 R_Mesh_ColorPointer(NULL, 0, 0);
3955 R_SetupGenericShader(false);
3956 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3957 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3958 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3962 matrix4x4_t r_waterscrollmatrix;
3964 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3966 if (r_refdef.fog_density)
3968 r_refdef.fogcolor[0] = r_refdef.fog_red;
3969 r_refdef.fogcolor[1] = r_refdef.fog_green;
3970 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3974 VectorCopy(r_refdef.fogcolor, fogvec);
3975 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3977 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3978 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3979 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3980 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3982 // color.rgb *= ContrastBoost * SceneBrightness;
3983 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3984 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3985 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3986 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3991 void R_UpdateVariables(void)
3995 r_refdef.scene.ambient = r_ambient.value;
3997 r_refdef.farclip = 4096;
3998 if (r_refdef.scene.worldmodel)
3999 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4000 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4002 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4003 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4004 r_refdef.polygonfactor = 0;
4005 r_refdef.polygonoffset = 0;
4006 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4007 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4009 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4010 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4011 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4012 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4013 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4014 if (r_showsurfaces.integer)
4016 r_refdef.scene.rtworld = false;
4017 r_refdef.scene.rtworldshadows = false;
4018 r_refdef.scene.rtdlight = false;
4019 r_refdef.scene.rtdlightshadows = false;
4020 r_refdef.lightmapintensity = 0;
4023 if (gamemode == GAME_NEHAHRA)
4025 if (gl_fogenable.integer)
4027 r_refdef.oldgl_fogenable = true;
4028 r_refdef.fog_density = gl_fogdensity.value;
4029 r_refdef.fog_red = gl_fogred.value;
4030 r_refdef.fog_green = gl_foggreen.value;
4031 r_refdef.fog_blue = gl_fogblue.value;
4032 r_refdef.fog_alpha = 1;
4033 r_refdef.fog_start = 0;
4034 r_refdef.fog_end = gl_skyclip.value;
4036 else if (r_refdef.oldgl_fogenable)
4038 r_refdef.oldgl_fogenable = false;
4039 r_refdef.fog_density = 0;
4040 r_refdef.fog_red = 0;
4041 r_refdef.fog_green = 0;
4042 r_refdef.fog_blue = 0;
4043 r_refdef.fog_alpha = 0;
4044 r_refdef.fog_start = 0;
4045 r_refdef.fog_end = 0;
4049 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4050 r_refdef.fog_start = max(0, r_refdef.fog_start);
4051 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4053 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4055 if (r_refdef.fog_density && r_drawfog.integer)
4057 r_refdef.fogenabled = true;
4058 // this is the point where the fog reaches 0.9986 alpha, which we
4059 // consider a good enough cutoff point for the texture
4060 // (0.9986 * 256 == 255.6)
4061 if (r_fog_exp2.integer)
4062 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4064 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4065 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4066 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4067 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4068 // fog color was already set
4069 // update the fog texture
4070 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)
4071 R_BuildFogTexture();
4074 r_refdef.fogenabled = false;
4076 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4078 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4080 // build GLSL gamma texture
4081 #define RAMPWIDTH 256
4082 unsigned short ramp[RAMPWIDTH * 3];
4083 unsigned char rampbgr[RAMPWIDTH][4];
4086 r_texture_gammaramps_serial = vid_gammatables_serial;
4088 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4089 for(i = 0; i < RAMPWIDTH; ++i)
4091 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4092 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4093 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4096 if (r_texture_gammaramps)
4098 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4102 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);
4108 // remove GLSL gamma texture
4112 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4113 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4119 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4120 if( scenetype != r_currentscenetype ) {
4121 // store the old scenetype
4122 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4123 r_currentscenetype = scenetype;
4124 // move in the new scene
4125 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4134 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4136 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4137 if( scenetype == r_currentscenetype ) {
4138 return &r_refdef.scene;
4140 return &r_scenes_store[ scenetype ];
4149 void R_RenderView(void)
4151 r_frame++; // used only by R_GetCurrentTexture
4152 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4154 R_AnimCache_NewFrame();
4156 if (r_refdef.view.isoverlay)
4158 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4159 GL_Clear( GL_DEPTH_BUFFER_BIT );
4160 R_TimeReport("depthclear");
4162 r_refdef.view.showdebug = false;
4164 r_waterstate.enabled = false;
4165 r_waterstate.numwaterplanes = 0;
4173 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4174 return; //Host_Error ("R_RenderView: NULL worldmodel");
4176 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4178 // break apart the view matrix into vectors for various purposes
4179 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4180 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4181 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4182 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4183 // make an inverted copy of the view matrix for tracking sprites
4184 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4186 R_Shadow_UpdateWorldLightSelection();
4188 R_Bloom_StartFrame();
4189 R_Water_StartFrame();
4192 if (r_timereport_active)
4193 R_TimeReport("viewsetup");
4195 R_ResetViewRendering3D();
4197 if (r_refdef.view.clear || r_refdef.fogenabled)
4199 R_ClearScreen(r_refdef.fogenabled);
4200 if (r_timereport_active)
4201 R_TimeReport("viewclear");
4203 r_refdef.view.clear = true;
4205 // this produces a bloom texture to be used in R_BlendView() later
4207 R_HDR_RenderBloomTexture();
4209 r_refdef.view.showdebug = true;
4212 if (r_timereport_active)
4213 R_TimeReport("visibility");
4215 r_waterstate.numwaterplanes = 0;
4216 if (r_waterstate.enabled)
4217 R_RenderWaterPlanes();
4220 r_waterstate.numwaterplanes = 0;
4223 if (r_timereport_active)
4224 R_TimeReport("blendview");
4226 GL_Scissor(0, 0, vid.width, vid.height);
4227 GL_ScissorTest(false);
4231 void R_RenderWaterPlanes(void)
4233 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4235 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4236 if (r_timereport_active)
4237 R_TimeReport("waterworld");
4240 // don't let sound skip if going slow
4241 if (r_refdef.scene.extraupdate)
4244 R_DrawModelsAddWaterPlanes();
4245 if (r_timereport_active)
4246 R_TimeReport("watermodels");
4248 if (r_waterstate.numwaterplanes)
4250 R_Water_ProcessPlanes();
4251 if (r_timereport_active)
4252 R_TimeReport("waterscenes");
4256 extern void R_DrawLightningBeams (void);
4257 extern void VM_CL_AddPolygonsToMeshQueue (void);
4258 extern void R_DrawPortals (void);
4259 extern cvar_t cl_locs_show;
4260 static void R_DrawLocs(void);
4261 static void R_DrawEntityBBoxes(void);
4262 void R_RenderScene(void)
4264 r_refdef.stats.renders++;
4268 // don't let sound skip if going slow
4269 if (r_refdef.scene.extraupdate)
4272 R_MeshQueue_BeginScene();
4276 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);
4278 if (cl.csqc_vidvars.drawworld)
4280 // don't let sound skip if going slow
4281 if (r_refdef.scene.extraupdate)
4284 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4286 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4287 if (r_timereport_active)
4288 R_TimeReport("worldsky");
4291 if (R_DrawBrushModelsSky() && r_timereport_active)
4292 R_TimeReport("bmodelsky");
4295 R_AnimCache_CacheVisibleEntities();
4297 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4299 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4300 if (r_timereport_active)
4301 R_TimeReport("worlddepth");
4303 if (r_depthfirst.integer >= 2)
4305 R_DrawModelsDepth();
4306 if (r_timereport_active)
4307 R_TimeReport("modeldepth");
4310 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4312 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4313 if (r_timereport_active)
4314 R_TimeReport("world");
4317 // don't let sound skip if going slow
4318 if (r_refdef.scene.extraupdate)
4322 if (r_timereport_active)
4323 R_TimeReport("models");
4325 // don't let sound skip if going slow
4326 if (r_refdef.scene.extraupdate)
4329 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlightning.integer && r_refdef.lightmapintensity > 0)
4331 R_DrawModelShadows();
4332 R_ResetViewRendering3D();
4333 // don't let sound skip if going slow
4334 if (r_refdef.scene.extraupdate)
4338 R_ShadowVolumeLighting(false);
4339 if (r_timereport_active)
4340 R_TimeReport("rtlights");
4342 // don't let sound skip if going slow
4343 if (r_refdef.scene.extraupdate)
4346 if (r_shadows.integer > 0 && r_shadows_drawafterrtlightning.integer && r_refdef.lightmapintensity > 0)
4348 R_DrawModelShadows();
4349 R_ResetViewRendering3D();
4350 // don't let sound skip if going slow
4351 if (r_refdef.scene.extraupdate)
4355 if (cl.csqc_vidvars.drawworld)
4357 R_DrawLightningBeams();
4358 if (r_timereport_active)
4359 R_TimeReport("lightning");
4362 if (r_timereport_active)
4363 R_TimeReport("decals");
4366 if (r_timereport_active)
4367 R_TimeReport("particles");
4370 if (r_timereport_active)
4371 R_TimeReport("explosions");
4374 R_SetupGenericShader(true);
4375 VM_CL_AddPolygonsToMeshQueue();
4377 if (r_refdef.view.showdebug)
4379 if (cl_locs_show.integer)
4382 if (r_timereport_active)
4383 R_TimeReport("showlocs");
4386 if (r_drawportals.integer)
4389 if (r_timereport_active)
4390 R_TimeReport("portals");
4393 if (r_showbboxes.value > 0)
4395 R_DrawEntityBBoxes();
4396 if (r_timereport_active)
4397 R_TimeReport("bboxes");
4401 R_SetupGenericShader(true);
4402 R_MeshQueue_RenderTransparent();
4403 if (r_timereport_active)
4404 R_TimeReport("drawtrans");
4406 R_SetupGenericShader(true);
4408 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))
4410 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4411 if (r_timereport_active)
4412 R_TimeReport("worlddebug");
4413 R_DrawModelsDebug();
4414 if (r_timereport_active)
4415 R_TimeReport("modeldebug");
4418 R_SetupGenericShader(true);
4420 if (cl.csqc_vidvars.drawworld)
4423 if (r_timereport_active)
4424 R_TimeReport("coronas");
4427 // don't let sound skip if going slow
4428 if (r_refdef.scene.extraupdate)
4431 R_ResetViewRendering2D();
4434 static const unsigned short bboxelements[36] =
4444 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4447 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4448 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4449 GL_DepthMask(false);
4450 GL_DepthRange(0, 1);
4451 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4452 R_Mesh_Matrix(&identitymatrix);
4453 R_Mesh_ResetTextureState();
4455 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4456 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4457 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4458 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4459 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4460 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4461 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4462 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4463 R_FillColors(color4f, 8, cr, cg, cb, ca);
4464 if (r_refdef.fogenabled)
4466 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4468 f1 = FogPoint_World(v);
4470 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4471 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4472 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4475 R_Mesh_VertexPointer(vertex3f, 0, 0);
4476 R_Mesh_ColorPointer(color4f, 0, 0);
4477 R_Mesh_ResetTextureState();
4478 R_SetupGenericShader(false);
4479 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4482 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4486 prvm_edict_t *edict;
4487 prvm_prog_t *prog_save = prog;
4489 // this function draws bounding boxes of server entities
4493 GL_CullFace(GL_NONE);
4494 R_SetupGenericShader(false);
4498 for (i = 0;i < numsurfaces;i++)
4500 edict = PRVM_EDICT_NUM(surfacelist[i]);
4501 switch ((int)edict->fields.server->solid)
4503 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4504 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4505 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4506 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4507 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4508 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4510 color[3] *= r_showbboxes.value;
4511 color[3] = bound(0, color[3], 1);
4512 GL_DepthTest(!r_showdisabledepthtest.integer);
4513 GL_CullFace(r_refdef.view.cullface_front);
4514 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4520 static void R_DrawEntityBBoxes(void)
4523 prvm_edict_t *edict;
4525 prvm_prog_t *prog_save = prog;
4527 // this function draws bounding boxes of server entities
4533 for (i = 0;i < prog->num_edicts;i++)
4535 edict = PRVM_EDICT_NUM(i);
4536 if (edict->priv.server->free)
4538 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4539 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4541 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4543 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4544 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4550 unsigned short nomodelelements[24] =
4562 float nomodelvertex3f[6*3] =
4572 float nomodelcolor4f[6*4] =
4574 0.0f, 0.0f, 0.5f, 1.0f,
4575 0.0f, 0.0f, 0.5f, 1.0f,
4576 0.0f, 0.5f, 0.0f, 1.0f,
4577 0.0f, 0.5f, 0.0f, 1.0f,
4578 0.5f, 0.0f, 0.0f, 1.0f,
4579 0.5f, 0.0f, 0.0f, 1.0f
4582 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4587 // this is only called once per entity so numsurfaces is always 1, and
4588 // surfacelist is always {0}, so this code does not handle batches
4589 R_Mesh_Matrix(&ent->matrix);
4591 if (ent->flags & EF_ADDITIVE)
4593 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4594 GL_DepthMask(false);
4596 else if (ent->alpha < 1)
4598 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4599 GL_DepthMask(false);
4603 GL_BlendFunc(GL_ONE, GL_ZERO);
4606 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4607 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4608 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4609 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4610 R_SetupGenericShader(false);
4611 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4612 if (r_refdef.fogenabled)
4615 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4616 R_Mesh_ColorPointer(color4f, 0, 0);
4617 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4618 f1 = FogPoint_World(org);
4620 for (i = 0, c = color4f;i < 6;i++, c += 4)
4622 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4623 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4624 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4628 else if (ent->alpha != 1)
4630 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4631 R_Mesh_ColorPointer(color4f, 0, 0);
4632 for (i = 0, c = color4f;i < 6;i++, c += 4)
4636 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4637 R_Mesh_ResetTextureState();
4638 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4641 void R_DrawNoModel(entity_render_t *ent)
4644 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4645 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4646 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4648 // R_DrawNoModelCallback(ent, 0);
4651 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4653 vec3_t right1, right2, diff, normal;
4655 VectorSubtract (org2, org1, normal);
4657 // calculate 'right' vector for start
4658 VectorSubtract (r_refdef.view.origin, org1, diff);
4659 CrossProduct (normal, diff, right1);
4660 VectorNormalize (right1);
4662 // calculate 'right' vector for end
4663 VectorSubtract (r_refdef.view.origin, org2, diff);
4664 CrossProduct (normal, diff, right2);
4665 VectorNormalize (right2);
4667 vert[ 0] = org1[0] + width * right1[0];
4668 vert[ 1] = org1[1] + width * right1[1];
4669 vert[ 2] = org1[2] + width * right1[2];
4670 vert[ 3] = org1[0] - width * right1[0];
4671 vert[ 4] = org1[1] - width * right1[1];
4672 vert[ 5] = org1[2] - width * right1[2];
4673 vert[ 6] = org2[0] - width * right2[0];
4674 vert[ 7] = org2[1] - width * right2[1];
4675 vert[ 8] = org2[2] - width * right2[2];
4676 vert[ 9] = org2[0] + width * right2[0];
4677 vert[10] = org2[1] + width * right2[1];
4678 vert[11] = org2[2] + width * right2[2];
4681 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4683 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)
4685 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4689 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4690 fog = FogPoint_World(origin);
4692 R_Mesh_Matrix(&identitymatrix);
4693 GL_BlendFunc(blendfunc1, blendfunc2);
4695 GL_CullFace(GL_NONE);
4697 GL_DepthMask(false);
4698 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4699 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4700 GL_DepthTest(!depthdisable);
4702 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4703 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4704 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4705 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4706 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4707 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4708 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4709 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4710 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4711 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4712 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4713 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4715 R_Mesh_VertexPointer(vertex3f, 0, 0);
4716 R_Mesh_ColorPointer(NULL, 0, 0);
4717 R_Mesh_ResetTextureState();
4718 R_SetupGenericShader(true);
4719 R_Mesh_TexBind(0, R_GetTexture(texture));
4720 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4721 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4722 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4723 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4725 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4727 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4728 GL_BlendFunc(blendfunc1, GL_ONE);
4730 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4731 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4735 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4740 VectorSet(v, x, y, z);
4741 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4742 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4744 if (i == mesh->numvertices)
4746 if (mesh->numvertices < mesh->maxvertices)
4748 VectorCopy(v, vertex3f);
4749 mesh->numvertices++;
4751 return mesh->numvertices;
4757 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4761 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4762 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4763 e = mesh->element3i + mesh->numtriangles * 3;
4764 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4766 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4767 if (mesh->numtriangles < mesh->maxtriangles)
4772 mesh->numtriangles++;
4774 element[1] = element[2];
4778 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4782 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4783 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4784 e = mesh->element3i + mesh->numtriangles * 3;
4785 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4787 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4788 if (mesh->numtriangles < mesh->maxtriangles)
4793 mesh->numtriangles++;
4795 element[1] = element[2];
4799 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4800 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4802 int planenum, planenum2;
4805 mplane_t *plane, *plane2;
4807 double temppoints[2][256*3];
4808 // figure out how large a bounding box we need to properly compute this brush
4810 for (w = 0;w < numplanes;w++)
4811 maxdist = max(maxdist, planes[w].dist);
4812 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4813 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4814 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4818 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4819 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4821 if (planenum2 == planenum)
4823 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);
4826 if (tempnumpoints < 3)
4828 // generate elements forming a triangle fan for this polygon
4829 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4833 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)
4835 texturelayer_t *layer;
4836 layer = t->currentlayers + t->currentnumlayers++;
4838 layer->depthmask = depthmask;
4839 layer->blendfunc1 = blendfunc1;
4840 layer->blendfunc2 = blendfunc2;
4841 layer->texture = texture;
4842 layer->texmatrix = *matrix;
4843 layer->color[0] = r * r_refdef.view.colorscale;
4844 layer->color[1] = g * r_refdef.view.colorscale;
4845 layer->color[2] = b * r_refdef.view.colorscale;
4846 layer->color[3] = a;
4849 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4852 index = parms[2] + r_refdef.scene.time * parms[3];
4853 index -= floor(index);
4857 case Q3WAVEFUNC_NONE:
4858 case Q3WAVEFUNC_NOISE:
4859 case Q3WAVEFUNC_COUNT:
4862 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4863 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4864 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4865 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4866 case Q3WAVEFUNC_TRIANGLE:
4868 f = index - floor(index);
4879 return (float)(parms[0] + parms[1] * f);
4882 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
4887 matrix4x4_t matrix, temp;
4888 switch(tcmod->tcmod)
4892 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4893 matrix = r_waterscrollmatrix;
4895 matrix = identitymatrix;
4897 case Q3TCMOD_ENTITYTRANSLATE:
4898 // this is used in Q3 to allow the gamecode to control texcoord
4899 // scrolling on the entity, which is not supported in darkplaces yet.
4900 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4902 case Q3TCMOD_ROTATE:
4903 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4904 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4905 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4908 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4910 case Q3TCMOD_SCROLL:
4911 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4913 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4914 w = (int) tcmod->parms[0];
4915 h = (int) tcmod->parms[1];
4916 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4918 idx = (int) floor(f * w * h);
4919 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4921 case Q3TCMOD_STRETCH:
4922 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4923 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4925 case Q3TCMOD_TRANSFORM:
4926 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4927 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4928 VectorSet(tcmat + 6, 0 , 0 , 1);
4929 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4930 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4932 case Q3TCMOD_TURBULENT:
4933 // this is handled in the RSurf_PrepareVertices function
4934 matrix = identitymatrix;
4938 Matrix4x4_Concat(texmatrix, &matrix, &temp);
4941 texture_t *R_GetCurrentTexture(texture_t *t)
4944 const entity_render_t *ent = rsurface.entity;
4945 dp_model_t *model = ent->model;
4946 q3shaderinfo_layer_tcmod_t *tcmod;
4948 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
4949 return t->currentframe;
4950 t->update_lastrenderframe = r_frame;
4951 t->update_lastrenderentity = (void *)ent;
4953 // switch to an alternate material if this is a q1bsp animated material
4955 texture_t *texture = t;
4956 int s = ent->skinnum;
4957 if ((unsigned int)s >= (unsigned int)model->numskins)
4959 if (model->skinscenes)
4961 if (model->skinscenes[s].framecount > 1)
4962 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4964 s = model->skinscenes[s].firstframe;
4967 t = t + s * model->num_surfaces;
4970 // use an alternate animation if the entity's frame is not 0,
4971 // and only if the texture has an alternate animation
4972 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
4973 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4975 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4977 texture->currentframe = t;
4980 // update currentskinframe to be a qw skin or animation frame
4981 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"))
4983 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4985 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4986 if (developer_loading.integer)
4987 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4988 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);
4990 t->currentskinframe = r_qwskincache_skinframe[i];
4991 if (t->currentskinframe == NULL)
4992 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4994 else if (t->numskinframes >= 2)
4995 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4996 if (t->backgroundnumskinframes >= 2)
4997 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
4999 t->currentmaterialflags = t->basematerialflags;
5000 t->currentalpha = ent->alpha;
5001 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5002 t->currentalpha *= r_wateralpha.value;
5003 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5004 t->currentalpha *= t->r_water_wateralpha;
5005 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5006 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5007 if (!(ent->flags & RENDER_LIGHT))
5008 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5009 else if (rsurface.modeltexcoordlightmap2f == NULL)
5011 // pick a model lighting mode
5012 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5013 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5015 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5017 if (ent->effects & EF_ADDITIVE)
5018 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5019 else if (t->currentalpha < 1)
5020 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5021 if (ent->effects & EF_DOUBLESIDED)
5022 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5023 if (ent->effects & EF_NODEPTHTEST)
5024 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5025 if (ent->flags & RENDER_VIEWMODEL)
5026 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5027 if (t->backgroundnumskinframes)
5028 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5029 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5031 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5032 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5035 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5037 // there is no tcmod
5038 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5040 t->currenttexmatrix = r_waterscrollmatrix;
5041 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5045 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5046 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5049 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5050 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5051 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5052 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5054 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5055 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5056 t->glosstexture = r_texture_black;
5057 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5058 t->backgroundglosstexture = r_texture_black;
5059 t->specularpower = r_shadow_glossexponent.value;
5060 // TODO: store reference values for these in the texture?
5061 t->specularscale = 0;
5062 if (r_shadow_gloss.integer > 0)
5064 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5066 if (r_shadow_glossintensity.value > 0)
5068 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5069 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5070 t->specularscale = r_shadow_glossintensity.value;
5073 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5075 t->glosstexture = r_texture_white;
5076 t->backgroundglosstexture = r_texture_white;
5077 t->specularscale = r_shadow_gloss2intensity.value;
5081 // lightmaps mode looks bad with dlights using actual texturing, so turn
5082 // off the colormap and glossmap, but leave the normalmap on as it still
5083 // accurately represents the shading involved
5084 if (gl_lightmaps.integer)
5086 t->basetexture = r_texture_grey128;
5087 t->backgroundbasetexture = NULL;
5088 t->specularscale = 0;
5089 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5092 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5093 VectorClear(t->dlightcolor);
5094 t->currentnumlayers = 0;
5095 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5098 int blendfunc1, blendfunc2;
5100 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5102 blendfunc1 = GL_SRC_ALPHA;
5103 blendfunc2 = GL_ONE;
5105 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5107 blendfunc1 = GL_SRC_ALPHA;
5108 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5110 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5112 blendfunc1 = t->customblendfunc[0];
5113 blendfunc2 = t->customblendfunc[1];
5117 blendfunc1 = GL_ONE;
5118 blendfunc2 = GL_ZERO;
5120 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5121 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5122 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5123 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5125 // fullbright is not affected by r_refdef.lightmapintensity
5126 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]);
5127 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5128 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]);
5129 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5130 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]);
5134 vec3_t ambientcolor;
5136 // set the color tint used for lights affecting this surface
5137 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5139 // q3bsp has no lightmap updates, so the lightstylevalue that
5140 // would normally be baked into the lightmap must be
5141 // applied to the color
5142 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5143 if (ent->model->type == mod_brushq3)
5144 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5145 colorscale *= r_refdef.lightmapintensity;
5146 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5147 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5148 // basic lit geometry
5149 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]);
5150 // add pants/shirt if needed
5151 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5152 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]);
5153 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5154 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]);
5155 // now add ambient passes if needed
5156 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5158 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]);
5159 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5160 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]);
5161 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5162 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]);
5165 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5166 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]);
5167 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5169 // if this is opaque use alpha blend which will darken the earlier
5172 // if this is an alpha blended material, all the earlier passes
5173 // were darkened by fog already, so we only need to add the fog
5174 // color ontop through the fog mask texture
5176 // if this is an additive blended material, all the earlier passes
5177 // were darkened by fog already, and we should not add fog color
5178 // (because the background was not darkened, there is no fog color
5179 // that was lost behind it).
5180 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]);
5184 return t->currentframe;
5187 rsurfacestate_t rsurface;
5189 void R_Mesh_ResizeArrays(int newvertices)
5192 if (rsurface.array_size >= newvertices)
5194 if (rsurface.array_modelvertex3f)
5195 Mem_Free(rsurface.array_modelvertex3f);
5196 rsurface.array_size = (newvertices + 1023) & ~1023;
5197 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5198 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5199 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5200 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5201 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5202 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5203 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5204 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5205 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5206 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5207 rsurface.array_color4f = base + rsurface.array_size * 27;
5208 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5211 void RSurf_ActiveWorldEntity(void)
5213 dp_model_t *model = r_refdef.scene.worldmodel;
5214 //if (rsurface.entity == r_refdef.scene.worldentity)
5216 rsurface.entity = r_refdef.scene.worldentity;
5217 if (rsurface.array_size < model->surfmesh.num_vertices)
5218 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5219 rsurface.matrix = identitymatrix;
5220 rsurface.inversematrix = identitymatrix;
5221 R_Mesh_Matrix(&identitymatrix);
5222 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5223 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5224 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5225 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5226 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5227 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5228 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5229 rsurface.frameblend[0].lerp = 1;
5230 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5231 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5232 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5233 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5234 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5235 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5236 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5237 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5238 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5239 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5240 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5241 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5242 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5243 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5244 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5245 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5246 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5247 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5248 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5249 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5250 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5251 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5252 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5253 rsurface.modelelement3i = model->surfmesh.data_element3i;
5254 rsurface.modelelement3s = model->surfmesh.data_element3s;
5255 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5256 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5257 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5258 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5259 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5260 rsurface.modelsurfaces = model->data_surfaces;
5261 rsurface.generatedvertex = false;
5262 rsurface.vertex3f = rsurface.modelvertex3f;
5263 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5264 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5265 rsurface.svector3f = rsurface.modelsvector3f;
5266 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5267 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5268 rsurface.tvector3f = rsurface.modeltvector3f;
5269 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5270 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5271 rsurface.normal3f = rsurface.modelnormal3f;
5272 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5273 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5274 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5277 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5279 dp_model_t *model = ent->model;
5280 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5282 rsurface.entity = (entity_render_t *)ent;
5283 if (rsurface.array_size < model->surfmesh.num_vertices)
5284 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5285 rsurface.matrix = ent->matrix;
5286 rsurface.inversematrix = ent->inversematrix;
5287 R_Mesh_Matrix(&rsurface.matrix);
5288 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5289 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5290 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5291 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5292 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5293 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5294 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5295 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5296 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5297 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5298 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5299 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5300 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5301 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5302 if (ent->model->brush.submodel)
5304 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5305 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5307 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5309 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5311 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5312 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5313 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5314 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5316 else if (wanttangents)
5318 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5319 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5320 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5321 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5322 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5324 else if (wantnormals)
5326 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5327 rsurface.modelsvector3f = NULL;
5328 rsurface.modeltvector3f = NULL;
5329 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5330 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5334 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5335 rsurface.modelsvector3f = NULL;
5336 rsurface.modeltvector3f = NULL;
5337 rsurface.modelnormal3f = NULL;
5338 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5340 rsurface.modelvertex3f_bufferobject = 0;
5341 rsurface.modelvertex3f_bufferoffset = 0;
5342 rsurface.modelsvector3f_bufferobject = 0;
5343 rsurface.modelsvector3f_bufferoffset = 0;
5344 rsurface.modeltvector3f_bufferobject = 0;
5345 rsurface.modeltvector3f_bufferoffset = 0;
5346 rsurface.modelnormal3f_bufferobject = 0;
5347 rsurface.modelnormal3f_bufferoffset = 0;
5348 rsurface.generatedvertex = true;
5352 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5353 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5354 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5355 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5356 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5357 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5358 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5359 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5360 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5361 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5362 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5363 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5364 rsurface.generatedvertex = false;
5366 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5367 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5368 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5369 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5370 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5371 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5372 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5373 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5374 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5375 rsurface.modelelement3i = model->surfmesh.data_element3i;
5376 rsurface.modelelement3s = model->surfmesh.data_element3s;
5377 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5378 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5379 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5380 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5381 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5382 rsurface.modelsurfaces = model->data_surfaces;
5383 rsurface.vertex3f = rsurface.modelvertex3f;
5384 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5385 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5386 rsurface.svector3f = rsurface.modelsvector3f;
5387 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5388 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5389 rsurface.tvector3f = rsurface.modeltvector3f;
5390 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5391 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5392 rsurface.normal3f = rsurface.modelnormal3f;
5393 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5394 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5395 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5398 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5399 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5402 int texturesurfaceindex;
5407 const float *v1, *in_tc;
5409 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5411 q3shaderinfo_deform_t *deform;
5412 // 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
5413 if (rsurface.generatedvertex)
5415 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5416 generatenormals = true;
5417 for (i = 0;i < Q3MAXDEFORMS;i++)
5419 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5421 generatetangents = true;
5422 generatenormals = true;
5424 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5425 generatenormals = true;
5427 if (generatenormals && !rsurface.modelnormal3f)
5429 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5430 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5431 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5432 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
5434 if (generatetangents && !rsurface.modelsvector3f)
5436 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5437 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5438 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5439 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5440 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5441 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5442 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 != 0);
5445 rsurface.vertex3f = rsurface.modelvertex3f;
5446 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5447 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5448 rsurface.svector3f = rsurface.modelsvector3f;
5449 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5450 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5451 rsurface.tvector3f = rsurface.modeltvector3f;
5452 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5453 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5454 rsurface.normal3f = rsurface.modelnormal3f;
5455 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5456 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5457 // if vertices are deformed (sprite flares and things in maps, possibly
5458 // water waves, bulges and other deformations), generate them into
5459 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5460 // (may be static model data or generated data for an animated model, or
5461 // the previous deform pass)
5462 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5464 switch (deform->deform)
5467 case Q3DEFORM_PROJECTIONSHADOW:
5468 case Q3DEFORM_TEXT0:
5469 case Q3DEFORM_TEXT1:
5470 case Q3DEFORM_TEXT2:
5471 case Q3DEFORM_TEXT3:
5472 case Q3DEFORM_TEXT4:
5473 case Q3DEFORM_TEXT5:
5474 case Q3DEFORM_TEXT6:
5475 case Q3DEFORM_TEXT7:
5478 case Q3DEFORM_AUTOSPRITE:
5479 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5480 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5481 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5482 VectorNormalize(newforward);
5483 VectorNormalize(newright);
5484 VectorNormalize(newup);
5485 // make deformed versions of only the model vertices used by the specified surfaces
5486 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5488 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5489 // a single autosprite surface can contain multiple sprites...
5490 for (j = 0;j < surface->num_vertices - 3;j += 4)
5492 VectorClear(center);
5493 for (i = 0;i < 4;i++)
5494 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5495 VectorScale(center, 0.25f, center);
5496 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5497 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5498 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5499 for (i = 0;i < 4;i++)
5501 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5502 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5505 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 != 0);
5506 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 != 0);
5508 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5509 rsurface.vertex3f_bufferobject = 0;
5510 rsurface.vertex3f_bufferoffset = 0;
5511 rsurface.svector3f = rsurface.array_deformedsvector3f;
5512 rsurface.svector3f_bufferobject = 0;
5513 rsurface.svector3f_bufferoffset = 0;
5514 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5515 rsurface.tvector3f_bufferobject = 0;
5516 rsurface.tvector3f_bufferoffset = 0;
5517 rsurface.normal3f = rsurface.array_deformednormal3f;
5518 rsurface.normal3f_bufferobject = 0;
5519 rsurface.normal3f_bufferoffset = 0;
5521 case Q3DEFORM_AUTOSPRITE2:
5522 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5523 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5524 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5525 VectorNormalize(newforward);
5526 VectorNormalize(newright);
5527 VectorNormalize(newup);
5528 // make deformed versions of only the model vertices used by the specified surfaces
5529 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5531 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5532 const float *v1, *v2;
5542 memset(shortest, 0, sizeof(shortest));
5543 // a single autosprite surface can contain multiple sprites...
5544 for (j = 0;j < surface->num_vertices - 3;j += 4)
5546 VectorClear(center);
5547 for (i = 0;i < 4;i++)
5548 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5549 VectorScale(center, 0.25f, center);
5550 // find the two shortest edges, then use them to define the
5551 // axis vectors for rotating around the central axis
5552 for (i = 0;i < 6;i++)
5554 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5555 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5557 Debug_PolygonBegin(NULL, 0);
5558 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5559 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);
5560 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5563 l = VectorDistance2(v1, v2);
5564 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5566 l += (1.0f / 1024.0f);
5567 if (shortest[0].length2 > l || i == 0)
5569 shortest[1] = shortest[0];
5570 shortest[0].length2 = l;
5571 shortest[0].v1 = v1;
5572 shortest[0].v2 = v2;
5574 else if (shortest[1].length2 > l || i == 1)
5576 shortest[1].length2 = l;
5577 shortest[1].v1 = v1;
5578 shortest[1].v2 = v2;
5581 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5582 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5584 Debug_PolygonBegin(NULL, 0);
5585 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5586 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);
5587 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5590 // this calculates the right vector from the shortest edge
5591 // and the up vector from the edge midpoints
5592 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5593 VectorNormalize(right);
5594 VectorSubtract(end, start, up);
5595 VectorNormalize(up);
5596 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5597 VectorSubtract(rsurface.modelorg, center, forward);
5598 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5599 VectorNegate(forward, forward);
5600 VectorReflect(forward, 0, up, forward);
5601 VectorNormalize(forward);
5602 CrossProduct(up, forward, newright);
5603 VectorNormalize(newright);
5605 Debug_PolygonBegin(NULL, 0);
5606 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);
5607 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5608 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5612 Debug_PolygonBegin(NULL, 0);
5613 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5614 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5615 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5618 // rotate the quad around the up axis vector, this is made
5619 // especially easy by the fact we know the quad is flat,
5620 // so we only have to subtract the center position and
5621 // measure distance along the right vector, and then
5622 // multiply that by the newright vector and add back the
5624 // we also need to subtract the old position to undo the
5625 // displacement from the center, which we do with a
5626 // DotProduct, the subtraction/addition of center is also
5627 // optimized into DotProducts here
5628 l = DotProduct(right, center);
5629 for (i = 0;i < 4;i++)
5631 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5632 f = DotProduct(right, v1) - l;
5633 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5636 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 != 0);
5637 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 != 0);
5639 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5640 rsurface.vertex3f_bufferobject = 0;
5641 rsurface.vertex3f_bufferoffset = 0;
5642 rsurface.svector3f = rsurface.array_deformedsvector3f;
5643 rsurface.svector3f_bufferobject = 0;
5644 rsurface.svector3f_bufferoffset = 0;
5645 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5646 rsurface.tvector3f_bufferobject = 0;
5647 rsurface.tvector3f_bufferoffset = 0;
5648 rsurface.normal3f = rsurface.array_deformednormal3f;
5649 rsurface.normal3f_bufferobject = 0;
5650 rsurface.normal3f_bufferoffset = 0;
5652 case Q3DEFORM_NORMAL:
5653 // deform the normals to make reflections wavey
5654 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5656 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5657 for (j = 0;j < surface->num_vertices;j++)
5660 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5661 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5662 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5663 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5664 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5665 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5666 VectorNormalize(normal);
5668 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 != 0);
5670 rsurface.svector3f = rsurface.array_deformedsvector3f;
5671 rsurface.svector3f_bufferobject = 0;
5672 rsurface.svector3f_bufferoffset = 0;
5673 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5674 rsurface.tvector3f_bufferobject = 0;
5675 rsurface.tvector3f_bufferoffset = 0;
5676 rsurface.normal3f = rsurface.array_deformednormal3f;
5677 rsurface.normal3f_bufferobject = 0;
5678 rsurface.normal3f_bufferoffset = 0;
5681 // deform vertex array to make wavey water and flags and such
5682 waveparms[0] = deform->waveparms[0];
5683 waveparms[1] = deform->waveparms[1];
5684 waveparms[2] = deform->waveparms[2];
5685 waveparms[3] = deform->waveparms[3];
5686 // this is how a divisor of vertex influence on deformation
5687 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5688 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5689 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5691 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5692 for (j = 0;j < surface->num_vertices;j++)
5694 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5695 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5696 // if the wavefunc depends on time, evaluate it per-vertex
5699 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5700 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5702 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5705 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5706 rsurface.vertex3f_bufferobject = 0;
5707 rsurface.vertex3f_bufferoffset = 0;
5709 case Q3DEFORM_BULGE:
5710 // deform vertex array to make the surface have moving bulges
5711 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5713 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5714 for (j = 0;j < surface->num_vertices;j++)
5716 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5717 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5720 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5721 rsurface.vertex3f_bufferobject = 0;
5722 rsurface.vertex3f_bufferoffset = 0;
5725 // deform vertex array
5726 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5727 VectorScale(deform->parms, scale, waveparms);
5728 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5730 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5731 for (j = 0;j < surface->num_vertices;j++)
5732 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5734 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5735 rsurface.vertex3f_bufferobject = 0;
5736 rsurface.vertex3f_bufferoffset = 0;
5740 // generate texcoords based on the chosen texcoord source
5741 switch(rsurface.texture->tcgen.tcgen)
5744 case Q3TCGEN_TEXTURE:
5745 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5746 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5747 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5749 case Q3TCGEN_LIGHTMAP:
5750 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5751 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5752 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5754 case Q3TCGEN_VECTOR:
5755 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5757 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5758 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)
5760 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5761 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5764 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5765 rsurface.texcoordtexture2f_bufferobject = 0;
5766 rsurface.texcoordtexture2f_bufferoffset = 0;
5768 case Q3TCGEN_ENVIRONMENT:
5769 // make environment reflections using a spheremap
5770 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5772 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5773 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5774 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5775 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5776 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5778 // identical to Q3A's method, but executed in worldspace so
5779 // carried models can be shiny too
5781 float viewer[3], d, reflected[3], worldreflected[3];
5783 VectorSubtract(rsurface.modelorg, vertex, viewer);
5784 // VectorNormalize(viewer);
5786 d = DotProduct(normal, viewer);
5788 reflected[0] = normal[0]*2*d - viewer[0];
5789 reflected[1] = normal[1]*2*d - viewer[1];
5790 reflected[2] = normal[2]*2*d - viewer[2];
5791 // note: this is proportinal to viewer, so we can normalize later
5793 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
5794 VectorNormalize(worldreflected);
5796 // note: this sphere map only uses world x and z!
5797 // so positive and negative y will LOOK THE SAME.
5798 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
5799 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
5802 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5803 rsurface.texcoordtexture2f_bufferobject = 0;
5804 rsurface.texcoordtexture2f_bufferoffset = 0;
5807 // the only tcmod that needs software vertex processing is turbulent, so
5808 // check for it here and apply the changes if needed
5809 // and we only support that as the first one
5810 // (handling a mixture of turbulent and other tcmods would be problematic
5811 // without punting it entirely to a software path)
5812 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5814 amplitude = rsurface.texture->tcmods[0].parms[1];
5815 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5816 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5818 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5819 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)
5821 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5822 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5825 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5826 rsurface.texcoordtexture2f_bufferobject = 0;
5827 rsurface.texcoordtexture2f_bufferoffset = 0;
5829 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5830 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5831 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5832 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5835 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5838 const msurface_t *surface = texturesurfacelist[0];
5839 const msurface_t *surface2;
5844 // TODO: lock all array ranges before render, rather than on each surface
5845 if (texturenumsurfaces == 1)
5847 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5848 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5850 else if (r_batchmode.integer == 2)
5852 #define MAXBATCHTRIANGLES 4096
5853 int batchtriangles = 0;
5854 int batchelements[MAXBATCHTRIANGLES*3];
5855 for (i = 0;i < texturenumsurfaces;i = j)
5857 surface = texturesurfacelist[i];
5859 if (surface->num_triangles > MAXBATCHTRIANGLES)
5861 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);
5864 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5865 batchtriangles = surface->num_triangles;
5866 firstvertex = surface->num_firstvertex;
5867 endvertex = surface->num_firstvertex + surface->num_vertices;
5868 for (;j < texturenumsurfaces;j++)
5870 surface2 = texturesurfacelist[j];
5871 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5873 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5874 batchtriangles += surface2->num_triangles;
5875 firstvertex = min(firstvertex, surface2->num_firstvertex);
5876 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5878 surface2 = texturesurfacelist[j-1];
5879 numvertices = endvertex - firstvertex;
5880 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5883 else if (r_batchmode.integer == 1)
5885 for (i = 0;i < texturenumsurfaces;i = j)
5887 surface = texturesurfacelist[i];
5888 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5889 if (texturesurfacelist[j] != surface2)
5891 surface2 = texturesurfacelist[j-1];
5892 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5893 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5894 GL_LockArrays(surface->num_firstvertex, numvertices);
5895 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5900 for (i = 0;i < texturenumsurfaces;i++)
5902 surface = texturesurfacelist[i];
5903 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5904 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);
5909 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5911 int i, planeindex, vertexindex;
5915 r_waterstate_waterplane_t *p, *bestp;
5916 msurface_t *surface;
5917 if (r_waterstate.renderingscene)
5919 for (i = 0;i < texturenumsurfaces;i++)
5921 surface = texturesurfacelist[i];
5922 if (lightmaptexunit >= 0)
5923 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5924 if (deluxemaptexunit >= 0)
5925 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5926 // pick the closest matching water plane
5929 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5932 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5934 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5935 d += fabs(PlaneDiff(vert, &p->plane));
5937 if (bestd > d || !bestp)
5945 if (refractiontexunit >= 0)
5946 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5947 if (reflectiontexunit >= 0)
5948 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5952 if (refractiontexunit >= 0)
5953 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5954 if (reflectiontexunit >= 0)
5955 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5957 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5958 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);
5962 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5966 const msurface_t *surface = texturesurfacelist[0];
5967 const msurface_t *surface2;
5972 // TODO: lock all array ranges before render, rather than on each surface
5973 if (texturenumsurfaces == 1)
5975 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5976 if (deluxemaptexunit >= 0)
5977 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5978 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5979 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);
5981 else if (r_batchmode.integer == 2)
5983 #define MAXBATCHTRIANGLES 4096
5984 int batchtriangles = 0;
5985 int batchelements[MAXBATCHTRIANGLES*3];
5986 for (i = 0;i < texturenumsurfaces;i = j)
5988 surface = texturesurfacelist[i];
5989 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5990 if (deluxemaptexunit >= 0)
5991 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5993 if (surface->num_triangles > MAXBATCHTRIANGLES)
5995 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);
5998 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5999 batchtriangles = surface->num_triangles;
6000 firstvertex = surface->num_firstvertex;
6001 endvertex = surface->num_firstvertex + surface->num_vertices;
6002 for (;j < texturenumsurfaces;j++)
6004 surface2 = texturesurfacelist[j];
6005 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6007 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6008 batchtriangles += surface2->num_triangles;
6009 firstvertex = min(firstvertex, surface2->num_firstvertex);
6010 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6012 surface2 = texturesurfacelist[j-1];
6013 numvertices = endvertex - firstvertex;
6014 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6017 else if (r_batchmode.integer == 1)
6020 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6021 for (i = 0;i < texturenumsurfaces;i = j)
6023 surface = texturesurfacelist[i];
6024 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6025 if (texturesurfacelist[j] != surface2)
6027 Con_Printf(" %i", j - i);
6030 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6032 for (i = 0;i < texturenumsurfaces;i = j)
6034 surface = texturesurfacelist[i];
6035 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6036 if (deluxemaptexunit >= 0)
6037 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6038 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6039 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6042 Con_Printf(" %i", j - i);
6044 surface2 = texturesurfacelist[j-1];
6045 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6046 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6047 GL_LockArrays(surface->num_firstvertex, numvertices);
6048 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6056 for (i = 0;i < texturenumsurfaces;i++)
6058 surface = texturesurfacelist[i];
6059 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6060 if (deluxemaptexunit >= 0)
6061 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6062 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6063 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);
6068 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6071 int texturesurfaceindex;
6072 if (r_showsurfaces.integer == 2)
6074 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6076 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6077 for (j = 0;j < surface->num_triangles;j++)
6079 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6080 GL_Color(f, f, f, 1);
6081 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6087 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6089 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6090 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6091 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);
6092 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6093 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);
6098 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6100 int texturesurfaceindex;
6103 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6105 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6106 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)
6114 rsurface.lightmapcolor4f = rsurface.array_color4f;
6115 rsurface.lightmapcolor4f_bufferobject = 0;
6116 rsurface.lightmapcolor4f_bufferoffset = 0;
6119 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6121 int texturesurfaceindex;
6125 if (rsurface.lightmapcolor4f)
6127 // generate color arrays for the surfaces in this list
6128 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6130 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6131 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)
6133 f = FogPoint_Model(v);
6143 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6145 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6146 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
6148 f = FogPoint_Model(v);
6156 rsurface.lightmapcolor4f = rsurface.array_color4f;
6157 rsurface.lightmapcolor4f_bufferobject = 0;
6158 rsurface.lightmapcolor4f_bufferoffset = 0;
6161 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6163 int texturesurfaceindex;
6167 if (!rsurface.lightmapcolor4f)
6169 // generate color arrays for the surfaces in this list
6170 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6172 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6173 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)
6175 f = FogPoint_Model(v);
6176 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6177 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6178 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6182 rsurface.lightmapcolor4f = rsurface.array_color4f;
6183 rsurface.lightmapcolor4f_bufferobject = 0;
6184 rsurface.lightmapcolor4f_bufferoffset = 0;
6187 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6189 int texturesurfaceindex;
6192 if (!rsurface.lightmapcolor4f)
6194 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6196 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6197 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)
6205 rsurface.lightmapcolor4f = rsurface.array_color4f;
6206 rsurface.lightmapcolor4f_bufferobject = 0;
6207 rsurface.lightmapcolor4f_bufferoffset = 0;
6210 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6212 int texturesurfaceindex;
6215 if (!rsurface.lightmapcolor4f)
6217 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6219 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6220 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)
6222 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6223 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6224 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6228 rsurface.lightmapcolor4f = rsurface.array_color4f;
6229 rsurface.lightmapcolor4f_bufferobject = 0;
6230 rsurface.lightmapcolor4f_bufferoffset = 0;
6233 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6236 rsurface.lightmapcolor4f = NULL;
6237 rsurface.lightmapcolor4f_bufferobject = 0;
6238 rsurface.lightmapcolor4f_bufferoffset = 0;
6239 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6240 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6241 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6242 GL_Color(r, g, b, a);
6243 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6246 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6248 // TODO: optimize applyfog && applycolor case
6249 // just apply fog if necessary, and tint the fog color array if necessary
6250 rsurface.lightmapcolor4f = NULL;
6251 rsurface.lightmapcolor4f_bufferobject = 0;
6252 rsurface.lightmapcolor4f_bufferoffset = 0;
6253 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6254 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6255 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6256 GL_Color(r, g, b, a);
6257 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6260 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6262 int texturesurfaceindex;
6266 if (texturesurfacelist[0]->lightmapinfo)
6268 // generate color arrays for the surfaces in this list
6269 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6271 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6272 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6274 if (surface->lightmapinfo->samples)
6276 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6277 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6278 VectorScale(lm, scale, c);
6279 if (surface->lightmapinfo->styles[1] != 255)
6281 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6283 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6284 VectorMA(c, scale, lm, c);
6285 if (surface->lightmapinfo->styles[2] != 255)
6288 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6289 VectorMA(c, scale, lm, c);
6290 if (surface->lightmapinfo->styles[3] != 255)
6293 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6294 VectorMA(c, scale, lm, c);
6304 rsurface.lightmapcolor4f = rsurface.array_color4f;
6305 rsurface.lightmapcolor4f_bufferobject = 0;
6306 rsurface.lightmapcolor4f_bufferoffset = 0;
6310 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6311 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6312 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6314 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6315 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6316 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6317 GL_Color(r, g, b, a);
6318 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6321 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6323 int texturesurfaceindex;
6326 float *v, *c, *c2, alpha;
6327 vec3_t ambientcolor;
6328 vec3_t diffusecolor;
6332 VectorCopy(rsurface.modellight_lightdir, lightdir);
6333 f = 0.5f * r_refdef.lightmapintensity;
6334 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6335 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6336 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6337 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6338 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6339 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6341 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6343 // generate color arrays for the surfaces in this list
6344 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6346 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6347 int numverts = surface->num_vertices;
6348 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6349 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6350 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6351 // q3-style directional shading
6352 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6354 if ((f = DotProduct(c2, lightdir)) > 0)
6355 VectorMA(ambientcolor, f, diffusecolor, c);
6357 VectorCopy(ambientcolor, c);
6365 rsurface.lightmapcolor4f = rsurface.array_color4f;
6366 rsurface.lightmapcolor4f_bufferobject = 0;
6367 rsurface.lightmapcolor4f_bufferoffset = 0;
6368 *applycolor = false;
6372 *r = ambientcolor[0];
6373 *g = ambientcolor[1];
6374 *b = ambientcolor[2];
6375 rsurface.lightmapcolor4f = NULL;
6376 rsurface.lightmapcolor4f_bufferobject = 0;
6377 rsurface.lightmapcolor4f_bufferoffset = 0;
6381 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6383 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6384 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6385 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6386 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6387 GL_Color(r, g, b, a);
6388 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6391 void RSurf_SetupDepthAndCulling(void)
6393 // submodels are biased to avoid z-fighting with world surfaces that they
6394 // may be exactly overlapping (avoids z-fighting artifacts on certain
6395 // doors and things in Quake maps)
6396 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6397 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6398 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6399 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6402 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6404 // transparent sky would be ridiculous
6405 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6407 R_SetupGenericShader(false);
6410 skyrendernow = false;
6411 // we have to force off the water clipping plane while rendering sky
6415 // restore entity matrix
6416 R_Mesh_Matrix(&rsurface.matrix);
6418 RSurf_SetupDepthAndCulling();
6420 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6421 // skymasking on them, and Quake3 never did sky masking (unlike
6422 // software Quake and software Quake2), so disable the sky masking
6423 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6424 // and skymasking also looks very bad when noclipping outside the
6425 // level, so don't use it then either.
6426 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6428 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6429 R_Mesh_ColorPointer(NULL, 0, 0);
6430 R_Mesh_ResetTextureState();
6431 if (skyrendermasked)
6433 R_SetupDepthOrShadowShader();
6434 // depth-only (masking)
6435 GL_ColorMask(0,0,0,0);
6436 // just to make sure that braindead drivers don't draw
6437 // anything despite that colormask...
6438 GL_BlendFunc(GL_ZERO, GL_ONE);
6442 R_SetupGenericShader(false);
6444 GL_BlendFunc(GL_ONE, GL_ZERO);
6446 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6447 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6448 if (skyrendermasked)
6449 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6451 R_Mesh_ResetTextureState();
6452 GL_Color(1, 1, 1, 1);
6455 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6457 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6460 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6461 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6462 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6463 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6464 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6465 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6466 if (rsurface.texture->backgroundcurrentskinframe)
6468 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6469 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6470 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6471 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6473 if(rsurface.texture->colormapping)
6475 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6476 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6478 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6479 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6480 R_Mesh_ColorPointer(NULL, 0, 0);
6482 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6484 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6486 // render background
6487 GL_BlendFunc(GL_ONE, GL_ZERO);
6489 GL_AlphaTest(false);
6491 GL_Color(1, 1, 1, 1);
6492 R_Mesh_ColorPointer(NULL, 0, 0);
6494 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6495 if (r_glsl_permutation)
6497 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6498 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6499 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6500 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6501 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6502 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6503 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);
6505 GL_LockArrays(0, 0);
6507 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6508 GL_DepthMask(false);
6509 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6510 R_Mesh_ColorPointer(NULL, 0, 0);
6512 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6513 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6514 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6517 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6518 if (!r_glsl_permutation)
6521 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6522 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6523 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6524 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6525 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6526 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6528 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6530 GL_BlendFunc(GL_ONE, GL_ZERO);
6532 GL_AlphaTest(false);
6536 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6537 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6538 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6541 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6543 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6544 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);
6546 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6550 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6551 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);
6553 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6555 GL_LockArrays(0, 0);
6558 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6560 // OpenGL 1.3 path - anything not completely ancient
6561 int texturesurfaceindex;
6562 qboolean applycolor;
6566 const texturelayer_t *layer;
6567 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6569 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6572 int layertexrgbscale;
6573 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6575 if (layerindex == 0)
6579 GL_AlphaTest(false);
6580 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6583 GL_DepthMask(layer->depthmask && writedepth);
6584 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6585 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6587 layertexrgbscale = 4;
6588 VectorScale(layer->color, 0.25f, layercolor);
6590 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6592 layertexrgbscale = 2;
6593 VectorScale(layer->color, 0.5f, layercolor);
6597 layertexrgbscale = 1;
6598 VectorScale(layer->color, 1.0f, layercolor);
6600 layercolor[3] = layer->color[3];
6601 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6602 R_Mesh_ColorPointer(NULL, 0, 0);
6603 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6604 switch (layer->type)
6606 case TEXTURELAYERTYPE_LITTEXTURE:
6607 memset(&m, 0, sizeof(m));
6608 m.tex[0] = R_GetTexture(r_texture_white);
6609 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6610 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6611 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6612 m.tex[1] = R_GetTexture(layer->texture);
6613 m.texmatrix[1] = layer->texmatrix;
6614 m.texrgbscale[1] = layertexrgbscale;
6615 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6616 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6617 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6618 R_Mesh_TextureState(&m);
6619 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6620 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6621 else if (rsurface.uselightmaptexture)
6622 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6624 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6626 case TEXTURELAYERTYPE_TEXTURE:
6627 memset(&m, 0, sizeof(m));
6628 m.tex[0] = R_GetTexture(layer->texture);
6629 m.texmatrix[0] = layer->texmatrix;
6630 m.texrgbscale[0] = layertexrgbscale;
6631 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6632 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6633 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6634 R_Mesh_TextureState(&m);
6635 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6637 case TEXTURELAYERTYPE_FOG:
6638 memset(&m, 0, sizeof(m));
6639 m.texrgbscale[0] = layertexrgbscale;
6642 m.tex[0] = R_GetTexture(layer->texture);
6643 m.texmatrix[0] = layer->texmatrix;
6644 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6645 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6646 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6648 R_Mesh_TextureState(&m);
6649 // generate a color array for the fog pass
6650 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6651 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6655 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6656 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)
6658 f = 1 - FogPoint_Model(v);
6659 c[0] = layercolor[0];
6660 c[1] = layercolor[1];
6661 c[2] = layercolor[2];
6662 c[3] = f * layercolor[3];
6665 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6668 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6670 GL_LockArrays(0, 0);
6673 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6675 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6676 GL_AlphaTest(false);
6680 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6682 // OpenGL 1.1 - crusty old voodoo path
6683 int texturesurfaceindex;
6687 const texturelayer_t *layer;
6688 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6690 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6692 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6694 if (layerindex == 0)
6698 GL_AlphaTest(false);
6699 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6702 GL_DepthMask(layer->depthmask && writedepth);
6703 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6704 R_Mesh_ColorPointer(NULL, 0, 0);
6705 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6706 switch (layer->type)
6708 case TEXTURELAYERTYPE_LITTEXTURE:
6709 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6711 // two-pass lit texture with 2x rgbscale
6712 // first the lightmap pass
6713 memset(&m, 0, sizeof(m));
6714 m.tex[0] = R_GetTexture(r_texture_white);
6715 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6716 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6717 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6718 R_Mesh_TextureState(&m);
6719 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6720 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6721 else if (rsurface.uselightmaptexture)
6722 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6724 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6725 GL_LockArrays(0, 0);
6726 // then apply the texture to it
6727 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6728 memset(&m, 0, sizeof(m));
6729 m.tex[0] = R_GetTexture(layer->texture);
6730 m.texmatrix[0] = layer->texmatrix;
6731 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6732 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6733 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6734 R_Mesh_TextureState(&m);
6735 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 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);
6739 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6740 memset(&m, 0, sizeof(m));
6741 m.tex[0] = R_GetTexture(layer->texture);
6742 m.texmatrix[0] = layer->texmatrix;
6743 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6744 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6745 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6746 R_Mesh_TextureState(&m);
6747 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6748 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);
6750 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);
6753 case TEXTURELAYERTYPE_TEXTURE:
6754 // singletexture unlit texture with transparency support
6755 memset(&m, 0, sizeof(m));
6756 m.tex[0] = R_GetTexture(layer->texture);
6757 m.texmatrix[0] = layer->texmatrix;
6758 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6759 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6760 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6761 R_Mesh_TextureState(&m);
6762 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);
6764 case TEXTURELAYERTYPE_FOG:
6765 // singletexture fogging
6766 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6769 memset(&m, 0, sizeof(m));
6770 m.tex[0] = R_GetTexture(layer->texture);
6771 m.texmatrix[0] = layer->texmatrix;
6772 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6773 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6774 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6775 R_Mesh_TextureState(&m);
6778 R_Mesh_ResetTextureState();
6779 // generate a color array for the fog pass
6780 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6784 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6785 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)
6787 f = 1 - FogPoint_Model(v);
6788 c[0] = layer->color[0];
6789 c[1] = layer->color[1];
6790 c[2] = layer->color[2];
6791 c[3] = f * layer->color[3];
6794 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6797 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6799 GL_LockArrays(0, 0);
6802 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6804 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6805 GL_AlphaTest(false);
6809 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6813 GL_AlphaTest(false);
6814 R_Mesh_ColorPointer(NULL, 0, 0);
6815 R_Mesh_ResetTextureState();
6816 R_SetupGenericShader(false);
6818 if(rsurface.texture && rsurface.texture->currentskinframe)
6820 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6821 c[3] *= rsurface.texture->currentalpha;
6831 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6833 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
6834 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
6835 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
6838 // brighten it up (as texture value 127 means "unlit")
6839 c[0] *= 2 * r_refdef.view.colorscale;
6840 c[1] *= 2 * r_refdef.view.colorscale;
6841 c[2] *= 2 * r_refdef.view.colorscale;
6843 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6844 c[3] *= r_wateralpha.value;
6846 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6848 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6849 GL_DepthMask(false);
6851 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6853 GL_BlendFunc(GL_ONE, GL_ONE);
6854 GL_DepthMask(false);
6856 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6858 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6859 GL_DepthMask(false);
6861 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6863 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6864 GL_DepthMask(false);
6868 GL_BlendFunc(GL_ONE, GL_ZERO);
6869 GL_DepthMask(writedepth);
6872 rsurface.lightmapcolor4f = NULL;
6874 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6876 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6878 rsurface.lightmapcolor4f = NULL;
6879 rsurface.lightmapcolor4f_bufferobject = 0;
6880 rsurface.lightmapcolor4f_bufferoffset = 0;
6882 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6884 qboolean applycolor = true;
6887 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6889 r_refdef.lightmapintensity = 1;
6890 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6891 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6895 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6897 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6898 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6899 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6902 if(!rsurface.lightmapcolor4f)
6903 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6905 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6906 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6907 if(r_refdef.fogenabled)
6908 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6910 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6911 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6914 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6917 RSurf_SetupDepthAndCulling();
6918 if (r_showsurfaces.integer == 3)
6919 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6920 else if (r_glsl.integer && gl_support_fragment_shader)
6921 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6922 else if (gl_combine.integer && r_textureunits.integer >= 2)
6923 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6925 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6929 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6932 RSurf_SetupDepthAndCulling();
6933 if (r_showsurfaces.integer == 3)
6934 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6935 else if (r_glsl.integer && gl_support_fragment_shader)
6936 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6937 else if (gl_combine.integer && r_textureunits.integer >= 2)
6938 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6940 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6944 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6947 int texturenumsurfaces, endsurface;
6949 msurface_t *surface;
6950 msurface_t *texturesurfacelist[1024];
6952 // if the model is static it doesn't matter what value we give for
6953 // wantnormals and wanttangents, so this logic uses only rules applicable
6954 // to a model, knowing that they are meaningless otherwise
6955 if (ent == r_refdef.scene.worldentity)
6956 RSurf_ActiveWorldEntity();
6957 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6958 RSurf_ActiveModelEntity(ent, false, false);
6960 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6962 for (i = 0;i < numsurfaces;i = j)
6965 surface = rsurface.modelsurfaces + surfacelist[i];
6966 texture = surface->texture;
6967 rsurface.texture = R_GetCurrentTexture(texture);
6968 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6969 // scan ahead until we find a different texture
6970 endsurface = min(i + 1024, numsurfaces);
6971 texturenumsurfaces = 0;
6972 texturesurfacelist[texturenumsurfaces++] = surface;
6973 for (;j < endsurface;j++)
6975 surface = rsurface.modelsurfaces + surfacelist[j];
6976 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6978 texturesurfacelist[texturenumsurfaces++] = surface;
6980 // render the range of surfaces
6981 if (ent == r_refdef.scene.worldentity)
6982 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6984 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6986 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6987 GL_AlphaTest(false);
6990 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6992 const entity_render_t *queueentity = r_refdef.scene.worldentity;
6996 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6998 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7000 RSurf_SetupDepthAndCulling();
7001 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7002 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7004 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7006 RSurf_SetupDepthAndCulling();
7007 GL_AlphaTest(false);
7008 R_Mesh_ColorPointer(NULL, 0, 0);
7009 R_Mesh_ResetTextureState();
7010 R_SetupGenericShader(false);
7011 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7013 GL_BlendFunc(GL_ONE, GL_ZERO);
7014 GL_Color(0, 0, 0, 1);
7015 GL_DepthTest(writedepth);
7016 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7018 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7020 RSurf_SetupDepthAndCulling();
7021 GL_AlphaTest(false);
7022 R_Mesh_ColorPointer(NULL, 0, 0);
7023 R_Mesh_ResetTextureState();
7024 R_SetupGenericShader(false);
7025 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7027 GL_BlendFunc(GL_ONE, GL_ZERO);
7029 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7031 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7032 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7033 else if (!rsurface.texture->currentnumlayers)
7035 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7037 // transparent surfaces get pushed off into the transparent queue
7038 int surfacelistindex;
7039 const msurface_t *surface;
7040 vec3_t tempcenter, center;
7041 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7043 surface = texturesurfacelist[surfacelistindex];
7044 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7045 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7046 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7047 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7048 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7053 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7054 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7059 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7063 // break the surface list down into batches by texture and use of lightmapping
7064 for (i = 0;i < numsurfaces;i = j)
7067 // texture is the base texture pointer, rsurface.texture is the
7068 // current frame/skin the texture is directing us to use (for example
7069 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7070 // use skin 1 instead)
7071 texture = surfacelist[i]->texture;
7072 rsurface.texture = R_GetCurrentTexture(texture);
7073 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7074 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7076 // if this texture is not the kind we want, skip ahead to the next one
7077 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7081 // simply scan ahead until we find a different texture or lightmap state
7082 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7084 // render the range of surfaces
7085 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7089 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7094 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7096 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7098 RSurf_SetupDepthAndCulling();
7099 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7100 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7102 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7104 RSurf_SetupDepthAndCulling();
7105 GL_AlphaTest(false);
7106 R_Mesh_ColorPointer(NULL, 0, 0);
7107 R_Mesh_ResetTextureState();
7108 R_SetupGenericShader(false);
7109 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7111 GL_BlendFunc(GL_ONE, GL_ZERO);
7112 GL_Color(0, 0, 0, 1);
7113 GL_DepthTest(writedepth);
7114 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7116 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7118 RSurf_SetupDepthAndCulling();
7119 GL_AlphaTest(false);
7120 R_Mesh_ColorPointer(NULL, 0, 0);
7121 R_Mesh_ResetTextureState();
7122 R_SetupGenericShader(false);
7123 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7125 GL_BlendFunc(GL_ONE, GL_ZERO);
7127 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7129 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7130 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7131 else if (!rsurface.texture->currentnumlayers)
7133 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7135 // transparent surfaces get pushed off into the transparent queue
7136 int surfacelistindex;
7137 const msurface_t *surface;
7138 vec3_t tempcenter, center;
7139 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7141 surface = texturesurfacelist[surfacelistindex];
7142 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7143 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7144 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7145 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7146 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7151 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7152 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7157 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7161 // break the surface list down into batches by texture and use of lightmapping
7162 for (i = 0;i < numsurfaces;i = j)
7165 // texture is the base texture pointer, rsurface.texture is the
7166 // current frame/skin the texture is directing us to use (for example
7167 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7168 // use skin 1 instead)
7169 texture = surfacelist[i]->texture;
7170 rsurface.texture = R_GetCurrentTexture(texture);
7171 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7172 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7174 // if this texture is not the kind we want, skip ahead to the next one
7175 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7179 // simply scan ahead until we find a different texture or lightmap state
7180 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7182 // render the range of surfaces
7183 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7187 float locboxvertex3f[6*4*3] =
7189 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7190 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7191 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7192 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7193 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7194 1,0,0, 0,0,0, 0,1,0, 1,1,0
7197 unsigned short locboxelements[6*2*3] =
7207 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7210 cl_locnode_t *loc = (cl_locnode_t *)ent;
7212 float vertex3f[6*4*3];
7214 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7215 GL_DepthMask(false);
7216 GL_DepthRange(0, 1);
7217 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7219 GL_CullFace(GL_NONE);
7220 R_Mesh_Matrix(&identitymatrix);
7222 R_Mesh_VertexPointer(vertex3f, 0, 0);
7223 R_Mesh_ColorPointer(NULL, 0, 0);
7224 R_Mesh_ResetTextureState();
7225 R_SetupGenericShader(false);
7228 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7229 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7230 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7231 surfacelist[0] < 0 ? 0.5f : 0.125f);
7233 if (VectorCompare(loc->mins, loc->maxs))
7235 VectorSet(size, 2, 2, 2);
7236 VectorMA(loc->mins, -0.5f, size, mins);
7240 VectorCopy(loc->mins, mins);
7241 VectorSubtract(loc->maxs, loc->mins, size);
7244 for (i = 0;i < 6*4*3;)
7245 for (j = 0;j < 3;j++, i++)
7246 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7248 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7251 void R_DrawLocs(void)
7254 cl_locnode_t *loc, *nearestloc;
7256 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7257 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7259 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7260 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7264 void R_DrawDebugModel(entity_render_t *ent)
7266 int i, j, k, l, flagsmask;
7267 const int *elements;
7269 msurface_t *surface;
7270 dp_model_t *model = ent->model;
7273 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7275 R_Mesh_ColorPointer(NULL, 0, 0);
7276 R_Mesh_ResetTextureState();
7277 R_SetupGenericShader(false);
7278 GL_DepthRange(0, 1);
7279 GL_DepthTest(!r_showdisabledepthtest.integer);
7280 GL_DepthMask(false);
7281 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7283 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7285 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7286 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7288 if (brush->colbrushf && brush->colbrushf->numtriangles)
7290 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7291 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
7292 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7295 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7297 if (surface->num_collisiontriangles)
7299 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7300 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);
7301 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7306 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7308 if (r_showtris.integer || r_shownormals.integer)
7310 if (r_showdisabledepthtest.integer)
7312 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7313 GL_DepthMask(false);
7317 GL_BlendFunc(GL_ONE, GL_ZERO);
7320 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7322 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7324 rsurface.texture = R_GetCurrentTexture(surface->texture);
7325 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7327 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7328 if (r_showtris.value > 0)
7330 if (!rsurface.texture->currentlayers->depthmask)
7331 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7332 else if (ent == r_refdef.scene.worldentity)
7333 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7335 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7336 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7337 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7338 R_Mesh_ColorPointer(NULL, 0, 0);
7339 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7340 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7341 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7342 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);
7343 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7346 if (r_shownormals.value < 0)
7349 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7351 VectorCopy(rsurface.vertex3f + l * 3, v);
7352 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7353 qglVertex3f(v[0], v[1], v[2]);
7354 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7355 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7356 qglVertex3f(v[0], v[1], v[2]);
7361 if (r_shownormals.value > 0)
7364 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7366 VectorCopy(rsurface.vertex3f + l * 3, v);
7367 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7368 qglVertex3f(v[0], v[1], v[2]);
7369 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7370 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7371 qglVertex3f(v[0], v[1], v[2]);
7376 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7378 VectorCopy(rsurface.vertex3f + l * 3, v);
7379 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7380 qglVertex3f(v[0], v[1], v[2]);
7381 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7382 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7383 qglVertex3f(v[0], v[1], v[2]);
7388 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7390 VectorCopy(rsurface.vertex3f + l * 3, v);
7391 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7392 qglVertex3f(v[0], v[1], v[2]);
7393 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7394 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7395 qglVertex3f(v[0], v[1], v[2]);
7402 rsurface.texture = NULL;
7406 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7407 int r_maxsurfacelist = 0;
7408 msurface_t **r_surfacelist = NULL;
7409 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7411 int i, j, endj, f, flagsmask;
7413 dp_model_t *model = r_refdef.scene.worldmodel;
7414 msurface_t *surfaces;
7415 unsigned char *update;
7416 int numsurfacelist = 0;
7420 if (r_maxsurfacelist < model->num_surfaces)
7422 r_maxsurfacelist = model->num_surfaces;
7424 Mem_Free(r_surfacelist);
7425 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7428 RSurf_ActiveWorldEntity();
7430 surfaces = model->data_surfaces;
7431 update = model->brushq1.lightmapupdateflags;
7433 // update light styles on this submodel
7434 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7436 model_brush_lightstyleinfo_t *style;
7437 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7439 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7441 int *list = style->surfacelist;
7442 style->value = r_refdef.scene.lightstylevalue[style->style];
7443 for (j = 0;j < style->numsurfaces;j++)
7444 update[list[j]] = true;
7449 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7453 R_DrawDebugModel(r_refdef.scene.worldentity);
7454 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7460 rsurface.uselightmaptexture = false;
7461 rsurface.texture = NULL;
7462 rsurface.rtlight = NULL;
7464 // add visible surfaces to draw list
7465 for (i = 0;i < model->nummodelsurfaces;i++)
7467 j = model->sortedmodelsurfaces[i];
7468 if (r_refdef.viewcache.world_surfacevisible[j])
7469 r_surfacelist[numsurfacelist++] = surfaces + j;
7471 // update lightmaps if needed
7473 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7474 if (r_refdef.viewcache.world_surfacevisible[j])
7476 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7477 // don't do anything if there were no surfaces
7478 if (!numsurfacelist)
7480 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7483 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7484 GL_AlphaTest(false);
7486 // add to stats if desired
7487 if (r_speeds.integer && !skysurfaces && !depthonly)
7489 r_refdef.stats.world_surfaces += numsurfacelist;
7490 for (j = 0;j < numsurfacelist;j++)
7491 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7493 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7496 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7498 int i, j, endj, f, flagsmask;
7500 dp_model_t *model = ent->model;
7501 msurface_t *surfaces;
7502 unsigned char *update;
7503 int numsurfacelist = 0;
7507 if (r_maxsurfacelist < model->num_surfaces)
7509 r_maxsurfacelist = model->num_surfaces;
7511 Mem_Free(r_surfacelist);
7512 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7515 // if the model is static it doesn't matter what value we give for
7516 // wantnormals and wanttangents, so this logic uses only rules applicable
7517 // to a model, knowing that they are meaningless otherwise
7518 if (ent == r_refdef.scene.worldentity)
7519 RSurf_ActiveWorldEntity();
7520 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7521 RSurf_ActiveModelEntity(ent, false, false);
7523 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7525 surfaces = model->data_surfaces;
7526 update = model->brushq1.lightmapupdateflags;
7528 // update light styles
7529 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7531 model_brush_lightstyleinfo_t *style;
7532 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7534 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7536 int *list = style->surfacelist;
7537 style->value = r_refdef.scene.lightstylevalue[style->style];
7538 for (j = 0;j < style->numsurfaces;j++)
7539 update[list[j]] = true;
7544 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7548 R_DrawDebugModel(ent);
7549 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7555 rsurface.uselightmaptexture = false;
7556 rsurface.texture = NULL;
7557 rsurface.rtlight = NULL;
7559 // add visible surfaces to draw list
7560 for (i = 0;i < model->nummodelsurfaces;i++)
7561 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7562 // don't do anything if there were no surfaces
7563 if (!numsurfacelist)
7565 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7568 // update lightmaps if needed
7570 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7572 R_BuildLightMap(ent, surfaces + j);
7573 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7574 GL_AlphaTest(false);
7576 // add to stats if desired
7577 if (r_speeds.integer && !skysurfaces && !depthonly)
7579 r_refdef.stats.entities_surfaces += numsurfacelist;
7580 for (j = 0;j < numsurfacelist;j++)
7581 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7583 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity