2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; // used only by R_GetCurrentTexture
38 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
39 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
40 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
41 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
42 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
43 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
44 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
45 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
46 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
47 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
48 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
49 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
50 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
51 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
52 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
53 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
54 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
55 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
56 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
57 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
58 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
59 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
60 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
61 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
62 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
63 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows DOWN, otherwise use the model lighting"};
64 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
65 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
66 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
67 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
68 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
69 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
71 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
72 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
73 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
74 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
75 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
76 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
77 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
78 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
80 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
82 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
83 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
84 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
85 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
86 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
87 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
88 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
89 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
90 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
91 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
92 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
93 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
95 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
96 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
97 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
98 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
99 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
101 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
102 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
103 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
104 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
106 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
107 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
108 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
109 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
110 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
111 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
112 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
114 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
115 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
116 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
117 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
119 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
121 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
123 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
125 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
126 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
127 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
128 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
129 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
130 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
132 extern cvar_t v_glslgamma;
134 extern qboolean v_flipped_state;
136 static struct r_bloomstate_s
141 int bloomwidth, bloomheight;
143 int screentexturewidth, screentextureheight;
144 rtexture_t *texture_screen;
146 int bloomtexturewidth, bloomtextureheight;
147 rtexture_t *texture_bloom;
149 // arrays for rendering the screen passes
150 float screentexcoord2f[8];
151 float bloomtexcoord2f[8];
152 float offsettexcoord2f[8];
156 r_waterstate_t r_waterstate;
158 // shadow volume bsp struct with automatically growing nodes buffer
161 rtexture_t *r_texture_blanknormalmap;
162 rtexture_t *r_texture_white;
163 rtexture_t *r_texture_grey128;
164 rtexture_t *r_texture_black;
165 rtexture_t *r_texture_notexture;
166 rtexture_t *r_texture_whitecube;
167 rtexture_t *r_texture_normalizationcube;
168 rtexture_t *r_texture_fogattenuation;
169 rtexture_t *r_texture_gammaramps;
170 unsigned int r_texture_gammaramps_serial;
171 //rtexture_t *r_texture_fogintensity;
173 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
174 unsigned int r_numqueries;
175 unsigned int r_maxqueries;
177 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
178 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
180 // vertex coordinates for a quad that covers the screen exactly
181 const static float r_screenvertex3f[12] =
189 extern void R_DrawModelShadows(void);
191 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
194 for (i = 0;i < verts;i++)
205 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
208 for (i = 0;i < verts;i++)
218 // FIXME: move this to client?
221 if (gamemode == GAME_NEHAHRA)
223 Cvar_Set("gl_fogenable", "0");
224 Cvar_Set("gl_fogdensity", "0.2");
225 Cvar_Set("gl_fogred", "0.3");
226 Cvar_Set("gl_foggreen", "0.3");
227 Cvar_Set("gl_fogblue", "0.3");
229 r_refdef.fog_density = 0;
230 r_refdef.fog_red = 0;
231 r_refdef.fog_green = 0;
232 r_refdef.fog_blue = 0;
233 r_refdef.fog_alpha = 1;
234 r_refdef.fog_start = 0;
235 r_refdef.fog_end = 0;
238 float FogForDistance(vec_t dist)
240 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
241 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
244 float FogPoint_World(const vec3_t p)
246 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
249 float FogPoint_Model(const vec3_t p)
251 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
254 static void R_BuildBlankTextures(void)
256 unsigned char data[4];
257 data[2] = 128; // normal X
258 data[1] = 128; // normal Y
259 data[0] = 255; // normal Z
260 data[3] = 128; // height
261 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
266 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
271 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
276 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
279 static void R_BuildNoTexture(void)
282 unsigned char pix[16][16][4];
283 // this makes a light grey/dark grey checkerboard texture
284 for (y = 0;y < 16;y++)
286 for (x = 0;x < 16;x++)
288 if ((y < 8) ^ (x < 8))
304 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
307 static void R_BuildWhiteCube(void)
309 unsigned char data[6*1*1*4];
310 memset(data, 255, sizeof(data));
311 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
314 static void R_BuildNormalizationCube(void)
318 vec_t s, t, intensity;
320 unsigned char data[6][NORMSIZE][NORMSIZE][4];
321 for (side = 0;side < 6;side++)
323 for (y = 0;y < NORMSIZE;y++)
325 for (x = 0;x < NORMSIZE;x++)
327 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
328 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
363 intensity = 127.0f / sqrt(DotProduct(v, v));
364 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
365 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
366 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
367 data[side][y][x][3] = 255;
371 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
374 static void R_BuildFogTexture(void)
378 unsigned char data1[FOGWIDTH][4];
379 //unsigned char data2[FOGWIDTH][4];
382 r_refdef.fogmasktable_start = r_refdef.fog_start;
383 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
384 r_refdef.fogmasktable_range = r_refdef.fogrange;
385 r_refdef.fogmasktable_density = r_refdef.fog_density;
387 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
388 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
390 d = (x * r - r_refdef.fogmasktable_start);
391 if(developer.integer >= 100)
392 Con_Printf("%f ", d);
394 if (r_fog_exp2.integer)
395 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
397 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
398 if(developer.integer >= 100)
399 Con_Printf(" : %f ", alpha);
400 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
401 if(developer.integer >= 100)
402 Con_Printf(" = %f\n", alpha);
403 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
406 for (x = 0;x < FOGWIDTH;x++)
408 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
413 //data2[x][0] = 255 - b;
414 //data2[x][1] = 255 - b;
415 //data2[x][2] = 255 - b;
418 if (r_texture_fogattenuation)
420 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
421 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
425 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
426 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
430 static const char *builtinshaderstring =
431 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
432 "// written by Forest 'LordHavoc' Hale\n"
434 "// common definitions between vertex shader and fragment shader:\n"
436 "//#ifdef __GLSL_CG_DATA_TYPES\n"
437 "//# define myhalf half\n"
438 "//# define myhalf2 half2\n"
439 "//# define myhalf3 half3\n"
440 "//# define myhalf4 half4\n"
442 "# define myhalf float\n"
443 "# define myhalf2 vec2\n"
444 "# define myhalf3 vec3\n"
445 "# define myhalf4 vec4\n"
448 "#ifdef MODE_DEPTH_OR_SHADOW\n"
450 "# ifdef VERTEX_SHADER\n"
453 " gl_Position = ftransform();\n"
459 "#ifdef MODE_POSTPROCESS\n"
460 "# ifdef VERTEX_SHADER\n"
463 " gl_FrontColor = gl_Color;\n"
464 " gl_Position = ftransform();\n"
465 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
467 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
471 "# ifdef FRAGMENT_SHADER\n"
473 "uniform sampler2D Texture_First;\n"
475 "uniform sampler2D Texture_Second;\n"
477 "#ifdef USEGAMMARAMPS\n"
478 "uniform sampler2D Texture_GammaRamps;\n"
480 "#ifdef USEVERTEXTEXTUREBLEND\n"
481 "uniform vec4 TintColor;\n"
483 "#ifdef USECOLORMOD\n"
484 "uniform vec3 Gamma;\n"
486 "//uncomment these if you want to use them:\n"
487 "uniform vec4 UserVec1;\n"
488 "// uniform vec4 UserVec2;\n"
489 "// uniform vec4 UserVec3;\n"
490 "// uniform vec4 UserVec4;\n"
491 "// uniform float ClientTime;\n"
492 "uniform vec2 PixelSize;\n"
495 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
497 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
499 "#ifdef USEVERTEXTEXTUREBLEND\n"
500 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
503 "#ifdef USEPOSTPROCESSING\n"
504 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
505 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
506 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
507 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
508 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
509 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
510 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
511 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
514 "#ifdef USEGAMMARAMPS\n"
515 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
516 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
517 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
524 "#ifdef MODE_GENERIC\n"
525 "# ifdef VERTEX_SHADER\n"
528 " gl_FrontColor = gl_Color;\n"
529 "# ifdef USEDIFFUSE\n"
530 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
532 "# ifdef USESPECULAR\n"
533 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
535 " gl_Position = ftransform();\n"
538 "# ifdef FRAGMENT_SHADER\n"
540 "# ifdef USEDIFFUSE\n"
541 "uniform sampler2D Texture_First;\n"
543 "# ifdef USESPECULAR\n"
544 "uniform sampler2D Texture_Second;\n"
549 " gl_FragColor = gl_Color;\n"
550 "# ifdef USEDIFFUSE\n"
551 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
554 "# ifdef USESPECULAR\n"
555 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
557 "# ifdef USECOLORMAPPING\n"
558 " gl_FragColor *= tex2;\n"
561 " gl_FragColor += tex2;\n"
563 "# ifdef USEVERTEXTEXTUREBLEND\n"
564 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
569 "#else // !MODE_GENERIC\n"
571 "varying vec2 TexCoord;\n"
572 "varying vec2 TexCoordLightmap;\n"
574 "#ifdef MODE_LIGHTSOURCE\n"
575 "varying vec3 CubeVector;\n"
578 "#ifdef MODE_LIGHTSOURCE\n"
579 "varying vec3 LightVector;\n"
581 "#ifdef MODE_LIGHTDIRECTION\n"
582 "varying vec3 LightVector;\n"
585 "varying vec3 EyeVector;\n"
587 "varying vec3 EyeVectorModelSpace;\n"
590 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
591 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
592 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
594 "#ifdef MODE_WATER\n"
595 "varying vec4 ModelViewProjectionPosition;\n"
597 "#ifdef MODE_REFRACTION\n"
598 "varying vec4 ModelViewProjectionPosition;\n"
600 "#ifdef USEREFLECTION\n"
601 "varying vec4 ModelViewProjectionPosition;\n"
608 "// vertex shader specific:\n"
609 "#ifdef VERTEX_SHADER\n"
611 "uniform vec3 LightPosition;\n"
612 "uniform vec3 EyePosition;\n"
613 "uniform vec3 LightDir;\n"
615 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
619 " gl_FrontColor = gl_Color;\n"
620 " // copy the surface texcoord\n"
621 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
622 "#ifndef MODE_LIGHTSOURCE\n"
623 "# ifndef MODE_LIGHTDIRECTION\n"
624 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
628 "#ifdef MODE_LIGHTSOURCE\n"
629 " // transform vertex position into light attenuation/cubemap space\n"
630 " // (-1 to +1 across the light box)\n"
631 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
633 " // transform unnormalized light direction into tangent space\n"
634 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
635 " // normalize it per pixel)\n"
636 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
637 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
638 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
639 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
642 "#ifdef MODE_LIGHTDIRECTION\n"
643 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
644 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
645 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
648 " // transform unnormalized eye direction into tangent space\n"
650 " vec3 EyeVectorModelSpace;\n"
652 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
653 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
654 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
655 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
657 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
658 " VectorS = gl_MultiTexCoord1.xyz;\n"
659 " VectorT = gl_MultiTexCoord2.xyz;\n"
660 " VectorR = gl_MultiTexCoord3.xyz;\n"
663 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
664 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
665 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
666 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
669 "// transform vertex to camera space, using ftransform to match non-VS\n"
671 " gl_Position = ftransform();\n"
673 "#ifdef MODE_WATER\n"
674 " ModelViewProjectionPosition = gl_Position;\n"
676 "#ifdef MODE_REFRACTION\n"
677 " ModelViewProjectionPosition = gl_Position;\n"
679 "#ifdef USEREFLECTION\n"
680 " ModelViewProjectionPosition = gl_Position;\n"
684 "#endif // VERTEX_SHADER\n"
689 "// fragment shader specific:\n"
690 "#ifdef FRAGMENT_SHADER\n"
692 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
693 "uniform sampler2D Texture_Normal;\n"
694 "uniform sampler2D Texture_Color;\n"
695 "uniform sampler2D Texture_Gloss;\n"
696 "uniform sampler2D Texture_Glow;\n"
697 "uniform sampler2D Texture_SecondaryNormal;\n"
698 "uniform sampler2D Texture_SecondaryColor;\n"
699 "uniform sampler2D Texture_SecondaryGloss;\n"
700 "uniform sampler2D Texture_SecondaryGlow;\n"
701 "uniform sampler2D Texture_Pants;\n"
702 "uniform sampler2D Texture_Shirt;\n"
703 "uniform sampler2D Texture_FogMask;\n"
704 "uniform sampler2D Texture_Lightmap;\n"
705 "uniform sampler2D Texture_Deluxemap;\n"
706 "uniform sampler2D Texture_Refraction;\n"
707 "uniform sampler2D Texture_Reflection;\n"
708 "uniform sampler2D Texture_Attenuation;\n"
709 "uniform samplerCube Texture_Cube;\n"
711 "uniform myhalf3 LightColor;\n"
712 "uniform myhalf3 AmbientColor;\n"
713 "uniform myhalf3 DiffuseColor;\n"
714 "uniform myhalf3 SpecularColor;\n"
715 "uniform myhalf3 Color_Pants;\n"
716 "uniform myhalf3 Color_Shirt;\n"
717 "uniform myhalf3 FogColor;\n"
719 "uniform myhalf4 TintColor;\n"
722 "//#ifdef MODE_WATER\n"
723 "uniform vec4 DistortScaleRefractReflect;\n"
724 "uniform vec4 ScreenScaleRefractReflect;\n"
725 "uniform vec4 ScreenCenterRefractReflect;\n"
726 "uniform myhalf4 RefractColor;\n"
727 "uniform myhalf4 ReflectColor;\n"
728 "uniform myhalf ReflectFactor;\n"
729 "uniform myhalf ReflectOffset;\n"
731 "//# ifdef MODE_REFRACTION\n"
732 "//uniform vec4 DistortScaleRefractReflect;\n"
733 "//uniform vec4 ScreenScaleRefractReflect;\n"
734 "//uniform vec4 ScreenCenterRefractReflect;\n"
735 "//uniform myhalf4 RefractColor;\n"
736 "//# ifdef USEREFLECTION\n"
737 "//uniform myhalf4 ReflectColor;\n"
740 "//# ifdef USEREFLECTION\n"
741 "//uniform vec4 DistortScaleRefractReflect;\n"
742 "//uniform vec4 ScreenScaleRefractReflect;\n"
743 "//uniform vec4 ScreenCenterRefractReflect;\n"
744 "//uniform myhalf4 ReflectColor;\n"
749 "uniform myhalf GlowScale;\n"
750 "uniform myhalf SceneBrightness;\n"
751 "#ifdef USECONTRASTBOOST\n"
752 "uniform myhalf ContrastBoostCoeff;\n"
755 "uniform float OffsetMapping_Scale;\n"
756 "uniform float OffsetMapping_Bias;\n"
757 "uniform float FogRangeRecip;\n"
759 "uniform myhalf AmbientScale;\n"
760 "uniform myhalf DiffuseScale;\n"
761 "uniform myhalf SpecularScale;\n"
762 "uniform myhalf SpecularPower;\n"
764 "#ifdef USEOFFSETMAPPING\n"
765 "vec2 OffsetMapping(vec2 TexCoord)\n"
767 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
768 " // 14 sample relief mapping: linear search and then binary search\n"
769 " // this basically steps forward a small amount repeatedly until it finds\n"
770 " // itself inside solid, then jitters forward and back using decreasing\n"
771 " // amounts to find the impact\n"
772 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
773 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
774 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
775 " vec3 RT = vec3(TexCoord, 1);\n"
776 " OffsetVector *= 0.1;\n"
777 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
778 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
779 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
780 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
781 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
782 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
783 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
784 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
785 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
786 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
787 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
788 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
789 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
790 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
793 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
794 " // this basically moves forward the full distance, and then backs up based\n"
795 " // on height of samples\n"
796 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
797 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
798 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
799 " TexCoord += OffsetVector;\n"
800 " OffsetVector *= 0.333;\n"
801 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
802 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
803 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
804 " return TexCoord;\n"
807 "#endif // USEOFFSETMAPPING\n"
809 "#ifdef MODE_WATER\n"
814 "#ifdef USEOFFSETMAPPING\n"
815 " // apply offsetmapping\n"
816 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
817 "#define TexCoord TexCoordOffset\n"
820 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
821 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
822 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
823 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
824 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
827 "#else // !MODE_WATER\n"
828 "#ifdef MODE_REFRACTION\n"
830 "// refraction pass\n"
833 "#ifdef USEOFFSETMAPPING\n"
834 " // apply offsetmapping\n"
835 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
836 "#define TexCoord TexCoordOffset\n"
839 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
840 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
841 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
842 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
845 "#else // !MODE_REFRACTION\n"
848 "#ifdef USEOFFSETMAPPING\n"
849 " // apply offsetmapping\n"
850 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
851 "#define TexCoord TexCoordOffset\n"
854 " // combine the diffuse textures (base, pants, shirt)\n"
855 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
856 "#ifdef USECOLORMAPPING\n"
857 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
859 "#ifdef USEVERTEXTEXTUREBLEND\n"
860 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
861 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
862 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
863 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord)), color.rgb, terrainblend);\n"
865 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
868 "#ifdef USEDIFFUSE\n"
869 " // get the surface normal and the gloss color\n"
870 "# ifdef USEVERTEXTEXTUREBLEND\n"
871 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
872 "# ifdef USESPECULAR\n"
873 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
876 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
877 "# ifdef USESPECULAR\n"
878 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
885 "#ifdef MODE_LIGHTSOURCE\n"
888 " // calculate surface normal, light normal, and specular normal\n"
889 " // compute color intensity for the two textures (colormap and glossmap)\n"
890 " // scale by light color and attenuation as efficiently as possible\n"
891 " // (do as much scalar math as possible rather than vector math)\n"
892 "# ifdef USEDIFFUSE\n"
893 " // get the light normal\n"
894 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
896 "# ifdef USESPECULAR\n"
897 "# ifndef USEEXACTSPECULARMATH\n"
898 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
901 " // calculate directional shading\n"
902 "# ifdef USEEXACTSPECULARMATH\n"
903 " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n"
905 " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * glosscolor);\n"
908 "# ifdef USEDIFFUSE\n"
909 " // calculate directional shading\n"
910 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
912 " // calculate directionless shading\n"
913 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
917 "# ifdef USECUBEFILTER\n"
918 " // apply light cubemap filter\n"
919 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
920 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
922 "#endif // MODE_LIGHTSOURCE\n"
927 "#ifdef MODE_LIGHTDIRECTION\n"
928 " // directional model lighting\n"
929 "# ifdef USEDIFFUSE\n"
930 " // get the light normal\n"
931 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
933 "# ifdef USESPECULAR\n"
934 " // calculate directional shading\n"
935 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
936 "# ifdef USEEXACTSPECULARMATH\n"
937 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
939 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
940 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
943 "# ifdef USEDIFFUSE\n"
945 " // calculate directional shading\n"
946 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
948 " color.rgb *= AmbientColor;\n"
951 "#endif // MODE_LIGHTDIRECTION\n"
956 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
957 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
959 " // get the light normal\n"
960 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
961 " myhalf3 diffusenormal;\n"
962 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
963 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
964 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
965 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
966 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
967 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
968 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
969 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
970 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
971 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
972 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
973 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
974 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
975 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
976 "# ifdef USESPECULAR\n"
977 "# ifdef USEEXACTSPECULARMATH\n"
978 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
980 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
981 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
985 " // apply lightmap color\n"
986 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
987 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
992 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
993 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
995 " // get the light normal\n"
996 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
997 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
998 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
999 "# ifdef USESPECULAR\n"
1000 "# ifdef USEEXACTSPECULARMATH\n"
1001 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1003 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1004 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1008 " // apply lightmap color\n"
1009 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1010 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1015 "#ifdef MODE_LIGHTMAP\n"
1016 " // apply lightmap color\n"
1017 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1018 "#endif // MODE_LIGHTMAP\n"
1023 "#ifdef MODE_VERTEXCOLOR\n"
1024 " // apply lightmap color\n"
1025 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1026 "#endif // MODE_VERTEXCOLOR\n"
1031 "#ifdef MODE_FLATCOLOR\n"
1032 "#endif // MODE_FLATCOLOR\n"
1040 " color *= TintColor;\n"
1043 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1046 "#ifdef USECONTRASTBOOST\n"
1047 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1050 " color.rgb *= SceneBrightness;\n"
1052 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1054 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1057 " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1058 "#ifdef USEREFLECTION\n"
1059 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1060 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1061 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1062 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1065 " gl_FragColor = vec4(color);\n"
1067 "#endif // !MODE_REFRACTION\n"
1068 "#endif // !MODE_WATER\n"
1070 "#endif // FRAGMENT_SHADER\n"
1072 "#endif // !MODE_GENERIC\n"
1073 "#endif // !MODE_POSTPROCESS\n"
1074 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1077 typedef struct shaderpermutationinfo_s
1079 const char *pretext;
1082 shaderpermutationinfo_t;
1084 typedef struct shadermodeinfo_s
1086 const char *vertexfilename;
1087 const char *geometryfilename;
1088 const char *fragmentfilename;
1089 const char *pretext;
1094 typedef enum shaderpermutation_e
1096 SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
1097 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1098 SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
1099 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1100 SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
1101 SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
1102 SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
1103 SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
1104 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, // (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1105 SHADERPERMUTATION_REFLECTION = 1<<9, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1106 SHADERPERMUTATION_OFFSETMAPPING = 1<<10, // adjust texcoords to roughly simulate a displacement mapped surface
1107 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1108 SHADERPERMUTATION_GAMMARAMPS = 1<<12, // gamma (postprocessing only)
1109 SHADERPERMUTATION_POSTPROCESSING = 1<<13, // user defined postprocessing
1110 SHADERPERMUTATION_LIMIT = 1<<14, // size of permutations array
1111 SHADERPERMUTATION_COUNT = 14 // size of shaderpermutationinfo array
1113 shaderpermutation_t;
1115 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1116 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1118 {"#define USEDIFFUSE\n", " diffuse"},
1119 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1120 {"#define USECOLORMAPPING\n", " colormapping"},
1121 {"#define USECONTRASTBOOST\n", " contrastboost"},
1122 {"#define USEFOG\n", " fog"},
1123 {"#define USECUBEFILTER\n", " cubefilter"},
1124 {"#define USEGLOW\n", " glow"},
1125 {"#define USESPECULAR\n", " specular"},
1126 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1127 {"#define USEREFLECTION\n", " reflection"},
1128 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1129 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1130 {"#define USEGAMMARAMPS\n", " gammaramps"},
1131 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1134 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
1135 typedef enum shadermode_e
1137 SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
1138 SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
1139 SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
1140 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1141 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
1142 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1143 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1144 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1145 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1146 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
1147 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
1148 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1153 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1154 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1156 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1157 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1158 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1159 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1160 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1161 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1162 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1163 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1164 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1165 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1166 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1167 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1170 typedef struct r_glsl_permutation_s
1172 // indicates if we have tried compiling this permutation already
1174 // 0 if compilation failed
1176 // locations of detected uniforms in program object, or -1 if not found
1177 int loc_Texture_First;
1178 int loc_Texture_Second;
1179 int loc_Texture_GammaRamps;
1180 int loc_Texture_Normal;
1181 int loc_Texture_Color;
1182 int loc_Texture_Gloss;
1183 int loc_Texture_Glow;
1184 int loc_Texture_SecondaryNormal;
1185 int loc_Texture_SecondaryColor;
1186 int loc_Texture_SecondaryGloss;
1187 int loc_Texture_SecondaryGlow;
1188 int loc_Texture_Pants;
1189 int loc_Texture_Shirt;
1190 int loc_Texture_FogMask;
1191 int loc_Texture_Lightmap;
1192 int loc_Texture_Deluxemap;
1193 int loc_Texture_Attenuation;
1194 int loc_Texture_Cube;
1195 int loc_Texture_Refraction;
1196 int loc_Texture_Reflection;
1198 int loc_LightPosition;
1199 int loc_EyePosition;
1200 int loc_Color_Pants;
1201 int loc_Color_Shirt;
1202 int loc_FogRangeRecip;
1203 int loc_AmbientScale;
1204 int loc_DiffuseScale;
1205 int loc_SpecularScale;
1206 int loc_SpecularPower;
1208 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1209 int loc_OffsetMapping_Scale;
1211 int loc_AmbientColor;
1212 int loc_DiffuseColor;
1213 int loc_SpecularColor;
1215 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1216 int loc_GammaCoeff; // 1 / gamma
1217 int loc_DistortScaleRefractReflect;
1218 int loc_ScreenScaleRefractReflect;
1219 int loc_ScreenCenterRefractReflect;
1220 int loc_RefractColor;
1221 int loc_ReflectColor;
1222 int loc_ReflectFactor;
1223 int loc_ReflectOffset;
1231 r_glsl_permutation_t;
1233 // information about each possible shader permutation
1234 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1235 // currently selected permutation
1236 r_glsl_permutation_t *r_glsl_permutation;
1238 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1241 if (!filename || !filename[0])
1243 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1246 if (printfromdisknotice)
1247 Con_DPrint("from disk... ");
1248 return shaderstring;
1250 else if (!strcmp(filename, "glsl/default.glsl"))
1252 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1253 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1255 return shaderstring;
1258 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1261 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1262 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1263 int vertstrings_count = 0;
1264 int geomstrings_count = 0;
1265 int fragstrings_count = 0;
1266 char *vertexstring, *geometrystring, *fragmentstring;
1267 const char *vertstrings_list[32+3];
1268 const char *geomstrings_list[32+3];
1269 const char *fragstrings_list[32+3];
1270 char permutationname[256];
1277 permutationname[0] = 0;
1278 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1279 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1280 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1282 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1284 // the first pretext is which type of shader to compile as
1285 // (later these will all be bound together as a program object)
1286 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1287 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1288 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1290 // the second pretext is the mode (for example a light source)
1291 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1292 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1293 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1294 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1296 // now add all the permutation pretexts
1297 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1299 if (permutation & (1<<i))
1301 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1302 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1303 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1304 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1308 // keep line numbers correct
1309 vertstrings_list[vertstrings_count++] = "\n";
1310 geomstrings_list[geomstrings_count++] = "\n";
1311 fragstrings_list[fragstrings_count++] = "\n";
1315 // now append the shader text itself
1316 vertstrings_list[vertstrings_count++] = vertexstring;
1317 geomstrings_list[geomstrings_count++] = geometrystring;
1318 fragstrings_list[fragstrings_count++] = fragmentstring;
1320 // if any sources were NULL, clear the respective list
1322 vertstrings_count = 0;
1323 if (!geometrystring)
1324 geomstrings_count = 0;
1325 if (!fragmentstring)
1326 fragstrings_count = 0;
1328 // compile the shader program
1329 if (vertstrings_count + geomstrings_count + fragstrings_count)
1330 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1334 qglUseProgramObjectARB(p->program);CHECKGLERROR
1335 // look up all the uniform variable names we care about, so we don't
1336 // have to look them up every time we set them
1337 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1338 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1339 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1340 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1341 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1342 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1343 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1344 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1345 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1346 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1347 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1348 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1349 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1350 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1351 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1352 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1353 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1354 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1355 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1356 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1357 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1358 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1359 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1360 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1361 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1362 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1363 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1364 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1365 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1366 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1367 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1368 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1369 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1370 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1371 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1372 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1373 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1374 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1375 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1376 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1377 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1378 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1379 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1380 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1381 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1382 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1383 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1384 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1385 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1386 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1387 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1388 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1389 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1390 // initialize the samplers to refer to the texture units we use
1391 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1392 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1393 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1394 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1395 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1396 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1397 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1398 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1399 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1400 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1401 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1402 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1403 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1404 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1405 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1406 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1407 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1408 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1409 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1410 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1412 if (developer.integer)
1413 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1416 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1420 Mem_Free(vertexstring);
1422 Mem_Free(geometrystring);
1424 Mem_Free(fragmentstring);
1427 void R_GLSL_Restart_f(void)
1430 unsigned int permutation;
1431 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1432 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1433 if (r_glsl_permutations[mode][permutation].program)
1434 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1435 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1438 void R_GLSL_DumpShader_f(void)
1442 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1445 Con_Printf("failed to write to glsl/default.glsl\n");
1449 FS_Print(file, "// The engine may define the following macros:\n");
1450 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1451 for (i = 0;i < SHADERMODE_COUNT;i++)
1452 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1453 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1454 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1455 FS_Print(file, "\n");
1456 FS_Print(file, builtinshaderstring);
1459 Con_Printf("glsl/default.glsl written\n");
1462 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1464 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1465 if (r_glsl_permutation != perm)
1467 r_glsl_permutation = perm;
1468 if (!r_glsl_permutation->program)
1470 if (!r_glsl_permutation->compiled)
1471 R_GLSL_CompilePermutation(mode, permutation);
1472 if (!r_glsl_permutation->program)
1474 // remove features until we find a valid permutation
1476 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1478 // reduce i more quickly whenever it would not remove any bits
1479 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1480 if (!(permutation & j))
1483 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1484 if (!r_glsl_permutation->compiled)
1485 R_GLSL_CompilePermutation(mode, permutation);
1486 if (r_glsl_permutation->program)
1489 if (i >= SHADERPERMUTATION_COUNT)
1491 Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n");
1492 Cvar_SetValueQuick(&r_glsl, 0);
1493 R_GLSL_Restart_f(); // unload shaders
1494 return; // no bit left to clear
1499 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1503 void R_SetupGenericShader(qboolean usetexture)
1505 if (gl_support_fragment_shader)
1507 if (r_glsl.integer && r_glsl_usegeneric.integer)
1508 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1509 else if (r_glsl_permutation)
1511 r_glsl_permutation = NULL;
1512 qglUseProgramObjectARB(0);CHECKGLERROR
1517 void R_SetupGenericTwoTextureShader(int texturemode)
1519 if (gl_support_fragment_shader)
1521 if (r_glsl.integer && r_glsl_usegeneric.integer)
1522 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1523 else if (r_glsl_permutation)
1525 r_glsl_permutation = NULL;
1526 qglUseProgramObjectARB(0);CHECKGLERROR
1529 if (!r_glsl_permutation)
1531 if (texturemode == GL_DECAL && gl_combine.integer)
1532 texturemode = GL_INTERPOLATE_ARB;
1533 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1537 void R_SetupDepthOrShadowShader(void)
1539 if (gl_support_fragment_shader)
1541 if (r_glsl.integer && r_glsl_usegeneric.integer)
1542 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1543 else if (r_glsl_permutation)
1545 r_glsl_permutation = NULL;
1546 qglUseProgramObjectARB(0);CHECKGLERROR
1551 extern rtexture_t *r_shadow_attenuationgradienttexture;
1552 extern rtexture_t *r_shadow_attenuation2dtexture;
1553 extern rtexture_t *r_shadow_attenuation3dtexture;
1554 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1556 // select a permutation of the lighting shader appropriate to this
1557 // combination of texture, entity, light source, and fogging, only use the
1558 // minimum features necessary to avoid wasting rendering time in the
1559 // fragment shader on features that are not being used
1560 unsigned int permutation = 0;
1561 unsigned int mode = 0;
1562 // TODO: implement geometry-shader based shadow volumes someday
1563 if (r_glsl_offsetmapping.integer)
1565 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1566 if (r_glsl_offsetmapping_reliefmapping.integer)
1567 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1569 if (rsurfacepass == RSURFPASS_BACKGROUND)
1571 // distorted background
1572 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1573 mode = SHADERMODE_WATER;
1575 mode = SHADERMODE_REFRACTION;
1577 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1580 mode = SHADERMODE_LIGHTSOURCE;
1581 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1582 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1583 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1584 permutation |= SHADERPERMUTATION_CUBEFILTER;
1585 if (diffusescale > 0)
1586 permutation |= SHADERPERMUTATION_DIFFUSE;
1587 if (specularscale > 0)
1588 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1589 if (r_refdef.fogenabled)
1590 permutation |= SHADERPERMUTATION_FOG;
1591 if (rsurface.texture->colormapping)
1592 permutation |= SHADERPERMUTATION_COLORMAPPING;
1593 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1594 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1596 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1598 // unshaded geometry (fullbright or ambient model lighting)
1599 mode = SHADERMODE_FLATCOLOR;
1600 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1601 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1602 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1603 permutation |= SHADERPERMUTATION_GLOW;
1604 if (r_refdef.fogenabled)
1605 permutation |= SHADERPERMUTATION_FOG;
1606 if (rsurface.texture->colormapping)
1607 permutation |= SHADERPERMUTATION_COLORMAPPING;
1608 if (r_glsl_offsetmapping.integer)
1610 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1611 if (r_glsl_offsetmapping_reliefmapping.integer)
1612 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1614 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1615 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1616 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1617 permutation |= SHADERPERMUTATION_REFLECTION;
1619 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1621 // directional model lighting
1622 mode = SHADERMODE_LIGHTDIRECTION;
1623 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1624 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1625 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1626 permutation |= SHADERPERMUTATION_GLOW;
1627 permutation |= SHADERPERMUTATION_DIFFUSE;
1628 if (specularscale > 0)
1629 permutation |= SHADERPERMUTATION_SPECULAR;
1630 if (r_refdef.fogenabled)
1631 permutation |= SHADERPERMUTATION_FOG;
1632 if (rsurface.texture->colormapping)
1633 permutation |= SHADERPERMUTATION_COLORMAPPING;
1634 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1635 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1636 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1637 permutation |= SHADERPERMUTATION_REFLECTION;
1639 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1641 // ambient model lighting
1642 mode = SHADERMODE_LIGHTDIRECTION;
1643 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1644 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1645 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1646 permutation |= SHADERPERMUTATION_GLOW;
1647 if (r_refdef.fogenabled)
1648 permutation |= SHADERPERMUTATION_FOG;
1649 if (rsurface.texture->colormapping)
1650 permutation |= SHADERPERMUTATION_COLORMAPPING;
1651 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1652 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1653 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1654 permutation |= SHADERPERMUTATION_REFLECTION;
1659 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1661 // deluxemapping (light direction texture)
1662 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1663 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1665 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1666 permutation |= SHADERPERMUTATION_DIFFUSE;
1667 if (specularscale > 0)
1668 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1670 else if (r_glsl_deluxemapping.integer >= 2)
1672 // fake deluxemapping (uniform light direction in tangentspace)
1673 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1674 permutation |= SHADERPERMUTATION_DIFFUSE;
1675 if (specularscale > 0)
1676 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1678 else if (rsurface.uselightmaptexture)
1680 // ordinary lightmapping (q1bsp, q3bsp)
1681 mode = SHADERMODE_LIGHTMAP;
1685 // ordinary vertex coloring (q3bsp)
1686 mode = SHADERMODE_VERTEXCOLOR;
1688 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1689 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1690 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1691 permutation |= SHADERPERMUTATION_GLOW;
1692 if (r_refdef.fogenabled)
1693 permutation |= SHADERPERMUTATION_FOG;
1694 if (rsurface.texture->colormapping)
1695 permutation |= SHADERPERMUTATION_COLORMAPPING;
1696 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1697 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1698 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1699 permutation |= SHADERPERMUTATION_REFLECTION;
1701 if(permutation & SHADERPERMUTATION_SPECULAR)
1702 if(r_shadow_glossexact.integer)
1703 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
1704 R_SetupShader_SetPermutation(mode, permutation);
1705 if (mode == SHADERMODE_LIGHTSOURCE)
1707 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1708 if (permutation & SHADERPERMUTATION_DIFFUSE)
1710 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1711 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1712 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1713 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1717 // ambient only is simpler
1718 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale, rsurface.texture->lightmapcolor[3]);
1719 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1720 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1721 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1723 // additive passes are only darkened by fog, not tinted
1724 if (r_glsl_permutation->loc_FogColor >= 0)
1725 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1729 if (mode == SHADERMODE_LIGHTDIRECTION)
1731 if (r_glsl_permutation->loc_AmbientColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale * 0.5f, rsurface.modellight_ambient[1] * ambientscale * 0.5f, rsurface.modellight_ambient[2] * ambientscale * 0.5f);
1732 if (r_glsl_permutation->loc_DiffuseColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale * 0.5f, rsurface.modellight_diffuse[1] * diffusescale * 0.5f, rsurface.modellight_diffuse[2] * diffusescale * 0.5f);
1733 if (r_glsl_permutation->loc_SpecularColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * 0.5f, rsurface.modellight_diffuse[1] * specularscale * 0.5f, rsurface.modellight_diffuse[2] * specularscale * 0.5f);
1734 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1738 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
1739 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1740 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1742 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
1743 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1744 // additive passes are only darkened by fog, not tinted
1745 if (r_glsl_permutation->loc_FogColor >= 0)
1747 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1748 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1750 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1752 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
1753 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
1754 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
1755 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1756 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1757 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1758 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1760 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1762 // The formula used is actually:
1763 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1764 // color.rgb *= SceneBrightness;
1766 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1767 // and do [[calculations]] here in the engine
1768 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1769 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1772 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1773 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1774 if (r_glsl_permutation->loc_Color_Pants >= 0)
1776 if (rsurface.texture->currentskinframe->pants)
1777 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1779 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1781 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1783 if (rsurface.texture->currentskinframe->shirt)
1784 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1786 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1788 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
1789 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
1791 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
1795 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1797 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1801 #define SKINFRAME_HASH 1024
1805 int loadsequence; // incremented each level change
1806 memexpandablearray_t array;
1807 skinframe_t *hash[SKINFRAME_HASH];
1810 r_skinframe_t r_skinframe;
1812 void R_SkinFrame_PrepareForPurge(void)
1814 r_skinframe.loadsequence++;
1815 // wrap it without hitting zero
1816 if (r_skinframe.loadsequence >= 200)
1817 r_skinframe.loadsequence = 1;
1820 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1824 // mark the skinframe as used for the purging code
1825 skinframe->loadsequence = r_skinframe.loadsequence;
1828 void R_SkinFrame_Purge(void)
1832 for (i = 0;i < SKINFRAME_HASH;i++)
1834 for (s = r_skinframe.hash[i];s;s = s->next)
1836 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1838 if (s->merged == s->base)
1840 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1841 R_PurgeTexture(s->stain );s->stain = NULL;
1842 R_PurgeTexture(s->merged);s->merged = NULL;
1843 R_PurgeTexture(s->base );s->base = NULL;
1844 R_PurgeTexture(s->pants );s->pants = NULL;
1845 R_PurgeTexture(s->shirt );s->shirt = NULL;
1846 R_PurgeTexture(s->nmap );s->nmap = NULL;
1847 R_PurgeTexture(s->gloss );s->gloss = NULL;
1848 R_PurgeTexture(s->glow );s->glow = NULL;
1849 R_PurgeTexture(s->fog );s->fog = NULL;
1850 s->loadsequence = 0;
1856 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1858 char basename[MAX_QPATH];
1860 Image_StripImageExtension(name, basename, sizeof(basename));
1862 if( last == NULL ) {
1864 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1865 item = r_skinframe.hash[hashindex];
1870 // linearly search through the hash bucket
1871 for( ; item ; item = item->next ) {
1872 if( !strcmp( item->basename, basename ) ) {
1879 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1883 char basename[MAX_QPATH];
1885 Image_StripImageExtension(name, basename, sizeof(basename));
1887 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1888 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1889 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1893 rtexture_t *dyntexture;
1894 // check whether its a dynamic texture
1895 dyntexture = CL_GetDynTexture( basename );
1896 if (!add && !dyntexture)
1898 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1899 memset(item, 0, sizeof(*item));
1900 strlcpy(item->basename, basename, sizeof(item->basename));
1901 item->base = dyntexture; // either NULL or dyntexture handle
1902 item->textureflags = textureflags;
1903 item->comparewidth = comparewidth;
1904 item->compareheight = compareheight;
1905 item->comparecrc = comparecrc;
1906 item->next = r_skinframe.hash[hashindex];
1907 r_skinframe.hash[hashindex] = item;
1909 else if( item->base == NULL )
1911 rtexture_t *dyntexture;
1912 // check whether its a dynamic texture
1913 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
1914 dyntexture = CL_GetDynTexture( basename );
1915 item->base = dyntexture; // either NULL or dyntexture handle
1918 R_SkinFrame_MarkUsed(item);
1922 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
1924 unsigned long long avgcolor[5], wsum; \
1932 for(pix = 0; pix < cnt; ++pix) \
1935 for(comp = 0; comp < 3; ++comp) \
1937 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
1940 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1942 for(comp = 0; comp < 3; ++comp) \
1943 avgcolor[comp] += getpixel * w; \
1946 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
1947 avgcolor[4] += getpixel; \
1949 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
1951 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
1952 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
1953 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
1954 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
1957 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
1959 // FIXME: it should be possible to disable loading various layers using
1960 // cvars, to prevent wasted loading time and memory usage if the user does
1962 qboolean loadnormalmap = true;
1963 qboolean loadgloss = true;
1964 qboolean loadpantsandshirt = true;
1965 qboolean loadglow = true;
1967 unsigned char *pixels;
1968 unsigned char *bumppixels;
1969 unsigned char *basepixels = NULL;
1970 int basepixels_width;
1971 int basepixels_height;
1972 skinframe_t *skinframe;
1976 if (cls.state == ca_dedicated)
1979 // return an existing skinframe if already loaded
1980 // if loading of the first image fails, don't make a new skinframe as it
1981 // would cause all future lookups of this to be missing
1982 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1983 if (skinframe && skinframe->base)
1986 basepixels = loadimagepixelsbgra(name, complain, true);
1987 if (basepixels == NULL)
1990 if (developer_loading.integer)
1991 Con_Printf("loading skin \"%s\"\n", name);
1993 // we've got some pixels to store, so really allocate this new texture now
1995 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1996 skinframe->stain = NULL;
1997 skinframe->merged = NULL;
1998 skinframe->base = r_texture_notexture;
1999 skinframe->pants = NULL;
2000 skinframe->shirt = NULL;
2001 skinframe->nmap = r_texture_blanknormalmap;
2002 skinframe->gloss = NULL;
2003 skinframe->glow = NULL;
2004 skinframe->fog = NULL;
2006 basepixels_width = image_width;
2007 basepixels_height = image_height;
2008 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2010 if (textureflags & TEXF_ALPHA)
2012 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2013 if (basepixels[j] < 255)
2015 if (j < basepixels_width * basepixels_height * 4)
2017 // has transparent pixels
2019 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2020 for (j = 0;j < image_width * image_height * 4;j += 4)
2025 pixels[j+3] = basepixels[j+3];
2027 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2032 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2033 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2035 // _norm is the name used by tenebrae and has been adopted as standard
2038 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2040 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2044 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2046 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2047 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2048 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2050 Mem_Free(bumppixels);
2052 else if (r_shadow_bumpscale_basetexture.value > 0)
2054 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2055 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2056 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2060 // _luma is supported for tenebrae compatibility
2061 // (I think it's a very stupid name, but oh well)
2062 // _glow is the preferred name
2063 if (loadglow && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) != NULL || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2064 if (loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2065 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2066 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2069 Mem_Free(basepixels);
2074 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2077 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2080 static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
2085 for (i = 0;i < width*height;i++)
2086 if (((unsigned char *)&palette[in[i]])[3] > 0)
2088 if (i == width*height)
2091 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2094 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2095 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2098 unsigned char *temp1, *temp2;
2099 skinframe_t *skinframe;
2101 if (cls.state == ca_dedicated)
2104 // if already loaded just return it, otherwise make a new skinframe
2105 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2106 if (skinframe && skinframe->base)
2109 skinframe->stain = NULL;
2110 skinframe->merged = NULL;
2111 skinframe->base = r_texture_notexture;
2112 skinframe->pants = NULL;
2113 skinframe->shirt = NULL;
2114 skinframe->nmap = r_texture_blanknormalmap;
2115 skinframe->gloss = NULL;
2116 skinframe->glow = NULL;
2117 skinframe->fog = NULL;
2119 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2123 if (developer_loading.integer)
2124 Con_Printf("loading 32bit skin \"%s\"\n", name);
2126 if (r_shadow_bumpscale_basetexture.value > 0)
2128 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2129 temp2 = temp1 + width * height * 4;
2130 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2131 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2134 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2135 if (textureflags & TEXF_ALPHA)
2137 for (i = 3;i < width * height * 4;i += 4)
2138 if (skindata[i] < 255)
2140 if (i < width * height * 4)
2142 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2143 memcpy(fogpixels, skindata, width * height * 4);
2144 for (i = 0;i < width * height * 4;i += 4)
2145 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2146 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2147 Mem_Free(fogpixels);
2151 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2152 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2157 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2160 unsigned char *temp1, *temp2;
2161 unsigned int *palette;
2162 skinframe_t *skinframe;
2164 if (cls.state == ca_dedicated)
2167 // if already loaded just return it, otherwise make a new skinframe
2168 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2169 if (skinframe && skinframe->base)
2172 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2174 skinframe->stain = NULL;
2175 skinframe->merged = NULL;
2176 skinframe->base = r_texture_notexture;
2177 skinframe->pants = NULL;
2178 skinframe->shirt = NULL;
2179 skinframe->nmap = r_texture_blanknormalmap;
2180 skinframe->gloss = NULL;
2181 skinframe->glow = NULL;
2182 skinframe->fog = NULL;
2184 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2188 if (developer_loading.integer)
2189 Con_Printf("loading quake skin \"%s\"\n", name);
2191 if (r_shadow_bumpscale_basetexture.value > 0)
2193 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2194 temp2 = temp1 + width * height * 4;
2195 // use either a custom palette or the quake palette
2196 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2197 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2198 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2201 // use either a custom palette, or the quake palette
2202 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2203 if (loadglowtexture)
2204 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2205 if (loadpantsandshirt)
2207 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2208 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2210 if (skinframe->pants || skinframe->shirt)
2211 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename), loadglowtexture ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap, skinframe->textureflags, false); // no special colors
2212 if (textureflags & TEXF_ALPHA)
2214 for (i = 0;i < width * height;i++)
2215 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2217 if (i < width * height)
2218 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2221 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2222 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2227 skinframe_t *R_SkinFrame_LoadMissing(void)
2229 skinframe_t *skinframe;
2231 if (cls.state == ca_dedicated)
2234 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2235 skinframe->stain = NULL;
2236 skinframe->merged = NULL;
2237 skinframe->base = r_texture_notexture;
2238 skinframe->pants = NULL;
2239 skinframe->shirt = NULL;
2240 skinframe->nmap = r_texture_blanknormalmap;
2241 skinframe->gloss = NULL;
2242 skinframe->glow = NULL;
2243 skinframe->fog = NULL;
2245 skinframe->avgcolor[0] = rand() / RAND_MAX;
2246 skinframe->avgcolor[1] = rand() / RAND_MAX;
2247 skinframe->avgcolor[2] = rand() / RAND_MAX;
2248 skinframe->avgcolor[3] = 1;
2253 void gl_main_start(void)
2257 memset(r_queries, 0, sizeof(r_queries));
2259 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2260 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2262 // set up r_skinframe loading system for textures
2263 memset(&r_skinframe, 0, sizeof(r_skinframe));
2264 r_skinframe.loadsequence = 1;
2265 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2267 r_main_texturepool = R_AllocTexturePool();
2268 R_BuildBlankTextures();
2270 if (gl_texturecubemap)
2273 R_BuildNormalizationCube();
2275 r_texture_fogattenuation = NULL;
2276 r_texture_gammaramps = NULL;
2277 //r_texture_fogintensity = NULL;
2278 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2279 memset(&r_waterstate, 0, sizeof(r_waterstate));
2280 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2281 memset(&r_svbsp, 0, sizeof (r_svbsp));
2283 r_refdef.fogmasktable_density = 0;
2286 void gl_main_shutdown(void)
2289 qglDeleteQueriesARB(r_maxqueries, r_queries);
2293 memset(r_queries, 0, sizeof(r_queries));
2295 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2296 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2298 // clear out the r_skinframe state
2299 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2300 memset(&r_skinframe, 0, sizeof(r_skinframe));
2303 Mem_Free(r_svbsp.nodes);
2304 memset(&r_svbsp, 0, sizeof (r_svbsp));
2305 R_FreeTexturePool(&r_main_texturepool);
2306 r_texture_blanknormalmap = NULL;
2307 r_texture_white = NULL;
2308 r_texture_grey128 = NULL;
2309 r_texture_black = NULL;
2310 r_texture_whitecube = NULL;
2311 r_texture_normalizationcube = NULL;
2312 r_texture_fogattenuation = NULL;
2313 r_texture_gammaramps = NULL;
2314 //r_texture_fogintensity = NULL;
2315 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2316 memset(&r_waterstate, 0, sizeof(r_waterstate));
2320 extern void CL_ParseEntityLump(char *entitystring);
2321 void gl_main_newmap(void)
2323 // FIXME: move this code to client
2325 char *entities, entname[MAX_QPATH];
2328 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2329 l = (int)strlen(entname) - 4;
2330 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2332 memcpy(entname + l, ".ent", 5);
2333 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2335 CL_ParseEntityLump(entities);
2340 if (cl.worldmodel->brush.entities)
2341 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2345 void GL_Main_Init(void)
2347 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2349 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2350 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2351 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2352 if (gamemode == GAME_NEHAHRA)
2354 Cvar_RegisterVariable (&gl_fogenable);
2355 Cvar_RegisterVariable (&gl_fogdensity);
2356 Cvar_RegisterVariable (&gl_fogred);
2357 Cvar_RegisterVariable (&gl_foggreen);
2358 Cvar_RegisterVariable (&gl_fogblue);
2359 Cvar_RegisterVariable (&gl_fogstart);
2360 Cvar_RegisterVariable (&gl_fogend);
2361 Cvar_RegisterVariable (&gl_skyclip);
2363 Cvar_RegisterVariable(&r_depthfirst);
2364 Cvar_RegisterVariable(&r_useinfinitefarclip);
2365 Cvar_RegisterVariable(&r_nearclip);
2366 Cvar_RegisterVariable(&r_showbboxes);
2367 Cvar_RegisterVariable(&r_showsurfaces);
2368 Cvar_RegisterVariable(&r_showtris);
2369 Cvar_RegisterVariable(&r_shownormals);
2370 Cvar_RegisterVariable(&r_showlighting);
2371 Cvar_RegisterVariable(&r_showshadowvolumes);
2372 Cvar_RegisterVariable(&r_showcollisionbrushes);
2373 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2374 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2375 Cvar_RegisterVariable(&r_showdisabledepthtest);
2376 Cvar_RegisterVariable(&r_drawportals);
2377 Cvar_RegisterVariable(&r_drawentities);
2378 Cvar_RegisterVariable(&r_cullentities_trace);
2379 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2380 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2381 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2382 Cvar_RegisterVariable(&r_drawviewmodel);
2383 Cvar_RegisterVariable(&r_speeds);
2384 Cvar_RegisterVariable(&r_fullbrights);
2385 Cvar_RegisterVariable(&r_wateralpha);
2386 Cvar_RegisterVariable(&r_dynamic);
2387 Cvar_RegisterVariable(&r_fullbright);
2388 Cvar_RegisterVariable(&r_shadows);
2389 Cvar_RegisterVariable(&r_shadows_throwdistance);
2390 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2391 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2392 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2393 Cvar_RegisterVariable(&r_fog_exp2);
2394 Cvar_RegisterVariable(&r_drawfog);
2395 Cvar_RegisterVariable(&r_textureunits);
2396 Cvar_RegisterVariable(&r_glsl);
2397 Cvar_RegisterVariable(&r_glsl_contrastboost);
2398 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2399 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2400 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2401 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2402 Cvar_RegisterVariable(&r_glsl_postprocess);
2403 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2404 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2405 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2406 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2407 Cvar_RegisterVariable(&r_glsl_usegeneric);
2408 Cvar_RegisterVariable(&r_water);
2409 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2410 Cvar_RegisterVariable(&r_water_clippingplanebias);
2411 Cvar_RegisterVariable(&r_water_refractdistort);
2412 Cvar_RegisterVariable(&r_water_reflectdistort);
2413 Cvar_RegisterVariable(&r_lerpsprites);
2414 Cvar_RegisterVariable(&r_lerpmodels);
2415 Cvar_RegisterVariable(&r_lerplightstyles);
2416 Cvar_RegisterVariable(&r_waterscroll);
2417 Cvar_RegisterVariable(&r_bloom);
2418 Cvar_RegisterVariable(&r_bloom_colorscale);
2419 Cvar_RegisterVariable(&r_bloom_brighten);
2420 Cvar_RegisterVariable(&r_bloom_blur);
2421 Cvar_RegisterVariable(&r_bloom_resolution);
2422 Cvar_RegisterVariable(&r_bloom_colorexponent);
2423 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2424 Cvar_RegisterVariable(&r_hdr);
2425 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2426 Cvar_RegisterVariable(&r_hdr_glowintensity);
2427 Cvar_RegisterVariable(&r_hdr_range);
2428 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2429 Cvar_RegisterVariable(&developer_texturelogging);
2430 Cvar_RegisterVariable(&gl_lightmaps);
2431 Cvar_RegisterVariable(&r_test);
2432 Cvar_RegisterVariable(&r_batchmode);
2433 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2434 Cvar_SetValue("r_fullbrights", 0);
2435 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2437 Cvar_RegisterVariable(&r_track_sprites);
2438 Cvar_RegisterVariable(&r_track_sprites_flags);
2439 Cvar_RegisterVariable(&r_track_sprites_scalew);
2440 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2443 extern void R_Textures_Init(void);
2444 extern void GL_Draw_Init(void);
2445 extern void GL_Main_Init(void);
2446 extern void R_Shadow_Init(void);
2447 extern void R_Sky_Init(void);
2448 extern void GL_Surf_Init(void);
2449 extern void R_Particles_Init(void);
2450 extern void R_Explosion_Init(void);
2451 extern void gl_backend_init(void);
2452 extern void Sbar_Init(void);
2453 extern void R_LightningBeams_Init(void);
2454 extern void Mod_RenderInit(void);
2456 void Render_Init(void)
2468 R_LightningBeams_Init();
2477 extern char *ENGINE_EXTENSIONS;
2480 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2481 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2482 gl_version = (const char *)qglGetString(GL_VERSION);
2483 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2487 if (!gl_platformextensions)
2488 gl_platformextensions = "";
2490 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2491 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2492 Con_Printf("GL_VERSION: %s\n", gl_version);
2493 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2494 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2496 VID_CheckExtensions();
2498 // LordHavoc: report supported extensions
2499 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2501 // clear to black (loading plaque will be seen over this)
2503 qglClearColor(0,0,0,1);CHECKGLERROR
2504 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2507 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2511 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2513 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2516 p = r_refdef.view.frustum + i;
2521 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2525 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2529 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2533 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2537 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2541 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2545 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2549 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2557 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2561 for (i = 0;i < numplanes;i++)
2568 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2572 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2576 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2580 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2584 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2588 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2592 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2596 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2604 //==================================================================================
2606 static void R_View_UpdateEntityLighting (void)
2609 entity_render_t *ent;
2610 vec3_t tempdiffusenormal;
2612 for (i = 0;i < r_refdef.scene.numentities;i++)
2614 ent = r_refdef.scene.entities[i];
2616 // skip unseen models
2617 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
2621 if (ent->model && ent->model->brush.num_leafs)
2623 // TODO: use modellight for r_ambient settings on world?
2624 VectorSet(ent->modellight_ambient, 0, 0, 0);
2625 VectorSet(ent->modellight_diffuse, 0, 0, 0);
2626 VectorSet(ent->modellight_lightdir, 0, 0, 1);
2630 // fetch the lighting from the worldmodel data
2631 VectorSet(ent->modellight_ambient, r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f));
2632 VectorClear(ent->modellight_diffuse);
2633 VectorClear(tempdiffusenormal);
2634 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
2637 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2638 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2641 VectorSet(ent->modellight_ambient, 1, 1, 1);
2643 // move the light direction into modelspace coordinates for lighting code
2644 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2645 if(VectorLength2(ent->modellight_lightdir) == 0)
2646 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2647 VectorNormalize(ent->modellight_lightdir);
2651 static void R_View_UpdateEntityVisible (void)
2654 entity_render_t *ent;
2656 if (!r_drawentities.integer)
2659 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2660 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2662 // worldmodel can check visibility
2663 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2664 for (i = 0;i < r_refdef.scene.numentities;i++)
2666 ent = r_refdef.scene.entities[i];
2667 if (!(ent->flags & renderimask))
2668 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
2669 if ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
2670 r_refdef.viewcache.entityvisible[i] = true;
2672 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2674 for (i = 0;i < r_refdef.scene.numentities;i++)
2676 ent = r_refdef.scene.entities[i];
2677 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2679 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.scene.worldmodel, r_refdef.view.origin, ent->mins, ent->maxs))
2680 ent->last_trace_visibility = realtime;
2681 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2682 r_refdef.viewcache.entityvisible[i] = 0;
2689 // no worldmodel or it can't check visibility
2690 for (i = 0;i < r_refdef.scene.numentities;i++)
2692 ent = r_refdef.scene.entities[i];
2693 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
2698 // only used if skyrendermasked, and normally returns false
2699 int R_DrawBrushModelsSky (void)
2702 entity_render_t *ent;
2704 if (!r_drawentities.integer)
2708 for (i = 0;i < r_refdef.scene.numentities;i++)
2710 if (!r_refdef.viewcache.entityvisible[i])
2712 ent = r_refdef.scene.entities[i];
2713 if (!ent->model || !ent->model->DrawSky)
2715 ent->model->DrawSky(ent);
2721 static void R_DrawNoModel(entity_render_t *ent);
2722 static void R_DrawModels(void)
2725 entity_render_t *ent;
2727 if (!r_drawentities.integer)
2730 for (i = 0;i < r_refdef.scene.numentities;i++)
2732 if (!r_refdef.viewcache.entityvisible[i])
2734 ent = r_refdef.scene.entities[i];
2735 r_refdef.stats.entities++;
2736 if (ent->model && ent->model->Draw != NULL)
2737 ent->model->Draw(ent);
2743 static void R_DrawModelsDepth(void)
2746 entity_render_t *ent;
2748 if (!r_drawentities.integer)
2751 for (i = 0;i < r_refdef.scene.numentities;i++)
2753 if (!r_refdef.viewcache.entityvisible[i])
2755 ent = r_refdef.scene.entities[i];
2756 if (ent->model && ent->model->DrawDepth != NULL)
2757 ent->model->DrawDepth(ent);
2761 static void R_DrawModelsDebug(void)
2764 entity_render_t *ent;
2766 if (!r_drawentities.integer)
2769 for (i = 0;i < r_refdef.scene.numentities;i++)
2771 if (!r_refdef.viewcache.entityvisible[i])
2773 ent = r_refdef.scene.entities[i];
2774 if (ent->model && ent->model->DrawDebug != NULL)
2775 ent->model->DrawDebug(ent);
2779 static void R_DrawModelsAddWaterPlanes(void)
2782 entity_render_t *ent;
2784 if (!r_drawentities.integer)
2787 for (i = 0;i < r_refdef.scene.numentities;i++)
2789 if (!r_refdef.viewcache.entityvisible[i])
2791 ent = r_refdef.scene.entities[i];
2792 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2793 ent->model->DrawAddWaterPlanes(ent);
2797 static void R_View_SetFrustum(void)
2800 double slopex, slopey;
2801 vec3_t forward, left, up, origin;
2803 // we can't trust r_refdef.view.forward and friends in reflected scenes
2804 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2807 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2808 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2809 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2810 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2811 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2812 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2813 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2814 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2815 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2816 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2817 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2818 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2822 zNear = r_refdef.nearclip;
2823 nudge = 1.0 - 1.0 / (1<<23);
2824 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2825 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2826 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2827 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2828 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2829 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2830 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2831 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2837 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2838 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2839 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2840 r_refdef.view.frustum[0].dist = m[15] - m[12];
2842 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2843 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2844 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2845 r_refdef.view.frustum[1].dist = m[15] + m[12];
2847 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2848 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2849 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2850 r_refdef.view.frustum[2].dist = m[15] - m[13];
2852 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2853 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2854 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2855 r_refdef.view.frustum[3].dist = m[15] + m[13];
2857 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2858 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2859 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2860 r_refdef.view.frustum[4].dist = m[15] - m[14];
2862 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2863 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2864 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2865 r_refdef.view.frustum[5].dist = m[15] + m[14];
2868 if (r_refdef.view.useperspective)
2870 slopex = 1.0 / r_refdef.view.frustum_x;
2871 slopey = 1.0 / r_refdef.view.frustum_y;
2872 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2873 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
2874 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
2875 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
2876 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2878 // Leaving those out was a mistake, those were in the old code, and they
2879 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2880 // I couldn't reproduce it after adding those normalizations. --blub
2881 VectorNormalize(r_refdef.view.frustum[0].normal);
2882 VectorNormalize(r_refdef.view.frustum[1].normal);
2883 VectorNormalize(r_refdef.view.frustum[2].normal);
2884 VectorNormalize(r_refdef.view.frustum[3].normal);
2886 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2887 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2888 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2889 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2890 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2892 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2893 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2894 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2895 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2896 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2900 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2901 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2902 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2903 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2904 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2905 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2906 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2907 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2908 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2909 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2911 r_refdef.view.numfrustumplanes = 5;
2913 if (r_refdef.view.useclipplane)
2915 r_refdef.view.numfrustumplanes = 6;
2916 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2919 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2920 PlaneClassify(r_refdef.view.frustum + i);
2922 // LordHavoc: note to all quake engine coders, Quake had a special case
2923 // for 90 degrees which assumed a square view (wrong), so I removed it,
2924 // Quake2 has it disabled as well.
2926 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2927 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2928 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2929 //PlaneClassify(&frustum[0]);
2931 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2932 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2933 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2934 //PlaneClassify(&frustum[1]);
2936 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2937 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2938 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2939 //PlaneClassify(&frustum[2]);
2941 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2942 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2943 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2944 //PlaneClassify(&frustum[3]);
2947 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2948 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2949 //PlaneClassify(&frustum[4]);
2952 void R_View_Update(void)
2954 R_View_SetFrustum();
2955 R_View_WorldVisibility(r_refdef.view.useclipplane);
2956 R_View_UpdateEntityVisible();
2957 R_View_UpdateEntityLighting();
2960 void R_SetupView(qboolean allowwaterclippingplane)
2962 if (!r_refdef.view.useperspective)
2963 GL_SetupView_Mode_Ortho(-r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
2964 else if (gl_stencil && r_useinfinitefarclip.integer)
2965 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2967 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2969 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2971 if (r_refdef.view.useclipplane && allowwaterclippingplane)
2973 // LordHavoc: couldn't figure out how to make this approach the
2974 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2975 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2976 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2977 dist = r_refdef.view.clipplane.dist;
2978 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2982 void R_ResetViewRendering2D(void)
2986 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2987 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2988 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2989 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2990 GL_Color(1, 1, 1, 1);
2991 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2992 GL_BlendFunc(GL_ONE, GL_ZERO);
2993 GL_AlphaTest(false);
2994 GL_ScissorTest(false);
2995 GL_DepthMask(false);
2996 GL_DepthRange(0, 1);
2997 GL_DepthTest(false);
2998 R_Mesh_Matrix(&identitymatrix);
2999 R_Mesh_ResetTextureState();
3000 GL_PolygonOffset(0, 0);
3001 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3002 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3003 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3004 qglStencilMask(~0);CHECKGLERROR
3005 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3006 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3007 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3008 R_SetupGenericShader(true);
3011 void R_ResetViewRendering3D(void)
3015 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3016 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3018 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
3019 GL_Color(1, 1, 1, 1);
3020 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3021 GL_BlendFunc(GL_ONE, GL_ZERO);
3022 GL_AlphaTest(false);
3023 GL_ScissorTest(true);
3025 GL_DepthRange(0, 1);
3027 R_Mesh_Matrix(&identitymatrix);
3028 R_Mesh_ResetTextureState();
3029 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3030 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3031 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3032 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3033 qglStencilMask(~0);CHECKGLERROR
3034 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3035 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3036 GL_CullFace(r_refdef.view.cullface_back);
3037 R_SetupGenericShader(true);
3040 void R_RenderScene(void);
3041 void R_RenderWaterPlanes(void);
3043 static void R_Water_StartFrame(void)
3046 int waterwidth, waterheight, texturewidth, textureheight;
3047 r_waterstate_waterplane_t *p;
3049 // set waterwidth and waterheight to the water resolution that will be
3050 // used (often less than the screen resolution for faster rendering)
3051 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3052 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3054 // calculate desired texture sizes
3055 // can't use water if the card does not support the texture size
3056 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3057 texturewidth = textureheight = waterwidth = waterheight = 0;
3058 else if (gl_support_arb_texture_non_power_of_two)
3060 texturewidth = waterwidth;
3061 textureheight = waterheight;
3065 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3066 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3069 // allocate textures as needed
3070 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3072 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3073 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3075 if (p->texture_refraction)
3076 R_FreeTexture(p->texture_refraction);
3077 p->texture_refraction = NULL;
3078 if (p->texture_reflection)
3079 R_FreeTexture(p->texture_reflection);
3080 p->texture_reflection = NULL;
3082 memset(&r_waterstate, 0, sizeof(r_waterstate));
3083 r_waterstate.waterwidth = waterwidth;
3084 r_waterstate.waterheight = waterheight;
3085 r_waterstate.texturewidth = texturewidth;
3086 r_waterstate.textureheight = textureheight;
3089 if (r_waterstate.waterwidth)
3091 r_waterstate.enabled = true;
3093 // set up variables that will be used in shader setup
3094 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3095 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3096 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3097 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3100 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3101 r_waterstate.numwaterplanes = 0;
3104 void R_Water_AddWaterPlane(msurface_t *surface)
3106 int triangleindex, planeindex;
3112 r_waterstate_waterplane_t *p;
3113 texture_t *t = R_GetCurrentTexture(surface->texture);
3114 // just use the first triangle with a valid normal for any decisions
3115 VectorClear(normal);
3116 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3118 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3119 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3120 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3121 TriangleNormal(vert[0], vert[1], vert[2], normal);
3122 if (VectorLength2(normal) >= 0.001)
3126 VectorCopy(normal, plane.normal);
3127 VectorNormalize(plane.normal);
3128 plane.dist = DotProduct(vert[0], plane.normal);
3129 PlaneClassify(&plane);
3130 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3132 // skip backfaces (except if nocullface is set)
3133 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3135 VectorNegate(plane.normal, plane.normal);
3137 PlaneClassify(&plane);
3141 // find a matching plane if there is one
3142 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3143 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3145 if (planeindex >= r_waterstate.maxwaterplanes)
3146 return; // nothing we can do, out of planes
3148 // if this triangle does not fit any known plane rendered this frame, add one
3149 if (planeindex >= r_waterstate.numwaterplanes)
3151 // store the new plane
3152 r_waterstate.numwaterplanes++;
3154 // clear materialflags and pvs
3155 p->materialflags = 0;
3156 p->pvsvalid = false;
3158 // merge this surface's materialflags into the waterplane
3159 p->materialflags |= t->currentmaterialflags;
3160 // merge this surface's PVS into the waterplane
3161 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3162 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3163 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3165 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3170 static void R_Water_ProcessPlanes(void)
3172 r_refdef_view_t originalview;
3173 r_refdef_view_t myview;
3175 r_waterstate_waterplane_t *p;
3177 originalview = r_refdef.view;
3179 // make sure enough textures are allocated
3180 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3182 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3184 if (!p->texture_refraction)
3185 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3186 if (!p->texture_refraction)
3190 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3192 if (!p->texture_reflection)
3193 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3194 if (!p->texture_reflection)
3200 r_refdef.view = originalview;
3201 r_refdef.view.showdebug = false;
3202 r_refdef.view.width = r_waterstate.waterwidth;
3203 r_refdef.view.height = r_waterstate.waterheight;
3204 r_refdef.view.useclipplane = true;
3205 myview = r_refdef.view;
3206 r_waterstate.renderingscene = true;
3207 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3209 // render the normal view scene and copy into texture
3210 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
3211 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3213 r_refdef.view = myview;
3214 r_refdef.view.clipplane = p->plane;
3215 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3216 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3217 PlaneClassify(&r_refdef.view.clipplane);
3219 R_ResetViewRendering3D();
3220 R_ClearScreen(r_refdef.fogenabled);
3224 // copy view into the screen texture
3225 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3226 GL_ActiveTexture(0);
3228 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3231 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3233 r_refdef.view = myview;
3234 // render reflected scene and copy into texture
3235 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3236 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3237 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3238 r_refdef.view.clipplane = p->plane;
3239 // reverse the cullface settings for this render
3240 r_refdef.view.cullface_front = GL_FRONT;
3241 r_refdef.view.cullface_back = GL_BACK;
3242 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3244 r_refdef.view.usecustompvs = true;
3246 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3248 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3251 R_ResetViewRendering3D();
3252 R_ClearScreen(r_refdef.fogenabled);
3256 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3257 GL_ActiveTexture(0);
3259 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3262 r_waterstate.renderingscene = false;
3263 r_refdef.view = originalview;
3264 R_ResetViewRendering3D();
3265 R_ClearScreen(r_refdef.fogenabled);
3269 r_refdef.view = originalview;
3270 r_waterstate.renderingscene = false;
3271 Cvar_SetValueQuick(&r_water, 0);
3272 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3276 void R_Bloom_StartFrame(void)
3278 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3280 // set bloomwidth and bloomheight to the bloom resolution that will be
3281 // used (often less than the screen resolution for faster rendering)
3282 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3283 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3284 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3285 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3286 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3288 // calculate desired texture sizes
3289 if (gl_support_arb_texture_non_power_of_two)
3291 screentexturewidth = r_refdef.view.width;
3292 screentextureheight = r_refdef.view.height;
3293 bloomtexturewidth = r_bloomstate.bloomwidth;
3294 bloomtextureheight = r_bloomstate.bloomheight;
3298 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3299 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3300 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3301 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3304 if ((r_hdr.integer || r_bloom.integer) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
3306 Cvar_SetValueQuick(&r_hdr, 0);
3307 Cvar_SetValueQuick(&r_bloom, 0);
3310 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
3311 screentexturewidth = screentextureheight = 0;
3312 if (!r_hdr.integer && !r_bloom.integer)
3313 bloomtexturewidth = bloomtextureheight = 0;
3315 // allocate textures as needed
3316 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3318 if (r_bloomstate.texture_screen)
3319 R_FreeTexture(r_bloomstate.texture_screen);
3320 r_bloomstate.texture_screen = NULL;
3321 r_bloomstate.screentexturewidth = screentexturewidth;
3322 r_bloomstate.screentextureheight = screentextureheight;
3323 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3324 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3326 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3328 if (r_bloomstate.texture_bloom)
3329 R_FreeTexture(r_bloomstate.texture_bloom);
3330 r_bloomstate.texture_bloom = NULL;
3331 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3332 r_bloomstate.bloomtextureheight = bloomtextureheight;
3333 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3334 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3337 // set up a texcoord array for the full resolution screen image
3338 // (we have to keep this around to copy back during final render)
3339 r_bloomstate.screentexcoord2f[0] = 0;
3340 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3341 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3342 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3343 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3344 r_bloomstate.screentexcoord2f[5] = 0;
3345 r_bloomstate.screentexcoord2f[6] = 0;
3346 r_bloomstate.screentexcoord2f[7] = 0;
3348 // set up a texcoord array for the reduced resolution bloom image
3349 // (which will be additive blended over the screen image)
3350 r_bloomstate.bloomtexcoord2f[0] = 0;
3351 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3352 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3353 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3354 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3355 r_bloomstate.bloomtexcoord2f[5] = 0;
3356 r_bloomstate.bloomtexcoord2f[6] = 0;
3357 r_bloomstate.bloomtexcoord2f[7] = 0;
3359 if (r_hdr.integer || r_bloom.integer)
3361 r_bloomstate.enabled = true;
3362 r_bloomstate.hdr = r_hdr.integer != 0;
3366 void R_Bloom_CopyBloomTexture(float colorscale)
3368 r_refdef.stats.bloom++;
3370 // scale down screen texture to the bloom texture size
3372 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3373 GL_BlendFunc(GL_ONE, GL_ZERO);
3374 GL_Color(colorscale, colorscale, colorscale, 1);
3375 // TODO: optimize with multitexture or GLSL
3376 R_SetupGenericShader(true);
3377 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3378 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3379 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3380 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3382 // we now have a bloom image in the framebuffer
3383 // copy it into the bloom image texture for later processing
3384 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3385 GL_ActiveTexture(0);
3387 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3388 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3391 void R_Bloom_CopyHDRTexture(void)
3393 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3394 GL_ActiveTexture(0);
3396 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3397 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3400 void R_Bloom_MakeTexture(void)
3403 float xoffset, yoffset, r, brighten;
3405 r_refdef.stats.bloom++;
3407 R_ResetViewRendering2D();
3408 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3409 R_Mesh_ColorPointer(NULL, 0, 0);
3410 R_SetupGenericShader(true);
3412 // we have a bloom image in the framebuffer
3414 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3416 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3419 r = bound(0, r_bloom_colorexponent.value / x, 1);
3420 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3421 GL_Color(r, r, r, 1);
3422 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3423 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3424 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3425 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3427 // copy the vertically blurred bloom view to a texture
3428 GL_ActiveTexture(0);
3430 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3431 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3434 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3435 brighten = r_bloom_brighten.value;
3437 brighten *= r_hdr_range.value;
3438 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3439 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3441 for (dir = 0;dir < 2;dir++)
3443 // blend on at multiple vertical offsets to achieve a vertical blur
3444 // TODO: do offset blends using GLSL
3445 GL_BlendFunc(GL_ONE, GL_ZERO);
3446 for (x = -range;x <= range;x++)
3448 if (!dir){xoffset = 0;yoffset = x;}
3449 else {xoffset = x;yoffset = 0;}
3450 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3451 yoffset /= (float)r_bloomstate.bloomtextureheight;
3452 // compute a texcoord array with the specified x and y offset
3453 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3454 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3455 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3456 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3457 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3458 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3459 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3460 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3461 // this r value looks like a 'dot' particle, fading sharply to
3462 // black at the edges
3463 // (probably not realistic but looks good enough)
3464 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3465 //r = (dir ? 1.0f : brighten)/(range*2+1);
3466 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3467 GL_Color(r, r, r, 1);
3468 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3469 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3470 GL_BlendFunc(GL_ONE, GL_ONE);
3473 // copy the vertically blurred bloom view to a texture
3474 GL_ActiveTexture(0);
3476 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3477 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3480 // apply subtract last
3481 // (just like it would be in a GLSL shader)
3482 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3484 GL_BlendFunc(GL_ONE, GL_ZERO);
3485 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3486 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3487 GL_Color(1, 1, 1, 1);
3488 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3489 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3491 GL_BlendFunc(GL_ONE, GL_ONE);
3492 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3493 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3494 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3495 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3496 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3497 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3498 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3500 // copy the darkened bloom view to a texture
3501 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3502 GL_ActiveTexture(0);
3504 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3505 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3509 void R_HDR_RenderBloomTexture(void)
3511 int oldwidth, oldheight;
3512 float oldcolorscale;
3514 oldcolorscale = r_refdef.view.colorscale;
3515 oldwidth = r_refdef.view.width;
3516 oldheight = r_refdef.view.height;
3517 r_refdef.view.width = r_bloomstate.bloomwidth;
3518 r_refdef.view.height = r_bloomstate.bloomheight;
3520 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3521 // TODO: add exposure compensation features
3522 // TODO: add fp16 framebuffer support
3524 r_refdef.view.showdebug = false;
3525 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3527 R_ResetViewRendering3D();
3529 R_ClearScreen(r_refdef.fogenabled);
3530 if (r_timereport_active)
3531 R_TimeReport("HDRclear");
3534 if (r_timereport_active)
3535 R_TimeReport("visibility");
3537 r_waterstate.numwaterplanes = 0;
3538 if (r_waterstate.enabled)
3539 R_RenderWaterPlanes();
3541 r_refdef.view.showdebug = true;
3543 r_waterstate.numwaterplanes = 0;
3545 R_ResetViewRendering2D();
3547 R_Bloom_CopyHDRTexture();
3548 R_Bloom_MakeTexture();
3550 // restore the view settings
3551 r_refdef.view.width = oldwidth;
3552 r_refdef.view.height = oldheight;
3553 r_refdef.view.colorscale = oldcolorscale;
3555 R_ResetViewRendering3D();
3557 R_ClearScreen(r_refdef.fogenabled);
3558 if (r_timereport_active)
3559 R_TimeReport("viewclear");
3562 static void R_BlendView(void)
3564 if (r_bloomstate.texture_screen)
3566 // copy view into the screen texture
3567 R_ResetViewRendering2D();
3568 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3569 R_Mesh_ColorPointer(NULL, 0, 0);
3570 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3571 GL_ActiveTexture(0);CHECKGLERROR
3572 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
3573 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3576 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3578 unsigned int permutation =
3579 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3580 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3581 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3582 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0);
3584 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3586 // render simple bloom effect
3587 // copy the screen and shrink it and darken it for the bloom process
3588 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3589 // make the bloom texture
3590 R_Bloom_MakeTexture();
3593 R_ResetViewRendering2D();
3594 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3595 R_Mesh_ColorPointer(NULL, 0, 0);
3596 GL_Color(1, 1, 1, 1);
3597 GL_BlendFunc(GL_ONE, GL_ZERO);
3598 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3599 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3600 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3601 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3602 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3603 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3604 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3605 if (r_glsl_permutation->loc_TintColor >= 0)
3606 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3607 if (r_glsl_permutation->loc_ClientTime >= 0)
3608 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3609 if (r_glsl_permutation->loc_PixelSize >= 0)
3610 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3611 if (r_glsl_permutation->loc_UserVec1 >= 0)
3613 float a=0, b=0, c=0, d=0;
3614 #if _MSC_VER >= 1400
3615 #define sscanf sscanf_s
3617 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3618 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3620 if (r_glsl_permutation->loc_UserVec2 >= 0)
3622 float a=0, b=0, c=0, d=0;
3623 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3624 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3626 if (r_glsl_permutation->loc_UserVec3 >= 0)
3628 float a=0, b=0, c=0, d=0;
3629 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3630 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3632 if (r_glsl_permutation->loc_UserVec4 >= 0)
3634 float a=0, b=0, c=0, d=0;
3635 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3636 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3638 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3639 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3645 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3647 // render high dynamic range bloom effect
3648 // the bloom texture was made earlier this render, so we just need to
3649 // blend it onto the screen...
3650 R_ResetViewRendering2D();
3651 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3652 R_Mesh_ColorPointer(NULL, 0, 0);
3653 R_SetupGenericShader(true);
3654 GL_Color(1, 1, 1, 1);
3655 GL_BlendFunc(GL_ONE, GL_ONE);
3656 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3657 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3658 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3659 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3661 else if (r_bloomstate.texture_bloom)
3663 // render simple bloom effect
3664 // copy the screen and shrink it and darken it for the bloom process
3665 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3666 // make the bloom texture
3667 R_Bloom_MakeTexture();
3668 // put the original screen image back in place and blend the bloom
3670 R_ResetViewRendering2D();
3671 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3672 R_Mesh_ColorPointer(NULL, 0, 0);
3673 GL_Color(1, 1, 1, 1);
3674 GL_BlendFunc(GL_ONE, GL_ZERO);
3675 // do both in one pass if possible
3676 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3677 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3678 if (r_textureunits.integer >= 2 && gl_combine.integer)
3680 R_SetupGenericTwoTextureShader(GL_ADD);
3681 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3682 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3686 R_SetupGenericShader(true);
3687 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3688 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3689 // now blend on the bloom texture
3690 GL_BlendFunc(GL_ONE, GL_ONE);
3691 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3692 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3694 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3695 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3697 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3699 // apply a color tint to the whole view
3700 R_ResetViewRendering2D();
3701 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3702 R_Mesh_ColorPointer(NULL, 0, 0);
3703 R_SetupGenericShader(false);
3704 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3705 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3706 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3710 matrix4x4_t r_waterscrollmatrix;
3712 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3714 if (r_refdef.fog_density)
3716 r_refdef.fogcolor[0] = r_refdef.fog_red;
3717 r_refdef.fogcolor[1] = r_refdef.fog_green;
3718 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3722 VectorCopy(r_refdef.fogcolor, fogvec);
3723 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3725 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3726 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3727 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3728 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3730 // color.rgb *= ContrastBoost * SceneBrightness;
3731 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3732 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3733 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3734 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3739 void R_UpdateVariables(void)
3743 r_refdef.scene.ambient = r_ambient.value;
3745 r_refdef.farclip = 4096;
3746 if (r_refdef.scene.worldmodel)
3747 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3748 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3750 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3751 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3752 r_refdef.polygonfactor = 0;
3753 r_refdef.polygonoffset = 0;
3754 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3755 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3757 r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
3758 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3759 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3760 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3761 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3762 if (r_showsurfaces.integer)
3764 r_refdef.scene.rtworld = false;
3765 r_refdef.scene.rtworldshadows = false;
3766 r_refdef.scene.rtdlight = false;
3767 r_refdef.scene.rtdlightshadows = false;
3768 r_refdef.lightmapintensity = 0;
3771 if (gamemode == GAME_NEHAHRA)
3773 if (gl_fogenable.integer)
3775 r_refdef.oldgl_fogenable = true;
3776 r_refdef.fog_density = gl_fogdensity.value;
3777 r_refdef.fog_red = gl_fogred.value;
3778 r_refdef.fog_green = gl_foggreen.value;
3779 r_refdef.fog_blue = gl_fogblue.value;
3780 r_refdef.fog_alpha = 1;
3781 r_refdef.fog_start = 0;
3782 r_refdef.fog_end = gl_skyclip.value;
3784 else if (r_refdef.oldgl_fogenable)
3786 r_refdef.oldgl_fogenable = false;
3787 r_refdef.fog_density = 0;
3788 r_refdef.fog_red = 0;
3789 r_refdef.fog_green = 0;
3790 r_refdef.fog_blue = 0;
3791 r_refdef.fog_alpha = 0;
3792 r_refdef.fog_start = 0;
3793 r_refdef.fog_end = 0;
3797 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3798 r_refdef.fog_start = max(0, r_refdef.fog_start);
3799 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3801 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3803 if (r_refdef.fog_density && r_drawfog.integer)
3805 r_refdef.fogenabled = true;
3806 // this is the point where the fog reaches 0.9986 alpha, which we
3807 // consider a good enough cutoff point for the texture
3808 // (0.9986 * 256 == 255.6)
3809 if (r_fog_exp2.integer)
3810 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3812 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3813 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3814 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3815 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3816 // fog color was already set
3817 // update the fog texture
3818 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)
3819 R_BuildFogTexture();
3822 r_refdef.fogenabled = false;
3824 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
3826 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
3828 // build GLSL gamma texture
3829 #define RAMPWIDTH 256
3830 unsigned short ramp[RAMPWIDTH * 3];
3831 unsigned char rampbgr[RAMPWIDTH][4];
3834 r_texture_gammaramps_serial = vid_gammatables_serial;
3836 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
3837 for(i = 0; i < RAMPWIDTH; ++i)
3839 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3840 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
3841 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
3844 if (r_texture_gammaramps)
3846 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
3850 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);
3856 // remove GLSL gamma texture
3860 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3861 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3867 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3868 if( scenetype != r_currentscenetype ) {
3869 // store the old scenetype
3870 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3871 r_currentscenetype = scenetype;
3872 // move in the new scene
3873 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3882 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3884 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3885 if( scenetype == r_currentscenetype ) {
3886 return &r_refdef.scene;
3888 return &r_scenes_store[ scenetype ];
3897 void R_RenderView(void)
3899 r_frame++; // used only by R_GetCurrentTexture
3900 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3902 if (r_refdef.view.isoverlay)
3904 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
3905 GL_Clear( GL_DEPTH_BUFFER_BIT );
3906 R_TimeReport("depthclear");
3908 r_refdef.view.showdebug = false;
3910 r_waterstate.enabled = false;
3911 r_waterstate.numwaterplanes = 0;
3919 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
3920 return; //Host_Error ("R_RenderView: NULL worldmodel");
3922 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3924 // break apart the view matrix into vectors for various purposes
3925 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3926 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3927 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3928 VectorNegate(r_refdef.view.left, r_refdef.view.right);
3929 // make an inverted copy of the view matrix for tracking sprites
3930 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3932 R_Shadow_UpdateWorldLightSelection();
3934 R_Bloom_StartFrame();
3935 R_Water_StartFrame();
3938 if (r_timereport_active)
3939 R_TimeReport("viewsetup");
3941 R_ResetViewRendering3D();
3943 if (r_refdef.view.clear || r_refdef.fogenabled)
3945 R_ClearScreen(r_refdef.fogenabled);
3946 if (r_timereport_active)
3947 R_TimeReport("viewclear");
3949 r_refdef.view.clear = true;
3951 // this produces a bloom texture to be used in R_BlendView() later
3953 R_HDR_RenderBloomTexture();
3955 r_refdef.view.showdebug = true;
3958 if (r_timereport_active)
3959 R_TimeReport("visibility");
3961 r_waterstate.numwaterplanes = 0;
3962 if (r_waterstate.enabled)
3963 R_RenderWaterPlanes();
3966 r_waterstate.numwaterplanes = 0;
3969 if (r_timereport_active)
3970 R_TimeReport("blendview");
3972 GL_Scissor(0, 0, vid.width, vid.height);
3973 GL_ScissorTest(false);
3977 void R_RenderWaterPlanes(void)
3979 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3981 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3982 if (r_timereport_active)
3983 R_TimeReport("waterworld");
3986 // don't let sound skip if going slow
3987 if (r_refdef.scene.extraupdate)
3990 R_DrawModelsAddWaterPlanes();
3991 if (r_timereport_active)
3992 R_TimeReport("watermodels");
3994 if (r_waterstate.numwaterplanes)
3996 R_Water_ProcessPlanes();
3997 if (r_timereport_active)
3998 R_TimeReport("waterscenes");
4002 extern void R_DrawLightningBeams (void);
4003 extern void VM_CL_AddPolygonsToMeshQueue (void);
4004 extern void R_DrawPortals (void);
4005 extern cvar_t cl_locs_show;
4006 static void R_DrawLocs(void);
4007 static void R_DrawEntityBBoxes(void);
4008 void R_RenderScene(void)
4010 r_refdef.stats.renders++;
4014 // don't let sound skip if going slow
4015 if (r_refdef.scene.extraupdate)
4018 R_MeshQueue_BeginScene();
4022 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);
4024 if (cl.csqc_vidvars.drawworld)
4026 // don't let sound skip if going slow
4027 if (r_refdef.scene.extraupdate)
4030 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4032 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4033 if (r_timereport_active)
4034 R_TimeReport("worldsky");
4037 if (R_DrawBrushModelsSky() && r_timereport_active)
4038 R_TimeReport("bmodelsky");
4041 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4043 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4044 if (r_timereport_active)
4045 R_TimeReport("worlddepth");
4047 if (r_depthfirst.integer >= 2)
4049 R_DrawModelsDepth();
4050 if (r_timereport_active)
4051 R_TimeReport("modeldepth");
4054 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4056 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4057 if (r_timereport_active)
4058 R_TimeReport("world");
4061 // don't let sound skip if going slow
4062 if (r_refdef.scene.extraupdate)
4066 if (r_timereport_active)
4067 R_TimeReport("models");
4069 // don't let sound skip if going slow
4070 if (r_refdef.scene.extraupdate)
4073 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
4075 R_DrawModelShadows();
4077 R_ResetViewRendering3D();
4079 // don't let sound skip if going slow
4080 if (r_refdef.scene.extraupdate)
4084 R_ShadowVolumeLighting(false);
4085 if (r_timereport_active)
4086 R_TimeReport("rtlights");
4088 // don't let sound skip if going slow
4089 if (r_refdef.scene.extraupdate)
4092 if (cl.csqc_vidvars.drawworld)
4094 R_DrawLightningBeams();
4095 if (r_timereport_active)
4096 R_TimeReport("lightning");
4099 if (r_timereport_active)
4100 R_TimeReport("decals");
4103 if (r_timereport_active)
4104 R_TimeReport("particles");
4107 if (r_timereport_active)
4108 R_TimeReport("explosions");
4111 R_SetupGenericShader(true);
4112 VM_CL_AddPolygonsToMeshQueue();
4114 if (r_refdef.view.showdebug)
4116 if (cl_locs_show.integer)
4119 if (r_timereport_active)
4120 R_TimeReport("showlocs");
4123 if (r_drawportals.integer)
4126 if (r_timereport_active)
4127 R_TimeReport("portals");
4130 if (r_showbboxes.value > 0)
4132 R_DrawEntityBBoxes();
4133 if (r_timereport_active)
4134 R_TimeReport("bboxes");
4138 R_SetupGenericShader(true);
4139 R_MeshQueue_RenderTransparent();
4140 if (r_timereport_active)
4141 R_TimeReport("drawtrans");
4143 R_SetupGenericShader(true);
4145 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))
4147 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4148 if (r_timereport_active)
4149 R_TimeReport("worlddebug");
4150 R_DrawModelsDebug();
4151 if (r_timereport_active)
4152 R_TimeReport("modeldebug");
4155 R_SetupGenericShader(true);
4157 if (cl.csqc_vidvars.drawworld)
4160 if (r_timereport_active)
4161 R_TimeReport("coronas");
4164 // don't let sound skip if going slow
4165 if (r_refdef.scene.extraupdate)
4168 R_ResetViewRendering2D();
4171 static const unsigned short bboxelements[36] =
4181 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4184 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4185 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4186 GL_DepthMask(false);
4187 GL_DepthRange(0, 1);
4188 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4189 R_Mesh_Matrix(&identitymatrix);
4190 R_Mesh_ResetTextureState();
4192 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4193 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4194 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4195 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4196 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4197 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4198 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4199 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4200 R_FillColors(color4f, 8, cr, cg, cb, ca);
4201 if (r_refdef.fogenabled)
4203 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4205 f1 = FogPoint_World(v);
4207 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4208 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4209 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4212 R_Mesh_VertexPointer(vertex3f, 0, 0);
4213 R_Mesh_ColorPointer(color4f, 0, 0);
4214 R_Mesh_ResetTextureState();
4215 R_SetupGenericShader(false);
4216 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4219 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4223 prvm_edict_t *edict;
4224 prvm_prog_t *prog_save = prog;
4226 // this function draws bounding boxes of server entities
4230 GL_CullFace(GL_NONE);
4231 R_SetupGenericShader(false);
4235 for (i = 0;i < numsurfaces;i++)
4237 edict = PRVM_EDICT_NUM(surfacelist[i]);
4238 switch ((int)edict->fields.server->solid)
4240 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4241 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4242 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4243 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4244 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4245 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4247 color[3] *= r_showbboxes.value;
4248 color[3] = bound(0, color[3], 1);
4249 GL_DepthTest(!r_showdisabledepthtest.integer);
4250 GL_CullFace(r_refdef.view.cullface_front);
4251 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4257 static void R_DrawEntityBBoxes(void)
4260 prvm_edict_t *edict;
4262 prvm_prog_t *prog_save = prog;
4264 // this function draws bounding boxes of server entities
4270 for (i = 0;i < prog->num_edicts;i++)
4272 edict = PRVM_EDICT_NUM(i);
4273 if (edict->priv.server->free)
4275 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4276 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4278 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4280 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4281 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4287 unsigned short nomodelelements[24] =
4299 float nomodelvertex3f[6*3] =
4309 float nomodelcolor4f[6*4] =
4311 0.0f, 0.0f, 0.5f, 1.0f,
4312 0.0f, 0.0f, 0.5f, 1.0f,
4313 0.0f, 0.5f, 0.0f, 1.0f,
4314 0.0f, 0.5f, 0.0f, 1.0f,
4315 0.5f, 0.0f, 0.0f, 1.0f,
4316 0.5f, 0.0f, 0.0f, 1.0f
4319 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4324 // this is only called once per entity so numsurfaces is always 1, and
4325 // surfacelist is always {0}, so this code does not handle batches
4326 R_Mesh_Matrix(&ent->matrix);
4328 if (ent->flags & EF_ADDITIVE)
4330 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4331 GL_DepthMask(false);
4333 else if (ent->alpha < 1)
4335 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4336 GL_DepthMask(false);
4340 GL_BlendFunc(GL_ONE, GL_ZERO);
4343 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4344 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4345 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4346 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4347 R_SetupGenericShader(false);
4348 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4349 if (r_refdef.fogenabled)
4352 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4353 R_Mesh_ColorPointer(color4f, 0, 0);
4354 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4355 f1 = FogPoint_World(org);
4357 for (i = 0, c = color4f;i < 6;i++, c += 4)
4359 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4360 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4361 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4365 else if (ent->alpha != 1)
4367 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4368 R_Mesh_ColorPointer(color4f, 0, 0);
4369 for (i = 0, c = color4f;i < 6;i++, c += 4)
4373 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4374 R_Mesh_ResetTextureState();
4375 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4378 void R_DrawNoModel(entity_render_t *ent)
4381 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4382 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4383 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4385 // R_DrawNoModelCallback(ent, 0);
4388 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4390 vec3_t right1, right2, diff, normal;
4392 VectorSubtract (org2, org1, normal);
4394 // calculate 'right' vector for start
4395 VectorSubtract (r_refdef.view.origin, org1, diff);
4396 CrossProduct (normal, diff, right1);
4397 VectorNormalize (right1);
4399 // calculate 'right' vector for end
4400 VectorSubtract (r_refdef.view.origin, org2, diff);
4401 CrossProduct (normal, diff, right2);
4402 VectorNormalize (right2);
4404 vert[ 0] = org1[0] + width * right1[0];
4405 vert[ 1] = org1[1] + width * right1[1];
4406 vert[ 2] = org1[2] + width * right1[2];
4407 vert[ 3] = org1[0] - width * right1[0];
4408 vert[ 4] = org1[1] - width * right1[1];
4409 vert[ 5] = org1[2] - width * right1[2];
4410 vert[ 6] = org2[0] - width * right2[0];
4411 vert[ 7] = org2[1] - width * right2[1];
4412 vert[ 8] = org2[2] - width * right2[2];
4413 vert[ 9] = org2[0] + width * right2[0];
4414 vert[10] = org2[1] + width * right2[1];
4415 vert[11] = org2[2] + width * right2[2];
4418 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4420 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)
4422 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4426 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4427 fog = FogPoint_World(origin);
4429 R_Mesh_Matrix(&identitymatrix);
4430 GL_BlendFunc(blendfunc1, blendfunc2);
4432 GL_CullFace(GL_NONE);
4434 GL_DepthMask(false);
4435 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4436 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4437 GL_DepthTest(!depthdisable);
4439 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4440 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4441 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4442 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4443 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4444 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4445 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4446 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4447 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4448 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4449 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4450 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4452 R_Mesh_VertexPointer(vertex3f, 0, 0);
4453 R_Mesh_ColorPointer(NULL, 0, 0);
4454 R_Mesh_ResetTextureState();
4455 R_SetupGenericShader(true);
4456 R_Mesh_TexBind(0, R_GetTexture(texture));
4457 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4458 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4459 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4460 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4462 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4464 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4465 GL_BlendFunc(blendfunc1, GL_ONE);
4467 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4468 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4472 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4477 VectorSet(v, x, y, z);
4478 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4479 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4481 if (i == mesh->numvertices)
4483 if (mesh->numvertices < mesh->maxvertices)
4485 VectorCopy(v, vertex3f);
4486 mesh->numvertices++;
4488 return mesh->numvertices;
4494 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4498 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4499 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4500 e = mesh->element3i + mesh->numtriangles * 3;
4501 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4503 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4504 if (mesh->numtriangles < mesh->maxtriangles)
4509 mesh->numtriangles++;
4511 element[1] = element[2];
4515 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4519 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4520 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4521 e = mesh->element3i + mesh->numtriangles * 3;
4522 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4524 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4525 if (mesh->numtriangles < mesh->maxtriangles)
4530 mesh->numtriangles++;
4532 element[1] = element[2];
4536 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4537 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4539 int planenum, planenum2;
4542 mplane_t *plane, *plane2;
4544 double temppoints[2][256*3];
4545 // figure out how large a bounding box we need to properly compute this brush
4547 for (w = 0;w < numplanes;w++)
4548 maxdist = max(maxdist, planes[w].dist);
4549 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4550 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4551 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4555 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4556 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4558 if (planenum2 == planenum)
4560 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);
4563 if (tempnumpoints < 3)
4565 // generate elements forming a triangle fan for this polygon
4566 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4570 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)
4572 texturelayer_t *layer;
4573 layer = t->currentlayers + t->currentnumlayers++;
4575 layer->depthmask = depthmask;
4576 layer->blendfunc1 = blendfunc1;
4577 layer->blendfunc2 = blendfunc2;
4578 layer->texture = texture;
4579 layer->texmatrix = *matrix;
4580 layer->color[0] = r * r_refdef.view.colorscale;
4581 layer->color[1] = g * r_refdef.view.colorscale;
4582 layer->color[2] = b * r_refdef.view.colorscale;
4583 layer->color[3] = a;
4586 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4589 index = parms[2] + r_refdef.scene.time * parms[3];
4590 index -= floor(index);
4594 case Q3WAVEFUNC_NONE:
4595 case Q3WAVEFUNC_NOISE:
4596 case Q3WAVEFUNC_COUNT:
4599 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4600 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4601 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4602 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4603 case Q3WAVEFUNC_TRIANGLE:
4605 f = index - floor(index);
4616 return (float)(parms[0] + parms[1] * f);
4619 texture_t *R_GetCurrentTexture(texture_t *t)
4623 const entity_render_t *ent = rsurface.entity;
4624 dp_model_t *model = ent->model;
4627 q3shaderinfo_layer_tcmod_t *tcmod;
4629 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
4630 return t->currentframe;
4631 t->update_lastrenderframe = r_frame;
4632 t->update_lastrenderentity = (void *)ent;
4634 // switch to an alternate material if this is a q1bsp animated material
4636 texture_t *texture = t;
4637 int s = ent->skinnum;
4638 if ((unsigned int)s >= (unsigned int)model->numskins)
4640 if (model->skinscenes)
4642 if (model->skinscenes[s].framecount > 1)
4643 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4645 s = model->skinscenes[s].firstframe;
4648 t = t + s * model->num_surfaces;
4651 // use an alternate animation if the entity's frame is not 0,
4652 // and only if the texture has an alternate animation
4653 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
4654 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4656 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4658 texture->currentframe = t;
4661 // update currentskinframe to be a qw skin or animation frame
4662 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"))
4664 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4666 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4667 if (developer_loading.integer)
4668 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4669 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);
4671 t->currentskinframe = r_qwskincache_skinframe[i];
4672 if (t->currentskinframe == NULL)
4673 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4675 else if (t->numskinframes >= 2)
4676 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
4677 if (t->backgroundnumskinframes >= 2)
4678 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
4680 t->currentmaterialflags = t->basematerialflags;
4681 t->currentalpha = ent->alpha;
4682 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4683 t->currentalpha *= r_wateralpha.value;
4684 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4685 t->currentalpha *= t->r_water_wateralpha;
4686 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4687 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4688 if (!(ent->flags & RENDER_LIGHT))
4689 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4690 else if (rsurface.modeltexcoordlightmap2f == NULL)
4692 // pick a model lighting mode
4693 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4694 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4696 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4698 if (ent->effects & EF_ADDITIVE)
4699 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4700 else if (t->currentalpha < 1)
4701 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4702 if (ent->effects & EF_DOUBLESIDED)
4703 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4704 if (ent->effects & EF_NODEPTHTEST)
4705 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4706 if (ent->flags & RENDER_VIEWMODEL)
4707 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4708 if (t->backgroundnumskinframes)
4709 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4710 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4712 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4713 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4716 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4718 // there is no tcmod
4719 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4720 t->currenttexmatrix = r_waterscrollmatrix;
4722 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4725 switch(tcmod->tcmod)
4729 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4730 matrix = r_waterscrollmatrix;
4732 matrix = identitymatrix;
4734 case Q3TCMOD_ENTITYTRANSLATE:
4735 // this is used in Q3 to allow the gamecode to control texcoord
4736 // scrolling on the entity, which is not supported in darkplaces yet.
4737 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4739 case Q3TCMOD_ROTATE:
4740 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4741 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4742 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4745 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4747 case Q3TCMOD_SCROLL:
4748 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4750 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4751 w = (int) tcmod->parms[0];
4752 h = (int) tcmod->parms[1];
4753 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4755 idx = (int) floor(f * w * h);
4756 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4758 case Q3TCMOD_STRETCH:
4759 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4760 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4762 case Q3TCMOD_TRANSFORM:
4763 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4764 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4765 VectorSet(tcmat + 6, 0 , 0 , 1);
4766 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4767 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4769 case Q3TCMOD_TURBULENT:
4770 // this is handled in the RSurf_PrepareVertices function
4771 matrix = identitymatrix;
4774 // either replace or concatenate the transformation
4776 t->currenttexmatrix = matrix;
4779 matrix4x4_t temp = t->currenttexmatrix;
4780 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4784 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4785 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4786 t->glosstexture = r_texture_black;
4787 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4788 t->backgroundglosstexture = r_texture_black;
4789 t->specularpower = r_shadow_glossexponent.value;
4790 // TODO: store reference values for these in the texture?
4791 t->specularscale = 0;
4792 if (r_shadow_gloss.integer > 0)
4794 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4796 if (r_shadow_glossintensity.value > 0)
4798 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4799 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4800 t->specularscale = r_shadow_glossintensity.value;
4803 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4805 t->glosstexture = r_texture_white;
4806 t->backgroundglosstexture = r_texture_white;
4807 t->specularscale = r_shadow_gloss2intensity.value;
4811 // lightmaps mode looks bad with dlights using actual texturing, so turn
4812 // off the colormap and glossmap, but leave the normalmap on as it still
4813 // accurately represents the shading involved
4814 if (gl_lightmaps.integer)
4816 t->basetexture = r_texture_grey128;
4817 t->backgroundbasetexture = NULL;
4818 t->specularscale = 0;
4819 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
4822 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4823 VectorClear(t->dlightcolor);
4824 t->currentnumlayers = 0;
4825 if (t->currentmaterialflags & MATERIALFLAG_WALL)
4828 int blendfunc1, blendfunc2, depthmask;
4829 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4831 blendfunc1 = GL_SRC_ALPHA;
4832 blendfunc2 = GL_ONE;
4834 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4836 blendfunc1 = GL_SRC_ALPHA;
4837 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4839 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4841 blendfunc1 = t->customblendfunc[0];
4842 blendfunc2 = t->customblendfunc[1];
4846 blendfunc1 = GL_ONE;
4847 blendfunc2 = GL_ZERO;
4849 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4850 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4851 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4852 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4854 // fullbright is not affected by r_refdef.lightmapintensity
4855 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]);
4856 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4857 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]);
4858 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4859 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]);
4863 vec3_t ambientcolor;
4865 // set the color tint used for lights affecting this surface
4866 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4868 // q3bsp has no lightmap updates, so the lightstylevalue that
4869 // would normally be baked into the lightmap must be
4870 // applied to the color
4871 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4872 if (ent->model->type == mod_brushq3)
4873 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4874 colorscale *= r_refdef.lightmapintensity;
4875 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
4876 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4877 // basic lit geometry
4878 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]);
4879 // add pants/shirt if needed
4880 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4881 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]);
4882 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4883 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]);
4884 // now add ambient passes if needed
4885 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4887 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]);
4888 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4889 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]);
4890 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4891 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]);
4894 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4895 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]);
4896 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4898 // if this is opaque use alpha blend which will darken the earlier
4901 // if this is an alpha blended material, all the earlier passes
4902 // were darkened by fog already, so we only need to add the fog
4903 // color ontop through the fog mask texture
4905 // if this is an additive blended material, all the earlier passes
4906 // were darkened by fog already, and we should not add fog color
4907 // (because the background was not darkened, there is no fog color
4908 // that was lost behind it).
4909 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]);
4913 return t->currentframe;
4916 rsurfacestate_t rsurface;
4918 void R_Mesh_ResizeArrays(int newvertices)
4921 if (rsurface.array_size >= newvertices)
4923 if (rsurface.array_modelvertex3f)
4924 Mem_Free(rsurface.array_modelvertex3f);
4925 rsurface.array_size = (newvertices + 1023) & ~1023;
4926 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4927 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4928 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4929 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4930 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4931 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4932 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4933 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4934 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4935 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4936 rsurface.array_color4f = base + rsurface.array_size * 27;
4937 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4940 void RSurf_ActiveWorldEntity(void)
4942 dp_model_t *model = r_refdef.scene.worldmodel;
4943 //if (rsurface.entity == r_refdef.scene.worldentity)
4945 rsurface.entity = r_refdef.scene.worldentity;
4946 if (rsurface.array_size < model->surfmesh.num_vertices)
4947 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4948 rsurface.matrix = identitymatrix;
4949 rsurface.inversematrix = identitymatrix;
4950 R_Mesh_Matrix(&identitymatrix);
4951 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4952 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4953 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4954 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4955 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4956 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4957 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
4958 rsurface.frameblend[0].lerp = 1;
4959 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4960 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4961 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4962 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4963 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4964 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4965 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4966 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4967 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4968 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4969 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4970 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4971 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4972 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4973 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4974 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4975 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4976 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4977 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4978 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4979 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4980 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4981 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4982 rsurface.modelelement3i = model->surfmesh.data_element3i;
4983 rsurface.modelelement3s = model->surfmesh.data_element3s;
4984 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
4985 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
4986 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4987 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4988 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4989 rsurface.modelsurfaces = model->data_surfaces;
4990 rsurface.generatedvertex = false;
4991 rsurface.vertex3f = rsurface.modelvertex3f;
4992 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4993 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4994 rsurface.svector3f = rsurface.modelsvector3f;
4995 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4996 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4997 rsurface.tvector3f = rsurface.modeltvector3f;
4998 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4999 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5000 rsurface.normal3f = rsurface.modelnormal3f;
5001 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5002 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5003 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5006 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5008 dp_model_t *model = ent->model;
5009 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5011 rsurface.entity = (entity_render_t *)ent;
5012 if (rsurface.array_size < model->surfmesh.num_vertices)
5013 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5014 rsurface.matrix = ent->matrix;
5015 rsurface.inversematrix = ent->inversematrix;
5016 R_Mesh_Matrix(&rsurface.matrix);
5017 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5018 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5019 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5020 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5021 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5022 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5023 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5024 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5025 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5026 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5027 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5028 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5029 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5030 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5031 if (ent->model->brush.submodel)
5033 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5034 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5036 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5040 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5041 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5042 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5043 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5044 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5046 else if (wantnormals)
5048 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5049 rsurface.modelsvector3f = NULL;
5050 rsurface.modeltvector3f = NULL;
5051 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5052 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5056 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5057 rsurface.modelsvector3f = NULL;
5058 rsurface.modeltvector3f = NULL;
5059 rsurface.modelnormal3f = NULL;
5060 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5062 rsurface.modelvertex3f_bufferobject = 0;
5063 rsurface.modelvertex3f_bufferoffset = 0;
5064 rsurface.modelsvector3f_bufferobject = 0;
5065 rsurface.modelsvector3f_bufferoffset = 0;
5066 rsurface.modeltvector3f_bufferobject = 0;
5067 rsurface.modeltvector3f_bufferoffset = 0;
5068 rsurface.modelnormal3f_bufferobject = 0;
5069 rsurface.modelnormal3f_bufferoffset = 0;
5070 rsurface.generatedvertex = true;
5074 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5075 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5076 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5077 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5078 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5079 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5080 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5081 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5082 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5083 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5084 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5085 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5086 rsurface.generatedvertex = false;
5088 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5089 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5090 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5091 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5092 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5093 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5094 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5095 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5096 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5097 rsurface.modelelement3i = model->surfmesh.data_element3i;
5098 rsurface.modelelement3s = model->surfmesh.data_element3s;
5099 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5100 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5101 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5102 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5103 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5104 rsurface.modelsurfaces = model->data_surfaces;
5105 rsurface.vertex3f = rsurface.modelvertex3f;
5106 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5107 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5108 rsurface.svector3f = rsurface.modelsvector3f;
5109 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5110 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5111 rsurface.tvector3f = rsurface.modeltvector3f;
5112 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5113 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5114 rsurface.normal3f = rsurface.modelnormal3f;
5115 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5116 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5117 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5120 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5121 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5124 int texturesurfaceindex;
5129 const float *v1, *in_tc;
5131 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5133 q3shaderinfo_deform_t *deform;
5134 // 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
5135 if (rsurface.generatedvertex)
5137 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5138 generatenormals = true;
5139 for (i = 0;i < Q3MAXDEFORMS;i++)
5141 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5143 generatetangents = true;
5144 generatenormals = true;
5146 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5147 generatenormals = true;
5149 if (generatenormals && !rsurface.modelnormal3f)
5151 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5152 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5153 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5154 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5156 if (generatetangents && !rsurface.modelsvector3f)
5158 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5159 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5160 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5161 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5162 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5163 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5164 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);
5167 rsurface.vertex3f = rsurface.modelvertex3f;
5168 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5169 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5170 rsurface.svector3f = rsurface.modelsvector3f;
5171 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5172 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5173 rsurface.tvector3f = rsurface.modeltvector3f;
5174 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5175 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5176 rsurface.normal3f = rsurface.modelnormal3f;
5177 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5178 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5179 // if vertices are deformed (sprite flares and things in maps, possibly
5180 // water waves, bulges and other deformations), generate them into
5181 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5182 // (may be static model data or generated data for an animated model, or
5183 // the previous deform pass)
5184 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5186 switch (deform->deform)
5189 case Q3DEFORM_PROJECTIONSHADOW:
5190 case Q3DEFORM_TEXT0:
5191 case Q3DEFORM_TEXT1:
5192 case Q3DEFORM_TEXT2:
5193 case Q3DEFORM_TEXT3:
5194 case Q3DEFORM_TEXT4:
5195 case Q3DEFORM_TEXT5:
5196 case Q3DEFORM_TEXT6:
5197 case Q3DEFORM_TEXT7:
5200 case Q3DEFORM_AUTOSPRITE:
5201 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5202 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5203 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5204 VectorNormalize(newforward);
5205 VectorNormalize(newright);
5206 VectorNormalize(newup);
5207 // make deformed versions of only the model vertices used by the specified surfaces
5208 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5210 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5211 // a single autosprite surface can contain multiple sprites...
5212 for (j = 0;j < surface->num_vertices - 3;j += 4)
5214 VectorClear(center);
5215 for (i = 0;i < 4;i++)
5216 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5217 VectorScale(center, 0.25f, center);
5218 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5219 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5220 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5221 for (i = 0;i < 4;i++)
5223 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5224 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5227 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);
5228 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);
5230 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5231 rsurface.vertex3f_bufferobject = 0;
5232 rsurface.vertex3f_bufferoffset = 0;
5233 rsurface.svector3f = rsurface.array_deformedsvector3f;
5234 rsurface.svector3f_bufferobject = 0;
5235 rsurface.svector3f_bufferoffset = 0;
5236 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5237 rsurface.tvector3f_bufferobject = 0;
5238 rsurface.tvector3f_bufferoffset = 0;
5239 rsurface.normal3f = rsurface.array_deformednormal3f;
5240 rsurface.normal3f_bufferobject = 0;
5241 rsurface.normal3f_bufferoffset = 0;
5243 case Q3DEFORM_AUTOSPRITE2:
5244 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5245 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5246 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5247 VectorNormalize(newforward);
5248 VectorNormalize(newright);
5249 VectorNormalize(newup);
5250 // make deformed versions of only the model vertices used by the specified surfaces
5251 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5253 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5254 const float *v1, *v2;
5264 memset(shortest, 0, sizeof(shortest));
5265 // a single autosprite surface can contain multiple sprites...
5266 for (j = 0;j < surface->num_vertices - 3;j += 4)
5268 VectorClear(center);
5269 for (i = 0;i < 4;i++)
5270 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5271 VectorScale(center, 0.25f, center);
5272 // find the two shortest edges, then use them to define the
5273 // axis vectors for rotating around the central axis
5274 for (i = 0;i < 6;i++)
5276 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5277 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5279 Debug_PolygonBegin(NULL, 0);
5280 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5281 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);
5282 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5285 l = VectorDistance2(v1, v2);
5286 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5288 l += (1.0f / 1024.0f);
5289 if (shortest[0].length2 > l || i == 0)
5291 shortest[1] = shortest[0];
5292 shortest[0].length2 = l;
5293 shortest[0].v1 = v1;
5294 shortest[0].v2 = v2;
5296 else if (shortest[1].length2 > l || i == 1)
5298 shortest[1].length2 = l;
5299 shortest[1].v1 = v1;
5300 shortest[1].v2 = v2;
5303 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5304 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5306 Debug_PolygonBegin(NULL, 0);
5307 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5308 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);
5309 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5312 // this calculates the right vector from the shortest edge
5313 // and the up vector from the edge midpoints
5314 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5315 VectorNormalize(right);
5316 VectorSubtract(end, start, up);
5317 VectorNormalize(up);
5318 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5319 //VectorSubtract(rsurface.modelorg, center, forward);
5320 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5321 VectorNegate(forward, forward);
5322 VectorReflect(forward, 0, up, forward);
5323 VectorNormalize(forward);
5324 CrossProduct(up, forward, newright);
5325 VectorNormalize(newright);
5327 Debug_PolygonBegin(NULL, 0);
5328 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);
5329 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5330 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5334 Debug_PolygonBegin(NULL, 0);
5335 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5336 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[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);
5340 // rotate the quad around the up axis vector, this is made
5341 // especially easy by the fact we know the quad is flat,
5342 // so we only have to subtract the center position and
5343 // measure distance along the right vector, and then
5344 // multiply that by the newright vector and add back the
5346 // we also need to subtract the old position to undo the
5347 // displacement from the center, which we do with a
5348 // DotProduct, the subtraction/addition of center is also
5349 // optimized into DotProducts here
5350 l = DotProduct(right, center);
5351 for (i = 0;i < 4;i++)
5353 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5354 f = DotProduct(right, v1) - l;
5355 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5358 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);
5359 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);
5361 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5362 rsurface.vertex3f_bufferobject = 0;
5363 rsurface.vertex3f_bufferoffset = 0;
5364 rsurface.svector3f = rsurface.array_deformedsvector3f;
5365 rsurface.svector3f_bufferobject = 0;
5366 rsurface.svector3f_bufferoffset = 0;
5367 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5368 rsurface.tvector3f_bufferobject = 0;
5369 rsurface.tvector3f_bufferoffset = 0;
5370 rsurface.normal3f = rsurface.array_deformednormal3f;
5371 rsurface.normal3f_bufferobject = 0;
5372 rsurface.normal3f_bufferoffset = 0;
5374 case Q3DEFORM_NORMAL:
5375 // deform the normals to make reflections wavey
5376 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5378 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5379 for (j = 0;j < surface->num_vertices;j++)
5382 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5383 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5384 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5385 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5386 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5387 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5388 VectorNormalize(normal);
5390 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);
5392 rsurface.svector3f = rsurface.array_deformedsvector3f;
5393 rsurface.svector3f_bufferobject = 0;
5394 rsurface.svector3f_bufferoffset = 0;
5395 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5396 rsurface.tvector3f_bufferobject = 0;
5397 rsurface.tvector3f_bufferoffset = 0;
5398 rsurface.normal3f = rsurface.array_deformednormal3f;
5399 rsurface.normal3f_bufferobject = 0;
5400 rsurface.normal3f_bufferoffset = 0;
5403 // deform vertex array to make wavey water and flags and such
5404 waveparms[0] = deform->waveparms[0];
5405 waveparms[1] = deform->waveparms[1];
5406 waveparms[2] = deform->waveparms[2];
5407 waveparms[3] = deform->waveparms[3];
5408 // this is how a divisor of vertex influence on deformation
5409 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5410 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5411 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5413 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5414 for (j = 0;j < surface->num_vertices;j++)
5416 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5417 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5418 // if the wavefunc depends on time, evaluate it per-vertex
5421 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5422 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5424 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5427 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5428 rsurface.vertex3f_bufferobject = 0;
5429 rsurface.vertex3f_bufferoffset = 0;
5431 case Q3DEFORM_BULGE:
5432 // deform vertex array to make the surface have moving bulges
5433 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5435 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5436 for (j = 0;j < surface->num_vertices;j++)
5438 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5439 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5442 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5443 rsurface.vertex3f_bufferobject = 0;
5444 rsurface.vertex3f_bufferoffset = 0;
5447 // deform vertex array
5448 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5449 VectorScale(deform->parms, scale, waveparms);
5450 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5452 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5453 for (j = 0;j < surface->num_vertices;j++)
5454 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5456 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5457 rsurface.vertex3f_bufferobject = 0;
5458 rsurface.vertex3f_bufferoffset = 0;
5462 // generate texcoords based on the chosen texcoord source
5463 switch(rsurface.texture->tcgen.tcgen)
5466 case Q3TCGEN_TEXTURE:
5467 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5468 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5469 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5471 case Q3TCGEN_LIGHTMAP:
5472 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5473 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5474 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5476 case Q3TCGEN_VECTOR:
5477 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5479 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5480 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)
5482 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5483 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5486 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5487 rsurface.texcoordtexture2f_bufferobject = 0;
5488 rsurface.texcoordtexture2f_bufferoffset = 0;
5490 case Q3TCGEN_ENVIRONMENT:
5491 // make environment reflections using a spheremap
5492 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5494 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5495 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5496 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5497 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5498 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5500 float l, d, eyedir[3];
5501 VectorSubtract(rsurface.modelorg, vertex, eyedir);
5502 l = 0.5f / VectorLength(eyedir);
5503 d = DotProduct(normal, eyedir)*2;
5504 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
5505 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
5508 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5509 rsurface.texcoordtexture2f_bufferobject = 0;
5510 rsurface.texcoordtexture2f_bufferoffset = 0;
5513 // the only tcmod that needs software vertex processing is turbulent, so
5514 // check for it here and apply the changes if needed
5515 // and we only support that as the first one
5516 // (handling a mixture of turbulent and other tcmods would be problematic
5517 // without punting it entirely to a software path)
5518 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5520 amplitude = rsurface.texture->tcmods[0].parms[1];
5521 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5522 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5524 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5525 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)
5527 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5528 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5531 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5532 rsurface.texcoordtexture2f_bufferobject = 0;
5533 rsurface.texcoordtexture2f_bufferoffset = 0;
5535 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5536 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5537 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5538 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5541 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5544 const msurface_t *surface = texturesurfacelist[0];
5545 const msurface_t *surface2;
5550 // TODO: lock all array ranges before render, rather than on each surface
5551 if (texturenumsurfaces == 1)
5553 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5554 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);
5556 else if (r_batchmode.integer == 2)
5558 #define MAXBATCHTRIANGLES 4096
5559 int batchtriangles = 0;
5560 int batchelements[MAXBATCHTRIANGLES*3];
5561 for (i = 0;i < texturenumsurfaces;i = j)
5563 surface = texturesurfacelist[i];
5565 if (surface->num_triangles > MAXBATCHTRIANGLES)
5567 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);
5570 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5571 batchtriangles = surface->num_triangles;
5572 firstvertex = surface->num_firstvertex;
5573 endvertex = surface->num_firstvertex + surface->num_vertices;
5574 for (;j < texturenumsurfaces;j++)
5576 surface2 = texturesurfacelist[j];
5577 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5579 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5580 batchtriangles += surface2->num_triangles;
5581 firstvertex = min(firstvertex, surface2->num_firstvertex);
5582 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5584 surface2 = texturesurfacelist[j-1];
5585 numvertices = endvertex - firstvertex;
5586 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5589 else if (r_batchmode.integer == 1)
5591 for (i = 0;i < texturenumsurfaces;i = j)
5593 surface = texturesurfacelist[i];
5594 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5595 if (texturesurfacelist[j] != surface2)
5597 surface2 = texturesurfacelist[j-1];
5598 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5599 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5600 GL_LockArrays(surface->num_firstvertex, numvertices);
5601 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5606 for (i = 0;i < texturenumsurfaces;i++)
5608 surface = texturesurfacelist[i];
5609 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5610 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);
5615 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5617 int i, planeindex, vertexindex;
5621 r_waterstate_waterplane_t *p, *bestp;
5622 msurface_t *surface;
5623 if (r_waterstate.renderingscene)
5625 for (i = 0;i < texturenumsurfaces;i++)
5627 surface = texturesurfacelist[i];
5628 if (lightmaptexunit >= 0)
5629 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5630 if (deluxemaptexunit >= 0)
5631 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5632 // pick the closest matching water plane
5635 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5638 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5640 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5641 d += fabs(PlaneDiff(vert, &p->plane));
5643 if (bestd > d || !bestp)
5651 if (refractiontexunit >= 0)
5652 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5653 if (reflectiontexunit >= 0)
5654 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5658 if (refractiontexunit >= 0)
5659 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5660 if (reflectiontexunit >= 0)
5661 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5663 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5664 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);
5668 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5672 const msurface_t *surface = texturesurfacelist[0];
5673 const msurface_t *surface2;
5678 // TODO: lock all array ranges before render, rather than on each surface
5679 if (texturenumsurfaces == 1)
5681 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5682 if (deluxemaptexunit >= 0)
5683 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5684 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5685 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);
5687 else if (r_batchmode.integer == 2)
5689 #define MAXBATCHTRIANGLES 4096
5690 int batchtriangles = 0;
5691 int batchelements[MAXBATCHTRIANGLES*3];
5692 for (i = 0;i < texturenumsurfaces;i = j)
5694 surface = texturesurfacelist[i];
5695 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5696 if (deluxemaptexunit >= 0)
5697 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5699 if (surface->num_triangles > MAXBATCHTRIANGLES)
5701 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5704 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5705 batchtriangles = surface->num_triangles;
5706 firstvertex = surface->num_firstvertex;
5707 endvertex = surface->num_firstvertex + surface->num_vertices;
5708 for (;j < texturenumsurfaces;j++)
5710 surface2 = texturesurfacelist[j];
5711 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5713 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5714 batchtriangles += surface2->num_triangles;
5715 firstvertex = min(firstvertex, surface2->num_firstvertex);
5716 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5718 surface2 = texturesurfacelist[j-1];
5719 numvertices = endvertex - firstvertex;
5720 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5723 else if (r_batchmode.integer == 1)
5726 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5727 for (i = 0;i < texturenumsurfaces;i = j)
5729 surface = texturesurfacelist[i];
5730 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5731 if (texturesurfacelist[j] != surface2)
5733 Con_Printf(" %i", j - i);
5736 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5738 for (i = 0;i < texturenumsurfaces;i = j)
5740 surface = texturesurfacelist[i];
5741 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5742 if (deluxemaptexunit >= 0)
5743 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5744 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5745 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5748 Con_Printf(" %i", j - i);
5750 surface2 = texturesurfacelist[j-1];
5751 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5752 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5753 GL_LockArrays(surface->num_firstvertex, numvertices);
5754 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5762 for (i = 0;i < texturenumsurfaces;i++)
5764 surface = texturesurfacelist[i];
5765 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5766 if (deluxemaptexunit >= 0)
5767 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5768 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5769 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);
5774 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5777 int texturesurfaceindex;
5778 if (r_showsurfaces.integer == 2)
5780 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5782 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5783 for (j = 0;j < surface->num_triangles;j++)
5785 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5786 GL_Color(f, f, f, 1);
5787 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5793 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5795 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5796 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5797 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);
5798 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5799 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);
5804 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
5806 int texturesurfaceindex;
5809 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5811 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5812 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)
5820 rsurface.lightmapcolor4f = rsurface.array_color4f;
5821 rsurface.lightmapcolor4f_bufferobject = 0;
5822 rsurface.lightmapcolor4f_bufferoffset = 0;
5825 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5827 int texturesurfaceindex;
5831 if (rsurface.lightmapcolor4f)
5833 // generate color arrays for the surfaces in this list
5834 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5836 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5837 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)
5839 f = FogPoint_Model(v);
5849 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5851 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5852 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)
5854 f = FogPoint_Model(v);
5862 rsurface.lightmapcolor4f = rsurface.array_color4f;
5863 rsurface.lightmapcolor4f_bufferobject = 0;
5864 rsurface.lightmapcolor4f_bufferoffset = 0;
5867 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
5869 int texturesurfaceindex;
5873 if (!rsurface.lightmapcolor4f)
5875 // generate color arrays for the surfaces in this list
5876 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5878 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5879 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)
5881 f = FogPoint_Model(v);
5882 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
5883 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
5884 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
5888 rsurface.lightmapcolor4f = rsurface.array_color4f;
5889 rsurface.lightmapcolor4f_bufferobject = 0;
5890 rsurface.lightmapcolor4f_bufferoffset = 0;
5893 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5895 int texturesurfaceindex;
5898 if (!rsurface.lightmapcolor4f)
5900 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5902 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5903 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)
5911 rsurface.lightmapcolor4f = rsurface.array_color4f;
5912 rsurface.lightmapcolor4f_bufferobject = 0;
5913 rsurface.lightmapcolor4f_bufferoffset = 0;
5916 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
5918 int texturesurfaceindex;
5921 if (!rsurface.lightmapcolor4f)
5923 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5925 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5926 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)
5928 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
5929 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
5930 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
5934 rsurface.lightmapcolor4f = rsurface.array_color4f;
5935 rsurface.lightmapcolor4f_bufferobject = 0;
5936 rsurface.lightmapcolor4f_bufferoffset = 0;
5939 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5942 rsurface.lightmapcolor4f = NULL;
5943 rsurface.lightmapcolor4f_bufferobject = 0;
5944 rsurface.lightmapcolor4f_bufferoffset = 0;
5945 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5946 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5947 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5948 GL_Color(r, g, b, a);
5949 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5952 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5954 // TODO: optimize applyfog && applycolor case
5955 // just apply fog if necessary, and tint the fog color array if necessary
5956 rsurface.lightmapcolor4f = NULL;
5957 rsurface.lightmapcolor4f_bufferobject = 0;
5958 rsurface.lightmapcolor4f_bufferoffset = 0;
5959 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5960 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5961 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5962 GL_Color(r, g, b, a);
5963 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5966 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5968 int texturesurfaceindex;
5972 if (texturesurfacelist[0]->lightmapinfo)
5974 // generate color arrays for the surfaces in this list
5975 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5977 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5978 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5980 if (surface->lightmapinfo->samples)
5982 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5983 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5984 VectorScale(lm, scale, c);
5985 if (surface->lightmapinfo->styles[1] != 255)
5987 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5989 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5990 VectorMA(c, scale, lm, c);
5991 if (surface->lightmapinfo->styles[2] != 255)
5994 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5995 VectorMA(c, scale, lm, c);
5996 if (surface->lightmapinfo->styles[3] != 255)
5999 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6000 VectorMA(c, scale, lm, c);
6010 rsurface.lightmapcolor4f = rsurface.array_color4f;
6011 rsurface.lightmapcolor4f_bufferobject = 0;
6012 rsurface.lightmapcolor4f_bufferoffset = 0;
6016 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6017 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6018 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6020 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6021 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6022 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6023 GL_Color(r, g, b, a);
6024 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6027 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6029 int texturesurfaceindex;
6032 float *v, *c, *c2, alpha;
6033 vec3_t ambientcolor;
6034 vec3_t diffusecolor;
6038 VectorCopy(rsurface.modellight_lightdir, lightdir);
6039 f = 0.5f * r_refdef.lightmapintensity;
6040 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6041 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6042 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6043 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6044 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6045 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6047 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6049 // generate color arrays for the surfaces in this list
6050 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6052 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6053 int numverts = surface->num_vertices;
6054 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6055 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6056 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6057 // q3-style directional shading
6058 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6060 if ((f = DotProduct(c2, lightdir)) > 0)
6061 VectorMA(ambientcolor, f, diffusecolor, c);
6063 VectorCopy(ambientcolor, c);
6071 rsurface.lightmapcolor4f = rsurface.array_color4f;
6072 rsurface.lightmapcolor4f_bufferobject = 0;
6073 rsurface.lightmapcolor4f_bufferoffset = 0;
6074 *applycolor = false;
6078 *r = ambientcolor[0];
6079 *g = ambientcolor[1];
6080 *b = ambientcolor[2];
6081 rsurface.lightmapcolor4f = NULL;
6082 rsurface.lightmapcolor4f_bufferobject = 0;
6083 rsurface.lightmapcolor4f_bufferoffset = 0;
6087 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6089 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6090 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6091 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6092 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6093 GL_Color(r, g, b, a);
6094 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6097 void RSurf_SetupDepthAndCulling(void)
6099 // submodels are biased to avoid z-fighting with world surfaces that they
6100 // may be exactly overlapping (avoids z-fighting artifacts on certain
6101 // doors and things in Quake maps)
6102 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6103 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6104 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6105 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6108 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6110 // transparent sky would be ridiculous
6111 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6113 R_SetupGenericShader(false);
6116 skyrendernow = false;
6117 // we have to force off the water clipping plane while rendering sky
6121 // restore entity matrix
6122 R_Mesh_Matrix(&rsurface.matrix);
6124 RSurf_SetupDepthAndCulling();
6126 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6127 // skymasking on them, and Quake3 never did sky masking (unlike
6128 // software Quake and software Quake2), so disable the sky masking
6129 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6130 // and skymasking also looks very bad when noclipping outside the
6131 // level, so don't use it then either.
6132 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6134 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6135 R_Mesh_ColorPointer(NULL, 0, 0);
6136 R_Mesh_ResetTextureState();
6137 if (skyrendermasked)
6139 R_SetupDepthOrShadowShader();
6140 // depth-only (masking)
6141 GL_ColorMask(0,0,0,0);
6142 // just to make sure that braindead drivers don't draw
6143 // anything despite that colormask...
6144 GL_BlendFunc(GL_ZERO, GL_ONE);
6148 R_SetupGenericShader(false);
6150 GL_BlendFunc(GL_ONE, GL_ZERO);
6152 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6153 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6154 if (skyrendermasked)
6155 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6157 R_Mesh_ResetTextureState();
6158 GL_Color(1, 1, 1, 1);
6161 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6163 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6166 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6167 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6168 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6169 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6170 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6171 if (rsurface.texture->backgroundcurrentskinframe)
6173 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6174 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6175 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6176 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6178 if(rsurface.texture->colormapping)
6180 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6181 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6183 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6184 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6185 R_Mesh_ColorPointer(NULL, 0, 0);
6187 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6189 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6191 // render background
6192 GL_BlendFunc(GL_ONE, GL_ZERO);
6194 GL_AlphaTest(false);
6196 GL_Color(1, 1, 1, 1);
6197 R_Mesh_ColorPointer(NULL, 0, 0);
6199 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6200 if (r_glsl_permutation)
6202 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6203 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6204 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6205 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6206 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6207 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6208 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);
6210 GL_LockArrays(0, 0);
6212 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6213 GL_DepthMask(false);
6214 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6215 R_Mesh_ColorPointer(NULL, 0, 0);
6217 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6218 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6219 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6222 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6223 if (!r_glsl_permutation)
6226 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6227 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6228 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6229 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6230 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6231 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6233 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6235 GL_BlendFunc(GL_ONE, GL_ZERO);
6237 GL_AlphaTest(false);
6241 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6242 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6243 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6246 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6248 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6249 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);
6251 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6255 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6256 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);
6258 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6260 GL_LockArrays(0, 0);
6263 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6265 // OpenGL 1.3 path - anything not completely ancient
6266 int texturesurfaceindex;
6267 qboolean applycolor;
6271 const texturelayer_t *layer;
6272 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6274 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6277 int layertexrgbscale;
6278 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6280 if (layerindex == 0)
6284 GL_AlphaTest(false);
6285 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6288 GL_DepthMask(layer->depthmask && writedepth);
6289 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6290 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6292 layertexrgbscale = 4;
6293 VectorScale(layer->color, 0.25f, layercolor);
6295 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6297 layertexrgbscale = 2;
6298 VectorScale(layer->color, 0.5f, layercolor);
6302 layertexrgbscale = 1;
6303 VectorScale(layer->color, 1.0f, layercolor);
6305 layercolor[3] = layer->color[3];
6306 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6307 R_Mesh_ColorPointer(NULL, 0, 0);
6308 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6309 switch (layer->type)
6311 case TEXTURELAYERTYPE_LITTEXTURE:
6312 memset(&m, 0, sizeof(m));
6313 m.tex[0] = R_GetTexture(r_texture_white);
6314 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6315 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6316 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6317 m.tex[1] = R_GetTexture(layer->texture);
6318 m.texmatrix[1] = layer->texmatrix;
6319 m.texrgbscale[1] = layertexrgbscale;
6320 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6321 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6322 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6323 R_Mesh_TextureState(&m);
6324 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6325 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6326 else if (rsurface.uselightmaptexture)
6327 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6329 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6331 case TEXTURELAYERTYPE_TEXTURE:
6332 memset(&m, 0, sizeof(m));
6333 m.tex[0] = R_GetTexture(layer->texture);
6334 m.texmatrix[0] = layer->texmatrix;
6335 m.texrgbscale[0] = layertexrgbscale;
6336 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6337 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6338 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6339 R_Mesh_TextureState(&m);
6340 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6342 case TEXTURELAYERTYPE_FOG:
6343 memset(&m, 0, sizeof(m));
6344 m.texrgbscale[0] = layertexrgbscale;
6347 m.tex[0] = R_GetTexture(layer->texture);
6348 m.texmatrix[0] = layer->texmatrix;
6349 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6350 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6351 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6353 R_Mesh_TextureState(&m);
6354 // generate a color array for the fog pass
6355 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6356 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6360 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6361 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)
6363 f = 1 - FogPoint_Model(v);
6364 c[0] = layercolor[0];
6365 c[1] = layercolor[1];
6366 c[2] = layercolor[2];
6367 c[3] = f * layercolor[3];
6370 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6373 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6375 GL_LockArrays(0, 0);
6378 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6380 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6381 GL_AlphaTest(false);
6385 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6387 // OpenGL 1.1 - crusty old voodoo path
6388 int texturesurfaceindex;
6392 const texturelayer_t *layer;
6393 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6395 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6397 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6399 if (layerindex == 0)
6403 GL_AlphaTest(false);
6404 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6407 GL_DepthMask(layer->depthmask && writedepth);
6408 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6409 R_Mesh_ColorPointer(NULL, 0, 0);
6410 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6411 switch (layer->type)
6413 case TEXTURELAYERTYPE_LITTEXTURE:
6414 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6416 // two-pass lit texture with 2x rgbscale
6417 // first the lightmap pass
6418 memset(&m, 0, sizeof(m));
6419 m.tex[0] = R_GetTexture(r_texture_white);
6420 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6421 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6422 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6423 R_Mesh_TextureState(&m);
6424 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6425 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6426 else if (rsurface.uselightmaptexture)
6427 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6429 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6430 GL_LockArrays(0, 0);
6431 // then apply the texture to it
6432 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6433 memset(&m, 0, sizeof(m));
6434 m.tex[0] = R_GetTexture(layer->texture);
6435 m.texmatrix[0] = layer->texmatrix;
6436 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6437 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6438 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6439 R_Mesh_TextureState(&m);
6440 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);
6444 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6445 memset(&m, 0, sizeof(m));
6446 m.tex[0] = R_GetTexture(layer->texture);
6447 m.texmatrix[0] = layer->texmatrix;
6448 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6449 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6450 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6451 R_Mesh_TextureState(&m);
6452 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6453 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);
6455 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);
6458 case TEXTURELAYERTYPE_TEXTURE:
6459 // singletexture unlit texture with transparency support
6460 memset(&m, 0, sizeof(m));
6461 m.tex[0] = R_GetTexture(layer->texture);
6462 m.texmatrix[0] = layer->texmatrix;
6463 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6464 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6465 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6466 R_Mesh_TextureState(&m);
6467 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);
6469 case TEXTURELAYERTYPE_FOG:
6470 // singletexture fogging
6471 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6474 memset(&m, 0, sizeof(m));
6475 m.tex[0] = R_GetTexture(layer->texture);
6476 m.texmatrix[0] = layer->texmatrix;
6477 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6478 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6479 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6480 R_Mesh_TextureState(&m);
6483 R_Mesh_ResetTextureState();
6484 // generate a color array for the fog pass
6485 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6489 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6490 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)
6492 f = 1 - FogPoint_Model(v);
6493 c[0] = layer->color[0];
6494 c[1] = layer->color[1];
6495 c[2] = layer->color[2];
6496 c[3] = f * layer->color[3];
6499 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6502 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6504 GL_LockArrays(0, 0);
6507 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6509 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6510 GL_AlphaTest(false);
6514 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6518 GL_AlphaTest(false);
6519 R_Mesh_ColorPointer(NULL, 0, 0);
6520 R_Mesh_ResetTextureState();
6521 R_SetupGenericShader(false);
6523 if(rsurface.texture && rsurface.texture->currentskinframe)
6524 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6533 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6535 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
6536 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
6537 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
6540 // brighten it up (as texture value 127 means "unlit")
6541 c[0] *= 2 * r_refdef.view.colorscale;
6542 c[1] *= 2 * r_refdef.view.colorscale;
6543 c[2] *= 2 * r_refdef.view.colorscale;
6545 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
6546 c[3] *= r_wateralpha.value;
6548 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
6550 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6551 GL_DepthMask(false);
6553 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6555 GL_BlendFunc(GL_ONE, GL_ONE);
6556 GL_DepthMask(false);
6558 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6560 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
6561 GL_DepthMask(false);
6563 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6565 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
6566 GL_DepthMask(false);
6570 GL_BlendFunc(GL_ONE, GL_ZERO);
6571 GL_DepthMask(writedepth);
6574 rsurface.lightmapcolor4f = NULL;
6576 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6578 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6580 rsurface.lightmapcolor4f = NULL;
6581 rsurface.lightmapcolor4f_bufferobject = 0;
6582 rsurface.lightmapcolor4f_bufferoffset = 0;
6584 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6586 qboolean applycolor = true;
6589 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6591 r_refdef.lightmapintensity = 1;
6592 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
6593 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6597 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6599 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6600 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6601 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6604 if(!rsurface.lightmapcolor4f)
6605 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
6607 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
6608 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
6609 if(r_refdef.fogenabled)
6610 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
6612 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6613 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6616 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6619 RSurf_SetupDepthAndCulling();
6620 if (r_showsurfaces.integer == 3)
6621 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6622 else if (r_glsl.integer && gl_support_fragment_shader)
6623 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6624 else if (gl_combine.integer && r_textureunits.integer >= 2)
6625 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6627 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6631 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6634 RSurf_SetupDepthAndCulling();
6635 if (r_showsurfaces.integer == 3)
6636 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
6637 else if (r_glsl.integer && gl_support_fragment_shader)
6638 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6639 else if (gl_combine.integer && r_textureunits.integer >= 2)
6640 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6642 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6646 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6649 int texturenumsurfaces, endsurface;
6651 msurface_t *surface;
6652 msurface_t *texturesurfacelist[1024];
6654 // if the model is static it doesn't matter what value we give for
6655 // wantnormals and wanttangents, so this logic uses only rules applicable
6656 // to a model, knowing that they are meaningless otherwise
6657 if (ent == r_refdef.scene.worldentity)
6658 RSurf_ActiveWorldEntity();
6659 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6660 RSurf_ActiveModelEntity(ent, false, false);
6662 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6664 for (i = 0;i < numsurfaces;i = j)
6667 surface = rsurface.modelsurfaces + surfacelist[i];
6668 texture = surface->texture;
6669 rsurface.texture = R_GetCurrentTexture(texture);
6670 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6671 // scan ahead until we find a different texture
6672 endsurface = min(i + 1024, numsurfaces);
6673 texturenumsurfaces = 0;
6674 texturesurfacelist[texturenumsurfaces++] = surface;
6675 for (;j < endsurface;j++)
6677 surface = rsurface.modelsurfaces + surfacelist[j];
6678 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6680 texturesurfacelist[texturenumsurfaces++] = surface;
6682 // render the range of surfaces
6683 if (ent == r_refdef.scene.worldentity)
6684 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6686 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6688 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6689 GL_AlphaTest(false);
6692 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6694 const entity_render_t *queueentity = r_refdef.scene.worldentity;
6698 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6700 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6702 RSurf_SetupDepthAndCulling();
6703 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6704 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6706 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6708 RSurf_SetupDepthAndCulling();
6709 GL_AlphaTest(false);
6710 R_Mesh_ColorPointer(NULL, 0, 0);
6711 R_Mesh_ResetTextureState();
6712 R_SetupGenericShader(false);
6713 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6715 GL_BlendFunc(GL_ONE, GL_ZERO);
6716 GL_Color(0, 0, 0, 1);
6717 GL_DepthTest(writedepth);
6718 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6720 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6722 RSurf_SetupDepthAndCulling();
6723 GL_AlphaTest(false);
6724 R_Mesh_ColorPointer(NULL, 0, 0);
6725 R_Mesh_ResetTextureState();
6726 R_SetupGenericShader(false);
6727 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6729 GL_BlendFunc(GL_ONE, GL_ZERO);
6731 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6733 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6734 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6735 else if (!rsurface.texture->currentnumlayers)
6737 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6739 // transparent surfaces get pushed off into the transparent queue
6740 int surfacelistindex;
6741 const msurface_t *surface;
6742 vec3_t tempcenter, center;
6743 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6745 surface = texturesurfacelist[surfacelistindex];
6746 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6747 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6748 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6749 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6750 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6755 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6756 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6761 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6765 // break the surface list down into batches by texture and use of lightmapping
6766 for (i = 0;i < numsurfaces;i = j)
6769 // texture is the base texture pointer, rsurface.texture is the
6770 // current frame/skin the texture is directing us to use (for example
6771 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6772 // use skin 1 instead)
6773 texture = surfacelist[i]->texture;
6774 rsurface.texture = R_GetCurrentTexture(texture);
6775 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6776 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6778 // if this texture is not the kind we want, skip ahead to the next one
6779 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6783 // simply scan ahead until we find a different texture or lightmap state
6784 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6786 // render the range of surfaces
6787 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6791 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6796 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6798 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6800 RSurf_SetupDepthAndCulling();
6801 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6802 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6804 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
6806 RSurf_SetupDepthAndCulling();
6807 GL_AlphaTest(false);
6808 R_Mesh_ColorPointer(NULL, 0, 0);
6809 R_Mesh_ResetTextureState();
6810 R_SetupGenericShader(false);
6811 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6813 GL_BlendFunc(GL_ONE, GL_ZERO);
6814 GL_Color(0, 0, 0, 1);
6815 GL_DepthTest(writedepth);
6816 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6818 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
6820 RSurf_SetupDepthAndCulling();
6821 GL_AlphaTest(false);
6822 R_Mesh_ColorPointer(NULL, 0, 0);
6823 R_Mesh_ResetTextureState();
6824 R_SetupGenericShader(false);
6825 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6827 GL_BlendFunc(GL_ONE, GL_ZERO);
6829 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6831 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6832 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6833 else if (!rsurface.texture->currentnumlayers)
6835 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
6837 // transparent surfaces get pushed off into the transparent queue
6838 int surfacelistindex;
6839 const msurface_t *surface;
6840 vec3_t tempcenter, center;
6841 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6843 surface = texturesurfacelist[surfacelistindex];
6844 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6845 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6846 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6847 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6848 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6853 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6854 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6859 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
6863 // break the surface list down into batches by texture and use of lightmapping
6864 for (i = 0;i < numsurfaces;i = j)
6867 // texture is the base texture pointer, rsurface.texture is the
6868 // current frame/skin the texture is directing us to use (for example
6869 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6870 // use skin 1 instead)
6871 texture = surfacelist[i]->texture;
6872 rsurface.texture = R_GetCurrentTexture(texture);
6873 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6874 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6876 // if this texture is not the kind we want, skip ahead to the next one
6877 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6881 // simply scan ahead until we find a different texture or lightmap state
6882 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6884 // render the range of surfaces
6885 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6889 float locboxvertex3f[6*4*3] =
6891 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6892 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6893 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6894 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6895 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6896 1,0,0, 0,0,0, 0,1,0, 1,1,0
6899 unsigned short locboxelements[6*2*3] =
6909 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6912 cl_locnode_t *loc = (cl_locnode_t *)ent;
6914 float vertex3f[6*4*3];
6916 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6917 GL_DepthMask(false);
6918 GL_DepthRange(0, 1);
6919 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6921 GL_CullFace(GL_NONE);
6922 R_Mesh_Matrix(&identitymatrix);
6924 R_Mesh_VertexPointer(vertex3f, 0, 0);
6925 R_Mesh_ColorPointer(NULL, 0, 0);
6926 R_Mesh_ResetTextureState();
6927 R_SetupGenericShader(false);
6930 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6931 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6932 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6933 surfacelist[0] < 0 ? 0.5f : 0.125f);
6935 if (VectorCompare(loc->mins, loc->maxs))
6937 VectorSet(size, 2, 2, 2);
6938 VectorMA(loc->mins, -0.5f, size, mins);
6942 VectorCopy(loc->mins, mins);
6943 VectorSubtract(loc->maxs, loc->mins, size);
6946 for (i = 0;i < 6*4*3;)
6947 for (j = 0;j < 3;j++, i++)
6948 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6950 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
6953 void R_DrawLocs(void)
6956 cl_locnode_t *loc, *nearestloc;
6958 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6959 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6961 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6962 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6966 void R_DrawDebugModel(entity_render_t *ent)
6968 int i, j, k, l, flagsmask;
6969 const int *elements;
6971 msurface_t *surface;
6972 dp_model_t *model = ent->model;
6975 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
6977 R_Mesh_ColorPointer(NULL, 0, 0);
6978 R_Mesh_ResetTextureState();
6979 R_SetupGenericShader(false);
6980 GL_DepthRange(0, 1);
6981 GL_DepthTest(!r_showdisabledepthtest.integer);
6982 GL_DepthMask(false);
6983 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6985 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6987 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6988 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6990 if (brush->colbrushf && brush->colbrushf->numtriangles)
6992 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6993 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);
6994 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
6997 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6999 if (surface->num_collisiontriangles)
7001 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7002 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);
7003 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7008 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7010 if (r_showtris.integer || r_shownormals.integer)
7012 if (r_showdisabledepthtest.integer)
7014 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7015 GL_DepthMask(false);
7019 GL_BlendFunc(GL_ONE, GL_ZERO);
7022 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7024 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7026 rsurface.texture = R_GetCurrentTexture(surface->texture);
7027 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7029 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7030 if (r_showtris.value > 0)
7032 if (!rsurface.texture->currentlayers->depthmask)
7033 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7034 else if (ent == r_refdef.scene.worldentity)
7035 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7037 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7038 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7039 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7040 R_Mesh_ColorPointer(NULL, 0, 0);
7041 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7042 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7043 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7044 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);
7045 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7048 if (r_shownormals.value < 0)
7051 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7053 VectorCopy(rsurface.vertex3f + l * 3, v);
7054 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7055 qglVertex3f(v[0], v[1], v[2]);
7056 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7057 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7058 qglVertex3f(v[0], v[1], v[2]);
7063 if (r_shownormals.value > 0)
7066 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7068 VectorCopy(rsurface.vertex3f + l * 3, v);
7069 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7070 qglVertex3f(v[0], v[1], v[2]);
7071 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7072 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7073 qglVertex3f(v[0], v[1], v[2]);
7078 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7080 VectorCopy(rsurface.vertex3f + l * 3, v);
7081 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7082 qglVertex3f(v[0], v[1], v[2]);
7083 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7084 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7085 qglVertex3f(v[0], v[1], v[2]);
7090 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7092 VectorCopy(rsurface.vertex3f + l * 3, v);
7093 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7094 qglVertex3f(v[0], v[1], v[2]);
7095 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7096 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7097 qglVertex3f(v[0], v[1], v[2]);
7104 rsurface.texture = NULL;
7108 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7109 int r_maxsurfacelist = 0;
7110 msurface_t **r_surfacelist = NULL;
7111 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7113 int i, j, endj, f, flagsmask;
7115 dp_model_t *model = r_refdef.scene.worldmodel;
7116 msurface_t *surfaces;
7117 unsigned char *update;
7118 int numsurfacelist = 0;
7122 if (r_maxsurfacelist < model->num_surfaces)
7124 r_maxsurfacelist = model->num_surfaces;
7126 Mem_Free(r_surfacelist);
7127 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7130 RSurf_ActiveWorldEntity();
7132 surfaces = model->data_surfaces;
7133 update = model->brushq1.lightmapupdateflags;
7135 // update light styles on this submodel
7136 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7138 model_brush_lightstyleinfo_t *style;
7139 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7141 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7143 int *list = style->surfacelist;
7144 style->value = r_refdef.scene.lightstylevalue[style->style];
7145 for (j = 0;j < style->numsurfaces;j++)
7146 update[list[j]] = true;
7151 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7155 R_DrawDebugModel(r_refdef.scene.worldentity);
7161 rsurface.uselightmaptexture = false;
7162 rsurface.texture = NULL;
7163 rsurface.rtlight = NULL;
7165 // add visible surfaces to draw list
7166 for (i = 0;i < model->nummodelsurfaces;i++)
7168 j = model->sortedmodelsurfaces[i];
7169 if (r_refdef.viewcache.world_surfacevisible[j])
7170 r_surfacelist[numsurfacelist++] = surfaces + j;
7172 // update lightmaps if needed
7174 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7175 if (r_refdef.viewcache.world_surfacevisible[j])
7177 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7178 // don't do anything if there were no surfaces
7179 if (!numsurfacelist)
7181 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7182 GL_AlphaTest(false);
7184 // add to stats if desired
7185 if (r_speeds.integer && !skysurfaces && !depthonly)
7187 r_refdef.stats.world_surfaces += numsurfacelist;
7188 for (j = 0;j < numsurfacelist;j++)
7189 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7193 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7195 int i, j, endj, f, flagsmask;
7197 dp_model_t *model = ent->model;
7198 msurface_t *surfaces;
7199 unsigned char *update;
7200 int numsurfacelist = 0;
7204 if (r_maxsurfacelist < model->num_surfaces)
7206 r_maxsurfacelist = model->num_surfaces;
7208 Mem_Free(r_surfacelist);
7209 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7212 // if the model is static it doesn't matter what value we give for
7213 // wantnormals and wanttangents, so this logic uses only rules applicable
7214 // to a model, knowing that they are meaningless otherwise
7215 if (ent == r_refdef.scene.worldentity)
7216 RSurf_ActiveWorldEntity();
7217 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
7218 RSurf_ActiveModelEntity(ent, false, false);
7220 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7222 surfaces = model->data_surfaces;
7223 update = model->brushq1.lightmapupdateflags;
7225 // update light styles
7226 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7228 model_brush_lightstyleinfo_t *style;
7229 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7231 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7233 int *list = style->surfacelist;
7234 style->value = r_refdef.scene.lightstylevalue[style->style];
7235 for (j = 0;j < style->numsurfaces;j++)
7236 update[list[j]] = true;
7241 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7245 R_DrawDebugModel(ent);
7251 rsurface.uselightmaptexture = false;
7252 rsurface.texture = NULL;
7253 rsurface.rtlight = NULL;
7255 // add visible surfaces to draw list
7256 for (i = 0;i < model->nummodelsurfaces;i++)
7257 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7258 // don't do anything if there were no surfaces
7259 if (!numsurfacelist)
7261 // update lightmaps if needed
7263 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7265 R_BuildLightMap(ent, surfaces + j);
7266 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7267 GL_AlphaTest(false);
7269 // add to stats if desired
7270 if (r_speeds.integer && !skysurfaces && !depthonly)
7272 r_refdef.stats.entities++;
7273 r_refdef.stats.entities_surfaces += numsurfacelist;
7274 for (j = 0;j < numsurfacelist;j++)
7275 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;