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"};
132 extern cvar_t v_glslgamma;
134 extern qboolean v_flipped_state;
136 static struct r_bloomstate_s
141 int bloomwidth, bloomheight;
143 int screentexturewidth, screentextureheight;
144 rtexture_t *texture_screen;
146 int bloomtexturewidth, bloomtextureheight;
147 rtexture_t *texture_bloom;
149 // arrays for rendering the screen passes
150 float screentexcoord2f[8];
151 float bloomtexcoord2f[8];
152 float offsettexcoord2f[8];
156 r_waterstate_t r_waterstate;
158 // shadow volume bsp struct with automatically growing nodes buffer
161 rtexture_t *r_texture_blanknormalmap;
162 rtexture_t *r_texture_white;
163 rtexture_t *r_texture_grey128;
164 rtexture_t *r_texture_black;
165 rtexture_t *r_texture_notexture;
166 rtexture_t *r_texture_whitecube;
167 rtexture_t *r_texture_normalizationcube;
168 rtexture_t *r_texture_fogattenuation;
169 rtexture_t *r_texture_gammaramps;
170 unsigned int r_texture_gammaramps_serial;
171 //rtexture_t *r_texture_fogintensity;
173 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
174 unsigned int r_numqueries;
175 unsigned int r_maxqueries;
177 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
178 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
180 // vertex coordinates for a quad that covers the screen exactly
181 const static float r_screenvertex3f[12] =
189 extern void R_DrawModelShadows(void);
191 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
194 for (i = 0;i < verts;i++)
205 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
208 for (i = 0;i < verts;i++)
218 // FIXME: move this to client?
221 if (gamemode == GAME_NEHAHRA)
223 Cvar_Set("gl_fogenable", "0");
224 Cvar_Set("gl_fogdensity", "0.2");
225 Cvar_Set("gl_fogred", "0.3");
226 Cvar_Set("gl_foggreen", "0.3");
227 Cvar_Set("gl_fogblue", "0.3");
229 r_refdef.fog_density = 0;
230 r_refdef.fog_red = 0;
231 r_refdef.fog_green = 0;
232 r_refdef.fog_blue = 0;
233 r_refdef.fog_alpha = 1;
234 r_refdef.fog_start = 0;
235 r_refdef.fog_end = 0;
238 float FogForDistance(vec_t dist)
240 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
241 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
244 float FogPoint_World(const vec3_t p)
246 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
249 float FogPoint_Model(const vec3_t p)
251 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
254 static void R_BuildBlankTextures(void)
256 unsigned char data[4];
257 data[2] = 128; // normal X
258 data[1] = 128; // normal Y
259 data[0] = 255; // normal Z
260 data[3] = 128; // height
261 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
266 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
271 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
276 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
279 static void R_BuildNoTexture(void)
282 unsigned char pix[16][16][4];
283 // this makes a light grey/dark grey checkerboard texture
284 for (y = 0;y < 16;y++)
286 for (x = 0;x < 16;x++)
288 if ((y < 8) ^ (x < 8))
304 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
307 static void R_BuildWhiteCube(void)
309 unsigned char data[6*1*1*4];
310 memset(data, 255, sizeof(data));
311 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
314 static void R_BuildNormalizationCube(void)
318 vec_t s, t, intensity;
320 unsigned char data[6][NORMSIZE][NORMSIZE][4];
321 for (side = 0;side < 6;side++)
323 for (y = 0;y < NORMSIZE;y++)
325 for (x = 0;x < NORMSIZE;x++)
327 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
328 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
363 intensity = 127.0f / sqrt(DotProduct(v, v));
364 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
365 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
366 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
367 data[side][y][x][3] = 255;
371 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
374 static void R_BuildFogTexture(void)
378 unsigned char data1[FOGWIDTH][4];
379 //unsigned char data2[FOGWIDTH][4];
382 r_refdef.fogmasktable_start = r_refdef.fog_start;
383 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
384 r_refdef.fogmasktable_range = r_refdef.fogrange;
385 r_refdef.fogmasktable_density = r_refdef.fog_density;
387 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
388 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
390 d = (x * r - r_refdef.fogmasktable_start);
391 if(developer.integer >= 100)
392 Con_Printf("%f ", d);
394 if (r_fog_exp2.integer)
395 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
397 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
398 if(developer.integer >= 100)
399 Con_Printf(" : %f ", alpha);
400 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
401 if(developer.integer >= 100)
402 Con_Printf(" = %f\n", alpha);
403 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
406 for (x = 0;x < FOGWIDTH;x++)
408 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
413 //data2[x][0] = 255 - b;
414 //data2[x][1] = 255 - b;
415 //data2[x][2] = 255 - b;
418 if (r_texture_fogattenuation)
420 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
421 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
425 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);
426 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
430 static const char *builtinshaderstring =
431 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
432 "// written by Forest 'LordHavoc' Hale\n"
434 "// common definitions between vertex shader and fragment shader:\n"
436 "//#ifdef __GLSL_CG_DATA_TYPES\n"
437 "//# define myhalf half\n"
438 "//# define myhalf2 half2\n"
439 "//# define myhalf3 half3\n"
440 "//# define myhalf4 half4\n"
442 "# define myhalf float\n"
443 "# define myhalf2 vec2\n"
444 "# define myhalf3 vec3\n"
445 "# define myhalf4 vec4\n"
448 "#ifdef MODE_DEPTH_OR_SHADOW\n"
450 "# ifdef VERTEX_SHADER\n"
453 " gl_Position = ftransform();\n"
459 "#ifdef MODE_POSTPROCESS\n"
460 "# ifdef VERTEX_SHADER\n"
463 " gl_FrontColor = gl_Color;\n"
464 " gl_Position = ftransform();\n"
465 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
467 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
471 "# ifdef FRAGMENT_SHADER\n"
473 "uniform sampler2D Texture_First;\n"
475 "uniform sampler2D Texture_Second;\n"
477 "#ifdef USEGAMMARAMPS\n"
478 "uniform sampler2D Texture_GammaRamps;\n"
480 "#ifdef USEVERTEXTEXTUREBLEND\n"
481 "uniform vec4 TintColor;\n"
483 "#ifdef USECOLORMOD\n"
484 "uniform vec3 Gamma;\n"
486 "//uncomment these if you want to use them:\n"
487 "uniform vec4 UserVec1;\n"
488 "// uniform vec4 UserVec2;\n"
489 "// uniform vec4 UserVec3;\n"
490 "// uniform vec4 UserVec4;\n"
491 "// uniform float ClientTime;\n"
492 "uniform vec2 PixelSize;\n"
495 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
497 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
499 "#ifdef USEVERTEXTEXTUREBLEND\n"
500 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
503 "#ifdef USEPOSTPROCESSING\n"
504 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
505 "// 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"
506 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
507 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
508 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
509 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
510 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
511 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
514 "#ifdef USEGAMMARAMPS\n"
515 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
516 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
517 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
524 "#ifdef MODE_GENERIC\n"
525 "# ifdef VERTEX_SHADER\n"
528 " gl_FrontColor = gl_Color;\n"
529 "# ifdef USEDIFFUSE\n"
530 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
532 "# ifdef USESPECULAR\n"
533 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
535 " gl_Position = ftransform();\n"
538 "# ifdef FRAGMENT_SHADER\n"
540 "# ifdef USEDIFFUSE\n"
541 "uniform sampler2D Texture_First;\n"
543 "# ifdef USESPECULAR\n"
544 "uniform sampler2D Texture_Second;\n"
549 " gl_FragColor = gl_Color;\n"
550 "# ifdef USEDIFFUSE\n"
551 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
554 "# ifdef USESPECULAR\n"
555 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
557 "# ifdef USECOLORMAPPING\n"
558 " gl_FragColor *= tex2;\n"
561 " gl_FragColor += tex2;\n"
563 "# ifdef USEVERTEXTEXTUREBLEND\n"
564 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
569 "#else // !MODE_GENERIC\n"
571 "varying vec2 TexCoord;\n"
572 "varying vec2 TexCoordLightmap;\n"
574 "#ifdef MODE_LIGHTSOURCE\n"
575 "varying vec3 CubeVector;\n"
578 "#ifdef MODE_LIGHTSOURCE\n"
579 "varying vec3 LightVector;\n"
581 "#ifdef MODE_LIGHTDIRECTION\n"
582 "varying vec3 LightVector;\n"
585 "varying vec3 EyeVector;\n"
587 "varying vec3 EyeVectorModelSpace;\n"
590 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
591 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
592 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
594 "#ifdef MODE_WATER\n"
595 "varying vec4 ModelViewProjectionPosition;\n"
597 "#ifdef MODE_REFRACTION\n"
598 "varying vec4 ModelViewProjectionPosition;\n"
600 "#ifdef USEREFLECTION\n"
601 "varying vec4 ModelViewProjectionPosition;\n"
608 "// vertex shader specific:\n"
609 "#ifdef VERTEX_SHADER\n"
611 "uniform vec3 LightPosition;\n"
612 "uniform vec3 EyePosition;\n"
613 "uniform vec3 LightDir;\n"
615 "// 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"
619 " gl_FrontColor = gl_Color;\n"
620 " // copy the surface texcoord\n"
621 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
622 "#ifndef MODE_LIGHTSOURCE\n"
623 "# ifndef MODE_LIGHTDIRECTION\n"
624 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
628 "#ifdef MODE_LIGHTSOURCE\n"
629 " // transform vertex position into light attenuation/cubemap space\n"
630 " // (-1 to +1 across the light box)\n"
631 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
633 " // transform unnormalized light direction into tangent space\n"
634 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
635 " // normalize it per pixel)\n"
636 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
637 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
638 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
639 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
642 "#ifdef MODE_LIGHTDIRECTION\n"
643 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
644 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
645 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
648 " // transform unnormalized eye direction into tangent space\n"
650 " vec3 EyeVectorModelSpace;\n"
652 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
653 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
654 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
655 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
657 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
658 " VectorS = gl_MultiTexCoord1.xyz;\n"
659 " VectorT = gl_MultiTexCoord2.xyz;\n"
660 " VectorR = gl_MultiTexCoord3.xyz;\n"
663 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
664 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
665 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
666 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
669 "// transform vertex to camera space, using ftransform to match non-VS\n"
671 " gl_Position = ftransform();\n"
673 "#ifdef MODE_WATER\n"
674 " ModelViewProjectionPosition = gl_Position;\n"
676 "#ifdef MODE_REFRACTION\n"
677 " ModelViewProjectionPosition = gl_Position;\n"
679 "#ifdef USEREFLECTION\n"
680 " ModelViewProjectionPosition = gl_Position;\n"
684 "#endif // VERTEX_SHADER\n"
689 "// fragment shader specific:\n"
690 "#ifdef FRAGMENT_SHADER\n"
692 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
693 "uniform sampler2D Texture_Normal;\n"
694 "uniform sampler2D Texture_Color;\n"
695 "uniform sampler2D Texture_Gloss;\n"
696 "uniform sampler2D Texture_Glow;\n"
697 "uniform sampler2D Texture_SecondaryNormal;\n"
698 "uniform sampler2D Texture_SecondaryColor;\n"
699 "uniform sampler2D Texture_SecondaryGloss;\n"
700 "uniform sampler2D Texture_SecondaryGlow;\n"
701 "uniform sampler2D Texture_Pants;\n"
702 "uniform sampler2D Texture_Shirt;\n"
703 "uniform sampler2D Texture_FogMask;\n"
704 "uniform sampler2D Texture_Lightmap;\n"
705 "uniform sampler2D Texture_Deluxemap;\n"
706 "uniform sampler2D Texture_Refraction;\n"
707 "uniform sampler2D Texture_Reflection;\n"
708 "uniform sampler2D Texture_Attenuation;\n"
709 "uniform samplerCube Texture_Cube;\n"
711 "uniform myhalf3 LightColor;\n"
712 "uniform myhalf3 AmbientColor;\n"
713 "uniform myhalf3 DiffuseColor;\n"
714 "uniform myhalf3 SpecularColor;\n"
715 "uniform myhalf3 Color_Pants;\n"
716 "uniform myhalf3 Color_Shirt;\n"
717 "uniform myhalf3 FogColor;\n"
719 "uniform myhalf4 TintColor;\n"
722 "//#ifdef MODE_WATER\n"
723 "uniform vec4 DistortScaleRefractReflect;\n"
724 "uniform vec4 ScreenScaleRefractReflect;\n"
725 "uniform vec4 ScreenCenterRefractReflect;\n"
726 "uniform myhalf4 RefractColor;\n"
727 "uniform myhalf4 ReflectColor;\n"
728 "uniform myhalf ReflectFactor;\n"
729 "uniform myhalf ReflectOffset;\n"
731 "//# ifdef MODE_REFRACTION\n"
732 "//uniform vec4 DistortScaleRefractReflect;\n"
733 "//uniform vec4 ScreenScaleRefractReflect;\n"
734 "//uniform vec4 ScreenCenterRefractReflect;\n"
735 "//uniform myhalf4 RefractColor;\n"
736 "//# ifdef USEREFLECTION\n"
737 "//uniform myhalf4 ReflectColor;\n"
740 "//# ifdef USEREFLECTION\n"
741 "//uniform vec4 DistortScaleRefractReflect;\n"
742 "//uniform vec4 ScreenScaleRefractReflect;\n"
743 "//uniform vec4 ScreenCenterRefractReflect;\n"
744 "//uniform myhalf4 ReflectColor;\n"
749 "uniform myhalf GlowScale;\n"
750 "uniform myhalf SceneBrightness;\n"
751 "#ifdef USECONTRASTBOOST\n"
752 "uniform myhalf ContrastBoostCoeff;\n"
755 "uniform float OffsetMapping_Scale;\n"
756 "uniform float OffsetMapping_Bias;\n"
757 "uniform float FogRangeRecip;\n"
759 "uniform myhalf AmbientScale;\n"
760 "uniform myhalf DiffuseScale;\n"
761 "uniform myhalf SpecularScale;\n"
762 "uniform myhalf SpecularPower;\n"
764 "#ifdef USEOFFSETMAPPING\n"
765 "vec2 OffsetMapping(vec2 TexCoord)\n"
767 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
768 " // 14 sample relief mapping: linear search and then binary search\n"
769 " // this basically steps forward a small amount repeatedly until it finds\n"
770 " // itself inside solid, then jitters forward and back using decreasing\n"
771 " // amounts to find the impact\n"
772 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
773 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
774 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
775 " vec3 RT = vec3(TexCoord, 1);\n"
776 " OffsetVector *= 0.1;\n"
777 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
778 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
779 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
780 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
781 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
782 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
783 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
784 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
785 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
786 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
787 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
788 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
789 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
790 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
793 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
794 " // this basically moves forward the full distance, and then backs up based\n"
795 " // on height of samples\n"
796 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
797 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
798 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
799 " TexCoord += OffsetVector;\n"
800 " OffsetVector *= 0.333;\n"
801 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
802 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
803 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
804 " return TexCoord;\n"
807 "#endif // USEOFFSETMAPPING\n"
809 "#ifdef MODE_WATER\n"
814 "#ifdef USEOFFSETMAPPING\n"
815 " // apply offsetmapping\n"
816 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
817 "#define TexCoord TexCoordOffset\n"
820 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
821 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
822 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
823 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
824 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
827 "#else // !MODE_WATER\n"
828 "#ifdef MODE_REFRACTION\n"
830 "// refraction pass\n"
833 "#ifdef USEOFFSETMAPPING\n"
834 " // apply offsetmapping\n"
835 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
836 "#define TexCoord TexCoordOffset\n"
839 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
840 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
841 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
842 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
845 "#else // !MODE_REFRACTION\n"
848 "#ifdef USEOFFSETMAPPING\n"
849 " // apply offsetmapping\n"
850 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
851 "#define TexCoord TexCoordOffset\n"
854 " // combine the diffuse textures (base, pants, shirt)\n"
855 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
856 "#ifdef USECOLORMAPPING\n"
857 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
859 "#ifdef USEVERTEXTEXTUREBLEND\n"
860 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
861 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
862 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
863 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord)), color.rgb, terrainblend);\n"
865 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
868 "#ifdef USEDIFFUSE\n"
869 " // get the surface normal and the gloss color\n"
870 "# ifdef USEVERTEXTEXTUREBLEND\n"
871 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
872 "# ifdef USESPECULAR\n"
873 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
876 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
877 "# ifdef USESPECULAR\n"
878 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
885 "#ifdef MODE_LIGHTSOURCE\n"
888 " // calculate surface normal, light normal, and specular normal\n"
889 " // compute color intensity for the two textures (colormap and glossmap)\n"
890 " // scale by light color and attenuation as efficiently as possible\n"
891 " // (do as much scalar math as possible rather than vector math)\n"
892 "# ifdef USEDIFFUSE\n"
893 " // get the light normal\n"
894 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
896 "# ifdef USESPECULAR\n"
897 "# ifndef USEEXACTSPECULARMATH\n"
898 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
901 " // calculate directional shading\n"
902 "# ifdef USEEXACTSPECULARMATH\n"
903 " 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"
905 " 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"
908 "# ifdef USEDIFFUSE\n"
909 " // calculate directional shading\n"
910 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
912 " // calculate directionless shading\n"
913 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
917 "# ifdef USECUBEFILTER\n"
918 " // apply light cubemap filter\n"
919 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
920 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
922 "#endif // MODE_LIGHTSOURCE\n"
927 "#ifdef MODE_LIGHTDIRECTION\n"
928 " // directional model lighting\n"
929 "# ifdef USEDIFFUSE\n"
930 " // get the light normal\n"
931 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
933 "# ifdef USESPECULAR\n"
934 " // calculate directional shading\n"
935 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
936 "# ifdef USEEXACTSPECULARMATH\n"
937 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
939 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
940 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
943 "# ifdef USEDIFFUSE\n"
945 " // calculate directional shading\n"
946 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
948 " color.rgb *= AmbientColor;\n"
951 "#endif // MODE_LIGHTDIRECTION\n"
956 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
957 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
959 " // get the light normal\n"
960 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
961 " myhalf3 diffusenormal;\n"
962 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
963 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
964 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
965 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
966 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
967 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
968 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
969 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
970 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
971 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
972 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
973 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
974 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
975 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
976 "# ifdef USESPECULAR\n"
977 "# ifdef USEEXACTSPECULARMATH\n"
978 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
980 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
981 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
985 " // apply lightmap color\n"
986 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
987 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
992 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
993 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
995 " // get the light normal\n"
996 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
997 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
998 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
999 "# ifdef USESPECULAR\n"
1000 "# ifdef USEEXACTSPECULARMATH\n"
1001 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1003 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1004 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1008 " // apply lightmap color\n"
1009 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1010 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1015 "#ifdef MODE_LIGHTMAP\n"
1016 " // apply lightmap color\n"
1017 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1018 "#endif // MODE_LIGHTMAP\n"
1023 "#ifdef MODE_VERTEXCOLOR\n"
1024 " // apply lightmap color\n"
1025 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1026 "#endif // MODE_VERTEXCOLOR\n"
1031 "#ifdef MODE_FLATCOLOR\n"
1032 "#endif // MODE_FLATCOLOR\n"
1040 " color *= TintColor;\n"
1043 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1046 "#ifdef USECONTRASTBOOST\n"
1047 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1050 " color.rgb *= SceneBrightness;\n"
1052 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1054 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1057 " // 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"
1058 "#ifdef USEREFLECTION\n"
1059 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1060 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1061 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1062 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1065 " gl_FragColor = vec4(color);\n"
1067 "#endif // !MODE_REFRACTION\n"
1068 "#endif // !MODE_WATER\n"
1070 "#endif // FRAGMENT_SHADER\n"
1072 "#endif // !MODE_GENERIC\n"
1073 "#endif // !MODE_POSTPROCESS\n"
1074 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1077 typedef struct shaderpermutationinfo_s
1079 const char *pretext;
1082 shaderpermutationinfo_t;
1084 typedef struct shadermodeinfo_s
1086 const char *vertexfilename;
1087 const char *geometryfilename;
1088 const char *fragmentfilename;
1089 const char *pretext;
1094 typedef enum shaderpermutation_e
1096 SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
1097 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1098 SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
1099 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1100 SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
1101 SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
1102 SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
1103 SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
1104 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, // (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1105 SHADERPERMUTATION_REFLECTION = 1<<9, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1106 SHADERPERMUTATION_OFFSETMAPPING = 1<<10, // adjust texcoords to roughly simulate a displacement mapped surface
1107 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1108 SHADERPERMUTATION_GAMMARAMPS = 1<<12, // gamma (postprocessing only)
1109 SHADERPERMUTATION_POSTPROCESSING = 1<<13, // user defined postprocessing
1110 SHADERPERMUTATION_LIMIT = 1<<14, // size of permutations array
1111 SHADERPERMUTATION_COUNT = 14 // size of shaderpermutationinfo array
1113 shaderpermutation_t;
1115 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1116 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1118 {"#define USEDIFFUSE\n", " diffuse"},
1119 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1120 {"#define USECOLORMAPPING\n", " colormapping"},
1121 {"#define USECONTRASTBOOST\n", " contrastboost"},
1122 {"#define USEFOG\n", " fog"},
1123 {"#define USECUBEFILTER\n", " cubefilter"},
1124 {"#define USEGLOW\n", " glow"},
1125 {"#define USESPECULAR\n", " specular"},
1126 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1127 {"#define USEREFLECTION\n", " reflection"},
1128 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1129 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1130 {"#define USEGAMMARAMPS\n", " gammaramps"},
1131 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1134 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
1135 typedef enum shadermode_e
1137 SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
1138 SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
1139 SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
1140 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1141 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
1142 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1143 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1144 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1145 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1146 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
1147 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
1148 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1153 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1154 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1156 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1157 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1158 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1159 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1160 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1161 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1162 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1163 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1164 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1165 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1166 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1167 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1170 typedef struct r_glsl_permutation_s
1172 // indicates if we have tried compiling this permutation already
1174 // 0 if compilation failed
1176 // locations of detected uniforms in program object, or -1 if not found
1177 int loc_Texture_First;
1178 int loc_Texture_Second;
1179 int loc_Texture_GammaRamps;
1180 int loc_Texture_Normal;
1181 int loc_Texture_Color;
1182 int loc_Texture_Gloss;
1183 int loc_Texture_Glow;
1184 int loc_Texture_SecondaryNormal;
1185 int loc_Texture_SecondaryColor;
1186 int loc_Texture_SecondaryGloss;
1187 int loc_Texture_SecondaryGlow;
1188 int loc_Texture_Pants;
1189 int loc_Texture_Shirt;
1190 int loc_Texture_FogMask;
1191 int loc_Texture_Lightmap;
1192 int loc_Texture_Deluxemap;
1193 int loc_Texture_Attenuation;
1194 int loc_Texture_Cube;
1195 int loc_Texture_Refraction;
1196 int loc_Texture_Reflection;
1198 int loc_LightPosition;
1199 int loc_EyePosition;
1200 int loc_Color_Pants;
1201 int loc_Color_Shirt;
1202 int loc_FogRangeRecip;
1203 int loc_AmbientScale;
1204 int loc_DiffuseScale;
1205 int loc_SpecularScale;
1206 int loc_SpecularPower;
1208 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1209 int loc_OffsetMapping_Scale;
1211 int loc_AmbientColor;
1212 int loc_DiffuseColor;
1213 int loc_SpecularColor;
1215 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1216 int loc_GammaCoeff; // 1 / gamma
1217 int loc_DistortScaleRefractReflect;
1218 int loc_ScreenScaleRefractReflect;
1219 int loc_ScreenCenterRefractReflect;
1220 int loc_RefractColor;
1221 int loc_ReflectColor;
1222 int loc_ReflectFactor;
1223 int loc_ReflectOffset;
1231 r_glsl_permutation_t;
1233 // information about each possible shader permutation
1234 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1235 // currently selected permutation
1236 r_glsl_permutation_t *r_glsl_permutation;
1238 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1241 if (!filename || !filename[0])
1243 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1246 if (printfromdisknotice)
1247 Con_DPrint("from disk... ");
1248 return shaderstring;
1250 else if (!strcmp(filename, "glsl/default.glsl"))
1252 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1253 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1255 return shaderstring;
1258 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1261 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1262 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1263 int vertstrings_count = 0;
1264 int geomstrings_count = 0;
1265 int fragstrings_count = 0;
1266 char *vertexstring, *geometrystring, *fragmentstring;
1267 const char *vertstrings_list[32+3];
1268 const char *geomstrings_list[32+3];
1269 const char *fragstrings_list[32+3];
1270 char permutationname[256];
1277 permutationname[0] = 0;
1278 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1279 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1280 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1282 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1284 // the first pretext is which type of shader to compile as
1285 // (later these will all be bound together as a program object)
1286 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1287 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1288 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1290 // the second pretext is the mode (for example a light source)
1291 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1292 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1293 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1294 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1296 // now add all the permutation pretexts
1297 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1299 if (permutation & (1<<i))
1301 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1302 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1303 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1304 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1308 // keep line numbers correct
1309 vertstrings_list[vertstrings_count++] = "\n";
1310 geomstrings_list[geomstrings_count++] = "\n";
1311 fragstrings_list[fragstrings_count++] = "\n";
1315 // now append the shader text itself
1316 vertstrings_list[vertstrings_count++] = vertexstring;
1317 geomstrings_list[geomstrings_count++] = geometrystring;
1318 fragstrings_list[fragstrings_count++] = fragmentstring;
1320 // if any sources were NULL, clear the respective list
1322 vertstrings_count = 0;
1323 if (!geometrystring)
1324 geomstrings_count = 0;
1325 if (!fragmentstring)
1326 fragstrings_count = 0;
1328 // compile the shader program
1329 if (vertstrings_count + geomstrings_count + fragstrings_count)
1330 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1334 qglUseProgramObjectARB(p->program);CHECKGLERROR
1335 // look up all the uniform variable names we care about, so we don't
1336 // have to look them up every time we set them
1337 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1338 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1339 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1340 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1341 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1342 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1343 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1344 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1345 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1346 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1347 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1348 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1349 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1350 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1351 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1352 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1353 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1354 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1355 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1356 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1357 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1358 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1359 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1360 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1361 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1362 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1363 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1364 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1365 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1366 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1367 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1368 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1369 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1370 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1371 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1372 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1373 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1374 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1375 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1376 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1377 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1378 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1379 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1380 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1381 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1382 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1383 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1384 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1385 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1386 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1387 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1388 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1389 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1390 // initialize the samplers to refer to the texture units we use
1391 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1392 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1393 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1394 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1395 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1396 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1397 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1398 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1399 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1400 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1401 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1402 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1403 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1404 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1405 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1406 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1407 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1408 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1409 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1410 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1412 if (developer.integer)
1413 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1416 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1420 Mem_Free(vertexstring);
1422 Mem_Free(geometrystring);
1424 Mem_Free(fragmentstring);
1427 void R_GLSL_Restart_f(void)
1430 unsigned int permutation;
1431 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1432 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1433 if (r_glsl_permutations[mode][permutation].program)
1434 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1435 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1438 void R_GLSL_DumpShader_f(void)
1442 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1445 Con_Printf("failed to write to glsl/default.glsl\n");
1449 FS_Print(file, "// The engine may define the following macros:\n");
1450 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1451 for (i = 0;i < SHADERMODE_COUNT;i++)
1452 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1453 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1454 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1455 FS_Print(file, "\n");
1456 FS_Print(file, builtinshaderstring);
1459 Con_Printf("glsl/default.glsl written\n");
1462 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1464 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1465 if (r_glsl_permutation != perm)
1467 r_glsl_permutation = perm;
1468 if (!r_glsl_permutation->program)
1470 if (!r_glsl_permutation->compiled)
1471 R_GLSL_CompilePermutation(mode, permutation);
1472 if (!r_glsl_permutation->program)
1474 // remove features until we find a valid permutation
1476 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1478 // reduce i more quickly whenever it would not remove any bits
1479 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1480 if (!(permutation & j))
1483 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1484 if (!r_glsl_permutation->compiled)
1485 R_GLSL_CompilePermutation(mode, permutation);
1486 if (r_glsl_permutation->program)
1489 if (i >= SHADERPERMUTATION_COUNT)
1491 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");
1492 Cvar_SetValueQuick(&r_glsl, 0);
1493 R_GLSL_Restart_f(); // unload shaders
1494 return; // no bit left to clear
1499 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1503 void R_SetupGenericShader(qboolean usetexture)
1505 if (gl_support_fragment_shader)
1507 if (r_glsl.integer && r_glsl_usegeneric.integer)
1508 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1509 else if (r_glsl_permutation)
1511 r_glsl_permutation = NULL;
1512 qglUseProgramObjectARB(0);CHECKGLERROR
1517 void R_SetupGenericTwoTextureShader(int texturemode)
1519 if (gl_support_fragment_shader)
1521 if (r_glsl.integer && r_glsl_usegeneric.integer)
1522 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))));
1523 else if (r_glsl_permutation)
1525 r_glsl_permutation = NULL;
1526 qglUseProgramObjectARB(0);CHECKGLERROR
1529 if (!r_glsl_permutation)
1531 if (texturemode == GL_DECAL && gl_combine.integer)
1532 texturemode = GL_INTERPOLATE_ARB;
1533 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1537 void R_SetupDepthOrShadowShader(void)
1539 if (gl_support_fragment_shader)
1541 if (r_glsl.integer && r_glsl_usegeneric.integer)
1542 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1543 else if (r_glsl_permutation)
1545 r_glsl_permutation = NULL;
1546 qglUseProgramObjectARB(0);CHECKGLERROR
1551 extern rtexture_t *r_shadow_attenuationgradienttexture;
1552 extern rtexture_t *r_shadow_attenuation2dtexture;
1553 extern rtexture_t *r_shadow_attenuation3dtexture;
1554 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1556 // select a permutation of the lighting shader appropriate to this
1557 // combination of texture, entity, light source, and fogging, only use the
1558 // minimum features necessary to avoid wasting rendering time in the
1559 // fragment shader on features that are not being used
1560 unsigned int permutation = 0;
1561 unsigned int mode = 0;
1562 // TODO: implement geometry-shader based shadow volumes someday
1563 if (r_glsl_offsetmapping.integer)
1565 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1566 if (r_glsl_offsetmapping_reliefmapping.integer)
1567 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1569 if (rsurfacepass == RSURFPASS_BACKGROUND)
1571 // distorted background
1572 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1573 mode = SHADERMODE_WATER;
1575 mode = SHADERMODE_REFRACTION;
1577 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1580 mode = SHADERMODE_LIGHTSOURCE;
1581 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1582 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1583 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1584 permutation |= SHADERPERMUTATION_CUBEFILTER;
1585 if (diffusescale > 0)
1586 permutation |= SHADERPERMUTATION_DIFFUSE;
1587 if (specularscale > 0)
1588 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1589 if (r_refdef.fogenabled)
1590 permutation |= SHADERPERMUTATION_FOG;
1591 if (rsurface.texture->colormapping)
1592 permutation |= SHADERPERMUTATION_COLORMAPPING;
1593 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1594 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1596 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1598 // unshaded geometry (fullbright or ambient model lighting)
1599 mode = SHADERMODE_FLATCOLOR;
1600 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1601 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1602 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1603 permutation |= SHADERPERMUTATION_GLOW;
1604 if (r_refdef.fogenabled)
1605 permutation |= SHADERPERMUTATION_FOG;
1606 if (rsurface.texture->colormapping)
1607 permutation |= SHADERPERMUTATION_COLORMAPPING;
1608 if (r_glsl_offsetmapping.integer)
1610 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1611 if (r_glsl_offsetmapping_reliefmapping.integer)
1612 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1614 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1615 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1616 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1617 permutation |= SHADERPERMUTATION_REFLECTION;
1619 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1621 // directional model lighting
1622 mode = SHADERMODE_LIGHTDIRECTION;
1623 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1624 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1625 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1626 permutation |= SHADERPERMUTATION_GLOW;
1627 permutation |= SHADERPERMUTATION_DIFFUSE;
1628 if (specularscale > 0)
1629 permutation |= SHADERPERMUTATION_SPECULAR;
1630 if (r_refdef.fogenabled)
1631 permutation |= SHADERPERMUTATION_FOG;
1632 if (rsurface.texture->colormapping)
1633 permutation |= SHADERPERMUTATION_COLORMAPPING;
1634 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1635 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1636 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1637 permutation |= SHADERPERMUTATION_REFLECTION;
1639 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1641 // ambient model lighting
1642 mode = SHADERMODE_LIGHTDIRECTION;
1643 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1644 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1645 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1646 permutation |= SHADERPERMUTATION_GLOW;
1647 if (r_refdef.fogenabled)
1648 permutation |= SHADERPERMUTATION_FOG;
1649 if (rsurface.texture->colormapping)
1650 permutation |= SHADERPERMUTATION_COLORMAPPING;
1651 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1652 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1653 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1654 permutation |= SHADERPERMUTATION_REFLECTION;
1659 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1661 // deluxemapping (light direction texture)
1662 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1663 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1665 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1666 permutation |= SHADERPERMUTATION_DIFFUSE;
1667 if (specularscale > 0)
1668 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1670 else if (r_glsl_deluxemapping.integer >= 2)
1672 // fake deluxemapping (uniform light direction in tangentspace)
1673 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1674 permutation |= SHADERPERMUTATION_DIFFUSE;
1675 if (specularscale > 0)
1676 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1678 else if (rsurface.uselightmaptexture)
1680 // ordinary lightmapping (q1bsp, q3bsp)
1681 mode = SHADERMODE_LIGHTMAP;
1685 // ordinary vertex coloring (q3bsp)
1686 mode = SHADERMODE_VERTEXCOLOR;
1688 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1689 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1690 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1691 permutation |= SHADERPERMUTATION_GLOW;
1692 if (r_refdef.fogenabled)
1693 permutation |= SHADERPERMUTATION_FOG;
1694 if (rsurface.texture->colormapping)
1695 permutation |= SHADERPERMUTATION_COLORMAPPING;
1696 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1697 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1698 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1699 permutation |= SHADERPERMUTATION_REFLECTION;
1701 if(permutation & SHADERPERMUTATION_SPECULAR)
1702 if(r_shadow_glossexact.integer)
1703 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
1704 R_SetupShader_SetPermutation(mode, permutation);
1705 if (mode == SHADERMODE_LIGHTSOURCE)
1707 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1708 if (permutation & SHADERPERMUTATION_DIFFUSE)
1710 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1711 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1712 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1713 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1717 // ambient only is simpler
1718 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]);
1719 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1720 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1721 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1723 // additive passes are only darkened by fog, not tinted
1724 if (r_glsl_permutation->loc_FogColor >= 0)
1725 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1729 if (mode == SHADERMODE_LIGHTDIRECTION)
1731 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);
1732 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);
1733 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);
1734 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]);
1738 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
1739 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1740 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1742 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]);
1743 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1744 // additive passes are only darkened by fog, not tinted
1745 if (r_glsl_permutation->loc_FogColor >= 0)
1747 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1748 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1750 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1752 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);
1753 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]);
1754 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]);
1755 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1756 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1757 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1758 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1760 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1762 // The formula used is actually:
1763 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1764 // color.rgb *= SceneBrightness;
1766 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1767 // and do [[calculations]] here in the engine
1768 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1769 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1772 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1773 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1774 if (r_glsl_permutation->loc_Color_Pants >= 0)
1776 if (rsurface.texture->currentskinframe->pants)
1777 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1779 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1781 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1783 if (rsurface.texture->currentskinframe->shirt)
1784 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1786 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1788 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
1789 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
1791 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
1795 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1797 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1801 #define SKINFRAME_HASH 1024
1805 int loadsequence; // incremented each level change
1806 memexpandablearray_t array;
1807 skinframe_t *hash[SKINFRAME_HASH];
1810 r_skinframe_t r_skinframe;
1812 void R_SkinFrame_PrepareForPurge(void)
1814 r_skinframe.loadsequence++;
1815 // wrap it without hitting zero
1816 if (r_skinframe.loadsequence >= 200)
1817 r_skinframe.loadsequence = 1;
1820 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1824 // mark the skinframe as used for the purging code
1825 skinframe->loadsequence = r_skinframe.loadsequence;
1828 void R_SkinFrame_Purge(void)
1832 for (i = 0;i < SKINFRAME_HASH;i++)
1834 for (s = r_skinframe.hash[i];s;s = s->next)
1836 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1838 if (s->merged == s->base)
1840 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1841 R_PurgeTexture(s->stain );s->stain = NULL;
1842 R_PurgeTexture(s->merged);s->merged = NULL;
1843 R_PurgeTexture(s->base );s->base = NULL;
1844 R_PurgeTexture(s->pants );s->pants = NULL;
1845 R_PurgeTexture(s->shirt );s->shirt = NULL;
1846 R_PurgeTexture(s->nmap );s->nmap = NULL;
1847 R_PurgeTexture(s->gloss );s->gloss = NULL;
1848 R_PurgeTexture(s->glow );s->glow = NULL;
1849 R_PurgeTexture(s->fog );s->fog = NULL;
1850 s->loadsequence = 0;
1856 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1858 char basename[MAX_QPATH];
1860 Image_StripImageExtension(name, basename, sizeof(basename));
1862 if( last == NULL ) {
1864 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1865 item = r_skinframe.hash[hashindex];
1870 // linearly search through the hash bucket
1871 for( ; item ; item = item->next ) {
1872 if( !strcmp( item->basename, basename ) ) {
1879 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1883 char basename[MAX_QPATH];
1885 Image_StripImageExtension(name, basename, sizeof(basename));
1887 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1888 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1889 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1893 rtexture_t *dyntexture;
1894 // check whether its a dynamic texture
1895 dyntexture = CL_GetDynTexture( basename );
1896 if (!add && !dyntexture)
1898 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1899 memset(item, 0, sizeof(*item));
1900 strlcpy(item->basename, basename, sizeof(item->basename));
1901 item->base = dyntexture; // either NULL or dyntexture handle
1902 item->textureflags = textureflags;
1903 item->comparewidth = comparewidth;
1904 item->compareheight = compareheight;
1905 item->comparecrc = comparecrc;
1906 item->next = r_skinframe.hash[hashindex];
1907 r_skinframe.hash[hashindex] = item;
1909 else if( item->base == NULL )
1911 rtexture_t *dyntexture;
1912 // check whether its a dynamic texture
1913 // 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]
1914 dyntexture = CL_GetDynTexture( basename );
1915 item->base = dyntexture; // either NULL or dyntexture handle
1918 R_SkinFrame_MarkUsed(item);
1922 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
1924 unsigned long long avgcolor[5], wsum; \
1932 for(pix = 0; pix < cnt; ++pix) \
1935 for(comp = 0; comp < 3; ++comp) \
1937 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
1940 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1942 for(comp = 0; comp < 3; ++comp) \
1943 avgcolor[comp] += getpixel * w; \
1946 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1947 avgcolor[4] += getpixel; \
1949 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
1951 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
1952 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
1953 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
1954 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
1957 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
1959 // FIXME: it should be possible to disable loading various layers using
1960 // cvars, to prevent wasted loading time and memory usage if the user does
1962 qboolean loadnormalmap = true;
1963 qboolean loadgloss = true;
1964 qboolean loadpantsandshirt = true;
1965 qboolean loadglow = true;
1967 unsigned char *pixels;
1968 unsigned char *bumppixels;
1969 unsigned char *basepixels = NULL;
1970 int basepixels_width;
1971 int basepixels_height;
1972 skinframe_t *skinframe;
1976 if (cls.state == ca_dedicated)
1979 // return an existing skinframe if already loaded
1980 // if loading of the first image fails, don't make a new skinframe as it
1981 // would cause all future lookups of this to be missing
1982 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1983 if (skinframe && skinframe->base)
1986 basepixels = loadimagepixelsbgra(name, complain, true);
1987 if (basepixels == NULL)
1990 if (developer_loading.integer)
1991 Con_Printf("loading skin \"%s\"\n", name);
1993 // we've got some pixels to store, so really allocate this new texture now
1995 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1996 skinframe->stain = NULL;
1997 skinframe->merged = NULL;
1998 skinframe->base = r_texture_notexture;
1999 skinframe->pants = NULL;
2000 skinframe->shirt = NULL;
2001 skinframe->nmap = r_texture_blanknormalmap;
2002 skinframe->gloss = NULL;
2003 skinframe->glow = NULL;
2004 skinframe->fog = NULL;
2006 basepixels_width = image_width;
2007 basepixels_height = image_height;
2008 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);
2010 if (textureflags & TEXF_ALPHA)
2012 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2013 if (basepixels[j] < 255)
2015 if (j < basepixels_width * basepixels_height * 4)
2017 // has transparent pixels
2019 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2020 for (j = 0;j < image_width * image_height * 4;j += 4)
2025 pixels[j+3] = basepixels[j+3];
2027 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);
2032 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2033 //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]);
2035 // _norm is the name used by tenebrae and has been adopted as standard
2038 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2040 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);
2044 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2046 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2047 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2048 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);
2050 Mem_Free(bumppixels);
2052 else if (r_shadow_bumpscale_basetexture.value > 0)
2054 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2055 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2056 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);
2060 // _luma is supported for tenebrae compatibility
2061 // (I think it's a very stupid name, but oh well)
2062 // _glow is the preferred name
2063 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;}
2064 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;}
2065 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;}
2066 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;}
2069 Mem_Free(basepixels);
2074 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2077 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2080 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)
2085 for (i = 0;i < width*height;i++)
2086 if (((unsigned char *)&palette[in[i]])[3] > 0)
2088 if (i == width*height)
2091 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2094 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2095 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2098 unsigned char *temp1, *temp2;
2099 skinframe_t *skinframe;
2101 if (cls.state == ca_dedicated)
2104 // if already loaded just return it, otherwise make a new skinframe
2105 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2106 if (skinframe && skinframe->base)
2109 skinframe->stain = NULL;
2110 skinframe->merged = NULL;
2111 skinframe->base = r_texture_notexture;
2112 skinframe->pants = NULL;
2113 skinframe->shirt = NULL;
2114 skinframe->nmap = r_texture_blanknormalmap;
2115 skinframe->gloss = NULL;
2116 skinframe->glow = NULL;
2117 skinframe->fog = NULL;
2119 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2123 if (developer_loading.integer)
2124 Con_Printf("loading 32bit skin \"%s\"\n", name);
2126 if (r_shadow_bumpscale_basetexture.value > 0)
2128 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2129 temp2 = temp1 + width * height * 4;
2130 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2131 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2134 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2135 if (textureflags & TEXF_ALPHA)
2137 for (i = 3;i < width * height * 4;i += 4)
2138 if (skindata[i] < 255)
2140 if (i < width * height * 4)
2142 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2143 memcpy(fogpixels, skindata, width * height * 4);
2144 for (i = 0;i < width * height * 4;i += 4)
2145 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2146 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2147 Mem_Free(fogpixels);
2151 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2152 //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]);
2157 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2160 unsigned char *temp1, *temp2;
2161 unsigned int *palette;
2162 skinframe_t *skinframe;
2164 if (cls.state == ca_dedicated)
2167 // if already loaded just return it, otherwise make a new skinframe
2168 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2169 if (skinframe && skinframe->base)
2172 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2174 skinframe->stain = NULL;
2175 skinframe->merged = NULL;
2176 skinframe->base = r_texture_notexture;
2177 skinframe->pants = NULL;
2178 skinframe->shirt = NULL;
2179 skinframe->nmap = r_texture_blanknormalmap;
2180 skinframe->gloss = NULL;
2181 skinframe->glow = NULL;
2182 skinframe->fog = NULL;
2184 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2188 if (developer_loading.integer)
2189 Con_Printf("loading quake skin \"%s\"\n", name);
2191 if (r_shadow_bumpscale_basetexture.value > 0)
2193 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2194 temp2 = temp1 + width * height * 4;
2195 // use either a custom palette or the quake palette
2196 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2197 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2198 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2201 // use either a custom palette, or the quake palette
2202 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2203 if (loadglowtexture)
2204 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2205 if (loadpantsandshirt)
2207 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2208 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2210 if (skinframe->pants || skinframe->shirt)
2211 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
2212 if (textureflags & TEXF_ALPHA)
2214 for (i = 0;i < width * height;i++)
2215 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2217 if (i < width * height)
2218 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2221 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2222 //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]);
2227 skinframe_t *R_SkinFrame_LoadMissing(void)
2229 skinframe_t *skinframe;
2231 if (cls.state == ca_dedicated)
2234 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2235 skinframe->stain = NULL;
2236 skinframe->merged = NULL;
2237 skinframe->base = r_texture_notexture;
2238 skinframe->pants = NULL;
2239 skinframe->shirt = NULL;
2240 skinframe->nmap = r_texture_blanknormalmap;
2241 skinframe->gloss = NULL;
2242 skinframe->glow = NULL;
2243 skinframe->fog = NULL;
2245 skinframe->avgcolor[0] = rand() / RAND_MAX;
2246 skinframe->avgcolor[1] = rand() / RAND_MAX;
2247 skinframe->avgcolor[2] = rand() / RAND_MAX;
2248 skinframe->avgcolor[3] = 1;
2253 void gl_main_start(void)
2257 memset(r_queries, 0, sizeof(r_queries));
2259 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2260 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2262 // set up r_skinframe loading system for textures
2263 memset(&r_skinframe, 0, sizeof(r_skinframe));
2264 r_skinframe.loadsequence = 1;
2265 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2267 r_main_texturepool = R_AllocTexturePool();
2268 R_BuildBlankTextures();
2270 if (gl_texturecubemap)
2273 R_BuildNormalizationCube();
2275 r_texture_fogattenuation = NULL;
2276 r_texture_gammaramps = NULL;
2277 //r_texture_fogintensity = NULL;
2278 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2279 memset(&r_waterstate, 0, sizeof(r_waterstate));
2280 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2281 memset(&r_svbsp, 0, sizeof (r_svbsp));
2283 r_refdef.fogmasktable_density = 0;
2286 void gl_main_shutdown(void)
2289 qglDeleteQueriesARB(r_maxqueries, r_queries);
2293 memset(r_queries, 0, sizeof(r_queries));
2295 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2296 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2298 // clear out the r_skinframe state
2299 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2300 memset(&r_skinframe, 0, sizeof(r_skinframe));
2303 Mem_Free(r_svbsp.nodes);
2304 memset(&r_svbsp, 0, sizeof (r_svbsp));
2305 R_FreeTexturePool(&r_main_texturepool);
2306 r_texture_blanknormalmap = NULL;
2307 r_texture_white = NULL;
2308 r_texture_grey128 = NULL;
2309 r_texture_black = NULL;
2310 r_texture_whitecube = NULL;
2311 r_texture_normalizationcube = NULL;
2312 r_texture_fogattenuation = NULL;
2313 r_texture_gammaramps = NULL;
2314 //r_texture_fogintensity = NULL;
2315 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2316 memset(&r_waterstate, 0, sizeof(r_waterstate));
2320 extern void CL_ParseEntityLump(char *entitystring);
2321 void gl_main_newmap(void)
2323 // FIXME: move this code to client
2325 char *entities, entname[MAX_QPATH];
2328 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2329 l = (int)strlen(entname) - 4;
2330 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2332 memcpy(entname + l, ".ent", 5);
2333 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2335 CL_ParseEntityLump(entities);
2340 if (cl.worldmodel->brush.entities)
2341 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2345 void GL_Main_Init(void)
2347 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2349 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2350 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2351 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2352 if (gamemode == GAME_NEHAHRA)
2354 Cvar_RegisterVariable (&gl_fogenable);
2355 Cvar_RegisterVariable (&gl_fogdensity);
2356 Cvar_RegisterVariable (&gl_fogred);
2357 Cvar_RegisterVariable (&gl_foggreen);
2358 Cvar_RegisterVariable (&gl_fogblue);
2359 Cvar_RegisterVariable (&gl_fogstart);
2360 Cvar_RegisterVariable (&gl_fogend);
2361 Cvar_RegisterVariable (&gl_skyclip);
2363 Cvar_RegisterVariable(&r_depthfirst);
2364 Cvar_RegisterVariable(&r_useinfinitefarclip);
2365 Cvar_RegisterVariable(&r_nearclip);
2366 Cvar_RegisterVariable(&r_showbboxes);
2367 Cvar_RegisterVariable(&r_showsurfaces);
2368 Cvar_RegisterVariable(&r_showtris);
2369 Cvar_RegisterVariable(&r_shownormals);
2370 Cvar_RegisterVariable(&r_showlighting);
2371 Cvar_RegisterVariable(&r_showshadowvolumes);
2372 Cvar_RegisterVariable(&r_showcollisionbrushes);
2373 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2374 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2375 Cvar_RegisterVariable(&r_showdisabledepthtest);
2376 Cvar_RegisterVariable(&r_drawportals);
2377 Cvar_RegisterVariable(&r_drawentities);
2378 Cvar_RegisterVariable(&r_cullentities_trace);
2379 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2380 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2381 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2382 Cvar_RegisterVariable(&r_drawviewmodel);
2383 Cvar_RegisterVariable(&r_speeds);
2384 Cvar_RegisterVariable(&r_fullbrights);
2385 Cvar_RegisterVariable(&r_wateralpha);
2386 Cvar_RegisterVariable(&r_dynamic);
2387 Cvar_RegisterVariable(&r_fullbright);
2388 Cvar_RegisterVariable(&r_shadows);
2389 Cvar_RegisterVariable(&r_shadows_throwdistance);
2390 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2391 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2392 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2393 Cvar_RegisterVariable(&r_fog_exp2);
2394 Cvar_RegisterVariable(&r_drawfog);
2395 Cvar_RegisterVariable(&r_textureunits);
2396 Cvar_RegisterVariable(&r_glsl);
2397 Cvar_RegisterVariable(&r_glsl_contrastboost);
2398 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2399 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2400 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2401 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2402 Cvar_RegisterVariable(&r_glsl_postprocess);
2403 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2404 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2405 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2406 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2407 Cvar_RegisterVariable(&r_glsl_usegeneric);
2408 Cvar_RegisterVariable(&r_water);
2409 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2410 Cvar_RegisterVariable(&r_water_clippingplanebias);
2411 Cvar_RegisterVariable(&r_water_refractdistort);
2412 Cvar_RegisterVariable(&r_water_reflectdistort);
2413 Cvar_RegisterVariable(&r_lerpsprites);
2414 Cvar_RegisterVariable(&r_lerpmodels);
2415 Cvar_RegisterVariable(&r_lerplightstyles);
2416 Cvar_RegisterVariable(&r_waterscroll);
2417 Cvar_RegisterVariable(&r_bloom);
2418 Cvar_RegisterVariable(&r_bloom_colorscale);
2419 Cvar_RegisterVariable(&r_bloom_brighten);
2420 Cvar_RegisterVariable(&r_bloom_blur);
2421 Cvar_RegisterVariable(&r_bloom_resolution);
2422 Cvar_RegisterVariable(&r_bloom_colorexponent);
2423 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2424 Cvar_RegisterVariable(&r_hdr);
2425 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2426 Cvar_RegisterVariable(&r_hdr_glowintensity);
2427 Cvar_RegisterVariable(&r_hdr_range);
2428 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2429 Cvar_RegisterVariable(&developer_texturelogging);
2430 Cvar_RegisterVariable(&gl_lightmaps);
2431 Cvar_RegisterVariable(&r_test);
2432 Cvar_RegisterVariable(&r_batchmode);
2433 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2434 Cvar_SetValue("r_fullbrights", 0);
2435 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2437 Cvar_RegisterVariable(&r_track_sprites);
2438 Cvar_RegisterVariable(&r_track_sprites_flags);
2439 Cvar_RegisterVariable(&r_track_sprites_scalew);
2440 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2443 extern void R_Textures_Init(void);
2444 extern void GL_Draw_Init(void);
2445 extern void GL_Main_Init(void);
2446 extern void R_Shadow_Init(void);
2447 extern void R_Sky_Init(void);
2448 extern void GL_Surf_Init(void);
2449 extern void R_Particles_Init(void);
2450 extern void R_Explosion_Init(void);
2451 extern void gl_backend_init(void);
2452 extern void Sbar_Init(void);
2453 extern void R_LightningBeams_Init(void);
2454 extern void Mod_RenderInit(void);
2456 void Render_Init(void)
2468 R_LightningBeams_Init();
2477 extern char *ENGINE_EXTENSIONS;
2480 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2481 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2482 gl_version = (const char *)qglGetString(GL_VERSION);
2483 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2487 if (!gl_platformextensions)
2488 gl_platformextensions = "";
2490 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2491 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2492 Con_Printf("GL_VERSION: %s\n", gl_version);
2493 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2494 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2496 VID_CheckExtensions();
2498 // LordHavoc: report supported extensions
2499 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2501 // clear to black (loading plaque will be seen over this)
2503 qglClearColor(0,0,0,1);CHECKGLERROR
2504 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2507 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2511 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2513 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2516 p = r_refdef.view.frustum + i;
2521 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2525 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2529 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2533 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2537 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2541 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2545 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2549 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2557 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2561 for (i = 0;i < numplanes;i++)
2568 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2572 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2576 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2580 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2584 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2588 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2592 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2596 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2604 //==================================================================================
2606 static void R_View_UpdateEntityLighting (void)
2609 entity_render_t *ent;
2610 vec3_t tempdiffusenormal;
2612 for (i = 0;i < r_refdef.scene.numentities;i++)
2614 ent = r_refdef.scene.entities[i];
2616 // skip unseen models
2617 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
2621 if (ent->model && ent->model->brush.num_leafs)
2623 // TODO: use modellight for r_ambient settings on world?
2624 VectorSet(ent->modellight_ambient, 0, 0, 0);
2625 VectorSet(ent->modellight_diffuse, 0, 0, 0);
2626 VectorSet(ent->modellight_lightdir, 0, 0, 1);
2630 // fetch the lighting from the worldmodel data
2631 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));
2632 VectorClear(ent->modellight_diffuse);
2633 VectorClear(tempdiffusenormal);
2634 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
2637 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2638 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2641 VectorSet(ent->modellight_ambient, 1, 1, 1);
2643 // move the light direction into modelspace coordinates for lighting code
2644 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2645 if(VectorLength2(ent->modellight_lightdir) == 0)
2646 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2647 VectorNormalize(ent->modellight_lightdir);
2651 static void R_View_UpdateEntityVisible (void)
2654 entity_render_t *ent;
2656 if (!r_drawentities.integer)
2659 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2660 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2662 // worldmodel can check visibility
2663 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2664 for (i = 0;i < r_refdef.scene.numentities;i++)
2666 ent = r_refdef.scene.entities[i];
2667 if (!(ent->flags & renderimask))
2668 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)))
2669 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))
2670 r_refdef.viewcache.entityvisible[i] = true;
2672 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2674 for (i = 0;i < r_refdef.scene.numentities;i++)
2676 ent = r_refdef.scene.entities[i];
2677 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2679 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))
2680 ent->last_trace_visibility = realtime;
2681 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2682 r_refdef.viewcache.entityvisible[i] = 0;
2689 // no worldmodel or it can't check visibility
2690 for (i = 0;i < r_refdef.scene.numentities;i++)
2692 ent = r_refdef.scene.entities[i];
2693 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));
2698 // only used if skyrendermasked, and normally returns false
2699 int R_DrawBrushModelsSky (void)
2702 entity_render_t *ent;
2704 if (!r_drawentities.integer)
2708 for (i = 0;i < r_refdef.scene.numentities;i++)
2710 if (!r_refdef.viewcache.entityvisible[i])
2712 ent = r_refdef.scene.entities[i];
2713 if (!ent->model || !ent->model->DrawSky)
2715 ent->model->DrawSky(ent);
2721 static void R_DrawNoModel(entity_render_t *ent);
2722 static void R_DrawModels(void)
2725 entity_render_t *ent;
2727 if (!r_drawentities.integer)
2730 for (i = 0;i < r_refdef.scene.numentities;i++)
2732 if (!r_refdef.viewcache.entityvisible[i])
2734 ent = r_refdef.scene.entities[i];
2735 r_refdef.stats.entities++;
2736 if (ent->model && ent->model->Draw != NULL)
2737 ent->model->Draw(ent);
2743 static void R_DrawModelsDepth(void)
2746 entity_render_t *ent;
2748 if (!r_drawentities.integer)
2751 for (i = 0;i < r_refdef.scene.numentities;i++)
2753 if (!r_refdef.viewcache.entityvisible[i])
2755 ent = r_refdef.scene.entities[i];
2756 if (ent->model && ent->model->DrawDepth != NULL)
2757 ent->model->DrawDepth(ent);
2761 static void R_DrawModelsDebug(void)
2764 entity_render_t *ent;
2766 if (!r_drawentities.integer)
2769 for (i = 0;i < r_refdef.scene.numentities;i++)
2771 if (!r_refdef.viewcache.entityvisible[i])
2773 ent = r_refdef.scene.entities[i];
2774 if (ent->model && ent->model->DrawDebug != NULL)
2775 ent->model->DrawDebug(ent);
2779 static void R_DrawModelsAddWaterPlanes(void)
2782 entity_render_t *ent;
2784 if (!r_drawentities.integer)
2787 for (i = 0;i < r_refdef.scene.numentities;i++)
2789 if (!r_refdef.viewcache.entityvisible[i])
2791 ent = r_refdef.scene.entities[i];
2792 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2793 ent->model->DrawAddWaterPlanes(ent);
2797 static void R_View_SetFrustum(void)
2800 double slopex, slopey;
2801 vec3_t forward, left, up, origin;
2803 // we can't trust r_refdef.view.forward and friends in reflected scenes
2804 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2807 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2808 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2809 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2810 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2811 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2812 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2813 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2814 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2815 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2816 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2817 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2818 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2822 zNear = r_refdef.nearclip;
2823 nudge = 1.0 - 1.0 / (1<<23);
2824 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2825 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2826 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2827 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2828 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2829 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2830 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2831 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2837 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2838 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2839 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2840 r_refdef.view.frustum[0].dist = m[15] - m[12];
2842 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2843 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2844 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2845 r_refdef.view.frustum[1].dist = m[15] + m[12];
2847 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2848 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2849 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2850 r_refdef.view.frustum[2].dist = m[15] - m[13];
2852 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2853 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2854 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2855 r_refdef.view.frustum[3].dist = m[15] + m[13];
2857 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2858 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2859 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2860 r_refdef.view.frustum[4].dist = m[15] - m[14];
2862 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2863 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2864 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2865 r_refdef.view.frustum[5].dist = m[15] + m[14];
2868 if (r_refdef.view.useperspective)
2870 slopex = 1.0 / r_refdef.view.frustum_x;
2871 slopey = 1.0 / r_refdef.view.frustum_y;
2872 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2873 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
2874 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
2875 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
2876 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2878 // Leaving those out was a mistake, those were in the old code, and they
2879 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2880 // I couldn't reproduce it after adding those normalizations. --blub
2881 VectorNormalize(r_refdef.view.frustum[0].normal);
2882 VectorNormalize(r_refdef.view.frustum[1].normal);
2883 VectorNormalize(r_refdef.view.frustum[2].normal);
2884 VectorNormalize(r_refdef.view.frustum[3].normal);
2886 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2887 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2888 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2889 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2890 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2892 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2893 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2894 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2895 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2896 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2900 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2901 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2902 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2903 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2904 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2905 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2906 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2907 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2908 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2909 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2911 r_refdef.view.numfrustumplanes = 5;
2913 if (r_refdef.view.useclipplane)
2915 r_refdef.view.numfrustumplanes = 6;
2916 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2919 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2920 PlaneClassify(r_refdef.view.frustum + i);
2922 // LordHavoc: note to all quake engine coders, Quake had a special case
2923 // for 90 degrees which assumed a square view (wrong), so I removed it,
2924 // Quake2 has it disabled as well.
2926 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2927 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2928 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2929 //PlaneClassify(&frustum[0]);
2931 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2932 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2933 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2934 //PlaneClassify(&frustum[1]);
2936 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2937 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2938 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2939 //PlaneClassify(&frustum[2]);
2941 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2942 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2943 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2944 //PlaneClassify(&frustum[3]);
2947 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2948 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2949 //PlaneClassify(&frustum[4]);
2952 void R_View_Update(void)
2954 R_View_SetFrustum();
2955 R_View_WorldVisibility(r_refdef.view.useclipplane);
2956 R_View_UpdateEntityVisible();
2957 R_View_UpdateEntityLighting();
2960 void R_SetupView(qboolean allowwaterclippingplane)
2962 if (!r_refdef.view.useperspective)
2963 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);
2964 else if (gl_stencil && r_useinfinitefarclip.integer)
2965 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2967 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2969 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2971 if (r_refdef.view.useclipplane && allowwaterclippingplane)
2973 // LordHavoc: couldn't figure out how to make this approach the
2974 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2975 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2976 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2977 dist = r_refdef.view.clipplane.dist;
2978 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2982 void R_ResetViewRendering2D(void)
2986 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2987 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2988 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2989 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2990 GL_Color(1, 1, 1, 1);
2991 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2992 GL_BlendFunc(GL_ONE, GL_ZERO);
2993 GL_AlphaTest(false);
2994 GL_ScissorTest(false);
2995 GL_DepthMask(false);
2996 GL_DepthRange(0, 1);
2997 GL_DepthTest(false);
2998 R_Mesh_Matrix(&identitymatrix);
2999 R_Mesh_ResetTextureState();
3000 GL_PolygonOffset(0, 0);
3001 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3002 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3003 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3004 qglStencilMask(~0);CHECKGLERROR
3005 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3006 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3007 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3008 R_SetupGenericShader(true);
3011 void R_ResetViewRendering3D(void)
3015 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3016 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3018 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3019 GL_Color(1, 1, 1, 1);
3020 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3021 GL_BlendFunc(GL_ONE, GL_ZERO);
3022 GL_AlphaTest(false);
3023 GL_ScissorTest(true);
3025 GL_DepthRange(0, 1);
3027 R_Mesh_Matrix(&identitymatrix);
3028 R_Mesh_ResetTextureState();
3029 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3030 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3031 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3032 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3033 qglStencilMask(~0);CHECKGLERROR
3034 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3035 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3036 GL_CullFace(r_refdef.view.cullface_back);
3037 R_SetupGenericShader(true);
3040 void R_RenderScene(void);
3041 void R_RenderWaterPlanes(void);
3043 static void R_Water_StartFrame(void)
3046 int waterwidth, waterheight, texturewidth, textureheight;
3047 r_waterstate_waterplane_t *p;
3049 // set waterwidth and waterheight to the water resolution that will be
3050 // used (often less than the screen resolution for faster rendering)
3051 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3052 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3054 // calculate desired texture sizes
3055 // can't use water if the card does not support the texture size
3056 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3057 texturewidth = textureheight = waterwidth = waterheight = 0;
3058 else if (gl_support_arb_texture_non_power_of_two)
3060 texturewidth = waterwidth;
3061 textureheight = waterheight;
3065 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3066 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3069 // allocate textures as needed
3070 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3072 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3073 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3075 if (p->texture_refraction)
3076 R_FreeTexture(p->texture_refraction);
3077 p->texture_refraction = NULL;
3078 if (p->texture_reflection)
3079 R_FreeTexture(p->texture_reflection);
3080 p->texture_reflection = NULL;
3082 memset(&r_waterstate, 0, sizeof(r_waterstate));
3083 r_waterstate.waterwidth = waterwidth;
3084 r_waterstate.waterheight = waterheight;
3085 r_waterstate.texturewidth = texturewidth;
3086 r_waterstate.textureheight = textureheight;
3089 if (r_waterstate.waterwidth)
3091 r_waterstate.enabled = true;
3093 // set up variables that will be used in shader setup
3094 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3095 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3096 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3097 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3100 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3101 r_waterstate.numwaterplanes = 0;
3104 void R_Water_AddWaterPlane(msurface_t *surface)
3106 int triangleindex, planeindex;
3112 r_waterstate_waterplane_t *p;
3113 texture_t *t = R_GetCurrentTexture(surface->texture);
3114 // just use the first triangle with a valid normal for any decisions
3115 VectorClear(normal);
3116 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3118 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3119 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3120 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3121 TriangleNormal(vert[0], vert[1], vert[2], normal);
3122 if (VectorLength2(normal) >= 0.001)
3126 VectorCopy(normal, plane.normal);
3127 VectorNormalize(plane.normal);
3128 plane.dist = DotProduct(vert[0], plane.normal);
3129 PlaneClassify(&plane);
3130 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3132 // skip backfaces (except if nocullface is set)
3133 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3135 VectorNegate(plane.normal, plane.normal);
3137 PlaneClassify(&plane);
3141 // find a matching plane if there is one
3142 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3143 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3145 if (planeindex >= r_waterstate.maxwaterplanes)
3146 return; // nothing we can do, out of planes
3148 // if this triangle does not fit any known plane rendered this frame, add one
3149 if (planeindex >= r_waterstate.numwaterplanes)
3151 // store the new plane
3152 r_waterstate.numwaterplanes++;
3154 // clear materialflags and pvs
3155 p->materialflags = 0;
3156 p->pvsvalid = false;
3158 // merge this surface's materialflags into the waterplane
3159 p->materialflags |= t->currentmaterialflags;
3160 // merge this surface's PVS into the waterplane
3161 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3162 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3163 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3165 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3170 static void R_Water_ProcessPlanes(void)
3172 r_refdef_view_t originalview;
3173 r_refdef_view_t myview;
3175 r_waterstate_waterplane_t *p;
3177 originalview = r_refdef.view;
3179 // make sure enough textures are allocated
3180 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3182 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3184 if (!p->texture_refraction)
3185 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);
3186 if (!p->texture_refraction)
3190 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3192 if (!p->texture_reflection)
3193 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);
3194 if (!p->texture_reflection)
3200 r_refdef.view = originalview;
3201 r_refdef.view.showdebug = false;
3202 r_refdef.view.width = r_waterstate.waterwidth;
3203 r_refdef.view.height = r_waterstate.waterheight;
3204 r_refdef.view.useclipplane = true;
3205 myview = r_refdef.view;
3206 r_waterstate.renderingscene = true;
3207 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3209 // render the normal view scene and copy into texture
3210 // (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)
3211 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3213 r_refdef.view = myview;
3214 r_refdef.view.clipplane = p->plane;
3215 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3216 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3217 PlaneClassify(&r_refdef.view.clipplane);
3219 R_ResetViewRendering3D();
3220 R_ClearScreen(r_refdef.fogenabled);
3224 // copy view into the screen texture
3225 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3226 GL_ActiveTexture(0);
3228 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
3231 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3233 r_refdef.view = myview;
3234 // render reflected scene and copy into texture
3235 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3236 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3237 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3238 r_refdef.view.clipplane = p->plane;
3239 // reverse the cullface settings for this render
3240 r_refdef.view.cullface_front = GL_FRONT;
3241 r_refdef.view.cullface_back = GL_BACK;
3242 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3244 r_refdef.view.usecustompvs = true;
3246 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3248 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3251 R_ResetViewRendering3D();
3252 R_ClearScreen(r_refdef.fogenabled);
3256 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3257 GL_ActiveTexture(0);
3259 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
3262 r_waterstate.renderingscene = false;
3263 r_refdef.view = originalview;
3264 R_ResetViewRendering3D();
3265 R_ClearScreen(r_refdef.fogenabled);
3269 r_refdef.view = originalview;
3270 r_waterstate.renderingscene = false;
3271 Cvar_SetValueQuick(&r_water, 0);
3272 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3276 void R_Bloom_StartFrame(void)
3278 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3280 // set bloomwidth and bloomheight to the bloom resolution that will be
3281 // used (often less than the screen resolution for faster rendering)
3282 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3283 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3284 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3285 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3286 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3288 // calculate desired texture sizes
3289 if (gl_support_arb_texture_non_power_of_two)
3291 screentexturewidth = r_refdef.view.width;
3292 screentextureheight = r_refdef.view.height;
3293 bloomtexturewidth = r_bloomstate.bloomwidth;
3294 bloomtextureheight = r_bloomstate.bloomheight;
3298 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3299 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3300 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3301 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3304 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))
3306 Cvar_SetValueQuick(&r_hdr, 0);
3307 Cvar_SetValueQuick(&r_bloom, 0);
3310 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
3311 screentexturewidth = screentextureheight = 0;
3312 if (!r_hdr.integer && !r_bloom.integer)
3313 bloomtexturewidth = bloomtextureheight = 0;
3315 // allocate textures as needed
3316 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3318 if (r_bloomstate.texture_screen)
3319 R_FreeTexture(r_bloomstate.texture_screen);
3320 r_bloomstate.texture_screen = NULL;
3321 r_bloomstate.screentexturewidth = screentexturewidth;
3322 r_bloomstate.screentextureheight = screentextureheight;
3323 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3324 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);
3326 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3328 if (r_bloomstate.texture_bloom)
3329 R_FreeTexture(r_bloomstate.texture_bloom);
3330 r_bloomstate.texture_bloom = NULL;
3331 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3332 r_bloomstate.bloomtextureheight = bloomtextureheight;
3333 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3334 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);
3337 // set up a texcoord array for the full resolution screen image
3338 // (we have to keep this around to copy back during final render)
3339 r_bloomstate.screentexcoord2f[0] = 0;
3340 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3341 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3342 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3343 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3344 r_bloomstate.screentexcoord2f[5] = 0;
3345 r_bloomstate.screentexcoord2f[6] = 0;
3346 r_bloomstate.screentexcoord2f[7] = 0;
3348 // set up a texcoord array for the reduced resolution bloom image
3349 // (which will be additive blended over the screen image)
3350 r_bloomstate.bloomtexcoord2f[0] = 0;
3351 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3352 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3353 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3354 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3355 r_bloomstate.bloomtexcoord2f[5] = 0;
3356 r_bloomstate.bloomtexcoord2f[6] = 0;
3357 r_bloomstate.bloomtexcoord2f[7] = 0;
3359 if (r_hdr.integer || r_bloom.integer)
3361 r_bloomstate.enabled = true;
3362 r_bloomstate.hdr = r_hdr.integer != 0;
3366 void R_Bloom_CopyBloomTexture(float colorscale)
3368 r_refdef.stats.bloom++;
3370 // scale down screen texture to the bloom texture size
3372 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3373 GL_BlendFunc(GL_ONE, GL_ZERO);
3374 GL_Color(colorscale, colorscale, colorscale, 1);
3375 // TODO: optimize with multitexture or GLSL
3376 R_SetupGenericShader(true);
3377 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3378 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3379 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3380 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3382 // we now have a bloom image in the framebuffer
3383 // copy it into the bloom image texture for later processing
3384 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3385 GL_ActiveTexture(0);
3387 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
3388 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3391 void R_Bloom_CopyHDRTexture(void)
3393 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3394 GL_ActiveTexture(0);
3396 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
3397 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3400 void R_Bloom_MakeTexture(void)
3403 float xoffset, yoffset, r, brighten;
3405 r_refdef.stats.bloom++;
3407 R_ResetViewRendering2D();
3408 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3409 R_Mesh_ColorPointer(NULL, 0, 0);
3410 R_SetupGenericShader(true);
3412 // we have a bloom image in the framebuffer
3414 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3416 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3419 r = bound(0, r_bloom_colorexponent.value / x, 1);
3420 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3421 GL_Color(r, r, r, 1);
3422 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3423 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3424 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3425 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3427 // copy the vertically blurred bloom view to a texture
3428 GL_ActiveTexture(0);
3430 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
3431 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3434 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3435 brighten = r_bloom_brighten.value;
3437 brighten *= r_hdr_range.value;
3438 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3439 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3441 for (dir = 0;dir < 2;dir++)
3443 // blend on at multiple vertical offsets to achieve a vertical blur
3444 // TODO: do offset blends using GLSL
3445 GL_BlendFunc(GL_ONE, GL_ZERO);
3446 for (x = -range;x <= range;x++)
3448 if (!dir){xoffset = 0;yoffset = x;}
3449 else {xoffset = x;yoffset = 0;}
3450 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3451 yoffset /= (float)r_bloomstate.bloomtextureheight;
3452 // compute a texcoord array with the specified x and y offset
3453 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3454 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3455 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3456 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3457 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3458 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3459 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3460 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3461 // this r value looks like a 'dot' particle, fading sharply to
3462 // black at the edges
3463 // (probably not realistic but looks good enough)
3464 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3465 //r = (dir ? 1.0f : brighten)/(range*2+1);
3466 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3467 GL_Color(r, r, r, 1);
3468 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3469 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3470 GL_BlendFunc(GL_ONE, GL_ONE);
3473 // copy the vertically blurred bloom view to a texture
3474 GL_ActiveTexture(0);
3476 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
3477 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3480 // apply subtract last
3481 // (just like it would be in a GLSL shader)
3482 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3484 GL_BlendFunc(GL_ONE, GL_ZERO);
3485 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3486 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3487 GL_Color(1, 1, 1, 1);
3488 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3489 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3491 GL_BlendFunc(GL_ONE, GL_ONE);
3492 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3493 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3494 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3495 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3496 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3497 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3498 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3500 // copy the darkened bloom view to a texture
3501 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3502 GL_ActiveTexture(0);
3504 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
3505 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3509 void R_HDR_RenderBloomTexture(void)
3511 int oldwidth, oldheight;
3512 float oldcolorscale;
3514 oldcolorscale = r_refdef.view.colorscale;
3515 oldwidth = r_refdef.view.width;
3516 oldheight = r_refdef.view.height;
3517 r_refdef.view.width = r_bloomstate.bloomwidth;
3518 r_refdef.view.height = r_bloomstate.bloomheight;
3520 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3521 // TODO: add exposure compensation features
3522 // TODO: add fp16 framebuffer support
3524 r_refdef.view.showdebug = false;
3525 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3527 R_ClearScreen(r_refdef.fogenabled);
3528 if (r_timereport_active)
3529 R_TimeReport("HDRclear");
3532 if (r_timereport_active)
3533 R_TimeReport("visibility");
3535 r_waterstate.numwaterplanes = 0;
3536 if (r_waterstate.enabled)
3537 R_RenderWaterPlanes();
3539 r_refdef.view.showdebug = true;
3541 r_waterstate.numwaterplanes = 0;
3543 R_ResetViewRendering2D();
3545 R_Bloom_CopyHDRTexture();
3546 R_Bloom_MakeTexture();
3548 // restore the view settings
3549 r_refdef.view.width = oldwidth;
3550 r_refdef.view.height = oldheight;
3551 r_refdef.view.colorscale = oldcolorscale;
3553 R_ResetViewRendering3D();
3555 R_ClearScreen(r_refdef.fogenabled);
3556 if (r_timereport_active)
3557 R_TimeReport("viewclear");
3560 static void R_BlendView(void)
3562 if (r_bloomstate.texture_screen)
3564 // copy view into the screen texture
3565 R_ResetViewRendering2D();
3566 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3567 R_Mesh_ColorPointer(NULL, 0, 0);
3568 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3569 GL_ActiveTexture(0);CHECKGLERROR
3570 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
3571 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3574 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3576 unsigned int permutation =
3577 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3578 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3579 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3580 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0);
3582 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3584 // render simple bloom effect
3585 // copy the screen and shrink it and darken it for the bloom process
3586 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3587 // make the bloom texture
3588 R_Bloom_MakeTexture();
3591 R_ResetViewRendering2D();
3592 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3593 R_Mesh_ColorPointer(NULL, 0, 0);
3594 GL_Color(1, 1, 1, 1);
3595 GL_BlendFunc(GL_ONE, GL_ZERO);
3596 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3597 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3598 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3599 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3600 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3601 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3602 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3603 if (r_glsl_permutation->loc_TintColor >= 0)
3604 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3605 if (r_glsl_permutation->loc_ClientTime >= 0)
3606 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3607 if (r_glsl_permutation->loc_PixelSize >= 0)
3608 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3609 if (r_glsl_permutation->loc_UserVec1 >= 0)
3611 float a=0, b=0, c=0, d=0;
3612 #if _MSC_VER >= 1400
3613 #define sscanf sscanf_s
3615 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3616 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3618 if (r_glsl_permutation->loc_UserVec2 >= 0)
3620 float a=0, b=0, c=0, d=0;
3621 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3622 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3624 if (r_glsl_permutation->loc_UserVec3 >= 0)
3626 float a=0, b=0, c=0, d=0;
3627 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3628 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3630 if (r_glsl_permutation->loc_UserVec4 >= 0)
3632 float a=0, b=0, c=0, d=0;
3633 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3634 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3636 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3637 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3643 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3645 // render high dynamic range bloom effect
3646 // the bloom texture was made earlier this render, so we just need to
3647 // blend it onto the screen...
3648 R_ResetViewRendering2D();
3649 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3650 R_Mesh_ColorPointer(NULL, 0, 0);
3651 R_SetupGenericShader(true);
3652 GL_Color(1, 1, 1, 1);
3653 GL_BlendFunc(GL_ONE, GL_ONE);
3654 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3655 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3656 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3657 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3659 else if (r_bloomstate.texture_bloom)
3661 // render simple bloom effect
3662 // copy the screen and shrink it and darken it for the bloom process
3663 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3664 // make the bloom texture
3665 R_Bloom_MakeTexture();
3666 // put the original screen image back in place and blend the bloom
3668 R_ResetViewRendering2D();
3669 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3670 R_Mesh_ColorPointer(NULL, 0, 0);
3671 GL_Color(1, 1, 1, 1);
3672 GL_BlendFunc(GL_ONE, GL_ZERO);
3673 // do both in one pass if possible
3674 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3675 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3676 if (r_textureunits.integer >= 2 && gl_combine.integer)
3678 R_SetupGenericTwoTextureShader(GL_ADD);
3679 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3680 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3684 R_SetupGenericShader(true);
3685 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3686 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3687 // now blend on the bloom texture
3688 GL_BlendFunc(GL_ONE, GL_ONE);
3689 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3690 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3692 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3693 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3695 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3697 // apply a color tint to the whole view
3698 R_ResetViewRendering2D();
3699 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3700 R_Mesh_ColorPointer(NULL, 0, 0);
3701 R_SetupGenericShader(false);
3702 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3703 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3704 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3708 matrix4x4_t r_waterscrollmatrix;
3710 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3712 if (r_refdef.fog_density)
3714 r_refdef.fogcolor[0] = r_refdef.fog_red;
3715 r_refdef.fogcolor[1] = r_refdef.fog_green;
3716 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3720 VectorCopy(r_refdef.fogcolor, fogvec);
3721 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3723 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3724 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3725 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3726 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3728 // color.rgb *= ContrastBoost * SceneBrightness;
3729 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3730 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3731 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3732 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3737 void R_UpdateVariables(void)
3741 r_refdef.scene.ambient = r_ambient.value;
3743 r_refdef.farclip = 4096;
3744 if (r_refdef.scene.worldmodel)
3745 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3746 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3748 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3749 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3750 r_refdef.polygonfactor = 0;
3751 r_refdef.polygonoffset = 0;
3752 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3753 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3755 r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
3756 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3757 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3758 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3759 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3760 if (r_showsurfaces.integer)
3762 r_refdef.scene.rtworld = false;
3763 r_refdef.scene.rtworldshadows = false;
3764 r_refdef.scene.rtdlight = false;
3765 r_refdef.scene.rtdlightshadows = false;
3766 r_refdef.lightmapintensity = 0;
3769 if (gamemode == GAME_NEHAHRA)
3771 if (gl_fogenable.integer)
3773 r_refdef.oldgl_fogenable = true;
3774 r_refdef.fog_density = gl_fogdensity.value;
3775 r_refdef.fog_red = gl_fogred.value;
3776 r_refdef.fog_green = gl_foggreen.value;
3777 r_refdef.fog_blue = gl_fogblue.value;
3778 r_refdef.fog_alpha = 1;
3779 r_refdef.fog_start = 0;
3780 r_refdef.fog_end = gl_skyclip.value;
3782 else if (r_refdef.oldgl_fogenable)
3784 r_refdef.oldgl_fogenable = false;
3785 r_refdef.fog_density = 0;
3786 r_refdef.fog_red = 0;
3787 r_refdef.fog_green = 0;
3788 r_refdef.fog_blue = 0;
3789 r_refdef.fog_alpha = 0;
3790 r_refdef.fog_start = 0;
3791 r_refdef.fog_end = 0;
3795 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3796 r_refdef.fog_start = max(0, r_refdef.fog_start);
3797 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3799 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3801 if (r_refdef.fog_density && r_drawfog.integer)
3803 r_refdef.fogenabled = true;
3804 // this is the point where the fog reaches 0.9986 alpha, which we
3805 // consider a good enough cutoff point for the texture
3806 // (0.9986 * 256 == 255.6)
3807 if (r_fog_exp2.integer)
3808 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3810 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3811 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3812 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3813 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3814 // fog color was already set
3815 // update the fog texture
3816 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)
3817 R_BuildFogTexture();
3820 r_refdef.fogenabled = false;
3822 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
3824 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
3826 // build GLSL gamma texture
3827 #define RAMPWIDTH 256
3828 unsigned short ramp[RAMPWIDTH * 3];
3829 unsigned char rampbgr[RAMPWIDTH][4];
3832 r_texture_gammaramps_serial = vid_gammatables_serial;
3834 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
3835 for(i = 0; i < RAMPWIDTH; ++i)
3837 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3838 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3839 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
3842 if (r_texture_gammaramps)
3844 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
3848 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);
3854 // remove GLSL gamma texture
3858 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3859 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3865 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3866 if( scenetype != r_currentscenetype ) {
3867 // store the old scenetype
3868 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3869 r_currentscenetype = scenetype;
3870 // move in the new scene
3871 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3880 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3882 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3883 if( scenetype == r_currentscenetype ) {
3884 return &r_refdef.scene;
3886 return &r_scenes_store[ scenetype ];
3895 void R_RenderView(void)
3897 r_frame++; // used only by R_GetCurrentTexture
3898 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3900 if (r_refdef.view.isoverlay)
3902 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
3903 GL_Clear( GL_DEPTH_BUFFER_BIT );
3904 R_TimeReport("depthclear");
3906 r_refdef.view.showdebug = false;
3908 r_waterstate.enabled = false;
3909 r_waterstate.numwaterplanes = 0;
3917 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
3918 return; //Host_Error ("R_RenderView: NULL worldmodel");
3920 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3922 // break apart the view matrix into vectors for various purposes
3923 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3924 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3925 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3926 VectorNegate(r_refdef.view.left, r_refdef.view.right);
3927 // make an inverted copy of the view matrix for tracking sprites
3928 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3930 R_Shadow_UpdateWorldLightSelection();
3932 R_Bloom_StartFrame();
3933 R_Water_StartFrame();
3936 if (r_timereport_active)
3937 R_TimeReport("viewsetup");
3939 R_ResetViewRendering3D();
3941 if (r_refdef.view.clear || r_refdef.fogenabled)
3943 R_ClearScreen(r_refdef.fogenabled);
3944 if (r_timereport_active)
3945 R_TimeReport("viewclear");
3947 r_refdef.view.clear = true;
3949 // this produces a bloom texture to be used in R_BlendView() later
3951 R_HDR_RenderBloomTexture();
3953 r_refdef.view.showdebug = true;
3956 if (r_timereport_active)
3957 R_TimeReport("visibility");
3959 r_waterstate.numwaterplanes = 0;
3960 if (r_waterstate.enabled)
3961 R_RenderWaterPlanes();
3964 r_waterstate.numwaterplanes = 0;
3967 if (r_timereport_active)
3968 R_TimeReport("blendview");
3970 GL_Scissor(0, 0, vid.width, vid.height);
3971 GL_ScissorTest(false);
3975 void R_RenderWaterPlanes(void)
3977 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3979 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3980 if (r_timereport_active)
3981 R_TimeReport("waterworld");
3984 // don't let sound skip if going slow
3985 if (r_refdef.scene.extraupdate)
3988 R_DrawModelsAddWaterPlanes();
3989 if (r_timereport_active)
3990 R_TimeReport("watermodels");
3992 if (r_waterstate.numwaterplanes)
3994 R_Water_ProcessPlanes();
3995 if (r_timereport_active)
3996 R_TimeReport("waterscenes");
4000 extern void R_DrawLightningBeams (void);
4001 extern void VM_CL_AddPolygonsToMeshQueue (void);
4002 extern void R_DrawPortals (void);
4003 extern cvar_t cl_locs_show;
4004 static void R_DrawLocs(void);
4005 static void R_DrawEntityBBoxes(void);
4006 void R_RenderScene(void)
4008 r_refdef.stats.renders++;
4012 // don't let sound skip if going slow
4013 if (r_refdef.scene.extraupdate)
4016 R_MeshQueue_BeginScene();
4020 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);
4022 if (cl.csqc_vidvars.drawworld)
4024 // don't let sound skip if going slow
4025 if (r_refdef.scene.extraupdate)
4028 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4030 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4031 if (r_timereport_active)
4032 R_TimeReport("worldsky");
4035 if (R_DrawBrushModelsSky() && r_timereport_active)
4036 R_TimeReport("bmodelsky");
4039 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4041 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4042 if (r_timereport_active)
4043 R_TimeReport("worlddepth");
4045 if (r_depthfirst.integer >= 2)
4047 R_DrawModelsDepth();
4048 if (r_timereport_active)
4049 R_TimeReport("modeldepth");
4052 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4054 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4055 if (r_timereport_active)
4056 R_TimeReport("world");
4059 // don't let sound skip if going slow
4060 if (r_refdef.scene.extraupdate)
4064 if (r_timereport_active)
4065 R_TimeReport("models");
4067 // don't let sound skip if going slow
4068 if (r_refdef.scene.extraupdate)
4071 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
4073 R_DrawModelShadows();
4075 R_ResetViewRendering3D();
4077 // don't let sound skip if going slow
4078 if (r_refdef.scene.extraupdate)
4082 R_ShadowVolumeLighting(false);
4083 if (r_timereport_active)
4084 R_TimeReport("rtlights");
4086 // don't let sound skip if going slow
4087 if (r_refdef.scene.extraupdate)
4090 if (cl.csqc_vidvars.drawworld)
4092 R_DrawLightningBeams();
4093 if (r_timereport_active)
4094 R_TimeReport("lightning");
4097 if (r_timereport_active)
4098 R_TimeReport("decals");
4101 if (r_timereport_active)
4102 R_TimeReport("particles");
4105 if (r_timereport_active)
4106 R_TimeReport("explosions");
4109 R_SetupGenericShader(true);
4110 VM_CL_AddPolygonsToMeshQueue();
4112 if (r_refdef.view.showdebug)
4114 if (cl_locs_show.integer)
4117 if (r_timereport_active)
4118 R_TimeReport("showlocs");
4121 if (r_drawportals.integer)
4124 if (r_timereport_active)
4125 R_TimeReport("portals");
4128 if (r_showbboxes.value > 0)
4130 R_DrawEntityBBoxes();
4131 if (r_timereport_active)
4132 R_TimeReport("bboxes");
4136 R_SetupGenericShader(true);
4137 R_MeshQueue_RenderTransparent();
4138 if (r_timereport_active)
4139 R_TimeReport("drawtrans");
4141 R_SetupGenericShader(true);
4143 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))
4145 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4146 if (r_timereport_active)
4147 R_TimeReport("worlddebug");
4148 R_DrawModelsDebug();
4149 if (r_timereport_active)
4150 R_TimeReport("modeldebug");
4153 R_SetupGenericShader(true);
4155 if (cl.csqc_vidvars.drawworld)
4158 if (r_timereport_active)
4159 R_TimeReport("coronas");
4162 // don't let sound skip if going slow
4163 if (r_refdef.scene.extraupdate)
4166 R_ResetViewRendering2D();
4169 static const unsigned short bboxelements[36] =
4179 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4182 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4183 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4184 GL_DepthMask(false);
4185 GL_DepthRange(0, 1);
4186 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4187 R_Mesh_Matrix(&identitymatrix);
4188 R_Mesh_ResetTextureState();
4190 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4191 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4192 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4193 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4194 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4195 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4196 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4197 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4198 R_FillColors(color4f, 8, cr, cg, cb, ca);
4199 if (r_refdef.fogenabled)
4201 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4203 f1 = FogPoint_World(v);
4205 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4206 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4207 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4210 R_Mesh_VertexPointer(vertex3f, 0, 0);
4211 R_Mesh_ColorPointer(color4f, 0, 0);
4212 R_Mesh_ResetTextureState();
4213 R_SetupGenericShader(false);
4214 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4217 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4221 prvm_edict_t *edict;
4222 prvm_prog_t *prog_save = prog;
4224 // this function draws bounding boxes of server entities
4228 GL_CullFace(GL_NONE);
4229 R_SetupGenericShader(false);
4233 for (i = 0;i < numsurfaces;i++)
4235 edict = PRVM_EDICT_NUM(surfacelist[i]);
4236 switch ((int)edict->fields.server->solid)
4238 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4239 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4240 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4241 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4242 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4243 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4245 color[3] *= r_showbboxes.value;
4246 color[3] = bound(0, color[3], 1);
4247 GL_DepthTest(!r_showdisabledepthtest.integer);
4248 GL_CullFace(r_refdef.view.cullface_front);
4249 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4255 static void R_DrawEntityBBoxes(void)
4258 prvm_edict_t *edict;
4260 prvm_prog_t *prog_save = prog;
4262 // this function draws bounding boxes of server entities
4268 for (i = 0;i < prog->num_edicts;i++)
4270 edict = PRVM_EDICT_NUM(i);
4271 if (edict->priv.server->free)
4273 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4274 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4276 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4278 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4279 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4285 unsigned short nomodelelements[24] =
4297 float nomodelvertex3f[6*3] =
4307 float nomodelcolor4f[6*4] =
4309 0.0f, 0.0f, 0.5f, 1.0f,
4310 0.0f, 0.0f, 0.5f, 1.0f,
4311 0.0f, 0.5f, 0.0f, 1.0f,
4312 0.0f, 0.5f, 0.0f, 1.0f,
4313 0.5f, 0.0f, 0.0f, 1.0f,
4314 0.5f, 0.0f, 0.0f, 1.0f
4317 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4322 // this is only called once per entity so numsurfaces is always 1, and
4323 // surfacelist is always {0}, so this code does not handle batches
4324 R_Mesh_Matrix(&ent->matrix);
4326 if (ent->flags & EF_ADDITIVE)
4328 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4329 GL_DepthMask(false);
4331 else if (ent->alpha < 1)
4333 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4334 GL_DepthMask(false);
4338 GL_BlendFunc(GL_ONE, GL_ZERO);
4341 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4342 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4343 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4344 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4345 R_SetupGenericShader(false);
4346 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4347 if (r_refdef.fogenabled)
4350 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4351 R_Mesh_ColorPointer(color4f, 0, 0);
4352 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4353 f1 = FogPoint_World(org);
4355 for (i = 0, c = color4f;i < 6;i++, c += 4)
4357 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4358 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4359 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4363 else if (ent->alpha != 1)
4365 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4366 R_Mesh_ColorPointer(color4f, 0, 0);
4367 for (i = 0, c = color4f;i < 6;i++, c += 4)
4371 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4372 R_Mesh_ResetTextureState();
4373 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4376 void R_DrawNoModel(entity_render_t *ent)
4379 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4380 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4381 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4383 // R_DrawNoModelCallback(ent, 0);
4386 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4388 vec3_t right1, right2, diff, normal;
4390 VectorSubtract (org2, org1, normal);
4392 // calculate 'right' vector for start
4393 VectorSubtract (r_refdef.view.origin, org1, diff);
4394 CrossProduct (normal, diff, right1);
4395 VectorNormalize (right1);
4397 // calculate 'right' vector for end
4398 VectorSubtract (r_refdef.view.origin, org2, diff);
4399 CrossProduct (normal, diff, right2);
4400 VectorNormalize (right2);
4402 vert[ 0] = org1[0] + width * right1[0];
4403 vert[ 1] = org1[1] + width * right1[1];
4404 vert[ 2] = org1[2] + width * right1[2];
4405 vert[ 3] = org1[0] - width * right1[0];
4406 vert[ 4] = org1[1] - width * right1[1];
4407 vert[ 5] = org1[2] - width * right1[2];
4408 vert[ 6] = org2[0] - width * right2[0];
4409 vert[ 7] = org2[1] - width * right2[1];
4410 vert[ 8] = org2[2] - width * right2[2];
4411 vert[ 9] = org2[0] + width * right2[0];
4412 vert[10] = org2[1] + width * right2[1];
4413 vert[11] = org2[2] + width * right2[2];
4416 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4418 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)
4420 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4424 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4425 fog = FogPoint_World(origin);
4427 R_Mesh_Matrix(&identitymatrix);
4428 GL_BlendFunc(blendfunc1, blendfunc2);
4430 GL_CullFace(GL_NONE);
4432 GL_DepthMask(false);
4433 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4434 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4435 GL_DepthTest(!depthdisable);
4437 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4438 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4439 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4440 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4441 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4442 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4443 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4444 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4445 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4446 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4447 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4448 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4450 R_Mesh_VertexPointer(vertex3f, 0, 0);
4451 R_Mesh_ColorPointer(NULL, 0, 0);
4452 R_Mesh_ResetTextureState();
4453 R_SetupGenericShader(true);
4454 R_Mesh_TexBind(0, R_GetTexture(texture));
4455 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4456 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4457 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4458 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4460 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4462 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4463 GL_BlendFunc(blendfunc1, GL_ONE);
4465 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4466 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4470 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4475 VectorSet(v, x, y, z);
4476 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4477 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4479 if (i == mesh->numvertices)
4481 if (mesh->numvertices < mesh->maxvertices)
4483 VectorCopy(v, vertex3f);
4484 mesh->numvertices++;
4486 return mesh->numvertices;
4492 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4496 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4497 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4498 e = mesh->element3i + mesh->numtriangles * 3;
4499 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4501 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4502 if (mesh->numtriangles < mesh->maxtriangles)
4507 mesh->numtriangles++;
4509 element[1] = element[2];
4513 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4517 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4518 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4519 e = mesh->element3i + mesh->numtriangles * 3;
4520 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4522 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4523 if (mesh->numtriangles < mesh->maxtriangles)
4528 mesh->numtriangles++;
4530 element[1] = element[2];
4534 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4535 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4537 int planenum, planenum2;
4540 mplane_t *plane, *plane2;
4542 double temppoints[2][256*3];
4543 // figure out how large a bounding box we need to properly compute this brush
4545 for (w = 0;w < numplanes;w++)
4546 maxdist = max(maxdist, planes[w].dist);
4547 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4548 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4549 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4553 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4554 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4556 if (planenum2 == planenum)
4558 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);
4561 if (tempnumpoints < 3)
4563 // generate elements forming a triangle fan for this polygon
4564 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4568 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)
4570 texturelayer_t *layer;
4571 layer = t->currentlayers + t->currentnumlayers++;
4573 layer->depthmask = depthmask;
4574 layer->blendfunc1 = blendfunc1;
4575 layer->blendfunc2 = blendfunc2;
4576 layer->texture = texture;
4577 layer->texmatrix = *matrix;
4578 layer->color[0] = r * r_refdef.view.colorscale;
4579 layer->color[1] = g * r_refdef.view.colorscale;
4580 layer->color[2] = b * r_refdef.view.colorscale;
4581 layer->color[3] = a;
4584 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4587 index = parms[2] + r_refdef.scene.time * parms[3];
4588 index -= floor(index);
4592 case Q3WAVEFUNC_NONE:
4593 case Q3WAVEFUNC_NOISE:
4594 case Q3WAVEFUNC_COUNT:
4597 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4598 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4599 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4600 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4601 case Q3WAVEFUNC_TRIANGLE:
4603 f = index - floor(index);
4614 return (float)(parms[0] + parms[1] * f);
4617 texture_t *R_GetCurrentTexture(texture_t *t)
4621 const entity_render_t *ent = rsurface.entity;
4622 dp_model_t *model = ent->model;
4625 q3shaderinfo_layer_tcmod_t *tcmod;
4627 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
4628 return t->currentframe;
4629 t->update_lastrenderframe = r_frame;
4630 t->update_lastrenderentity = (void *)ent;
4632 // switch to an alternate material if this is a q1bsp animated material
4634 texture_t *texture = t;
4635 int s = ent->skinnum;
4636 if ((unsigned int)s >= (unsigned int)model->numskins)
4638 if (model->skinscenes)
4640 if (model->skinscenes[s].framecount > 1)
4641 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4643 s = model->skinscenes[s].firstframe;
4646 t = t + s * model->num_surfaces;
4649 // use an alternate animation if the entity's frame is not 0,
4650 // and only if the texture has an alternate animation
4651 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
4652 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4654 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4656 texture->currentframe = t;
4659 // update currentskinframe to be a qw skin or animation frame
4660 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"))
4662 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4664 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4665 if (developer_loading.integer)
4666 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4667 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);
4669 t->currentskinframe = r_qwskincache_skinframe[i];
4670 if (t->currentskinframe == NULL)
4671 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4673 else if (t->numskinframes >= 2)
4674 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4675 if (t->backgroundnumskinframes >= 2)
4676 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
4678 t->currentmaterialflags = t->basematerialflags;
4679 t->currentalpha = ent->alpha;
4680 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4681 t->currentalpha *= r_wateralpha.value;
4682 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4683 t->currentalpha *= t->r_water_wateralpha;
4684 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4685 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4686 if (!(ent->flags & RENDER_LIGHT))
4687 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4688 else if (rsurface.modeltexcoordlightmap2f == NULL)
4690 // pick a model lighting mode
4691 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4692 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4694 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4696 if (ent->effects & EF_ADDITIVE)
4697 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4698 else if (t->currentalpha < 1)
4699 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4700 if (ent->effects & EF_DOUBLESIDED)
4701 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4702 if (ent->effects & EF_NODEPTHTEST)
4703 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4704 if (ent->flags & RENDER_VIEWMODEL)
4705 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4706 if (t->backgroundnumskinframes)
4707 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4708 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4710 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4711 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4714 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4716 // there is no tcmod
4717 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4718 t->currenttexmatrix = r_waterscrollmatrix;
4720 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4723 switch(tcmod->tcmod)
4727 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4728 matrix = r_waterscrollmatrix;
4730 matrix = identitymatrix;
4732 case Q3TCMOD_ENTITYTRANSLATE:
4733 // this is used in Q3 to allow the gamecode to control texcoord
4734 // scrolling on the entity, which is not supported in darkplaces yet.
4735 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4737 case Q3TCMOD_ROTATE:
4738 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4739 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4740 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4743 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4745 case Q3TCMOD_SCROLL:
4746 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4748 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4749 w = (int) tcmod->parms[0];
4750 h = (int) tcmod->parms[1];
4751 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4753 idx = (int) floor(f * w * h);
4754 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4756 case Q3TCMOD_STRETCH:
4757 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4758 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4760 case Q3TCMOD_TRANSFORM:
4761 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4762 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4763 VectorSet(tcmat + 6, 0 , 0 , 1);
4764 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4765 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4767 case Q3TCMOD_TURBULENT:
4768 // this is handled in the RSurf_PrepareVertices function
4769 matrix = identitymatrix;
4772 // either replace or concatenate the transformation
4774 t->currenttexmatrix = matrix;
4777 matrix4x4_t temp = t->currenttexmatrix;
4778 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4782 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4783 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4784 t->glosstexture = r_texture_black;
4785 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4786 t->backgroundglosstexture = r_texture_black;
4787 t->specularpower = r_shadow_glossexponent.value;
4788 // TODO: store reference values for these in the texture?
4789 t->specularscale = 0;
4790 if (r_shadow_gloss.integer > 0)
4792 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4794 if (r_shadow_glossintensity.value > 0)
4796 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4797 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4798 t->specularscale = r_shadow_glossintensity.value;
4801 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4803 t->glosstexture = r_texture_white;
4804 t->backgroundglosstexture = r_texture_white;
4805 t->specularscale = r_shadow_gloss2intensity.value;
4809 // lightmaps mode looks bad with dlights using actual texturing, so turn
4810 // off the colormap and glossmap, but leave the normalmap on as it still
4811 // accurately represents the shading involved
4812 if (gl_lightmaps.integer)
4814 t->basetexture = r_texture_grey128;
4815 t->backgroundbasetexture = NULL;
4816 t->specularscale = 0;
4817 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
4820 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4821 VectorClear(t->dlightcolor);
4822 t->currentnumlayers = 0;
4823 if (t->currentmaterialflags & MATERIALFLAG_WALL)
4826 int blendfunc1, blendfunc2, depthmask;
4827 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4829 blendfunc1 = GL_SRC_ALPHA;
4830 blendfunc2 = GL_ONE;
4832 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4834 blendfunc1 = GL_SRC_ALPHA;
4835 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4837 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4839 blendfunc1 = t->customblendfunc[0];
4840 blendfunc2 = t->customblendfunc[1];
4844 blendfunc1 = GL_ONE;
4845 blendfunc2 = GL_ZERO;
4847 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4848 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4849 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4850 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4852 // fullbright is not affected by r_refdef.lightmapintensity
4853 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]);
4854 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4855 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]);
4856 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4857 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]);
4861 vec3_t ambientcolor;
4863 // set the color tint used for lights affecting this surface
4864 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4866 // q3bsp has no lightmap updates, so the lightstylevalue that
4867 // would normally be baked into the lightmap must be
4868 // applied to the color
4869 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4870 if (ent->model->type == mod_brushq3)
4871 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4872 colorscale *= r_refdef.lightmapintensity;
4873 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
4874 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4875 // basic lit geometry
4876 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]);
4877 // add pants/shirt if needed
4878 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4879 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]);
4880 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4881 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]);
4882 // now add ambient passes if needed
4883 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4885 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]);
4886 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4887 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]);
4888 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4889 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]);
4892 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4893 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]);
4894 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4896 // if this is opaque use alpha blend which will darken the earlier
4899 // if this is an alpha blended material, all the earlier passes
4900 // were darkened by fog already, so we only need to add the fog
4901 // color ontop through the fog mask texture
4903 // if this is an additive blended material, all the earlier passes
4904 // were darkened by fog already, and we should not add fog color
4905 // (because the background was not darkened, there is no fog color
4906 // that was lost behind it).
4907 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]);
4911 return t->currentframe;
4914 rsurfacestate_t rsurface;
4916 void R_Mesh_ResizeArrays(int newvertices)
4919 if (rsurface.array_size >= newvertices)
4921 if (rsurface.array_modelvertex3f)
4922 Mem_Free(rsurface.array_modelvertex3f);
4923 rsurface.array_size = (newvertices + 1023) & ~1023;
4924 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4925 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4926 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4927 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4928 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4929 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4930 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4931 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4932 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4933 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4934 rsurface.array_color4f = base + rsurface.array_size * 27;
4935 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4938 void RSurf_ActiveWorldEntity(void)
4940 dp_model_t *model = r_refdef.scene.worldmodel;
4941 //if (rsurface.entity == r_refdef.scene.worldentity)
4943 rsurface.entity = r_refdef.scene.worldentity;
4944 if (rsurface.array_size < model->surfmesh.num_vertices)
4945 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4946 rsurface.matrix = identitymatrix;
4947 rsurface.inversematrix = identitymatrix;
4948 R_Mesh_Matrix(&identitymatrix);
4949 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4950 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4951 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4952 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4953 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4954 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4955 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
4956 rsurface.frameblend[0].lerp = 1;
4957 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4958 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4959 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4960 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4961 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4962 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4963 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4964 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4965 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4966 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4967 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4968 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4969 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4970 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4971 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4972 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4973 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4974 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4975 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4976 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4977 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4978 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4979 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4980 rsurface.modelelement3i = model->surfmesh.data_element3i;
4981 rsurface.modelelement3s = model->surfmesh.data_element3s;
4982 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
4983 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
4984 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4985 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4986 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4987 rsurface.modelsurfaces = model->data_surfaces;
4988 rsurface.generatedvertex = false;
4989 rsurface.vertex3f = rsurface.modelvertex3f;
4990 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4991 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4992 rsurface.svector3f = rsurface.modelsvector3f;
4993 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4994 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4995 rsurface.tvector3f = rsurface.modeltvector3f;
4996 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4997 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4998 rsurface.normal3f = rsurface.modelnormal3f;
4999 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5000 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5001 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5004 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5006 dp_model_t *model = ent->model;
5007 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5009 rsurface.entity = (entity_render_t *)ent;
5010 if (rsurface.array_size < model->surfmesh.num_vertices)
5011 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5012 rsurface.matrix = ent->matrix;
5013 rsurface.inversematrix = ent->inversematrix;
5014 R_Mesh_Matrix(&rsurface.matrix);
5015 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5016 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5017 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5018 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5019 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5020 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5021 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5022 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5023 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5024 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5025 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5026 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5027 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5028 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5029 if (ent->model->brush.submodel)
5031 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5032 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5034 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5038 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5039 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5040 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5041 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5042 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5044 else if (wantnormals)
5046 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5047 rsurface.modelsvector3f = NULL;
5048 rsurface.modeltvector3f = NULL;
5049 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5050 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5054 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5055 rsurface.modelsvector3f = NULL;
5056 rsurface.modeltvector3f = NULL;
5057 rsurface.modelnormal3f = NULL;
5058 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5060 rsurface.modelvertex3f_bufferobject = 0;
5061 rsurface.modelvertex3f_bufferoffset = 0;
5062 rsurface.modelsvector3f_bufferobject = 0;
5063 rsurface.modelsvector3f_bufferoffset = 0;
5064 rsurface.modeltvector3f_bufferobject = 0;
5065 rsurface.modeltvector3f_bufferoffset = 0;
5066 rsurface.modelnormal3f_bufferobject = 0;
5067 rsurface.modelnormal3f_bufferoffset = 0;
5068 rsurface.generatedvertex = true;
5072 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5073 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5074 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5075 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5076 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5077 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5078 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5079 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5080 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5081 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5082 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5083 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5084 rsurface.generatedvertex = false;
5086 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5087 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5088 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5089 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5090 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5091 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5092 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5093 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5094 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5095 rsurface.modelelement3i = model->surfmesh.data_element3i;
5096 rsurface.modelelement3s = model->surfmesh.data_element3s;
5097 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5098 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5099 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5100 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5101 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5102 rsurface.modelsurfaces = model->data_surfaces;
5103 rsurface.vertex3f = rsurface.modelvertex3f;
5104 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5105 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5106 rsurface.svector3f = rsurface.modelsvector3f;
5107 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5108 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5109 rsurface.tvector3f = rsurface.modeltvector3f;
5110 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5111 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5112 rsurface.normal3f = rsurface.modelnormal3f;
5113 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5114 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5115 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5118 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5119 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5122 int texturesurfaceindex;
5127 const float *v1, *in_tc;
5129 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5131 q3shaderinfo_deform_t *deform;
5132 // 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
5133 if (rsurface.generatedvertex)
5135 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5136 generatenormals = true;
5137 for (i = 0;i < Q3MAXDEFORMS;i++)
5139 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5141 generatetangents = true;
5142 generatenormals = true;
5144 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5145 generatenormals = true;
5147 if (generatenormals && !rsurface.modelnormal3f)
5149 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5150 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5151 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5152 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5154 if (generatetangents && !rsurface.modelsvector3f)
5156 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5157 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5158 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5159 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5160 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5161 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5162 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);
5165 rsurface.vertex3f = rsurface.modelvertex3f;
5166 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5167 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5168 rsurface.svector3f = rsurface.modelsvector3f;
5169 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5170 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5171 rsurface.tvector3f = rsurface.modeltvector3f;
5172 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5173 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5174 rsurface.normal3f = rsurface.modelnormal3f;
5175 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5176 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5177 // if vertices are deformed (sprite flares and things in maps, possibly
5178 // water waves, bulges and other deformations), generate them into
5179 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5180 // (may be static model data or generated data for an animated model, or
5181 // the previous deform pass)
5182 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5184 switch (deform->deform)
5187 case Q3DEFORM_PROJECTIONSHADOW:
5188 case Q3DEFORM_TEXT0:
5189 case Q3DEFORM_TEXT1:
5190 case Q3DEFORM_TEXT2:
5191 case Q3DEFORM_TEXT3:
5192 case Q3DEFORM_TEXT4:
5193 case Q3DEFORM_TEXT5:
5194 case Q3DEFORM_TEXT6:
5195 case Q3DEFORM_TEXT7:
5198 case Q3DEFORM_AUTOSPRITE:
5199 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5200 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5201 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5202 VectorNormalize(newforward);
5203 VectorNormalize(newright);
5204 VectorNormalize(newup);
5205 // make deformed versions of only the model vertices used by the specified surfaces
5206 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5208 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5209 // a single autosprite surface can contain multiple sprites...
5210 for (j = 0;j < surface->num_vertices - 3;j += 4)
5212 VectorClear(center);
5213 for (i = 0;i < 4;i++)
5214 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5215 VectorScale(center, 0.25f, center);
5216 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5217 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5218 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5219 for (i = 0;i < 4;i++)
5221 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5222 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5225 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);
5226 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);
5228 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5229 rsurface.vertex3f_bufferobject = 0;
5230 rsurface.vertex3f_bufferoffset = 0;
5231 rsurface.svector3f = rsurface.array_deformedsvector3f;
5232 rsurface.svector3f_bufferobject = 0;
5233 rsurface.svector3f_bufferoffset = 0;
5234 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5235 rsurface.tvector3f_bufferobject = 0;
5236 rsurface.tvector3f_bufferoffset = 0;
5237 rsurface.normal3f = rsurface.array_deformednormal3f;
5238 rsurface.normal3f_bufferobject = 0;
5239 rsurface.normal3f_bufferoffset = 0;
5241 case Q3DEFORM_AUTOSPRITE2:
5242 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5243 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5244 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5245 VectorNormalize(newforward);
5246 VectorNormalize(newright);
5247 VectorNormalize(newup);
5248 // make deformed versions of only the model vertices used by the specified surfaces
5249 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5251 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5252 const float *v1, *v2;
5262 memset(shortest, 0, sizeof(shortest));
5263 // a single autosprite surface can contain multiple sprites...
5264 for (j = 0;j < surface->num_vertices - 3;j += 4)
5266 VectorClear(center);
5267 for (i = 0;i < 4;i++)
5268 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5269 VectorScale(center, 0.25f, center);
5270 // find the two shortest edges, then use them to define the
5271 // axis vectors for rotating around the central axis
5272 for (i = 0;i < 6;i++)
5274 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5275 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5277 Debug_PolygonBegin(NULL, 0);
5278 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5279 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);
5280 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5283 l = VectorDistance2(v1, v2);
5284 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5286 l += (1.0f / 1024.0f);
5287 if (shortest[0].length2 > l || i == 0)
5289 shortest[1] = shortest[0];
5290 shortest[0].length2 = l;
5291 shortest[0].v1 = v1;
5292 shortest[0].v2 = v2;
5294 else if (shortest[1].length2 > l || i == 1)
5296 shortest[1].length2 = l;
5297 shortest[1].v1 = v1;
5298 shortest[1].v2 = v2;
5301 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5302 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5304 Debug_PolygonBegin(NULL, 0);
5305 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5306 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);
5307 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5310 // this calculates the right vector from the shortest edge
5311 // and the up vector from the edge midpoints
5312 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5313 VectorNormalize(right);
5314 VectorSubtract(end, start, up);
5315 VectorNormalize(up);
5316 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5317 //VectorSubtract(rsurface.modelorg, center, forward);
5318 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5319 VectorNegate(forward, forward);
5320 VectorReflect(forward, 0, up, forward);
5321 VectorNormalize(forward);
5322 CrossProduct(up, forward, newright);
5323 VectorNormalize(newright);
5325 Debug_PolygonBegin(NULL, 0);
5326 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);
5327 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5328 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5332 Debug_PolygonBegin(NULL, 0);
5333 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5334 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5335 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5338 // rotate the quad around the up axis vector, this is made
5339 // especially easy by the fact we know the quad is flat,
5340 // so we only have to subtract the center position and
5341 // measure distance along the right vector, and then
5342 // multiply that by the newright vector and add back the
5344 // we also need to subtract the old position to undo the
5345 // displacement from the center, which we do with a
5346 // DotProduct, the subtraction/addition of center is also
5347 // optimized into DotProducts here
5348 l = DotProduct(right, center);
5349 for (i = 0;i < 4;i++)
5351 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5352 f = DotProduct(right, v1) - l;
5353 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5356 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);
5357 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);
5359 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5360 rsurface.vertex3f_bufferobject = 0;
5361 rsurface.vertex3f_bufferoffset = 0;
5362 rsurface.svector3f = rsurface.array_deformedsvector3f;
5363 rsurface.svector3f_bufferobject = 0;
5364 rsurface.svector3f_bufferoffset = 0;
5365 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5366 rsurface.tvector3f_bufferobject = 0;
5367 rsurface.tvector3f_bufferoffset = 0;
5368 rsurface.normal3f = rsurface.array_deformednormal3f;
5369 rsurface.normal3f_bufferobject = 0;
5370 rsurface.normal3f_bufferoffset = 0;
5372 case Q3DEFORM_NORMAL:
5373 // deform the normals to make reflections wavey
5374 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5376 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5377 for (j = 0;j < surface->num_vertices;j++)
5380 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5381 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5382 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5383 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5384 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5385 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5386 VectorNormalize(normal);
5388 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);
5390 rsurface.svector3f = rsurface.array_deformedsvector3f;
5391 rsurface.svector3f_bufferobject = 0;
5392 rsurface.svector3f_bufferoffset = 0;
5393 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5394 rsurface.tvector3f_bufferobject = 0;
5395 rsurface.tvector3f_bufferoffset = 0;
5396 rsurface.normal3f = rsurface.array_deformednormal3f;
5397 rsurface.normal3f_bufferobject = 0;
5398 rsurface.normal3f_bufferoffset = 0;
5401 // deform vertex array to make wavey water and flags and such
5402 waveparms[0] = deform->waveparms[0];
5403 waveparms[1] = deform->waveparms[1];
5404 waveparms[2] = deform->waveparms[2];
5405 waveparms[3] = deform->waveparms[3];
5406 // this is how a divisor of vertex influence on deformation
5407 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5408 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5409 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5411 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5412 for (j = 0;j < surface->num_vertices;j++)
5414 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5415 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5416 // if the wavefunc depends on time, evaluate it per-vertex
5419 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5420 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5422 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5425 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5426 rsurface.vertex3f_bufferobject = 0;
5427 rsurface.vertex3f_bufferoffset = 0;
5429 case Q3DEFORM_BULGE:
5430 // deform vertex array to make the surface have moving bulges
5431 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5433 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5434 for (j = 0;j < surface->num_vertices;j++)
5436 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5437 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5440 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5441 rsurface.vertex3f_bufferobject = 0;
5442 rsurface.vertex3f_bufferoffset = 0;
5445 // deform vertex array
5446 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5447 VectorScale(deform->parms, scale, waveparms);
5448 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5450 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5451 for (j = 0;j < surface->num_vertices;j++)
5452 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5454 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5455 rsurface.vertex3f_bufferobject = 0;
5456 rsurface.vertex3f_bufferoffset = 0;
5460 // generate texcoords based on the chosen texcoord source
5461 switch(rsurface.texture->tcgen.tcgen)
5464 case Q3TCGEN_TEXTURE:
5465 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5466 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5467 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5469 case Q3TCGEN_LIGHTMAP:
5470 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5471 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5472 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5474 case Q3TCGEN_VECTOR:
5475 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5477 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5478 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)
5480 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5481 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5484 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5485 rsurface.texcoordtexture2f_bufferobject = 0;
5486 rsurface.texcoordtexture2f_bufferoffset = 0;
5488 case Q3TCGEN_ENVIRONMENT:
5489 // make environment reflections using a spheremap
5490 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5492 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5493 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5494 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5495 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5496 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5498 float l, d, eyedir[3];
5499 VectorSubtract(rsurface.modelorg, vertex, eyedir);
5500 l = 0.5f / VectorLength(eyedir);
5501 d = DotProduct(normal, eyedir)*2;
5502 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
5503 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
5506 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5507 rsurface.texcoordtexture2f_bufferobject = 0;
5508 rsurface.texcoordtexture2f_bufferoffset = 0;
5511 // the only tcmod that needs software vertex processing is turbulent, so
5512 // check for it here and apply the changes if needed
5513 // and we only support that as the first one
5514 // (handling a mixture of turbulent and other tcmods would be problematic
5515 // without punting it entirely to a software path)
5516 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5518 amplitude = rsurface.texture->tcmods[0].parms[1];
5519 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5520 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5522 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5523 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)
5525 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5526 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5529 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5530 rsurface.texcoordtexture2f_bufferobject = 0;
5531 rsurface.texcoordtexture2f_bufferoffset = 0;
5533 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5534 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5535 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5536 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5539 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5542 const msurface_t *surface = texturesurfacelist[0];
5543 const msurface_t *surface2;
5548 // TODO: lock all array ranges before render, rather than on each surface
5549 if (texturenumsurfaces == 1)
5551 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5552 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);
5554 else if (r_batchmode.integer == 2)
5556 #define MAXBATCHTRIANGLES 4096
5557 int batchtriangles = 0;
5558 int batchelements[MAXBATCHTRIANGLES*3];
5559 for (i = 0;i < texturenumsurfaces;i = j)
5561 surface = texturesurfacelist[i];
5563 if (surface->num_triangles > MAXBATCHTRIANGLES)
5565 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);
5568 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5569 batchtriangles = surface->num_triangles;
5570 firstvertex = surface->num_firstvertex;
5571 endvertex = surface->num_firstvertex + surface->num_vertices;
5572 for (;j < texturenumsurfaces;j++)
5574 surface2 = texturesurfacelist[j];
5575 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5577 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5578 batchtriangles += surface2->num_triangles;
5579 firstvertex = min(firstvertex, surface2->num_firstvertex);
5580 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5582 surface2 = texturesurfacelist[j-1];
5583 numvertices = endvertex - firstvertex;
5584 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5587 else if (r_batchmode.integer == 1)
5589 for (i = 0;i < texturenumsurfaces;i = j)
5591 surface = texturesurfacelist[i];
5592 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5593 if (texturesurfacelist[j] != surface2)
5595 surface2 = texturesurfacelist[j-1];
5596 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5597 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5598 GL_LockArrays(surface->num_firstvertex, numvertices);
5599 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5604 for (i = 0;i < texturenumsurfaces;i++)
5606 surface = texturesurfacelist[i];
5607 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5608 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);
5613 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5615 int i, planeindex, vertexindex;
5619 r_waterstate_waterplane_t *p, *bestp;
5620 msurface_t *surface;
5621 if (r_waterstate.renderingscene)
5623 for (i = 0;i < texturenumsurfaces;i++)
5625 surface = texturesurfacelist[i];
5626 if (lightmaptexunit >= 0)
5627 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5628 if (deluxemaptexunit >= 0)
5629 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5630 // pick the closest matching water plane
5633 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5636 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5638 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5639 d += fabs(PlaneDiff(vert, &p->plane));
5641 if (bestd > d || !bestp)
5649 if (refractiontexunit >= 0)
5650 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5651 if (reflectiontexunit >= 0)
5652 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5656 if (refractiontexunit >= 0)
5657 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5658 if (reflectiontexunit >= 0)
5659 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5661 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5662 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);
5666 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5670 const msurface_t *surface = texturesurfacelist[0];
5671 const msurface_t *surface2;
5676 // TODO: lock all array ranges before render, rather than on each surface
5677 if (texturenumsurfaces == 1)
5679 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5680 if (deluxemaptexunit >= 0)
5681 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5682 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5683 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);
5685 else if (r_batchmode.integer == 2)
5687 #define MAXBATCHTRIANGLES 4096
5688 int batchtriangles = 0;
5689 int batchelements[MAXBATCHTRIANGLES*3];
5690 for (i = 0;i < texturenumsurfaces;i = j)
5692 surface = texturesurfacelist[i];
5693 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5694 if (deluxemaptexunit >= 0)
5695 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5697 if (surface->num_triangles > MAXBATCHTRIANGLES)
5699 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);
5702 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5703 batchtriangles = surface->num_triangles;
5704 firstvertex = surface->num_firstvertex;
5705 endvertex = surface->num_firstvertex + surface->num_vertices;
5706 for (;j < texturenumsurfaces;j++)
5708 surface2 = texturesurfacelist[j];
5709 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5711 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5712 batchtriangles += surface2->num_triangles;
5713 firstvertex = min(firstvertex, surface2->num_firstvertex);
5714 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5716 surface2 = texturesurfacelist[j-1];
5717 numvertices = endvertex - firstvertex;
5718 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5721 else if (r_batchmode.integer == 1)
5724 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5725 for (i = 0;i < texturenumsurfaces;i = j)
5727 surface = texturesurfacelist[i];
5728 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5729 if (texturesurfacelist[j] != surface2)
5731 Con_Printf(" %i", j - i);
5734 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5736 for (i = 0;i < texturenumsurfaces;i = j)
5738 surface = texturesurfacelist[i];
5739 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5740 if (deluxemaptexunit >= 0)
5741 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5742 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5743 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5746 Con_Printf(" %i", j - i);
5748 surface2 = texturesurfacelist[j-1];
5749 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5750 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5751 GL_LockArrays(surface->num_firstvertex, numvertices);
5752 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5760 for (i = 0;i < texturenumsurfaces;i++)
5762 surface = texturesurfacelist[i];
5763 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5764 if (deluxemaptexunit >= 0)
5765 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5766 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5767 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);
5772 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5775 int texturesurfaceindex;
5776 if (r_showsurfaces.integer == 2)
5778 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5780 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5781 for (j = 0;j < surface->num_triangles;j++)
5783 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5784 GL_Color(f, f, f, 1);
5785 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5791 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5793 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5794 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5795 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);
5796 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5797 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);
5802 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
5804 int texturesurfaceindex;
5807 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5809 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5810 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)
5818 rsurface.lightmapcolor4f = rsurface.array_color4f;
5819 rsurface.lightmapcolor4f_bufferobject = 0;
5820 rsurface.lightmapcolor4f_bufferoffset = 0;
5823 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5825 int texturesurfaceindex;
5829 if (rsurface.lightmapcolor4f)
5831 // generate color arrays for the surfaces in this list
5832 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5834 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5835 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)
5837 f = FogPoint_Model(v);
5847 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5849 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5850 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)
5852 f = FogPoint_Model(v);
5860 rsurface.lightmapcolor4f = rsurface.array_color4f;
5861 rsurface.lightmapcolor4f_bufferobject = 0;
5862 rsurface.lightmapcolor4f_bufferoffset = 0;
5865 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
5867 int texturesurfaceindex;
5871 if (!rsurface.lightmapcolor4f)
5873 // generate color arrays for the surfaces in this list
5874 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5876 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5877 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)
5879 f = FogPoint_Model(v);
5880 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
5881 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
5882 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
5886 rsurface.lightmapcolor4f = rsurface.array_color4f;
5887 rsurface.lightmapcolor4f_bufferobject = 0;
5888 rsurface.lightmapcolor4f_bufferoffset = 0;
5891 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5893 int texturesurfaceindex;
5896 if (!rsurface.lightmapcolor4f)
5898 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5900 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5901 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)
5909 rsurface.lightmapcolor4f = rsurface.array_color4f;
5910 rsurface.lightmapcolor4f_bufferobject = 0;
5911 rsurface.lightmapcolor4f_bufferoffset = 0;
5914 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
5916 int texturesurfaceindex;
5919 if (!rsurface.lightmapcolor4f)
5921 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5923 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5924 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)
5926 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
5927 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
5928 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
5932 rsurface.lightmapcolor4f = rsurface.array_color4f;
5933 rsurface.lightmapcolor4f_bufferobject = 0;
5934 rsurface.lightmapcolor4f_bufferoffset = 0;
5937 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5940 rsurface.lightmapcolor4f = NULL;
5941 rsurface.lightmapcolor4f_bufferobject = 0;
5942 rsurface.lightmapcolor4f_bufferoffset = 0;
5943 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5944 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5945 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5946 GL_Color(r, g, b, a);
5947 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5950 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5952 // TODO: optimize applyfog && applycolor case
5953 // just apply fog if necessary, and tint the fog color array if necessary
5954 rsurface.lightmapcolor4f = NULL;
5955 rsurface.lightmapcolor4f_bufferobject = 0;
5956 rsurface.lightmapcolor4f_bufferoffset = 0;
5957 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5958 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5959 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5960 GL_Color(r, g, b, a);
5961 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5964 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5966 int texturesurfaceindex;
5970 if (texturesurfacelist[0]->lightmapinfo)
5972 // generate color arrays for the surfaces in this list
5973 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5975 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5976 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5978 if (surface->lightmapinfo->samples)
5980 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5981 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5982 VectorScale(lm, scale, c);
5983 if (surface->lightmapinfo->styles[1] != 255)
5985 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5987 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5988 VectorMA(c, scale, lm, c);
5989 if (surface->lightmapinfo->styles[2] != 255)
5992 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5993 VectorMA(c, scale, lm, c);
5994 if (surface->lightmapinfo->styles[3] != 255)
5997 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5998 VectorMA(c, scale, lm, c);
6008 rsurface.lightmapcolor4f = rsurface.array_color4f;
6009 rsurface.lightmapcolor4f_bufferobject = 0;
6010 rsurface.lightmapcolor4f_bufferoffset = 0;
6014 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6015 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6016 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6018 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6019 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6020 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6021 GL_Color(r, g, b, a);
6022 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6025 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6027 int texturesurfaceindex;
6030 float *v, *c, *c2, alpha;
6031 vec3_t ambientcolor;
6032 vec3_t diffusecolor;
6036 VectorCopy(rsurface.modellight_lightdir, lightdir);
6037 f = 0.5f * r_refdef.lightmapintensity;
6038 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6039 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6040 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6041 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6042 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6043 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6045 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6047 // generate color arrays for the surfaces in this list
6048 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6050 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6051 int numverts = surface->num_vertices;
6052 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6053 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6054 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6055 // q3-style directional shading
6056 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6058 if ((f = DotProduct(c2, lightdir)) > 0)
6059 VectorMA(ambientcolor, f, diffusecolor, c);
6061 VectorCopy(ambientcolor, c);
6069 rsurface.lightmapcolor4f = rsurface.array_color4f;
6070 rsurface.lightmapcolor4f_bufferobject = 0;
6071 rsurface.lightmapcolor4f_bufferoffset = 0;
6072 *applycolor = false;
6076 *r = ambientcolor[0];
6077 *g = ambientcolor[1];
6078 *b = ambientcolor[2];
6079 rsurface.lightmapcolor4f = NULL;
6080 rsurface.lightmapcolor4f_bufferobject = 0;
6081 rsurface.lightmapcolor4f_bufferoffset = 0;
6085 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6087 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6088 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6089 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6090 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6091 GL_Color(r, g, b, a);
6092 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6095 void RSurf_SetupDepthAndCulling(void)
6097 // submodels are biased to avoid z-fighting with world surfaces that they
6098 // may be exactly overlapping (avoids z-fighting artifacts on certain
6099 // doors and things in Quake maps)
6100 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6101 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6102 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6103 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6106 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6108 // transparent sky would be ridiculous
6109 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6111 R_SetupGenericShader(false);
6114 skyrendernow = false;
6115 // we have to force off the water clipping plane while rendering sky
6119 // restore entity matrix
6120 R_Mesh_Matrix(&rsurface.matrix);
6122 RSurf_SetupDepthAndCulling();
6124 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6125 // skymasking on them, and Quake3 never did sky masking (unlike
6126 // software Quake and software Quake2), so disable the sky masking
6127 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6128 // and skymasking also looks very bad when noclipping outside the
6129 // level, so don't use it then either.
6130 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6132 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6133 R_Mesh_ColorPointer(NULL, 0, 0);
6134 R_Mesh_ResetTextureState();
6135 if (skyrendermasked)
6137 R_SetupDepthOrShadowShader();
6138 // depth-only (masking)
6139 GL_ColorMask(0,0,0,0);
6140 // just to make sure that braindead drivers don't draw
6141 // anything despite that colormask...
6142 GL_BlendFunc(GL_ZERO, GL_ONE);
6146 R_SetupGenericShader(false);
6148 GL_BlendFunc(GL_ONE, GL_ZERO);
6150 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6151 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6152 if (skyrendermasked)
6153 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6155 R_Mesh_ResetTextureState();
6156 GL_Color(1, 1, 1, 1);
6159 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6161 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6164 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6165 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6166 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6167 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6168 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6169 if (rsurface.texture->backgroundcurrentskinframe)
6171 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6172 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6173 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6174 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6176 if(rsurface.texture->colormapping)
6178 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6179 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6181 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6182 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6183 R_Mesh_ColorPointer(NULL, 0, 0);
6185 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6187 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6189 // render background
6190 GL_BlendFunc(GL_ONE, GL_ZERO);
6192 GL_AlphaTest(false);
6194 GL_Color(1, 1, 1, 1);
6195 R_Mesh_ColorPointer(NULL, 0, 0);
6197 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6198 if (r_glsl_permutation)
6200 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6201 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6202 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6203 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6204 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6205 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6206 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);
6208 GL_LockArrays(0, 0);
6210 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6211 GL_DepthMask(false);
6212 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6213 R_Mesh_ColorPointer(NULL, 0, 0);
6215 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6216 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6217 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6220 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6221 if (!r_glsl_permutation)
6224 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6225 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6226 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6227 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6228 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6229 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6231 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6233 GL_BlendFunc(GL_ONE, GL_ZERO);
6235 GL_AlphaTest(false);
6239 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6240 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6241 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6244 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6246 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6247 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);
6249 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6253 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6254 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);
6256 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6258 GL_LockArrays(0, 0);
6261 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6263 // OpenGL 1.3 path - anything not completely ancient
6264 int texturesurfaceindex;
6265 qboolean applycolor;
6269 const texturelayer_t *layer;
6270 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6272 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6275 int layertexrgbscale;
6276 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6278 if (layerindex == 0)
6282 GL_AlphaTest(false);
6283 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6286 GL_DepthMask(layer->depthmask && writedepth);
6287 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6288 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6290 layertexrgbscale = 4;
6291 VectorScale(layer->color, 0.25f, layercolor);
6293 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6295 layertexrgbscale = 2;
6296 VectorScale(layer->color, 0.5f, layercolor);
6300 layertexrgbscale = 1;
6301 VectorScale(layer->color, 1.0f, layercolor);
6303 layercolor[3] = layer->color[3];
6304 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6305 R_Mesh_ColorPointer(NULL, 0, 0);
6306 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6307 switch (layer->type)
6309 case TEXTURELAYERTYPE_LITTEXTURE:
6310 memset(&m, 0, sizeof(m));
6311 m.tex[0] = R_GetTexture(r_texture_white);
6312 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6313 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6314 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6315 m.tex[1] = R_GetTexture(layer->texture);
6316 m.texmatrix[1] = layer->texmatrix;
6317 m.texrgbscale[1] = layertexrgbscale;
6318 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6319 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6320 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6321 R_Mesh_TextureState(&m);
6322 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6323 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6324 else if (rsurface.uselightmaptexture)
6325 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6327 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6329 case TEXTURELAYERTYPE_TEXTURE:
6330 memset(&m, 0, sizeof(m));
6331 m.tex[0] = R_GetTexture(layer->texture);
6332 m.texmatrix[0] = layer->texmatrix;
6333 m.texrgbscale[0] = layertexrgbscale;
6334 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6335 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6336 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6337 R_Mesh_TextureState(&m);
6338 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6340 case TEXTURELAYERTYPE_FOG:
6341 memset(&m, 0, sizeof(m));
6342 m.texrgbscale[0] = layertexrgbscale;
6345 m.tex[0] = R_GetTexture(layer->texture);
6346 m.texmatrix[0] = layer->texmatrix;
6347 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6348 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6349 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6351 R_Mesh_TextureState(&m);
6352 // generate a color array for the fog pass
6353 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6354 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6358 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6359 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)
6361 f = 1 - FogPoint_Model(v);
6362 c[0] = layercolor[0];
6363 c[1] = layercolor[1];
6364 c[2] = layercolor[2];
6365 c[3] = f * layercolor[3];
6368 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6371 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6373 GL_LockArrays(0, 0);
6376 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6378 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6379 GL_AlphaTest(false);
6383 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6385 // OpenGL 1.1 - crusty old voodoo path
6386 int texturesurfaceindex;
6390 const texturelayer_t *layer;
6391 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6393 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6395 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6397 if (layerindex == 0)
6401 GL_AlphaTest(false);
6402 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6405 GL_DepthMask(layer->depthmask && writedepth);
6406 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6407 R_Mesh_ColorPointer(NULL, 0, 0);
6408 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6409 switch (layer->type)
6411 case TEXTURELAYERTYPE_LITTEXTURE:
6412 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6414 // two-pass lit texture with 2x rgbscale
6415 // first the lightmap pass
6416 memset(&m, 0, sizeof(m));
6417 m.tex[0] = R_GetTexture(r_texture_white);
6418 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6419 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6420 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6421 R_Mesh_TextureState(&m);
6422 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6423 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6424 else if (rsurface.uselightmaptexture)
6425 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6427 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6428 GL_LockArrays(0, 0);
6429 // then apply the texture to it
6430 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6431 memset(&m, 0, sizeof(m));
6432 m.tex[0] = R_GetTexture(layer->texture);
6433 m.texmatrix[0] = layer->texmatrix;
6434 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6435 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6436 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6437 R_Mesh_TextureState(&m);
6438 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);
6442 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6443 memset(&m, 0, sizeof(m));
6444 m.tex[0] = R_GetTexture(layer->texture);
6445 m.texmatrix[0] = layer->texmatrix;
6446 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6447 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6448 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6449 R_Mesh_TextureState(&m);
6450 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6451 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);
6453 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);
6456 case TEXTURELAYERTYPE_TEXTURE:
6457 // singletexture unlit texture with transparency support
6458 memset(&m, 0, sizeof(m));
6459 m.tex[0] = R_GetTexture(layer->texture);
6460 m.texmatrix[0] = layer->texmatrix;
6461 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6462 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6463 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6464 R_Mesh_TextureState(&m);
6465 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, 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);
6467 case TEXTURELAYERTYPE_FOG:
6468 // singletexture fogging
6469 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6472 memset(&m, 0, sizeof(m));
6473 m.tex[0] = R_GetTexture(layer->texture);
6474 m.texmatrix[0] = layer->texmatrix;
6475 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6476 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6477 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6478 R_Mesh_TextureState(&m);
6481 R_Mesh_ResetTextureState();
6482 // generate a color array for the fog pass
6483 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6487 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6488 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)
6490 f = 1 - FogPoint_Model(v);
6491 c[0] = layer->color[0];
6492 c[1] = layer->color[1];
6493 c[2] = layer->color[2];
6494 c[3] = f * layer->color[3];
6497 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6500 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6502 GL_LockArrays(0, 0);
6505 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6507 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6508 GL_AlphaTest(false);
6512 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6516 GL_AlphaTest(false);
6517 R_Mesh_ColorPointer(NULL, 0, 0);
6518 R_Mesh_ResetTextureState();
6519 R_SetupGenericShader(false);
6521 if(rsurface.texture && rsurface.texture->currentskinframe)
6522 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6531 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6533 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
6534 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
6535 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
6538 // brighten it up (as texture value 127 means "unlit")
6539 c[0] *= 2 * r_refdef.view.colorscale;
6540 c[1] *= 2 * r_refdef.view.colorscale;
6541 c[2] *= 2 * r_refdef.view.colorscale;
6543 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6544 c[3] *= r_wateralpha.value;
6546 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6548 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6549 GL_DepthMask(false);
6551 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6553 GL_BlendFunc(GL_ONE, GL_ONE);
6554 GL_DepthMask(false);
6556 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6558 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6559 GL_DepthMask(false);
6561 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6563 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6564 GL_DepthMask(false);
6568 GL_BlendFunc(GL_ONE, GL_ZERO);
6569 GL_DepthMask(writedepth);
6572 rsurface.lightmapcolor4f = NULL;
6574 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6576 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6578 rsurface.lightmapcolor4f = NULL;
6579 rsurface.lightmapcolor4f_bufferobject = 0;
6580 rsurface.lightmapcolor4f_bufferoffset = 0;
6582 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6584 qboolean applycolor = true;
6587 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6589 r_refdef.lightmapintensity = 1;
6590 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6591 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6595 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6597 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6598 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6599 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6602 if(!rsurface.lightmapcolor4f)
6603 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6605 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6606 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6607 if(r_refdef.fogenabled)
6608 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6610 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6611 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6614 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6617 RSurf_SetupDepthAndCulling();
6618 if (r_showsurfaces.integer == 3)
6619 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6620 else if (r_glsl.integer && gl_support_fragment_shader)
6621 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6622 else if (gl_combine.integer && r_textureunits.integer >= 2)
6623 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6625 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6629 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6632 RSurf_SetupDepthAndCulling();
6633 if (r_showsurfaces.integer == 3)
6634 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6635 else if (r_glsl.integer && gl_support_fragment_shader)
6636 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6637 else if (gl_combine.integer && r_textureunits.integer >= 2)
6638 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6640 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6644 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6647 int texturenumsurfaces, endsurface;
6649 msurface_t *surface;
6650 msurface_t *texturesurfacelist[1024];
6652 // if the model is static it doesn't matter what value we give for
6653 // wantnormals and wanttangents, so this logic uses only rules applicable
6654 // to a model, knowing that they are meaningless otherwise
6655 if (ent == r_refdef.scene.worldentity)
6656 RSurf_ActiveWorldEntity();
6657 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6658 RSurf_ActiveModelEntity(ent, false, false);
6660 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6662 for (i = 0;i < numsurfaces;i = j)
6665 surface = rsurface.modelsurfaces + surfacelist[i];
6666 texture = surface->texture;
6667 rsurface.texture = R_GetCurrentTexture(texture);
6668 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6669 // scan ahead until we find a different texture
6670 endsurface = min(i + 1024, numsurfaces);
6671 texturenumsurfaces = 0;
6672 texturesurfacelist[texturenumsurfaces++] = surface;
6673 for (;j < endsurface;j++)
6675 surface = rsurface.modelsurfaces + surfacelist[j];
6676 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6678 texturesurfacelist[texturenumsurfaces++] = surface;
6680 // render the range of surfaces
6681 if (ent == r_refdef.scene.worldentity)
6682 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6684 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6686 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6687 GL_AlphaTest(false);
6690 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6692 const entity_render_t *queueentity = r_refdef.scene.worldentity;
6696 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6698 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6700 RSurf_SetupDepthAndCulling();
6701 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6702 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6704 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6706 RSurf_SetupDepthAndCulling();
6707 GL_AlphaTest(false);
6708 R_Mesh_ColorPointer(NULL, 0, 0);
6709 R_Mesh_ResetTextureState();
6710 R_SetupGenericShader(false);
6711 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6713 GL_BlendFunc(GL_ONE, GL_ZERO);
6714 GL_Color(0, 0, 0, 1);
6715 GL_DepthTest(writedepth);
6716 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6718 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6720 RSurf_SetupDepthAndCulling();
6721 GL_AlphaTest(false);
6722 R_Mesh_ColorPointer(NULL, 0, 0);
6723 R_Mesh_ResetTextureState();
6724 R_SetupGenericShader(false);
6725 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6727 GL_BlendFunc(GL_ONE, GL_ZERO);
6729 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6731 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6732 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6733 else if (!rsurface.texture->currentnumlayers)
6735 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6737 // transparent surfaces get pushed off into the transparent queue
6738 int surfacelistindex;
6739 const msurface_t *surface;
6740 vec3_t tempcenter, center;
6741 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6743 surface = texturesurfacelist[surfacelistindex];
6744 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6745 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6746 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6747 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6748 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6753 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6754 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6759 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6763 // break the surface list down into batches by texture and use of lightmapping
6764 for (i = 0;i < numsurfaces;i = j)
6767 // texture is the base texture pointer, rsurface.texture is the
6768 // current frame/skin the texture is directing us to use (for example
6769 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6770 // use skin 1 instead)
6771 texture = surfacelist[i]->texture;
6772 rsurface.texture = R_GetCurrentTexture(texture);
6773 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6774 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6776 // if this texture is not the kind we want, skip ahead to the next one
6777 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6781 // simply scan ahead until we find a different texture or lightmap state
6782 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6784 // render the range of surfaces
6785 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6789 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6794 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6796 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6798 RSurf_SetupDepthAndCulling();
6799 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6800 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6802 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6804 RSurf_SetupDepthAndCulling();
6805 GL_AlphaTest(false);
6806 R_Mesh_ColorPointer(NULL, 0, 0);
6807 R_Mesh_ResetTextureState();
6808 R_SetupGenericShader(false);
6809 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6811 GL_BlendFunc(GL_ONE, GL_ZERO);
6812 GL_Color(0, 0, 0, 1);
6813 GL_DepthTest(writedepth);
6814 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6816 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6818 RSurf_SetupDepthAndCulling();
6819 GL_AlphaTest(false);
6820 R_Mesh_ColorPointer(NULL, 0, 0);
6821 R_Mesh_ResetTextureState();
6822 R_SetupGenericShader(false);
6823 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6825 GL_BlendFunc(GL_ONE, GL_ZERO);
6827 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6829 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6830 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6831 else if (!rsurface.texture->currentnumlayers)
6833 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6835 // transparent surfaces get pushed off into the transparent queue
6836 int surfacelistindex;
6837 const msurface_t *surface;
6838 vec3_t tempcenter, center;
6839 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6841 surface = texturesurfacelist[surfacelistindex];
6842 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6843 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6844 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6845 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6846 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6851 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6852 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6857 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6861 // break the surface list down into batches by texture and use of lightmapping
6862 for (i = 0;i < numsurfaces;i = j)
6865 // texture is the base texture pointer, rsurface.texture is the
6866 // current frame/skin the texture is directing us to use (for example
6867 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6868 // use skin 1 instead)
6869 texture = surfacelist[i]->texture;
6870 rsurface.texture = R_GetCurrentTexture(texture);
6871 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6872 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6874 // if this texture is not the kind we want, skip ahead to the next one
6875 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6879 // simply scan ahead until we find a different texture or lightmap state
6880 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6882 // render the range of surfaces
6883 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6887 float locboxvertex3f[6*4*3] =
6889 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6890 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6891 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6892 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6893 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6894 1,0,0, 0,0,0, 0,1,0, 1,1,0
6897 unsigned short locboxelements[6*2*3] =
6907 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6910 cl_locnode_t *loc = (cl_locnode_t *)ent;
6912 float vertex3f[6*4*3];
6914 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6915 GL_DepthMask(false);
6916 GL_DepthRange(0, 1);
6917 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6919 GL_CullFace(GL_NONE);
6920 R_Mesh_Matrix(&identitymatrix);
6922 R_Mesh_VertexPointer(vertex3f, 0, 0);
6923 R_Mesh_ColorPointer(NULL, 0, 0);
6924 R_Mesh_ResetTextureState();
6925 R_SetupGenericShader(false);
6928 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6929 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6930 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6931 surfacelist[0] < 0 ? 0.5f : 0.125f);
6933 if (VectorCompare(loc->mins, loc->maxs))
6935 VectorSet(size, 2, 2, 2);
6936 VectorMA(loc->mins, -0.5f, size, mins);
6940 VectorCopy(loc->mins, mins);
6941 VectorSubtract(loc->maxs, loc->mins, size);
6944 for (i = 0;i < 6*4*3;)
6945 for (j = 0;j < 3;j++, i++)
6946 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6948 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
6951 void R_DrawLocs(void)
6954 cl_locnode_t *loc, *nearestloc;
6956 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6957 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6959 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6960 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6964 void R_DrawDebugModel(entity_render_t *ent)
6966 int i, j, k, l, flagsmask;
6967 const int *elements;
6969 msurface_t *surface;
6970 dp_model_t *model = ent->model;
6973 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
6975 R_Mesh_ColorPointer(NULL, 0, 0);
6976 R_Mesh_ResetTextureState();
6977 R_SetupGenericShader(false);
6978 GL_DepthRange(0, 1);
6979 GL_DepthTest(!r_showdisabledepthtest.integer);
6980 GL_DepthMask(false);
6981 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6983 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6985 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6986 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6988 if (brush->colbrushf && brush->colbrushf->numtriangles)
6990 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6991 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);
6992 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
6995 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6997 if (surface->num_collisiontriangles)
6999 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7000 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);
7001 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7006 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7008 if (r_showtris.integer || r_shownormals.integer)
7010 if (r_showdisabledepthtest.integer)
7012 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7013 GL_DepthMask(false);
7017 GL_BlendFunc(GL_ONE, GL_ZERO);
7020 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7022 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7024 rsurface.texture = R_GetCurrentTexture(surface->texture);
7025 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7027 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7028 if (r_showtris.value > 0)
7030 if (!rsurface.texture->currentlayers->depthmask)
7031 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7032 else if (ent == r_refdef.scene.worldentity)
7033 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7035 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7036 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7037 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7038 R_Mesh_ColorPointer(NULL, 0, 0);
7039 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7040 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7041 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7042 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);
7043 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7046 if (r_shownormals.value < 0)
7049 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7051 VectorCopy(rsurface.vertex3f + l * 3, v);
7052 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7053 qglVertex3f(v[0], v[1], v[2]);
7054 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7055 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7056 qglVertex3f(v[0], v[1], v[2]);
7061 if (r_shownormals.value > 0)
7064 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7066 VectorCopy(rsurface.vertex3f + l * 3, v);
7067 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7068 qglVertex3f(v[0], v[1], v[2]);
7069 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7070 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7071 qglVertex3f(v[0], v[1], v[2]);
7076 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7078 VectorCopy(rsurface.vertex3f + l * 3, v);
7079 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7080 qglVertex3f(v[0], v[1], v[2]);
7081 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7082 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7083 qglVertex3f(v[0], v[1], v[2]);
7088 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7090 VectorCopy(rsurface.vertex3f + l * 3, v);
7091 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7092 qglVertex3f(v[0], v[1], v[2]);
7093 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7094 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7095 qglVertex3f(v[0], v[1], v[2]);
7102 rsurface.texture = NULL;
7106 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7107 int r_maxsurfacelist = 0;
7108 msurface_t **r_surfacelist = NULL;
7109 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7111 int i, j, endj, f, flagsmask;
7113 dp_model_t *model = r_refdef.scene.worldmodel;
7114 msurface_t *surfaces;
7115 unsigned char *update;
7116 int numsurfacelist = 0;
7120 if (r_maxsurfacelist < model->num_surfaces)
7122 r_maxsurfacelist = model->num_surfaces;
7124 Mem_Free(r_surfacelist);
7125 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7128 RSurf_ActiveWorldEntity();
7130 surfaces = model->data_surfaces;
7131 update = model->brushq1.lightmapupdateflags;
7133 // update light styles on this submodel
7134 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7136 model_brush_lightstyleinfo_t *style;
7137 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7139 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7141 int *list = style->surfacelist;
7142 style->value = r_refdef.scene.lightstylevalue[style->style];
7143 for (j = 0;j < style->numsurfaces;j++)
7144 update[list[j]] = true;
7149 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7153 R_DrawDebugModel(r_refdef.scene.worldentity);
7159 rsurface.uselightmaptexture = false;
7160 rsurface.texture = NULL;
7161 rsurface.rtlight = NULL;
7163 // add visible surfaces to draw list
7164 for (i = 0;i < model->nummodelsurfaces;i++)
7166 j = model->sortedmodelsurfaces[i];
7167 if (r_refdef.viewcache.world_surfacevisible[j])
7168 r_surfacelist[numsurfacelist++] = surfaces + j;
7170 // update lightmaps if needed
7172 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7173 if (r_refdef.viewcache.world_surfacevisible[j])
7175 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7176 // don't do anything if there were no surfaces
7177 if (!numsurfacelist)
7179 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7180 GL_AlphaTest(false);
7182 // add to stats if desired
7183 if (r_speeds.integer && !skysurfaces && !depthonly)
7185 r_refdef.stats.world_surfaces += numsurfacelist;
7186 for (j = 0;j < numsurfacelist;j++)
7187 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7191 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7193 int i, j, endj, f, flagsmask;
7195 dp_model_t *model = ent->model;
7196 msurface_t *surfaces;
7197 unsigned char *update;
7198 int numsurfacelist = 0;
7202 if (r_maxsurfacelist < model->num_surfaces)
7204 r_maxsurfacelist = model->num_surfaces;
7206 Mem_Free(r_surfacelist);
7207 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7210 // if the model is static it doesn't matter what value we give for
7211 // wantnormals and wanttangents, so this logic uses only rules applicable
7212 // to a model, knowing that they are meaningless otherwise
7213 if (ent == r_refdef.scene.worldentity)
7214 RSurf_ActiveWorldEntity();
7215 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
7216 RSurf_ActiveModelEntity(ent, false, false);
7218 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7220 surfaces = model->data_surfaces;
7221 update = model->brushq1.lightmapupdateflags;
7223 // update light styles
7224 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7226 model_brush_lightstyleinfo_t *style;
7227 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7229 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7231 int *list = style->surfacelist;
7232 style->value = r_refdef.scene.lightstylevalue[style->style];
7233 for (j = 0;j < style->numsurfaces;j++)
7234 update[list[j]] = true;
7239 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7243 R_DrawDebugModel(ent);
7249 rsurface.uselightmaptexture = false;
7250 rsurface.texture = NULL;
7251 rsurface.rtlight = NULL;
7253 // add visible surfaces to draw list
7254 for (i = 0;i < model->nummodelsurfaces;i++)
7255 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7256 // don't do anything if there were no surfaces
7257 if (!numsurfacelist)
7259 // update lightmaps if needed
7261 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7263 R_BuildLightMap(ent, surfaces + j);
7264 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7265 GL_AlphaTest(false);
7267 // add to stats if desired
7268 if (r_speeds.integer && !skysurfaces && !depthonly)
7270 r_refdef.stats.entities++;
7271 r_refdef.stats.entities_surfaces += numsurfacelist;
7272 for (j = 0;j < numsurfacelist;j++)
7273 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;