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;
36 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "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"};
37 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
38 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
39 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)"};
40 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
41 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
42 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"};
43 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"};
44 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
45 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"};
46 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"};
47 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"};
48 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
49 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
50 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
51 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
52 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
53 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
54 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
55 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
56 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
57 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
58 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
59 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
60 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
61 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
62 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
63 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"};
64 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"};
65 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
74 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
76 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)"};
78 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
79 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)"};
80 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)"};
81 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
82 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
83 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
84 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
85 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)"};
86 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)"};
87 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)"};
88 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)"};
89 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)"};
91 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)"};
92 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
93 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"};
94 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
95 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
97 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
98 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
99 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
100 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
102 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
103 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
104 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
105 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
106 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
107 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
108 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
110 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
111 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
112 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
113 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)"};
115 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"};
117 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"};
119 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
121 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
122 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
123 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"};
124 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
125 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
126 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
128 extern cvar_t v_glslgamma;
130 extern qboolean v_flipped_state;
132 static struct r_bloomstate_s
137 int bloomwidth, bloomheight;
139 int screentexturewidth, screentextureheight;
140 rtexture_t *texture_screen;
142 int bloomtexturewidth, bloomtextureheight;
143 rtexture_t *texture_bloom;
145 // arrays for rendering the screen passes
146 float screentexcoord2f[8];
147 float bloomtexcoord2f[8];
148 float offsettexcoord2f[8];
152 typedef struct r_waterstate_waterplane_s
154 rtexture_t *texture_refraction;
155 rtexture_t *texture_reflection;
157 int materialflags; // combined flags of all water surfaces on this plane
158 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
161 r_waterstate_waterplane_t;
163 #define MAX_WATERPLANES 16
165 static struct r_waterstate_s
169 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
171 int waterwidth, waterheight;
172 int texturewidth, textureheight;
174 int maxwaterplanes; // same as MAX_WATERPLANES
176 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
178 float screenscale[2];
179 float screencenter[2];
183 // shadow volume bsp struct with automatically growing nodes buffer
186 rtexture_t *r_texture_blanknormalmap;
187 rtexture_t *r_texture_white;
188 rtexture_t *r_texture_grey128;
189 rtexture_t *r_texture_black;
190 rtexture_t *r_texture_notexture;
191 rtexture_t *r_texture_whitecube;
192 rtexture_t *r_texture_normalizationcube;
193 rtexture_t *r_texture_fogattenuation;
194 rtexture_t *r_texture_gammaramps;
195 unsigned int r_texture_gammaramps_serial;
196 //rtexture_t *r_texture_fogintensity;
198 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
199 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
201 // vertex coordinates for a quad that covers the screen exactly
202 const static float r_screenvertex3f[12] =
210 extern void R_DrawModelShadows(void);
212 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
215 for (i = 0;i < verts;i++)
226 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
229 for (i = 0;i < verts;i++)
239 // FIXME: move this to client?
242 if (gamemode == GAME_NEHAHRA)
244 Cvar_Set("gl_fogenable", "0");
245 Cvar_Set("gl_fogdensity", "0.2");
246 Cvar_Set("gl_fogred", "0.3");
247 Cvar_Set("gl_foggreen", "0.3");
248 Cvar_Set("gl_fogblue", "0.3");
250 r_refdef.fog_density = 0;
251 r_refdef.fog_red = 0;
252 r_refdef.fog_green = 0;
253 r_refdef.fog_blue = 0;
254 r_refdef.fog_alpha = 1;
255 r_refdef.fog_start = 0;
256 r_refdef.fog_end = 0;
259 float FogForDistance(vec_t dist)
261 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
262 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
265 float FogPoint_World(const vec3_t p)
267 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
270 float FogPoint_Model(const vec3_t p)
272 return FogForDistance(VectorDistance((p), rsurface.modelorg));
275 static void R_BuildBlankTextures(void)
277 unsigned char data[4];
278 data[2] = 128; // normal X
279 data[1] = 128; // normal Y
280 data[0] = 255; // normal Z
281 data[3] = 128; // height
282 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
287 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
292 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
297 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
300 static void R_BuildNoTexture(void)
303 unsigned char pix[16][16][4];
304 // this makes a light grey/dark grey checkerboard texture
305 for (y = 0;y < 16;y++)
307 for (x = 0;x < 16;x++)
309 if ((y < 8) ^ (x < 8))
325 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
328 static void R_BuildWhiteCube(void)
330 unsigned char data[6*1*1*4];
331 memset(data, 255, sizeof(data));
332 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
335 static void R_BuildNormalizationCube(void)
339 vec_t s, t, intensity;
341 unsigned char data[6][NORMSIZE][NORMSIZE][4];
342 for (side = 0;side < 6;side++)
344 for (y = 0;y < NORMSIZE;y++)
346 for (x = 0;x < NORMSIZE;x++)
348 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
349 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
384 intensity = 127.0f / sqrt(DotProduct(v, v));
385 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
386 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
387 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
388 data[side][y][x][3] = 255;
392 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
395 static void R_BuildFogTexture(void)
399 unsigned char data1[FOGWIDTH][4];
400 //unsigned char data2[FOGWIDTH][4];
403 r_refdef.fogmasktable_start = r_refdef.fog_start;
404 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
405 r_refdef.fogmasktable_range = r_refdef.fogrange;
406 r_refdef.fogmasktable_density = r_refdef.fog_density;
408 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
409 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
411 d = (x * r - r_refdef.fogmasktable_start);
412 if(developer.integer >= 100)
413 Con_Printf("%f ", d);
415 if (r_fog_exp2.integer)
416 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
418 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
419 if(developer.integer >= 100)
420 Con_Printf(" : %f ", alpha);
421 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
422 if(developer.integer >= 100)
423 Con_Printf(" = %f\n", alpha);
424 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
427 for (x = 0;x < FOGWIDTH;x++)
429 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
434 //data2[x][0] = 255 - b;
435 //data2[x][1] = 255 - b;
436 //data2[x][2] = 255 - b;
439 if (r_texture_fogattenuation)
441 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
442 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
446 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);
447 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
451 static const char *builtinshaderstring =
452 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
453 "// written by Forest 'LordHavoc' Hale\n"
455 "// common definitions between vertex shader and fragment shader:\n"
457 "//#ifdef __GLSL_CG_DATA_TYPES\n"
458 "//# define myhalf half\n"
459 "//# define myhalf2 half2\n"
460 "//# define myhalf3 half3\n"
461 "//# define myhalf4 half4\n"
463 "# define myhalf float\n"
464 "# define myhalf2 vec2\n"
465 "# define myhalf3 vec3\n"
466 "# define myhalf4 vec4\n"
469 "#ifdef MODE_DEPTH_OR_SHADOW\n"
471 "# ifdef VERTEX_SHADER\n"
474 " gl_Position = ftransform();\n"
480 "#ifdef MODE_POSTPROCESS\n"
481 "# ifdef VERTEX_SHADER\n"
484 " gl_FrontColor = gl_Color;\n"
485 " gl_Position = ftransform();\n"
486 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
488 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
492 "# ifdef FRAGMENT_SHADER\n"
494 "uniform sampler2D Texture_First;\n"
496 "uniform sampler2D Texture_Second;\n"
498 "#ifdef USEGAMMARAMPS\n"
499 "uniform sampler2D Texture_GammaRamps;\n"
501 "#ifdef USEVERTEXTEXTUREBLEND\n"
502 "uniform vec4 TintColor;\n"
504 "#ifdef USECOLORMOD\n"
505 "uniform vec3 Gamma;\n"
507 "//uncomment these if you want to use them:\n"
508 "// uniform vec4 UserVec1;\n"
509 "// uniform vec4 UserVec2;\n"
510 "// uniform vec4 UserVec3;\n"
511 "// uniform vec4 UserVec4;\n"
512 "// uniform float ClientTime;\n"
515 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
517 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
519 "#ifdef USEVERTEXTEXTUREBLEND\n"
520 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
523 "#ifdef USEPOSTPROCESSING\n"
524 "// add your own postprocessing here or make your own ifdef for it\n"
527 "#ifdef USEGAMMARAMPS\n"
528 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
529 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
530 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
537 "#ifdef MODE_GENERIC\n"
538 "# ifdef VERTEX_SHADER\n"
541 " gl_FrontColor = gl_Color;\n"
542 "# ifdef USEDIFFUSE\n"
543 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
545 "# ifdef USESPECULAR\n"
546 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
548 " gl_Position = ftransform();\n"
551 "# ifdef FRAGMENT_SHADER\n"
553 "# ifdef USEDIFFUSE\n"
554 "uniform sampler2D Texture_First;\n"
556 "# ifdef USESPECULAR\n"
557 "uniform sampler2D Texture_Second;\n"
562 " gl_FragColor = gl_Color;\n"
563 "# ifdef USEDIFFUSE\n"
564 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
567 "# ifdef USESPECULAR\n"
568 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
570 "# ifdef USECOLORMAPPING\n"
571 " gl_FragColor *= tex2;\n"
574 " gl_FragColor += tex2;\n"
576 "# ifdef USEVERTEXTEXTUREBLEND\n"
577 " gl_FragColor = mix(tex2, gl_FragColor, tex2.a);\n"
582 "#else // !MODE_GENERIC\n"
584 "varying vec2 TexCoord;\n"
585 "varying vec2 TexCoordLightmap;\n"
587 "#ifdef MODE_LIGHTSOURCE\n"
588 "varying vec3 CubeVector;\n"
591 "#ifdef MODE_LIGHTSOURCE\n"
592 "varying vec3 LightVector;\n"
594 "#ifdef MODE_LIGHTDIRECTION\n"
595 "varying vec3 LightVector;\n"
598 "varying vec3 EyeVector;\n"
600 "varying vec3 EyeVectorModelSpace;\n"
603 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
604 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
605 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
607 "#ifdef MODE_WATER\n"
608 "varying vec4 ModelViewProjectionPosition;\n"
610 "#ifdef MODE_REFRACTION\n"
611 "varying vec4 ModelViewProjectionPosition;\n"
613 "#ifdef USEREFLECTION\n"
614 "varying vec4 ModelViewProjectionPosition;\n"
621 "// vertex shader specific:\n"
622 "#ifdef VERTEX_SHADER\n"
624 "uniform vec3 LightPosition;\n"
625 "uniform vec3 EyePosition;\n"
626 "uniform vec3 LightDir;\n"
628 "// 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"
632 " gl_FrontColor = gl_Color;\n"
633 " // copy the surface texcoord\n"
634 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
635 "#ifndef MODE_LIGHTSOURCE\n"
636 "# ifndef MODE_LIGHTDIRECTION\n"
637 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
641 "#ifdef MODE_LIGHTSOURCE\n"
642 " // transform vertex position into light attenuation/cubemap space\n"
643 " // (-1 to +1 across the light box)\n"
644 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
646 " // transform unnormalized light direction into tangent space\n"
647 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
648 " // normalize it per pixel)\n"
649 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
650 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
651 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
652 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
655 "#ifdef MODE_LIGHTDIRECTION\n"
656 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
657 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
658 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
661 " // transform unnormalized eye direction into tangent space\n"
663 " vec3 EyeVectorModelSpace;\n"
665 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
666 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
667 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
668 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
670 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
671 " VectorS = gl_MultiTexCoord1.xyz;\n"
672 " VectorT = gl_MultiTexCoord2.xyz;\n"
673 " VectorR = gl_MultiTexCoord3.xyz;\n"
676 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
677 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
678 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
679 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
682 "// transform vertex to camera space, using ftransform to match non-VS\n"
684 " gl_Position = ftransform();\n"
686 "#ifdef MODE_WATER\n"
687 " ModelViewProjectionPosition = gl_Position;\n"
689 "#ifdef MODE_REFRACTION\n"
690 " ModelViewProjectionPosition = gl_Position;\n"
692 "#ifdef USEREFLECTION\n"
693 " ModelViewProjectionPosition = gl_Position;\n"
697 "#endif // VERTEX_SHADER\n"
702 "// fragment shader specific:\n"
703 "#ifdef FRAGMENT_SHADER\n"
705 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
706 "uniform sampler2D Texture_Normal;\n"
707 "uniform sampler2D Texture_Color;\n"
708 "uniform sampler2D Texture_Gloss;\n"
709 "uniform sampler2D Texture_Glow;\n"
710 "uniform sampler2D Texture_SecondaryNormal;\n"
711 "uniform sampler2D Texture_SecondaryColor;\n"
712 "uniform sampler2D Texture_SecondaryGloss;\n"
713 "uniform sampler2D Texture_SecondaryGlow;\n"
714 "uniform sampler2D Texture_Pants;\n"
715 "uniform sampler2D Texture_Shirt;\n"
716 "uniform sampler2D Texture_FogMask;\n"
717 "uniform sampler2D Texture_Lightmap;\n"
718 "uniform sampler2D Texture_Deluxemap;\n"
719 "uniform sampler2D Texture_Refraction;\n"
720 "uniform sampler2D Texture_Reflection;\n"
721 "uniform sampler2D Texture_Attenuation;\n"
722 "uniform samplerCube Texture_Cube;\n"
724 "uniform myhalf3 LightColor;\n"
725 "uniform myhalf3 AmbientColor;\n"
726 "uniform myhalf3 DiffuseColor;\n"
727 "uniform myhalf3 SpecularColor;\n"
728 "uniform myhalf3 Color_Pants;\n"
729 "uniform myhalf3 Color_Shirt;\n"
730 "uniform myhalf3 FogColor;\n"
732 "uniform myhalf4 TintColor;\n"
735 "//#ifdef MODE_WATER\n"
736 "uniform vec4 DistortScaleRefractReflect;\n"
737 "uniform vec4 ScreenScaleRefractReflect;\n"
738 "uniform vec4 ScreenCenterRefractReflect;\n"
739 "uniform myhalf4 RefractColor;\n"
740 "uniform myhalf4 ReflectColor;\n"
741 "uniform myhalf ReflectFactor;\n"
742 "uniform myhalf ReflectOffset;\n"
744 "//# ifdef MODE_REFRACTION\n"
745 "//uniform vec4 DistortScaleRefractReflect;\n"
746 "//uniform vec4 ScreenScaleRefractReflect;\n"
747 "//uniform vec4 ScreenCenterRefractReflect;\n"
748 "//uniform myhalf4 RefractColor;\n"
749 "//# ifdef USEREFLECTION\n"
750 "//uniform myhalf4 ReflectColor;\n"
753 "//# ifdef USEREFLECTION\n"
754 "//uniform vec4 DistortScaleRefractReflect;\n"
755 "//uniform vec4 ScreenScaleRefractReflect;\n"
756 "//uniform vec4 ScreenCenterRefractReflect;\n"
757 "//uniform myhalf4 ReflectColor;\n"
762 "uniform myhalf GlowScale;\n"
763 "uniform myhalf SceneBrightness;\n"
764 "#ifdef USECONTRASTBOOST\n"
765 "uniform myhalf ContrastBoostCoeff;\n"
768 "uniform float OffsetMapping_Scale;\n"
769 "uniform float OffsetMapping_Bias;\n"
770 "uniform float FogRangeRecip;\n"
772 "uniform myhalf AmbientScale;\n"
773 "uniform myhalf DiffuseScale;\n"
774 "uniform myhalf SpecularScale;\n"
775 "uniform myhalf SpecularPower;\n"
777 "#ifdef USEOFFSETMAPPING\n"
778 "vec2 OffsetMapping(vec2 TexCoord)\n"
780 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
781 " // 14 sample relief mapping: linear search and then binary search\n"
782 " // this basically steps forward a small amount repeatedly until it finds\n"
783 " // itself inside solid, then jitters forward and back using decreasing\n"
784 " // amounts to find the impact\n"
785 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
786 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
787 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
788 " vec3 RT = vec3(TexCoord, 1);\n"
789 " OffsetVector *= 0.1;\n"
790 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
791 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
792 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
793 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
794 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
795 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
796 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
797 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
798 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
799 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
800 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
801 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
802 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
803 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
806 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
807 " // this basically moves forward the full distance, and then backs up based\n"
808 " // on height of samples\n"
809 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
810 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
811 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
812 " TexCoord += OffsetVector;\n"
813 " OffsetVector *= 0.333;\n"
814 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
815 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
816 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
817 " return TexCoord;\n"
820 "#endif // USEOFFSETMAPPING\n"
822 "#ifdef MODE_WATER\n"
827 "#ifdef USEOFFSETMAPPING\n"
828 " // apply offsetmapping\n"
829 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
830 "#define TexCoord TexCoordOffset\n"
833 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
834 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
835 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
836 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
837 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
840 "#else // !MODE_WATER\n"
841 "#ifdef MODE_REFRACTION\n"
843 "// refraction pass\n"
846 "#ifdef USEOFFSETMAPPING\n"
847 " // apply offsetmapping\n"
848 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
849 "#define TexCoord TexCoordOffset\n"
852 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
853 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
854 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
855 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
858 "#else // !MODE_REFRACTION\n"
861 "#ifdef USEOFFSETMAPPING\n"
862 " // apply offsetmapping\n"
863 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
864 "#define TexCoord TexCoordOffset\n"
867 " // combine the diffuse textures (base, pants, shirt)\n"
868 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
869 "#ifdef USECOLORMAPPING\n"
870 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
872 "#ifdef USEVERTEXTEXTUREBLEND\n"
873 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
874 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
875 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
876 " color = mix(myhalf4(texture2D(Texture_SecondaryColor, TexCoord)), color, terrainblend);\n"
877 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
880 "#ifdef USEDIFFUSE\n"
881 " // get the surface normal and the gloss color\n"
882 "# ifdef USEVERTEXTEXTUREBLEND\n"
883 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
884 "# ifdef USESPECULAR\n"
885 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
888 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
889 "# ifdef USESPECULAR\n"
890 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
897 "#ifdef MODE_LIGHTSOURCE\n"
900 " // calculate surface normal, light normal, and specular normal\n"
901 " // compute color intensity for the two textures (colormap and glossmap)\n"
902 " // scale by light color and attenuation as efficiently as possible\n"
903 " // (do as much scalar math as possible rather than vector math)\n"
904 "# ifdef USEDIFFUSE\n"
905 " // get the light normal\n"
906 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
908 "# ifdef USESPECULAR\n"
909 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
911 " // calculate directional shading\n"
912 " 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"
914 "# ifdef USEDIFFUSE\n"
915 " // calculate directional shading\n"
916 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
918 " // calculate directionless shading\n"
919 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
923 "# ifdef USECUBEFILTER\n"
924 " // apply light cubemap filter\n"
925 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
926 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
928 "#endif // MODE_LIGHTSOURCE\n"
933 "#ifdef MODE_LIGHTDIRECTION\n"
934 " // directional model lighting\n"
935 "# ifdef USEDIFFUSE\n"
936 " // get the light normal\n"
937 " myhalf3 diffusenormal = myhalf3(LightVector);\n"
939 "# ifdef USESPECULAR\n"
940 " // calculate directional shading\n"
941 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
942 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
943 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
945 "# ifdef USEDIFFUSE\n"
947 " // calculate directional shading\n"
948 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
950 " color.rgb *= AmbientColor;\n"
953 "#endif // MODE_LIGHTDIRECTION\n"
958 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
959 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
961 " // get the light normal\n"
962 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5);\n"
963 " myhalf3 diffusenormal = normalize(myhalf3(dot(diffusenormal_modelspace, myhalf3(VectorS)), dot(diffusenormal_modelspace, myhalf3(VectorT)), dot(diffusenormal_modelspace, myhalf3(VectorR))));\n"
964 " // calculate directional shading\n"
965 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
966 "# ifdef USESPECULAR\n"
967 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
968 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
971 " // apply lightmap color\n"
972 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
973 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
978 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
979 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
981 " // get the light normal\n"
982 " myhalf3 diffusenormal = normalize(myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5));\n"
983 " // calculate directional shading\n"
984 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
985 "# ifdef USESPECULAR\n"
986 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
987 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
990 " // apply lightmap color\n"
991 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
992 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
997 "#ifdef MODE_LIGHTMAP\n"
998 " // apply lightmap color\n"
999 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1000 "#endif // MODE_LIGHTMAP\n"
1005 "#ifdef MODE_VERTEXCOLOR\n"
1006 " // apply lightmap color\n"
1007 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1008 "#endif // MODE_VERTEXCOLOR\n"
1013 "#ifdef MODE_FLATCOLOR\n"
1014 "#endif // MODE_FLATCOLOR\n"
1022 " color *= TintColor;\n"
1025 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1028 "#ifdef USECONTRASTBOOST\n"
1029 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1032 " color.rgb *= SceneBrightness;\n"
1034 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1036 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1039 " // 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"
1040 "#ifdef USEREFLECTION\n"
1041 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1042 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1043 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1044 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1047 " gl_FragColor = vec4(color);\n"
1049 "#endif // !MODE_REFRACTION\n"
1050 "#endif // !MODE_WATER\n"
1052 "#endif // FRAGMENT_SHADER\n"
1054 "#endif // !MODE_GENERIC\n"
1055 "#endif // !MODE_POSTPROCESS\n"
1056 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1059 typedef struct shaderpermutationinfo_s
1061 const char *pretext;
1064 shaderpermutationinfo_t;
1066 typedef struct shadermodeinfo_s
1068 const char *vertexfilename;
1069 const char *geometryfilename;
1070 const char *fragmentfilename;
1071 const char *pretext;
1076 typedef enum shaderpermutation_e
1078 SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
1079 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1080 SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
1081 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1082 SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
1083 SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
1084 SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
1085 SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
1086 SHADERPERMUTATION_REFLECTION = 1<<8, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1087 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, // adjust texcoords to roughly simulate a displacement mapped surface
1088 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1089 SHADERPERMUTATION_GAMMARAMPS = 1<<11, // gamma (postprocessing only)
1090 SHADERPERMUTATION_POSTPROCESSING = 1<<12, // user defined postprocessing
1091 SHADERPERMUTATION_LIMIT = 1<<13, // size of permutations array
1092 SHADERPERMUTATION_COUNT = 13 // size of shaderpermutationinfo array
1094 shaderpermutation_t;
1096 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1097 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1099 {"#define USEDIFFUSE\n", " diffuse"},
1100 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1101 {"#define USECOLORMAPPING\n", " colormapping"},
1102 {"#define USECONTRASTBOOST\n", " contrastboost"},
1103 {"#define USEFOG\n", " fog"},
1104 {"#define USECUBEFILTER\n", " cubefilter"},
1105 {"#define USEGLOW\n", " glow"},
1106 {"#define USESPECULAR\n", " specular"},
1107 {"#define USEREFLECTION\n", " reflection"},
1108 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1109 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1110 {"#define USEGAMMARAMPS\n", " gammaramps"},
1111 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1114 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
1115 typedef enum shadermode_e
1117 SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
1118 SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
1119 SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
1120 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1121 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
1122 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1123 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1124 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1125 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1126 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
1127 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
1128 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1133 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1134 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1136 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1137 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1138 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1139 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1140 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1141 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1142 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1143 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1144 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1145 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1146 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1147 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1150 typedef struct r_glsl_permutation_s
1152 // indicates if we have tried compiling this permutation already
1154 // 0 if compilation failed
1156 // locations of detected uniforms in program object, or -1 if not found
1157 int loc_Texture_First;
1158 int loc_Texture_Second;
1159 int loc_Texture_GammaRamps;
1160 int loc_Texture_Normal;
1161 int loc_Texture_Color;
1162 int loc_Texture_Gloss;
1163 int loc_Texture_Glow;
1164 int loc_Texture_SecondaryNormal;
1165 int loc_Texture_SecondaryColor;
1166 int loc_Texture_SecondaryGloss;
1167 int loc_Texture_SecondaryGlow;
1168 int loc_Texture_Pants;
1169 int loc_Texture_Shirt;
1170 int loc_Texture_FogMask;
1171 int loc_Texture_Lightmap;
1172 int loc_Texture_Deluxemap;
1173 int loc_Texture_Attenuation;
1174 int loc_Texture_Cube;
1175 int loc_Texture_Refraction;
1176 int loc_Texture_Reflection;
1178 int loc_LightPosition;
1179 int loc_EyePosition;
1180 int loc_Color_Pants;
1181 int loc_Color_Shirt;
1182 int loc_FogRangeRecip;
1183 int loc_AmbientScale;
1184 int loc_DiffuseScale;
1185 int loc_SpecularScale;
1186 int loc_SpecularPower;
1188 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1189 int loc_OffsetMapping_Scale;
1191 int loc_AmbientColor;
1192 int loc_DiffuseColor;
1193 int loc_SpecularColor;
1195 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1196 int loc_GammaCoeff; // 1 / gamma
1197 int loc_DistortScaleRefractReflect;
1198 int loc_ScreenScaleRefractReflect;
1199 int loc_ScreenCenterRefractReflect;
1200 int loc_RefractColor;
1201 int loc_ReflectColor;
1202 int loc_ReflectFactor;
1203 int loc_ReflectOffset;
1210 r_glsl_permutation_t;
1212 // information about each possible shader permutation
1213 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1214 // currently selected permutation
1215 r_glsl_permutation_t *r_glsl_permutation;
1217 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1220 if (!filename || !filename[0])
1222 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1225 if (printfromdisknotice)
1226 Con_DPrint("from disk... ");
1227 return shaderstring;
1229 else if (!strcmp(filename, "glsl/default.glsl"))
1231 shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1232 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1234 return shaderstring;
1237 static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t permutation)
1240 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1241 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1242 int vertstrings_count = 0;
1243 int geomstrings_count = 0;
1244 int fragstrings_count = 0;
1245 char *vertexstring, *geometrystring, *fragmentstring;
1246 const char *vertstrings_list[32+3];
1247 const char *geomstrings_list[32+3];
1248 const char *fragstrings_list[32+3];
1249 char permutationname[256];
1256 permutationname[0] = 0;
1257 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1258 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1259 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1261 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1263 // the first pretext is which type of shader to compile as
1264 // (later these will all be bound together as a program object)
1265 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1266 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1267 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1269 // the second pretext is the mode (for example a light source)
1270 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1271 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1272 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1273 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1275 // now add all the permutation pretexts
1276 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1278 if (permutation & (1<<i))
1280 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1281 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1282 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1283 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1287 // keep line numbers correct
1288 vertstrings_list[vertstrings_count++] = "\n";
1289 geomstrings_list[geomstrings_count++] = "\n";
1290 fragstrings_list[fragstrings_count++] = "\n";
1294 // now append the shader text itself
1295 vertstrings_list[vertstrings_count++] = vertexstring;
1296 geomstrings_list[geomstrings_count++] = geometrystring;
1297 fragstrings_list[fragstrings_count++] = fragmentstring;
1299 // if any sources were NULL, clear the respective list
1301 vertstrings_count = 0;
1302 if (!geometrystring)
1303 geomstrings_count = 0;
1304 if (!fragmentstring)
1305 fragstrings_count = 0;
1307 // compile the shader program
1308 if (vertstrings_count + geomstrings_count + fragstrings_count)
1309 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1313 qglUseProgramObjectARB(p->program);CHECKGLERROR
1314 // look up all the uniform variable names we care about, so we don't
1315 // have to look them up every time we set them
1316 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1317 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1318 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1319 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1320 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1321 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1322 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1323 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1324 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1325 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1326 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1327 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1328 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1329 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1330 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1331 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1332 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1333 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1334 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1335 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1336 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1337 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1338 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1339 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1340 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1341 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1342 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1343 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1344 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1345 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1346 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1347 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1348 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1349 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1350 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1351 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1352 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1353 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1354 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1355 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1356 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1357 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1358 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1359 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1360 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1361 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1362 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1363 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1364 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1365 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1366 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1367 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1368 // initialize the samplers to refer to the texture units we use
1369 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1370 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1371 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1372 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1373 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1374 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1375 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1376 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1377 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1378 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1379 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1380 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1381 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1382 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1383 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1384 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1385 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1386 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1387 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1388 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1390 if (developer.integer)
1391 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1394 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1398 Mem_Free(vertexstring);
1400 Mem_Free(geometrystring);
1402 Mem_Free(fragmentstring);
1405 void R_GLSL_Restart_f(void)
1408 shaderpermutation_t permutation;
1409 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1410 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1411 if (r_glsl_permutations[mode][permutation].program)
1412 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1413 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1416 void R_GLSL_DumpShader_f(void)
1420 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1423 Con_Printf("failed to write to glsl/default.glsl\n");
1427 FS_Print(file, "// The engine may define the following macros:\n");
1428 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1429 for (i = 0;i < SHADERMODE_COUNT;i++)
1430 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1431 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1432 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1433 FS_Print(file, "\n");
1434 FS_Print(file, builtinshaderstring);
1437 Con_Printf("glsl/default.glsl written\n");
1440 void R_SetupShader_SetPermutation(shadermode_t mode, unsigned int permutation)
1442 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1443 if (r_glsl_permutation != perm)
1445 r_glsl_permutation = perm;
1446 if (!r_glsl_permutation->program)
1448 if (!r_glsl_permutation->compiled)
1449 R_GLSL_CompilePermutation(mode, permutation);
1450 if (!r_glsl_permutation->program)
1452 // remove features until we find a valid permutation
1454 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1456 // reduce i more quickly whenever it would not remove any bits
1457 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1458 if (!(permutation & j))
1461 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1462 if (!r_glsl_permutation->compiled)
1463 R_GLSL_CompilePermutation(mode, permutation);
1464 if (r_glsl_permutation->program)
1467 if (i >= SHADERPERMUTATION_COUNT)
1469 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");
1470 Cvar_SetValueQuick(&r_glsl, 0);
1471 R_GLSL_Restart_f(); // unload shaders
1472 return; // no bit left to clear
1477 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1481 void R_SetupGenericShader(qboolean usetexture)
1483 if (gl_support_fragment_shader)
1485 if (r_glsl.integer && r_glsl_usegeneric.integer)
1486 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1487 else if (r_glsl_permutation)
1489 r_glsl_permutation = NULL;
1490 qglUseProgramObjectARB(0);CHECKGLERROR
1495 void R_SetupGenericTwoTextureShader(int texturemode)
1497 if (gl_support_fragment_shader)
1499 if (r_glsl.integer && r_glsl_usegeneric.integer)
1500 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1501 else if (r_glsl_permutation)
1503 r_glsl_permutation = NULL;
1504 qglUseProgramObjectARB(0);CHECKGLERROR
1507 if (!r_glsl_permutation)
1509 if (texturemode == GL_DECAL && gl_combine.integer)
1510 texturemode = GL_INTERPOLATE_ARB;
1511 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1515 void R_SetupDepthOrShadowShader(void)
1517 if (gl_support_fragment_shader)
1519 if (r_glsl.integer && r_glsl_usegeneric.integer)
1520 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1521 else if (r_glsl_permutation)
1523 r_glsl_permutation = NULL;
1524 qglUseProgramObjectARB(0);CHECKGLERROR
1529 extern rtexture_t *r_shadow_attenuationgradienttexture;
1530 extern rtexture_t *r_shadow_attenuation2dtexture;
1531 extern rtexture_t *r_shadow_attenuation3dtexture;
1532 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1534 // select a permutation of the lighting shader appropriate to this
1535 // combination of texture, entity, light source, and fogging, only use the
1536 // minimum features necessary to avoid wasting rendering time in the
1537 // fragment shader on features that are not being used
1538 unsigned int permutation = 0;
1539 shadermode_t mode = 0;
1540 // TODO: implement geometry-shader based shadow volumes someday
1541 if (r_glsl_offsetmapping.integer)
1543 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1544 if (r_glsl_offsetmapping_reliefmapping.integer)
1545 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1547 if (rsurfacepass == RSURFPASS_BACKGROUND)
1549 // distorted background
1550 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1551 mode = SHADERMODE_WATER;
1553 mode = SHADERMODE_REFRACTION;
1555 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1558 mode = SHADERMODE_LIGHTSOURCE;
1559 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1560 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1561 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1562 permutation |= SHADERPERMUTATION_CUBEFILTER;
1563 if (diffusescale > 0)
1564 permutation |= SHADERPERMUTATION_DIFFUSE;
1565 if (specularscale > 0)
1566 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1567 if (r_refdef.fogenabled)
1568 permutation |= SHADERPERMUTATION_FOG;
1569 if (rsurface.texture->colormapping)
1570 permutation |= SHADERPERMUTATION_COLORMAPPING;
1571 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1572 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1574 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1576 // unshaded geometry (fullbright or ambient model lighting)
1577 mode = SHADERMODE_FLATCOLOR;
1578 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1579 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1580 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1581 permutation |= SHADERPERMUTATION_GLOW;
1582 if (r_refdef.fogenabled)
1583 permutation |= SHADERPERMUTATION_FOG;
1584 if (rsurface.texture->colormapping)
1585 permutation |= SHADERPERMUTATION_COLORMAPPING;
1586 if (r_glsl_offsetmapping.integer)
1588 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1589 if (r_glsl_offsetmapping_reliefmapping.integer)
1590 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1592 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1593 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1594 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1595 permutation |= SHADERPERMUTATION_REFLECTION;
1597 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1599 // directional model lighting
1600 mode = SHADERMODE_LIGHTDIRECTION;
1601 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1602 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1603 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1604 permutation |= SHADERPERMUTATION_GLOW;
1605 permutation |= SHADERPERMUTATION_DIFFUSE;
1606 if (specularscale > 0)
1607 permutation |= SHADERPERMUTATION_SPECULAR;
1608 if (r_refdef.fogenabled)
1609 permutation |= SHADERPERMUTATION_FOG;
1610 if (rsurface.texture->colormapping)
1611 permutation |= SHADERPERMUTATION_COLORMAPPING;
1612 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1613 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1614 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1615 permutation |= SHADERPERMUTATION_REFLECTION;
1617 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1619 // ambient model lighting
1620 mode = SHADERMODE_LIGHTDIRECTION;
1621 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1622 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1623 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1624 permutation |= SHADERPERMUTATION_GLOW;
1625 if (r_refdef.fogenabled)
1626 permutation |= SHADERPERMUTATION_FOG;
1627 if (rsurface.texture->colormapping)
1628 permutation |= SHADERPERMUTATION_COLORMAPPING;
1629 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1630 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1631 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1632 permutation |= SHADERPERMUTATION_REFLECTION;
1637 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1639 // deluxemapping (light direction texture)
1640 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1641 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1643 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1644 permutation |= SHADERPERMUTATION_DIFFUSE;
1645 if (specularscale > 0)
1646 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1648 else if (r_glsl_deluxemapping.integer >= 2)
1650 // fake deluxemapping (uniform light direction in tangentspace)
1651 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1652 permutation |= SHADERPERMUTATION_DIFFUSE;
1653 if (specularscale > 0)
1654 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1656 else if (rsurface.uselightmaptexture)
1658 // ordinary lightmapping (q1bsp, q3bsp)
1659 mode = SHADERMODE_LIGHTMAP;
1663 // ordinary vertex coloring (q3bsp)
1664 mode = SHADERMODE_VERTEXCOLOR;
1666 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1667 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1668 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1669 permutation |= SHADERPERMUTATION_GLOW;
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 R_SetupShader_SetPermutation(mode, permutation);
1680 if (mode == SHADERMODE_LIGHTSOURCE)
1682 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1683 if (permutation & SHADERPERMUTATION_DIFFUSE)
1685 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1686 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1687 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1688 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1692 // ambient only is simpler
1693 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]);
1694 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1695 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1696 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1698 // additive passes are only darkened by fog, not tinted
1699 if (r_glsl_permutation->loc_FogColor >= 0)
1700 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1704 if (mode == SHADERMODE_LIGHTDIRECTION)
1706 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);
1707 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);
1708 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);
1709 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]);
1713 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
1714 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1715 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1717 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]);
1718 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1719 // additive passes are only darkened by fog, not tinted
1720 if (r_glsl_permutation->loc_FogColor >= 0)
1722 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1723 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1725 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1727 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);
1728 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]);
1729 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]);
1730 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1731 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1732 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1733 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1735 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1737 // The formula used is actually:
1738 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1739 // color.rgb *= SceneBrightness;
1741 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1742 // and do [[calculations]] here in the engine
1743 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1744 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1747 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1748 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1749 if (r_glsl_permutation->loc_Color_Pants >= 0)
1751 if (rsurface.texture->currentskinframe->pants)
1752 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1754 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1756 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1758 if (rsurface.texture->currentskinframe->shirt)
1759 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1761 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1763 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1764 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1765 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1769 #define SKINFRAME_HASH 1024
1773 int loadsequence; // incremented each level change
1774 memexpandablearray_t array;
1775 skinframe_t *hash[SKINFRAME_HASH];
1779 void R_SkinFrame_PrepareForPurge(void)
1781 r_skinframe.loadsequence++;
1782 // wrap it without hitting zero
1783 if (r_skinframe.loadsequence >= 200)
1784 r_skinframe.loadsequence = 1;
1787 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1791 // mark the skinframe as used for the purging code
1792 skinframe->loadsequence = r_skinframe.loadsequence;
1795 void R_SkinFrame_Purge(void)
1799 for (i = 0;i < SKINFRAME_HASH;i++)
1801 for (s = r_skinframe.hash[i];s;s = s->next)
1803 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1805 if (s->merged == s->base)
1807 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1808 R_PurgeTexture(s->stain );s->stain = NULL;
1809 R_PurgeTexture(s->merged);s->merged = NULL;
1810 R_PurgeTexture(s->base );s->base = NULL;
1811 R_PurgeTexture(s->pants );s->pants = NULL;
1812 R_PurgeTexture(s->shirt );s->shirt = NULL;
1813 R_PurgeTexture(s->nmap );s->nmap = NULL;
1814 R_PurgeTexture(s->gloss );s->gloss = NULL;
1815 R_PurgeTexture(s->glow );s->glow = NULL;
1816 R_PurgeTexture(s->fog );s->fog = NULL;
1817 s->loadsequence = 0;
1823 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1825 char basename[MAX_QPATH];
1827 Image_StripImageExtension(name, basename, sizeof(basename));
1829 if( last == NULL ) {
1831 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1832 item = r_skinframe.hash[hashindex];
1837 // linearly search through the hash bucket
1838 for( ; item ; item = item->next ) {
1839 if( !strcmp( item->basename, basename ) ) {
1846 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1850 char basename[MAX_QPATH];
1852 Image_StripImageExtension(name, basename, sizeof(basename));
1854 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1855 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1856 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1860 rtexture_t *dyntexture;
1861 // check whether its a dynamic texture
1862 dyntexture = CL_GetDynTexture( basename );
1863 if (!add && !dyntexture)
1865 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1866 memset(item, 0, sizeof(*item));
1867 strlcpy(item->basename, basename, sizeof(item->basename));
1868 item->base = dyntexture; // either NULL or dyntexture handle
1869 item->textureflags = textureflags;
1870 item->comparewidth = comparewidth;
1871 item->compareheight = compareheight;
1872 item->comparecrc = comparecrc;
1873 item->next = r_skinframe.hash[hashindex];
1874 r_skinframe.hash[hashindex] = item;
1876 else if( item->base == NULL )
1878 rtexture_t *dyntexture;
1879 // check whether its a dynamic texture
1880 // 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]
1881 dyntexture = CL_GetDynTexture( basename );
1882 item->base = dyntexture; // either NULL or dyntexture handle
1885 R_SkinFrame_MarkUsed(item);
1889 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1891 // FIXME: it should be possible to disable loading various layers using
1892 // cvars, to prevent wasted loading time and memory usage if the user does
1894 qboolean loadnormalmap = true;
1895 qboolean loadgloss = true;
1896 qboolean loadpantsandshirt = true;
1897 qboolean loadglow = true;
1899 unsigned char *pixels;
1900 unsigned char *bumppixels;
1901 unsigned char *basepixels = NULL;
1902 int basepixels_width;
1903 int basepixels_height;
1904 skinframe_t *skinframe;
1906 if (cls.state == ca_dedicated)
1909 // return an existing skinframe if already loaded
1910 // if loading of the first image fails, don't make a new skinframe as it
1911 // would cause all future lookups of this to be missing
1912 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1913 if (skinframe && skinframe->base)
1916 basepixels = loadimagepixelsbgra(name, complain, true);
1917 if (basepixels == NULL)
1920 // we've got some pixels to store, so really allocate this new texture now
1922 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1923 skinframe->stain = NULL;
1924 skinframe->merged = NULL;
1925 skinframe->base = r_texture_notexture;
1926 skinframe->pants = NULL;
1927 skinframe->shirt = NULL;
1928 skinframe->nmap = r_texture_blanknormalmap;
1929 skinframe->gloss = NULL;
1930 skinframe->glow = NULL;
1931 skinframe->fog = NULL;
1933 basepixels_width = image_width;
1934 basepixels_height = image_height;
1935 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);
1937 if (textureflags & TEXF_ALPHA)
1939 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1940 if (basepixels[j] < 255)
1942 if (j < basepixels_width * basepixels_height * 4)
1944 // has transparent pixels
1945 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1946 for (j = 0;j < image_width * image_height * 4;j += 4)
1951 pixels[j+3] = basepixels[j+3];
1953 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);
1958 // _norm is the name used by tenebrae and has been adopted as standard
1961 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1963 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1967 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1969 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1970 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1971 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1973 Mem_Free(bumppixels);
1975 else if (r_shadow_bumpscale_basetexture.value > 0)
1977 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1978 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1979 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1983 // _luma is supported for tenebrae compatibility
1984 // (I think it's a very stupid name, but oh well)
1985 // _glow is the preferred name
1986 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;}
1987 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;}
1988 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;}
1989 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;}
1992 Mem_Free(basepixels);
1997 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)
2002 for (i = 0;i < width*height;i++)
2003 if (((unsigned char *)&palette[in[i]])[3] > 0)
2005 if (i == width*height)
2008 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2011 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2012 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2015 unsigned char *temp1, *temp2;
2016 skinframe_t *skinframe;
2018 if (cls.state == ca_dedicated)
2021 // if already loaded just return it, otherwise make a new skinframe
2022 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2023 if (skinframe && skinframe->base)
2026 skinframe->stain = NULL;
2027 skinframe->merged = NULL;
2028 skinframe->base = r_texture_notexture;
2029 skinframe->pants = NULL;
2030 skinframe->shirt = NULL;
2031 skinframe->nmap = r_texture_blanknormalmap;
2032 skinframe->gloss = NULL;
2033 skinframe->glow = NULL;
2034 skinframe->fog = NULL;
2036 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2040 if (r_shadow_bumpscale_basetexture.value > 0)
2042 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2043 temp2 = temp1 + width * height * 4;
2044 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2045 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2048 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2049 if (textureflags & TEXF_ALPHA)
2051 for (i = 3;i < width * height * 4;i += 4)
2052 if (skindata[i] < 255)
2054 if (i < width * height * 4)
2056 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2057 memcpy(fogpixels, skindata, width * height * 4);
2058 for (i = 0;i < width * height * 4;i += 4)
2059 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2060 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2061 Mem_Free(fogpixels);
2068 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2071 unsigned char *temp1, *temp2;
2072 skinframe_t *skinframe;
2074 if (cls.state == ca_dedicated)
2077 // if already loaded just return it, otherwise make a new skinframe
2078 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2079 if (skinframe && skinframe->base)
2082 skinframe->stain = NULL;
2083 skinframe->merged = NULL;
2084 skinframe->base = r_texture_notexture;
2085 skinframe->pants = NULL;
2086 skinframe->shirt = NULL;
2087 skinframe->nmap = r_texture_blanknormalmap;
2088 skinframe->gloss = NULL;
2089 skinframe->glow = NULL;
2090 skinframe->fog = NULL;
2092 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2096 if (r_shadow_bumpscale_basetexture.value > 0)
2098 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2099 temp2 = temp1 + width * height * 4;
2100 // use either a custom palette or the quake palette
2101 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2102 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2103 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2106 // use either a custom palette, or the quake palette
2107 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete)), skinframe->textureflags, true); // all
2108 if (loadglowtexture)
2109 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2110 if (loadpantsandshirt)
2112 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2113 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2115 if (skinframe->pants || skinframe->shirt)
2116 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
2117 if (textureflags & TEXF_ALPHA)
2119 for (i = 0;i < width * height;i++)
2120 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2122 if (i < width * height)
2123 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2129 skinframe_t *R_SkinFrame_LoadMissing(void)
2131 skinframe_t *skinframe;
2133 if (cls.state == ca_dedicated)
2136 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
2137 skinframe->stain = NULL;
2138 skinframe->merged = NULL;
2139 skinframe->base = r_texture_notexture;
2140 skinframe->pants = NULL;
2141 skinframe->shirt = NULL;
2142 skinframe->nmap = r_texture_blanknormalmap;
2143 skinframe->gloss = NULL;
2144 skinframe->glow = NULL;
2145 skinframe->fog = NULL;
2150 void gl_main_start(void)
2152 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2153 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2155 // set up r_skinframe loading system for textures
2156 memset(&r_skinframe, 0, sizeof(r_skinframe));
2157 r_skinframe.loadsequence = 1;
2158 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2160 r_main_texturepool = R_AllocTexturePool();
2161 R_BuildBlankTextures();
2163 if (gl_texturecubemap)
2166 R_BuildNormalizationCube();
2168 r_texture_fogattenuation = NULL;
2169 r_texture_gammaramps = NULL;
2170 //r_texture_fogintensity = NULL;
2171 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2172 memset(&r_waterstate, 0, sizeof(r_waterstate));
2173 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2174 memset(&r_svbsp, 0, sizeof (r_svbsp));
2176 r_refdef.fogmasktable_density = 0;
2179 void gl_main_shutdown(void)
2181 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2182 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2184 // clear out the r_skinframe state
2185 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2186 memset(&r_skinframe, 0, sizeof(r_skinframe));
2189 Mem_Free(r_svbsp.nodes);
2190 memset(&r_svbsp, 0, sizeof (r_svbsp));
2191 R_FreeTexturePool(&r_main_texturepool);
2192 r_texture_blanknormalmap = NULL;
2193 r_texture_white = NULL;
2194 r_texture_grey128 = NULL;
2195 r_texture_black = NULL;
2196 r_texture_whitecube = NULL;
2197 r_texture_normalizationcube = NULL;
2198 r_texture_fogattenuation = NULL;
2199 r_texture_gammaramps = NULL;
2200 //r_texture_fogintensity = NULL;
2201 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2202 memset(&r_waterstate, 0, sizeof(r_waterstate));
2206 extern void CL_ParseEntityLump(char *entitystring);
2207 void gl_main_newmap(void)
2209 // FIXME: move this code to client
2211 char *entities, entname[MAX_QPATH];
2214 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2215 l = (int)strlen(entname) - 4;
2216 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2218 memcpy(entname + l, ".ent", 5);
2219 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2221 CL_ParseEntityLump(entities);
2226 if (cl.worldmodel->brush.entities)
2227 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2231 void GL_Main_Init(void)
2233 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2235 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2236 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2237 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2238 if (gamemode == GAME_NEHAHRA)
2240 Cvar_RegisterVariable (&gl_fogenable);
2241 Cvar_RegisterVariable (&gl_fogdensity);
2242 Cvar_RegisterVariable (&gl_fogred);
2243 Cvar_RegisterVariable (&gl_foggreen);
2244 Cvar_RegisterVariable (&gl_fogblue);
2245 Cvar_RegisterVariable (&gl_fogstart);
2246 Cvar_RegisterVariable (&gl_fogend);
2247 Cvar_RegisterVariable (&gl_skyclip);
2249 Cvar_RegisterVariable(&r_depthfirst);
2250 Cvar_RegisterVariable(&r_nearclip);
2251 Cvar_RegisterVariable(&r_showbboxes);
2252 Cvar_RegisterVariable(&r_showsurfaces);
2253 Cvar_RegisterVariable(&r_showtris);
2254 Cvar_RegisterVariable(&r_shownormals);
2255 Cvar_RegisterVariable(&r_showlighting);
2256 Cvar_RegisterVariable(&r_showshadowvolumes);
2257 Cvar_RegisterVariable(&r_showcollisionbrushes);
2258 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2259 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2260 Cvar_RegisterVariable(&r_showdisabledepthtest);
2261 Cvar_RegisterVariable(&r_drawportals);
2262 Cvar_RegisterVariable(&r_drawentities);
2263 Cvar_RegisterVariable(&r_cullentities_trace);
2264 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2265 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2266 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2267 Cvar_RegisterVariable(&r_drawviewmodel);
2268 Cvar_RegisterVariable(&r_speeds);
2269 Cvar_RegisterVariable(&r_fullbrights);
2270 Cvar_RegisterVariable(&r_wateralpha);
2271 Cvar_RegisterVariable(&r_dynamic);
2272 Cvar_RegisterVariable(&r_fullbright);
2273 Cvar_RegisterVariable(&r_shadows);
2274 Cvar_RegisterVariable(&r_shadows_throwdistance);
2275 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2276 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2277 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2278 Cvar_RegisterVariable(&r_fog_exp2);
2279 Cvar_RegisterVariable(&r_textureunits);
2280 Cvar_RegisterVariable(&r_glsl);
2281 Cvar_RegisterVariable(&r_glsl_contrastboost);
2282 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2283 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2284 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2285 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2286 Cvar_RegisterVariable(&r_glsl_postprocess);
2287 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2288 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2289 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2290 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2291 Cvar_RegisterVariable(&r_glsl_usegeneric);
2292 Cvar_RegisterVariable(&r_water);
2293 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2294 Cvar_RegisterVariable(&r_water_clippingplanebias);
2295 Cvar_RegisterVariable(&r_water_refractdistort);
2296 Cvar_RegisterVariable(&r_water_reflectdistort);
2297 Cvar_RegisterVariable(&r_lerpsprites);
2298 Cvar_RegisterVariable(&r_lerpmodels);
2299 Cvar_RegisterVariable(&r_lerplightstyles);
2300 Cvar_RegisterVariable(&r_waterscroll);
2301 Cvar_RegisterVariable(&r_bloom);
2302 Cvar_RegisterVariable(&r_bloom_colorscale);
2303 Cvar_RegisterVariable(&r_bloom_brighten);
2304 Cvar_RegisterVariable(&r_bloom_blur);
2305 Cvar_RegisterVariable(&r_bloom_resolution);
2306 Cvar_RegisterVariable(&r_bloom_colorexponent);
2307 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2308 Cvar_RegisterVariable(&r_hdr);
2309 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2310 Cvar_RegisterVariable(&r_hdr_glowintensity);
2311 Cvar_RegisterVariable(&r_hdr_range);
2312 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2313 Cvar_RegisterVariable(&developer_texturelogging);
2314 Cvar_RegisterVariable(&gl_lightmaps);
2315 Cvar_RegisterVariable(&r_test);
2316 Cvar_RegisterVariable(&r_batchmode);
2317 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2318 Cvar_SetValue("r_fullbrights", 0);
2319 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2321 Cvar_RegisterVariable(&r_track_sprites);
2322 Cvar_RegisterVariable(&r_track_sprites_flags);
2323 Cvar_RegisterVariable(&r_track_sprites_scalew);
2324 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2327 extern void R_Textures_Init(void);
2328 extern void GL_Draw_Init(void);
2329 extern void GL_Main_Init(void);
2330 extern void R_Shadow_Init(void);
2331 extern void R_Sky_Init(void);
2332 extern void GL_Surf_Init(void);
2333 extern void R_Particles_Init(void);
2334 extern void R_Explosion_Init(void);
2335 extern void gl_backend_init(void);
2336 extern void Sbar_Init(void);
2337 extern void R_LightningBeams_Init(void);
2338 extern void Mod_RenderInit(void);
2340 void Render_Init(void)
2352 R_LightningBeams_Init();
2361 extern char *ENGINE_EXTENSIONS;
2364 VID_CheckExtensions();
2366 // LordHavoc: report supported extensions
2367 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2369 // clear to black (loading plaque will be seen over this)
2371 qglClearColor(0,0,0,1);CHECKGLERROR
2372 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2375 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2379 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2381 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2384 p = r_refdef.view.frustum + i;
2389 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2393 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2397 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2401 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2405 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2409 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2413 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2417 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2425 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2429 for (i = 0;i < numplanes;i++)
2436 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2440 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2444 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2448 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2452 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2456 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2460 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2464 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2472 //==================================================================================
2474 static void R_View_UpdateEntityVisible (void)
2477 entity_render_t *ent;
2479 if (!r_drawentities.integer)
2482 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2483 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2485 // worldmodel can check visibility
2486 for (i = 0;i < r_refdef.scene.numentities;i++)
2488 ent = r_refdef.scene.entities[i];
2489 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)) && ((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));
2492 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2494 for (i = 0;i < r_refdef.scene.numentities;i++)
2496 ent = r_refdef.scene.entities[i];
2497 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2499 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))
2500 ent->last_trace_visibility = realtime;
2501 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2502 r_refdef.viewcache.entityvisible[i] = 0;
2509 // no worldmodel or it can't check visibility
2510 for (i = 0;i < r_refdef.scene.numentities;i++)
2512 ent = r_refdef.scene.entities[i];
2513 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));
2518 // only used if skyrendermasked, and normally returns false
2519 int R_DrawBrushModelsSky (void)
2522 entity_render_t *ent;
2524 if (!r_drawentities.integer)
2528 for (i = 0;i < r_refdef.scene.numentities;i++)
2530 if (!r_refdef.viewcache.entityvisible[i])
2532 ent = r_refdef.scene.entities[i];
2533 if (!ent->model || !ent->model->DrawSky)
2535 ent->model->DrawSky(ent);
2541 static void R_DrawNoModel(entity_render_t *ent);
2542 static void R_DrawModels(void)
2545 entity_render_t *ent;
2547 if (!r_drawentities.integer)
2550 for (i = 0;i < r_refdef.scene.numentities;i++)
2552 if (!r_refdef.viewcache.entityvisible[i])
2554 ent = r_refdef.scene.entities[i];
2555 r_refdef.stats.entities++;
2556 if (ent->model && ent->model->Draw != NULL)
2557 ent->model->Draw(ent);
2563 static void R_DrawModelsDepth(void)
2566 entity_render_t *ent;
2568 if (!r_drawentities.integer)
2571 for (i = 0;i < r_refdef.scene.numentities;i++)
2573 if (!r_refdef.viewcache.entityvisible[i])
2575 ent = r_refdef.scene.entities[i];
2576 if (ent->model && ent->model->DrawDepth != NULL)
2577 ent->model->DrawDepth(ent);
2581 static void R_DrawModelsDebug(void)
2584 entity_render_t *ent;
2586 if (!r_drawentities.integer)
2589 for (i = 0;i < r_refdef.scene.numentities;i++)
2591 if (!r_refdef.viewcache.entityvisible[i])
2593 ent = r_refdef.scene.entities[i];
2594 if (ent->model && ent->model->DrawDebug != NULL)
2595 ent->model->DrawDebug(ent);
2599 static void R_DrawModelsAddWaterPlanes(void)
2602 entity_render_t *ent;
2604 if (!r_drawentities.integer)
2607 for (i = 0;i < r_refdef.scene.numentities;i++)
2609 if (!r_refdef.viewcache.entityvisible[i])
2611 ent = r_refdef.scene.entities[i];
2612 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2613 ent->model->DrawAddWaterPlanes(ent);
2617 static void R_View_SetFrustum(void)
2620 double slopex, slopey;
2621 vec3_t forward, left, up, origin;
2623 // we can't trust r_refdef.view.forward and friends in reflected scenes
2624 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2627 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2628 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2629 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2630 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2631 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2632 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2633 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2634 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2635 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2636 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2637 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2638 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2642 zNear = r_refdef.nearclip;
2643 nudge = 1.0 - 1.0 / (1<<23);
2644 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2645 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2646 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2647 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2648 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2649 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2650 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2651 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2657 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2658 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2659 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2660 r_refdef.view.frustum[0].dist = m[15] - m[12];
2662 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2663 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2664 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2665 r_refdef.view.frustum[1].dist = m[15] + m[12];
2667 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2668 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2669 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2670 r_refdef.view.frustum[2].dist = m[15] - m[13];
2672 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2673 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2674 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2675 r_refdef.view.frustum[3].dist = m[15] + m[13];
2677 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2678 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2679 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2680 r_refdef.view.frustum[4].dist = m[15] - m[14];
2682 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2683 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2684 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2685 r_refdef.view.frustum[5].dist = m[15] + m[14];
2688 if (r_refdef.view.useperspective)
2690 slopex = 1.0 / r_refdef.view.frustum_x;
2691 slopey = 1.0 / r_refdef.view.frustum_y;
2692 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2693 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
2694 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
2695 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
2696 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2698 // Leaving those out was a mistake, those were in the old code, and they
2699 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2700 // I couldn't reproduce it after adding those normalizations. --blub
2701 VectorNormalize(r_refdef.view.frustum[0].normal);
2702 VectorNormalize(r_refdef.view.frustum[1].normal);
2703 VectorNormalize(r_refdef.view.frustum[2].normal);
2704 VectorNormalize(r_refdef.view.frustum[3].normal);
2706 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2707 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2708 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2709 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2710 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2712 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2713 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2714 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2715 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2716 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2720 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2721 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2722 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2723 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2724 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2725 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2726 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2727 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2728 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2729 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2731 r_refdef.view.numfrustumplanes = 5;
2733 if (r_refdef.view.useclipplane)
2735 r_refdef.view.numfrustumplanes = 6;
2736 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2739 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2740 PlaneClassify(r_refdef.view.frustum + i);
2742 // LordHavoc: note to all quake engine coders, Quake had a special case
2743 // for 90 degrees which assumed a square view (wrong), so I removed it,
2744 // Quake2 has it disabled as well.
2746 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2747 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2748 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2749 //PlaneClassify(&frustum[0]);
2751 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2752 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2753 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2754 //PlaneClassify(&frustum[1]);
2756 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2757 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2758 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2759 //PlaneClassify(&frustum[2]);
2761 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2762 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2763 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2764 //PlaneClassify(&frustum[3]);
2767 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2768 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2769 //PlaneClassify(&frustum[4]);
2772 void R_View_Update(void)
2774 R_View_SetFrustum();
2775 R_View_WorldVisibility(r_refdef.view.useclipplane);
2776 R_View_UpdateEntityVisible();
2779 void R_SetupView(qboolean allowwaterclippingplane)
2781 if (!r_refdef.view.useperspective)
2782 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);
2783 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2784 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2786 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2788 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2790 if (r_refdef.view.useclipplane && allowwaterclippingplane)
2792 // LordHavoc: couldn't figure out how to make this approach the
2793 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2794 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2795 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2796 dist = r_refdef.view.clipplane.dist;
2797 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2801 void R_ResetViewRendering2D(void)
2805 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2806 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2807 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2808 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2809 GL_Color(1, 1, 1, 1);
2810 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2811 GL_BlendFunc(GL_ONE, GL_ZERO);
2812 GL_AlphaTest(false);
2813 GL_ScissorTest(false);
2814 GL_DepthMask(false);
2815 GL_DepthRange(0, 1);
2816 GL_DepthTest(false);
2817 R_Mesh_Matrix(&identitymatrix);
2818 R_Mesh_ResetTextureState();
2819 GL_PolygonOffset(0, 0);
2820 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2821 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2822 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2823 qglStencilMask(~0);CHECKGLERROR
2824 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2825 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2826 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2827 R_SetupGenericShader(true);
2830 void R_ResetViewRendering3D(void)
2834 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2835 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2837 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2838 GL_Color(1, 1, 1, 1);
2839 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2840 GL_BlendFunc(GL_ONE, GL_ZERO);
2841 GL_AlphaTest(false);
2842 GL_ScissorTest(true);
2844 GL_DepthRange(0, 1);
2846 R_Mesh_Matrix(&identitymatrix);
2847 R_Mesh_ResetTextureState();
2848 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2849 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2850 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2851 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2852 qglStencilMask(~0);CHECKGLERROR
2853 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2854 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2855 GL_CullFace(r_refdef.view.cullface_back);
2856 R_SetupGenericShader(true);
2859 void R_RenderScene(qboolean addwaterplanes);
2861 static void R_Water_StartFrame(void)
2864 int waterwidth, waterheight, texturewidth, textureheight;
2865 r_waterstate_waterplane_t *p;
2867 // set waterwidth and waterheight to the water resolution that will be
2868 // used (often less than the screen resolution for faster rendering)
2869 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
2870 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
2872 // calculate desired texture sizes
2873 // can't use water if the card does not support the texture size
2874 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2875 texturewidth = textureheight = waterwidth = waterheight = 0;
2876 else if (gl_support_arb_texture_non_power_of_two)
2878 texturewidth = waterwidth;
2879 textureheight = waterheight;
2883 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2884 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2887 // allocate textures as needed
2888 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2890 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2891 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2893 if (p->texture_refraction)
2894 R_FreeTexture(p->texture_refraction);
2895 p->texture_refraction = NULL;
2896 if (p->texture_reflection)
2897 R_FreeTexture(p->texture_reflection);
2898 p->texture_reflection = NULL;
2900 memset(&r_waterstate, 0, sizeof(r_waterstate));
2901 r_waterstate.waterwidth = waterwidth;
2902 r_waterstate.waterheight = waterheight;
2903 r_waterstate.texturewidth = texturewidth;
2904 r_waterstate.textureheight = textureheight;
2907 if (r_waterstate.waterwidth)
2909 r_waterstate.enabled = true;
2911 // set up variables that will be used in shader setup
2912 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2913 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2914 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2915 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2918 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2919 r_waterstate.numwaterplanes = 0;
2922 static void R_Water_AddWaterPlane(msurface_t *surface)
2924 int triangleindex, planeindex;
2930 r_waterstate_waterplane_t *p;
2931 // just use the first triangle with a valid normal for any decisions
2932 VectorClear(normal);
2933 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2935 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2936 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2937 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2938 TriangleNormal(vert[0], vert[1], vert[2], normal);
2939 if (VectorLength2(normal) >= 0.001)
2943 VectorCopy(normal, plane.normal);
2944 VectorNormalize(plane.normal);
2945 plane.dist = DotProduct(vert[0], plane.normal);
2946 PlaneClassify(&plane);
2947 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
2949 // skip backfaces (except if nocullface is set)
2950 if (!(surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
2952 VectorNegate(plane.normal, plane.normal);
2954 PlaneClassify(&plane);
2958 // find a matching plane if there is one
2959 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2960 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2962 if (planeindex >= r_waterstate.maxwaterplanes)
2963 return; // nothing we can do, out of planes
2965 // if this triangle does not fit any known plane rendered this frame, add one
2966 if (planeindex >= r_waterstate.numwaterplanes)
2968 // store the new plane
2969 r_waterstate.numwaterplanes++;
2971 // clear materialflags and pvs
2972 p->materialflags = 0;
2973 p->pvsvalid = false;
2975 // merge this surface's materialflags into the waterplane
2976 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2977 // merge this surface's PVS into the waterplane
2978 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
2979 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
2980 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
2982 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2987 static void R_Water_ProcessPlanes(void)
2989 r_refdef_view_t originalview;
2991 r_waterstate_waterplane_t *p;
2993 originalview = r_refdef.view;
2995 // make sure enough textures are allocated
2996 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2998 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3000 if (!p->texture_refraction)
3001 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);
3002 if (!p->texture_refraction)
3006 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3008 if (!p->texture_reflection)
3009 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);
3010 if (!p->texture_reflection)
3016 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3018 r_refdef.view.showdebug = false;
3019 r_refdef.view.width = r_waterstate.waterwidth;
3020 r_refdef.view.height = r_waterstate.waterheight;
3021 r_refdef.view.useclipplane = true;
3022 r_waterstate.renderingscene = true;
3024 // render the normal view scene and copy into texture
3025 // (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)
3026 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3028 r_refdef.view.clipplane = p->plane;
3029 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3030 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3031 PlaneClassify(&r_refdef.view.clipplane);
3033 R_RenderScene(false);
3035 // copy view into the screen texture
3036 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3037 GL_ActiveTexture(0);
3039 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
3042 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3044 // render reflected scene and copy into texture
3045 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3046 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3047 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3048 r_refdef.view.clipplane = p->plane;
3049 // reverse the cullface settings for this render
3050 r_refdef.view.cullface_front = GL_FRONT;
3051 r_refdef.view.cullface_back = GL_BACK;
3052 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3054 r_refdef.view.usecustompvs = true;
3056 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3058 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3061 R_ResetViewRendering3D();
3062 R_ClearScreen(r_refdef.fogenabled);
3063 if (r_timereport_active)
3064 R_TimeReport("viewclear");
3066 R_RenderScene(false);
3068 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3069 GL_ActiveTexture(0);
3071 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
3073 R_ResetViewRendering3D();
3074 R_ClearScreen(r_refdef.fogenabled);
3075 if (r_timereport_active)
3076 R_TimeReport("viewclear");
3079 r_refdef.view = originalview;
3080 r_refdef.view.clear = true;
3081 r_waterstate.renderingscene = false;
3085 r_refdef.view = originalview;
3086 r_waterstate.renderingscene = false;
3087 Cvar_SetValueQuick(&r_water, 0);
3088 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3092 void R_Bloom_StartFrame(void)
3094 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3096 // set bloomwidth and bloomheight to the bloom resolution that will be
3097 // used (often less than the screen resolution for faster rendering)
3098 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3099 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3100 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3101 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3102 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3104 // calculate desired texture sizes
3105 if (gl_support_arb_texture_non_power_of_two)
3107 screentexturewidth = r_refdef.view.width;
3108 screentextureheight = r_refdef.view.height;
3109 bloomtexturewidth = r_bloomstate.bloomwidth;
3110 bloomtextureheight = r_bloomstate.bloomheight;
3114 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3115 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3116 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3117 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3120 if ((r_hdr.integer || r_bloom.integer) && ((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))
3122 Cvar_SetValueQuick(&r_hdr, 0);
3123 Cvar_SetValueQuick(&r_bloom, 0);
3126 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
3127 screentexturewidth = screentextureheight = 0;
3128 if (!r_hdr.integer && !r_bloom.integer)
3129 bloomtexturewidth = bloomtextureheight = 0;
3131 // allocate textures as needed
3132 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3134 if (r_bloomstate.texture_screen)
3135 R_FreeTexture(r_bloomstate.texture_screen);
3136 r_bloomstate.texture_screen = NULL;
3137 r_bloomstate.screentexturewidth = screentexturewidth;
3138 r_bloomstate.screentextureheight = screentextureheight;
3139 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3140 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);
3142 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3144 if (r_bloomstate.texture_bloom)
3145 R_FreeTexture(r_bloomstate.texture_bloom);
3146 r_bloomstate.texture_bloom = NULL;
3147 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3148 r_bloomstate.bloomtextureheight = bloomtextureheight;
3149 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3150 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);
3153 // set up a texcoord array for the full resolution screen image
3154 // (we have to keep this around to copy back during final render)
3155 r_bloomstate.screentexcoord2f[0] = 0;
3156 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3157 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3158 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3159 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3160 r_bloomstate.screentexcoord2f[5] = 0;
3161 r_bloomstate.screentexcoord2f[6] = 0;
3162 r_bloomstate.screentexcoord2f[7] = 0;
3164 // set up a texcoord array for the reduced resolution bloom image
3165 // (which will be additive blended over the screen image)
3166 r_bloomstate.bloomtexcoord2f[0] = 0;
3167 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3168 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3169 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3170 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3171 r_bloomstate.bloomtexcoord2f[5] = 0;
3172 r_bloomstate.bloomtexcoord2f[6] = 0;
3173 r_bloomstate.bloomtexcoord2f[7] = 0;
3175 if (r_hdr.integer || r_bloom.integer)
3177 r_bloomstate.enabled = true;
3178 r_bloomstate.hdr = r_hdr.integer != 0;
3182 void R_Bloom_CopyBloomTexture(float colorscale)
3184 r_refdef.stats.bloom++;
3186 // scale down screen texture to the bloom texture size
3188 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3189 GL_BlendFunc(GL_ONE, GL_ZERO);
3190 GL_Color(colorscale, colorscale, colorscale, 1);
3191 // TODO: optimize with multitexture or GLSL
3192 R_SetupGenericShader(true);
3193 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3194 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3195 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3196 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3198 // we now have a bloom image in the framebuffer
3199 // copy it into the bloom image texture for later processing
3200 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3201 GL_ActiveTexture(0);
3203 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
3204 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3207 void R_Bloom_CopyHDRTexture(void)
3209 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3210 GL_ActiveTexture(0);
3212 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
3213 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3216 void R_Bloom_MakeTexture(void)
3219 float xoffset, yoffset, r, brighten;
3221 r_refdef.stats.bloom++;
3223 R_ResetViewRendering2D();
3224 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3225 R_Mesh_ColorPointer(NULL, 0, 0);
3226 R_SetupGenericShader(true);
3228 // we have a bloom image in the framebuffer
3230 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3232 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3235 r = bound(0, r_bloom_colorexponent.value / x, 1);
3236 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3237 GL_Color(r, r, r, 1);
3238 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3239 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3240 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3241 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3243 // copy the vertically blurred bloom view to a texture
3244 GL_ActiveTexture(0);
3246 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
3247 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3250 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3251 brighten = r_bloom_brighten.value;
3253 brighten *= r_hdr_range.value;
3254 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3255 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3257 for (dir = 0;dir < 2;dir++)
3259 // blend on at multiple vertical offsets to achieve a vertical blur
3260 // TODO: do offset blends using GLSL
3261 GL_BlendFunc(GL_ONE, GL_ZERO);
3262 for (x = -range;x <= range;x++)
3264 if (!dir){xoffset = 0;yoffset = x;}
3265 else {xoffset = x;yoffset = 0;}
3266 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3267 yoffset /= (float)r_bloomstate.bloomtextureheight;
3268 // compute a texcoord array with the specified x and y offset
3269 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3270 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3271 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3272 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3273 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3274 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3275 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3276 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3277 // this r value looks like a 'dot' particle, fading sharply to
3278 // black at the edges
3279 // (probably not realistic but looks good enough)
3280 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3281 //r = (dir ? 1.0f : brighten)/(range*2+1);
3282 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3283 GL_Color(r, r, r, 1);
3284 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3285 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3286 GL_BlendFunc(GL_ONE, GL_ONE);
3289 // copy the vertically blurred bloom view to a texture
3290 GL_ActiveTexture(0);
3292 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
3293 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3296 // apply subtract last
3297 // (just like it would be in a GLSL shader)
3298 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3300 GL_BlendFunc(GL_ONE, GL_ZERO);
3301 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3302 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3303 GL_Color(1, 1, 1, 1);
3304 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3305 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3307 GL_BlendFunc(GL_ONE, GL_ONE);
3308 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3309 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3310 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3311 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3312 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3313 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3314 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3316 // copy the darkened bloom view to a texture
3317 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3318 GL_ActiveTexture(0);
3320 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
3321 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3325 void R_HDR_RenderBloomTexture(void)
3327 int oldwidth, oldheight;
3328 float oldcolorscale;
3330 oldcolorscale = r_refdef.view.colorscale;
3331 oldwidth = r_refdef.view.width;
3332 oldheight = r_refdef.view.height;
3333 r_refdef.view.width = r_bloomstate.bloomwidth;
3334 r_refdef.view.height = r_bloomstate.bloomheight;
3336 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3337 // TODO: add exposure compensation features
3338 // TODO: add fp16 framebuffer support
3340 r_refdef.view.showdebug = false;
3341 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3343 R_ClearScreen(r_refdef.fogenabled);
3344 if (r_timereport_active)
3345 R_TimeReport("HDRclear");
3347 r_waterstate.numwaterplanes = 0;
3348 R_RenderScene(r_waterstate.enabled);
3349 r_refdef.view.showdebug = true;
3351 R_ResetViewRendering2D();
3353 R_Bloom_CopyHDRTexture();
3354 R_Bloom_MakeTexture();
3356 // restore the view settings
3357 r_refdef.view.width = oldwidth;
3358 r_refdef.view.height = oldheight;
3359 r_refdef.view.colorscale = oldcolorscale;
3361 R_ResetViewRendering3D();
3363 R_ClearScreen(r_refdef.fogenabled);
3364 if (r_timereport_active)
3365 R_TimeReport("viewclear");
3368 static void R_BlendView(void)
3370 if (r_bloomstate.texture_screen)
3372 // copy view into the screen texture
3373 R_ResetViewRendering2D();
3374 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3375 R_Mesh_ColorPointer(NULL, 0, 0);
3376 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3377 GL_ActiveTexture(0);CHECKGLERROR
3378 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
3379 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3382 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3384 unsigned int permutation =
3385 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3386 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3387 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3388 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0);
3390 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3392 // render simple bloom effect
3393 // copy the screen and shrink it and darken it for the bloom process
3394 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3395 // make the bloom texture
3396 R_Bloom_MakeTexture();
3399 R_ResetViewRendering2D();
3400 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3401 R_Mesh_ColorPointer(NULL, 0, 0);
3402 GL_Color(1, 1, 1, 1);
3403 GL_BlendFunc(GL_ONE, GL_ZERO);
3404 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3405 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3406 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3407 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3408 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3409 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3410 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3411 if (r_glsl_permutation->loc_TintColor >= 0)
3412 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3413 if (r_glsl_permutation->loc_ClientTime >= 0)
3414 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3415 if (r_glsl_permutation->loc_UserVec1 >= 0)
3417 float a=0, b=0, c=0, d=0;
3418 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3419 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3421 if (r_glsl_permutation->loc_UserVec2 >= 0)
3423 float a=0, b=0, c=0, d=0;
3424 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3425 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3427 if (r_glsl_permutation->loc_UserVec3 >= 0)
3429 float a=0, b=0, c=0, d=0;
3430 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3431 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3433 if (r_glsl_permutation->loc_UserVec4 >= 0)
3435 float a=0, b=0, c=0, d=0;
3436 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3437 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3439 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3440 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3446 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3448 // render high dynamic range bloom effect
3449 // the bloom texture was made earlier this render, so we just need to
3450 // blend it onto the screen...
3451 R_ResetViewRendering2D();
3452 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3453 R_Mesh_ColorPointer(NULL, 0, 0);
3454 R_SetupGenericShader(true);
3455 GL_Color(1, 1, 1, 1);
3456 GL_BlendFunc(GL_ONE, GL_ONE);
3457 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3458 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3459 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3460 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3462 else if (r_bloomstate.texture_bloom)
3464 // render simple bloom effect
3465 // copy the screen and shrink it and darken it for the bloom process
3466 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3467 // make the bloom texture
3468 R_Bloom_MakeTexture();
3469 // put the original screen image back in place and blend the bloom
3471 R_ResetViewRendering2D();
3472 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3473 R_Mesh_ColorPointer(NULL, 0, 0);
3474 GL_Color(1, 1, 1, 1);
3475 GL_BlendFunc(GL_ONE, GL_ZERO);
3476 // do both in one pass if possible
3477 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3478 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3479 if (r_textureunits.integer >= 2 && gl_combine.integer)
3481 R_SetupGenericTwoTextureShader(GL_ADD);
3482 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3483 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3487 R_SetupGenericShader(true);
3488 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3489 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3490 // now blend on the bloom texture
3491 GL_BlendFunc(GL_ONE, GL_ONE);
3492 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3493 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3495 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3496 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3498 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3500 // apply a color tint to the whole view
3501 R_ResetViewRendering2D();
3502 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3503 R_Mesh_ColorPointer(NULL, 0, 0);
3504 R_SetupGenericShader(false);
3505 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3506 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3507 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3511 void R_RenderScene(qboolean addwaterplanes);
3513 matrix4x4_t r_waterscrollmatrix;
3515 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3517 if (r_refdef.fog_density)
3519 r_refdef.fogcolor[0] = r_refdef.fog_red;
3520 r_refdef.fogcolor[1] = r_refdef.fog_green;
3521 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3525 VectorCopy(r_refdef.fogcolor, fogvec);
3526 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3528 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3529 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3530 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3531 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3533 // color.rgb *= ContrastBoost * SceneBrightness;
3534 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3535 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3536 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3537 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3542 void R_UpdateVariables(void)
3546 r_refdef.farclip = 4096;
3547 if (r_refdef.scene.worldmodel)
3548 r_refdef.farclip += VectorDistance(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3549 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3551 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3552 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3553 r_refdef.polygonfactor = 0;
3554 r_refdef.polygonoffset = 0;
3555 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3556 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3558 r_refdef.rtworld = r_shadow_realtime_world.integer;
3559 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3560 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3561 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3562 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3563 if (r_showsurfaces.integer)
3565 r_refdef.rtworld = false;
3566 r_refdef.rtworldshadows = false;
3567 r_refdef.rtdlight = false;
3568 r_refdef.rtdlightshadows = false;
3569 r_refdef.lightmapintensity = 0;
3572 if (gamemode == GAME_NEHAHRA)
3574 if (gl_fogenable.integer)
3576 r_refdef.oldgl_fogenable = true;
3577 r_refdef.fog_density = gl_fogdensity.value;
3578 r_refdef.fog_red = gl_fogred.value;
3579 r_refdef.fog_green = gl_foggreen.value;
3580 r_refdef.fog_blue = gl_fogblue.value;
3581 r_refdef.fog_alpha = 1;
3582 r_refdef.fog_start = 0;
3583 r_refdef.fog_end = gl_skyclip.value;
3585 else if (r_refdef.oldgl_fogenable)
3587 r_refdef.oldgl_fogenable = false;
3588 r_refdef.fog_density = 0;
3589 r_refdef.fog_red = 0;
3590 r_refdef.fog_green = 0;
3591 r_refdef.fog_blue = 0;
3592 r_refdef.fog_alpha = 0;
3593 r_refdef.fog_start = 0;
3594 r_refdef.fog_end = 0;
3598 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3599 r_refdef.fog_start = max(0, r_refdef.fog_start);
3600 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3602 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3604 if (r_refdef.fog_density)
3606 r_refdef.fogenabled = true;
3607 // this is the point where the fog reaches 0.9986 alpha, which we
3608 // consider a good enough cutoff point for the texture
3609 // (0.9986 * 256 == 255.6)
3610 if (r_fog_exp2.integer)
3611 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3613 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3614 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3615 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3616 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3617 // fog color was already set
3618 // update the fog texture
3619 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)
3620 R_BuildFogTexture();
3623 r_refdef.fogenabled = false;
3625 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
3627 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
3629 // build GLSL gamma texture
3630 #define RAMPWIDTH 256
3631 unsigned short ramp[RAMPWIDTH * 3];
3632 unsigned char ramprgb[RAMPWIDTH][4];
3635 r_texture_gammaramps_serial = vid_gammatables_serial;
3637 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
3638 for(i = 0; i < RAMPWIDTH; ++i)
3640 ramprgb[i][0] = ramp[i] >> 8;
3641 ramprgb[i][1] = ramp[i + RAMPWIDTH] >> 8;
3642 ramprgb[i][2] = ramp[i + 2 * RAMPWIDTH] >> 8;
3645 if (r_texture_gammaramps)
3647 R_UpdateTexture(r_texture_gammaramps, &ramprgb[0][0], 0, 0, RAMPWIDTH, 1);
3651 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &ramprgb[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
3657 // remove GLSL gamma texture
3661 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3662 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3668 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3669 if( scenetype != r_currentscenetype ) {
3670 // store the old scenetype
3671 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3672 r_currentscenetype = scenetype;
3673 // move in the new scene
3674 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3683 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3685 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3686 if( scenetype == r_currentscenetype ) {
3687 return &r_refdef.scene;
3689 return &r_scenes_store[ scenetype ];
3698 void R_RenderView(void)
3700 if (!r_refdef.scene.entities/* || !r_refdef.scene.worldmodel*/)
3701 return; //Host_Error ("R_RenderView: NULL worldmodel");
3703 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3705 // break apart the view matrix into vectors for various purposes
3706 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3707 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3708 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3709 VectorNegate(r_refdef.view.left, r_refdef.view.right);
3710 // make an inverted copy of the view matrix for tracking sprites
3711 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3713 R_Shadow_UpdateWorldLightSelection();
3715 R_Bloom_StartFrame();
3716 R_Water_StartFrame();
3719 if (r_timereport_active)
3720 R_TimeReport("viewsetup");
3722 R_ResetViewRendering3D();
3724 if (r_refdef.view.clear || r_refdef.fogenabled)
3726 R_ClearScreen(r_refdef.fogenabled);
3727 if (r_timereport_active)
3728 R_TimeReport("viewclear");
3730 r_refdef.view.clear = true;
3732 r_refdef.view.showdebug = true;
3734 // this produces a bloom texture to be used in R_BlendView() later
3736 R_HDR_RenderBloomTexture();
3738 r_waterstate.numwaterplanes = 0;
3739 R_RenderScene(r_waterstate.enabled);
3742 if (r_timereport_active)
3743 R_TimeReport("blendview");
3745 GL_Scissor(0, 0, vid.width, vid.height);
3746 GL_ScissorTest(false);
3750 extern void R_DrawLightningBeams (void);
3751 extern void VM_CL_AddPolygonsToMeshQueue (void);
3752 extern void R_DrawPortals (void);
3753 extern cvar_t cl_locs_show;
3754 static void R_DrawLocs(void);
3755 static void R_DrawEntityBBoxes(void);
3756 void R_RenderScene(qboolean addwaterplanes)
3758 r_refdef.stats.renders++;
3764 R_ResetViewRendering3D();
3767 if (r_timereport_active)
3768 R_TimeReport("watervis");
3770 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3772 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3773 if (r_timereport_active)
3774 R_TimeReport("waterworld");
3777 // don't let sound skip if going slow
3778 if (r_refdef.scene.extraupdate)
3781 R_DrawModelsAddWaterPlanes();
3782 if (r_timereport_active)
3783 R_TimeReport("watermodels");
3785 R_Water_ProcessPlanes();
3786 if (r_timereport_active)
3787 R_TimeReport("waterscenes");
3790 R_ResetViewRendering3D();
3792 // don't let sound skip if going slow
3793 if (r_refdef.scene.extraupdate)
3796 R_MeshQueue_BeginScene();
3801 if (r_timereport_active)
3802 R_TimeReport("visibility");
3804 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);
3806 if (cl.csqc_vidvars.drawworld)
3808 // don't let sound skip if going slow
3809 if (r_refdef.scene.extraupdate)
3812 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
3814 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
3815 if (r_timereport_active)
3816 R_TimeReport("worldsky");
3819 if (R_DrawBrushModelsSky() && r_timereport_active)
3820 R_TimeReport("bmodelsky");
3823 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
3825 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
3826 if (r_timereport_active)
3827 R_TimeReport("worlddepth");
3829 if (r_depthfirst.integer >= 2)
3831 R_DrawModelsDepth();
3832 if (r_timereport_active)
3833 R_TimeReport("modeldepth");
3836 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
3838 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
3839 if (r_timereport_active)
3840 R_TimeReport("world");
3843 // don't let sound skip if going slow
3844 if (r_refdef.scene.extraupdate)
3848 if (r_timereport_active)
3849 R_TimeReport("models");
3851 // don't let sound skip if going slow
3852 if (r_refdef.scene.extraupdate)
3855 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3857 R_DrawModelShadows();
3859 R_ResetViewRendering3D();
3861 // don't let sound skip if going slow
3862 if (r_refdef.scene.extraupdate)
3866 R_ShadowVolumeLighting(false);
3867 if (r_timereport_active)
3868 R_TimeReport("rtlights");
3870 // don't let sound skip if going slow
3871 if (r_refdef.scene.extraupdate)
3874 if (cl.csqc_vidvars.drawworld)
3876 R_DrawLightningBeams();
3877 if (r_timereport_active)
3878 R_TimeReport("lightning");
3881 if (r_timereport_active)
3882 R_TimeReport("decals");
3885 if (r_timereport_active)
3886 R_TimeReport("particles");
3889 if (r_timereport_active)
3890 R_TimeReport("explosions");
3893 R_SetupGenericShader(true);
3894 VM_CL_AddPolygonsToMeshQueue();
3896 if (r_refdef.view.showdebug)
3898 if (cl_locs_show.integer)
3901 if (r_timereport_active)
3902 R_TimeReport("showlocs");
3905 if (r_drawportals.integer)
3908 if (r_timereport_active)
3909 R_TimeReport("portals");
3912 if (r_showbboxes.value > 0)
3914 R_DrawEntityBBoxes();
3915 if (r_timereport_active)
3916 R_TimeReport("bboxes");
3920 R_SetupGenericShader(true);
3921 R_MeshQueue_RenderTransparent();
3922 if (r_timereport_active)
3923 R_TimeReport("drawtrans");
3925 R_SetupGenericShader(true);
3927 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))
3929 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
3930 if (r_timereport_active)
3931 R_TimeReport("worlddebug");
3932 R_DrawModelsDebug();
3933 if (r_timereport_active)
3934 R_TimeReport("modeldebug");
3937 R_SetupGenericShader(true);
3939 if (cl.csqc_vidvars.drawworld)
3942 if (r_timereport_active)
3943 R_TimeReport("coronas");
3946 // don't let sound skip if going slow
3947 if (r_refdef.scene.extraupdate)
3950 R_ResetViewRendering2D();
3953 static const int bboxelements[36] =
3963 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3966 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3967 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3968 GL_DepthMask(false);
3969 GL_DepthRange(0, 1);
3970 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3971 R_Mesh_Matrix(&identitymatrix);
3972 R_Mesh_ResetTextureState();
3974 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3975 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3976 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3977 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3978 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3979 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3980 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3981 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3982 R_FillColors(color4f, 8, cr, cg, cb, ca);
3983 if (r_refdef.fogenabled)
3985 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3987 f1 = FogPoint_World(v);
3989 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3990 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3991 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3994 R_Mesh_VertexPointer(vertex3f, 0, 0);
3995 R_Mesh_ColorPointer(color4f, 0, 0);
3996 R_Mesh_ResetTextureState();
3997 R_SetupGenericShader(false);
3998 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
4001 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4005 prvm_edict_t *edict;
4006 // this function draws bounding boxes of server entities
4009 R_SetupGenericShader(false);
4011 for (i = 0;i < numsurfaces;i++)
4013 edict = PRVM_EDICT_NUM(surfacelist[i]);
4014 switch ((int)edict->fields.server->solid)
4016 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4017 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4018 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4019 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4020 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4021 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4023 color[3] *= r_showbboxes.value;
4024 color[3] = bound(0, color[3], 1);
4025 GL_DepthTest(!r_showdisabledepthtest.integer);
4026 GL_CullFace(r_refdef.view.cullface_front);
4027 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4032 static void R_DrawEntityBBoxes(void)
4035 prvm_edict_t *edict;
4037 // this function draws bounding boxes of server entities
4041 for (i = 0;i < prog->num_edicts;i++)
4043 edict = PRVM_EDICT_NUM(i);
4044 if (edict->priv.server->free)
4046 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4047 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4052 int nomodelelements[24] =
4064 float nomodelvertex3f[6*3] =
4074 float nomodelcolor4f[6*4] =
4076 0.0f, 0.0f, 0.5f, 1.0f,
4077 0.0f, 0.0f, 0.5f, 1.0f,
4078 0.0f, 0.5f, 0.0f, 1.0f,
4079 0.0f, 0.5f, 0.0f, 1.0f,
4080 0.5f, 0.0f, 0.0f, 1.0f,
4081 0.5f, 0.0f, 0.0f, 1.0f
4084 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4089 // this is only called once per entity so numsurfaces is always 1, and
4090 // surfacelist is always {0}, so this code does not handle batches
4091 R_Mesh_Matrix(&ent->matrix);
4093 if (ent->flags & EF_ADDITIVE)
4095 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4096 GL_DepthMask(false);
4098 else if (ent->alpha < 1)
4100 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4101 GL_DepthMask(false);
4105 GL_BlendFunc(GL_ONE, GL_ZERO);
4108 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4109 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4110 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4111 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4112 R_SetupGenericShader(false);
4113 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4114 if (r_refdef.fogenabled)
4117 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4118 R_Mesh_ColorPointer(color4f, 0, 0);
4119 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4120 f1 = FogPoint_World(org);
4122 for (i = 0, c = color4f;i < 6;i++, c += 4)
4124 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4125 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4126 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4130 else if (ent->alpha != 1)
4132 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4133 R_Mesh_ColorPointer(color4f, 0, 0);
4134 for (i = 0, c = color4f;i < 6;i++, c += 4)
4138 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4139 R_Mesh_ResetTextureState();
4140 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
4143 void R_DrawNoModel(entity_render_t *ent)
4146 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4147 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4148 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4150 // R_DrawNoModelCallback(ent, 0);
4153 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4155 vec3_t right1, right2, diff, normal;
4157 VectorSubtract (org2, org1, normal);
4159 // calculate 'right' vector for start
4160 VectorSubtract (r_refdef.view.origin, org1, diff);
4161 CrossProduct (normal, diff, right1);
4162 VectorNormalize (right1);
4164 // calculate 'right' vector for end
4165 VectorSubtract (r_refdef.view.origin, org2, diff);
4166 CrossProduct (normal, diff, right2);
4167 VectorNormalize (right2);
4169 vert[ 0] = org1[0] + width * right1[0];
4170 vert[ 1] = org1[1] + width * right1[1];
4171 vert[ 2] = org1[2] + width * right1[2];
4172 vert[ 3] = org1[0] - width * right1[0];
4173 vert[ 4] = org1[1] - width * right1[1];
4174 vert[ 5] = org1[2] - width * right1[2];
4175 vert[ 6] = org2[0] - width * right2[0];
4176 vert[ 7] = org2[1] - width * right2[1];
4177 vert[ 8] = org2[2] - width * right2[2];
4178 vert[ 9] = org2[0] + width * right2[0];
4179 vert[10] = org2[1] + width * right2[1];
4180 vert[11] = org2[2] + width * right2[2];
4183 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4185 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)
4190 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4191 fog = FogPoint_World(origin);
4193 R_Mesh_Matrix(&identitymatrix);
4194 GL_BlendFunc(blendfunc1, blendfunc2);
4200 GL_CullFace(r_refdef.view.cullface_front);
4203 GL_CullFace(r_refdef.view.cullface_back);
4204 GL_CullFace(GL_NONE);
4206 GL_DepthMask(false);
4207 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4208 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4209 GL_DepthTest(!depthdisable);
4211 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4212 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4213 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4214 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4215 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4216 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4217 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4218 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4219 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4220 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4221 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4222 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4224 R_Mesh_VertexPointer(vertex3f, 0, 0);
4225 R_Mesh_ColorPointer(NULL, 0, 0);
4226 R_Mesh_ResetTextureState();
4227 R_SetupGenericShader(true);
4228 R_Mesh_TexBind(0, R_GetTexture(texture));
4229 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4230 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4231 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4232 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
4234 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4236 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4237 GL_BlendFunc(blendfunc1, GL_ONE);
4239 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4240 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
4244 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4249 VectorSet(v, x, y, z);
4250 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4251 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4253 if (i == mesh->numvertices)
4255 if (mesh->numvertices < mesh->maxvertices)
4257 VectorCopy(v, vertex3f);
4258 mesh->numvertices++;
4260 return mesh->numvertices;
4266 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4270 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4271 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4272 e = mesh->element3i + mesh->numtriangles * 3;
4273 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4275 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4276 if (mesh->numtriangles < mesh->maxtriangles)
4281 mesh->numtriangles++;
4283 element[1] = element[2];
4287 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4291 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4292 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4293 e = mesh->element3i + mesh->numtriangles * 3;
4294 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4296 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4297 if (mesh->numtriangles < mesh->maxtriangles)
4302 mesh->numtriangles++;
4304 element[1] = element[2];
4308 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4309 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4311 int planenum, planenum2;
4314 mplane_t *plane, *plane2;
4316 double temppoints[2][256*3];
4317 // figure out how large a bounding box we need to properly compute this brush
4319 for (w = 0;w < numplanes;w++)
4320 maxdist = max(maxdist, planes[w].dist);
4321 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4322 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4323 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4327 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4328 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4330 if (planenum2 == planenum)
4332 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);
4335 if (tempnumpoints < 3)
4337 // generate elements forming a triangle fan for this polygon
4338 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4342 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)
4344 texturelayer_t *layer;
4345 layer = t->currentlayers + t->currentnumlayers++;
4347 layer->depthmask = depthmask;
4348 layer->blendfunc1 = blendfunc1;
4349 layer->blendfunc2 = blendfunc2;
4350 layer->texture = texture;
4351 layer->texmatrix = *matrix;
4352 layer->color[0] = r * r_refdef.view.colorscale;
4353 layer->color[1] = g * r_refdef.view.colorscale;
4354 layer->color[2] = b * r_refdef.view.colorscale;
4355 layer->color[3] = a;
4358 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4361 index = parms[2] + r_refdef.scene.time * parms[3];
4362 index -= floor(index);
4366 case Q3WAVEFUNC_NONE:
4367 case Q3WAVEFUNC_NOISE:
4368 case Q3WAVEFUNC_COUNT:
4371 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4372 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4373 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4374 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4375 case Q3WAVEFUNC_TRIANGLE:
4377 f = index - floor(index);
4388 return (float)(parms[0] + parms[1] * f);
4391 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4394 model_t *model = ent->model;
4397 q3shaderinfo_layer_tcmod_t *tcmod;
4399 // switch to an alternate material if this is a q1bsp animated material
4401 texture_t *texture = t;
4402 int s = ent->skinnum;
4403 if ((unsigned int)s >= (unsigned int)model->numskins)
4405 if (model->skinscenes)
4407 if (model->skinscenes[s].framecount > 1)
4408 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4410 s = model->skinscenes[s].firstframe;
4413 t = t + s * model->num_surfaces;
4416 // use an alternate animation if the entity's frame is not 0,
4417 // and only if the texture has an alternate animation
4418 if (ent->frame2 != 0 && t->anim_total[1])
4419 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4421 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4423 texture->currentframe = t;
4426 // update currentskinframe to be a qw skin or animation frame
4427 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4429 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4431 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4432 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4433 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);
4435 t->currentskinframe = r_qwskincache_skinframe[i];
4436 if (t->currentskinframe == NULL)
4437 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4439 else if (t->numskinframes >= 2)
4440 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4441 if (t->backgroundnumskinframes >= 2)
4442 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4444 t->currentmaterialflags = t->basematerialflags;
4445 t->currentalpha = ent->alpha;
4446 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4448 t->currentalpha *= r_wateralpha.value;
4450 * FIXME what is this supposed to do?
4451 // if rendering refraction/reflection, disable transparency
4452 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4453 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4456 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled)
4457 t->currentalpha *= t->r_water_wateralpha;
4458 if(!r_waterstate.enabled)
4459 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4460 if (!(ent->flags & RENDER_LIGHT))
4461 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4462 else if (rsurface.modeltexcoordlightmap2f == NULL)
4464 // pick a model lighting mode
4465 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4466 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4468 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4470 if (ent->effects & EF_ADDITIVE)
4471 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4472 else if (t->currentalpha < 1)
4473 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4474 if (ent->effects & EF_DOUBLESIDED)
4475 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4476 if (ent->effects & EF_NODEPTHTEST)
4477 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4478 if (ent->flags & RENDER_VIEWMODEL)
4479 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4480 if (t->backgroundnumskinframes)
4481 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4482 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4484 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4485 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4488 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4490 // there is no tcmod
4491 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4492 t->currenttexmatrix = r_waterscrollmatrix;
4494 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4497 switch(tcmod->tcmod)
4501 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4502 matrix = r_waterscrollmatrix;
4504 matrix = identitymatrix;
4506 case Q3TCMOD_ENTITYTRANSLATE:
4507 // this is used in Q3 to allow the gamecode to control texcoord
4508 // scrolling on the entity, which is not supported in darkplaces yet.
4509 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4511 case Q3TCMOD_ROTATE:
4512 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4513 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4514 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4517 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4519 case Q3TCMOD_SCROLL:
4520 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4522 case Q3TCMOD_STRETCH:
4523 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4524 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4526 case Q3TCMOD_TRANSFORM:
4527 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4528 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4529 VectorSet(tcmat + 6, 0 , 0 , 1);
4530 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4531 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4533 case Q3TCMOD_TURBULENT:
4534 // this is handled in the RSurf_PrepareVertices function
4535 matrix = identitymatrix;
4538 // either replace or concatenate the transformation
4540 t->currenttexmatrix = matrix;
4543 matrix4x4_t temp = t->currenttexmatrix;
4544 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4548 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4549 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4550 t->glosstexture = r_texture_black;
4551 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4552 t->backgroundglosstexture = r_texture_black;
4553 t->specularpower = r_shadow_glossexponent.value;
4554 // TODO: store reference values for these in the texture?
4555 t->specularscale = 0;
4556 if (r_shadow_gloss.integer > 0)
4558 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4560 if (r_shadow_glossintensity.value > 0)
4562 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4563 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4564 t->specularscale = r_shadow_glossintensity.value;
4567 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4569 t->glosstexture = r_texture_white;
4570 t->backgroundglosstexture = r_texture_white;
4571 t->specularscale = r_shadow_gloss2intensity.value;
4575 // lightmaps mode looks bad with dlights using actual texturing, so turn
4576 // off the colormap and glossmap, but leave the normalmap on as it still
4577 // accurately represents the shading involved
4578 if (gl_lightmaps.integer)
4580 t->basetexture = r_texture_grey128;
4581 t->backgroundbasetexture = NULL;
4582 t->specularscale = 0;
4583 t->currentmaterialflags &= ~(MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_WATERALPHA | MATERIALFLAG_WATER | MATERIALFLAG_SKY | MATERIALFLAG_ALPHATEST | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4584 t->currentmaterialflags |= MATERIALFLAG_WALL;
4587 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4588 VectorClear(t->dlightcolor);
4589 t->currentnumlayers = 0;
4590 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4592 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4594 int blendfunc1, blendfunc2, depthmask;
4595 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4597 blendfunc1 = GL_SRC_ALPHA;
4598 blendfunc2 = GL_ONE;
4600 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4602 blendfunc1 = GL_SRC_ALPHA;
4603 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4605 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4607 blendfunc1 = t->customblendfunc[0];
4608 blendfunc2 = t->customblendfunc[1];
4612 blendfunc1 = GL_ONE;
4613 blendfunc2 = GL_ZERO;
4615 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4616 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4619 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4620 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4621 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4623 // fullbright is not affected by r_refdef.lightmapintensity
4624 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]);
4625 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4626 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]);
4627 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4628 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]);
4632 vec3_t ambientcolor;
4634 // set the color tint used for lights affecting this surface
4635 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4637 // q3bsp has no lightmap updates, so the lightstylevalue that
4638 // would normally be baked into the lightmap must be
4639 // applied to the color
4640 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4641 if (ent->model->type == mod_brushq3)
4642 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4643 colorscale *= r_refdef.lightmapintensity;
4644 VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor);
4645 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4646 // basic lit geometry
4647 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]);
4648 // add pants/shirt if needed
4649 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4650 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]);
4651 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4652 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]);
4653 // now add ambient passes if needed
4654 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4656 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]);
4657 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4658 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]);
4659 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4660 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]);
4663 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4664 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]);
4665 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4667 // if this is opaque use alpha blend which will darken the earlier
4670 // if this is an alpha blended material, all the earlier passes
4671 // were darkened by fog already, so we only need to add the fog
4672 // color ontop through the fog mask texture
4674 // if this is an additive blended material, all the earlier passes
4675 // were darkened by fog already, and we should not add fog color
4676 // (because the background was not darkened, there is no fog color
4677 // that was lost behind it).
4678 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]);
4685 void R_UpdateAllTextureInfo(entity_render_t *ent)
4689 for (i = 0;i < ent->model->num_texturesperskin;i++)
4690 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4693 rsurfacestate_t rsurface;
4695 void R_Mesh_ResizeArrays(int newvertices)
4698 if (rsurface.array_size >= newvertices)
4700 if (rsurface.array_modelvertex3f)
4701 Mem_Free(rsurface.array_modelvertex3f);
4702 rsurface.array_size = (newvertices + 1023) & ~1023;
4703 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4704 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4705 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4706 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4707 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4708 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4709 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4710 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4711 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4712 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4713 rsurface.array_color4f = base + rsurface.array_size * 27;
4714 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4717 void RSurf_ActiveWorldEntity(void)
4719 model_t *model = r_refdef.scene.worldmodel;
4720 if (rsurface.array_size < model->surfmesh.num_vertices)
4721 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4722 rsurface.matrix = identitymatrix;
4723 rsurface.inversematrix = identitymatrix;
4724 R_Mesh_Matrix(&identitymatrix);
4725 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4726 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4727 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4728 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4729 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4730 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4731 rsurface.frameblend[0].frame = 0;
4732 rsurface.frameblend[0].lerp = 1;
4733 rsurface.frameblend[1].frame = 0;
4734 rsurface.frameblend[1].lerp = 0;
4735 rsurface.frameblend[2].frame = 0;
4736 rsurface.frameblend[2].lerp = 0;
4737 rsurface.frameblend[3].frame = 0;
4738 rsurface.frameblend[3].lerp = 0;
4739 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4740 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4741 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4742 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4743 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4744 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4745 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4746 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4747 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4748 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4749 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4750 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4751 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4752 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4753 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4754 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4755 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4756 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4757 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4758 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4759 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4760 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4761 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4762 rsurface.modelelement3i = model->surfmesh.data_element3i;
4763 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4764 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4765 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4766 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4767 rsurface.modelsurfaces = model->data_surfaces;
4768 rsurface.generatedvertex = false;
4769 rsurface.vertex3f = rsurface.modelvertex3f;
4770 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4771 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4772 rsurface.svector3f = rsurface.modelsvector3f;
4773 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4774 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4775 rsurface.tvector3f = rsurface.modeltvector3f;
4776 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4777 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4778 rsurface.normal3f = rsurface.modelnormal3f;
4779 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4780 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4781 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4784 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4786 model_t *model = ent->model;
4787 if (rsurface.array_size < model->surfmesh.num_vertices)
4788 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4789 rsurface.matrix = ent->matrix;
4790 rsurface.inversematrix = ent->inversematrix;
4791 R_Mesh_Matrix(&rsurface.matrix);
4792 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
4793 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4794 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4795 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4796 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4797 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4798 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4799 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4800 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4801 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4802 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4803 rsurface.frameblend[0] = ent->frameblend[0];
4804 rsurface.frameblend[1] = ent->frameblend[1];
4805 rsurface.frameblend[2] = ent->frameblend[2];
4806 rsurface.frameblend[3] = ent->frameblend[3];
4807 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4808 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4809 if (ent->model->brush.submodel)
4811 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4812 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4814 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4818 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4819 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4820 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4821 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4822 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4824 else if (wantnormals)
4826 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4827 rsurface.modelsvector3f = NULL;
4828 rsurface.modeltvector3f = NULL;
4829 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4830 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4834 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4835 rsurface.modelsvector3f = NULL;
4836 rsurface.modeltvector3f = NULL;
4837 rsurface.modelnormal3f = NULL;
4838 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4840 rsurface.modelvertex3f_bufferobject = 0;
4841 rsurface.modelvertex3f_bufferoffset = 0;
4842 rsurface.modelsvector3f_bufferobject = 0;
4843 rsurface.modelsvector3f_bufferoffset = 0;
4844 rsurface.modeltvector3f_bufferobject = 0;
4845 rsurface.modeltvector3f_bufferoffset = 0;
4846 rsurface.modelnormal3f_bufferobject = 0;
4847 rsurface.modelnormal3f_bufferoffset = 0;
4848 rsurface.generatedvertex = true;
4852 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4853 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4854 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4855 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4856 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4857 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4858 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4859 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4860 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4861 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4862 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4863 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4864 rsurface.generatedvertex = false;
4866 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4867 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4868 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4869 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4870 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4871 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4872 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4873 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4874 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4875 rsurface.modelelement3i = model->surfmesh.data_element3i;
4876 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4877 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4878 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4879 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4880 rsurface.modelsurfaces = model->data_surfaces;
4881 rsurface.vertex3f = rsurface.modelvertex3f;
4882 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4883 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4884 rsurface.svector3f = rsurface.modelsvector3f;
4885 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4886 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4887 rsurface.tvector3f = rsurface.modeltvector3f;
4888 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4889 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4890 rsurface.normal3f = rsurface.modelnormal3f;
4891 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4892 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4893 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4896 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4897 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4900 int texturesurfaceindex;
4905 const float *v1, *in_tc;
4907 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4909 q3shaderinfo_deform_t *deform;
4910 // 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
4911 if (rsurface.generatedvertex)
4913 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4914 generatenormals = true;
4915 for (i = 0;i < Q3MAXDEFORMS;i++)
4917 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4919 generatetangents = true;
4920 generatenormals = true;
4922 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4923 generatenormals = true;
4925 if (generatenormals && !rsurface.modelnormal3f)
4927 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4928 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4929 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4930 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4932 if (generatetangents && !rsurface.modelsvector3f)
4934 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4935 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4936 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4937 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4938 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4939 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4940 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);
4943 rsurface.vertex3f = rsurface.modelvertex3f;
4944 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4945 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4946 rsurface.svector3f = rsurface.modelsvector3f;
4947 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4948 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4949 rsurface.tvector3f = rsurface.modeltvector3f;
4950 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4951 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4952 rsurface.normal3f = rsurface.modelnormal3f;
4953 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4954 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4955 // if vertices are deformed (sprite flares and things in maps, possibly
4956 // water waves, bulges and other deformations), generate them into
4957 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4958 // (may be static model data or generated data for an animated model, or
4959 // the previous deform pass)
4960 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4962 switch (deform->deform)
4965 case Q3DEFORM_PROJECTIONSHADOW:
4966 case Q3DEFORM_TEXT0:
4967 case Q3DEFORM_TEXT1:
4968 case Q3DEFORM_TEXT2:
4969 case Q3DEFORM_TEXT3:
4970 case Q3DEFORM_TEXT4:
4971 case Q3DEFORM_TEXT5:
4972 case Q3DEFORM_TEXT6:
4973 case Q3DEFORM_TEXT7:
4976 case Q3DEFORM_AUTOSPRITE:
4977 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4978 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4979 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4980 VectorNormalize(newforward);
4981 VectorNormalize(newright);
4982 VectorNormalize(newup);
4983 // make deformed versions of only the model vertices used by the specified surfaces
4984 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4986 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4987 // a single autosprite surface can contain multiple sprites...
4988 for (j = 0;j < surface->num_vertices - 3;j += 4)
4990 VectorClear(center);
4991 for (i = 0;i < 4;i++)
4992 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4993 VectorScale(center, 0.25f, center);
4994 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4995 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4996 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4997 for (i = 0;i < 4;i++)
4999 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5000 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5003 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);
5004 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);
5006 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5007 rsurface.vertex3f_bufferobject = 0;
5008 rsurface.vertex3f_bufferoffset = 0;
5009 rsurface.svector3f = rsurface.array_deformedsvector3f;
5010 rsurface.svector3f_bufferobject = 0;
5011 rsurface.svector3f_bufferoffset = 0;
5012 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5013 rsurface.tvector3f_bufferobject = 0;
5014 rsurface.tvector3f_bufferoffset = 0;
5015 rsurface.normal3f = rsurface.array_deformednormal3f;
5016 rsurface.normal3f_bufferobject = 0;
5017 rsurface.normal3f_bufferoffset = 0;
5019 case Q3DEFORM_AUTOSPRITE2:
5020 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5021 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5022 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5023 VectorNormalize(newforward);
5024 VectorNormalize(newright);
5025 VectorNormalize(newup);
5026 // make deformed versions of only the model vertices used by the specified surfaces
5027 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5029 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5030 const float *v1, *v2;
5040 memset(shortest, 0, sizeof(shortest));
5041 // a single autosprite surface can contain multiple sprites...
5042 for (j = 0;j < surface->num_vertices - 3;j += 4)
5044 VectorClear(center);
5045 for (i = 0;i < 4;i++)
5046 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5047 VectorScale(center, 0.25f, center);
5048 // find the two shortest edges, then use them to define the
5049 // axis vectors for rotating around the central axis
5050 for (i = 0;i < 6;i++)
5052 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5053 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5055 Debug_PolygonBegin(NULL, 0);
5056 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5057 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);
5058 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5061 l = VectorDistance2(v1, v2);
5062 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5064 l += (1.0f / 1024.0f);
5065 if (shortest[0].length2 > l || i == 0)
5067 shortest[1] = shortest[0];
5068 shortest[0].length2 = l;
5069 shortest[0].v1 = v1;
5070 shortest[0].v2 = v2;
5072 else if (shortest[1].length2 > l || i == 1)
5074 shortest[1].length2 = l;
5075 shortest[1].v1 = v1;
5076 shortest[1].v2 = v2;
5079 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5080 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5082 Debug_PolygonBegin(NULL, 0);
5083 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5084 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);
5085 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5088 // this calculates the right vector from the shortest edge
5089 // and the up vector from the edge midpoints
5090 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5091 VectorNormalize(right);
5092 VectorSubtract(end, start, up);
5093 VectorNormalize(up);
5094 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5095 //VectorSubtract(rsurface.modelorg, center, forward);
5096 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5097 VectorNegate(forward, forward);
5098 VectorReflect(forward, 0, up, forward);
5099 VectorNormalize(forward);
5100 CrossProduct(up, forward, newright);
5101 VectorNormalize(newright);
5103 Debug_PolygonBegin(NULL, 0);
5104 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);
5105 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5106 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5110 Debug_PolygonBegin(NULL, 0);
5111 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5112 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5113 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5116 // rotate the quad around the up axis vector, this is made
5117 // especially easy by the fact we know the quad is flat,
5118 // so we only have to subtract the center position and
5119 // measure distance along the right vector, and then
5120 // multiply that by the newright vector and add back the
5122 // we also need to subtract the old position to undo the
5123 // displacement from the center, which we do with a
5124 // DotProduct, the subtraction/addition of center is also
5125 // optimized into DotProducts here
5126 l = DotProduct(right, center);
5127 for (i = 0;i < 4;i++)
5129 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5130 f = DotProduct(right, v1) - l;
5131 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5134 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);
5135 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);
5137 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5138 rsurface.vertex3f_bufferobject = 0;
5139 rsurface.vertex3f_bufferoffset = 0;
5140 rsurface.svector3f = rsurface.array_deformedsvector3f;
5141 rsurface.svector3f_bufferobject = 0;
5142 rsurface.svector3f_bufferoffset = 0;
5143 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5144 rsurface.tvector3f_bufferobject = 0;
5145 rsurface.tvector3f_bufferoffset = 0;
5146 rsurface.normal3f = rsurface.array_deformednormal3f;
5147 rsurface.normal3f_bufferobject = 0;
5148 rsurface.normal3f_bufferoffset = 0;
5150 case Q3DEFORM_NORMAL:
5151 // deform the normals to make reflections wavey
5152 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5154 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5155 for (j = 0;j < surface->num_vertices;j++)
5158 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5159 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5160 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5161 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5162 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5163 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5164 VectorNormalize(normal);
5166 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);
5168 rsurface.svector3f = rsurface.array_deformedsvector3f;
5169 rsurface.svector3f_bufferobject = 0;
5170 rsurface.svector3f_bufferoffset = 0;
5171 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5172 rsurface.tvector3f_bufferobject = 0;
5173 rsurface.tvector3f_bufferoffset = 0;
5174 rsurface.normal3f = rsurface.array_deformednormal3f;
5175 rsurface.normal3f_bufferobject = 0;
5176 rsurface.normal3f_bufferoffset = 0;
5179 // deform vertex array to make wavey water and flags and such
5180 waveparms[0] = deform->waveparms[0];
5181 waveparms[1] = deform->waveparms[1];
5182 waveparms[2] = deform->waveparms[2];
5183 waveparms[3] = deform->waveparms[3];
5184 // this is how a divisor of vertex influence on deformation
5185 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5186 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5187 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5189 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5190 for (j = 0;j < surface->num_vertices;j++)
5192 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5193 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5194 // if the wavefunc depends on time, evaluate it per-vertex
5197 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5198 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5200 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5203 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5204 rsurface.vertex3f_bufferobject = 0;
5205 rsurface.vertex3f_bufferoffset = 0;
5207 case Q3DEFORM_BULGE:
5208 // deform vertex array to make the surface have moving bulges
5209 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5211 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5212 for (j = 0;j < surface->num_vertices;j++)
5214 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5215 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5218 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5219 rsurface.vertex3f_bufferobject = 0;
5220 rsurface.vertex3f_bufferoffset = 0;
5223 // deform vertex array
5224 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5225 VectorScale(deform->parms, scale, waveparms);
5226 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5228 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5229 for (j = 0;j < surface->num_vertices;j++)
5230 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5232 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5233 rsurface.vertex3f_bufferobject = 0;
5234 rsurface.vertex3f_bufferoffset = 0;
5238 // generate texcoords based on the chosen texcoord source
5239 switch(rsurface.texture->tcgen.tcgen)
5242 case Q3TCGEN_TEXTURE:
5243 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5244 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5245 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5247 case Q3TCGEN_LIGHTMAP:
5248 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5249 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5250 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5252 case Q3TCGEN_VECTOR:
5253 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5255 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5256 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)
5258 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5259 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5262 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5263 rsurface.texcoordtexture2f_bufferobject = 0;
5264 rsurface.texcoordtexture2f_bufferoffset = 0;
5266 case Q3TCGEN_ENVIRONMENT:
5267 // make environment reflections using a spheremap
5268 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5270 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5271 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5272 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5273 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5274 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5276 float l, d, eyedir[3];
5277 VectorSubtract(rsurface.modelorg, vertex, eyedir);
5278 l = 0.5f / VectorLength(eyedir);
5279 d = DotProduct(normal, eyedir)*2;
5280 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
5281 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
5284 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5285 rsurface.texcoordtexture2f_bufferobject = 0;
5286 rsurface.texcoordtexture2f_bufferoffset = 0;
5289 // the only tcmod that needs software vertex processing is turbulent, so
5290 // check for it here and apply the changes if needed
5291 // and we only support that as the first one
5292 // (handling a mixture of turbulent and other tcmods would be problematic
5293 // without punting it entirely to a software path)
5294 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5296 amplitude = rsurface.texture->tcmods[0].parms[1];
5297 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5298 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5300 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5301 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)
5303 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5304 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5307 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5308 rsurface.texcoordtexture2f_bufferobject = 0;
5309 rsurface.texcoordtexture2f_bufferoffset = 0;
5311 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5312 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5313 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5314 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5317 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5320 const msurface_t *surface = texturesurfacelist[0];
5321 const msurface_t *surface2;
5326 // TODO: lock all array ranges before render, rather than on each surface
5327 if (texturenumsurfaces == 1)
5329 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5330 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5332 else if (r_batchmode.integer == 2)
5334 #define MAXBATCHTRIANGLES 4096
5335 int batchtriangles = 0;
5336 int batchelements[MAXBATCHTRIANGLES*3];
5337 for (i = 0;i < texturenumsurfaces;i = j)
5339 surface = texturesurfacelist[i];
5341 if (surface->num_triangles > MAXBATCHTRIANGLES)
5343 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5346 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5347 batchtriangles = surface->num_triangles;
5348 firstvertex = surface->num_firstvertex;
5349 endvertex = surface->num_firstvertex + surface->num_vertices;
5350 for (;j < texturenumsurfaces;j++)
5352 surface2 = texturesurfacelist[j];
5353 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5355 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5356 batchtriangles += surface2->num_triangles;
5357 firstvertex = min(firstvertex, surface2->num_firstvertex);
5358 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5360 surface2 = texturesurfacelist[j-1];
5361 numvertices = endvertex - firstvertex;
5362 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5365 else if (r_batchmode.integer == 1)
5367 for (i = 0;i < texturenumsurfaces;i = j)
5369 surface = texturesurfacelist[i];
5370 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5371 if (texturesurfacelist[j] != surface2)
5373 surface2 = texturesurfacelist[j-1];
5374 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5375 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5376 GL_LockArrays(surface->num_firstvertex, numvertices);
5377 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5382 for (i = 0;i < texturenumsurfaces;i++)
5384 surface = texturesurfacelist[i];
5385 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5386 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5391 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5393 int i, planeindex, vertexindex;
5397 r_waterstate_waterplane_t *p, *bestp;
5398 msurface_t *surface;
5399 if (r_waterstate.renderingscene)
5401 for (i = 0;i < texturenumsurfaces;i++)
5403 surface = texturesurfacelist[i];
5404 if (lightmaptexunit >= 0)
5405 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5406 if (deluxemaptexunit >= 0)
5407 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5408 // pick the closest matching water plane
5411 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5414 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5416 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5417 d += fabs(PlaneDiff(vert, &p->plane));
5419 if (bestd > d || !bestp)
5427 if (refractiontexunit >= 0)
5428 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5429 if (reflectiontexunit >= 0)
5430 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5434 if (refractiontexunit >= 0)
5435 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5436 if (reflectiontexunit >= 0)
5437 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5439 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5440 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5444 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5448 const msurface_t *surface = texturesurfacelist[0];
5449 const msurface_t *surface2;
5454 // TODO: lock all array ranges before render, rather than on each surface
5455 if (texturenumsurfaces == 1)
5457 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5458 if (deluxemaptexunit >= 0)
5459 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5460 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5461 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5463 else if (r_batchmode.integer == 2)
5465 #define MAXBATCHTRIANGLES 4096
5466 int batchtriangles = 0;
5467 int batchelements[MAXBATCHTRIANGLES*3];
5468 for (i = 0;i < texturenumsurfaces;i = j)
5470 surface = texturesurfacelist[i];
5471 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5472 if (deluxemaptexunit >= 0)
5473 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5475 if (surface->num_triangles > MAXBATCHTRIANGLES)
5477 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5480 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5481 batchtriangles = surface->num_triangles;
5482 firstvertex = surface->num_firstvertex;
5483 endvertex = surface->num_firstvertex + surface->num_vertices;
5484 for (;j < texturenumsurfaces;j++)
5486 surface2 = texturesurfacelist[j];
5487 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5489 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5490 batchtriangles += surface2->num_triangles;
5491 firstvertex = min(firstvertex, surface2->num_firstvertex);
5492 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5494 surface2 = texturesurfacelist[j-1];
5495 numvertices = endvertex - firstvertex;
5496 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5499 else if (r_batchmode.integer == 1)
5502 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5503 for (i = 0;i < texturenumsurfaces;i = j)
5505 surface = texturesurfacelist[i];
5506 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5507 if (texturesurfacelist[j] != surface2)
5509 Con_Printf(" %i", j - i);
5512 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5514 for (i = 0;i < texturenumsurfaces;i = j)
5516 surface = texturesurfacelist[i];
5517 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5518 if (deluxemaptexunit >= 0)
5519 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5520 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5521 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5524 Con_Printf(" %i", j - i);
5526 surface2 = texturesurfacelist[j-1];
5527 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5528 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5529 GL_LockArrays(surface->num_firstvertex, numvertices);
5530 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5538 for (i = 0;i < texturenumsurfaces;i++)
5540 surface = texturesurfacelist[i];
5541 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5542 if (deluxemaptexunit >= 0)
5543 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5544 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5545 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5550 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5553 int texturesurfaceindex;
5554 if (r_showsurfaces.integer == 2)
5556 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5558 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5559 for (j = 0;j < surface->num_triangles;j++)
5561 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5562 GL_Color(f, f, f, 1);
5563 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface.modelelement3i + 3 * (j + surface->num_firsttriangle)), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * (j + surface->num_firsttriangle)));
5569 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5571 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5572 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5573 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);
5574 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5575 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5580 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5582 int texturesurfaceindex;
5586 if (rsurface.lightmapcolor4f)
5588 // generate color arrays for the surfaces in this list
5589 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5591 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5592 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)
5594 f = FogPoint_Model(v);
5604 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5606 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5607 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)
5609 f = FogPoint_Model(v);
5617 rsurface.lightmapcolor4f = rsurface.array_color4f;
5618 rsurface.lightmapcolor4f_bufferobject = 0;
5619 rsurface.lightmapcolor4f_bufferoffset = 0;
5622 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5624 int texturesurfaceindex;
5627 if (!rsurface.lightmapcolor4f)
5629 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5631 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5632 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)
5640 rsurface.lightmapcolor4f = rsurface.array_color4f;
5641 rsurface.lightmapcolor4f_bufferobject = 0;
5642 rsurface.lightmapcolor4f_bufferoffset = 0;
5645 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5648 rsurface.lightmapcolor4f = NULL;
5649 rsurface.lightmapcolor4f_bufferobject = 0;
5650 rsurface.lightmapcolor4f_bufferoffset = 0;
5651 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5652 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5653 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5654 GL_Color(r, g, b, a);
5655 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5658 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5660 // TODO: optimize applyfog && applycolor case
5661 // just apply fog if necessary, and tint the fog color array if necessary
5662 rsurface.lightmapcolor4f = NULL;
5663 rsurface.lightmapcolor4f_bufferobject = 0;
5664 rsurface.lightmapcolor4f_bufferoffset = 0;
5665 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5666 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5667 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5668 GL_Color(r, g, b, a);
5669 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5672 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5674 int texturesurfaceindex;
5678 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5680 // generate color arrays for the surfaces in this list
5681 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5683 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5684 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5686 if (surface->lightmapinfo->samples)
5688 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5689 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5690 VectorScale(lm, scale, c);
5691 if (surface->lightmapinfo->styles[1] != 255)
5693 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5695 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5696 VectorMA(c, scale, lm, c);
5697 if (surface->lightmapinfo->styles[2] != 255)
5700 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5701 VectorMA(c, scale, lm, c);
5702 if (surface->lightmapinfo->styles[3] != 255)
5705 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5706 VectorMA(c, scale, lm, c);
5716 rsurface.lightmapcolor4f = rsurface.array_color4f;
5717 rsurface.lightmapcolor4f_bufferobject = 0;
5718 rsurface.lightmapcolor4f_bufferoffset = 0;
5722 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5723 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5724 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5726 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5727 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5728 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5729 GL_Color(r, g, b, a);
5730 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5733 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5735 int texturesurfaceindex;
5739 vec3_t ambientcolor;
5740 vec3_t diffusecolor;
5744 VectorCopy(rsurface.modellight_lightdir, lightdir);
5745 f = 0.5f * r_refdef.lightmapintensity;
5746 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5747 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5748 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5749 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5750 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5751 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5752 if (VectorLength2(diffusecolor) > 0)
5754 // generate color arrays for the surfaces in this list
5755 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5757 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5758 int numverts = surface->num_vertices;
5759 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5760 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5761 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5762 // q3-style directional shading
5763 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5765 if ((f = DotProduct(c2, lightdir)) > 0)
5766 VectorMA(ambientcolor, f, diffusecolor, c);
5768 VectorCopy(ambientcolor, c);
5777 rsurface.lightmapcolor4f = rsurface.array_color4f;
5778 rsurface.lightmapcolor4f_bufferobject = 0;
5779 rsurface.lightmapcolor4f_bufferoffset = 0;
5783 r = ambientcolor[0];
5784 g = ambientcolor[1];
5785 b = ambientcolor[2];
5786 rsurface.lightmapcolor4f = NULL;
5787 rsurface.lightmapcolor4f_bufferobject = 0;
5788 rsurface.lightmapcolor4f_bufferoffset = 0;
5790 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5791 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5792 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5793 GL_Color(r, g, b, a);
5794 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5797 void RSurf_SetupDepthAndCulling(void)
5799 // submodels are biased to avoid z-fighting with world surfaces that they
5800 // may be exactly overlapping (avoids z-fighting artifacts on certain
5801 // doors and things in Quake maps)
5802 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5803 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5804 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5805 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
5808 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5810 // transparent sky would be ridiculous
5811 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5813 R_SetupGenericShader(false);
5816 skyrendernow = false;
5817 // we have to force off the water clipping plane while rendering sky
5821 // restore entity matrix
5822 R_Mesh_Matrix(&rsurface.matrix);
5824 RSurf_SetupDepthAndCulling();
5826 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5827 // skymasking on them, and Quake3 never did sky masking (unlike
5828 // software Quake and software Quake2), so disable the sky masking
5829 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5830 // and skymasking also looks very bad when noclipping outside the
5831 // level, so don't use it then either.
5832 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
5834 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5835 R_Mesh_ColorPointer(NULL, 0, 0);
5836 R_Mesh_ResetTextureState();
5837 if (skyrendermasked)
5839 R_SetupDepthOrShadowShader();
5840 // depth-only (masking)
5841 GL_ColorMask(0,0,0,0);
5842 // just to make sure that braindead drivers don't draw
5843 // anything despite that colormask...
5844 GL_BlendFunc(GL_ZERO, GL_ONE);
5848 R_SetupGenericShader(false);
5850 GL_BlendFunc(GL_ONE, GL_ZERO);
5852 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5853 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5854 if (skyrendermasked)
5855 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5857 R_Mesh_ResetTextureState();
5858 GL_Color(1, 1, 1, 1);
5861 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5863 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5866 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5867 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5868 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
5869 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
5870 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
5871 if (rsurface.texture->backgroundcurrentskinframe)
5873 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
5874 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
5875 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
5876 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
5878 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
5879 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5880 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
5881 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5882 R_Mesh_ColorPointer(NULL, 0, 0);
5884 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5886 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5888 // render background
5889 GL_BlendFunc(GL_ONE, GL_ZERO);
5891 GL_AlphaTest(false);
5893 GL_Color(1, 1, 1, 1);
5894 R_Mesh_ColorPointer(NULL, 0, 0);
5896 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5897 if (r_glsl_permutation)
5899 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5900 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5901 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5902 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5903 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5904 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5905 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);
5907 GL_LockArrays(0, 0);
5909 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5910 GL_DepthMask(false);
5911 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5912 R_Mesh_ColorPointer(NULL, 0, 0);
5914 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5915 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
5916 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
5919 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5920 if (!r_glsl_permutation)
5923 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5924 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5925 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5926 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5927 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5928 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5930 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5932 GL_BlendFunc(GL_ONE, GL_ZERO);
5934 GL_AlphaTest(false);
5938 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5939 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5940 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5943 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5945 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5946 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);
5948 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
5952 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5953 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);
5955 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5957 GL_LockArrays(0, 0);
5960 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5962 // OpenGL 1.3 path - anything not completely ancient
5963 int texturesurfaceindex;
5964 qboolean applycolor;
5968 const texturelayer_t *layer;
5969 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5971 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5974 int layertexrgbscale;
5975 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5977 if (layerindex == 0)
5981 GL_AlphaTest(false);
5982 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5985 GL_DepthMask(layer->depthmask && writedepth);
5986 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5987 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
5989 layertexrgbscale = 4;
5990 VectorScale(layer->color, 0.25f, layercolor);
5992 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
5994 layertexrgbscale = 2;
5995 VectorScale(layer->color, 0.5f, layercolor);
5999 layertexrgbscale = 1;
6000 VectorScale(layer->color, 1.0f, layercolor);
6002 layercolor[3] = layer->color[3];
6003 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6004 R_Mesh_ColorPointer(NULL, 0, 0);
6005 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6006 switch (layer->type)
6008 case TEXTURELAYERTYPE_LITTEXTURE:
6009 memset(&m, 0, sizeof(m));
6010 m.tex[0] = R_GetTexture(r_texture_white);
6011 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6012 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6013 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6014 m.tex[1] = R_GetTexture(layer->texture);
6015 m.texmatrix[1] = layer->texmatrix;
6016 m.texrgbscale[1] = layertexrgbscale;
6017 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6018 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6019 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6020 R_Mesh_TextureState(&m);
6021 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6022 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6023 else if (rsurface.uselightmaptexture)
6024 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6026 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6028 case TEXTURELAYERTYPE_TEXTURE:
6029 memset(&m, 0, sizeof(m));
6030 m.tex[0] = R_GetTexture(layer->texture);
6031 m.texmatrix[0] = layer->texmatrix;
6032 m.texrgbscale[0] = layertexrgbscale;
6033 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6034 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6035 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6036 R_Mesh_TextureState(&m);
6037 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6039 case TEXTURELAYERTYPE_FOG:
6040 memset(&m, 0, sizeof(m));
6041 m.texrgbscale[0] = layertexrgbscale;
6044 m.tex[0] = R_GetTexture(layer->texture);
6045 m.texmatrix[0] = layer->texmatrix;
6046 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6047 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6048 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6050 R_Mesh_TextureState(&m);
6051 // generate a color array for the fog pass
6052 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6053 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6057 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6058 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)
6060 f = 1 - FogPoint_Model(v);
6061 c[0] = layercolor[0];
6062 c[1] = layercolor[1];
6063 c[2] = layercolor[2];
6064 c[3] = f * layercolor[3];
6067 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6070 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6072 GL_LockArrays(0, 0);
6075 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6077 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6078 GL_AlphaTest(false);
6082 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6084 // OpenGL 1.1 - crusty old voodoo path
6085 int texturesurfaceindex;
6089 const texturelayer_t *layer;
6090 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6092 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6094 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6096 if (layerindex == 0)
6100 GL_AlphaTest(false);
6101 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6104 GL_DepthMask(layer->depthmask && writedepth);
6105 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6106 R_Mesh_ColorPointer(NULL, 0, 0);
6107 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6108 switch (layer->type)
6110 case TEXTURELAYERTYPE_LITTEXTURE:
6111 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6113 // two-pass lit texture with 2x rgbscale
6114 // first the lightmap pass
6115 memset(&m, 0, sizeof(m));
6116 m.tex[0] = R_GetTexture(r_texture_white);
6117 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6118 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6119 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6120 R_Mesh_TextureState(&m);
6121 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6122 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6123 else if (rsurface.uselightmaptexture)
6124 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6126 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6127 GL_LockArrays(0, 0);
6128 // then apply the texture to it
6129 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6130 memset(&m, 0, sizeof(m));
6131 m.tex[0] = R_GetTexture(layer->texture);
6132 m.texmatrix[0] = layer->texmatrix;
6133 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6134 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6135 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6136 R_Mesh_TextureState(&m);
6137 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);
6141 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6142 memset(&m, 0, sizeof(m));
6143 m.tex[0] = R_GetTexture(layer->texture);
6144 m.texmatrix[0] = layer->texmatrix;
6145 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6146 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6147 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6148 R_Mesh_TextureState(&m);
6149 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6150 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);
6152 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);
6155 case TEXTURELAYERTYPE_TEXTURE:
6156 // singletexture unlit texture with transparency support
6157 memset(&m, 0, sizeof(m));
6158 m.tex[0] = R_GetTexture(layer->texture);
6159 m.texmatrix[0] = layer->texmatrix;
6160 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6161 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6162 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6163 R_Mesh_TextureState(&m);
6164 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);
6166 case TEXTURELAYERTYPE_FOG:
6167 // singletexture fogging
6168 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6171 memset(&m, 0, sizeof(m));
6172 m.tex[0] = R_GetTexture(layer->texture);
6173 m.texmatrix[0] = layer->texmatrix;
6174 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6175 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6176 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6177 R_Mesh_TextureState(&m);
6180 R_Mesh_ResetTextureState();
6181 // generate a color array for the fog pass
6182 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6186 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6187 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)
6189 f = 1 - FogPoint_Model(v);
6190 c[0] = layer->color[0];
6191 c[1] = layer->color[1];
6192 c[2] = layer->color[2];
6193 c[3] = f * layer->color[3];
6196 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6199 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6201 GL_LockArrays(0, 0);
6204 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6206 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6207 GL_AlphaTest(false);
6211 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6214 RSurf_SetupDepthAndCulling();
6215 if (r_glsl.integer && gl_support_fragment_shader)
6216 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6217 else if (gl_combine.integer && r_textureunits.integer >= 2)
6218 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6220 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6224 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6227 int texturenumsurfaces, endsurface;
6229 msurface_t *surface;
6230 msurface_t *texturesurfacelist[1024];
6232 // if the model is static it doesn't matter what value we give for
6233 // wantnormals and wanttangents, so this logic uses only rules applicable
6234 // to a model, knowing that they are meaningless otherwise
6235 if (ent == r_refdef.scene.worldentity)
6236 RSurf_ActiveWorldEntity();
6237 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6238 RSurf_ActiveModelEntity(ent, false, false);
6240 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6242 for (i = 0;i < numsurfaces;i = j)
6245 surface = rsurface.modelsurfaces + surfacelist[i];
6246 texture = surface->texture;
6247 R_UpdateTextureInfo(ent, texture);
6248 rsurface.texture = texture->currentframe;
6249 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6250 // scan ahead until we find a different texture
6251 endsurface = min(i + 1024, numsurfaces);
6252 texturenumsurfaces = 0;
6253 texturesurfacelist[texturenumsurfaces++] = surface;
6254 for (;j < endsurface;j++)
6256 surface = rsurface.modelsurfaces + surfacelist[j];
6257 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6259 texturesurfacelist[texturenumsurfaces++] = surface;
6261 // render the range of surfaces
6262 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6264 GL_AlphaTest(false);
6267 static void R_ProcessTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6272 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6274 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6276 RSurf_SetupDepthAndCulling();
6277 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6278 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6280 else if (r_showsurfaces.integer)
6282 RSurf_SetupDepthAndCulling();
6284 GL_BlendFunc(GL_ONE, GL_ZERO);
6286 GL_AlphaTest(false);
6287 R_Mesh_ColorPointer(NULL, 0, 0);
6288 R_Mesh_ResetTextureState();
6289 R_SetupGenericShader(false);
6290 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6291 if (!r_refdef.view.showdebug)
6293 GL_Color(0, 0, 0, 1);
6294 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6297 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6299 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6300 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6301 else if (!rsurface.texture->currentnumlayers)
6303 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) && queueentity)
6305 // transparent surfaces get pushed off into the transparent queue
6306 int surfacelistindex;
6307 const msurface_t *surface;
6308 vec3_t tempcenter, center;
6309 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6311 surface = texturesurfacelist[surfacelistindex];
6312 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6313 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6314 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6315 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6316 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6321 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6322 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6327 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6331 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6334 for (i = 0;i < numsurfaces;i++)
6335 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6336 R_Water_AddWaterPlane(surfacelist[i]);
6339 // break the surface list down into batches by texture and use of lightmapping
6340 for (i = 0;i < numsurfaces;i = j)
6343 // texture is the base texture pointer, rsurface.texture is the
6344 // current frame/skin the texture is directing us to use (for example
6345 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6346 // use skin 1 instead)
6347 texture = surfacelist[i]->texture;
6348 rsurface.texture = texture->currentframe;
6349 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6350 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6352 // if this texture is not the kind we want, skip ahead to the next one
6353 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6357 // simply scan ahead until we find a different texture or lightmap state
6358 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6360 // render the range of surfaces
6361 R_ProcessTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6365 float locboxvertex3f[6*4*3] =
6367 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6368 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6369 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6370 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6371 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6372 1,0,0, 0,0,0, 0,1,0, 1,1,0
6375 int locboxelement3i[6*2*3] =
6385 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6388 cl_locnode_t *loc = (cl_locnode_t *)ent;
6390 float vertex3f[6*4*3];
6392 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6393 GL_DepthMask(false);
6394 GL_DepthRange(0, 1);
6395 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6397 GL_CullFace(GL_NONE);
6398 R_Mesh_Matrix(&identitymatrix);
6400 R_Mesh_VertexPointer(vertex3f, 0, 0);
6401 R_Mesh_ColorPointer(NULL, 0, 0);
6402 R_Mesh_ResetTextureState();
6403 R_SetupGenericShader(false);
6406 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6407 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6408 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6409 surfacelist[0] < 0 ? 0.5f : 0.125f);
6411 if (VectorCompare(loc->mins, loc->maxs))
6413 VectorSet(size, 2, 2, 2);
6414 VectorMA(loc->mins, -0.5f, size, mins);
6418 VectorCopy(loc->mins, mins);
6419 VectorSubtract(loc->maxs, loc->mins, size);
6422 for (i = 0;i < 6*4*3;)
6423 for (j = 0;j < 3;j++, i++)
6424 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6426 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6429 void R_DrawLocs(void)
6432 cl_locnode_t *loc, *nearestloc;
6434 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6435 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6437 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6438 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6442 void R_DrawDebugModel(entity_render_t *ent)
6444 int i, j, k, l, flagsmask;
6445 const int *elements;
6447 msurface_t *surface;
6448 model_t *model = ent->model;
6451 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6453 R_Mesh_ColorPointer(NULL, 0, 0);
6454 R_Mesh_ResetTextureState();
6455 R_SetupGenericShader(false);
6456 GL_DepthRange(0, 1);
6457 GL_DepthTest(!r_showdisabledepthtest.integer);
6458 GL_DepthMask(false);
6459 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6461 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6463 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6464 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6466 if (brush->colbrushf && brush->colbrushf->numtriangles)
6468 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6469 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);
6470 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6473 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6475 if (surface->num_collisiontriangles)
6477 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6478 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);
6479 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6484 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6486 if (r_showtris.integer || r_shownormals.integer)
6488 if (r_showdisabledepthtest.integer)
6490 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6491 GL_DepthMask(false);
6495 GL_BlendFunc(GL_ONE, GL_ZERO);
6498 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6500 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
6502 rsurface.texture = surface->texture->currentframe;
6503 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6505 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6506 if (r_showtris.value > 0)
6508 if (!rsurface.texture->currentlayers->depthmask)
6509 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
6510 else if (ent == r_refdef.scene.worldentity)
6511 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
6513 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
6514 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6517 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6519 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6520 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6521 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6522 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6527 if (r_shownormals.value > 0)
6530 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6532 VectorCopy(rsurface.vertex3f + l * 3, v);
6533 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
6534 qglVertex3f(v[0], v[1], v[2]);
6535 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6536 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6537 qglVertex3f(v[0], v[1], v[2]);
6542 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6544 VectorCopy(rsurface.vertex3f + l * 3, v);
6545 GL_Color(0, r_refdef.view.colorscale, 0, 1);
6546 qglVertex3f(v[0], v[1], v[2]);
6547 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6548 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6549 qglVertex3f(v[0], v[1], v[2]);
6554 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6556 VectorCopy(rsurface.vertex3f + l * 3, v);
6557 GL_Color(0, 0, r_refdef.view.colorscale, 1);
6558 qglVertex3f(v[0], v[1], v[2]);
6559 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6560 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6561 qglVertex3f(v[0], v[1], v[2]);
6568 rsurface.texture = NULL;
6572 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6573 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6575 int i, j, endj, f, flagsmask;
6576 msurface_t *surface;
6578 model_t *model = r_refdef.scene.worldmodel;
6579 const int maxsurfacelist = 1024;
6580 int numsurfacelist = 0;
6581 msurface_t *surfacelist[1024];
6585 RSurf_ActiveWorldEntity();
6587 // update light styles on this submodel
6588 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6590 model_brush_lightstyleinfo_t *style;
6591 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6593 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6595 msurface_t *surfaces = model->data_surfaces;
6596 int *list = style->surfacelist;
6597 style->value = r_refdef.scene.lightstylevalue[style->style];
6598 for (j = 0;j < style->numsurfaces;j++)
6599 surfaces[list[j]].cached_dlight = true;
6604 R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
6605 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6609 R_DrawDebugModel(r_refdef.scene.worldentity);
6615 rsurface.uselightmaptexture = false;
6616 rsurface.texture = NULL;
6617 rsurface.rtlight = NULL;
6619 j = model->firstmodelsurface;
6620 endj = j + model->nummodelsurfaces;
6623 // quickly skip over non-visible surfaces
6624 for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++)
6626 // quickly iterate over visible surfaces
6627 for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++)
6629 // process this surface
6630 surface = model->data_surfaces + j;
6631 // if this surface fits the criteria, add it to the list
6632 if (surface->num_triangles)
6634 // if lightmap parameters changed, rebuild lightmap texture
6635 if (surface->cached_dlight)
6636 R_BuildLightMap(r_refdef.scene.worldentity, surface);
6637 // add face to draw list
6638 surfacelist[numsurfacelist++] = surface;
6639 r_refdef.stats.world_triangles += surface->num_triangles;
6640 if (numsurfacelist >= maxsurfacelist)
6642 r_refdef.stats.world_surfaces += numsurfacelist;
6643 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6649 r_refdef.stats.world_surfaces += numsurfacelist;
6651 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6652 GL_AlphaTest(false);
6655 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6657 int i, j, f, flagsmask;
6658 msurface_t *surface, *endsurface;
6660 model_t *model = ent->model;
6661 const int maxsurfacelist = 1024;
6662 int numsurfacelist = 0;
6663 msurface_t *surfacelist[1024];
6667 // if the model is static it doesn't matter what value we give for
6668 // wantnormals and wanttangents, so this logic uses only rules applicable
6669 // to a model, knowing that they are meaningless otherwise
6670 if (ent == r_refdef.scene.worldentity)
6671 RSurf_ActiveWorldEntity();
6672 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6673 RSurf_ActiveModelEntity(ent, false, false);
6675 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6677 // update light styles
6678 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6680 model_brush_lightstyleinfo_t *style;
6681 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6683 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6685 msurface_t *surfaces = model->data_surfaces;
6686 int *list = style->surfacelist;
6687 style->value = r_refdef.scene.lightstylevalue[style->style];
6688 for (j = 0;j < style->numsurfaces;j++)
6689 surfaces[list[j]].cached_dlight = true;
6694 R_UpdateAllTextureInfo(ent);
6695 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6699 R_DrawDebugModel(ent);
6705 rsurface.uselightmaptexture = false;
6706 rsurface.texture = NULL;
6707 rsurface.rtlight = NULL;
6709 surface = model->data_surfaces + model->firstmodelsurface;
6710 endsurface = surface + model->nummodelsurfaces;
6711 for (;surface < endsurface;surface++)
6713 // if this surface fits the criteria, add it to the list
6714 if (surface->num_triangles)
6716 // if lightmap parameters changed, rebuild lightmap texture
6717 if (surface->cached_dlight)
6718 R_BuildLightMap(ent, surface);
6719 // add face to draw list
6720 surfacelist[numsurfacelist++] = surface;
6721 r_refdef.stats.entities_triangles += surface->num_triangles;
6722 if (numsurfacelist >= maxsurfacelist)
6724 r_refdef.stats.entities_surfaces += numsurfacelist;
6725 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6730 r_refdef.stats.entities_surfaces += numsurfacelist;
6732 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6733 GL_AlphaTest(false);