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 (requires r_lerpmodels 1)"};
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(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->frame2 != 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 rsurface.frameblend[0].frame = 0;
4956 rsurface.frameblend[0].lerp = 1;
4957 rsurface.frameblend[1].frame = 0;
4958 rsurface.frameblend[1].lerp = 0;
4959 rsurface.frameblend[2].frame = 0;
4960 rsurface.frameblend[2].lerp = 0;
4961 rsurface.frameblend[3].frame = 0;
4962 rsurface.frameblend[3].lerp = 0;
4963 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4964 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4965 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4966 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4967 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4968 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4969 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4970 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4971 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4972 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4973 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4974 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4975 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4976 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4977 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4978 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4979 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4980 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4981 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4982 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4983 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4984 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4985 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4986 rsurface.modelelement3i = model->surfmesh.data_element3i;
4987 rsurface.modelelement3s = model->surfmesh.data_element3s;
4988 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
4989 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
4990 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4991 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4992 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4993 rsurface.modelsurfaces = model->data_surfaces;
4994 rsurface.generatedvertex = false;
4995 rsurface.vertex3f = rsurface.modelvertex3f;
4996 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4997 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4998 rsurface.svector3f = rsurface.modelsvector3f;
4999 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5000 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5001 rsurface.tvector3f = rsurface.modeltvector3f;
5002 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5003 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5004 rsurface.normal3f = rsurface.modelnormal3f;
5005 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5006 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5007 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5010 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5012 dp_model_t *model = ent->model;
5013 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5015 rsurface.entity = (entity_render_t *)ent;
5016 if (rsurface.array_size < model->surfmesh.num_vertices)
5017 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5018 rsurface.matrix = ent->matrix;
5019 rsurface.inversematrix = ent->inversematrix;
5020 R_Mesh_Matrix(&rsurface.matrix);
5021 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5022 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5023 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5024 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5025 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5026 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5027 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5028 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5029 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5030 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5031 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5032 rsurface.frameblend[0] = ent->frameblend[0];
5033 rsurface.frameblend[1] = ent->frameblend[1];
5034 rsurface.frameblend[2] = ent->frameblend[2];
5035 rsurface.frameblend[3] = ent->frameblend[3];
5036 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5037 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5038 if (ent->model->brush.submodel)
5040 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5041 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5043 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
5047 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5048 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5049 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5050 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5051 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5053 else if (wantnormals)
5055 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5056 rsurface.modelsvector3f = NULL;
5057 rsurface.modeltvector3f = NULL;
5058 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5059 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5063 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5064 rsurface.modelsvector3f = NULL;
5065 rsurface.modeltvector3f = NULL;
5066 rsurface.modelnormal3f = NULL;
5067 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5069 rsurface.modelvertex3f_bufferobject = 0;
5070 rsurface.modelvertex3f_bufferoffset = 0;
5071 rsurface.modelsvector3f_bufferobject = 0;
5072 rsurface.modelsvector3f_bufferoffset = 0;
5073 rsurface.modeltvector3f_bufferobject = 0;
5074 rsurface.modeltvector3f_bufferoffset = 0;
5075 rsurface.modelnormal3f_bufferobject = 0;
5076 rsurface.modelnormal3f_bufferoffset = 0;
5077 rsurface.generatedvertex = true;
5081 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5082 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5083 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5084 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5085 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5086 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5087 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5088 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5089 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5090 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5091 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5092 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5093 rsurface.generatedvertex = false;
5095 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5096 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5097 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5098 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5099 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5100 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5101 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5102 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5103 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5104 rsurface.modelelement3i = model->surfmesh.data_element3i;
5105 rsurface.modelelement3s = model->surfmesh.data_element3s;
5106 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5107 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5108 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5109 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5110 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5111 rsurface.modelsurfaces = model->data_surfaces;
5112 rsurface.vertex3f = rsurface.modelvertex3f;
5113 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5114 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5115 rsurface.svector3f = rsurface.modelsvector3f;
5116 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5117 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5118 rsurface.tvector3f = rsurface.modeltvector3f;
5119 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5120 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5121 rsurface.normal3f = rsurface.modelnormal3f;
5122 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5123 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5124 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5127 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5128 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5131 int texturesurfaceindex;
5136 const float *v1, *in_tc;
5138 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5140 q3shaderinfo_deform_t *deform;
5141 // 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
5142 if (rsurface.generatedvertex)
5144 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5145 generatenormals = true;
5146 for (i = 0;i < Q3MAXDEFORMS;i++)
5148 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5150 generatetangents = true;
5151 generatenormals = true;
5153 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5154 generatenormals = true;
5156 if (generatenormals && !rsurface.modelnormal3f)
5158 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5159 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5160 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5161 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5163 if (generatetangents && !rsurface.modelsvector3f)
5165 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5166 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5167 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5168 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5169 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5170 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5171 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);
5174 rsurface.vertex3f = rsurface.modelvertex3f;
5175 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5176 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5177 rsurface.svector3f = rsurface.modelsvector3f;
5178 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5179 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5180 rsurface.tvector3f = rsurface.modeltvector3f;
5181 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5182 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5183 rsurface.normal3f = rsurface.modelnormal3f;
5184 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5185 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5186 // if vertices are deformed (sprite flares and things in maps, possibly
5187 // water waves, bulges and other deformations), generate them into
5188 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5189 // (may be static model data or generated data for an animated model, or
5190 // the previous deform pass)
5191 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5193 switch (deform->deform)
5196 case Q3DEFORM_PROJECTIONSHADOW:
5197 case Q3DEFORM_TEXT0:
5198 case Q3DEFORM_TEXT1:
5199 case Q3DEFORM_TEXT2:
5200 case Q3DEFORM_TEXT3:
5201 case Q3DEFORM_TEXT4:
5202 case Q3DEFORM_TEXT5:
5203 case Q3DEFORM_TEXT6:
5204 case Q3DEFORM_TEXT7:
5207 case Q3DEFORM_AUTOSPRITE:
5208 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5209 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5210 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5211 VectorNormalize(newforward);
5212 VectorNormalize(newright);
5213 VectorNormalize(newup);
5214 // make deformed versions of only the model vertices used by the specified surfaces
5215 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5217 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5218 // a single autosprite surface can contain multiple sprites...
5219 for (j = 0;j < surface->num_vertices - 3;j += 4)
5221 VectorClear(center);
5222 for (i = 0;i < 4;i++)
5223 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5224 VectorScale(center, 0.25f, center);
5225 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5226 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5227 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5228 for (i = 0;i < 4;i++)
5230 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5231 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5234 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);
5235 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);
5237 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5238 rsurface.vertex3f_bufferobject = 0;
5239 rsurface.vertex3f_bufferoffset = 0;
5240 rsurface.svector3f = rsurface.array_deformedsvector3f;
5241 rsurface.svector3f_bufferobject = 0;
5242 rsurface.svector3f_bufferoffset = 0;
5243 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5244 rsurface.tvector3f_bufferobject = 0;
5245 rsurface.tvector3f_bufferoffset = 0;
5246 rsurface.normal3f = rsurface.array_deformednormal3f;
5247 rsurface.normal3f_bufferobject = 0;
5248 rsurface.normal3f_bufferoffset = 0;
5250 case Q3DEFORM_AUTOSPRITE2:
5251 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5252 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5253 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5254 VectorNormalize(newforward);
5255 VectorNormalize(newright);
5256 VectorNormalize(newup);
5257 // make deformed versions of only the model vertices used by the specified surfaces
5258 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5260 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5261 const float *v1, *v2;
5271 memset(shortest, 0, sizeof(shortest));
5272 // a single autosprite surface can contain multiple sprites...
5273 for (j = 0;j < surface->num_vertices - 3;j += 4)
5275 VectorClear(center);
5276 for (i = 0;i < 4;i++)
5277 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5278 VectorScale(center, 0.25f, center);
5279 // find the two shortest edges, then use them to define the
5280 // axis vectors for rotating around the central axis
5281 for (i = 0;i < 6;i++)
5283 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5284 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5286 Debug_PolygonBegin(NULL, 0);
5287 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5288 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);
5289 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5292 l = VectorDistance2(v1, v2);
5293 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5295 l += (1.0f / 1024.0f);
5296 if (shortest[0].length2 > l || i == 0)
5298 shortest[1] = shortest[0];
5299 shortest[0].length2 = l;
5300 shortest[0].v1 = v1;
5301 shortest[0].v2 = v2;
5303 else if (shortest[1].length2 > l || i == 1)
5305 shortest[1].length2 = l;
5306 shortest[1].v1 = v1;
5307 shortest[1].v2 = v2;
5310 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5311 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5313 Debug_PolygonBegin(NULL, 0);
5314 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5315 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);
5316 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5319 // this calculates the right vector from the shortest edge
5320 // and the up vector from the edge midpoints
5321 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5322 VectorNormalize(right);
5323 VectorSubtract(end, start, up);
5324 VectorNormalize(up);
5325 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5326 //VectorSubtract(rsurface.modelorg, center, forward);
5327 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5328 VectorNegate(forward, forward);
5329 VectorReflect(forward, 0, up, forward);
5330 VectorNormalize(forward);
5331 CrossProduct(up, forward, newright);
5332 VectorNormalize(newright);
5334 Debug_PolygonBegin(NULL, 0);
5335 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);
5336 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5337 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5341 Debug_PolygonBegin(NULL, 0);
5342 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5343 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5344 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5347 // rotate the quad around the up axis vector, this is made
5348 // especially easy by the fact we know the quad is flat,
5349 // so we only have to subtract the center position and
5350 // measure distance along the right vector, and then
5351 // multiply that by the newright vector and add back the
5353 // we also need to subtract the old position to undo the
5354 // displacement from the center, which we do with a
5355 // DotProduct, the subtraction/addition of center is also
5356 // optimized into DotProducts here
5357 l = DotProduct(right, center);
5358 for (i = 0;i < 4;i++)
5360 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5361 f = DotProduct(right, v1) - l;
5362 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5365 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);
5366 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);
5368 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5369 rsurface.vertex3f_bufferobject = 0;
5370 rsurface.vertex3f_bufferoffset = 0;
5371 rsurface.svector3f = rsurface.array_deformedsvector3f;
5372 rsurface.svector3f_bufferobject = 0;
5373 rsurface.svector3f_bufferoffset = 0;
5374 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5375 rsurface.tvector3f_bufferobject = 0;
5376 rsurface.tvector3f_bufferoffset = 0;
5377 rsurface.normal3f = rsurface.array_deformednormal3f;
5378 rsurface.normal3f_bufferobject = 0;
5379 rsurface.normal3f_bufferoffset = 0;
5381 case Q3DEFORM_NORMAL:
5382 // deform the normals to make reflections wavey
5383 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5385 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5386 for (j = 0;j < surface->num_vertices;j++)
5389 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5390 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5391 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5392 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5393 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5394 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5395 VectorNormalize(normal);
5397 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);
5399 rsurface.svector3f = rsurface.array_deformedsvector3f;
5400 rsurface.svector3f_bufferobject = 0;
5401 rsurface.svector3f_bufferoffset = 0;
5402 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5403 rsurface.tvector3f_bufferobject = 0;
5404 rsurface.tvector3f_bufferoffset = 0;
5405 rsurface.normal3f = rsurface.array_deformednormal3f;
5406 rsurface.normal3f_bufferobject = 0;
5407 rsurface.normal3f_bufferoffset = 0;
5410 // deform vertex array to make wavey water and flags and such
5411 waveparms[0] = deform->waveparms[0];
5412 waveparms[1] = deform->waveparms[1];
5413 waveparms[2] = deform->waveparms[2];
5414 waveparms[3] = deform->waveparms[3];
5415 // this is how a divisor of vertex influence on deformation
5416 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5417 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5418 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5420 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5421 for (j = 0;j < surface->num_vertices;j++)
5423 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5424 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5425 // if the wavefunc depends on time, evaluate it per-vertex
5428 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5429 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5431 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5434 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5435 rsurface.vertex3f_bufferobject = 0;
5436 rsurface.vertex3f_bufferoffset = 0;
5438 case Q3DEFORM_BULGE:
5439 // deform vertex array to make the surface have moving bulges
5440 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5442 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5443 for (j = 0;j < surface->num_vertices;j++)
5445 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5446 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5449 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5450 rsurface.vertex3f_bufferobject = 0;
5451 rsurface.vertex3f_bufferoffset = 0;
5454 // deform vertex array
5455 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5456 VectorScale(deform->parms, scale, waveparms);
5457 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5459 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5460 for (j = 0;j < surface->num_vertices;j++)
5461 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5463 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5464 rsurface.vertex3f_bufferobject = 0;
5465 rsurface.vertex3f_bufferoffset = 0;
5469 // generate texcoords based on the chosen texcoord source
5470 switch(rsurface.texture->tcgen.tcgen)
5473 case Q3TCGEN_TEXTURE:
5474 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5475 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5476 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5478 case Q3TCGEN_LIGHTMAP:
5479 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5480 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5481 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5483 case Q3TCGEN_VECTOR:
5484 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5486 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5487 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)
5489 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5490 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5493 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5494 rsurface.texcoordtexture2f_bufferobject = 0;
5495 rsurface.texcoordtexture2f_bufferoffset = 0;
5497 case Q3TCGEN_ENVIRONMENT:
5498 // make environment reflections using a spheremap
5499 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5501 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5502 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5503 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5504 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5505 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5507 float l, d, eyedir[3];
5508 VectorSubtract(rsurface.modelorg, vertex, eyedir);
5509 l = 0.5f / VectorLength(eyedir);
5510 d = DotProduct(normal, eyedir)*2;
5511 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
5512 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
5515 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5516 rsurface.texcoordtexture2f_bufferobject = 0;
5517 rsurface.texcoordtexture2f_bufferoffset = 0;
5520 // the only tcmod that needs software vertex processing is turbulent, so
5521 // check for it here and apply the changes if needed
5522 // and we only support that as the first one
5523 // (handling a mixture of turbulent and other tcmods would be problematic
5524 // without punting it entirely to a software path)
5525 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5527 amplitude = rsurface.texture->tcmods[0].parms[1];
5528 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5529 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5531 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5532 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)
5534 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5535 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5538 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5539 rsurface.texcoordtexture2f_bufferobject = 0;
5540 rsurface.texcoordtexture2f_bufferoffset = 0;
5542 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5543 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5544 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5545 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5548 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5551 const msurface_t *surface = texturesurfacelist[0];
5552 const msurface_t *surface2;
5557 // TODO: lock all array ranges before render, rather than on each surface
5558 if (texturenumsurfaces == 1)
5560 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5561 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);
5563 else if (r_batchmode.integer == 2)
5565 #define MAXBATCHTRIANGLES 4096
5566 int batchtriangles = 0;
5567 int batchelements[MAXBATCHTRIANGLES*3];
5568 for (i = 0;i < texturenumsurfaces;i = j)
5570 surface = texturesurfacelist[i];
5572 if (surface->num_triangles > MAXBATCHTRIANGLES)
5574 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);
5577 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5578 batchtriangles = surface->num_triangles;
5579 firstvertex = surface->num_firstvertex;
5580 endvertex = surface->num_firstvertex + surface->num_vertices;
5581 for (;j < texturenumsurfaces;j++)
5583 surface2 = texturesurfacelist[j];
5584 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5586 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5587 batchtriangles += surface2->num_triangles;
5588 firstvertex = min(firstvertex, surface2->num_firstvertex);
5589 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5591 surface2 = texturesurfacelist[j-1];
5592 numvertices = endvertex - firstvertex;
5593 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5596 else if (r_batchmode.integer == 1)
5598 for (i = 0;i < texturenumsurfaces;i = j)
5600 surface = texturesurfacelist[i];
5601 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5602 if (texturesurfacelist[j] != surface2)
5604 surface2 = texturesurfacelist[j-1];
5605 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5606 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5607 GL_LockArrays(surface->num_firstvertex, numvertices);
5608 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5613 for (i = 0;i < texturenumsurfaces;i++)
5615 surface = texturesurfacelist[i];
5616 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5617 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);
5622 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5624 int i, planeindex, vertexindex;
5628 r_waterstate_waterplane_t *p, *bestp;
5629 msurface_t *surface;
5630 if (r_waterstate.renderingscene)
5632 for (i = 0;i < texturenumsurfaces;i++)
5634 surface = texturesurfacelist[i];
5635 if (lightmaptexunit >= 0)
5636 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5637 if (deluxemaptexunit >= 0)
5638 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5639 // pick the closest matching water plane
5642 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5645 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5647 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5648 d += fabs(PlaneDiff(vert, &p->plane));
5650 if (bestd > d || !bestp)
5658 if (refractiontexunit >= 0)
5659 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5660 if (reflectiontexunit >= 0)
5661 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5665 if (refractiontexunit >= 0)
5666 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5667 if (reflectiontexunit >= 0)
5668 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5670 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5671 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);
5675 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5679 const msurface_t *surface = texturesurfacelist[0];
5680 const msurface_t *surface2;
5685 // TODO: lock all array ranges before render, rather than on each surface
5686 if (texturenumsurfaces == 1)
5688 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5689 if (deluxemaptexunit >= 0)
5690 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5691 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5692 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5694 else if (r_batchmode.integer == 2)
5696 #define MAXBATCHTRIANGLES 4096
5697 int batchtriangles = 0;
5698 int batchelements[MAXBATCHTRIANGLES*3];
5699 for (i = 0;i < texturenumsurfaces;i = j)
5701 surface = texturesurfacelist[i];
5702 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5703 if (deluxemaptexunit >= 0)
5704 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5706 if (surface->num_triangles > MAXBATCHTRIANGLES)
5708 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);
5711 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5712 batchtriangles = surface->num_triangles;
5713 firstvertex = surface->num_firstvertex;
5714 endvertex = surface->num_firstvertex + surface->num_vertices;
5715 for (;j < texturenumsurfaces;j++)
5717 surface2 = texturesurfacelist[j];
5718 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5720 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5721 batchtriangles += surface2->num_triangles;
5722 firstvertex = min(firstvertex, surface2->num_firstvertex);
5723 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5725 surface2 = texturesurfacelist[j-1];
5726 numvertices = endvertex - firstvertex;
5727 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5730 else if (r_batchmode.integer == 1)
5733 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5734 for (i = 0;i < texturenumsurfaces;i = j)
5736 surface = texturesurfacelist[i];
5737 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5738 if (texturesurfacelist[j] != surface2)
5740 Con_Printf(" %i", j - i);
5743 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5745 for (i = 0;i < texturenumsurfaces;i = j)
5747 surface = texturesurfacelist[i];
5748 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5749 if (deluxemaptexunit >= 0)
5750 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5751 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5752 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5755 Con_Printf(" %i", j - i);
5757 surface2 = texturesurfacelist[j-1];
5758 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5759 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5760 GL_LockArrays(surface->num_firstvertex, numvertices);
5761 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5769 for (i = 0;i < texturenumsurfaces;i++)
5771 surface = texturesurfacelist[i];
5772 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5773 if (deluxemaptexunit >= 0)
5774 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5775 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5776 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);
5781 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5784 int texturesurfaceindex;
5785 if (r_showsurfaces.integer == 2)
5787 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5789 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5790 for (j = 0;j < surface->num_triangles;j++)
5792 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5793 GL_Color(f, f, f, 1);
5794 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5800 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5802 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5803 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5804 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);
5805 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5806 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5811 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
5813 int texturesurfaceindex;
5816 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5818 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5819 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)
5827 rsurface.lightmapcolor4f = rsurface.array_color4f;
5828 rsurface.lightmapcolor4f_bufferobject = 0;
5829 rsurface.lightmapcolor4f_bufferoffset = 0;
5832 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5834 int texturesurfaceindex;
5838 if (rsurface.lightmapcolor4f)
5840 // generate color arrays for the surfaces in this list
5841 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5843 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5844 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)
5846 f = FogPoint_Model(v);
5856 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5858 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5859 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)
5861 f = FogPoint_Model(v);
5869 rsurface.lightmapcolor4f = rsurface.array_color4f;
5870 rsurface.lightmapcolor4f_bufferobject = 0;
5871 rsurface.lightmapcolor4f_bufferoffset = 0;
5874 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
5876 int texturesurfaceindex;
5880 if (!rsurface.lightmapcolor4f)
5882 // generate color arrays for the surfaces in this list
5883 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5885 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5886 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)
5888 f = FogPoint_Model(v);
5889 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
5890 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
5891 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
5895 rsurface.lightmapcolor4f = rsurface.array_color4f;
5896 rsurface.lightmapcolor4f_bufferobject = 0;
5897 rsurface.lightmapcolor4f_bufferoffset = 0;
5900 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5902 int texturesurfaceindex;
5905 if (!rsurface.lightmapcolor4f)
5907 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5909 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5910 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)
5918 rsurface.lightmapcolor4f = rsurface.array_color4f;
5919 rsurface.lightmapcolor4f_bufferobject = 0;
5920 rsurface.lightmapcolor4f_bufferoffset = 0;
5923 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
5925 int texturesurfaceindex;
5928 if (!rsurface.lightmapcolor4f)
5930 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5932 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5933 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)
5935 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
5936 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
5937 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
5941 rsurface.lightmapcolor4f = rsurface.array_color4f;
5942 rsurface.lightmapcolor4f_bufferobject = 0;
5943 rsurface.lightmapcolor4f_bufferoffset = 0;
5946 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5949 rsurface.lightmapcolor4f = NULL;
5950 rsurface.lightmapcolor4f_bufferobject = 0;
5951 rsurface.lightmapcolor4f_bufferoffset = 0;
5952 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5953 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5954 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5955 GL_Color(r, g, b, a);
5956 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5959 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5961 // TODO: optimize applyfog && applycolor case
5962 // just apply fog if necessary, and tint the fog color array if necessary
5963 rsurface.lightmapcolor4f = NULL;
5964 rsurface.lightmapcolor4f_bufferobject = 0;
5965 rsurface.lightmapcolor4f_bufferoffset = 0;
5966 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5967 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5968 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5969 GL_Color(r, g, b, a);
5970 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5973 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5975 int texturesurfaceindex;
5979 if (texturesurfacelist[0]->lightmapinfo)
5981 // generate color arrays for the surfaces in this list
5982 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5984 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5985 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5987 if (surface->lightmapinfo->samples)
5989 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5990 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5991 VectorScale(lm, scale, c);
5992 if (surface->lightmapinfo->styles[1] != 255)
5994 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5996 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5997 VectorMA(c, scale, lm, c);
5998 if (surface->lightmapinfo->styles[2] != 255)
6001 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6002 VectorMA(c, scale, lm, c);
6003 if (surface->lightmapinfo->styles[3] != 255)
6006 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6007 VectorMA(c, scale, lm, c);
6017 rsurface.lightmapcolor4f = rsurface.array_color4f;
6018 rsurface.lightmapcolor4f_bufferobject = 0;
6019 rsurface.lightmapcolor4f_bufferoffset = 0;
6023 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6024 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6025 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6027 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6028 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6029 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6030 GL_Color(r, g, b, a);
6031 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6034 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6036 int texturesurfaceindex;
6039 float *v, *c, *c2, alpha;
6040 vec3_t ambientcolor;
6041 vec3_t diffusecolor;
6045 VectorCopy(rsurface.modellight_lightdir, lightdir);
6046 f = 0.5f * r_refdef.lightmapintensity;
6047 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6048 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6049 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6050 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6051 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6052 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6054 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6056 // generate color arrays for the surfaces in this list
6057 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6059 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6060 int numverts = surface->num_vertices;
6061 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6062 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6063 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6064 // q3-style directional shading
6065 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6067 if ((f = DotProduct(c2, lightdir)) > 0)
6068 VectorMA(ambientcolor, f, diffusecolor, c);
6070 VectorCopy(ambientcolor, c);
6078 rsurface.lightmapcolor4f = rsurface.array_color4f;
6079 rsurface.lightmapcolor4f_bufferobject = 0;
6080 rsurface.lightmapcolor4f_bufferoffset = 0;
6081 *applycolor = false;
6085 *r = ambientcolor[0];
6086 *g = ambientcolor[1];
6087 *b = ambientcolor[2];
6088 rsurface.lightmapcolor4f = NULL;
6089 rsurface.lightmapcolor4f_bufferobject = 0;
6090 rsurface.lightmapcolor4f_bufferoffset = 0;
6094 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6096 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6097 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6098 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6099 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6100 GL_Color(r, g, b, a);
6101 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6104 void RSurf_SetupDepthAndCulling(void)
6106 // submodels are biased to avoid z-fighting with world surfaces that they
6107 // may be exactly overlapping (avoids z-fighting artifacts on certain
6108 // doors and things in Quake maps)
6109 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6110 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6111 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6112 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6115 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6117 // transparent sky would be ridiculous
6118 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6120 R_SetupGenericShader(false);
6123 skyrendernow = false;
6124 // we have to force off the water clipping plane while rendering sky
6128 // restore entity matrix
6129 R_Mesh_Matrix(&rsurface.matrix);
6131 RSurf_SetupDepthAndCulling();
6133 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6134 // skymasking on them, and Quake3 never did sky masking (unlike
6135 // software Quake and software Quake2), so disable the sky masking
6136 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6137 // and skymasking also looks very bad when noclipping outside the
6138 // level, so don't use it then either.
6139 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6141 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6142 R_Mesh_ColorPointer(NULL, 0, 0);
6143 R_Mesh_ResetTextureState();
6144 if (skyrendermasked)
6146 R_SetupDepthOrShadowShader();
6147 // depth-only (masking)
6148 GL_ColorMask(0,0,0,0);
6149 // just to make sure that braindead drivers don't draw
6150 // anything despite that colormask...
6151 GL_BlendFunc(GL_ZERO, GL_ONE);
6155 R_SetupGenericShader(false);
6157 GL_BlendFunc(GL_ONE, GL_ZERO);
6159 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6160 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6161 if (skyrendermasked)
6162 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6164 R_Mesh_ResetTextureState();
6165 GL_Color(1, 1, 1, 1);
6168 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6170 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6173 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6174 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6175 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6176 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6177 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6178 if (rsurface.texture->backgroundcurrentskinframe)
6180 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6181 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6182 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6183 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6185 if(rsurface.texture->colormapping)
6187 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6188 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6190 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6191 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6192 R_Mesh_ColorPointer(NULL, 0, 0);
6194 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6196 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6198 // render background
6199 GL_BlendFunc(GL_ONE, GL_ZERO);
6201 GL_AlphaTest(false);
6203 GL_Color(1, 1, 1, 1);
6204 R_Mesh_ColorPointer(NULL, 0, 0);
6206 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6207 if (r_glsl_permutation)
6209 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6210 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6211 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6212 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6213 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6214 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6215 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);
6217 GL_LockArrays(0, 0);
6219 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6220 GL_DepthMask(false);
6221 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6222 R_Mesh_ColorPointer(NULL, 0, 0);
6224 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6225 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6226 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6229 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6230 if (!r_glsl_permutation)
6233 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6234 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6235 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6236 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6237 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6238 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6240 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6242 GL_BlendFunc(GL_ONE, GL_ZERO);
6244 GL_AlphaTest(false);
6248 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6249 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6250 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6253 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6255 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6256 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);
6258 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6262 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6263 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);
6265 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6267 GL_LockArrays(0, 0);
6270 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6272 // OpenGL 1.3 path - anything not completely ancient
6273 int texturesurfaceindex;
6274 qboolean applycolor;
6278 const texturelayer_t *layer;
6279 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6281 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6284 int layertexrgbscale;
6285 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6287 if (layerindex == 0)
6291 GL_AlphaTest(false);
6292 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6295 GL_DepthMask(layer->depthmask && writedepth);
6296 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6297 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6299 layertexrgbscale = 4;
6300 VectorScale(layer->color, 0.25f, layercolor);
6302 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6304 layertexrgbscale = 2;
6305 VectorScale(layer->color, 0.5f, layercolor);
6309 layertexrgbscale = 1;
6310 VectorScale(layer->color, 1.0f, layercolor);
6312 layercolor[3] = layer->color[3];
6313 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6314 R_Mesh_ColorPointer(NULL, 0, 0);
6315 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6316 switch (layer->type)
6318 case TEXTURELAYERTYPE_LITTEXTURE:
6319 memset(&m, 0, sizeof(m));
6320 m.tex[0] = R_GetTexture(r_texture_white);
6321 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6322 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6323 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6324 m.tex[1] = R_GetTexture(layer->texture);
6325 m.texmatrix[1] = layer->texmatrix;
6326 m.texrgbscale[1] = layertexrgbscale;
6327 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6328 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6329 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6330 R_Mesh_TextureState(&m);
6331 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6332 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6333 else if (rsurface.uselightmaptexture)
6334 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6336 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6338 case TEXTURELAYERTYPE_TEXTURE:
6339 memset(&m, 0, sizeof(m));
6340 m.tex[0] = R_GetTexture(layer->texture);
6341 m.texmatrix[0] = layer->texmatrix;
6342 m.texrgbscale[0] = layertexrgbscale;
6343 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6344 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6345 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6346 R_Mesh_TextureState(&m);
6347 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6349 case TEXTURELAYERTYPE_FOG:
6350 memset(&m, 0, sizeof(m));
6351 m.texrgbscale[0] = layertexrgbscale;
6354 m.tex[0] = R_GetTexture(layer->texture);
6355 m.texmatrix[0] = layer->texmatrix;
6356 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6357 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6358 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6360 R_Mesh_TextureState(&m);
6361 // generate a color array for the fog pass
6362 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6363 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6367 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6368 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)
6370 f = 1 - FogPoint_Model(v);
6371 c[0] = layercolor[0];
6372 c[1] = layercolor[1];
6373 c[2] = layercolor[2];
6374 c[3] = f * layercolor[3];
6377 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6380 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6382 GL_LockArrays(0, 0);
6385 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6387 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6388 GL_AlphaTest(false);
6392 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6394 // OpenGL 1.1 - crusty old voodoo path
6395 int texturesurfaceindex;
6399 const texturelayer_t *layer;
6400 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6402 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6404 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6406 if (layerindex == 0)
6410 GL_AlphaTest(false);
6411 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6414 GL_DepthMask(layer->depthmask && writedepth);
6415 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6416 R_Mesh_ColorPointer(NULL, 0, 0);
6417 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6418 switch (layer->type)
6420 case TEXTURELAYERTYPE_LITTEXTURE:
6421 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6423 // two-pass lit texture with 2x rgbscale
6424 // first the lightmap pass
6425 memset(&m, 0, sizeof(m));
6426 m.tex[0] = R_GetTexture(r_texture_white);
6427 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6428 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6429 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6430 R_Mesh_TextureState(&m);
6431 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6432 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6433 else if (rsurface.uselightmaptexture)
6434 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6436 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6437 GL_LockArrays(0, 0);
6438 // then apply the texture to it
6439 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6440 memset(&m, 0, sizeof(m));
6441 m.tex[0] = R_GetTexture(layer->texture);
6442 m.texmatrix[0] = layer->texmatrix;
6443 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6444 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6445 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6446 R_Mesh_TextureState(&m);
6447 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);
6451 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6452 memset(&m, 0, sizeof(m));
6453 m.tex[0] = R_GetTexture(layer->texture);
6454 m.texmatrix[0] = layer->texmatrix;
6455 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6456 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6457 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6458 R_Mesh_TextureState(&m);
6459 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6460 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);
6462 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);
6465 case TEXTURELAYERTYPE_TEXTURE:
6466 // singletexture unlit texture with transparency support
6467 memset(&m, 0, sizeof(m));
6468 m.tex[0] = R_GetTexture(layer->texture);
6469 m.texmatrix[0] = layer->texmatrix;
6470 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6471 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6472 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6473 R_Mesh_TextureState(&m);
6474 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);
6476 case TEXTURELAYERTYPE_FOG:
6477 // singletexture fogging
6478 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6481 memset(&m, 0, sizeof(m));
6482 m.tex[0] = R_GetTexture(layer->texture);
6483 m.texmatrix[0] = layer->texmatrix;
6484 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6485 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6486 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6487 R_Mesh_TextureState(&m);
6490 R_Mesh_ResetTextureState();
6491 // generate a color array for the fog pass
6492 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6496 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6497 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)
6499 f = 1 - FogPoint_Model(v);
6500 c[0] = layer->color[0];
6501 c[1] = layer->color[1];
6502 c[2] = layer->color[2];
6503 c[3] = f * layer->color[3];
6506 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6509 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6511 GL_LockArrays(0, 0);
6514 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6516 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6517 GL_AlphaTest(false);
6521 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6525 GL_AlphaTest(false);
6526 R_Mesh_ColorPointer(NULL, 0, 0);
6527 R_Mesh_ResetTextureState();
6528 R_SetupGenericShader(false);
6530 if(rsurface.texture && rsurface.texture->currentskinframe)
6531 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6540 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6542 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
6543 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
6544 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
6547 // brighten it up (as texture value 127 means "unlit")
6548 c[0] *= 2 * r_refdef.view.colorscale;
6549 c[1] *= 2 * r_refdef.view.colorscale;
6550 c[2] *= 2 * r_refdef.view.colorscale;
6552 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6553 c[3] *= r_wateralpha.value;
6555 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6557 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6558 GL_DepthMask(false);
6560 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6562 GL_BlendFunc(GL_ONE, GL_ONE);
6563 GL_DepthMask(false);
6565 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6567 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6568 GL_DepthMask(false);
6570 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6572 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6573 GL_DepthMask(false);
6577 GL_BlendFunc(GL_ONE, GL_ZERO);
6578 GL_DepthMask(writedepth);
6581 rsurface.lightmapcolor4f = NULL;
6583 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6585 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6587 rsurface.lightmapcolor4f = NULL;
6588 rsurface.lightmapcolor4f_bufferobject = 0;
6589 rsurface.lightmapcolor4f_bufferoffset = 0;
6591 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6593 qboolean applycolor = true;
6596 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6598 r_refdef.lightmapintensity = 1;
6599 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6600 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6604 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6606 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6607 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6608 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6611 if(!rsurface.lightmapcolor4f)
6612 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6614 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6615 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6616 if(r_refdef.fogenabled)
6617 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6619 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6620 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6623 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6626 RSurf_SetupDepthAndCulling();
6627 if (r_showsurfaces.integer == 3)
6628 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6629 else if (r_glsl.integer && gl_support_fragment_shader)
6630 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6631 else if (gl_combine.integer && r_textureunits.integer >= 2)
6632 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6634 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6638 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6641 RSurf_SetupDepthAndCulling();
6642 if (r_showsurfaces.integer == 3)
6643 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6644 else if (r_glsl.integer && gl_support_fragment_shader)
6645 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6646 else if (gl_combine.integer && r_textureunits.integer >= 2)
6647 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6649 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6653 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6656 int texturenumsurfaces, endsurface;
6658 msurface_t *surface;
6659 msurface_t *texturesurfacelist[1024];
6661 // if the model is static it doesn't matter what value we give for
6662 // wantnormals and wanttangents, so this logic uses only rules applicable
6663 // to a model, knowing that they are meaningless otherwise
6664 if (ent == r_refdef.scene.worldentity)
6665 RSurf_ActiveWorldEntity();
6666 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6667 RSurf_ActiveModelEntity(ent, false, false);
6669 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6671 for (i = 0;i < numsurfaces;i = j)
6674 surface = rsurface.modelsurfaces + surfacelist[i];
6675 texture = surface->texture;
6676 rsurface.texture = R_GetCurrentTexture(texture);
6677 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6678 // scan ahead until we find a different texture
6679 endsurface = min(i + 1024, numsurfaces);
6680 texturenumsurfaces = 0;
6681 texturesurfacelist[texturenumsurfaces++] = surface;
6682 for (;j < endsurface;j++)
6684 surface = rsurface.modelsurfaces + surfacelist[j];
6685 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6687 texturesurfacelist[texturenumsurfaces++] = surface;
6689 // render the range of surfaces
6690 if (ent == r_refdef.scene.worldentity)
6691 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6693 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6695 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6696 GL_AlphaTest(false);
6699 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6701 const entity_render_t *queueentity = r_refdef.scene.worldentity;
6705 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6707 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6709 RSurf_SetupDepthAndCulling();
6710 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6711 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6713 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6715 RSurf_SetupDepthAndCulling();
6716 GL_AlphaTest(false);
6717 R_Mesh_ColorPointer(NULL, 0, 0);
6718 R_Mesh_ResetTextureState();
6719 R_SetupGenericShader(false);
6720 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6722 GL_BlendFunc(GL_ONE, GL_ZERO);
6723 GL_Color(0, 0, 0, 1);
6724 GL_DepthTest(writedepth);
6725 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6727 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6729 RSurf_SetupDepthAndCulling();
6730 GL_AlphaTest(false);
6731 R_Mesh_ColorPointer(NULL, 0, 0);
6732 R_Mesh_ResetTextureState();
6733 R_SetupGenericShader(false);
6734 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6736 GL_BlendFunc(GL_ONE, GL_ZERO);
6738 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6740 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6741 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6742 else if (!rsurface.texture->currentnumlayers)
6744 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6746 // transparent surfaces get pushed off into the transparent queue
6747 int surfacelistindex;
6748 const msurface_t *surface;
6749 vec3_t tempcenter, center;
6750 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6752 surface = texturesurfacelist[surfacelistindex];
6753 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6754 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6755 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6756 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6757 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6762 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6763 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6768 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6772 // break the surface list down into batches by texture and use of lightmapping
6773 for (i = 0;i < numsurfaces;i = j)
6776 // texture is the base texture pointer, rsurface.texture is the
6777 // current frame/skin the texture is directing us to use (for example
6778 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6779 // use skin 1 instead)
6780 texture = surfacelist[i]->texture;
6781 rsurface.texture = R_GetCurrentTexture(texture);
6782 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6783 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6785 // if this texture is not the kind we want, skip ahead to the next one
6786 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6790 // simply scan ahead until we find a different texture or lightmap state
6791 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6793 // render the range of surfaces
6794 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6798 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6803 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6805 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6807 RSurf_SetupDepthAndCulling();
6808 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6809 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6811 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6813 RSurf_SetupDepthAndCulling();
6814 GL_AlphaTest(false);
6815 R_Mesh_ColorPointer(NULL, 0, 0);
6816 R_Mesh_ResetTextureState();
6817 R_SetupGenericShader(false);
6818 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6820 GL_BlendFunc(GL_ONE, GL_ZERO);
6821 GL_Color(0, 0, 0, 1);
6822 GL_DepthTest(writedepth);
6823 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6825 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6827 RSurf_SetupDepthAndCulling();
6828 GL_AlphaTest(false);
6829 R_Mesh_ColorPointer(NULL, 0, 0);
6830 R_Mesh_ResetTextureState();
6831 R_SetupGenericShader(false);
6832 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6834 GL_BlendFunc(GL_ONE, GL_ZERO);
6836 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6838 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6839 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6840 else if (!rsurface.texture->currentnumlayers)
6842 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6844 // transparent surfaces get pushed off into the transparent queue
6845 int surfacelistindex;
6846 const msurface_t *surface;
6847 vec3_t tempcenter, center;
6848 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6850 surface = texturesurfacelist[surfacelistindex];
6851 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6852 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6853 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6854 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6855 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6860 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6861 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6866 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6870 // break the surface list down into batches by texture and use of lightmapping
6871 for (i = 0;i < numsurfaces;i = j)
6874 // texture is the base texture pointer, rsurface.texture is the
6875 // current frame/skin the texture is directing us to use (for example
6876 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6877 // use skin 1 instead)
6878 texture = surfacelist[i]->texture;
6879 rsurface.texture = R_GetCurrentTexture(texture);
6880 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6881 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6883 // if this texture is not the kind we want, skip ahead to the next one
6884 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6888 // simply scan ahead until we find a different texture or lightmap state
6889 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6891 // render the range of surfaces
6892 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6896 float locboxvertex3f[6*4*3] =
6898 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6899 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6900 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6901 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6902 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6903 1,0,0, 0,0,0, 0,1,0, 1,1,0
6906 unsigned short locboxelements[6*2*3] =
6916 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6919 cl_locnode_t *loc = (cl_locnode_t *)ent;
6921 float vertex3f[6*4*3];
6923 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6924 GL_DepthMask(false);
6925 GL_DepthRange(0, 1);
6926 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6928 GL_CullFace(GL_NONE);
6929 R_Mesh_Matrix(&identitymatrix);
6931 R_Mesh_VertexPointer(vertex3f, 0, 0);
6932 R_Mesh_ColorPointer(NULL, 0, 0);
6933 R_Mesh_ResetTextureState();
6934 R_SetupGenericShader(false);
6937 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6938 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6939 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6940 surfacelist[0] < 0 ? 0.5f : 0.125f);
6942 if (VectorCompare(loc->mins, loc->maxs))
6944 VectorSet(size, 2, 2, 2);
6945 VectorMA(loc->mins, -0.5f, size, mins);
6949 VectorCopy(loc->mins, mins);
6950 VectorSubtract(loc->maxs, loc->mins, size);
6953 for (i = 0;i < 6*4*3;)
6954 for (j = 0;j < 3;j++, i++)
6955 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6957 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
6960 void R_DrawLocs(void)
6963 cl_locnode_t *loc, *nearestloc;
6965 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6966 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6968 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6969 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6973 void R_DrawDebugModel(entity_render_t *ent)
6975 int i, j, k, l, flagsmask;
6976 const int *elements;
6978 msurface_t *surface;
6979 dp_model_t *model = ent->model;
6982 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
6984 R_Mesh_ColorPointer(NULL, 0, 0);
6985 R_Mesh_ResetTextureState();
6986 R_SetupGenericShader(false);
6987 GL_DepthRange(0, 1);
6988 GL_DepthTest(!r_showdisabledepthtest.integer);
6989 GL_DepthMask(false);
6990 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6992 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6994 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6995 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6997 if (brush->colbrushf && brush->colbrushf->numtriangles)
6999 R_Mesh_VertexPointer(brush->colbrushf->points->v, 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, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7004 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7006 if (surface->num_collisiontriangles)
7008 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7009 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);
7010 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7015 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7017 if (r_showtris.integer || r_shownormals.integer)
7019 if (r_showdisabledepthtest.integer)
7021 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7022 GL_DepthMask(false);
7026 GL_BlendFunc(GL_ONE, GL_ZERO);
7029 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7031 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7033 rsurface.texture = R_GetCurrentTexture(surface->texture);
7034 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7036 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7037 if (r_showtris.value > 0)
7039 if (!rsurface.texture->currentlayers->depthmask)
7040 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7041 else if (ent == r_refdef.scene.worldentity)
7042 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7044 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7045 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7046 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7047 R_Mesh_ColorPointer(NULL, 0, 0);
7048 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7049 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7050 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7051 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);
7052 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7055 if (r_shownormals.value < 0)
7058 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7060 VectorCopy(rsurface.vertex3f + l * 3, v);
7061 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7062 qglVertex3f(v[0], v[1], v[2]);
7063 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7064 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7065 qglVertex3f(v[0], v[1], v[2]);
7070 if (r_shownormals.value > 0)
7073 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7075 VectorCopy(rsurface.vertex3f + l * 3, v);
7076 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7077 qglVertex3f(v[0], v[1], v[2]);
7078 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7079 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7080 qglVertex3f(v[0], v[1], v[2]);
7085 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7087 VectorCopy(rsurface.vertex3f + l * 3, v);
7088 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7089 qglVertex3f(v[0], v[1], v[2]);
7090 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7091 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7092 qglVertex3f(v[0], v[1], v[2]);
7097 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7099 VectorCopy(rsurface.vertex3f + l * 3, v);
7100 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7101 qglVertex3f(v[0], v[1], v[2]);
7102 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7103 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7104 qglVertex3f(v[0], v[1], v[2]);
7111 rsurface.texture = NULL;
7115 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7116 int r_maxsurfacelist = 0;
7117 msurface_t **r_surfacelist = NULL;
7118 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7120 int i, j, endj, f, flagsmask;
7122 dp_model_t *model = r_refdef.scene.worldmodel;
7123 msurface_t *surfaces;
7124 unsigned char *update;
7125 int numsurfacelist = 0;
7129 if (r_maxsurfacelist < model->num_surfaces)
7131 r_maxsurfacelist = model->num_surfaces;
7133 Mem_Free(r_surfacelist);
7134 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7137 RSurf_ActiveWorldEntity();
7139 surfaces = model->data_surfaces;
7140 update = model->brushq1.lightmapupdateflags;
7142 // update light styles on this submodel
7143 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7145 model_brush_lightstyleinfo_t *style;
7146 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7148 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7150 int *list = style->surfacelist;
7151 style->value = r_refdef.scene.lightstylevalue[style->style];
7152 for (j = 0;j < style->numsurfaces;j++)
7153 update[list[j]] = true;
7158 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7162 R_DrawDebugModel(r_refdef.scene.worldentity);
7168 rsurface.uselightmaptexture = false;
7169 rsurface.texture = NULL;
7170 rsurface.rtlight = NULL;
7172 // add visible surfaces to draw list
7173 for (i = 0;i < model->nummodelsurfaces;i++)
7175 j = model->sortedmodelsurfaces[i];
7176 if (r_refdef.viewcache.world_surfacevisible[j])
7177 r_surfacelist[numsurfacelist++] = surfaces + j;
7179 // update lightmaps if needed
7181 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7182 if (r_refdef.viewcache.world_surfacevisible[j])
7184 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7185 // don't do anything if there were no surfaces
7186 if (!numsurfacelist)
7188 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7189 GL_AlphaTest(false);
7191 // add to stats if desired
7192 if (r_speeds.integer && !skysurfaces && !depthonly)
7194 r_refdef.stats.world_surfaces += numsurfacelist;
7195 for (j = 0;j < numsurfacelist;j++)
7196 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7200 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7202 int i, j, endj, f, flagsmask;
7204 dp_model_t *model = ent->model;
7205 msurface_t *surfaces;
7206 unsigned char *update;
7207 int numsurfacelist = 0;
7211 if (r_maxsurfacelist < model->num_surfaces)
7213 r_maxsurfacelist = model->num_surfaces;
7215 Mem_Free(r_surfacelist);
7216 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7219 // if the model is static it doesn't matter what value we give for
7220 // wantnormals and wanttangents, so this logic uses only rules applicable
7221 // to a model, knowing that they are meaningless otherwise
7222 if (ent == r_refdef.scene.worldentity)
7223 RSurf_ActiveWorldEntity();
7224 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
7225 RSurf_ActiveModelEntity(ent, false, false);
7227 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7229 surfaces = model->data_surfaces;
7230 update = model->brushq1.lightmapupdateflags;
7232 // update light styles
7233 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7235 model_brush_lightstyleinfo_t *style;
7236 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7238 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7240 int *list = style->surfacelist;
7241 style->value = r_refdef.scene.lightstylevalue[style->style];
7242 for (j = 0;j < style->numsurfaces;j++)
7243 update[list[j]] = true;
7248 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7252 R_DrawDebugModel(ent);
7258 rsurface.uselightmaptexture = false;
7259 rsurface.texture = NULL;
7260 rsurface.rtlight = NULL;
7262 // add visible surfaces to draw list
7263 for (i = 0;i < model->nummodelsurfaces;i++)
7264 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7265 // don't do anything if there were no surfaces
7266 if (!numsurfacelist)
7268 // update lightmaps if needed
7270 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7272 R_BuildLightMap(ent, surfaces + j);
7273 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7274 GL_AlphaTest(false);
7276 // add to stats if desired
7277 if (r_speeds.integer && !skysurfaces && !depthonly)
7279 r_refdef.stats.entities++;
7280 r_refdef.stats.entities_surfaces += numsurfacelist;
7281 for (j = 0;j < numsurfacelist;j++)
7282 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;