2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; // used only by R_GetCurrentTexture
38 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
39 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
40 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
41 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
42 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)"};
43 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
44 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
45 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"};
46 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"};
47 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
48 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"};
49 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"};
50 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"};
51 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
52 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
53 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
54 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
55 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
56 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
57 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
58 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
59 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
60 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
61 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
62 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
63 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows DOWN, otherwise use the model lighting"};
64 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
65 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
66 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"};
67 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"};
68 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
69 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
71 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
72 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
73 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
74 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
75 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
76 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
77 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
78 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
80 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)"};
82 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
83 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)"};
84 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)"};
85 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
86 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
87 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
88 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
89 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)"};
90 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)"};
91 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)"};
92 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)"};
93 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)"};
95 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)"};
96 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
97 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"};
98 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
99 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
101 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
102 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
103 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
104 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
106 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
107 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
108 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
109 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
110 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
111 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
112 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
114 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
115 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
116 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
117 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)"};
119 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"};
121 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"};
123 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
125 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
126 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
127 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"};
128 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
129 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
130 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
131 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
133 extern cvar_t v_glslgamma;
135 extern qboolean v_flipped_state;
137 static struct r_bloomstate_s
142 int bloomwidth, bloomheight;
144 int screentexturewidth, screentextureheight;
145 rtexture_t *texture_screen;
147 int bloomtexturewidth, bloomtextureheight;
148 rtexture_t *texture_bloom;
150 // arrays for rendering the screen passes
151 float screentexcoord2f[8];
152 float bloomtexcoord2f[8];
153 float offsettexcoord2f[8];
157 r_waterstate_t r_waterstate;
159 // shadow volume bsp struct with automatically growing nodes buffer
162 rtexture_t *r_texture_blanknormalmap;
163 rtexture_t *r_texture_white;
164 rtexture_t *r_texture_grey128;
165 rtexture_t *r_texture_black;
166 rtexture_t *r_texture_notexture;
167 rtexture_t *r_texture_whitecube;
168 rtexture_t *r_texture_normalizationcube;
169 rtexture_t *r_texture_fogattenuation;
170 rtexture_t *r_texture_gammaramps;
171 unsigned int r_texture_gammaramps_serial;
172 //rtexture_t *r_texture_fogintensity;
174 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
175 unsigned int r_numqueries;
176 unsigned int r_maxqueries;
178 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
179 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
181 // vertex coordinates for a quad that covers the screen exactly
182 const static float r_screenvertex3f[12] =
190 extern void R_DrawModelShadows(void);
192 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
195 for (i = 0;i < verts;i++)
206 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
209 for (i = 0;i < verts;i++)
219 // FIXME: move this to client?
222 if (gamemode == GAME_NEHAHRA)
224 Cvar_Set("gl_fogenable", "0");
225 Cvar_Set("gl_fogdensity", "0.2");
226 Cvar_Set("gl_fogred", "0.3");
227 Cvar_Set("gl_foggreen", "0.3");
228 Cvar_Set("gl_fogblue", "0.3");
230 r_refdef.fog_density = 0;
231 r_refdef.fog_red = 0;
232 r_refdef.fog_green = 0;
233 r_refdef.fog_blue = 0;
234 r_refdef.fog_alpha = 1;
235 r_refdef.fog_start = 0;
236 r_refdef.fog_end = 0;
239 float FogForDistance(vec_t dist)
241 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
242 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
245 float FogPoint_World(const vec3_t p)
247 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
250 float FogPoint_Model(const vec3_t p)
252 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
255 static void R_BuildBlankTextures(void)
257 unsigned char data[4];
258 data[2] = 128; // normal X
259 data[1] = 128; // normal Y
260 data[0] = 255; // normal Z
261 data[3] = 128; // height
262 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
267 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
272 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
277 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
280 static void R_BuildNoTexture(void)
283 unsigned char pix[16][16][4];
284 // this makes a light grey/dark grey checkerboard texture
285 for (y = 0;y < 16;y++)
287 for (x = 0;x < 16;x++)
289 if ((y < 8) ^ (x < 8))
305 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
308 static void R_BuildWhiteCube(void)
310 unsigned char data[6*1*1*4];
311 memset(data, 255, sizeof(data));
312 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
315 static void R_BuildNormalizationCube(void)
319 vec_t s, t, intensity;
321 unsigned char data[6][NORMSIZE][NORMSIZE][4];
322 for (side = 0;side < 6;side++)
324 for (y = 0;y < NORMSIZE;y++)
326 for (x = 0;x < NORMSIZE;x++)
328 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
329 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
364 intensity = 127.0f / sqrt(DotProduct(v, v));
365 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
366 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
367 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
368 data[side][y][x][3] = 255;
372 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
375 static void R_BuildFogTexture(void)
379 unsigned char data1[FOGWIDTH][4];
380 //unsigned char data2[FOGWIDTH][4];
383 r_refdef.fogmasktable_start = r_refdef.fog_start;
384 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
385 r_refdef.fogmasktable_range = r_refdef.fogrange;
386 r_refdef.fogmasktable_density = r_refdef.fog_density;
388 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
389 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
391 d = (x * r - r_refdef.fogmasktable_start);
392 if(developer.integer >= 100)
393 Con_Printf("%f ", d);
395 if (r_fog_exp2.integer)
396 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
398 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
399 if(developer.integer >= 100)
400 Con_Printf(" : %f ", alpha);
401 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
402 if(developer.integer >= 100)
403 Con_Printf(" = %f\n", alpha);
404 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
407 for (x = 0;x < FOGWIDTH;x++)
409 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
414 //data2[x][0] = 255 - b;
415 //data2[x][1] = 255 - b;
416 //data2[x][2] = 255 - b;
419 if (r_texture_fogattenuation)
421 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
422 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
426 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);
427 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
431 static const char *builtinshaderstring =
432 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
433 "// written by Forest 'LordHavoc' Hale\n"
435 "// common definitions between vertex shader and fragment shader:\n"
437 "//#ifdef __GLSL_CG_DATA_TYPES\n"
438 "//# define myhalf half\n"
439 "//# define myhalf2 half2\n"
440 "//# define myhalf3 half3\n"
441 "//# define myhalf4 half4\n"
443 "# define myhalf float\n"
444 "# define myhalf2 vec2\n"
445 "# define myhalf3 vec3\n"
446 "# define myhalf4 vec4\n"
449 "#ifdef MODE_DEPTH_OR_SHADOW\n"
451 "# ifdef VERTEX_SHADER\n"
454 " gl_Position = ftransform();\n"
460 "#ifdef MODE_POSTPROCESS\n"
461 "# ifdef VERTEX_SHADER\n"
464 " gl_FrontColor = gl_Color;\n"
465 " gl_Position = ftransform();\n"
466 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
468 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
472 "# ifdef FRAGMENT_SHADER\n"
474 "uniform sampler2D Texture_First;\n"
476 "uniform sampler2D Texture_Second;\n"
478 "#ifdef USEGAMMARAMPS\n"
479 "uniform sampler2D Texture_GammaRamps;\n"
481 "#ifdef USESATURATION\n"
482 "uniform float Saturation;\n"
484 "#ifdef USEVERTEXTEXTUREBLEND\n"
485 "uniform vec4 TintColor;\n"
487 "#ifdef USECOLORMOD\n"
488 "uniform vec3 Gamma;\n"
490 "//uncomment these if you want to use them:\n"
491 "uniform vec4 UserVec1;\n"
492 "// uniform vec4 UserVec2;\n"
493 "// uniform vec4 UserVec3;\n"
494 "// uniform vec4 UserVec4;\n"
495 "// uniform float ClientTime;\n"
496 "uniform vec2 PixelSize;\n"
499 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
501 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
503 "#ifdef USEVERTEXTEXTUREBLEND\n"
504 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
507 "#ifdef USEPOSTPROCESSING\n"
508 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
509 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
510 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
511 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
512 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
513 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
514 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
515 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
518 "#ifdef USESATURATION\n"
519 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
520 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
521 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
522 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" // TODO: test this on ATI
525 "#ifdef USEGAMMARAMPS\n"
526 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
527 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
528 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
535 "#ifdef MODE_GENERIC\n"
536 "# ifdef VERTEX_SHADER\n"
539 " gl_FrontColor = gl_Color;\n"
540 "# ifdef USEDIFFUSE\n"
541 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
543 "# ifdef USESPECULAR\n"
544 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
546 " gl_Position = ftransform();\n"
549 "# ifdef FRAGMENT_SHADER\n"
551 "# ifdef USEDIFFUSE\n"
552 "uniform sampler2D Texture_First;\n"
554 "# ifdef USESPECULAR\n"
555 "uniform sampler2D Texture_Second;\n"
560 " gl_FragColor = gl_Color;\n"
561 "# ifdef USEDIFFUSE\n"
562 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
565 "# ifdef USESPECULAR\n"
566 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
568 "# ifdef USECOLORMAPPING\n"
569 " gl_FragColor *= tex2;\n"
572 " gl_FragColor += tex2;\n"
574 "# ifdef USEVERTEXTEXTUREBLEND\n"
575 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
580 "#else // !MODE_GENERIC\n"
582 "varying vec2 TexCoord;\n"
583 "varying vec2 TexCoordLightmap;\n"
585 "#ifdef MODE_LIGHTSOURCE\n"
586 "varying vec3 CubeVector;\n"
589 "#ifdef MODE_LIGHTSOURCE\n"
590 "varying vec3 LightVector;\n"
592 "#ifdef MODE_LIGHTDIRECTION\n"
593 "varying vec3 LightVector;\n"
596 "varying vec3 EyeVector;\n"
598 "varying vec3 EyeVectorModelSpace;\n"
601 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
602 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
603 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
605 "#ifdef MODE_WATER\n"
606 "varying vec4 ModelViewProjectionPosition;\n"
608 "#ifdef MODE_REFRACTION\n"
609 "varying vec4 ModelViewProjectionPosition;\n"
611 "#ifdef USEREFLECTION\n"
612 "varying vec4 ModelViewProjectionPosition;\n"
619 "// vertex shader specific:\n"
620 "#ifdef VERTEX_SHADER\n"
622 "uniform vec3 LightPosition;\n"
623 "uniform vec3 EyePosition;\n"
624 "uniform vec3 LightDir;\n"
626 "// 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"
630 " gl_FrontColor = gl_Color;\n"
631 " // copy the surface texcoord\n"
632 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
633 "#ifndef MODE_LIGHTSOURCE\n"
634 "# ifndef MODE_LIGHTDIRECTION\n"
635 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
639 "#ifdef MODE_LIGHTSOURCE\n"
640 " // transform vertex position into light attenuation/cubemap space\n"
641 " // (-1 to +1 across the light box)\n"
642 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
644 " // transform unnormalized light direction into tangent space\n"
645 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
646 " // normalize it per pixel)\n"
647 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
648 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
649 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
650 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
653 "#ifdef MODE_LIGHTDIRECTION\n"
654 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
655 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
656 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
659 " // transform unnormalized eye direction into tangent space\n"
661 " vec3 EyeVectorModelSpace;\n"
663 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
664 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
665 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
666 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
668 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
669 " VectorS = gl_MultiTexCoord1.xyz;\n"
670 " VectorT = gl_MultiTexCoord2.xyz;\n"
671 " VectorR = gl_MultiTexCoord3.xyz;\n"
674 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
675 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
676 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
677 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
680 "// transform vertex to camera space, using ftransform to match non-VS\n"
682 " gl_Position = ftransform();\n"
684 "#ifdef MODE_WATER\n"
685 " ModelViewProjectionPosition = gl_Position;\n"
687 "#ifdef MODE_REFRACTION\n"
688 " ModelViewProjectionPosition = gl_Position;\n"
690 "#ifdef USEREFLECTION\n"
691 " ModelViewProjectionPosition = gl_Position;\n"
695 "#endif // VERTEX_SHADER\n"
700 "// fragment shader specific:\n"
701 "#ifdef FRAGMENT_SHADER\n"
703 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
704 "uniform sampler2D Texture_Normal;\n"
705 "uniform sampler2D Texture_Color;\n"
706 "uniform sampler2D Texture_Gloss;\n"
707 "uniform sampler2D Texture_Glow;\n"
708 "uniform sampler2D Texture_SecondaryNormal;\n"
709 "uniform sampler2D Texture_SecondaryColor;\n"
710 "uniform sampler2D Texture_SecondaryGloss;\n"
711 "uniform sampler2D Texture_SecondaryGlow;\n"
712 "uniform sampler2D Texture_Pants;\n"
713 "uniform sampler2D Texture_Shirt;\n"
714 "uniform sampler2D Texture_FogMask;\n"
715 "uniform sampler2D Texture_Lightmap;\n"
716 "uniform sampler2D Texture_Deluxemap;\n"
717 "uniform sampler2D Texture_Refraction;\n"
718 "uniform sampler2D Texture_Reflection;\n"
719 "uniform sampler2D Texture_Attenuation;\n"
720 "uniform samplerCube Texture_Cube;\n"
722 "uniform myhalf3 LightColor;\n"
723 "uniform myhalf3 AmbientColor;\n"
724 "uniform myhalf3 DiffuseColor;\n"
725 "uniform myhalf3 SpecularColor;\n"
726 "uniform myhalf3 Color_Pants;\n"
727 "uniform myhalf3 Color_Shirt;\n"
728 "uniform myhalf3 FogColor;\n"
730 "uniform myhalf4 TintColor;\n"
733 "//#ifdef MODE_WATER\n"
734 "uniform vec4 DistortScaleRefractReflect;\n"
735 "uniform vec4 ScreenScaleRefractReflect;\n"
736 "uniform vec4 ScreenCenterRefractReflect;\n"
737 "uniform myhalf4 RefractColor;\n"
738 "uniform myhalf4 ReflectColor;\n"
739 "uniform myhalf ReflectFactor;\n"
740 "uniform myhalf ReflectOffset;\n"
742 "//# ifdef MODE_REFRACTION\n"
743 "//uniform vec4 DistortScaleRefractReflect;\n"
744 "//uniform vec4 ScreenScaleRefractReflect;\n"
745 "//uniform vec4 ScreenCenterRefractReflect;\n"
746 "//uniform myhalf4 RefractColor;\n"
747 "//# ifdef USEREFLECTION\n"
748 "//uniform myhalf4 ReflectColor;\n"
751 "//# ifdef USEREFLECTION\n"
752 "//uniform vec4 DistortScaleRefractReflect;\n"
753 "//uniform vec4 ScreenScaleRefractReflect;\n"
754 "//uniform vec4 ScreenCenterRefractReflect;\n"
755 "//uniform myhalf4 ReflectColor;\n"
760 "uniform myhalf GlowScale;\n"
761 "uniform myhalf SceneBrightness;\n"
762 "#ifdef USECONTRASTBOOST\n"
763 "uniform myhalf ContrastBoostCoeff;\n"
766 "uniform float OffsetMapping_Scale;\n"
767 "uniform float OffsetMapping_Bias;\n"
768 "uniform float FogRangeRecip;\n"
770 "uniform myhalf AmbientScale;\n"
771 "uniform myhalf DiffuseScale;\n"
772 "uniform myhalf SpecularScale;\n"
773 "uniform myhalf SpecularPower;\n"
775 "#ifdef USEOFFSETMAPPING\n"
776 "vec2 OffsetMapping(vec2 TexCoord)\n"
778 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
779 " // 14 sample relief mapping: linear search and then binary search\n"
780 " // this basically steps forward a small amount repeatedly until it finds\n"
781 " // itself inside solid, then jitters forward and back using decreasing\n"
782 " // amounts to find the impact\n"
783 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
784 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
785 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
786 " vec3 RT = vec3(TexCoord, 1);\n"
787 " OffsetVector *= 0.1;\n"
788 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
789 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
798 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
799 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
800 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
801 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
804 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
805 " // this basically moves forward the full distance, and then backs up based\n"
806 " // on height of samples\n"
807 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
808 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
809 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
810 " TexCoord += OffsetVector;\n"
811 " OffsetVector *= 0.333;\n"
812 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
813 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
814 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
815 " return TexCoord;\n"
818 "#endif // USEOFFSETMAPPING\n"
820 "#ifdef MODE_WATER\n"
825 "#ifdef USEOFFSETMAPPING\n"
826 " // apply offsetmapping\n"
827 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
828 "#define TexCoord TexCoordOffset\n"
831 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
832 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
833 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
834 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
835 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
838 "#else // !MODE_WATER\n"
839 "#ifdef MODE_REFRACTION\n"
841 "// refraction pass\n"
844 "#ifdef USEOFFSETMAPPING\n"
845 " // apply offsetmapping\n"
846 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
847 "#define TexCoord TexCoordOffset\n"
850 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
851 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
852 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
853 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
856 "#else // !MODE_REFRACTION\n"
859 "#ifdef USEOFFSETMAPPING\n"
860 " // apply offsetmapping\n"
861 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
862 "#define TexCoord TexCoordOffset\n"
865 " // combine the diffuse textures (base, pants, shirt)\n"
866 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
867 "#ifdef USECOLORMAPPING\n"
868 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
870 "#ifdef USEVERTEXTEXTUREBLEND\n"
871 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
872 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
873 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
874 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord)), color.rgb, terrainblend);\n"
876 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
879 "#ifdef USEDIFFUSE\n"
880 " // get the surface normal and the gloss color\n"
881 "# ifdef USEVERTEXTEXTUREBLEND\n"
882 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
883 "# ifdef USESPECULAR\n"
884 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
887 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
888 "# ifdef USESPECULAR\n"
889 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
896 "#ifdef MODE_LIGHTSOURCE\n"
899 " // calculate surface normal, light normal, and specular normal\n"
900 " // compute color intensity for the two textures (colormap and glossmap)\n"
901 " // scale by light color and attenuation as efficiently as possible\n"
902 " // (do as much scalar math as possible rather than vector math)\n"
903 "# ifdef USEDIFFUSE\n"
904 " // get the light normal\n"
905 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
907 "# ifdef USESPECULAR\n"
908 "# ifndef USEEXACTSPECULARMATH\n"
909 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
912 " // calculate directional shading\n"
913 "# ifdef USEEXACTSPECULARMATH\n"
914 " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n"
916 " 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"
919 "# ifdef USEDIFFUSE\n"
920 " // calculate directional shading\n"
921 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
923 " // calculate directionless shading\n"
924 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
928 "# ifdef USECUBEFILTER\n"
929 " // apply light cubemap filter\n"
930 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
931 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
933 "#endif // MODE_LIGHTSOURCE\n"
938 "#ifdef MODE_LIGHTDIRECTION\n"
939 " // directional model lighting\n"
940 "# ifdef USEDIFFUSE\n"
941 " // get the light normal\n"
942 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
944 "# ifdef USESPECULAR\n"
945 " // calculate directional shading\n"
946 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
947 "# ifdef USEEXACTSPECULARMATH\n"
948 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
950 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
951 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
954 "# ifdef USEDIFFUSE\n"
956 " // calculate directional shading\n"
957 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
959 " color.rgb *= AmbientColor;\n"
962 "#endif // MODE_LIGHTDIRECTION\n"
967 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
968 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
970 " // get the light normal\n"
971 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
972 " myhalf3 diffusenormal;\n"
973 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
974 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
975 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
976 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
977 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
978 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
979 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
980 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
981 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
982 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
983 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
984 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
985 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
986 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
987 "# ifdef USESPECULAR\n"
988 "# ifdef USEEXACTSPECULARMATH\n"
989 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
991 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
992 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
996 " // apply lightmap color\n"
997 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
998 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1003 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1004 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1006 " // get the light normal\n"
1007 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1008 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1009 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1010 "# ifdef USESPECULAR\n"
1011 "# ifdef USEEXACTSPECULARMATH\n"
1012 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1014 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1015 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1019 " // apply lightmap color\n"
1020 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1021 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1026 "#ifdef MODE_LIGHTMAP\n"
1027 " // apply lightmap color\n"
1028 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1029 "#endif // MODE_LIGHTMAP\n"
1034 "#ifdef MODE_VERTEXCOLOR\n"
1035 " // apply lightmap color\n"
1036 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1037 "#endif // MODE_VERTEXCOLOR\n"
1042 "#ifdef MODE_FLATCOLOR\n"
1043 "#endif // MODE_FLATCOLOR\n"
1051 " color *= TintColor;\n"
1054 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1057 "#ifdef USECONTRASTBOOST\n"
1058 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1061 " color.rgb *= SceneBrightness;\n"
1063 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1065 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1068 " // 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"
1069 "#ifdef USEREFLECTION\n"
1070 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1071 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1072 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1073 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1076 " gl_FragColor = vec4(color);\n"
1078 "#endif // !MODE_REFRACTION\n"
1079 "#endif // !MODE_WATER\n"
1081 "#endif // FRAGMENT_SHADER\n"
1083 "#endif // !MODE_GENERIC\n"
1084 "#endif // !MODE_POSTPROCESS\n"
1085 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1088 typedef struct shaderpermutationinfo_s
1090 const char *pretext;
1093 shaderpermutationinfo_t;
1095 typedef struct shadermodeinfo_s
1097 const char *vertexfilename;
1098 const char *geometryfilename;
1099 const char *fragmentfilename;
1100 const char *pretext;
1105 typedef enum shaderpermutation_e
1107 SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
1108 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1109 SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
1110 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1111 SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
1112 SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
1113 SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
1114 SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
1115 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, // (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1116 SHADERPERMUTATION_REFLECTION = 1<<9, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1117 SHADERPERMUTATION_OFFSETMAPPING = 1<<10, // adjust texcoords to roughly simulate a displacement mapped surface
1118 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1119 SHADERPERMUTATION_GAMMARAMPS = 1<<12, // gamma (postprocessing only)
1120 SHADERPERMUTATION_POSTPROCESSING = 1<<13, // user defined postprocessing
1121 SHADERPERMUTATION_SATURATION = 1<<14, // user defined postprocessing
1122 SHADERPERMUTATION_LIMIT = 1<<15, // size of permutations array
1123 SHADERPERMUTATION_COUNT = 15 // size of shaderpermutationinfo array
1125 shaderpermutation_t;
1127 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1128 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1130 {"#define USEDIFFUSE\n", " diffuse"},
1131 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1132 {"#define USECOLORMAPPING\n", " colormapping"},
1133 {"#define USECONTRASTBOOST\n", " contrastboost"},
1134 {"#define USEFOG\n", " fog"},
1135 {"#define USECUBEFILTER\n", " cubefilter"},
1136 {"#define USEGLOW\n", " glow"},
1137 {"#define USESPECULAR\n", " specular"},
1138 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1139 {"#define USEREFLECTION\n", " reflection"},
1140 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1141 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1142 {"#define USEGAMMARAMPS\n", " gammaramps"},
1143 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1144 {"#define USESATURATION\n", " saturation"},
1147 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
1148 typedef enum shadermode_e
1150 SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
1151 SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
1152 SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
1153 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1154 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
1155 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1156 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1157 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1158 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1159 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
1160 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
1161 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1166 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1167 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1169 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1170 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1171 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1172 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1173 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1174 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1175 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1176 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1177 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1178 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1179 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1180 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1183 typedef struct r_glsl_permutation_s
1185 // indicates if we have tried compiling this permutation already
1187 // 0 if compilation failed
1189 // locations of detected uniforms in program object, or -1 if not found
1190 int loc_Texture_First;
1191 int loc_Texture_Second;
1192 int loc_Texture_GammaRamps;
1193 int loc_Texture_Normal;
1194 int loc_Texture_Color;
1195 int loc_Texture_Gloss;
1196 int loc_Texture_Glow;
1197 int loc_Texture_SecondaryNormal;
1198 int loc_Texture_SecondaryColor;
1199 int loc_Texture_SecondaryGloss;
1200 int loc_Texture_SecondaryGlow;
1201 int loc_Texture_Pants;
1202 int loc_Texture_Shirt;
1203 int loc_Texture_FogMask;
1204 int loc_Texture_Lightmap;
1205 int loc_Texture_Deluxemap;
1206 int loc_Texture_Attenuation;
1207 int loc_Texture_Cube;
1208 int loc_Texture_Refraction;
1209 int loc_Texture_Reflection;
1211 int loc_LightPosition;
1212 int loc_EyePosition;
1213 int loc_Color_Pants;
1214 int loc_Color_Shirt;
1215 int loc_FogRangeRecip;
1216 int loc_AmbientScale;
1217 int loc_DiffuseScale;
1218 int loc_SpecularScale;
1219 int loc_SpecularPower;
1221 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1222 int loc_OffsetMapping_Scale;
1224 int loc_AmbientColor;
1225 int loc_DiffuseColor;
1226 int loc_SpecularColor;
1228 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1229 int loc_GammaCoeff; // 1 / gamma
1230 int loc_DistortScaleRefractReflect;
1231 int loc_ScreenScaleRefractReflect;
1232 int loc_ScreenCenterRefractReflect;
1233 int loc_RefractColor;
1234 int loc_ReflectColor;
1235 int loc_ReflectFactor;
1236 int loc_ReflectOffset;
1245 r_glsl_permutation_t;
1247 // information about each possible shader permutation
1248 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1249 // currently selected permutation
1250 r_glsl_permutation_t *r_glsl_permutation;
1252 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1255 if (!filename || !filename[0])
1257 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1260 if (printfromdisknotice)
1261 Con_DPrint("from disk... ");
1262 return shaderstring;
1264 else if (!strcmp(filename, "glsl/default.glsl"))
1266 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1267 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1269 return shaderstring;
1272 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1275 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1276 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1277 int vertstrings_count = 0;
1278 int geomstrings_count = 0;
1279 int fragstrings_count = 0;
1280 char *vertexstring, *geometrystring, *fragmentstring;
1281 const char *vertstrings_list[32+3];
1282 const char *geomstrings_list[32+3];
1283 const char *fragstrings_list[32+3];
1284 char permutationname[256];
1291 permutationname[0] = 0;
1292 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1293 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1294 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1296 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1298 // the first pretext is which type of shader to compile as
1299 // (later these will all be bound together as a program object)
1300 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1301 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1302 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1304 // the second pretext is the mode (for example a light source)
1305 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1306 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1307 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1308 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1310 // now add all the permutation pretexts
1311 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1313 if (permutation & (1<<i))
1315 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1316 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1317 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1318 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1322 // keep line numbers correct
1323 vertstrings_list[vertstrings_count++] = "\n";
1324 geomstrings_list[geomstrings_count++] = "\n";
1325 fragstrings_list[fragstrings_count++] = "\n";
1329 // now append the shader text itself
1330 vertstrings_list[vertstrings_count++] = vertexstring;
1331 geomstrings_list[geomstrings_count++] = geometrystring;
1332 fragstrings_list[fragstrings_count++] = fragmentstring;
1334 // if any sources were NULL, clear the respective list
1336 vertstrings_count = 0;
1337 if (!geometrystring)
1338 geomstrings_count = 0;
1339 if (!fragmentstring)
1340 fragstrings_count = 0;
1342 // compile the shader program
1343 if (vertstrings_count + geomstrings_count + fragstrings_count)
1344 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1348 qglUseProgramObjectARB(p->program);CHECKGLERROR
1349 // look up all the uniform variable names we care about, so we don't
1350 // have to look them up every time we set them
1351 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1352 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1353 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1354 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1355 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1356 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1357 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1358 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1359 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1360 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1361 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1362 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1363 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1364 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1365 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1366 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1367 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1368 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1369 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1370 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1371 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1372 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1373 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1374 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1375 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1376 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1377 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1378 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1379 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1380 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1381 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1382 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1383 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1384 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1385 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1386 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1387 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1388 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1389 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1390 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1391 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1392 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1393 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1394 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1395 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1396 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1397 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1398 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1399 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1400 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1401 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1402 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1403 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1404 // initialize the samplers to refer to the texture units we use
1405 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1406 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1407 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1408 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1409 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1410 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1411 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1412 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1413 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1414 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1415 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1416 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1417 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1418 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1419 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1420 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1421 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1422 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1423 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1424 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1426 if (developer.integer)
1427 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1430 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1434 Mem_Free(vertexstring);
1436 Mem_Free(geometrystring);
1438 Mem_Free(fragmentstring);
1441 void R_GLSL_Restart_f(void)
1444 unsigned int permutation;
1445 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1446 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1447 if (r_glsl_permutations[mode][permutation].program)
1448 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1449 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1452 void R_GLSL_DumpShader_f(void)
1456 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1459 Con_Printf("failed to write to glsl/default.glsl\n");
1463 FS_Print(file, "// The engine may define the following macros:\n");
1464 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1465 for (i = 0;i < SHADERMODE_COUNT;i++)
1466 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1467 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1468 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1469 FS_Print(file, "\n");
1470 FS_Print(file, builtinshaderstring);
1473 Con_Printf("glsl/default.glsl written\n");
1476 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1478 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1479 if (r_glsl_permutation != perm)
1481 r_glsl_permutation = perm;
1482 if (!r_glsl_permutation->program)
1484 if (!r_glsl_permutation->compiled)
1485 R_GLSL_CompilePermutation(mode, permutation);
1486 if (!r_glsl_permutation->program)
1488 // remove features until we find a valid permutation
1490 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1492 // reduce i more quickly whenever it would not remove any bits
1493 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1494 if (!(permutation & j))
1497 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1498 if (!r_glsl_permutation->compiled)
1499 R_GLSL_CompilePermutation(mode, permutation);
1500 if (r_glsl_permutation->program)
1503 if (i >= SHADERPERMUTATION_COUNT)
1505 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");
1506 Cvar_SetValueQuick(&r_glsl, 0);
1507 R_GLSL_Restart_f(); // unload shaders
1508 return; // no bit left to clear
1513 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1517 void R_SetupGenericShader(qboolean usetexture)
1519 if (gl_support_fragment_shader)
1521 if (r_glsl.integer && r_glsl_usegeneric.integer)
1522 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1523 else if (r_glsl_permutation)
1525 r_glsl_permutation = NULL;
1526 qglUseProgramObjectARB(0);CHECKGLERROR
1531 void R_SetupGenericTwoTextureShader(int texturemode)
1533 if (gl_support_fragment_shader)
1535 if (r_glsl.integer && r_glsl_usegeneric.integer)
1536 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1537 else if (r_glsl_permutation)
1539 r_glsl_permutation = NULL;
1540 qglUseProgramObjectARB(0);CHECKGLERROR
1543 if (!r_glsl_permutation)
1545 if (texturemode == GL_DECAL && gl_combine.integer)
1546 texturemode = GL_INTERPOLATE_ARB;
1547 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1551 void R_SetupDepthOrShadowShader(void)
1553 if (gl_support_fragment_shader)
1555 if (r_glsl.integer && r_glsl_usegeneric.integer)
1556 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1557 else if (r_glsl_permutation)
1559 r_glsl_permutation = NULL;
1560 qglUseProgramObjectARB(0);CHECKGLERROR
1565 extern rtexture_t *r_shadow_attenuationgradienttexture;
1566 extern rtexture_t *r_shadow_attenuation2dtexture;
1567 extern rtexture_t *r_shadow_attenuation3dtexture;
1568 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1570 // select a permutation of the lighting shader appropriate to this
1571 // combination of texture, entity, light source, and fogging, only use the
1572 // minimum features necessary to avoid wasting rendering time in the
1573 // fragment shader on features that are not being used
1574 unsigned int permutation = 0;
1575 unsigned int mode = 0;
1576 // TODO: implement geometry-shader based shadow volumes someday
1577 if (r_glsl_offsetmapping.integer)
1579 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1580 if (r_glsl_offsetmapping_reliefmapping.integer)
1581 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1583 if (rsurfacepass == RSURFPASS_BACKGROUND)
1585 // distorted background
1586 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1587 mode = SHADERMODE_WATER;
1589 mode = SHADERMODE_REFRACTION;
1591 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1594 mode = SHADERMODE_LIGHTSOURCE;
1595 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1596 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1597 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1598 permutation |= SHADERPERMUTATION_CUBEFILTER;
1599 if (diffusescale > 0)
1600 permutation |= SHADERPERMUTATION_DIFFUSE;
1601 if (specularscale > 0)
1602 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1603 if (r_refdef.fogenabled)
1604 permutation |= SHADERPERMUTATION_FOG;
1605 if (rsurface.texture->colormapping)
1606 permutation |= SHADERPERMUTATION_COLORMAPPING;
1607 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1608 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1610 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1612 // unshaded geometry (fullbright or ambient model lighting)
1613 mode = SHADERMODE_FLATCOLOR;
1614 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1615 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1616 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1617 permutation |= SHADERPERMUTATION_GLOW;
1618 if (r_refdef.fogenabled)
1619 permutation |= SHADERPERMUTATION_FOG;
1620 if (rsurface.texture->colormapping)
1621 permutation |= SHADERPERMUTATION_COLORMAPPING;
1622 if (r_glsl_offsetmapping.integer)
1624 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1625 if (r_glsl_offsetmapping_reliefmapping.integer)
1626 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1628 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1629 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1630 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1631 permutation |= SHADERPERMUTATION_REFLECTION;
1633 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1635 // directional model lighting
1636 mode = SHADERMODE_LIGHTDIRECTION;
1637 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1638 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1639 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1640 permutation |= SHADERPERMUTATION_GLOW;
1641 permutation |= SHADERPERMUTATION_DIFFUSE;
1642 if (specularscale > 0)
1643 permutation |= SHADERPERMUTATION_SPECULAR;
1644 if (r_refdef.fogenabled)
1645 permutation |= SHADERPERMUTATION_FOG;
1646 if (rsurface.texture->colormapping)
1647 permutation |= SHADERPERMUTATION_COLORMAPPING;
1648 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1649 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1650 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1651 permutation |= SHADERPERMUTATION_REFLECTION;
1653 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1655 // ambient model lighting
1656 mode = SHADERMODE_LIGHTDIRECTION;
1657 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1658 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1659 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1660 permutation |= SHADERPERMUTATION_GLOW;
1661 if (r_refdef.fogenabled)
1662 permutation |= SHADERPERMUTATION_FOG;
1663 if (rsurface.texture->colormapping)
1664 permutation |= SHADERPERMUTATION_COLORMAPPING;
1665 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1666 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1667 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1668 permutation |= SHADERPERMUTATION_REFLECTION;
1673 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1675 // deluxemapping (light direction texture)
1676 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1677 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1679 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1680 permutation |= SHADERPERMUTATION_DIFFUSE;
1681 if (specularscale > 0)
1682 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1684 else if (r_glsl_deluxemapping.integer >= 2)
1686 // fake deluxemapping (uniform light direction in tangentspace)
1687 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1688 permutation |= SHADERPERMUTATION_DIFFUSE;
1689 if (specularscale > 0)
1690 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1692 else if (rsurface.uselightmaptexture)
1694 // ordinary lightmapping (q1bsp, q3bsp)
1695 mode = SHADERMODE_LIGHTMAP;
1699 // ordinary vertex coloring (q3bsp)
1700 mode = SHADERMODE_VERTEXCOLOR;
1702 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1703 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1704 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1705 permutation |= SHADERPERMUTATION_GLOW;
1706 if (r_refdef.fogenabled)
1707 permutation |= SHADERPERMUTATION_FOG;
1708 if (rsurface.texture->colormapping)
1709 permutation |= SHADERPERMUTATION_COLORMAPPING;
1710 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1711 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1712 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1713 permutation |= SHADERPERMUTATION_REFLECTION;
1715 if(permutation & SHADERPERMUTATION_SPECULAR)
1716 if(r_shadow_glossexact.integer)
1717 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
1718 R_SetupShader_SetPermutation(mode, permutation);
1719 if (mode == SHADERMODE_LIGHTSOURCE)
1721 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1722 if (permutation & SHADERPERMUTATION_DIFFUSE)
1724 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1725 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1726 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1727 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1731 // ambient only is simpler
1732 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]);
1733 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1734 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1735 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1737 // additive passes are only darkened by fog, not tinted
1738 if (r_glsl_permutation->loc_FogColor >= 0)
1739 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1743 if (mode == SHADERMODE_LIGHTDIRECTION)
1745 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);
1746 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);
1747 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);
1748 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]);
1752 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
1753 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1754 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1756 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]);
1757 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1758 // additive passes are only darkened by fog, not tinted
1759 if (r_glsl_permutation->loc_FogColor >= 0)
1761 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1762 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1764 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1766 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);
1767 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]);
1768 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]);
1769 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1770 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1771 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1772 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1774 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1776 // The formula used is actually:
1777 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1778 // color.rgb *= SceneBrightness;
1780 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1781 // and do [[calculations]] here in the engine
1782 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1783 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1786 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1787 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1788 if (r_glsl_permutation->loc_Color_Pants >= 0)
1790 if (rsurface.texture->currentskinframe->pants)
1791 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1793 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1795 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1797 if (rsurface.texture->currentskinframe->shirt)
1798 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1800 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1802 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
1803 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
1805 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
1809 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1811 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1815 #define SKINFRAME_HASH 1024
1819 int loadsequence; // incremented each level change
1820 memexpandablearray_t array;
1821 skinframe_t *hash[SKINFRAME_HASH];
1824 r_skinframe_t r_skinframe;
1826 void R_SkinFrame_PrepareForPurge(void)
1828 r_skinframe.loadsequence++;
1829 // wrap it without hitting zero
1830 if (r_skinframe.loadsequence >= 200)
1831 r_skinframe.loadsequence = 1;
1834 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1838 // mark the skinframe as used for the purging code
1839 skinframe->loadsequence = r_skinframe.loadsequence;
1842 void R_SkinFrame_Purge(void)
1846 for (i = 0;i < SKINFRAME_HASH;i++)
1848 for (s = r_skinframe.hash[i];s;s = s->next)
1850 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1852 if (s->merged == s->base)
1854 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1855 R_PurgeTexture(s->stain );s->stain = NULL;
1856 R_PurgeTexture(s->merged);s->merged = NULL;
1857 R_PurgeTexture(s->base );s->base = NULL;
1858 R_PurgeTexture(s->pants );s->pants = NULL;
1859 R_PurgeTexture(s->shirt );s->shirt = NULL;
1860 R_PurgeTexture(s->nmap );s->nmap = NULL;
1861 R_PurgeTexture(s->gloss );s->gloss = NULL;
1862 R_PurgeTexture(s->glow );s->glow = NULL;
1863 R_PurgeTexture(s->fog );s->fog = NULL;
1864 s->loadsequence = 0;
1870 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1872 char basename[MAX_QPATH];
1874 Image_StripImageExtension(name, basename, sizeof(basename));
1876 if( last == NULL ) {
1878 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1879 item = r_skinframe.hash[hashindex];
1884 // linearly search through the hash bucket
1885 for( ; item ; item = item->next ) {
1886 if( !strcmp( item->basename, basename ) ) {
1893 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1897 char basename[MAX_QPATH];
1899 Image_StripImageExtension(name, basename, sizeof(basename));
1901 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1902 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1903 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1907 rtexture_t *dyntexture;
1908 // check whether its a dynamic texture
1909 dyntexture = CL_GetDynTexture( basename );
1910 if (!add && !dyntexture)
1912 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1913 memset(item, 0, sizeof(*item));
1914 strlcpy(item->basename, basename, sizeof(item->basename));
1915 item->base = dyntexture; // either NULL or dyntexture handle
1916 item->textureflags = textureflags;
1917 item->comparewidth = comparewidth;
1918 item->compareheight = compareheight;
1919 item->comparecrc = comparecrc;
1920 item->next = r_skinframe.hash[hashindex];
1921 r_skinframe.hash[hashindex] = item;
1923 else if( item->base == NULL )
1925 rtexture_t *dyntexture;
1926 // check whether its a dynamic texture
1927 // 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]
1928 dyntexture = CL_GetDynTexture( basename );
1929 item->base = dyntexture; // either NULL or dyntexture handle
1932 R_SkinFrame_MarkUsed(item);
1936 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
1938 unsigned long long avgcolor[5], wsum; \
1946 for(pix = 0; pix < cnt; ++pix) \
1949 for(comp = 0; comp < 3; ++comp) \
1951 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
1954 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1956 for(comp = 0; comp < 3; ++comp) \
1957 avgcolor[comp] += getpixel * w; \
1960 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1961 avgcolor[4] += getpixel; \
1963 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
1965 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
1966 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
1967 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
1968 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
1971 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
1973 // FIXME: it should be possible to disable loading various layers using
1974 // cvars, to prevent wasted loading time and memory usage if the user does
1976 qboolean loadnormalmap = true;
1977 qboolean loadgloss = true;
1978 qboolean loadpantsandshirt = true;
1979 qboolean loadglow = true;
1981 unsigned char *pixels;
1982 unsigned char *bumppixels;
1983 unsigned char *basepixels = NULL;
1984 int basepixels_width;
1985 int basepixels_height;
1986 skinframe_t *skinframe;
1990 if (cls.state == ca_dedicated)
1993 // return an existing skinframe if already loaded
1994 // if loading of the first image fails, don't make a new skinframe as it
1995 // would cause all future lookups of this to be missing
1996 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1997 if (skinframe && skinframe->base)
2000 basepixels = loadimagepixelsbgra(name, complain, true);
2001 if (basepixels == NULL)
2004 if (developer_loading.integer)
2005 Con_Printf("loading skin \"%s\"\n", name);
2007 // we've got some pixels to store, so really allocate this new texture now
2009 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2010 skinframe->stain = NULL;
2011 skinframe->merged = NULL;
2012 skinframe->base = r_texture_notexture;
2013 skinframe->pants = NULL;
2014 skinframe->shirt = NULL;
2015 skinframe->nmap = r_texture_blanknormalmap;
2016 skinframe->gloss = NULL;
2017 skinframe->glow = NULL;
2018 skinframe->fog = NULL;
2020 basepixels_width = image_width;
2021 basepixels_height = image_height;
2022 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);
2024 if (textureflags & TEXF_ALPHA)
2026 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2027 if (basepixels[j] < 255)
2029 if (j < basepixels_width * basepixels_height * 4)
2031 // has transparent pixels
2033 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2034 for (j = 0;j < image_width * image_height * 4;j += 4)
2039 pixels[j+3] = basepixels[j+3];
2041 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);
2046 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2047 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2049 // _norm is the name used by tenebrae and has been adopted as standard
2052 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2054 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2058 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2060 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2061 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2062 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2064 Mem_Free(bumppixels);
2066 else if (r_shadow_bumpscale_basetexture.value > 0)
2068 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2069 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2070 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2074 // _luma is supported for tenebrae compatibility
2075 // (I think it's a very stupid name, but oh well)
2076 // _glow is the preferred name
2077 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;}
2078 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;}
2079 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;}
2080 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;}
2083 Mem_Free(basepixels);
2088 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2091 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2094 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)
2099 for (i = 0;i < width*height;i++)
2100 if (((unsigned char *)&palette[in[i]])[3] > 0)
2102 if (i == width*height)
2105 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2108 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2109 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2112 unsigned char *temp1, *temp2;
2113 skinframe_t *skinframe;
2115 if (cls.state == ca_dedicated)
2118 // if already loaded just return it, otherwise make a new skinframe
2119 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2120 if (skinframe && skinframe->base)
2123 skinframe->stain = NULL;
2124 skinframe->merged = NULL;
2125 skinframe->base = r_texture_notexture;
2126 skinframe->pants = NULL;
2127 skinframe->shirt = NULL;
2128 skinframe->nmap = r_texture_blanknormalmap;
2129 skinframe->gloss = NULL;
2130 skinframe->glow = NULL;
2131 skinframe->fog = NULL;
2133 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2137 if (developer_loading.integer)
2138 Con_Printf("loading 32bit skin \"%s\"\n", name);
2140 if (r_shadow_bumpscale_basetexture.value > 0)
2142 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2143 temp2 = temp1 + width * height * 4;
2144 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2145 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2148 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2149 if (textureflags & TEXF_ALPHA)
2151 for (i = 3;i < width * height * 4;i += 4)
2152 if (skindata[i] < 255)
2154 if (i < width * height * 4)
2156 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2157 memcpy(fogpixels, skindata, width * height * 4);
2158 for (i = 0;i < width * height * 4;i += 4)
2159 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2160 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2161 Mem_Free(fogpixels);
2165 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2166 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2171 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2174 unsigned char *temp1, *temp2;
2175 unsigned int *palette;
2176 skinframe_t *skinframe;
2178 if (cls.state == ca_dedicated)
2181 // if already loaded just return it, otherwise make a new skinframe
2182 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2183 if (skinframe && skinframe->base)
2186 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2188 skinframe->stain = NULL;
2189 skinframe->merged = NULL;
2190 skinframe->base = r_texture_notexture;
2191 skinframe->pants = NULL;
2192 skinframe->shirt = NULL;
2193 skinframe->nmap = r_texture_blanknormalmap;
2194 skinframe->gloss = NULL;
2195 skinframe->glow = NULL;
2196 skinframe->fog = NULL;
2198 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2202 if (developer_loading.integer)
2203 Con_Printf("loading quake skin \"%s\"\n", name);
2205 if (r_shadow_bumpscale_basetexture.value > 0)
2207 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2208 temp2 = temp1 + width * height * 4;
2209 // use either a custom palette or the quake palette
2210 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2211 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2212 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2215 // use either a custom palette, or the quake palette
2216 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2217 if (loadglowtexture)
2218 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2219 if (loadpantsandshirt)
2221 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2222 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2224 if (skinframe->pants || skinframe->shirt)
2225 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
2226 if (textureflags & TEXF_ALPHA)
2228 for (i = 0;i < width * height;i++)
2229 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2231 if (i < width * height)
2232 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2235 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2236 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2241 skinframe_t *R_SkinFrame_LoadMissing(void)
2243 skinframe_t *skinframe;
2245 if (cls.state == ca_dedicated)
2248 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2249 skinframe->stain = NULL;
2250 skinframe->merged = NULL;
2251 skinframe->base = r_texture_notexture;
2252 skinframe->pants = NULL;
2253 skinframe->shirt = NULL;
2254 skinframe->nmap = r_texture_blanknormalmap;
2255 skinframe->gloss = NULL;
2256 skinframe->glow = NULL;
2257 skinframe->fog = NULL;
2259 skinframe->avgcolor[0] = rand() / RAND_MAX;
2260 skinframe->avgcolor[1] = rand() / RAND_MAX;
2261 skinframe->avgcolor[2] = rand() / RAND_MAX;
2262 skinframe->avgcolor[3] = 1;
2267 void gl_main_start(void)
2271 memset(r_queries, 0, sizeof(r_queries));
2273 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2274 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2276 // set up r_skinframe loading system for textures
2277 memset(&r_skinframe, 0, sizeof(r_skinframe));
2278 r_skinframe.loadsequence = 1;
2279 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2281 r_main_texturepool = R_AllocTexturePool();
2282 R_BuildBlankTextures();
2284 if (gl_texturecubemap)
2287 R_BuildNormalizationCube();
2289 r_texture_fogattenuation = NULL;
2290 r_texture_gammaramps = NULL;
2291 //r_texture_fogintensity = NULL;
2292 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2293 memset(&r_waterstate, 0, sizeof(r_waterstate));
2294 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2295 memset(&r_svbsp, 0, sizeof (r_svbsp));
2297 r_refdef.fogmasktable_density = 0;
2300 extern rtexture_t *loadingscreentexture;
2301 void gl_main_shutdown(void)
2304 qglDeleteQueriesARB(r_maxqueries, r_queries);
2308 memset(r_queries, 0, sizeof(r_queries));
2310 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2311 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2313 // clear out the r_skinframe state
2314 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2315 memset(&r_skinframe, 0, sizeof(r_skinframe));
2318 Mem_Free(r_svbsp.nodes);
2319 memset(&r_svbsp, 0, sizeof (r_svbsp));
2320 R_FreeTexturePool(&r_main_texturepool);
2321 loadingscreentexture = NULL;
2322 r_texture_blanknormalmap = NULL;
2323 r_texture_white = NULL;
2324 r_texture_grey128 = NULL;
2325 r_texture_black = NULL;
2326 r_texture_whitecube = NULL;
2327 r_texture_normalizationcube = NULL;
2328 r_texture_fogattenuation = NULL;
2329 r_texture_gammaramps = NULL;
2330 //r_texture_fogintensity = NULL;
2331 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2332 memset(&r_waterstate, 0, sizeof(r_waterstate));
2336 extern void CL_ParseEntityLump(char *entitystring);
2337 void gl_main_newmap(void)
2339 // FIXME: move this code to client
2341 char *entities, entname[MAX_QPATH];
2344 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2345 l = (int)strlen(entname) - 4;
2346 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2348 memcpy(entname + l, ".ent", 5);
2349 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2351 CL_ParseEntityLump(entities);
2356 if (cl.worldmodel->brush.entities)
2357 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2361 void GL_Main_Init(void)
2363 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2365 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2366 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2367 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2368 if (gamemode == GAME_NEHAHRA)
2370 Cvar_RegisterVariable (&gl_fogenable);
2371 Cvar_RegisterVariable (&gl_fogdensity);
2372 Cvar_RegisterVariable (&gl_fogred);
2373 Cvar_RegisterVariable (&gl_foggreen);
2374 Cvar_RegisterVariable (&gl_fogblue);
2375 Cvar_RegisterVariable (&gl_fogstart);
2376 Cvar_RegisterVariable (&gl_fogend);
2377 Cvar_RegisterVariable (&gl_skyclip);
2379 Cvar_RegisterVariable(&r_depthfirst);
2380 Cvar_RegisterVariable(&r_useinfinitefarclip);
2381 Cvar_RegisterVariable(&r_nearclip);
2382 Cvar_RegisterVariable(&r_showbboxes);
2383 Cvar_RegisterVariable(&r_showsurfaces);
2384 Cvar_RegisterVariable(&r_showtris);
2385 Cvar_RegisterVariable(&r_shownormals);
2386 Cvar_RegisterVariable(&r_showlighting);
2387 Cvar_RegisterVariable(&r_showshadowvolumes);
2388 Cvar_RegisterVariable(&r_showcollisionbrushes);
2389 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2390 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2391 Cvar_RegisterVariable(&r_showdisabledepthtest);
2392 Cvar_RegisterVariable(&r_drawportals);
2393 Cvar_RegisterVariable(&r_drawentities);
2394 Cvar_RegisterVariable(&r_cullentities_trace);
2395 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2396 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2397 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2398 Cvar_RegisterVariable(&r_drawviewmodel);
2399 Cvar_RegisterVariable(&r_speeds);
2400 Cvar_RegisterVariable(&r_fullbrights);
2401 Cvar_RegisterVariable(&r_wateralpha);
2402 Cvar_RegisterVariable(&r_dynamic);
2403 Cvar_RegisterVariable(&r_fullbright);
2404 Cvar_RegisterVariable(&r_shadows);
2405 Cvar_RegisterVariable(&r_shadows_throwdistance);
2406 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2407 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2408 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2409 Cvar_RegisterVariable(&r_fog_exp2);
2410 Cvar_RegisterVariable(&r_drawfog);
2411 Cvar_RegisterVariable(&r_textureunits);
2412 Cvar_RegisterVariable(&r_glsl);
2413 Cvar_RegisterVariable(&r_glsl_contrastboost);
2414 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2415 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2416 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2417 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2418 Cvar_RegisterVariable(&r_glsl_postprocess);
2419 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2420 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2421 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2422 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2423 Cvar_RegisterVariable(&r_glsl_usegeneric);
2424 Cvar_RegisterVariable(&r_water);
2425 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2426 Cvar_RegisterVariable(&r_water_clippingplanebias);
2427 Cvar_RegisterVariable(&r_water_refractdistort);
2428 Cvar_RegisterVariable(&r_water_reflectdistort);
2429 Cvar_RegisterVariable(&r_lerpsprites);
2430 Cvar_RegisterVariable(&r_lerpmodels);
2431 Cvar_RegisterVariable(&r_lerplightstyles);
2432 Cvar_RegisterVariable(&r_waterscroll);
2433 Cvar_RegisterVariable(&r_bloom);
2434 Cvar_RegisterVariable(&r_bloom_colorscale);
2435 Cvar_RegisterVariable(&r_bloom_brighten);
2436 Cvar_RegisterVariable(&r_bloom_blur);
2437 Cvar_RegisterVariable(&r_bloom_resolution);
2438 Cvar_RegisterVariable(&r_bloom_colorexponent);
2439 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2440 Cvar_RegisterVariable(&r_hdr);
2441 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2442 Cvar_RegisterVariable(&r_hdr_glowintensity);
2443 Cvar_RegisterVariable(&r_hdr_range);
2444 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2445 Cvar_RegisterVariable(&developer_texturelogging);
2446 Cvar_RegisterVariable(&gl_lightmaps);
2447 Cvar_RegisterVariable(&r_test);
2448 Cvar_RegisterVariable(&r_batchmode);
2449 Cvar_RegisterVariable(&r_glsl_saturation);
2450 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2451 Cvar_SetValue("r_fullbrights", 0);
2452 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2454 Cvar_RegisterVariable(&r_track_sprites);
2455 Cvar_RegisterVariable(&r_track_sprites_flags);
2456 Cvar_RegisterVariable(&r_track_sprites_scalew);
2457 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2460 extern void R_Textures_Init(void);
2461 extern void GL_Draw_Init(void);
2462 extern void GL_Main_Init(void);
2463 extern void R_Shadow_Init(void);
2464 extern void R_Sky_Init(void);
2465 extern void GL_Surf_Init(void);
2466 extern void R_Particles_Init(void);
2467 extern void R_Explosion_Init(void);
2468 extern void gl_backend_init(void);
2469 extern void Sbar_Init(void);
2470 extern void R_LightningBeams_Init(void);
2471 extern void Mod_RenderInit(void);
2473 void Render_Init(void)
2485 R_LightningBeams_Init();
2494 extern char *ENGINE_EXTENSIONS;
2497 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2498 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2499 gl_version = (const char *)qglGetString(GL_VERSION);
2500 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2504 if (!gl_platformextensions)
2505 gl_platformextensions = "";
2507 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2508 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2509 Con_Printf("GL_VERSION: %s\n", gl_version);
2510 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2511 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2513 VID_CheckExtensions();
2515 // LordHavoc: report supported extensions
2516 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2518 // clear to black (loading plaque will be seen over this)
2520 qglClearColor(0,0,0,1);CHECKGLERROR
2521 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2524 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2528 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2530 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2533 p = r_refdef.view.frustum + i;
2538 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2542 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2546 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2550 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2554 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2558 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2562 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2566 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2574 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2578 for (i = 0;i < numplanes;i++)
2585 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2589 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2593 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2597 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2601 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2605 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2609 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2613 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2621 //==================================================================================
2623 static void R_View_UpdateEntityLighting (void)
2626 entity_render_t *ent;
2627 vec3_t tempdiffusenormal;
2629 for (i = 0;i < r_refdef.scene.numentities;i++)
2631 ent = r_refdef.scene.entities[i];
2633 // skip unseen models
2634 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
2638 if (ent->model && ent->model->brush.num_leafs)
2640 // TODO: use modellight for r_ambient settings on world?
2641 VectorSet(ent->modellight_ambient, 0, 0, 0);
2642 VectorSet(ent->modellight_diffuse, 0, 0, 0);
2643 VectorSet(ent->modellight_lightdir, 0, 0, 1);
2647 // fetch the lighting from the worldmodel data
2648 VectorSet(ent->modellight_ambient, r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f));
2649 VectorClear(ent->modellight_diffuse);
2650 VectorClear(tempdiffusenormal);
2651 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
2654 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2655 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2658 VectorSet(ent->modellight_ambient, 1, 1, 1);
2660 // move the light direction into modelspace coordinates for lighting code
2661 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2662 if(VectorLength2(ent->modellight_lightdir) == 0)
2663 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2664 VectorNormalize(ent->modellight_lightdir);
2668 static void R_View_UpdateEntityVisible (void)
2671 entity_render_t *ent;
2673 if (!r_drawentities.integer)
2676 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2677 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2679 // worldmodel can check visibility
2680 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2681 for (i = 0;i < r_refdef.scene.numentities;i++)
2683 ent = r_refdef.scene.entities[i];
2684 if (!(ent->flags & renderimask))
2685 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
2686 if ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
2687 r_refdef.viewcache.entityvisible[i] = true;
2689 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2691 for (i = 0;i < r_refdef.scene.numentities;i++)
2693 ent = r_refdef.scene.entities[i];
2694 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2696 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))
2697 ent->last_trace_visibility = realtime;
2698 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2699 r_refdef.viewcache.entityvisible[i] = 0;
2706 // no worldmodel or it can't check visibility
2707 for (i = 0;i < r_refdef.scene.numentities;i++)
2709 ent = r_refdef.scene.entities[i];
2710 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));
2715 // only used if skyrendermasked, and normally returns false
2716 int R_DrawBrushModelsSky (void)
2719 entity_render_t *ent;
2721 if (!r_drawentities.integer)
2725 for (i = 0;i < r_refdef.scene.numentities;i++)
2727 if (!r_refdef.viewcache.entityvisible[i])
2729 ent = r_refdef.scene.entities[i];
2730 if (!ent->model || !ent->model->DrawSky)
2732 ent->model->DrawSky(ent);
2738 static void R_DrawNoModel(entity_render_t *ent);
2739 static void R_DrawModels(void)
2742 entity_render_t *ent;
2744 if (!r_drawentities.integer)
2747 for (i = 0;i < r_refdef.scene.numentities;i++)
2749 if (!r_refdef.viewcache.entityvisible[i])
2751 ent = r_refdef.scene.entities[i];
2752 r_refdef.stats.entities++;
2753 if (ent->model && ent->model->Draw != NULL)
2754 ent->model->Draw(ent);
2760 static void R_DrawModelsDepth(void)
2763 entity_render_t *ent;
2765 if (!r_drawentities.integer)
2768 for (i = 0;i < r_refdef.scene.numentities;i++)
2770 if (!r_refdef.viewcache.entityvisible[i])
2772 ent = r_refdef.scene.entities[i];
2773 if (ent->model && ent->model->DrawDepth != NULL)
2774 ent->model->DrawDepth(ent);
2778 static void R_DrawModelsDebug(void)
2781 entity_render_t *ent;
2783 if (!r_drawentities.integer)
2786 for (i = 0;i < r_refdef.scene.numentities;i++)
2788 if (!r_refdef.viewcache.entityvisible[i])
2790 ent = r_refdef.scene.entities[i];
2791 if (ent->model && ent->model->DrawDebug != NULL)
2792 ent->model->DrawDebug(ent);
2796 static void R_DrawModelsAddWaterPlanes(void)
2799 entity_render_t *ent;
2801 if (!r_drawentities.integer)
2804 for (i = 0;i < r_refdef.scene.numentities;i++)
2806 if (!r_refdef.viewcache.entityvisible[i])
2808 ent = r_refdef.scene.entities[i];
2809 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2810 ent->model->DrawAddWaterPlanes(ent);
2814 static void R_View_SetFrustum(void)
2817 double slopex, slopey;
2818 vec3_t forward, left, up, origin;
2820 // we can't trust r_refdef.view.forward and friends in reflected scenes
2821 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2824 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2825 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2826 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2827 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2828 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2829 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2830 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2831 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2832 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2833 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2834 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2835 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2839 zNear = r_refdef.nearclip;
2840 nudge = 1.0 - 1.0 / (1<<23);
2841 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2842 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2843 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2844 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2845 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2846 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2847 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2848 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2854 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2855 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2856 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2857 r_refdef.view.frustum[0].dist = m[15] - m[12];
2859 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2860 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2861 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2862 r_refdef.view.frustum[1].dist = m[15] + m[12];
2864 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2865 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2866 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2867 r_refdef.view.frustum[2].dist = m[15] - m[13];
2869 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2870 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2871 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2872 r_refdef.view.frustum[3].dist = m[15] + m[13];
2874 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2875 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2876 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2877 r_refdef.view.frustum[4].dist = m[15] - m[14];
2879 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2880 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2881 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2882 r_refdef.view.frustum[5].dist = m[15] + m[14];
2885 if (r_refdef.view.useperspective)
2887 slopex = 1.0 / r_refdef.view.frustum_x;
2888 slopey = 1.0 / r_refdef.view.frustum_y;
2889 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2890 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
2891 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
2892 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
2893 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2895 // Leaving those out was a mistake, those were in the old code, and they
2896 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2897 // I couldn't reproduce it after adding those normalizations. --blub
2898 VectorNormalize(r_refdef.view.frustum[0].normal);
2899 VectorNormalize(r_refdef.view.frustum[1].normal);
2900 VectorNormalize(r_refdef.view.frustum[2].normal);
2901 VectorNormalize(r_refdef.view.frustum[3].normal);
2903 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2904 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2905 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2906 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2907 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2909 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2910 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2911 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2912 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2913 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2917 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2918 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2919 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2920 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2921 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2922 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2923 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2924 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2925 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2926 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2928 r_refdef.view.numfrustumplanes = 5;
2930 if (r_refdef.view.useclipplane)
2932 r_refdef.view.numfrustumplanes = 6;
2933 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2936 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2937 PlaneClassify(r_refdef.view.frustum + i);
2939 // LordHavoc: note to all quake engine coders, Quake had a special case
2940 // for 90 degrees which assumed a square view (wrong), so I removed it,
2941 // Quake2 has it disabled as well.
2943 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2944 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2945 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2946 //PlaneClassify(&frustum[0]);
2948 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2949 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2950 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2951 //PlaneClassify(&frustum[1]);
2953 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2954 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2955 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2956 //PlaneClassify(&frustum[2]);
2958 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2959 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2960 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2961 //PlaneClassify(&frustum[3]);
2964 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2965 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2966 //PlaneClassify(&frustum[4]);
2969 void R_View_Update(void)
2971 R_View_SetFrustum();
2972 R_View_WorldVisibility(r_refdef.view.useclipplane);
2973 R_View_UpdateEntityVisible();
2974 R_View_UpdateEntityLighting();
2977 void R_SetupView(qboolean allowwaterclippingplane)
2979 if (!r_refdef.view.useperspective)
2980 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);
2981 else if (gl_stencil && r_useinfinitefarclip.integer)
2982 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2984 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2986 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2988 if (r_refdef.view.useclipplane && allowwaterclippingplane)
2990 // LordHavoc: couldn't figure out how to make this approach the
2991 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2992 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2993 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2994 dist = r_refdef.view.clipplane.dist;
2995 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2999 void R_ResetViewRendering2D(void)
3003 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3004 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3005 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
3006 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3007 GL_Color(1, 1, 1, 1);
3008 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3009 GL_BlendFunc(GL_ONE, GL_ZERO);
3010 GL_AlphaTest(false);
3011 GL_ScissorTest(false);
3012 GL_DepthMask(false);
3013 GL_DepthRange(0, 1);
3014 GL_DepthTest(false);
3015 R_Mesh_Matrix(&identitymatrix);
3016 R_Mesh_ResetTextureState();
3017 GL_PolygonOffset(0, 0);
3018 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3019 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3020 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3021 qglStencilMask(~0);CHECKGLERROR
3022 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3023 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3024 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3025 R_SetupGenericShader(true);
3028 void R_ResetViewRendering3D(void)
3032 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3033 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3035 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3036 GL_Color(1, 1, 1, 1);
3037 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3038 GL_BlendFunc(GL_ONE, GL_ZERO);
3039 GL_AlphaTest(false);
3040 GL_ScissorTest(true);
3042 GL_DepthRange(0, 1);
3044 R_Mesh_Matrix(&identitymatrix);
3045 R_Mesh_ResetTextureState();
3046 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3047 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3048 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3049 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3050 qglStencilMask(~0);CHECKGLERROR
3051 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3052 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3053 GL_CullFace(r_refdef.view.cullface_back);
3054 R_SetupGenericShader(true);
3057 void R_RenderScene(void);
3058 void R_RenderWaterPlanes(void);
3060 static void R_Water_StartFrame(void)
3063 int waterwidth, waterheight, texturewidth, textureheight;
3064 r_waterstate_waterplane_t *p;
3066 // set waterwidth and waterheight to the water resolution that will be
3067 // used (often less than the screen resolution for faster rendering)
3068 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3069 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3071 // calculate desired texture sizes
3072 // can't use water if the card does not support the texture size
3073 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3074 texturewidth = textureheight = waterwidth = waterheight = 0;
3075 else if (gl_support_arb_texture_non_power_of_two)
3077 texturewidth = waterwidth;
3078 textureheight = waterheight;
3082 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3083 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3086 // allocate textures as needed
3087 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3089 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3090 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3092 if (p->texture_refraction)
3093 R_FreeTexture(p->texture_refraction);
3094 p->texture_refraction = NULL;
3095 if (p->texture_reflection)
3096 R_FreeTexture(p->texture_reflection);
3097 p->texture_reflection = NULL;
3099 memset(&r_waterstate, 0, sizeof(r_waterstate));
3100 r_waterstate.waterwidth = waterwidth;
3101 r_waterstate.waterheight = waterheight;
3102 r_waterstate.texturewidth = texturewidth;
3103 r_waterstate.textureheight = textureheight;
3106 if (r_waterstate.waterwidth)
3108 r_waterstate.enabled = true;
3110 // set up variables that will be used in shader setup
3111 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3112 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3113 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3114 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3117 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3118 r_waterstate.numwaterplanes = 0;
3121 void R_Water_AddWaterPlane(msurface_t *surface)
3123 int triangleindex, planeindex;
3129 r_waterstate_waterplane_t *p;
3130 texture_t *t = R_GetCurrentTexture(surface->texture);
3131 // just use the first triangle with a valid normal for any decisions
3132 VectorClear(normal);
3133 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3135 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3136 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3137 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3138 TriangleNormal(vert[0], vert[1], vert[2], normal);
3139 if (VectorLength2(normal) >= 0.001)
3143 VectorCopy(normal, plane.normal);
3144 VectorNormalize(plane.normal);
3145 plane.dist = DotProduct(vert[0], plane.normal);
3146 PlaneClassify(&plane);
3147 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3149 // skip backfaces (except if nocullface is set)
3150 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3152 VectorNegate(plane.normal, plane.normal);
3154 PlaneClassify(&plane);
3158 // find a matching plane if there is one
3159 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3160 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3162 if (planeindex >= r_waterstate.maxwaterplanes)
3163 return; // nothing we can do, out of planes
3165 // if this triangle does not fit any known plane rendered this frame, add one
3166 if (planeindex >= r_waterstate.numwaterplanes)
3168 // store the new plane
3169 r_waterstate.numwaterplanes++;
3171 // clear materialflags and pvs
3172 p->materialflags = 0;
3173 p->pvsvalid = false;
3175 // merge this surface's materialflags into the waterplane
3176 p->materialflags |= t->currentmaterialflags;
3177 // merge this surface's PVS into the waterplane
3178 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3179 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3180 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3182 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3187 static void R_Water_ProcessPlanes(void)
3189 r_refdef_view_t originalview;
3190 r_refdef_view_t myview;
3192 r_waterstate_waterplane_t *p;
3194 originalview = r_refdef.view;
3196 // make sure enough textures are allocated
3197 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3199 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3201 if (!p->texture_refraction)
3202 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);
3203 if (!p->texture_refraction)
3207 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3209 if (!p->texture_reflection)
3210 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);
3211 if (!p->texture_reflection)
3217 r_refdef.view = originalview;
3218 r_refdef.view.showdebug = false;
3219 r_refdef.view.width = r_waterstate.waterwidth;
3220 r_refdef.view.height = r_waterstate.waterheight;
3221 r_refdef.view.useclipplane = true;
3222 myview = r_refdef.view;
3223 r_waterstate.renderingscene = true;
3224 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3226 // render the normal view scene and copy into texture
3227 // (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)
3228 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3230 r_refdef.view = myview;
3231 r_refdef.view.clipplane = p->plane;
3232 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3233 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3234 PlaneClassify(&r_refdef.view.clipplane);
3236 R_ResetViewRendering3D();
3237 R_ClearScreen(r_refdef.fogenabled);
3241 // copy view into the screen texture
3242 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3243 GL_ActiveTexture(0);
3245 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
3248 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3250 r_refdef.view = myview;
3251 // render reflected scene and copy into texture
3252 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3253 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3254 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3255 r_refdef.view.clipplane = p->plane;
3256 // reverse the cullface settings for this render
3257 r_refdef.view.cullface_front = GL_FRONT;
3258 r_refdef.view.cullface_back = GL_BACK;
3259 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3261 r_refdef.view.usecustompvs = true;
3263 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3265 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3268 R_ResetViewRendering3D();
3269 R_ClearScreen(r_refdef.fogenabled);
3273 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3274 GL_ActiveTexture(0);
3276 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
3279 r_waterstate.renderingscene = false;
3280 r_refdef.view = originalview;
3281 R_ResetViewRendering3D();
3282 R_ClearScreen(r_refdef.fogenabled);
3286 r_refdef.view = originalview;
3287 r_waterstate.renderingscene = false;
3288 Cvar_SetValueQuick(&r_water, 0);
3289 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3293 void R_Bloom_StartFrame(void)
3295 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3297 // set bloomwidth and bloomheight to the bloom resolution that will be
3298 // used (often less than the screen resolution for faster rendering)
3299 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3300 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3301 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3302 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3303 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3305 // calculate desired texture sizes
3306 if (gl_support_arb_texture_non_power_of_two)
3308 screentexturewidth = r_refdef.view.width;
3309 screentextureheight = r_refdef.view.height;
3310 bloomtexturewidth = r_bloomstate.bloomwidth;
3311 bloomtextureheight = r_bloomstate.bloomheight;
3315 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3316 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3317 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3318 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3321 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))
3323 Cvar_SetValueQuick(&r_hdr, 0);
3324 Cvar_SetValueQuick(&r_bloom, 0);
3327 if (!(r_glsl.integer && (r_glsl_postprocess.integer || r_glsl_saturation.value != 1 || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
3328 screentexturewidth = screentextureheight = 0;
3329 if (!r_hdr.integer && !r_bloom.integer)
3330 bloomtexturewidth = bloomtextureheight = 0;
3332 // allocate textures as needed
3333 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3335 if (r_bloomstate.texture_screen)
3336 R_FreeTexture(r_bloomstate.texture_screen);
3337 r_bloomstate.texture_screen = NULL;
3338 r_bloomstate.screentexturewidth = screentexturewidth;
3339 r_bloomstate.screentextureheight = screentextureheight;
3340 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3341 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);
3343 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3345 if (r_bloomstate.texture_bloom)
3346 R_FreeTexture(r_bloomstate.texture_bloom);
3347 r_bloomstate.texture_bloom = NULL;
3348 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3349 r_bloomstate.bloomtextureheight = bloomtextureheight;
3350 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3351 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);
3354 // set up a texcoord array for the full resolution screen image
3355 // (we have to keep this around to copy back during final render)
3356 r_bloomstate.screentexcoord2f[0] = 0;
3357 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3358 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3359 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3360 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3361 r_bloomstate.screentexcoord2f[5] = 0;
3362 r_bloomstate.screentexcoord2f[6] = 0;
3363 r_bloomstate.screentexcoord2f[7] = 0;
3365 // set up a texcoord array for the reduced resolution bloom image
3366 // (which will be additive blended over the screen image)
3367 r_bloomstate.bloomtexcoord2f[0] = 0;
3368 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3369 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3370 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3371 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3372 r_bloomstate.bloomtexcoord2f[5] = 0;
3373 r_bloomstate.bloomtexcoord2f[6] = 0;
3374 r_bloomstate.bloomtexcoord2f[7] = 0;
3376 if (r_hdr.integer || r_bloom.integer)
3378 r_bloomstate.enabled = true;
3379 r_bloomstate.hdr = r_hdr.integer != 0;
3383 void R_Bloom_CopyBloomTexture(float colorscale)
3385 r_refdef.stats.bloom++;
3387 // scale down screen texture to the bloom texture size
3389 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3390 GL_BlendFunc(GL_ONE, GL_ZERO);
3391 GL_Color(colorscale, colorscale, colorscale, 1);
3392 // TODO: optimize with multitexture or GLSL
3393 R_SetupGenericShader(true);
3394 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3395 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3396 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3397 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3399 // we now have a bloom image in the framebuffer
3400 // copy it into the bloom image texture for later processing
3401 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3402 GL_ActiveTexture(0);
3404 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
3405 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3408 void R_Bloom_CopyHDRTexture(void)
3410 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3411 GL_ActiveTexture(0);
3413 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
3414 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3417 void R_Bloom_MakeTexture(void)
3420 float xoffset, yoffset, r, brighten;
3422 r_refdef.stats.bloom++;
3424 R_ResetViewRendering2D();
3425 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3426 R_Mesh_ColorPointer(NULL, 0, 0);
3427 R_SetupGenericShader(true);
3429 // we have a bloom image in the framebuffer
3431 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3433 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3436 r = bound(0, r_bloom_colorexponent.value / x, 1);
3437 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3438 GL_Color(r, r, r, 1);
3439 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3440 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3441 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3442 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3444 // copy the vertically blurred bloom view to a texture
3445 GL_ActiveTexture(0);
3447 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
3448 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3451 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3452 brighten = r_bloom_brighten.value;
3454 brighten *= r_hdr_range.value;
3455 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3456 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3458 for (dir = 0;dir < 2;dir++)
3460 // blend on at multiple vertical offsets to achieve a vertical blur
3461 // TODO: do offset blends using GLSL
3462 GL_BlendFunc(GL_ONE, GL_ZERO);
3463 for (x = -range;x <= range;x++)
3465 if (!dir){xoffset = 0;yoffset = x;}
3466 else {xoffset = x;yoffset = 0;}
3467 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3468 yoffset /= (float)r_bloomstate.bloomtextureheight;
3469 // compute a texcoord array with the specified x and y offset
3470 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3471 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3472 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3473 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3474 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3475 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3476 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3477 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3478 // this r value looks like a 'dot' particle, fading sharply to
3479 // black at the edges
3480 // (probably not realistic but looks good enough)
3481 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3482 //r = (dir ? 1.0f : brighten)/(range*2+1);
3483 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3484 GL_Color(r, r, r, 1);
3485 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3486 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3487 GL_BlendFunc(GL_ONE, GL_ONE);
3490 // copy the vertically blurred bloom view to a texture
3491 GL_ActiveTexture(0);
3493 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
3494 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3497 // apply subtract last
3498 // (just like it would be in a GLSL shader)
3499 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3501 GL_BlendFunc(GL_ONE, GL_ZERO);
3502 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3503 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3504 GL_Color(1, 1, 1, 1);
3505 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3506 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3508 GL_BlendFunc(GL_ONE, GL_ONE);
3509 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3510 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3511 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3512 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3513 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3514 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3515 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3517 // copy the darkened bloom view to a texture
3518 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3519 GL_ActiveTexture(0);
3521 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
3522 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3526 void R_HDR_RenderBloomTexture(void)
3528 int oldwidth, oldheight;
3529 float oldcolorscale;
3531 oldcolorscale = r_refdef.view.colorscale;
3532 oldwidth = r_refdef.view.width;
3533 oldheight = r_refdef.view.height;
3534 r_refdef.view.width = r_bloomstate.bloomwidth;
3535 r_refdef.view.height = r_bloomstate.bloomheight;
3537 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3538 // TODO: add exposure compensation features
3539 // TODO: add fp16 framebuffer support
3541 r_refdef.view.showdebug = false;
3542 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3544 R_ResetViewRendering3D();
3546 R_ClearScreen(r_refdef.fogenabled);
3547 if (r_timereport_active)
3548 R_TimeReport("HDRclear");
3551 if (r_timereport_active)
3552 R_TimeReport("visibility");
3554 r_waterstate.numwaterplanes = 0;
3555 if (r_waterstate.enabled)
3556 R_RenderWaterPlanes();
3558 r_refdef.view.showdebug = true;
3560 r_waterstate.numwaterplanes = 0;
3562 R_ResetViewRendering2D();
3564 R_Bloom_CopyHDRTexture();
3565 R_Bloom_MakeTexture();
3567 // restore the view settings
3568 r_refdef.view.width = oldwidth;
3569 r_refdef.view.height = oldheight;
3570 r_refdef.view.colorscale = oldcolorscale;
3572 R_ResetViewRendering3D();
3574 R_ClearScreen(r_refdef.fogenabled);
3575 if (r_timereport_active)
3576 R_TimeReport("viewclear");
3579 static void R_BlendView(void)
3581 if (r_bloomstate.texture_screen)
3583 // copy view into the screen texture
3584 R_ResetViewRendering2D();
3585 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3586 R_Mesh_ColorPointer(NULL, 0, 0);
3587 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3588 GL_ActiveTexture(0);CHECKGLERROR
3589 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
3590 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3593 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3595 unsigned int permutation =
3596 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3597 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3598 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3599 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
3600 | (r_glsl_saturation.value != 1 ? SHADERPERMUTATION_SATURATION : 0);
3602 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3604 // render simple bloom effect
3605 // copy the screen and shrink it and darken it for the bloom process
3606 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3607 // make the bloom texture
3608 R_Bloom_MakeTexture();
3611 R_ResetViewRendering2D();
3612 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3613 R_Mesh_ColorPointer(NULL, 0, 0);
3614 GL_Color(1, 1, 1, 1);
3615 GL_BlendFunc(GL_ONE, GL_ZERO);
3616 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3617 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3618 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3619 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3620 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3621 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3622 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3623 if (r_glsl_permutation->loc_TintColor >= 0)
3624 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3625 if (r_glsl_permutation->loc_ClientTime >= 0)
3626 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3627 if (r_glsl_permutation->loc_PixelSize >= 0)
3628 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3629 if (r_glsl_permutation->loc_UserVec1 >= 0)
3631 float a=0, b=0, c=0, d=0;
3632 #if _MSC_VER >= 1400
3633 #define sscanf sscanf_s
3635 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3636 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3638 if (r_glsl_permutation->loc_UserVec2 >= 0)
3640 float a=0, b=0, c=0, d=0;
3641 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3642 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3644 if (r_glsl_permutation->loc_UserVec3 >= 0)
3646 float a=0, b=0, c=0, d=0;
3647 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3648 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3650 if (r_glsl_permutation->loc_UserVec4 >= 0)
3652 float a=0, b=0, c=0, d=0;
3653 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3654 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3656 if (r_glsl_permutation->loc_Saturation >= 0)
3657 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
3658 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3659 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3665 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3667 // render high dynamic range bloom effect
3668 // the bloom texture was made earlier this render, so we just need to
3669 // blend it onto the screen...
3670 R_ResetViewRendering2D();
3671 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3672 R_Mesh_ColorPointer(NULL, 0, 0);
3673 R_SetupGenericShader(true);
3674 GL_Color(1, 1, 1, 1);
3675 GL_BlendFunc(GL_ONE, GL_ONE);
3676 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3677 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3678 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3679 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3681 else if (r_bloomstate.texture_bloom)
3683 // render simple bloom effect
3684 // copy the screen and shrink it and darken it for the bloom process
3685 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3686 // make the bloom texture
3687 R_Bloom_MakeTexture();
3688 // put the original screen image back in place and blend the bloom
3690 R_ResetViewRendering2D();
3691 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3692 R_Mesh_ColorPointer(NULL, 0, 0);
3693 GL_Color(1, 1, 1, 1);
3694 GL_BlendFunc(GL_ONE, GL_ZERO);
3695 // do both in one pass if possible
3696 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3697 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3698 if (r_textureunits.integer >= 2 && gl_combine.integer)
3700 R_SetupGenericTwoTextureShader(GL_ADD);
3701 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3702 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3706 R_SetupGenericShader(true);
3707 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3708 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3709 // now blend on the bloom texture
3710 GL_BlendFunc(GL_ONE, GL_ONE);
3711 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3712 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3714 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3715 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3717 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3719 // apply a color tint to the whole view
3720 R_ResetViewRendering2D();
3721 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3722 R_Mesh_ColorPointer(NULL, 0, 0);
3723 R_SetupGenericShader(false);
3724 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3725 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3726 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3730 matrix4x4_t r_waterscrollmatrix;
3732 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3734 if (r_refdef.fog_density)
3736 r_refdef.fogcolor[0] = r_refdef.fog_red;
3737 r_refdef.fogcolor[1] = r_refdef.fog_green;
3738 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3742 VectorCopy(r_refdef.fogcolor, fogvec);
3743 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3745 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3746 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3747 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3748 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3750 // color.rgb *= ContrastBoost * SceneBrightness;
3751 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3752 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3753 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3754 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3759 void R_UpdateVariables(void)
3763 r_refdef.scene.ambient = r_ambient.value;
3765 r_refdef.farclip = 4096;
3766 if (r_refdef.scene.worldmodel)
3767 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3768 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3770 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3771 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3772 r_refdef.polygonfactor = 0;
3773 r_refdef.polygonoffset = 0;
3774 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3775 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3777 r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
3778 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3779 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3780 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3781 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3782 if (r_showsurfaces.integer)
3784 r_refdef.scene.rtworld = false;
3785 r_refdef.scene.rtworldshadows = false;
3786 r_refdef.scene.rtdlight = false;
3787 r_refdef.scene.rtdlightshadows = false;
3788 r_refdef.lightmapintensity = 0;
3791 if (gamemode == GAME_NEHAHRA)
3793 if (gl_fogenable.integer)
3795 r_refdef.oldgl_fogenable = true;
3796 r_refdef.fog_density = gl_fogdensity.value;
3797 r_refdef.fog_red = gl_fogred.value;
3798 r_refdef.fog_green = gl_foggreen.value;
3799 r_refdef.fog_blue = gl_fogblue.value;
3800 r_refdef.fog_alpha = 1;
3801 r_refdef.fog_start = 0;
3802 r_refdef.fog_end = gl_skyclip.value;
3804 else if (r_refdef.oldgl_fogenable)
3806 r_refdef.oldgl_fogenable = false;
3807 r_refdef.fog_density = 0;
3808 r_refdef.fog_red = 0;
3809 r_refdef.fog_green = 0;
3810 r_refdef.fog_blue = 0;
3811 r_refdef.fog_alpha = 0;
3812 r_refdef.fog_start = 0;
3813 r_refdef.fog_end = 0;
3817 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3818 r_refdef.fog_start = max(0, r_refdef.fog_start);
3819 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3821 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3823 if (r_refdef.fog_density && r_drawfog.integer)
3825 r_refdef.fogenabled = true;
3826 // this is the point where the fog reaches 0.9986 alpha, which we
3827 // consider a good enough cutoff point for the texture
3828 // (0.9986 * 256 == 255.6)
3829 if (r_fog_exp2.integer)
3830 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3832 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3833 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3834 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3835 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3836 // fog color was already set
3837 // update the fog texture
3838 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)
3839 R_BuildFogTexture();
3842 r_refdef.fogenabled = false;
3844 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
3846 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
3848 // build GLSL gamma texture
3849 #define RAMPWIDTH 256
3850 unsigned short ramp[RAMPWIDTH * 3];
3851 unsigned char rampbgr[RAMPWIDTH][4];
3854 r_texture_gammaramps_serial = vid_gammatables_serial;
3856 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
3857 for(i = 0; i < RAMPWIDTH; ++i)
3859 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3860 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3861 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
3864 if (r_texture_gammaramps)
3866 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
3870 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
3876 // remove GLSL gamma texture
3880 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3881 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3887 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3888 if( scenetype != r_currentscenetype ) {
3889 // store the old scenetype
3890 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3891 r_currentscenetype = scenetype;
3892 // move in the new scene
3893 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3902 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3904 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3905 if( scenetype == r_currentscenetype ) {
3906 return &r_refdef.scene;
3908 return &r_scenes_store[ scenetype ];
3917 void R_RenderView(void)
3919 r_frame++; // used only by R_GetCurrentTexture
3920 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3922 if (r_refdef.view.isoverlay)
3924 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
3925 GL_Clear( GL_DEPTH_BUFFER_BIT );
3926 R_TimeReport("depthclear");
3928 r_refdef.view.showdebug = false;
3930 r_waterstate.enabled = false;
3931 r_waterstate.numwaterplanes = 0;
3939 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
3940 return; //Host_Error ("R_RenderView: NULL worldmodel");
3942 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3944 // break apart the view matrix into vectors for various purposes
3945 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3946 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3947 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3948 VectorNegate(r_refdef.view.left, r_refdef.view.right);
3949 // make an inverted copy of the view matrix for tracking sprites
3950 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3952 R_Shadow_UpdateWorldLightSelection();
3954 R_Bloom_StartFrame();
3955 R_Water_StartFrame();
3958 if (r_timereport_active)
3959 R_TimeReport("viewsetup");
3961 R_ResetViewRendering3D();
3963 if (r_refdef.view.clear || r_refdef.fogenabled)
3965 R_ClearScreen(r_refdef.fogenabled);
3966 if (r_timereport_active)
3967 R_TimeReport("viewclear");
3969 r_refdef.view.clear = true;
3971 // this produces a bloom texture to be used in R_BlendView() later
3973 R_HDR_RenderBloomTexture();
3975 r_refdef.view.showdebug = true;
3978 if (r_timereport_active)
3979 R_TimeReport("visibility");
3981 r_waterstate.numwaterplanes = 0;
3982 if (r_waterstate.enabled)
3983 R_RenderWaterPlanes();
3986 r_waterstate.numwaterplanes = 0;
3989 if (r_timereport_active)
3990 R_TimeReport("blendview");
3992 GL_Scissor(0, 0, vid.width, vid.height);
3993 GL_ScissorTest(false);
3997 void R_RenderWaterPlanes(void)
3999 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4001 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4002 if (r_timereport_active)
4003 R_TimeReport("waterworld");
4006 // don't let sound skip if going slow
4007 if (r_refdef.scene.extraupdate)
4010 R_DrawModelsAddWaterPlanes();
4011 if (r_timereport_active)
4012 R_TimeReport("watermodels");
4014 if (r_waterstate.numwaterplanes)
4016 R_Water_ProcessPlanes();
4017 if (r_timereport_active)
4018 R_TimeReport("waterscenes");
4022 extern void R_DrawLightningBeams (void);
4023 extern void VM_CL_AddPolygonsToMeshQueue (void);
4024 extern void R_DrawPortals (void);
4025 extern cvar_t cl_locs_show;
4026 static void R_DrawLocs(void);
4027 static void R_DrawEntityBBoxes(void);
4028 void R_RenderScene(void)
4030 r_refdef.stats.renders++;
4034 // don't let sound skip if going slow
4035 if (r_refdef.scene.extraupdate)
4038 R_MeshQueue_BeginScene();
4042 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);
4044 if (cl.csqc_vidvars.drawworld)
4046 // don't let sound skip if going slow
4047 if (r_refdef.scene.extraupdate)
4050 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4052 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4053 if (r_timereport_active)
4054 R_TimeReport("worldsky");
4057 if (R_DrawBrushModelsSky() && r_timereport_active)
4058 R_TimeReport("bmodelsky");
4061 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4063 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4064 if (r_timereport_active)
4065 R_TimeReport("worlddepth");
4067 if (r_depthfirst.integer >= 2)
4069 R_DrawModelsDepth();
4070 if (r_timereport_active)
4071 R_TimeReport("modeldepth");
4074 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4076 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4077 if (r_timereport_active)
4078 R_TimeReport("world");
4081 // don't let sound skip if going slow
4082 if (r_refdef.scene.extraupdate)
4086 if (r_timereport_active)
4087 R_TimeReport("models");
4089 // don't let sound skip if going slow
4090 if (r_refdef.scene.extraupdate)
4093 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
4095 R_DrawModelShadows();
4097 R_ResetViewRendering3D();
4099 // don't let sound skip if going slow
4100 if (r_refdef.scene.extraupdate)
4104 R_ShadowVolumeLighting(false);
4105 if (r_timereport_active)
4106 R_TimeReport("rtlights");
4108 // don't let sound skip if going slow
4109 if (r_refdef.scene.extraupdate)
4112 if (cl.csqc_vidvars.drawworld)
4114 R_DrawLightningBeams();
4115 if (r_timereport_active)
4116 R_TimeReport("lightning");
4119 if (r_timereport_active)
4120 R_TimeReport("decals");
4123 if (r_timereport_active)
4124 R_TimeReport("particles");
4127 if (r_timereport_active)
4128 R_TimeReport("explosions");
4131 R_SetupGenericShader(true);
4132 VM_CL_AddPolygonsToMeshQueue();
4134 if (r_refdef.view.showdebug)
4136 if (cl_locs_show.integer)
4139 if (r_timereport_active)
4140 R_TimeReport("showlocs");
4143 if (r_drawportals.integer)
4146 if (r_timereport_active)
4147 R_TimeReport("portals");
4150 if (r_showbboxes.value > 0)
4152 R_DrawEntityBBoxes();
4153 if (r_timereport_active)
4154 R_TimeReport("bboxes");
4158 R_SetupGenericShader(true);
4159 R_MeshQueue_RenderTransparent();
4160 if (r_timereport_active)
4161 R_TimeReport("drawtrans");
4163 R_SetupGenericShader(true);
4165 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))
4167 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4168 if (r_timereport_active)
4169 R_TimeReport("worlddebug");
4170 R_DrawModelsDebug();
4171 if (r_timereport_active)
4172 R_TimeReport("modeldebug");
4175 R_SetupGenericShader(true);
4177 if (cl.csqc_vidvars.drawworld)
4180 if (r_timereport_active)
4181 R_TimeReport("coronas");
4184 // don't let sound skip if going slow
4185 if (r_refdef.scene.extraupdate)
4188 R_ResetViewRendering2D();
4191 static const unsigned short bboxelements[36] =
4201 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4204 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4205 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4206 GL_DepthMask(false);
4207 GL_DepthRange(0, 1);
4208 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4209 R_Mesh_Matrix(&identitymatrix);
4210 R_Mesh_ResetTextureState();
4212 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4213 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4214 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4215 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4216 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4217 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4218 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4219 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4220 R_FillColors(color4f, 8, cr, cg, cb, ca);
4221 if (r_refdef.fogenabled)
4223 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4225 f1 = FogPoint_World(v);
4227 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4228 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4229 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4232 R_Mesh_VertexPointer(vertex3f, 0, 0);
4233 R_Mesh_ColorPointer(color4f, 0, 0);
4234 R_Mesh_ResetTextureState();
4235 R_SetupGenericShader(false);
4236 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4239 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4243 prvm_edict_t *edict;
4244 prvm_prog_t *prog_save = prog;
4246 // this function draws bounding boxes of server entities
4250 GL_CullFace(GL_NONE);
4251 R_SetupGenericShader(false);
4255 for (i = 0;i < numsurfaces;i++)
4257 edict = PRVM_EDICT_NUM(surfacelist[i]);
4258 switch ((int)edict->fields.server->solid)
4260 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4261 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4262 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4263 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4264 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4265 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4267 color[3] *= r_showbboxes.value;
4268 color[3] = bound(0, color[3], 1);
4269 GL_DepthTest(!r_showdisabledepthtest.integer);
4270 GL_CullFace(r_refdef.view.cullface_front);
4271 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4277 static void R_DrawEntityBBoxes(void)
4280 prvm_edict_t *edict;
4282 prvm_prog_t *prog_save = prog;
4284 // this function draws bounding boxes of server entities
4290 for (i = 0;i < prog->num_edicts;i++)
4292 edict = PRVM_EDICT_NUM(i);
4293 if (edict->priv.server->free)
4295 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4296 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4298 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4300 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4301 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4307 unsigned short nomodelelements[24] =
4319 float nomodelvertex3f[6*3] =
4329 float nomodelcolor4f[6*4] =
4331 0.0f, 0.0f, 0.5f, 1.0f,
4332 0.0f, 0.0f, 0.5f, 1.0f,
4333 0.0f, 0.5f, 0.0f, 1.0f,
4334 0.0f, 0.5f, 0.0f, 1.0f,
4335 0.5f, 0.0f, 0.0f, 1.0f,
4336 0.5f, 0.0f, 0.0f, 1.0f
4339 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4344 // this is only called once per entity so numsurfaces is always 1, and
4345 // surfacelist is always {0}, so this code does not handle batches
4346 R_Mesh_Matrix(&ent->matrix);
4348 if (ent->flags & EF_ADDITIVE)
4350 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4351 GL_DepthMask(false);
4353 else if (ent->alpha < 1)
4355 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4356 GL_DepthMask(false);
4360 GL_BlendFunc(GL_ONE, GL_ZERO);
4363 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4364 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4365 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4366 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4367 R_SetupGenericShader(false);
4368 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4369 if (r_refdef.fogenabled)
4372 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4373 R_Mesh_ColorPointer(color4f, 0, 0);
4374 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4375 f1 = FogPoint_World(org);
4377 for (i = 0, c = color4f;i < 6;i++, c += 4)
4379 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4380 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4381 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4385 else if (ent->alpha != 1)
4387 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4388 R_Mesh_ColorPointer(color4f, 0, 0);
4389 for (i = 0, c = color4f;i < 6;i++, c += 4)
4393 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4394 R_Mesh_ResetTextureState();
4395 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4398 void R_DrawNoModel(entity_render_t *ent)
4401 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4402 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4403 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4405 // R_DrawNoModelCallback(ent, 0);
4408 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4410 vec3_t right1, right2, diff, normal;
4412 VectorSubtract (org2, org1, normal);
4414 // calculate 'right' vector for start
4415 VectorSubtract (r_refdef.view.origin, org1, diff);
4416 CrossProduct (normal, diff, right1);
4417 VectorNormalize (right1);
4419 // calculate 'right' vector for end
4420 VectorSubtract (r_refdef.view.origin, org2, diff);
4421 CrossProduct (normal, diff, right2);
4422 VectorNormalize (right2);
4424 vert[ 0] = org1[0] + width * right1[0];
4425 vert[ 1] = org1[1] + width * right1[1];
4426 vert[ 2] = org1[2] + width * right1[2];
4427 vert[ 3] = org1[0] - width * right1[0];
4428 vert[ 4] = org1[1] - width * right1[1];
4429 vert[ 5] = org1[2] - width * right1[2];
4430 vert[ 6] = org2[0] - width * right2[0];
4431 vert[ 7] = org2[1] - width * right2[1];
4432 vert[ 8] = org2[2] - width * right2[2];
4433 vert[ 9] = org2[0] + width * right2[0];
4434 vert[10] = org2[1] + width * right2[1];
4435 vert[11] = org2[2] + width * right2[2];
4438 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4440 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)
4442 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4446 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4447 fog = FogPoint_World(origin);
4449 R_Mesh_Matrix(&identitymatrix);
4450 GL_BlendFunc(blendfunc1, blendfunc2);
4452 GL_CullFace(GL_NONE);
4454 GL_DepthMask(false);
4455 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4456 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4457 GL_DepthTest(!depthdisable);
4459 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4460 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4461 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4462 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4463 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4464 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4465 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4466 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4467 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4468 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4469 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4470 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4472 R_Mesh_VertexPointer(vertex3f, 0, 0);
4473 R_Mesh_ColorPointer(NULL, 0, 0);
4474 R_Mesh_ResetTextureState();
4475 R_SetupGenericShader(true);
4476 R_Mesh_TexBind(0, R_GetTexture(texture));
4477 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4478 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4479 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4480 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4482 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4484 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4485 GL_BlendFunc(blendfunc1, GL_ONE);
4487 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4488 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4492 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4497 VectorSet(v, x, y, z);
4498 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4499 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4501 if (i == mesh->numvertices)
4503 if (mesh->numvertices < mesh->maxvertices)
4505 VectorCopy(v, vertex3f);
4506 mesh->numvertices++;
4508 return mesh->numvertices;
4514 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4518 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4519 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4520 e = mesh->element3i + mesh->numtriangles * 3;
4521 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4523 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4524 if (mesh->numtriangles < mesh->maxtriangles)
4529 mesh->numtriangles++;
4531 element[1] = element[2];
4535 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4539 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4540 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4541 e = mesh->element3i + mesh->numtriangles * 3;
4542 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4544 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4545 if (mesh->numtriangles < mesh->maxtriangles)
4550 mesh->numtriangles++;
4552 element[1] = element[2];
4556 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4557 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4559 int planenum, planenum2;
4562 mplane_t *plane, *plane2;
4564 double temppoints[2][256*3];
4565 // figure out how large a bounding box we need to properly compute this brush
4567 for (w = 0;w < numplanes;w++)
4568 maxdist = max(maxdist, planes[w].dist);
4569 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4570 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4571 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4575 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4576 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4578 if (planenum2 == planenum)
4580 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);
4583 if (tempnumpoints < 3)
4585 // generate elements forming a triangle fan for this polygon
4586 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4590 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)
4592 texturelayer_t *layer;
4593 layer = t->currentlayers + t->currentnumlayers++;
4595 layer->depthmask = depthmask;
4596 layer->blendfunc1 = blendfunc1;
4597 layer->blendfunc2 = blendfunc2;
4598 layer->texture = texture;
4599 layer->texmatrix = *matrix;
4600 layer->color[0] = r * r_refdef.view.colorscale;
4601 layer->color[1] = g * r_refdef.view.colorscale;
4602 layer->color[2] = b * r_refdef.view.colorscale;
4603 layer->color[3] = a;
4606 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4609 index = parms[2] + r_refdef.scene.time * parms[3];
4610 index -= floor(index);
4614 case Q3WAVEFUNC_NONE:
4615 case Q3WAVEFUNC_NOISE:
4616 case Q3WAVEFUNC_COUNT:
4619 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4620 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4621 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4622 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4623 case Q3WAVEFUNC_TRIANGLE:
4625 f = index - floor(index);
4636 return (float)(parms[0] + parms[1] * f);
4639 texture_t *R_GetCurrentTexture(texture_t *t)
4643 const entity_render_t *ent = rsurface.entity;
4644 dp_model_t *model = ent->model;
4647 q3shaderinfo_layer_tcmod_t *tcmod;
4649 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
4650 return t->currentframe;
4651 t->update_lastrenderframe = r_frame;
4652 t->update_lastrenderentity = (void *)ent;
4654 // switch to an alternate material if this is a q1bsp animated material
4656 texture_t *texture = t;
4657 int s = ent->skinnum;
4658 if ((unsigned int)s >= (unsigned int)model->numskins)
4660 if (model->skinscenes)
4662 if (model->skinscenes[s].framecount > 1)
4663 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4665 s = model->skinscenes[s].firstframe;
4668 t = t + s * model->num_surfaces;
4671 // use an alternate animation if the entity's frame is not 0,
4672 // and only if the texture has an alternate animation
4673 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
4674 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4676 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4678 texture->currentframe = t;
4681 // update currentskinframe to be a qw skin or animation frame
4682 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[i].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl"))
4684 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4686 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4687 if (developer_loading.integer)
4688 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4689 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);
4691 t->currentskinframe = r_qwskincache_skinframe[i];
4692 if (t->currentskinframe == NULL)
4693 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4695 else if (t->numskinframes >= 2)
4696 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4697 if (t->backgroundnumskinframes >= 2)
4698 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
4700 t->currentmaterialflags = t->basematerialflags;
4701 t->currentalpha = ent->alpha;
4702 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4703 t->currentalpha *= r_wateralpha.value;
4704 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4705 t->currentalpha *= t->r_water_wateralpha;
4706 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4707 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4708 if (!(ent->flags & RENDER_LIGHT))
4709 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4710 else if (rsurface.modeltexcoordlightmap2f == NULL)
4712 // pick a model lighting mode
4713 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4714 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4716 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4718 if (ent->effects & EF_ADDITIVE)
4719 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4720 else if (t->currentalpha < 1)
4721 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4722 if (ent->effects & EF_DOUBLESIDED)
4723 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4724 if (ent->effects & EF_NODEPTHTEST)
4725 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4726 if (ent->flags & RENDER_VIEWMODEL)
4727 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4728 if (t->backgroundnumskinframes)
4729 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4730 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4732 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4733 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4736 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4738 // there is no tcmod
4739 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4740 t->currenttexmatrix = r_waterscrollmatrix;
4742 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4745 switch(tcmod->tcmod)
4749 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4750 matrix = r_waterscrollmatrix;
4752 matrix = identitymatrix;
4754 case Q3TCMOD_ENTITYTRANSLATE:
4755 // this is used in Q3 to allow the gamecode to control texcoord
4756 // scrolling on the entity, which is not supported in darkplaces yet.
4757 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4759 case Q3TCMOD_ROTATE:
4760 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4761 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4762 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4765 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4767 case Q3TCMOD_SCROLL:
4768 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4770 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4771 w = (int) tcmod->parms[0];
4772 h = (int) tcmod->parms[1];
4773 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4775 idx = (int) floor(f * w * h);
4776 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4778 case Q3TCMOD_STRETCH:
4779 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4780 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4782 case Q3TCMOD_TRANSFORM:
4783 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4784 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4785 VectorSet(tcmat + 6, 0 , 0 , 1);
4786 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4787 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4789 case Q3TCMOD_TURBULENT:
4790 // this is handled in the RSurf_PrepareVertices function
4791 matrix = identitymatrix;
4794 // either replace or concatenate the transformation
4796 t->currenttexmatrix = matrix;
4799 matrix4x4_t temp = t->currenttexmatrix;
4800 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4804 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4805 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4806 t->glosstexture = r_texture_black;
4807 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4808 t->backgroundglosstexture = r_texture_black;
4809 t->specularpower = r_shadow_glossexponent.value;
4810 // TODO: store reference values for these in the texture?
4811 t->specularscale = 0;
4812 if (r_shadow_gloss.integer > 0)
4814 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4816 if (r_shadow_glossintensity.value > 0)
4818 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4819 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4820 t->specularscale = r_shadow_glossintensity.value;
4823 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4825 t->glosstexture = r_texture_white;
4826 t->backgroundglosstexture = r_texture_white;
4827 t->specularscale = r_shadow_gloss2intensity.value;
4831 // lightmaps mode looks bad with dlights using actual texturing, so turn
4832 // off the colormap and glossmap, but leave the normalmap on as it still
4833 // accurately represents the shading involved
4834 if (gl_lightmaps.integer)
4836 t->basetexture = r_texture_grey128;
4837 t->backgroundbasetexture = NULL;
4838 t->specularscale = 0;
4839 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
4842 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4843 VectorClear(t->dlightcolor);
4844 t->currentnumlayers = 0;
4845 if (t->currentmaterialflags & MATERIALFLAG_WALL)
4848 int blendfunc1, blendfunc2, depthmask;
4849 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4851 blendfunc1 = GL_SRC_ALPHA;
4852 blendfunc2 = GL_ONE;
4854 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4856 blendfunc1 = GL_SRC_ALPHA;
4857 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4859 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4861 blendfunc1 = t->customblendfunc[0];
4862 blendfunc2 = t->customblendfunc[1];
4866 blendfunc1 = GL_ONE;
4867 blendfunc2 = GL_ZERO;
4869 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4870 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4871 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4872 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4874 // fullbright is not affected by r_refdef.lightmapintensity
4875 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]);
4876 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4877 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]);
4878 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4879 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]);
4883 vec3_t ambientcolor;
4885 // set the color tint used for lights affecting this surface
4886 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4888 // q3bsp has no lightmap updates, so the lightstylevalue that
4889 // would normally be baked into the lightmap must be
4890 // applied to the color
4891 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4892 if (ent->model->type == mod_brushq3)
4893 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4894 colorscale *= r_refdef.lightmapintensity;
4895 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
4896 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4897 // basic lit geometry
4898 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]);
4899 // add pants/shirt if needed
4900 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4901 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]);
4902 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4903 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]);
4904 // now add ambient passes if needed
4905 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4907 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]);
4908 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4909 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]);
4910 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4911 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]);
4914 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4915 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]);
4916 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4918 // if this is opaque use alpha blend which will darken the earlier
4921 // if this is an alpha blended material, all the earlier passes
4922 // were darkened by fog already, so we only need to add the fog
4923 // color ontop through the fog mask texture
4925 // if this is an additive blended material, all the earlier passes
4926 // were darkened by fog already, and we should not add fog color
4927 // (because the background was not darkened, there is no fog color
4928 // that was lost behind it).
4929 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]);
4933 return t->currentframe;
4936 rsurfacestate_t rsurface;
4938 void R_Mesh_ResizeArrays(int newvertices)
4941 if (rsurface.array_size >= newvertices)
4943 if (rsurface.array_modelvertex3f)
4944 Mem_Free(rsurface.array_modelvertex3f);
4945 rsurface.array_size = (newvertices + 1023) & ~1023;
4946 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4947 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4948 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4949 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4950 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4951 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4952 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4953 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4954 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4955 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4956 rsurface.array_color4f = base + rsurface.array_size * 27;
4957 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4960 void RSurf_ActiveWorldEntity(void)
4962 dp_model_t *model = r_refdef.scene.worldmodel;
4963 //if (rsurface.entity == r_refdef.scene.worldentity)
4965 rsurface.entity = r_refdef.scene.worldentity;
4966 if (rsurface.array_size < model->surfmesh.num_vertices)
4967 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4968 rsurface.matrix = identitymatrix;
4969 rsurface.inversematrix = identitymatrix;
4970 R_Mesh_Matrix(&identitymatrix);
4971 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4972 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4973 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4974 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4975 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4976 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4977 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
4978 rsurface.frameblend[0].lerp = 1;
4979 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4980 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4981 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4982 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4983 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4984 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4985 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4986 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4987 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4988 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4989 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4990 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4991 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4992 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4993 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4994 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4995 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4996 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4997 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4998 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4999 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5000 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5001 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5002 rsurface.modelelement3i = model->surfmesh.data_element3i;
5003 rsurface.modelelement3s = model->surfmesh.data_element3s;
5004 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5005 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5006 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5007 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5008 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5009 rsurface.modelsurfaces = model->data_surfaces;
5010 rsurface.generatedvertex = false;
5011 rsurface.vertex3f = rsurface.modelvertex3f;
5012 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5013 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5014 rsurface.svector3f = rsurface.modelsvector3f;
5015 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5016 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5017 rsurface.tvector3f = rsurface.modeltvector3f;
5018 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5019 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5020 rsurface.normal3f = rsurface.modelnormal3f;
5021 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5022 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5023 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5026 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5028 dp_model_t *model = ent->model;
5029 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5031 rsurface.entity = (entity_render_t *)ent;
5032 if (rsurface.array_size < model->surfmesh.num_vertices)
5033 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5034 rsurface.matrix = ent->matrix;
5035 rsurface.inversematrix = ent->inversematrix;
5036 R_Mesh_Matrix(&rsurface.matrix);
5037 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5038 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5039 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5040 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5041 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5042 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5043 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5044 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5045 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5046 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5047 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5048 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5049 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5050 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5051 if (ent->model->brush.submodel)
5053 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5054 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5056 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5060 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5061 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5062 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5063 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5064 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5066 else if (wantnormals)
5068 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5069 rsurface.modelsvector3f = NULL;
5070 rsurface.modeltvector3f = NULL;
5071 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5072 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5076 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5077 rsurface.modelsvector3f = NULL;
5078 rsurface.modeltvector3f = NULL;
5079 rsurface.modelnormal3f = NULL;
5080 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5082 rsurface.modelvertex3f_bufferobject = 0;
5083 rsurface.modelvertex3f_bufferoffset = 0;
5084 rsurface.modelsvector3f_bufferobject = 0;
5085 rsurface.modelsvector3f_bufferoffset = 0;
5086 rsurface.modeltvector3f_bufferobject = 0;
5087 rsurface.modeltvector3f_bufferoffset = 0;
5088 rsurface.modelnormal3f_bufferobject = 0;
5089 rsurface.modelnormal3f_bufferoffset = 0;
5090 rsurface.generatedvertex = true;
5094 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5095 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5096 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5097 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5098 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5099 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5100 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5101 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5102 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5103 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5104 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5105 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5106 rsurface.generatedvertex = false;
5108 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5109 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5110 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5111 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5112 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5113 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5114 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5115 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5116 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5117 rsurface.modelelement3i = model->surfmesh.data_element3i;
5118 rsurface.modelelement3s = model->surfmesh.data_element3s;
5119 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5120 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5121 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5122 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5123 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5124 rsurface.modelsurfaces = model->data_surfaces;
5125 rsurface.vertex3f = rsurface.modelvertex3f;
5126 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5127 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5128 rsurface.svector3f = rsurface.modelsvector3f;
5129 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5130 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5131 rsurface.tvector3f = rsurface.modeltvector3f;
5132 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5133 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5134 rsurface.normal3f = rsurface.modelnormal3f;
5135 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5136 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5137 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5140 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5141 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5144 int texturesurfaceindex;
5149 const float *v1, *in_tc;
5151 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5153 q3shaderinfo_deform_t *deform;
5154 // 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
5155 if (rsurface.generatedvertex)
5157 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5158 generatenormals = true;
5159 for (i = 0;i < Q3MAXDEFORMS;i++)
5161 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5163 generatetangents = true;
5164 generatenormals = true;
5166 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5167 generatenormals = true;
5169 if (generatenormals && !rsurface.modelnormal3f)
5171 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5172 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5173 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5174 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5176 if (generatetangents && !rsurface.modelsvector3f)
5178 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5179 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5180 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5181 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5182 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5183 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5184 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);
5187 rsurface.vertex3f = rsurface.modelvertex3f;
5188 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5189 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5190 rsurface.svector3f = rsurface.modelsvector3f;
5191 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5192 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5193 rsurface.tvector3f = rsurface.modeltvector3f;
5194 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5195 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5196 rsurface.normal3f = rsurface.modelnormal3f;
5197 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5198 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5199 // if vertices are deformed (sprite flares and things in maps, possibly
5200 // water waves, bulges and other deformations), generate them into
5201 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5202 // (may be static model data or generated data for an animated model, or
5203 // the previous deform pass)
5204 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5206 switch (deform->deform)
5209 case Q3DEFORM_PROJECTIONSHADOW:
5210 case Q3DEFORM_TEXT0:
5211 case Q3DEFORM_TEXT1:
5212 case Q3DEFORM_TEXT2:
5213 case Q3DEFORM_TEXT3:
5214 case Q3DEFORM_TEXT4:
5215 case Q3DEFORM_TEXT5:
5216 case Q3DEFORM_TEXT6:
5217 case Q3DEFORM_TEXT7:
5220 case Q3DEFORM_AUTOSPRITE:
5221 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5222 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5223 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5224 VectorNormalize(newforward);
5225 VectorNormalize(newright);
5226 VectorNormalize(newup);
5227 // make deformed versions of only the model vertices used by the specified surfaces
5228 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5230 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5231 // a single autosprite surface can contain multiple sprites...
5232 for (j = 0;j < surface->num_vertices - 3;j += 4)
5234 VectorClear(center);
5235 for (i = 0;i < 4;i++)
5236 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5237 VectorScale(center, 0.25f, center);
5238 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5239 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5240 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5241 for (i = 0;i < 4;i++)
5243 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5244 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5247 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);
5248 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);
5250 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5251 rsurface.vertex3f_bufferobject = 0;
5252 rsurface.vertex3f_bufferoffset = 0;
5253 rsurface.svector3f = rsurface.array_deformedsvector3f;
5254 rsurface.svector3f_bufferobject = 0;
5255 rsurface.svector3f_bufferoffset = 0;
5256 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5257 rsurface.tvector3f_bufferobject = 0;
5258 rsurface.tvector3f_bufferoffset = 0;
5259 rsurface.normal3f = rsurface.array_deformednormal3f;
5260 rsurface.normal3f_bufferobject = 0;
5261 rsurface.normal3f_bufferoffset = 0;
5263 case Q3DEFORM_AUTOSPRITE2:
5264 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5265 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5266 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5267 VectorNormalize(newforward);
5268 VectorNormalize(newright);
5269 VectorNormalize(newup);
5270 // make deformed versions of only the model vertices used by the specified surfaces
5271 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5273 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5274 const float *v1, *v2;
5284 memset(shortest, 0, sizeof(shortest));
5285 // a single autosprite surface can contain multiple sprites...
5286 for (j = 0;j < surface->num_vertices - 3;j += 4)
5288 VectorClear(center);
5289 for (i = 0;i < 4;i++)
5290 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5291 VectorScale(center, 0.25f, center);
5292 // find the two shortest edges, then use them to define the
5293 // axis vectors for rotating around the central axis
5294 for (i = 0;i < 6;i++)
5296 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5297 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5299 Debug_PolygonBegin(NULL, 0);
5300 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5301 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);
5302 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5305 l = VectorDistance2(v1, v2);
5306 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5308 l += (1.0f / 1024.0f);
5309 if (shortest[0].length2 > l || i == 0)
5311 shortest[1] = shortest[0];
5312 shortest[0].length2 = l;
5313 shortest[0].v1 = v1;
5314 shortest[0].v2 = v2;
5316 else if (shortest[1].length2 > l || i == 1)
5318 shortest[1].length2 = l;
5319 shortest[1].v1 = v1;
5320 shortest[1].v2 = v2;
5323 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5324 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5326 Debug_PolygonBegin(NULL, 0);
5327 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5328 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);
5329 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5332 // this calculates the right vector from the shortest edge
5333 // and the up vector from the edge midpoints
5334 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5335 VectorNormalize(right);
5336 VectorSubtract(end, start, up);
5337 VectorNormalize(up);
5338 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5339 //VectorSubtract(rsurface.modelorg, center, forward);
5340 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5341 VectorNegate(forward, forward);
5342 VectorReflect(forward, 0, up, forward);
5343 VectorNormalize(forward);
5344 CrossProduct(up, forward, newright);
5345 VectorNormalize(newright);
5347 Debug_PolygonBegin(NULL, 0);
5348 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);
5349 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5350 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5354 Debug_PolygonBegin(NULL, 0);
5355 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5356 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5357 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5360 // rotate the quad around the up axis vector, this is made
5361 // especially easy by the fact we know the quad is flat,
5362 // so we only have to subtract the center position and
5363 // measure distance along the right vector, and then
5364 // multiply that by the newright vector and add back the
5366 // we also need to subtract the old position to undo the
5367 // displacement from the center, which we do with a
5368 // DotProduct, the subtraction/addition of center is also
5369 // optimized into DotProducts here
5370 l = DotProduct(right, center);
5371 for (i = 0;i < 4;i++)
5373 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5374 f = DotProduct(right, v1) - l;
5375 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5378 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);
5379 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);
5381 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5382 rsurface.vertex3f_bufferobject = 0;
5383 rsurface.vertex3f_bufferoffset = 0;
5384 rsurface.svector3f = rsurface.array_deformedsvector3f;
5385 rsurface.svector3f_bufferobject = 0;
5386 rsurface.svector3f_bufferoffset = 0;
5387 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5388 rsurface.tvector3f_bufferobject = 0;
5389 rsurface.tvector3f_bufferoffset = 0;
5390 rsurface.normal3f = rsurface.array_deformednormal3f;
5391 rsurface.normal3f_bufferobject = 0;
5392 rsurface.normal3f_bufferoffset = 0;
5394 case Q3DEFORM_NORMAL:
5395 // deform the normals to make reflections wavey
5396 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5398 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5399 for (j = 0;j < surface->num_vertices;j++)
5402 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5403 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5404 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5405 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5406 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5407 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5408 VectorNormalize(normal);
5410 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);
5412 rsurface.svector3f = rsurface.array_deformedsvector3f;
5413 rsurface.svector3f_bufferobject = 0;
5414 rsurface.svector3f_bufferoffset = 0;
5415 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5416 rsurface.tvector3f_bufferobject = 0;
5417 rsurface.tvector3f_bufferoffset = 0;
5418 rsurface.normal3f = rsurface.array_deformednormal3f;
5419 rsurface.normal3f_bufferobject = 0;
5420 rsurface.normal3f_bufferoffset = 0;
5423 // deform vertex array to make wavey water and flags and such
5424 waveparms[0] = deform->waveparms[0];
5425 waveparms[1] = deform->waveparms[1];
5426 waveparms[2] = deform->waveparms[2];
5427 waveparms[3] = deform->waveparms[3];
5428 // this is how a divisor of vertex influence on deformation
5429 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5430 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5431 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5433 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5434 for (j = 0;j < surface->num_vertices;j++)
5436 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5437 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5438 // if the wavefunc depends on time, evaluate it per-vertex
5441 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5442 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5444 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5447 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5448 rsurface.vertex3f_bufferobject = 0;
5449 rsurface.vertex3f_bufferoffset = 0;
5451 case Q3DEFORM_BULGE:
5452 // deform vertex array to make the surface have moving bulges
5453 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5455 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5456 for (j = 0;j < surface->num_vertices;j++)
5458 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5459 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5462 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5463 rsurface.vertex3f_bufferobject = 0;
5464 rsurface.vertex3f_bufferoffset = 0;
5467 // deform vertex array
5468 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5469 VectorScale(deform->parms, scale, waveparms);
5470 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5472 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5473 for (j = 0;j < surface->num_vertices;j++)
5474 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5476 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5477 rsurface.vertex3f_bufferobject = 0;
5478 rsurface.vertex3f_bufferoffset = 0;
5482 // generate texcoords based on the chosen texcoord source
5483 switch(rsurface.texture->tcgen.tcgen)
5486 case Q3TCGEN_TEXTURE:
5487 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5488 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5489 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5491 case Q3TCGEN_LIGHTMAP:
5492 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5493 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5494 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5496 case Q3TCGEN_VECTOR:
5497 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5499 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5500 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)
5502 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5503 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5506 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5507 rsurface.texcoordtexture2f_bufferobject = 0;
5508 rsurface.texcoordtexture2f_bufferoffset = 0;
5510 case Q3TCGEN_ENVIRONMENT:
5511 // make environment reflections using a spheremap
5512 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5514 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5515 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5516 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5517 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5518 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5520 // identical to Q3A's method, but executed in worldspace so
5521 // carried models can be shiny too
5523 float viewer[3], d, reflected[3], worldreflected[3];
5525 VectorSubtract(rsurface.modelorg, vertex, viewer);
5526 // VectorNormalize(viewer);
5528 d = DotProduct(normal, viewer);
5530 reflected[0] = normal[0]*2*d - viewer[0];
5531 reflected[1] = normal[1]*2*d - viewer[1];
5532 reflected[2] = normal[2]*2*d - viewer[2];
5533 // note: this is proportinal to viewer, so we can normalize later
5535 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
5536 VectorNormalize(worldreflected);
5538 // note: this sphere map only uses world x and z!
5539 // so positive and negative y will LOOK THE SAME.
5540 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
5541 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
5544 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5545 rsurface.texcoordtexture2f_bufferobject = 0;
5546 rsurface.texcoordtexture2f_bufferoffset = 0;
5549 // the only tcmod that needs software vertex processing is turbulent, so
5550 // check for it here and apply the changes if needed
5551 // and we only support that as the first one
5552 // (handling a mixture of turbulent and other tcmods would be problematic
5553 // without punting it entirely to a software path)
5554 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5556 amplitude = rsurface.texture->tcmods[0].parms[1];
5557 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5558 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5560 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5561 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)
5563 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5564 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5567 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5568 rsurface.texcoordtexture2f_bufferobject = 0;
5569 rsurface.texcoordtexture2f_bufferoffset = 0;
5571 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5572 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5573 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5574 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5577 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5580 const msurface_t *surface = texturesurfacelist[0];
5581 const msurface_t *surface2;
5586 // TODO: lock all array ranges before render, rather than on each surface
5587 if (texturenumsurfaces == 1)
5589 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5590 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5592 else if (r_batchmode.integer == 2)
5594 #define MAXBATCHTRIANGLES 4096
5595 int batchtriangles = 0;
5596 int batchelements[MAXBATCHTRIANGLES*3];
5597 for (i = 0;i < texturenumsurfaces;i = j)
5599 surface = texturesurfacelist[i];
5601 if (surface->num_triangles > MAXBATCHTRIANGLES)
5603 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5606 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5607 batchtriangles = surface->num_triangles;
5608 firstvertex = surface->num_firstvertex;
5609 endvertex = surface->num_firstvertex + surface->num_vertices;
5610 for (;j < texturenumsurfaces;j++)
5612 surface2 = texturesurfacelist[j];
5613 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5615 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5616 batchtriangles += surface2->num_triangles;
5617 firstvertex = min(firstvertex, surface2->num_firstvertex);
5618 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5620 surface2 = texturesurfacelist[j-1];
5621 numvertices = endvertex - firstvertex;
5622 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5625 else if (r_batchmode.integer == 1)
5627 for (i = 0;i < texturenumsurfaces;i = j)
5629 surface = texturesurfacelist[i];
5630 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5631 if (texturesurfacelist[j] != surface2)
5633 surface2 = texturesurfacelist[j-1];
5634 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5635 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5636 GL_LockArrays(surface->num_firstvertex, numvertices);
5637 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5642 for (i = 0;i < texturenumsurfaces;i++)
5644 surface = texturesurfacelist[i];
5645 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5646 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5651 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5653 int i, planeindex, vertexindex;
5657 r_waterstate_waterplane_t *p, *bestp;
5658 msurface_t *surface;
5659 if (r_waterstate.renderingscene)
5661 for (i = 0;i < texturenumsurfaces;i++)
5663 surface = texturesurfacelist[i];
5664 if (lightmaptexunit >= 0)
5665 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5666 if (deluxemaptexunit >= 0)
5667 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5668 // pick the closest matching water plane
5671 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5674 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5676 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5677 d += fabs(PlaneDiff(vert, &p->plane));
5679 if (bestd > d || !bestp)
5687 if (refractiontexunit >= 0)
5688 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5689 if (reflectiontexunit >= 0)
5690 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5694 if (refractiontexunit >= 0)
5695 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5696 if (reflectiontexunit >= 0)
5697 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5699 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5700 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5704 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5708 const msurface_t *surface = texturesurfacelist[0];
5709 const msurface_t *surface2;
5714 // TODO: lock all array ranges before render, rather than on each surface
5715 if (texturenumsurfaces == 1)
5717 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5718 if (deluxemaptexunit >= 0)
5719 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5720 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5721 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5723 else if (r_batchmode.integer == 2)
5725 #define MAXBATCHTRIANGLES 4096
5726 int batchtriangles = 0;
5727 int batchelements[MAXBATCHTRIANGLES*3];
5728 for (i = 0;i < texturenumsurfaces;i = j)
5730 surface = texturesurfacelist[i];
5731 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5732 if (deluxemaptexunit >= 0)
5733 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5735 if (surface->num_triangles > MAXBATCHTRIANGLES)
5737 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5740 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5741 batchtriangles = surface->num_triangles;
5742 firstvertex = surface->num_firstvertex;
5743 endvertex = surface->num_firstvertex + surface->num_vertices;
5744 for (;j < texturenumsurfaces;j++)
5746 surface2 = texturesurfacelist[j];
5747 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5749 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5750 batchtriangles += surface2->num_triangles;
5751 firstvertex = min(firstvertex, surface2->num_firstvertex);
5752 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5754 surface2 = texturesurfacelist[j-1];
5755 numvertices = endvertex - firstvertex;
5756 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5759 else if (r_batchmode.integer == 1)
5762 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5763 for (i = 0;i < texturenumsurfaces;i = j)
5765 surface = texturesurfacelist[i];
5766 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5767 if (texturesurfacelist[j] != surface2)
5769 Con_Printf(" %i", j - i);
5772 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5774 for (i = 0;i < texturenumsurfaces;i = j)
5776 surface = texturesurfacelist[i];
5777 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5778 if (deluxemaptexunit >= 0)
5779 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5780 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5781 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5784 Con_Printf(" %i", j - i);
5786 surface2 = texturesurfacelist[j-1];
5787 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5788 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5789 GL_LockArrays(surface->num_firstvertex, numvertices);
5790 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5798 for (i = 0;i < texturenumsurfaces;i++)
5800 surface = texturesurfacelist[i];
5801 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5802 if (deluxemaptexunit >= 0)
5803 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5804 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5805 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5810 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5813 int texturesurfaceindex;
5814 if (r_showsurfaces.integer == 2)
5816 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5818 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5819 for (j = 0;j < surface->num_triangles;j++)
5821 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5822 GL_Color(f, f, f, 1);
5823 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5829 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5831 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5832 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5833 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);
5834 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5835 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5840 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
5842 int texturesurfaceindex;
5845 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5847 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5848 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)
5856 rsurface.lightmapcolor4f = rsurface.array_color4f;
5857 rsurface.lightmapcolor4f_bufferobject = 0;
5858 rsurface.lightmapcolor4f_bufferoffset = 0;
5861 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5863 int texturesurfaceindex;
5867 if (rsurface.lightmapcolor4f)
5869 // generate color arrays for the surfaces in this list
5870 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5872 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5873 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)
5875 f = FogPoint_Model(v);
5885 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5887 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5888 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)
5890 f = FogPoint_Model(v);
5898 rsurface.lightmapcolor4f = rsurface.array_color4f;
5899 rsurface.lightmapcolor4f_bufferobject = 0;
5900 rsurface.lightmapcolor4f_bufferoffset = 0;
5903 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
5905 int texturesurfaceindex;
5909 if (!rsurface.lightmapcolor4f)
5911 // generate color arrays for the surfaces in this list
5912 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5914 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5915 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)
5917 f = FogPoint_Model(v);
5918 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
5919 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
5920 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
5924 rsurface.lightmapcolor4f = rsurface.array_color4f;
5925 rsurface.lightmapcolor4f_bufferobject = 0;
5926 rsurface.lightmapcolor4f_bufferoffset = 0;
5929 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5931 int texturesurfaceindex;
5934 if (!rsurface.lightmapcolor4f)
5936 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5938 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5939 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)
5947 rsurface.lightmapcolor4f = rsurface.array_color4f;
5948 rsurface.lightmapcolor4f_bufferobject = 0;
5949 rsurface.lightmapcolor4f_bufferoffset = 0;
5952 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
5954 int texturesurfaceindex;
5957 if (!rsurface.lightmapcolor4f)
5959 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5961 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5962 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)
5964 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
5965 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
5966 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
5970 rsurface.lightmapcolor4f = rsurface.array_color4f;
5971 rsurface.lightmapcolor4f_bufferobject = 0;
5972 rsurface.lightmapcolor4f_bufferoffset = 0;
5975 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5978 rsurface.lightmapcolor4f = NULL;
5979 rsurface.lightmapcolor4f_bufferobject = 0;
5980 rsurface.lightmapcolor4f_bufferoffset = 0;
5981 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5982 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5983 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5984 GL_Color(r, g, b, a);
5985 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5988 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5990 // TODO: optimize applyfog && applycolor case
5991 // just apply fog if necessary, and tint the fog color array if necessary
5992 rsurface.lightmapcolor4f = NULL;
5993 rsurface.lightmapcolor4f_bufferobject = 0;
5994 rsurface.lightmapcolor4f_bufferoffset = 0;
5995 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5996 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5997 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5998 GL_Color(r, g, b, a);
5999 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6002 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6004 int texturesurfaceindex;
6008 if (texturesurfacelist[0]->lightmapinfo)
6010 // generate color arrays for the surfaces in this list
6011 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6013 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6014 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6016 if (surface->lightmapinfo->samples)
6018 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6019 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6020 VectorScale(lm, scale, c);
6021 if (surface->lightmapinfo->styles[1] != 255)
6023 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6025 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6026 VectorMA(c, scale, lm, c);
6027 if (surface->lightmapinfo->styles[2] != 255)
6030 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6031 VectorMA(c, scale, lm, c);
6032 if (surface->lightmapinfo->styles[3] != 255)
6035 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6036 VectorMA(c, scale, lm, c);
6046 rsurface.lightmapcolor4f = rsurface.array_color4f;
6047 rsurface.lightmapcolor4f_bufferobject = 0;
6048 rsurface.lightmapcolor4f_bufferoffset = 0;
6052 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6053 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6054 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6056 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6057 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6058 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6059 GL_Color(r, g, b, a);
6060 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6063 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6065 int texturesurfaceindex;
6068 float *v, *c, *c2, alpha;
6069 vec3_t ambientcolor;
6070 vec3_t diffusecolor;
6074 VectorCopy(rsurface.modellight_lightdir, lightdir);
6075 f = 0.5f * r_refdef.lightmapintensity;
6076 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6077 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6078 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6079 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6080 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6081 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6083 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6085 // generate color arrays for the surfaces in this list
6086 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6088 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6089 int numverts = surface->num_vertices;
6090 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6091 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6092 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6093 // q3-style directional shading
6094 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6096 if ((f = DotProduct(c2, lightdir)) > 0)
6097 VectorMA(ambientcolor, f, diffusecolor, c);
6099 VectorCopy(ambientcolor, c);
6107 rsurface.lightmapcolor4f = rsurface.array_color4f;
6108 rsurface.lightmapcolor4f_bufferobject = 0;
6109 rsurface.lightmapcolor4f_bufferoffset = 0;
6110 *applycolor = false;
6114 *r = ambientcolor[0];
6115 *g = ambientcolor[1];
6116 *b = ambientcolor[2];
6117 rsurface.lightmapcolor4f = NULL;
6118 rsurface.lightmapcolor4f_bufferobject = 0;
6119 rsurface.lightmapcolor4f_bufferoffset = 0;
6123 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6125 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6126 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6127 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6128 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6129 GL_Color(r, g, b, a);
6130 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6133 void RSurf_SetupDepthAndCulling(void)
6135 // submodels are biased to avoid z-fighting with world surfaces that they
6136 // may be exactly overlapping (avoids z-fighting artifacts on certain
6137 // doors and things in Quake maps)
6138 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6139 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6140 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6141 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6144 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6146 // transparent sky would be ridiculous
6147 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6149 R_SetupGenericShader(false);
6152 skyrendernow = false;
6153 // we have to force off the water clipping plane while rendering sky
6157 // restore entity matrix
6158 R_Mesh_Matrix(&rsurface.matrix);
6160 RSurf_SetupDepthAndCulling();
6162 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6163 // skymasking on them, and Quake3 never did sky masking (unlike
6164 // software Quake and software Quake2), so disable the sky masking
6165 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6166 // and skymasking also looks very bad when noclipping outside the
6167 // level, so don't use it then either.
6168 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6170 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6171 R_Mesh_ColorPointer(NULL, 0, 0);
6172 R_Mesh_ResetTextureState();
6173 if (skyrendermasked)
6175 R_SetupDepthOrShadowShader();
6176 // depth-only (masking)
6177 GL_ColorMask(0,0,0,0);
6178 // just to make sure that braindead drivers don't draw
6179 // anything despite that colormask...
6180 GL_BlendFunc(GL_ZERO, GL_ONE);
6184 R_SetupGenericShader(false);
6186 GL_BlendFunc(GL_ONE, GL_ZERO);
6188 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6189 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6190 if (skyrendermasked)
6191 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6193 R_Mesh_ResetTextureState();
6194 GL_Color(1, 1, 1, 1);
6197 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6199 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6202 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6203 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6204 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6205 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6206 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6207 if (rsurface.texture->backgroundcurrentskinframe)
6209 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6210 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6211 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6212 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6214 if(rsurface.texture->colormapping)
6216 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6217 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6219 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6220 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6221 R_Mesh_ColorPointer(NULL, 0, 0);
6223 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6225 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6227 // render background
6228 GL_BlendFunc(GL_ONE, GL_ZERO);
6230 GL_AlphaTest(false);
6232 GL_Color(1, 1, 1, 1);
6233 R_Mesh_ColorPointer(NULL, 0, 0);
6235 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6236 if (r_glsl_permutation)
6238 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6239 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6240 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6241 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6242 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6243 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6244 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);
6246 GL_LockArrays(0, 0);
6248 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6249 GL_DepthMask(false);
6250 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6251 R_Mesh_ColorPointer(NULL, 0, 0);
6253 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6254 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6255 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6258 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6259 if (!r_glsl_permutation)
6262 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6263 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6264 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6265 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6266 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6267 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6269 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6271 GL_BlendFunc(GL_ONE, GL_ZERO);
6273 GL_AlphaTest(false);
6277 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6278 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6279 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6282 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6284 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6285 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);
6287 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6291 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6292 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);
6294 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6296 GL_LockArrays(0, 0);
6299 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6301 // OpenGL 1.3 path - anything not completely ancient
6302 int texturesurfaceindex;
6303 qboolean applycolor;
6307 const texturelayer_t *layer;
6308 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6310 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6313 int layertexrgbscale;
6314 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6316 if (layerindex == 0)
6320 GL_AlphaTest(false);
6321 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6324 GL_DepthMask(layer->depthmask && writedepth);
6325 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6326 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6328 layertexrgbscale = 4;
6329 VectorScale(layer->color, 0.25f, layercolor);
6331 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6333 layertexrgbscale = 2;
6334 VectorScale(layer->color, 0.5f, layercolor);
6338 layertexrgbscale = 1;
6339 VectorScale(layer->color, 1.0f, layercolor);
6341 layercolor[3] = layer->color[3];
6342 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6343 R_Mesh_ColorPointer(NULL, 0, 0);
6344 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6345 switch (layer->type)
6347 case TEXTURELAYERTYPE_LITTEXTURE:
6348 memset(&m, 0, sizeof(m));
6349 m.tex[0] = R_GetTexture(r_texture_white);
6350 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6351 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6352 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6353 m.tex[1] = R_GetTexture(layer->texture);
6354 m.texmatrix[1] = layer->texmatrix;
6355 m.texrgbscale[1] = layertexrgbscale;
6356 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6357 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6358 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6359 R_Mesh_TextureState(&m);
6360 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6361 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6362 else if (rsurface.uselightmaptexture)
6363 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6365 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6367 case TEXTURELAYERTYPE_TEXTURE:
6368 memset(&m, 0, sizeof(m));
6369 m.tex[0] = R_GetTexture(layer->texture);
6370 m.texmatrix[0] = layer->texmatrix;
6371 m.texrgbscale[0] = layertexrgbscale;
6372 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6373 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6374 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6375 R_Mesh_TextureState(&m);
6376 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6378 case TEXTURELAYERTYPE_FOG:
6379 memset(&m, 0, sizeof(m));
6380 m.texrgbscale[0] = layertexrgbscale;
6383 m.tex[0] = R_GetTexture(layer->texture);
6384 m.texmatrix[0] = layer->texmatrix;
6385 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6386 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6387 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6389 R_Mesh_TextureState(&m);
6390 // generate a color array for the fog pass
6391 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6392 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6396 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6397 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)
6399 f = 1 - FogPoint_Model(v);
6400 c[0] = layercolor[0];
6401 c[1] = layercolor[1];
6402 c[2] = layercolor[2];
6403 c[3] = f * layercolor[3];
6406 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6409 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6411 GL_LockArrays(0, 0);
6414 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6416 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6417 GL_AlphaTest(false);
6421 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6423 // OpenGL 1.1 - crusty old voodoo path
6424 int texturesurfaceindex;
6428 const texturelayer_t *layer;
6429 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6431 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6433 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6435 if (layerindex == 0)
6439 GL_AlphaTest(false);
6440 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6443 GL_DepthMask(layer->depthmask && writedepth);
6444 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6445 R_Mesh_ColorPointer(NULL, 0, 0);
6446 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6447 switch (layer->type)
6449 case TEXTURELAYERTYPE_LITTEXTURE:
6450 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6452 // two-pass lit texture with 2x rgbscale
6453 // first the lightmap pass
6454 memset(&m, 0, sizeof(m));
6455 m.tex[0] = R_GetTexture(r_texture_white);
6456 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6457 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6458 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6459 R_Mesh_TextureState(&m);
6460 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6461 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6462 else if (rsurface.uselightmaptexture)
6463 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6465 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6466 GL_LockArrays(0, 0);
6467 // then apply the texture to it
6468 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6469 memset(&m, 0, sizeof(m));
6470 m.tex[0] = R_GetTexture(layer->texture);
6471 m.texmatrix[0] = layer->texmatrix;
6472 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6473 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6474 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6475 R_Mesh_TextureState(&m);
6476 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);
6480 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6481 memset(&m, 0, sizeof(m));
6482 m.tex[0] = R_GetTexture(layer->texture);
6483 m.texmatrix[0] = layer->texmatrix;
6484 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6485 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6486 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6487 R_Mesh_TextureState(&m);
6488 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6489 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);
6491 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);
6494 case TEXTURELAYERTYPE_TEXTURE:
6495 // singletexture unlit texture with transparency support
6496 memset(&m, 0, sizeof(m));
6497 m.tex[0] = R_GetTexture(layer->texture);
6498 m.texmatrix[0] = layer->texmatrix;
6499 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6500 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6501 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6502 R_Mesh_TextureState(&m);
6503 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);
6505 case TEXTURELAYERTYPE_FOG:
6506 // singletexture fogging
6507 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6510 memset(&m, 0, sizeof(m));
6511 m.tex[0] = R_GetTexture(layer->texture);
6512 m.texmatrix[0] = layer->texmatrix;
6513 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6514 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6515 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6516 R_Mesh_TextureState(&m);
6519 R_Mesh_ResetTextureState();
6520 // generate a color array for the fog pass
6521 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6525 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6526 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)
6528 f = 1 - FogPoint_Model(v);
6529 c[0] = layer->color[0];
6530 c[1] = layer->color[1];
6531 c[2] = layer->color[2];
6532 c[3] = f * layer->color[3];
6535 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6538 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6540 GL_LockArrays(0, 0);
6543 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6545 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6546 GL_AlphaTest(false);
6550 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6554 GL_AlphaTest(false);
6555 R_Mesh_ColorPointer(NULL, 0, 0);
6556 R_Mesh_ResetTextureState();
6557 R_SetupGenericShader(false);
6559 if(rsurface.texture && rsurface.texture->currentskinframe)
6560 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6569 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6571 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
6572 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
6573 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
6576 // brighten it up (as texture value 127 means "unlit")
6577 c[0] *= 2 * r_refdef.view.colorscale;
6578 c[1] *= 2 * r_refdef.view.colorscale;
6579 c[2] *= 2 * r_refdef.view.colorscale;
6581 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6582 c[3] *= r_wateralpha.value;
6584 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6586 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6587 GL_DepthMask(false);
6589 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6591 GL_BlendFunc(GL_ONE, GL_ONE);
6592 GL_DepthMask(false);
6594 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6596 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6597 GL_DepthMask(false);
6599 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6601 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6602 GL_DepthMask(false);
6606 GL_BlendFunc(GL_ONE, GL_ZERO);
6607 GL_DepthMask(writedepth);
6610 rsurface.lightmapcolor4f = NULL;
6612 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6614 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6616 rsurface.lightmapcolor4f = NULL;
6617 rsurface.lightmapcolor4f_bufferobject = 0;
6618 rsurface.lightmapcolor4f_bufferoffset = 0;
6620 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6622 qboolean applycolor = true;
6625 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6627 r_refdef.lightmapintensity = 1;
6628 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6629 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6633 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6635 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6636 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6637 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6640 if(!rsurface.lightmapcolor4f)
6641 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6643 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6644 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6645 if(r_refdef.fogenabled)
6646 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6648 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6649 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6652 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6655 RSurf_SetupDepthAndCulling();
6656 if (r_showsurfaces.integer == 3)
6657 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6658 else if (r_glsl.integer && gl_support_fragment_shader)
6659 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6660 else if (gl_combine.integer && r_textureunits.integer >= 2)
6661 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6663 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6667 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6670 RSurf_SetupDepthAndCulling();
6671 if (r_showsurfaces.integer == 3)
6672 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6673 else if (r_glsl.integer && gl_support_fragment_shader)
6674 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6675 else if (gl_combine.integer && r_textureunits.integer >= 2)
6676 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6678 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6682 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6685 int texturenumsurfaces, endsurface;
6687 msurface_t *surface;
6688 msurface_t *texturesurfacelist[1024];
6690 // if the model is static it doesn't matter what value we give for
6691 // wantnormals and wanttangents, so this logic uses only rules applicable
6692 // to a model, knowing that they are meaningless otherwise
6693 if (ent == r_refdef.scene.worldentity)
6694 RSurf_ActiveWorldEntity();
6695 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6696 RSurf_ActiveModelEntity(ent, false, false);
6698 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6700 for (i = 0;i < numsurfaces;i = j)
6703 surface = rsurface.modelsurfaces + surfacelist[i];
6704 texture = surface->texture;
6705 rsurface.texture = R_GetCurrentTexture(texture);
6706 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6707 // scan ahead until we find a different texture
6708 endsurface = min(i + 1024, numsurfaces);
6709 texturenumsurfaces = 0;
6710 texturesurfacelist[texturenumsurfaces++] = surface;
6711 for (;j < endsurface;j++)
6713 surface = rsurface.modelsurfaces + surfacelist[j];
6714 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6716 texturesurfacelist[texturenumsurfaces++] = surface;
6718 // render the range of surfaces
6719 if (ent == r_refdef.scene.worldentity)
6720 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6722 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6724 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6725 GL_AlphaTest(false);
6728 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6730 const entity_render_t *queueentity = r_refdef.scene.worldentity;
6734 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6736 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6738 RSurf_SetupDepthAndCulling();
6739 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6740 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6742 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6744 RSurf_SetupDepthAndCulling();
6745 GL_AlphaTest(false);
6746 R_Mesh_ColorPointer(NULL, 0, 0);
6747 R_Mesh_ResetTextureState();
6748 R_SetupGenericShader(false);
6749 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6751 GL_BlendFunc(GL_ONE, GL_ZERO);
6752 GL_Color(0, 0, 0, 1);
6753 GL_DepthTest(writedepth);
6754 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6756 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6758 RSurf_SetupDepthAndCulling();
6759 GL_AlphaTest(false);
6760 R_Mesh_ColorPointer(NULL, 0, 0);
6761 R_Mesh_ResetTextureState();
6762 R_SetupGenericShader(false);
6763 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6765 GL_BlendFunc(GL_ONE, GL_ZERO);
6767 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6769 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6770 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6771 else if (!rsurface.texture->currentnumlayers)
6773 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6775 // transparent surfaces get pushed off into the transparent queue
6776 int surfacelistindex;
6777 const msurface_t *surface;
6778 vec3_t tempcenter, center;
6779 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6781 surface = texturesurfacelist[surfacelistindex];
6782 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6783 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6784 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6785 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6786 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6791 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6792 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6797 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6801 // break the surface list down into batches by texture and use of lightmapping
6802 for (i = 0;i < numsurfaces;i = j)
6805 // texture is the base texture pointer, rsurface.texture is the
6806 // current frame/skin the texture is directing us to use (for example
6807 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6808 // use skin 1 instead)
6809 texture = surfacelist[i]->texture;
6810 rsurface.texture = R_GetCurrentTexture(texture);
6811 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6812 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6814 // if this texture is not the kind we want, skip ahead to the next one
6815 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6819 // simply scan ahead until we find a different texture or lightmap state
6820 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6822 // render the range of surfaces
6823 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6827 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6832 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6834 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6836 RSurf_SetupDepthAndCulling();
6837 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6838 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6840 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6842 RSurf_SetupDepthAndCulling();
6843 GL_AlphaTest(false);
6844 R_Mesh_ColorPointer(NULL, 0, 0);
6845 R_Mesh_ResetTextureState();
6846 R_SetupGenericShader(false);
6847 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6849 GL_BlendFunc(GL_ONE, GL_ZERO);
6850 GL_Color(0, 0, 0, 1);
6851 GL_DepthTest(writedepth);
6852 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6854 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6856 RSurf_SetupDepthAndCulling();
6857 GL_AlphaTest(false);
6858 R_Mesh_ColorPointer(NULL, 0, 0);
6859 R_Mesh_ResetTextureState();
6860 R_SetupGenericShader(false);
6861 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6863 GL_BlendFunc(GL_ONE, GL_ZERO);
6865 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6867 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6868 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6869 else if (!rsurface.texture->currentnumlayers)
6871 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6873 // transparent surfaces get pushed off into the transparent queue
6874 int surfacelistindex;
6875 const msurface_t *surface;
6876 vec3_t tempcenter, center;
6877 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6879 surface = texturesurfacelist[surfacelistindex];
6880 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6881 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6882 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6883 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6884 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6889 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6890 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6895 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6899 // break the surface list down into batches by texture and use of lightmapping
6900 for (i = 0;i < numsurfaces;i = j)
6903 // texture is the base texture pointer, rsurface.texture is the
6904 // current frame/skin the texture is directing us to use (for example
6905 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6906 // use skin 1 instead)
6907 texture = surfacelist[i]->texture;
6908 rsurface.texture = R_GetCurrentTexture(texture);
6909 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6910 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6912 // if this texture is not the kind we want, skip ahead to the next one
6913 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6917 // simply scan ahead until we find a different texture or lightmap state
6918 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6920 // render the range of surfaces
6921 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6925 float locboxvertex3f[6*4*3] =
6927 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6928 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6929 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6930 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6931 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6932 1,0,0, 0,0,0, 0,1,0, 1,1,0
6935 unsigned short locboxelements[6*2*3] =
6945 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6948 cl_locnode_t *loc = (cl_locnode_t *)ent;
6950 float vertex3f[6*4*3];
6952 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6953 GL_DepthMask(false);
6954 GL_DepthRange(0, 1);
6955 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6957 GL_CullFace(GL_NONE);
6958 R_Mesh_Matrix(&identitymatrix);
6960 R_Mesh_VertexPointer(vertex3f, 0, 0);
6961 R_Mesh_ColorPointer(NULL, 0, 0);
6962 R_Mesh_ResetTextureState();
6963 R_SetupGenericShader(false);
6966 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6967 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6968 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6969 surfacelist[0] < 0 ? 0.5f : 0.125f);
6971 if (VectorCompare(loc->mins, loc->maxs))
6973 VectorSet(size, 2, 2, 2);
6974 VectorMA(loc->mins, -0.5f, size, mins);
6978 VectorCopy(loc->mins, mins);
6979 VectorSubtract(loc->maxs, loc->mins, size);
6982 for (i = 0;i < 6*4*3;)
6983 for (j = 0;j < 3;j++, i++)
6984 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6986 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
6989 void R_DrawLocs(void)
6992 cl_locnode_t *loc, *nearestloc;
6994 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6995 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6997 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6998 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7002 void R_DrawDebugModel(entity_render_t *ent)
7004 int i, j, k, l, flagsmask;
7005 const int *elements;
7007 msurface_t *surface;
7008 dp_model_t *model = ent->model;
7011 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7013 R_Mesh_ColorPointer(NULL, 0, 0);
7014 R_Mesh_ResetTextureState();
7015 R_SetupGenericShader(false);
7016 GL_DepthRange(0, 1);
7017 GL_DepthTest(!r_showdisabledepthtest.integer);
7018 GL_DepthMask(false);
7019 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7021 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7023 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7024 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7026 if (brush->colbrushf && brush->colbrushf->numtriangles)
7028 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7029 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);
7030 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7033 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7035 if (surface->num_collisiontriangles)
7037 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7038 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);
7039 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7044 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7046 if (r_showtris.integer || r_shownormals.integer)
7048 if (r_showdisabledepthtest.integer)
7050 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7051 GL_DepthMask(false);
7055 GL_BlendFunc(GL_ONE, GL_ZERO);
7058 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7060 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7062 rsurface.texture = R_GetCurrentTexture(surface->texture);
7063 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7065 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7066 if (r_showtris.value > 0)
7068 if (!rsurface.texture->currentlayers->depthmask)
7069 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7070 else if (ent == r_refdef.scene.worldentity)
7071 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7073 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7074 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7075 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7076 R_Mesh_ColorPointer(NULL, 0, 0);
7077 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7078 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7079 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7080 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7081 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7084 if (r_shownormals.value < 0)
7087 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7089 VectorCopy(rsurface.vertex3f + l * 3, v);
7090 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7091 qglVertex3f(v[0], v[1], v[2]);
7092 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7093 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7094 qglVertex3f(v[0], v[1], v[2]);
7099 if (r_shownormals.value > 0)
7102 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7104 VectorCopy(rsurface.vertex3f + l * 3, v);
7105 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7106 qglVertex3f(v[0], v[1], v[2]);
7107 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7108 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7109 qglVertex3f(v[0], v[1], v[2]);
7114 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7116 VectorCopy(rsurface.vertex3f + l * 3, v);
7117 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7118 qglVertex3f(v[0], v[1], v[2]);
7119 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7120 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7121 qglVertex3f(v[0], v[1], v[2]);
7126 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7128 VectorCopy(rsurface.vertex3f + l * 3, v);
7129 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7130 qglVertex3f(v[0], v[1], v[2]);
7131 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7132 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7133 qglVertex3f(v[0], v[1], v[2]);
7140 rsurface.texture = NULL;
7144 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7145 int r_maxsurfacelist = 0;
7146 msurface_t **r_surfacelist = NULL;
7147 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7149 int i, j, endj, f, flagsmask;
7151 dp_model_t *model = r_refdef.scene.worldmodel;
7152 msurface_t *surfaces;
7153 unsigned char *update;
7154 int numsurfacelist = 0;
7158 if (r_maxsurfacelist < model->num_surfaces)
7160 r_maxsurfacelist = model->num_surfaces;
7162 Mem_Free(r_surfacelist);
7163 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7166 RSurf_ActiveWorldEntity();
7168 surfaces = model->data_surfaces;
7169 update = model->brushq1.lightmapupdateflags;
7171 // update light styles on this submodel
7172 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7174 model_brush_lightstyleinfo_t *style;
7175 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7177 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7179 int *list = style->surfacelist;
7180 style->value = r_refdef.scene.lightstylevalue[style->style];
7181 for (j = 0;j < style->numsurfaces;j++)
7182 update[list[j]] = true;
7187 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7191 R_DrawDebugModel(r_refdef.scene.worldentity);
7192 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7198 rsurface.uselightmaptexture = false;
7199 rsurface.texture = NULL;
7200 rsurface.rtlight = NULL;
7202 // add visible surfaces to draw list
7203 for (i = 0;i < model->nummodelsurfaces;i++)
7205 j = model->sortedmodelsurfaces[i];
7206 if (r_refdef.viewcache.world_surfacevisible[j])
7207 r_surfacelist[numsurfacelist++] = surfaces + j;
7209 // update lightmaps if needed
7211 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7212 if (r_refdef.viewcache.world_surfacevisible[j])
7214 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7215 // don't do anything if there were no surfaces
7216 if (!numsurfacelist)
7218 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7221 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7222 GL_AlphaTest(false);
7224 // add to stats if desired
7225 if (r_speeds.integer && !skysurfaces && !depthonly)
7227 r_refdef.stats.world_surfaces += numsurfacelist;
7228 for (j = 0;j < numsurfacelist;j++)
7229 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7231 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7234 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7236 int i, j, endj, f, flagsmask;
7238 dp_model_t *model = ent->model;
7239 msurface_t *surfaces;
7240 unsigned char *update;
7241 int numsurfacelist = 0;
7245 if (r_maxsurfacelist < model->num_surfaces)
7247 r_maxsurfacelist = model->num_surfaces;
7249 Mem_Free(r_surfacelist);
7250 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7253 // if the model is static it doesn't matter what value we give for
7254 // wantnormals and wanttangents, so this logic uses only rules applicable
7255 // to a model, knowing that they are meaningless otherwise
7256 if (ent == r_refdef.scene.worldentity)
7257 RSurf_ActiveWorldEntity();
7258 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
7259 RSurf_ActiveModelEntity(ent, false, false);
7261 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7263 surfaces = model->data_surfaces;
7264 update = model->brushq1.lightmapupdateflags;
7266 // update light styles
7267 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7269 model_brush_lightstyleinfo_t *style;
7270 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7272 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7274 int *list = style->surfacelist;
7275 style->value = r_refdef.scene.lightstylevalue[style->style];
7276 for (j = 0;j < style->numsurfaces;j++)
7277 update[list[j]] = true;
7282 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7286 R_DrawDebugModel(ent);
7287 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7293 rsurface.uselightmaptexture = false;
7294 rsurface.texture = NULL;
7295 rsurface.rtlight = NULL;
7297 // add visible surfaces to draw list
7298 for (i = 0;i < model->nummodelsurfaces;i++)
7299 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7300 // don't do anything if there were no surfaces
7301 if (!numsurfacelist)
7303 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7306 // update lightmaps if needed
7308 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7310 R_BuildLightMap(ent, surfaces + j);
7311 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7312 GL_AlphaTest(false);
7314 // add to stats if desired
7315 if (r_speeds.integer && !skysurfaces && !depthonly)
7317 r_refdef.stats.entities_surfaces += numsurfacelist;
7318 for (j = 0;j < numsurfacelist;j++)
7319 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7321 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity