2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
36 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "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"};
37 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
38 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
39 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
40 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)"};
41 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
42 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
43 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"};
44 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"};
45 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
46 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"};
47 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"};
48 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"};
49 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
50 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
51 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
52 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
53 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
54 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
55 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
56 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
57 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
58 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
59 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
60 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
61 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"};
62 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
63 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
64 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"};
65 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"};
66 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
67 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
69 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
70 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
71 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
72 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
73 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
74 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
75 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
76 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
78 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)"};
80 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
81 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)"};
82 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)"};
83 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
84 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
85 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
86 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
87 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)"};
88 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)"};
89 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)"};
90 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)"};
91 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)"};
93 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)"};
94 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
95 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"};
96 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
97 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
99 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
100 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
101 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
102 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
104 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
105 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
106 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
107 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
108 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
109 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
110 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
112 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
113 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
114 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
115 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)"};
117 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"};
119 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"};
121 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
123 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
124 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
125 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"};
126 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
127 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
128 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
130 extern cvar_t v_glslgamma;
132 extern qboolean v_flipped_state;
134 static struct r_bloomstate_s
139 int bloomwidth, bloomheight;
141 int screentexturewidth, screentextureheight;
142 rtexture_t *texture_screen;
144 int bloomtexturewidth, bloomtextureheight;
145 rtexture_t *texture_bloom;
147 // arrays for rendering the screen passes
148 float screentexcoord2f[8];
149 float bloomtexcoord2f[8];
150 float offsettexcoord2f[8];
154 r_waterstate_t r_waterstate;
156 // shadow volume bsp struct with automatically growing nodes buffer
159 rtexture_t *r_texture_blanknormalmap;
160 rtexture_t *r_texture_white;
161 rtexture_t *r_texture_grey128;
162 rtexture_t *r_texture_black;
163 rtexture_t *r_texture_notexture;
164 rtexture_t *r_texture_whitecube;
165 rtexture_t *r_texture_normalizationcube;
166 rtexture_t *r_texture_fogattenuation;
167 rtexture_t *r_texture_gammaramps;
168 unsigned int r_texture_gammaramps_serial;
169 //rtexture_t *r_texture_fogintensity;
171 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
172 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
174 // vertex coordinates for a quad that covers the screen exactly
175 const static float r_screenvertex3f[12] =
183 extern void R_DrawModelShadows(void);
185 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
188 for (i = 0;i < verts;i++)
199 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
202 for (i = 0;i < verts;i++)
212 // FIXME: move this to client?
215 if (gamemode == GAME_NEHAHRA)
217 Cvar_Set("gl_fogenable", "0");
218 Cvar_Set("gl_fogdensity", "0.2");
219 Cvar_Set("gl_fogred", "0.3");
220 Cvar_Set("gl_foggreen", "0.3");
221 Cvar_Set("gl_fogblue", "0.3");
223 r_refdef.fog_density = 0;
224 r_refdef.fog_red = 0;
225 r_refdef.fog_green = 0;
226 r_refdef.fog_blue = 0;
227 r_refdef.fog_alpha = 1;
228 r_refdef.fog_start = 0;
229 r_refdef.fog_end = 0;
232 float FogForDistance(vec_t dist)
234 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
235 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
238 float FogPoint_World(const vec3_t p)
240 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
243 float FogPoint_Model(const vec3_t p)
245 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
248 static void R_BuildBlankTextures(void)
250 unsigned char data[4];
251 data[2] = 128; // normal X
252 data[1] = 128; // normal Y
253 data[0] = 255; // normal Z
254 data[3] = 128; // height
255 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
260 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
265 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
270 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
273 static void R_BuildNoTexture(void)
276 unsigned char pix[16][16][4];
277 // this makes a light grey/dark grey checkerboard texture
278 for (y = 0;y < 16;y++)
280 for (x = 0;x < 16;x++)
282 if ((y < 8) ^ (x < 8))
298 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
301 static void R_BuildWhiteCube(void)
303 unsigned char data[6*1*1*4];
304 memset(data, 255, sizeof(data));
305 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
308 static void R_BuildNormalizationCube(void)
312 vec_t s, t, intensity;
314 unsigned char data[6][NORMSIZE][NORMSIZE][4];
315 for (side = 0;side < 6;side++)
317 for (y = 0;y < NORMSIZE;y++)
319 for (x = 0;x < NORMSIZE;x++)
321 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
322 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
357 intensity = 127.0f / sqrt(DotProduct(v, v));
358 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
359 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
360 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
361 data[side][y][x][3] = 255;
365 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
368 static void R_BuildFogTexture(void)
372 unsigned char data1[FOGWIDTH][4];
373 //unsigned char data2[FOGWIDTH][4];
376 r_refdef.fogmasktable_start = r_refdef.fog_start;
377 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
378 r_refdef.fogmasktable_range = r_refdef.fogrange;
379 r_refdef.fogmasktable_density = r_refdef.fog_density;
381 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
382 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
384 d = (x * r - r_refdef.fogmasktable_start);
385 if(developer.integer >= 100)
386 Con_Printf("%f ", d);
388 if (r_fog_exp2.integer)
389 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
391 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
392 if(developer.integer >= 100)
393 Con_Printf(" : %f ", alpha);
394 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
395 if(developer.integer >= 100)
396 Con_Printf(" = %f\n", alpha);
397 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
400 for (x = 0;x < FOGWIDTH;x++)
402 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
407 //data2[x][0] = 255 - b;
408 //data2[x][1] = 255 - b;
409 //data2[x][2] = 255 - b;
412 if (r_texture_fogattenuation)
414 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
415 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
419 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);
420 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
424 static const char *builtinshaderstring =
425 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
426 "// written by Forest 'LordHavoc' Hale\n"
428 "// common definitions between vertex shader and fragment shader:\n"
430 "//#ifdef __GLSL_CG_DATA_TYPES\n"
431 "//# define myhalf half\n"
432 "//# define myhalf2 half2\n"
433 "//# define myhalf3 half3\n"
434 "//# define myhalf4 half4\n"
436 "# define myhalf float\n"
437 "# define myhalf2 vec2\n"
438 "# define myhalf3 vec3\n"
439 "# define myhalf4 vec4\n"
442 "#ifdef MODE_DEPTH_OR_SHADOW\n"
444 "# ifdef VERTEX_SHADER\n"
447 " gl_Position = ftransform();\n"
453 "#ifdef MODE_POSTPROCESS\n"
454 "# ifdef VERTEX_SHADER\n"
457 " gl_FrontColor = gl_Color;\n"
458 " gl_Position = ftransform();\n"
459 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
461 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
465 "# ifdef FRAGMENT_SHADER\n"
467 "uniform sampler2D Texture_First;\n"
469 "uniform sampler2D Texture_Second;\n"
471 "#ifdef USEGAMMARAMPS\n"
472 "uniform sampler2D Texture_GammaRamps;\n"
474 "#ifdef USEVERTEXTEXTUREBLEND\n"
475 "uniform vec4 TintColor;\n"
477 "#ifdef USECOLORMOD\n"
478 "uniform vec3 Gamma;\n"
480 "//uncomment these if you want to use them:\n"
481 "// uniform vec4 UserVec1;\n"
482 "// uniform vec4 UserVec2;\n"
483 "// uniform vec4 UserVec3;\n"
484 "// uniform vec4 UserVec4;\n"
485 "// uniform float ClientTime;\n"
486 "// uniform vec2 PixelSize;\n"
489 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
491 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
493 "#ifdef USEVERTEXTEXTUREBLEND\n"
494 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
497 "#ifdef USEPOSTPROCESSING\n"
498 "// add your own postprocessing here or make your own ifdef for it\n"
501 "#ifdef USEGAMMARAMPS\n"
502 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
503 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
504 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
511 "#ifdef MODE_GENERIC\n"
512 "# ifdef VERTEX_SHADER\n"
515 " gl_FrontColor = gl_Color;\n"
516 "# ifdef USEDIFFUSE\n"
517 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
519 "# ifdef USESPECULAR\n"
520 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
522 " gl_Position = ftransform();\n"
525 "# ifdef FRAGMENT_SHADER\n"
527 "# ifdef USEDIFFUSE\n"
528 "uniform sampler2D Texture_First;\n"
530 "# ifdef USESPECULAR\n"
531 "uniform sampler2D Texture_Second;\n"
536 " gl_FragColor = gl_Color;\n"
537 "# ifdef USEDIFFUSE\n"
538 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
541 "# ifdef USESPECULAR\n"
542 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
544 "# ifdef USECOLORMAPPING\n"
545 " gl_FragColor *= tex2;\n"
548 " gl_FragColor += tex2;\n"
550 "# ifdef USEVERTEXTEXTUREBLEND\n"
551 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
556 "#else // !MODE_GENERIC\n"
558 "varying vec2 TexCoord;\n"
559 "varying vec2 TexCoordLightmap;\n"
561 "#ifdef MODE_LIGHTSOURCE\n"
562 "varying vec3 CubeVector;\n"
565 "#ifdef MODE_LIGHTSOURCE\n"
566 "varying vec3 LightVector;\n"
568 "#ifdef MODE_LIGHTDIRECTION\n"
569 "varying vec3 LightVector;\n"
572 "varying vec3 EyeVector;\n"
574 "varying vec3 EyeVectorModelSpace;\n"
577 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
578 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
579 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
581 "#ifdef MODE_WATER\n"
582 "varying vec4 ModelViewProjectionPosition;\n"
584 "#ifdef MODE_REFRACTION\n"
585 "varying vec4 ModelViewProjectionPosition;\n"
587 "#ifdef USEREFLECTION\n"
588 "varying vec4 ModelViewProjectionPosition;\n"
595 "// vertex shader specific:\n"
596 "#ifdef VERTEX_SHADER\n"
598 "uniform vec3 LightPosition;\n"
599 "uniform vec3 EyePosition;\n"
600 "uniform vec3 LightDir;\n"
602 "// 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"
606 " gl_FrontColor = gl_Color;\n"
607 " // copy the surface texcoord\n"
608 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
609 "#ifndef MODE_LIGHTSOURCE\n"
610 "# ifndef MODE_LIGHTDIRECTION\n"
611 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
615 "#ifdef MODE_LIGHTSOURCE\n"
616 " // transform vertex position into light attenuation/cubemap space\n"
617 " // (-1 to +1 across the light box)\n"
618 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
620 " // transform unnormalized light direction into tangent space\n"
621 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
622 " // normalize it per pixel)\n"
623 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
624 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
625 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
626 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
629 "#ifdef MODE_LIGHTDIRECTION\n"
630 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
631 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
632 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
635 " // transform unnormalized eye direction into tangent space\n"
637 " vec3 EyeVectorModelSpace;\n"
639 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
640 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
641 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
642 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
644 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
645 " VectorS = gl_MultiTexCoord1.xyz;\n"
646 " VectorT = gl_MultiTexCoord2.xyz;\n"
647 " VectorR = gl_MultiTexCoord3.xyz;\n"
650 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
651 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
652 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
653 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
656 "// transform vertex to camera space, using ftransform to match non-VS\n"
658 " gl_Position = ftransform();\n"
660 "#ifdef MODE_WATER\n"
661 " ModelViewProjectionPosition = gl_Position;\n"
663 "#ifdef MODE_REFRACTION\n"
664 " ModelViewProjectionPosition = gl_Position;\n"
666 "#ifdef USEREFLECTION\n"
667 " ModelViewProjectionPosition = gl_Position;\n"
671 "#endif // VERTEX_SHADER\n"
676 "// fragment shader specific:\n"
677 "#ifdef FRAGMENT_SHADER\n"
679 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
680 "uniform sampler2D Texture_Normal;\n"
681 "uniform sampler2D Texture_Color;\n"
682 "uniform sampler2D Texture_Gloss;\n"
683 "uniform sampler2D Texture_Glow;\n"
684 "uniform sampler2D Texture_SecondaryNormal;\n"
685 "uniform sampler2D Texture_SecondaryColor;\n"
686 "uniform sampler2D Texture_SecondaryGloss;\n"
687 "uniform sampler2D Texture_SecondaryGlow;\n"
688 "uniform sampler2D Texture_Pants;\n"
689 "uniform sampler2D Texture_Shirt;\n"
690 "uniform sampler2D Texture_FogMask;\n"
691 "uniform sampler2D Texture_Lightmap;\n"
692 "uniform sampler2D Texture_Deluxemap;\n"
693 "uniform sampler2D Texture_Refraction;\n"
694 "uniform sampler2D Texture_Reflection;\n"
695 "uniform sampler2D Texture_Attenuation;\n"
696 "uniform samplerCube Texture_Cube;\n"
698 "uniform myhalf3 LightColor;\n"
699 "uniform myhalf3 AmbientColor;\n"
700 "uniform myhalf3 DiffuseColor;\n"
701 "uniform myhalf3 SpecularColor;\n"
702 "uniform myhalf3 Color_Pants;\n"
703 "uniform myhalf3 Color_Shirt;\n"
704 "uniform myhalf3 FogColor;\n"
706 "uniform myhalf4 TintColor;\n"
709 "//#ifdef MODE_WATER\n"
710 "uniform vec4 DistortScaleRefractReflect;\n"
711 "uniform vec4 ScreenScaleRefractReflect;\n"
712 "uniform vec4 ScreenCenterRefractReflect;\n"
713 "uniform myhalf4 RefractColor;\n"
714 "uniform myhalf4 ReflectColor;\n"
715 "uniform myhalf ReflectFactor;\n"
716 "uniform myhalf ReflectOffset;\n"
718 "//# ifdef MODE_REFRACTION\n"
719 "//uniform vec4 DistortScaleRefractReflect;\n"
720 "//uniform vec4 ScreenScaleRefractReflect;\n"
721 "//uniform vec4 ScreenCenterRefractReflect;\n"
722 "//uniform myhalf4 RefractColor;\n"
723 "//# ifdef USEREFLECTION\n"
724 "//uniform myhalf4 ReflectColor;\n"
727 "//# ifdef USEREFLECTION\n"
728 "//uniform vec4 DistortScaleRefractReflect;\n"
729 "//uniform vec4 ScreenScaleRefractReflect;\n"
730 "//uniform vec4 ScreenCenterRefractReflect;\n"
731 "//uniform myhalf4 ReflectColor;\n"
736 "uniform myhalf GlowScale;\n"
737 "uniform myhalf SceneBrightness;\n"
738 "#ifdef USECONTRASTBOOST\n"
739 "uniform myhalf ContrastBoostCoeff;\n"
742 "uniform float OffsetMapping_Scale;\n"
743 "uniform float OffsetMapping_Bias;\n"
744 "uniform float FogRangeRecip;\n"
746 "uniform myhalf AmbientScale;\n"
747 "uniform myhalf DiffuseScale;\n"
748 "uniform myhalf SpecularScale;\n"
749 "uniform myhalf SpecularPower;\n"
751 "#ifdef USEOFFSETMAPPING\n"
752 "vec2 OffsetMapping(vec2 TexCoord)\n"
754 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
755 " // 14 sample relief mapping: linear search and then binary search\n"
756 " // this basically steps forward a small amount repeatedly until it finds\n"
757 " // itself inside solid, then jitters forward and back using decreasing\n"
758 " // amounts to find the impact\n"
759 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
760 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
761 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
762 " vec3 RT = vec3(TexCoord, 1);\n"
763 " OffsetVector *= 0.1;\n"
764 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
765 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
766 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
767 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
768 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
769 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
770 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
771 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
772 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
773 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
774 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
775 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
776 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
777 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
780 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
781 " // this basically moves forward the full distance, and then backs up based\n"
782 " // on height of samples\n"
783 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
784 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
785 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
786 " TexCoord += OffsetVector;\n"
787 " OffsetVector *= 0.333;\n"
788 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
789 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
790 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
791 " return TexCoord;\n"
794 "#endif // USEOFFSETMAPPING\n"
796 "#ifdef MODE_WATER\n"
801 "#ifdef USEOFFSETMAPPING\n"
802 " // apply offsetmapping\n"
803 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
804 "#define TexCoord TexCoordOffset\n"
807 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
808 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
809 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
810 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
811 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
814 "#else // !MODE_WATER\n"
815 "#ifdef MODE_REFRACTION\n"
817 "// refraction pass\n"
820 "#ifdef USEOFFSETMAPPING\n"
821 " // apply offsetmapping\n"
822 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
823 "#define TexCoord TexCoordOffset\n"
826 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
827 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
828 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
829 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
832 "#else // !MODE_REFRACTION\n"
835 "#ifdef USEOFFSETMAPPING\n"
836 " // apply offsetmapping\n"
837 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
838 "#define TexCoord TexCoordOffset\n"
841 " // combine the diffuse textures (base, pants, shirt)\n"
842 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
843 "#ifdef USECOLORMAPPING\n"
844 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
846 "#ifdef USEVERTEXTEXTUREBLEND\n"
847 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
848 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
849 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
850 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord)), color.rgb, terrainblend);\n"
852 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
855 "#ifdef USEDIFFUSE\n"
856 " // get the surface normal and the gloss color\n"
857 "# ifdef USEVERTEXTEXTUREBLEND\n"
858 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
859 "# ifdef USESPECULAR\n"
860 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
863 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
864 "# ifdef USESPECULAR\n"
865 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
872 "#ifdef MODE_LIGHTSOURCE\n"
875 " // calculate surface normal, light normal, and specular normal\n"
876 " // compute color intensity for the two textures (colormap and glossmap)\n"
877 " // scale by light color and attenuation as efficiently as possible\n"
878 " // (do as much scalar math as possible rather than vector math)\n"
879 "# ifdef USEDIFFUSE\n"
880 " // get the light normal\n"
881 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
883 "# ifdef USESPECULAR\n"
884 "# ifndef USEEXACTSPECULARMATH\n"
885 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
888 " // calculate directional shading\n"
889 "# ifdef USEEXACTSPECULARMATH\n"
890 " 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"
892 " 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"
895 "# ifdef USEDIFFUSE\n"
896 " // calculate directional shading\n"
897 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
899 " // calculate directionless shading\n"
900 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
904 "# ifdef USECUBEFILTER\n"
905 " // apply light cubemap filter\n"
906 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
907 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
909 "#endif // MODE_LIGHTSOURCE\n"
914 "#ifdef MODE_LIGHTDIRECTION\n"
915 " // directional model lighting\n"
916 "# ifdef USEDIFFUSE\n"
917 " // get the light normal\n"
918 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
920 "# ifdef USESPECULAR\n"
921 " // calculate directional shading\n"
922 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
923 "# ifdef USEEXACTSPECULARMATH\n"
924 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
926 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
927 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
930 "# ifdef USEDIFFUSE\n"
932 " // calculate directional shading\n"
933 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
935 " color.rgb *= AmbientColor;\n"
938 "#endif // MODE_LIGHTDIRECTION\n"
943 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
944 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
946 " // get the light normal\n"
947 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
948 " myhalf3 diffusenormal;\n"
949 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
950 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
951 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
952 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
953 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
954 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
955 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
956 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
957 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
958 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
959 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
960 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
961 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
962 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
963 "# ifdef USESPECULAR\n"
964 "# ifdef USEEXACTSPECULARMATH\n"
965 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
967 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
968 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
972 " // apply lightmap color\n"
973 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
974 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
979 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
980 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
982 " // get the light normal\n"
983 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
984 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
985 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
986 "# ifdef USESPECULAR\n"
987 "# ifdef USEEXACTSPECULARMATH\n"
988 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
990 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
991 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
995 " // apply lightmap color\n"
996 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
997 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1002 "#ifdef MODE_LIGHTMAP\n"
1003 " // apply lightmap color\n"
1004 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1005 "#endif // MODE_LIGHTMAP\n"
1010 "#ifdef MODE_VERTEXCOLOR\n"
1011 " // apply lightmap color\n"
1012 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1013 "#endif // MODE_VERTEXCOLOR\n"
1018 "#ifdef MODE_FLATCOLOR\n"
1019 "#endif // MODE_FLATCOLOR\n"
1027 " color *= TintColor;\n"
1030 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1033 "#ifdef USECONTRASTBOOST\n"
1034 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1037 " color.rgb *= SceneBrightness;\n"
1039 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1041 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1044 " // 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"
1045 "#ifdef USEREFLECTION\n"
1046 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1047 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1048 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1049 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1052 " gl_FragColor = vec4(color);\n"
1054 "#endif // !MODE_REFRACTION\n"
1055 "#endif // !MODE_WATER\n"
1057 "#endif // FRAGMENT_SHADER\n"
1059 "#endif // !MODE_GENERIC\n"
1060 "#endif // !MODE_POSTPROCESS\n"
1061 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1064 typedef struct shaderpermutationinfo_s
1066 const char *pretext;
1069 shaderpermutationinfo_t;
1071 typedef struct shadermodeinfo_s
1073 const char *vertexfilename;
1074 const char *geometryfilename;
1075 const char *fragmentfilename;
1076 const char *pretext;
1081 typedef enum shaderpermutation_e
1083 SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
1084 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1085 SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
1086 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1087 SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
1088 SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
1089 SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
1090 SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
1091 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<8, // (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1092 SHADERPERMUTATION_REFLECTION = 1<<9, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1093 SHADERPERMUTATION_OFFSETMAPPING = 1<<10, // adjust texcoords to roughly simulate a displacement mapped surface
1094 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<11, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1095 SHADERPERMUTATION_GAMMARAMPS = 1<<12, // gamma (postprocessing only)
1096 SHADERPERMUTATION_POSTPROCESSING = 1<<13, // user defined postprocessing
1097 SHADERPERMUTATION_LIMIT = 1<<14, // size of permutations array
1098 SHADERPERMUTATION_COUNT = 14 // size of shaderpermutationinfo array
1100 shaderpermutation_t;
1102 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1103 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1105 {"#define USEDIFFUSE\n", " diffuse"},
1106 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1107 {"#define USECOLORMAPPING\n", " colormapping"},
1108 {"#define USECONTRASTBOOST\n", " contrastboost"},
1109 {"#define USEFOG\n", " fog"},
1110 {"#define USECUBEFILTER\n", " cubefilter"},
1111 {"#define USEGLOW\n", " glow"},
1112 {"#define USESPECULAR\n", " specular"},
1113 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1114 {"#define USEREFLECTION\n", " reflection"},
1115 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1116 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1117 {"#define USEGAMMARAMPS\n", " gammaramps"},
1118 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1121 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
1122 typedef enum shadermode_e
1124 SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
1125 SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
1126 SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
1127 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1128 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
1129 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1130 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1131 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1132 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1133 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
1134 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
1135 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1140 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1141 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1143 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1144 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1145 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1146 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1147 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1148 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1149 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1150 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1151 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1152 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1153 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1154 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1157 typedef struct r_glsl_permutation_s
1159 // indicates if we have tried compiling this permutation already
1161 // 0 if compilation failed
1163 // locations of detected uniforms in program object, or -1 if not found
1164 int loc_Texture_First;
1165 int loc_Texture_Second;
1166 int loc_Texture_GammaRamps;
1167 int loc_Texture_Normal;
1168 int loc_Texture_Color;
1169 int loc_Texture_Gloss;
1170 int loc_Texture_Glow;
1171 int loc_Texture_SecondaryNormal;
1172 int loc_Texture_SecondaryColor;
1173 int loc_Texture_SecondaryGloss;
1174 int loc_Texture_SecondaryGlow;
1175 int loc_Texture_Pants;
1176 int loc_Texture_Shirt;
1177 int loc_Texture_FogMask;
1178 int loc_Texture_Lightmap;
1179 int loc_Texture_Deluxemap;
1180 int loc_Texture_Attenuation;
1181 int loc_Texture_Cube;
1182 int loc_Texture_Refraction;
1183 int loc_Texture_Reflection;
1185 int loc_LightPosition;
1186 int loc_EyePosition;
1187 int loc_Color_Pants;
1188 int loc_Color_Shirt;
1189 int loc_FogRangeRecip;
1190 int loc_AmbientScale;
1191 int loc_DiffuseScale;
1192 int loc_SpecularScale;
1193 int loc_SpecularPower;
1195 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1196 int loc_OffsetMapping_Scale;
1198 int loc_AmbientColor;
1199 int loc_DiffuseColor;
1200 int loc_SpecularColor;
1202 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1203 int loc_GammaCoeff; // 1 / gamma
1204 int loc_DistortScaleRefractReflect;
1205 int loc_ScreenScaleRefractReflect;
1206 int loc_ScreenCenterRefractReflect;
1207 int loc_RefractColor;
1208 int loc_ReflectColor;
1209 int loc_ReflectFactor;
1210 int loc_ReflectOffset;
1218 r_glsl_permutation_t;
1220 // information about each possible shader permutation
1221 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1222 // currently selected permutation
1223 r_glsl_permutation_t *r_glsl_permutation;
1225 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1228 if (!filename || !filename[0])
1230 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1233 if (printfromdisknotice)
1234 Con_DPrint("from disk... ");
1235 return shaderstring;
1237 else if (!strcmp(filename, "glsl/default.glsl"))
1239 shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1240 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1242 return shaderstring;
1245 static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t permutation)
1248 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1249 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1250 int vertstrings_count = 0;
1251 int geomstrings_count = 0;
1252 int fragstrings_count = 0;
1253 char *vertexstring, *geometrystring, *fragmentstring;
1254 const char *vertstrings_list[32+3];
1255 const char *geomstrings_list[32+3];
1256 const char *fragstrings_list[32+3];
1257 char permutationname[256];
1264 permutationname[0] = 0;
1265 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1266 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1267 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1269 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1271 // the first pretext is which type of shader to compile as
1272 // (later these will all be bound together as a program object)
1273 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1274 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1275 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1277 // the second pretext is the mode (for example a light source)
1278 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1279 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1280 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1281 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1283 // now add all the permutation pretexts
1284 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1286 if (permutation & (1<<i))
1288 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1289 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1290 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1291 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1295 // keep line numbers correct
1296 vertstrings_list[vertstrings_count++] = "\n";
1297 geomstrings_list[geomstrings_count++] = "\n";
1298 fragstrings_list[fragstrings_count++] = "\n";
1302 // now append the shader text itself
1303 vertstrings_list[vertstrings_count++] = vertexstring;
1304 geomstrings_list[geomstrings_count++] = geometrystring;
1305 fragstrings_list[fragstrings_count++] = fragmentstring;
1307 // if any sources were NULL, clear the respective list
1309 vertstrings_count = 0;
1310 if (!geometrystring)
1311 geomstrings_count = 0;
1312 if (!fragmentstring)
1313 fragstrings_count = 0;
1315 // compile the shader program
1316 if (vertstrings_count + geomstrings_count + fragstrings_count)
1317 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1321 qglUseProgramObjectARB(p->program);CHECKGLERROR
1322 // look up all the uniform variable names we care about, so we don't
1323 // have to look them up every time we set them
1324 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1325 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1326 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1327 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1328 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1329 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1330 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1331 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1332 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1333 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1334 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1335 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1336 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1337 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1338 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1339 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1340 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1341 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1342 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1343 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1344 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1345 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1346 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1347 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1348 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1349 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1350 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1351 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1352 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1353 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1354 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1355 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1356 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1357 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1358 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1359 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1360 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1361 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1362 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1363 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1364 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1365 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1366 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1367 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1368 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1369 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1370 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1371 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1372 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1373 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1374 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1375 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1376 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1377 // initialize the samplers to refer to the texture units we use
1378 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1379 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1380 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1381 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1382 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1383 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1384 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1385 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1386 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1387 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1388 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1389 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1390 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1391 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1392 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1393 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1394 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1395 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1396 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1397 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1399 if (developer.integer)
1400 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1403 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1407 Mem_Free(vertexstring);
1409 Mem_Free(geometrystring);
1411 Mem_Free(fragmentstring);
1414 void R_GLSL_Restart_f(void)
1417 shaderpermutation_t permutation;
1418 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1419 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1420 if (r_glsl_permutations[mode][permutation].program)
1421 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1422 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1425 void R_GLSL_DumpShader_f(void)
1429 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1432 Con_Printf("failed to write to glsl/default.glsl\n");
1436 FS_Print(file, "// The engine may define the following macros:\n");
1437 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1438 for (i = 0;i < SHADERMODE_COUNT;i++)
1439 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1440 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1441 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1442 FS_Print(file, "\n");
1443 FS_Print(file, builtinshaderstring);
1446 Con_Printf("glsl/default.glsl written\n");
1449 void R_SetupShader_SetPermutation(shadermode_t mode, unsigned int permutation)
1451 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1452 if (r_glsl_permutation != perm)
1454 r_glsl_permutation = perm;
1455 if (!r_glsl_permutation->program)
1457 if (!r_glsl_permutation->compiled)
1458 R_GLSL_CompilePermutation(mode, permutation);
1459 if (!r_glsl_permutation->program)
1461 // remove features until we find a valid permutation
1463 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1465 // reduce i more quickly whenever it would not remove any bits
1466 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1467 if (!(permutation & j))
1470 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1471 if (!r_glsl_permutation->compiled)
1472 R_GLSL_CompilePermutation(mode, permutation);
1473 if (r_glsl_permutation->program)
1476 if (i >= SHADERPERMUTATION_COUNT)
1478 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");
1479 Cvar_SetValueQuick(&r_glsl, 0);
1480 R_GLSL_Restart_f(); // unload shaders
1481 return; // no bit left to clear
1486 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1490 void R_SetupGenericShader(qboolean usetexture)
1492 if (gl_support_fragment_shader)
1494 if (r_glsl.integer && r_glsl_usegeneric.integer)
1495 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1496 else if (r_glsl_permutation)
1498 r_glsl_permutation = NULL;
1499 qglUseProgramObjectARB(0);CHECKGLERROR
1504 void R_SetupGenericTwoTextureShader(int texturemode)
1506 if (gl_support_fragment_shader)
1508 if (r_glsl.integer && r_glsl_usegeneric.integer)
1509 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))));
1510 else if (r_glsl_permutation)
1512 r_glsl_permutation = NULL;
1513 qglUseProgramObjectARB(0);CHECKGLERROR
1516 if (!r_glsl_permutation)
1518 if (texturemode == GL_DECAL && gl_combine.integer)
1519 texturemode = GL_INTERPOLATE_ARB;
1520 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1524 void R_SetupDepthOrShadowShader(void)
1526 if (gl_support_fragment_shader)
1528 if (r_glsl.integer && r_glsl_usegeneric.integer)
1529 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1530 else if (r_glsl_permutation)
1532 r_glsl_permutation = NULL;
1533 qglUseProgramObjectARB(0);CHECKGLERROR
1538 extern rtexture_t *r_shadow_attenuationgradienttexture;
1539 extern rtexture_t *r_shadow_attenuation2dtexture;
1540 extern rtexture_t *r_shadow_attenuation3dtexture;
1541 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1543 // select a permutation of the lighting shader appropriate to this
1544 // combination of texture, entity, light source, and fogging, only use the
1545 // minimum features necessary to avoid wasting rendering time in the
1546 // fragment shader on features that are not being used
1547 unsigned int permutation = 0;
1548 shadermode_t mode = 0;
1549 // TODO: implement geometry-shader based shadow volumes someday
1550 if (r_glsl_offsetmapping.integer)
1552 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1553 if (r_glsl_offsetmapping_reliefmapping.integer)
1554 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1556 if (rsurfacepass == RSURFPASS_BACKGROUND)
1558 // distorted background
1559 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1560 mode = SHADERMODE_WATER;
1562 mode = SHADERMODE_REFRACTION;
1564 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1567 mode = SHADERMODE_LIGHTSOURCE;
1568 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1569 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1570 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1571 permutation |= SHADERPERMUTATION_CUBEFILTER;
1572 if (diffusescale > 0)
1573 permutation |= SHADERPERMUTATION_DIFFUSE;
1574 if (specularscale > 0)
1575 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1576 if (r_refdef.fogenabled)
1577 permutation |= SHADERPERMUTATION_FOG;
1578 if (rsurface.texture->colormapping)
1579 permutation |= SHADERPERMUTATION_COLORMAPPING;
1580 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1581 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1583 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1585 // unshaded geometry (fullbright or ambient model lighting)
1586 mode = SHADERMODE_FLATCOLOR;
1587 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1588 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1589 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1590 permutation |= SHADERPERMUTATION_GLOW;
1591 if (r_refdef.fogenabled)
1592 permutation |= SHADERPERMUTATION_FOG;
1593 if (rsurface.texture->colormapping)
1594 permutation |= SHADERPERMUTATION_COLORMAPPING;
1595 if (r_glsl_offsetmapping.integer)
1597 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1598 if (r_glsl_offsetmapping_reliefmapping.integer)
1599 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1601 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1602 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1603 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1604 permutation |= SHADERPERMUTATION_REFLECTION;
1606 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1608 // directional model lighting
1609 mode = SHADERMODE_LIGHTDIRECTION;
1610 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1611 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1612 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1613 permutation |= SHADERPERMUTATION_GLOW;
1614 permutation |= SHADERPERMUTATION_DIFFUSE;
1615 if (specularscale > 0)
1616 permutation |= SHADERPERMUTATION_SPECULAR;
1617 if (r_refdef.fogenabled)
1618 permutation |= SHADERPERMUTATION_FOG;
1619 if (rsurface.texture->colormapping)
1620 permutation |= SHADERPERMUTATION_COLORMAPPING;
1621 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1622 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1623 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1624 permutation |= SHADERPERMUTATION_REFLECTION;
1626 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1628 // ambient model lighting
1629 mode = SHADERMODE_LIGHTDIRECTION;
1630 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1631 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1632 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1633 permutation |= SHADERPERMUTATION_GLOW;
1634 if (r_refdef.fogenabled)
1635 permutation |= SHADERPERMUTATION_FOG;
1636 if (rsurface.texture->colormapping)
1637 permutation |= SHADERPERMUTATION_COLORMAPPING;
1638 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1639 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1640 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1641 permutation |= SHADERPERMUTATION_REFLECTION;
1646 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1648 // deluxemapping (light direction texture)
1649 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1650 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1652 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1653 permutation |= SHADERPERMUTATION_DIFFUSE;
1654 if (specularscale > 0)
1655 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1657 else if (r_glsl_deluxemapping.integer >= 2)
1659 // fake deluxemapping (uniform light direction in tangentspace)
1660 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1661 permutation |= SHADERPERMUTATION_DIFFUSE;
1662 if (specularscale > 0)
1663 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1665 else if (rsurface.uselightmaptexture)
1667 // ordinary lightmapping (q1bsp, q3bsp)
1668 mode = SHADERMODE_LIGHTMAP;
1672 // ordinary vertex coloring (q3bsp)
1673 mode = SHADERMODE_VERTEXCOLOR;
1675 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1676 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1677 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1678 permutation |= SHADERPERMUTATION_GLOW;
1679 if (r_refdef.fogenabled)
1680 permutation |= SHADERPERMUTATION_FOG;
1681 if (rsurface.texture->colormapping)
1682 permutation |= SHADERPERMUTATION_COLORMAPPING;
1683 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1684 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1685 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1686 permutation |= SHADERPERMUTATION_REFLECTION;
1688 if(permutation & SHADERPERMUTATION_SPECULAR)
1689 if(r_shadow_glossexact.integer)
1690 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
1691 R_SetupShader_SetPermutation(mode, permutation);
1692 if (mode == SHADERMODE_LIGHTSOURCE)
1694 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1695 if (permutation & SHADERPERMUTATION_DIFFUSE)
1697 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1698 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1699 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1700 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1704 // ambient only is simpler
1705 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]);
1706 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1707 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1708 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1710 // additive passes are only darkened by fog, not tinted
1711 if (r_glsl_permutation->loc_FogColor >= 0)
1712 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1716 if (mode == SHADERMODE_LIGHTDIRECTION)
1718 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);
1719 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);
1720 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);
1721 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]);
1725 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
1726 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1727 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1729 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]);
1730 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1731 // additive passes are only darkened by fog, not tinted
1732 if (r_glsl_permutation->loc_FogColor >= 0)
1734 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1735 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1737 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1739 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);
1740 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]);
1741 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]);
1742 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1743 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1744 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1745 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1747 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1749 // The formula used is actually:
1750 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1751 // color.rgb *= SceneBrightness;
1753 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1754 // and do [[calculations]] here in the engine
1755 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1756 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1759 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1760 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1761 if (r_glsl_permutation->loc_Color_Pants >= 0)
1763 if (rsurface.texture->currentskinframe->pants)
1764 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1766 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1768 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1770 if (rsurface.texture->currentskinframe->shirt)
1771 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1773 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1775 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
1776 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
1778 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
1782 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1784 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1788 #define SKINFRAME_HASH 1024
1792 int loadsequence; // incremented each level change
1793 memexpandablearray_t array;
1794 skinframe_t *hash[SKINFRAME_HASH];
1798 void R_SkinFrame_PrepareForPurge(void)
1800 r_skinframe.loadsequence++;
1801 // wrap it without hitting zero
1802 if (r_skinframe.loadsequence >= 200)
1803 r_skinframe.loadsequence = 1;
1806 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1810 // mark the skinframe as used for the purging code
1811 skinframe->loadsequence = r_skinframe.loadsequence;
1814 void R_SkinFrame_Purge(void)
1818 for (i = 0;i < SKINFRAME_HASH;i++)
1820 for (s = r_skinframe.hash[i];s;s = s->next)
1822 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1824 if (s->merged == s->base)
1826 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1827 R_PurgeTexture(s->stain );s->stain = NULL;
1828 R_PurgeTexture(s->merged);s->merged = NULL;
1829 R_PurgeTexture(s->base );s->base = NULL;
1830 R_PurgeTexture(s->pants );s->pants = NULL;
1831 R_PurgeTexture(s->shirt );s->shirt = NULL;
1832 R_PurgeTexture(s->nmap );s->nmap = NULL;
1833 R_PurgeTexture(s->gloss );s->gloss = NULL;
1834 R_PurgeTexture(s->glow );s->glow = NULL;
1835 R_PurgeTexture(s->fog );s->fog = NULL;
1836 s->loadsequence = 0;
1842 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1844 char basename[MAX_QPATH];
1846 Image_StripImageExtension(name, basename, sizeof(basename));
1848 if( last == NULL ) {
1850 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1851 item = r_skinframe.hash[hashindex];
1856 // linearly search through the hash bucket
1857 for( ; item ; item = item->next ) {
1858 if( !strcmp( item->basename, basename ) ) {
1865 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1869 char basename[MAX_QPATH];
1871 Image_StripImageExtension(name, basename, sizeof(basename));
1873 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1874 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1875 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1879 rtexture_t *dyntexture;
1880 // check whether its a dynamic texture
1881 dyntexture = CL_GetDynTexture( basename );
1882 if (!add && !dyntexture)
1884 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1885 memset(item, 0, sizeof(*item));
1886 strlcpy(item->basename, basename, sizeof(item->basename));
1887 item->base = dyntexture; // either NULL or dyntexture handle
1888 item->textureflags = textureflags;
1889 item->comparewidth = comparewidth;
1890 item->compareheight = compareheight;
1891 item->comparecrc = comparecrc;
1892 item->next = r_skinframe.hash[hashindex];
1893 r_skinframe.hash[hashindex] = item;
1895 else if( item->base == NULL )
1897 rtexture_t *dyntexture;
1898 // check whether its a dynamic texture
1899 // 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]
1900 dyntexture = CL_GetDynTexture( basename );
1901 item->base = dyntexture; // either NULL or dyntexture handle
1904 R_SkinFrame_MarkUsed(item);
1908 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
1910 // FIXME: it should be possible to disable loading various layers using
1911 // cvars, to prevent wasted loading time and memory usage if the user does
1913 qboolean loadnormalmap = true;
1914 qboolean loadgloss = true;
1915 qboolean loadpantsandshirt = true;
1916 qboolean loadglow = true;
1918 unsigned char *pixels;
1919 unsigned char *bumppixels;
1920 unsigned char *basepixels = NULL;
1921 int basepixels_width;
1922 int basepixels_height;
1923 skinframe_t *skinframe;
1924 double avgcolor[4], w, wsum;
1928 if (cls.state == ca_dedicated)
1931 // return an existing skinframe if already loaded
1932 // if loading of the first image fails, don't make a new skinframe as it
1933 // would cause all future lookups of this to be missing
1934 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1935 if (skinframe && skinframe->base)
1938 basepixels = loadimagepixelsbgra(name, complain, true);
1939 if (basepixels == NULL)
1942 if (developer_loading.integer)
1943 Con_Printf("loading skin \"%s\"\n", name);
1945 // we've got some pixels to store, so really allocate this new texture now
1947 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1948 skinframe->stain = NULL;
1949 skinframe->merged = NULL;
1950 skinframe->base = r_texture_notexture;
1951 skinframe->pants = NULL;
1952 skinframe->shirt = NULL;
1953 skinframe->nmap = r_texture_blanknormalmap;
1954 skinframe->gloss = NULL;
1955 skinframe->glow = NULL;
1956 skinframe->fog = NULL;
1958 basepixels_width = image_width;
1959 basepixels_height = image_height;
1960 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);
1962 if (textureflags & TEXF_ALPHA)
1964 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1965 if (basepixels[j] < 255)
1967 if (j < basepixels_width * basepixels_height * 4)
1969 // has transparent pixels
1971 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1972 for (j = 0;j < image_width * image_height * 4;j += 4)
1977 pixels[j+3] = basepixels[j+3];
1979 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);
1989 for(j = 0; j < basepixels_width * basepixels_height * 4; j += 4)
1991 w = (int)basepixels[j + 0] + (int)basepixels[j + 1] + (int)basepixels[j + 2]; // use this weight, so black pixels don't contribute (needed for model skins)
1992 avgcolor[2] += basepixels[j + 0] * w;
1993 avgcolor[1] += basepixels[j + 1] * w;
1994 avgcolor[0] += basepixels[j + 2] * w;
1995 avgcolor[3] += basepixels[j + 3] * w;
1998 if(avgcolor[3] == 0) // just fully transparent pixels seen? bad luck...
1999 avgcolor[3] = 255.0 * wsum;
2000 if(avgcolor[3] == 0) // no pixels seen? even worse
2002 avgcolor[0] /= avgcolor[3];
2003 avgcolor[1] /= avgcolor[3];
2004 avgcolor[2] /= avgcolor[3];
2005 avgcolor[3] /= 255.0 * wsum; // to 0..1 range
2006 skinframe->avgcolor[0] = avgcolor[0];
2007 skinframe->avgcolor[1] = avgcolor[1];
2008 skinframe->avgcolor[2] = avgcolor[2];
2009 skinframe->avgcolor[3] = avgcolor[3];
2011 // _norm is the name used by tenebrae and has been adopted as standard
2014 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2016 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);
2020 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2022 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2023 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2024 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);
2026 Mem_Free(bumppixels);
2028 else if (r_shadow_bumpscale_basetexture.value > 0)
2030 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2031 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2032 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);
2036 // _luma is supported for tenebrae compatibility
2037 // (I think it's a very stupid name, but oh well)
2038 // _glow is the preferred name
2039 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;}
2040 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;}
2041 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;}
2042 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;}
2045 Mem_Free(basepixels);
2050 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2053 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2056 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)
2061 for (i = 0;i < width*height;i++)
2062 if (((unsigned char *)&palette[in[i]])[3] > 0)
2064 if (i == width*height)
2067 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2070 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2071 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2074 unsigned char *temp1, *temp2;
2075 skinframe_t *skinframe;
2076 double avgcolor[4], w, wsum;
2079 if (cls.state == ca_dedicated)
2082 // if already loaded just return it, otherwise make a new skinframe
2083 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2084 if (skinframe && skinframe->base)
2087 skinframe->stain = NULL;
2088 skinframe->merged = NULL;
2089 skinframe->base = r_texture_notexture;
2090 skinframe->pants = NULL;
2091 skinframe->shirt = NULL;
2092 skinframe->nmap = r_texture_blanknormalmap;
2093 skinframe->gloss = NULL;
2094 skinframe->glow = NULL;
2095 skinframe->fog = NULL;
2097 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2101 if (developer_loading.integer)
2102 Con_Printf("loading 32bit skin \"%s\"\n", name);
2104 if (r_shadow_bumpscale_basetexture.value > 0)
2106 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2107 temp2 = temp1 + width * height * 4;
2108 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2109 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2112 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2113 if (textureflags & TEXF_ALPHA)
2115 for (i = 3;i < width * height * 4;i += 4)
2116 if (skindata[i] < 255)
2118 if (i < width * height * 4)
2120 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2121 memcpy(fogpixels, skindata, width * height * 4);
2122 for (i = 0;i < width * height * 4;i += 4)
2123 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2124 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2125 Mem_Free(fogpixels);
2134 for(j = 0; j < width * height * 4; j += 4)
2136 w = (int)skindata[j + 0] + (int)skindata[j + 1] + (int)skindata[j + 2];
2137 avgcolor[2] += skindata[j + 0] * w;
2138 avgcolor[1] += skindata[j + 1] * w;
2139 avgcolor[0] += skindata[j + 2] * w;
2140 avgcolor[3] += skindata[j + 3] * w;
2143 if(avgcolor[3] == 0) // just fully transparent pixels seen? bad luck...
2144 avgcolor[3] = 255.0 * wsum;
2145 if(avgcolor[3] == 0) // no pixels seen? even worse
2147 avgcolor[0] /= avgcolor[3];
2148 avgcolor[1] /= avgcolor[3];
2149 avgcolor[2] /= avgcolor[3];
2150 avgcolor[3] /= 255.0 * wsum; // to 0..1 range
2151 skinframe->avgcolor[0] = avgcolor[0];
2152 skinframe->avgcolor[1] = avgcolor[1];
2153 skinframe->avgcolor[2] = avgcolor[2];
2154 skinframe->avgcolor[3] = avgcolor[3];
2159 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2162 unsigned char *temp1, *temp2;
2163 skinframe_t *skinframe;
2164 double avgcolor[4], w, wsum;
2167 if (cls.state == ca_dedicated)
2170 // if already loaded just return it, otherwise make a new skinframe
2171 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2172 if (skinframe && skinframe->base)
2175 skinframe->stain = NULL;
2176 skinframe->merged = NULL;
2177 skinframe->base = r_texture_notexture;
2178 skinframe->pants = NULL;
2179 skinframe->shirt = NULL;
2180 skinframe->nmap = r_texture_blanknormalmap;
2181 skinframe->gloss = NULL;
2182 skinframe->glow = NULL;
2183 skinframe->fog = NULL;
2185 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2189 if (developer_loading.integer)
2190 Con_Printf("loading quake skin \"%s\"\n", name);
2192 if (r_shadow_bumpscale_basetexture.value > 0)
2194 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2195 temp2 = temp1 + width * height * 4;
2196 // use either a custom palette or the quake palette
2197 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2198 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2199 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2202 // use either a custom palette, or the quake palette
2203 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete)), skinframe->textureflags, true); // all
2204 if (loadglowtexture)
2205 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2206 if (loadpantsandshirt)
2208 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2209 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2211 if (skinframe->pants || skinframe->shirt)
2212 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
2213 if (textureflags & TEXF_ALPHA)
2215 for (i = 0;i < width * height;i++)
2216 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2218 if (i < width * height)
2219 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2227 for(j = 0; j < width * height; ++j)
2229 temp1 = ((unsigned char *)palette_bgra_alpha) + (skindata[j]*4);
2230 w = (int)temp1[0] + (int)temp1[1] + (int)temp1[2];
2231 avgcolor[2] += temp1[0] * w;
2232 avgcolor[1] += temp1[1] * w;
2233 avgcolor[0] += temp1[2] * w;
2234 avgcolor[3] += temp1[3] * w;
2237 if(avgcolor[3] == 0) // just fully transparent pixels seen? bad luck...
2238 avgcolor[3] = 255.0 * wsum;
2239 if(avgcolor[3] == 0) // no pixels seen? even worse
2241 avgcolor[0] /= avgcolor[3];
2242 avgcolor[1] /= avgcolor[3];
2243 avgcolor[2] /= avgcolor[3];
2244 avgcolor[3] /= 255.0 * wsum; // to 0..1 range
2245 skinframe->avgcolor[0] = avgcolor[0];
2246 skinframe->avgcolor[1] = avgcolor[1];
2247 skinframe->avgcolor[2] = avgcolor[2];
2248 skinframe->avgcolor[3] = avgcolor[3];
2253 skinframe_t *R_SkinFrame_LoadMissing(void)
2255 skinframe_t *skinframe;
2257 if (cls.state == ca_dedicated)
2260 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
2261 skinframe->stain = NULL;
2262 skinframe->merged = NULL;
2263 skinframe->base = r_texture_notexture;
2264 skinframe->pants = NULL;
2265 skinframe->shirt = NULL;
2266 skinframe->nmap = r_texture_blanknormalmap;
2267 skinframe->gloss = NULL;
2268 skinframe->glow = NULL;
2269 skinframe->fog = NULL;
2271 skinframe->avgcolor[0] = rand() / RAND_MAX;
2272 skinframe->avgcolor[1] = rand() / RAND_MAX;
2273 skinframe->avgcolor[2] = rand() / RAND_MAX;
2274 skinframe->avgcolor[3] = 1;
2279 void gl_main_start(void)
2281 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2282 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2284 // set up r_skinframe loading system for textures
2285 memset(&r_skinframe, 0, sizeof(r_skinframe));
2286 r_skinframe.loadsequence = 1;
2287 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2289 r_main_texturepool = R_AllocTexturePool();
2290 R_BuildBlankTextures();
2292 if (gl_texturecubemap)
2295 R_BuildNormalizationCube();
2297 r_texture_fogattenuation = NULL;
2298 r_texture_gammaramps = NULL;
2299 //r_texture_fogintensity = NULL;
2300 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2301 memset(&r_waterstate, 0, sizeof(r_waterstate));
2302 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2303 memset(&r_svbsp, 0, sizeof (r_svbsp));
2305 r_refdef.fogmasktable_density = 0;
2308 void gl_main_shutdown(void)
2310 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2311 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2313 // clear out the r_skinframe state
2314 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2315 memset(&r_skinframe, 0, sizeof(r_skinframe));
2318 Mem_Free(r_svbsp.nodes);
2319 memset(&r_svbsp, 0, sizeof (r_svbsp));
2320 R_FreeTexturePool(&r_main_texturepool);
2321 r_texture_blanknormalmap = NULL;
2322 r_texture_white = NULL;
2323 r_texture_grey128 = NULL;
2324 r_texture_black = NULL;
2325 r_texture_whitecube = NULL;
2326 r_texture_normalizationcube = NULL;
2327 r_texture_fogattenuation = NULL;
2328 r_texture_gammaramps = NULL;
2329 //r_texture_fogintensity = NULL;
2330 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2331 memset(&r_waterstate, 0, sizeof(r_waterstate));
2335 extern void CL_ParseEntityLump(char *entitystring);
2336 void gl_main_newmap(void)
2338 // FIXME: move this code to client
2340 char *entities, entname[MAX_QPATH];
2343 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2344 l = (int)strlen(entname) - 4;
2345 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2347 memcpy(entname + l, ".ent", 5);
2348 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2350 CL_ParseEntityLump(entities);
2355 if (cl.worldmodel->brush.entities)
2356 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2360 void GL_Main_Init(void)
2362 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2364 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2365 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2366 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2367 if (gamemode == GAME_NEHAHRA)
2369 Cvar_RegisterVariable (&gl_fogenable);
2370 Cvar_RegisterVariable (&gl_fogdensity);
2371 Cvar_RegisterVariable (&gl_fogred);
2372 Cvar_RegisterVariable (&gl_foggreen);
2373 Cvar_RegisterVariable (&gl_fogblue);
2374 Cvar_RegisterVariable (&gl_fogstart);
2375 Cvar_RegisterVariable (&gl_fogend);
2376 Cvar_RegisterVariable (&gl_skyclip);
2378 Cvar_RegisterVariable(&r_depthfirst);
2379 Cvar_RegisterVariable(&r_useinfinitefarclip);
2380 Cvar_RegisterVariable(&r_nearclip);
2381 Cvar_RegisterVariable(&r_showbboxes);
2382 Cvar_RegisterVariable(&r_showsurfaces);
2383 Cvar_RegisterVariable(&r_showtris);
2384 Cvar_RegisterVariable(&r_shownormals);
2385 Cvar_RegisterVariable(&r_showlighting);
2386 Cvar_RegisterVariable(&r_showshadowvolumes);
2387 Cvar_RegisterVariable(&r_showcollisionbrushes);
2388 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2389 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2390 Cvar_RegisterVariable(&r_showdisabledepthtest);
2391 Cvar_RegisterVariable(&r_drawportals);
2392 Cvar_RegisterVariable(&r_drawentities);
2393 Cvar_RegisterVariable(&r_cullentities_trace);
2394 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2395 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2396 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2397 Cvar_RegisterVariable(&r_drawviewmodel);
2398 Cvar_RegisterVariable(&r_speeds);
2399 Cvar_RegisterVariable(&r_fullbrights);
2400 Cvar_RegisterVariable(&r_wateralpha);
2401 Cvar_RegisterVariable(&r_dynamic);
2402 Cvar_RegisterVariable(&r_fullbright);
2403 Cvar_RegisterVariable(&r_shadows);
2404 Cvar_RegisterVariable(&r_shadows_throwdistance);
2405 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2406 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2407 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2408 Cvar_RegisterVariable(&r_fog_exp2);
2409 Cvar_RegisterVariable(&r_drawfog);
2410 Cvar_RegisterVariable(&r_textureunits);
2411 Cvar_RegisterVariable(&r_glsl);
2412 Cvar_RegisterVariable(&r_glsl_contrastboost);
2413 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2414 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2415 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2416 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2417 Cvar_RegisterVariable(&r_glsl_postprocess);
2418 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2419 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2420 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2421 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2422 Cvar_RegisterVariable(&r_glsl_usegeneric);
2423 Cvar_RegisterVariable(&r_water);
2424 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2425 Cvar_RegisterVariable(&r_water_clippingplanebias);
2426 Cvar_RegisterVariable(&r_water_refractdistort);
2427 Cvar_RegisterVariable(&r_water_reflectdistort);
2428 Cvar_RegisterVariable(&r_lerpsprites);
2429 Cvar_RegisterVariable(&r_lerpmodels);
2430 Cvar_RegisterVariable(&r_lerplightstyles);
2431 Cvar_RegisterVariable(&r_waterscroll);
2432 Cvar_RegisterVariable(&r_bloom);
2433 Cvar_RegisterVariable(&r_bloom_colorscale);
2434 Cvar_RegisterVariable(&r_bloom_brighten);
2435 Cvar_RegisterVariable(&r_bloom_blur);
2436 Cvar_RegisterVariable(&r_bloom_resolution);
2437 Cvar_RegisterVariable(&r_bloom_colorexponent);
2438 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2439 Cvar_RegisterVariable(&r_hdr);
2440 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2441 Cvar_RegisterVariable(&r_hdr_glowintensity);
2442 Cvar_RegisterVariable(&r_hdr_range);
2443 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2444 Cvar_RegisterVariable(&developer_texturelogging);
2445 Cvar_RegisterVariable(&gl_lightmaps);
2446 Cvar_RegisterVariable(&r_test);
2447 Cvar_RegisterVariable(&r_batchmode);
2448 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2449 Cvar_SetValue("r_fullbrights", 0);
2450 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2452 Cvar_RegisterVariable(&r_track_sprites);
2453 Cvar_RegisterVariable(&r_track_sprites_flags);
2454 Cvar_RegisterVariable(&r_track_sprites_scalew);
2455 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2458 extern void R_Textures_Init(void);
2459 extern void GL_Draw_Init(void);
2460 extern void GL_Main_Init(void);
2461 extern void R_Shadow_Init(void);
2462 extern void R_Sky_Init(void);
2463 extern void GL_Surf_Init(void);
2464 extern void R_Particles_Init(void);
2465 extern void R_Explosion_Init(void);
2466 extern void gl_backend_init(void);
2467 extern void Sbar_Init(void);
2468 extern void R_LightningBeams_Init(void);
2469 extern void Mod_RenderInit(void);
2471 void Render_Init(void)
2483 R_LightningBeams_Init();
2492 extern char *ENGINE_EXTENSIONS;
2495 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2496 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2497 gl_version = (const char *)qglGetString(GL_VERSION);
2498 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2502 if (!gl_platformextensions)
2503 gl_platformextensions = "";
2505 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2506 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2507 Con_Printf("GL_VERSION: %s\n", gl_version);
2508 Con_Printf("GL_EXTENSIONS: %s\n", gl_extensions);
2509 Con_Printf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2511 VID_CheckExtensions();
2513 // LordHavoc: report supported extensions
2514 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2516 // clear to black (loading plaque will be seen over this)
2518 qglClearColor(0,0,0,1);CHECKGLERROR
2519 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2522 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2526 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2528 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2531 p = r_refdef.view.frustum + i;
2536 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2540 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2544 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2548 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2552 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2556 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2560 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2564 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2572 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2576 for (i = 0;i < numplanes;i++)
2583 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2587 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2591 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2595 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2599 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2603 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2607 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2611 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2619 //==================================================================================
2621 static void R_View_UpdateEntityVisible (void)
2624 entity_render_t *ent;
2626 if (!r_drawentities.integer)
2629 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2630 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2632 // worldmodel can check visibility
2633 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
2634 for (i = 0;i < r_refdef.scene.numentities;i++)
2636 ent = r_refdef.scene.entities[i];
2637 if (!(ent->flags & renderimask))
2638 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)))
2639 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))
2640 r_refdef.viewcache.entityvisible[i] = true;
2642 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2644 for (i = 0;i < r_refdef.scene.numentities;i++)
2646 ent = r_refdef.scene.entities[i];
2647 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2649 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))
2650 ent->last_trace_visibility = realtime;
2651 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2652 r_refdef.viewcache.entityvisible[i] = 0;
2659 // no worldmodel or it can't check visibility
2660 for (i = 0;i < r_refdef.scene.numentities;i++)
2662 ent = r_refdef.scene.entities[i];
2663 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));
2668 // only used if skyrendermasked, and normally returns false
2669 int R_DrawBrushModelsSky (void)
2672 entity_render_t *ent;
2674 if (!r_drawentities.integer)
2678 for (i = 0;i < r_refdef.scene.numentities;i++)
2680 if (!r_refdef.viewcache.entityvisible[i])
2682 ent = r_refdef.scene.entities[i];
2683 if (!ent->model || !ent->model->DrawSky)
2685 ent->model->DrawSky(ent);
2691 static void R_DrawNoModel(entity_render_t *ent);
2692 static void R_DrawModels(void)
2695 entity_render_t *ent;
2697 if (!r_drawentities.integer)
2700 for (i = 0;i < r_refdef.scene.numentities;i++)
2702 if (!r_refdef.viewcache.entityvisible[i])
2704 ent = r_refdef.scene.entities[i];
2705 r_refdef.stats.entities++;
2706 if (ent->model && ent->model->Draw != NULL)
2707 ent->model->Draw(ent);
2713 static void R_DrawModelsDepth(void)
2716 entity_render_t *ent;
2718 if (!r_drawentities.integer)
2721 for (i = 0;i < r_refdef.scene.numentities;i++)
2723 if (!r_refdef.viewcache.entityvisible[i])
2725 ent = r_refdef.scene.entities[i];
2726 if (ent->model && ent->model->DrawDepth != NULL)
2727 ent->model->DrawDepth(ent);
2731 static void R_DrawModelsDebug(void)
2734 entity_render_t *ent;
2736 if (!r_drawentities.integer)
2739 for (i = 0;i < r_refdef.scene.numentities;i++)
2741 if (!r_refdef.viewcache.entityvisible[i])
2743 ent = r_refdef.scene.entities[i];
2744 if (ent->model && ent->model->DrawDebug != NULL)
2745 ent->model->DrawDebug(ent);
2749 static void R_DrawModelsAddWaterPlanes(void)
2752 entity_render_t *ent;
2754 if (!r_drawentities.integer)
2757 for (i = 0;i < r_refdef.scene.numentities;i++)
2759 if (!r_refdef.viewcache.entityvisible[i])
2761 ent = r_refdef.scene.entities[i];
2762 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2763 ent->model->DrawAddWaterPlanes(ent);
2767 static void R_View_SetFrustum(void)
2770 double slopex, slopey;
2771 vec3_t forward, left, up, origin;
2773 // we can't trust r_refdef.view.forward and friends in reflected scenes
2774 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2777 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2778 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2779 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2780 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2781 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2782 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2783 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2784 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2785 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2786 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2787 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2788 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2792 zNear = r_refdef.nearclip;
2793 nudge = 1.0 - 1.0 / (1<<23);
2794 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2795 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2796 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2797 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2798 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2799 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2800 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2801 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2807 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2808 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2809 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2810 r_refdef.view.frustum[0].dist = m[15] - m[12];
2812 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2813 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2814 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2815 r_refdef.view.frustum[1].dist = m[15] + m[12];
2817 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2818 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2819 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2820 r_refdef.view.frustum[2].dist = m[15] - m[13];
2822 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2823 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2824 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2825 r_refdef.view.frustum[3].dist = m[15] + m[13];
2827 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2828 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2829 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2830 r_refdef.view.frustum[4].dist = m[15] - m[14];
2832 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2833 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2834 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2835 r_refdef.view.frustum[5].dist = m[15] + m[14];
2838 if (r_refdef.view.useperspective)
2840 slopex = 1.0 / r_refdef.view.frustum_x;
2841 slopey = 1.0 / r_refdef.view.frustum_y;
2842 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2843 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
2844 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
2845 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
2846 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2848 // Leaving those out was a mistake, those were in the old code, and they
2849 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2850 // I couldn't reproduce it after adding those normalizations. --blub
2851 VectorNormalize(r_refdef.view.frustum[0].normal);
2852 VectorNormalize(r_refdef.view.frustum[1].normal);
2853 VectorNormalize(r_refdef.view.frustum[2].normal);
2854 VectorNormalize(r_refdef.view.frustum[3].normal);
2856 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2857 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2858 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2859 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2860 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2862 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2863 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2864 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2865 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2866 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2870 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2871 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2872 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2873 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2874 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2875 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2876 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2877 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2878 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2879 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2881 r_refdef.view.numfrustumplanes = 5;
2883 if (r_refdef.view.useclipplane)
2885 r_refdef.view.numfrustumplanes = 6;
2886 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2889 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2890 PlaneClassify(r_refdef.view.frustum + i);
2892 // LordHavoc: note to all quake engine coders, Quake had a special case
2893 // for 90 degrees which assumed a square view (wrong), so I removed it,
2894 // Quake2 has it disabled as well.
2896 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2897 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2898 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2899 //PlaneClassify(&frustum[0]);
2901 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2902 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2903 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2904 //PlaneClassify(&frustum[1]);
2906 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2907 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2908 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2909 //PlaneClassify(&frustum[2]);
2911 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2912 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2913 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2914 //PlaneClassify(&frustum[3]);
2917 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2918 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2919 //PlaneClassify(&frustum[4]);
2922 void R_View_Update(void)
2924 R_View_SetFrustum();
2925 R_View_WorldVisibility(r_refdef.view.useclipplane);
2926 R_View_UpdateEntityVisible();
2929 void R_SetupView(qboolean allowwaterclippingplane)
2931 if (!r_refdef.view.useperspective)
2932 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);
2933 else if (gl_stencil && r_useinfinitefarclip.integer)
2934 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2936 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2938 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2940 if (r_refdef.view.useclipplane && allowwaterclippingplane)
2942 // LordHavoc: couldn't figure out how to make this approach the
2943 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2944 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2945 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2946 dist = r_refdef.view.clipplane.dist;
2947 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2951 void R_ResetViewRendering2D(void)
2955 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2956 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2957 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2958 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2959 GL_Color(1, 1, 1, 1);
2960 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2961 GL_BlendFunc(GL_ONE, GL_ZERO);
2962 GL_AlphaTest(false);
2963 GL_ScissorTest(false);
2964 GL_DepthMask(false);
2965 GL_DepthRange(0, 1);
2966 GL_DepthTest(false);
2967 R_Mesh_Matrix(&identitymatrix);
2968 R_Mesh_ResetTextureState();
2969 GL_PolygonOffset(0, 0);
2970 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2971 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2972 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2973 qglStencilMask(~0);CHECKGLERROR
2974 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2975 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2976 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2977 R_SetupGenericShader(true);
2980 void R_ResetViewRendering3D(void)
2984 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2985 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2987 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2988 GL_Color(1, 1, 1, 1);
2989 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2990 GL_BlendFunc(GL_ONE, GL_ZERO);
2991 GL_AlphaTest(false);
2992 GL_ScissorTest(true);
2994 GL_DepthRange(0, 1);
2996 R_Mesh_Matrix(&identitymatrix);
2997 R_Mesh_ResetTextureState();
2998 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2999 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3000 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3001 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3002 qglStencilMask(~0);CHECKGLERROR
3003 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3004 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3005 GL_CullFace(r_refdef.view.cullface_back);
3006 R_SetupGenericShader(true);
3009 void R_RenderScene(qboolean addwaterplanes);
3011 static void R_Water_StartFrame(void)
3014 int waterwidth, waterheight, texturewidth, textureheight;
3015 r_waterstate_waterplane_t *p;
3017 // set waterwidth and waterheight to the water resolution that will be
3018 // used (often less than the screen resolution for faster rendering)
3019 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3020 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3022 // calculate desired texture sizes
3023 // can't use water if the card does not support the texture size
3024 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
3025 texturewidth = textureheight = waterwidth = waterheight = 0;
3026 else if (gl_support_arb_texture_non_power_of_two)
3028 texturewidth = waterwidth;
3029 textureheight = waterheight;
3033 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3034 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3037 // allocate textures as needed
3038 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3040 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3041 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3043 if (p->texture_refraction)
3044 R_FreeTexture(p->texture_refraction);
3045 p->texture_refraction = NULL;
3046 if (p->texture_reflection)
3047 R_FreeTexture(p->texture_reflection);
3048 p->texture_reflection = NULL;
3050 memset(&r_waterstate, 0, sizeof(r_waterstate));
3051 r_waterstate.waterwidth = waterwidth;
3052 r_waterstate.waterheight = waterheight;
3053 r_waterstate.texturewidth = texturewidth;
3054 r_waterstate.textureheight = textureheight;
3057 if (r_waterstate.waterwidth)
3059 r_waterstate.enabled = true;
3061 // set up variables that will be used in shader setup
3062 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3063 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3064 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3065 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3068 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3069 r_waterstate.numwaterplanes = 0;
3072 static void R_Water_AddWaterPlane(msurface_t *surface)
3074 int triangleindex, planeindex;
3080 r_waterstate_waterplane_t *p;
3081 // just use the first triangle with a valid normal for any decisions
3082 VectorClear(normal);
3083 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3085 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3086 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3087 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3088 TriangleNormal(vert[0], vert[1], vert[2], normal);
3089 if (VectorLength2(normal) >= 0.001)
3093 VectorCopy(normal, plane.normal);
3094 VectorNormalize(plane.normal);
3095 plane.dist = DotProduct(vert[0], plane.normal);
3096 PlaneClassify(&plane);
3097 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3099 // skip backfaces (except if nocullface is set)
3100 if (!(surface->texture->currentframe->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3102 VectorNegate(plane.normal, plane.normal);
3104 PlaneClassify(&plane);
3108 // find a matching plane if there is one
3109 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3110 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3112 if (planeindex >= r_waterstate.maxwaterplanes)
3113 return; // nothing we can do, out of planes
3115 // if this triangle does not fit any known plane rendered this frame, add one
3116 if (planeindex >= r_waterstate.numwaterplanes)
3118 // store the new plane
3119 r_waterstate.numwaterplanes++;
3121 // clear materialflags and pvs
3122 p->materialflags = 0;
3123 p->pvsvalid = false;
3125 // merge this surface's materialflags into the waterplane
3126 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
3127 // merge this surface's PVS into the waterplane
3128 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3129 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3130 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3132 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3137 static void R_Water_ProcessPlanes(void)
3139 r_refdef_view_t originalview;
3141 r_waterstate_waterplane_t *p;
3143 originalview = r_refdef.view;
3145 // make sure enough textures are allocated
3146 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3148 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3150 if (!p->texture_refraction)
3151 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);
3152 if (!p->texture_refraction)
3156 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3158 if (!p->texture_reflection)
3159 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);
3160 if (!p->texture_reflection)
3166 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3168 r_refdef.view.showdebug = false;
3169 r_refdef.view.width = r_waterstate.waterwidth;
3170 r_refdef.view.height = r_waterstate.waterheight;
3171 r_refdef.view.useclipplane = true;
3172 r_waterstate.renderingscene = true;
3174 // render the normal view scene and copy into texture
3175 // (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)
3176 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3178 r_refdef.view.clipplane = p->plane;
3179 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3180 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3181 PlaneClassify(&r_refdef.view.clipplane);
3183 R_RenderScene(false);
3185 // copy view into the screen texture
3186 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3187 GL_ActiveTexture(0);
3189 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
3192 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3194 // render reflected scene and copy into texture
3195 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3196 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3197 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3198 r_refdef.view.clipplane = p->plane;
3199 // reverse the cullface settings for this render
3200 r_refdef.view.cullface_front = GL_FRONT;
3201 r_refdef.view.cullface_back = GL_BACK;
3202 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3204 r_refdef.view.usecustompvs = true;
3206 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3208 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3211 R_ResetViewRendering3D();
3212 R_ClearScreen(r_refdef.fogenabled);
3213 if (r_timereport_active)
3214 R_TimeReport("viewclear");
3216 R_RenderScene(false);
3218 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3219 GL_ActiveTexture(0);
3221 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
3223 R_ResetViewRendering3D();
3224 R_ClearScreen(r_refdef.fogenabled);
3225 if (r_timereport_active)
3226 R_TimeReport("viewclear");
3229 r_refdef.view = originalview;
3230 r_refdef.view.clear = true;
3231 r_waterstate.renderingscene = false;
3235 r_refdef.view = originalview;
3236 r_waterstate.renderingscene = false;
3237 Cvar_SetValueQuick(&r_water, 0);
3238 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3242 void R_Bloom_StartFrame(void)
3244 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3246 // set bloomwidth and bloomheight to the bloom resolution that will be
3247 // used (often less than the screen resolution for faster rendering)
3248 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3249 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3250 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3251 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3252 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3254 // calculate desired texture sizes
3255 if (gl_support_arb_texture_non_power_of_two)
3257 screentexturewidth = r_refdef.view.width;
3258 screentextureheight = r_refdef.view.height;
3259 bloomtexturewidth = r_bloomstate.bloomwidth;
3260 bloomtextureheight = r_bloomstate.bloomheight;
3264 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3265 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3266 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3267 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3270 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))
3272 Cvar_SetValueQuick(&r_hdr, 0);
3273 Cvar_SetValueQuick(&r_bloom, 0);
3276 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (v_glslgamma.integer && !vid_gammatables_trivial) || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
3277 screentexturewidth = screentextureheight = 0;
3278 if (!r_hdr.integer && !r_bloom.integer)
3279 bloomtexturewidth = bloomtextureheight = 0;
3281 // allocate textures as needed
3282 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3284 if (r_bloomstate.texture_screen)
3285 R_FreeTexture(r_bloomstate.texture_screen);
3286 r_bloomstate.texture_screen = NULL;
3287 r_bloomstate.screentexturewidth = screentexturewidth;
3288 r_bloomstate.screentextureheight = screentextureheight;
3289 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3290 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);
3292 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3294 if (r_bloomstate.texture_bloom)
3295 R_FreeTexture(r_bloomstate.texture_bloom);
3296 r_bloomstate.texture_bloom = NULL;
3297 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3298 r_bloomstate.bloomtextureheight = bloomtextureheight;
3299 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3300 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);
3303 // set up a texcoord array for the full resolution screen image
3304 // (we have to keep this around to copy back during final render)
3305 r_bloomstate.screentexcoord2f[0] = 0;
3306 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3307 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3308 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3309 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3310 r_bloomstate.screentexcoord2f[5] = 0;
3311 r_bloomstate.screentexcoord2f[6] = 0;
3312 r_bloomstate.screentexcoord2f[7] = 0;
3314 // set up a texcoord array for the reduced resolution bloom image
3315 // (which will be additive blended over the screen image)
3316 r_bloomstate.bloomtexcoord2f[0] = 0;
3317 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3318 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3319 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3320 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3321 r_bloomstate.bloomtexcoord2f[5] = 0;
3322 r_bloomstate.bloomtexcoord2f[6] = 0;
3323 r_bloomstate.bloomtexcoord2f[7] = 0;
3325 if (r_hdr.integer || r_bloom.integer)
3327 r_bloomstate.enabled = true;
3328 r_bloomstate.hdr = r_hdr.integer != 0;
3332 void R_Bloom_CopyBloomTexture(float colorscale)
3334 r_refdef.stats.bloom++;
3336 // scale down screen texture to the bloom texture size
3338 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3339 GL_BlendFunc(GL_ONE, GL_ZERO);
3340 GL_Color(colorscale, colorscale, colorscale, 1);
3341 // TODO: optimize with multitexture or GLSL
3342 R_SetupGenericShader(true);
3343 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3344 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3345 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3346 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3348 // we now have a bloom image in the framebuffer
3349 // copy it into the bloom image texture for later processing
3350 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3351 GL_ActiveTexture(0);
3353 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
3354 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3357 void R_Bloom_CopyHDRTexture(void)
3359 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3360 GL_ActiveTexture(0);
3362 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
3363 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3366 void R_Bloom_MakeTexture(void)
3369 float xoffset, yoffset, r, brighten;
3371 r_refdef.stats.bloom++;
3373 R_ResetViewRendering2D();
3374 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3375 R_Mesh_ColorPointer(NULL, 0, 0);
3376 R_SetupGenericShader(true);
3378 // we have a bloom image in the framebuffer
3380 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3382 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3385 r = bound(0, r_bloom_colorexponent.value / x, 1);
3386 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3387 GL_Color(r, r, r, 1);
3388 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3389 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3390 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3391 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3393 // copy the vertically blurred bloom view to a texture
3394 GL_ActiveTexture(0);
3396 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
3397 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3400 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3401 brighten = r_bloom_brighten.value;
3403 brighten *= r_hdr_range.value;
3404 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3405 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3407 for (dir = 0;dir < 2;dir++)
3409 // blend on at multiple vertical offsets to achieve a vertical blur
3410 // TODO: do offset blends using GLSL
3411 GL_BlendFunc(GL_ONE, GL_ZERO);
3412 for (x = -range;x <= range;x++)
3414 if (!dir){xoffset = 0;yoffset = x;}
3415 else {xoffset = x;yoffset = 0;}
3416 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3417 yoffset /= (float)r_bloomstate.bloomtextureheight;
3418 // compute a texcoord array with the specified x and y offset
3419 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3420 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3421 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3422 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3423 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3424 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3425 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3426 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3427 // this r value looks like a 'dot' particle, fading sharply to
3428 // black at the edges
3429 // (probably not realistic but looks good enough)
3430 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3431 //r = (dir ? 1.0f : brighten)/(range*2+1);
3432 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3433 GL_Color(r, r, r, 1);
3434 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3435 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3436 GL_BlendFunc(GL_ONE, GL_ONE);
3439 // copy the vertically blurred bloom view to a texture
3440 GL_ActiveTexture(0);
3442 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
3443 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3446 // apply subtract last
3447 // (just like it would be in a GLSL shader)
3448 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3450 GL_BlendFunc(GL_ONE, GL_ZERO);
3451 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3452 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3453 GL_Color(1, 1, 1, 1);
3454 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3455 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3457 GL_BlendFunc(GL_ONE, GL_ONE);
3458 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3459 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3460 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3461 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3462 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3463 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3464 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3466 // copy the darkened bloom view to a texture
3467 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3468 GL_ActiveTexture(0);
3470 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
3471 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3475 void R_HDR_RenderBloomTexture(void)
3477 int oldwidth, oldheight;
3478 float oldcolorscale;
3480 oldcolorscale = r_refdef.view.colorscale;
3481 oldwidth = r_refdef.view.width;
3482 oldheight = r_refdef.view.height;
3483 r_refdef.view.width = r_bloomstate.bloomwidth;
3484 r_refdef.view.height = r_bloomstate.bloomheight;
3486 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3487 // TODO: add exposure compensation features
3488 // TODO: add fp16 framebuffer support
3490 r_refdef.view.showdebug = false;
3491 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3493 R_ClearScreen(r_refdef.fogenabled);
3494 if (r_timereport_active)
3495 R_TimeReport("HDRclear");
3497 r_waterstate.numwaterplanes = 0;
3498 R_RenderScene(r_waterstate.enabled);
3499 r_refdef.view.showdebug = true;
3501 R_ResetViewRendering2D();
3503 R_Bloom_CopyHDRTexture();
3504 R_Bloom_MakeTexture();
3506 // restore the view settings
3507 r_refdef.view.width = oldwidth;
3508 r_refdef.view.height = oldheight;
3509 r_refdef.view.colorscale = oldcolorscale;
3511 R_ResetViewRendering3D();
3513 R_ClearScreen(r_refdef.fogenabled);
3514 if (r_timereport_active)
3515 R_TimeReport("viewclear");
3518 static void R_BlendView(void)
3520 if (r_bloomstate.texture_screen)
3522 // copy view into the screen texture
3523 R_ResetViewRendering2D();
3524 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3525 R_Mesh_ColorPointer(NULL, 0, 0);
3526 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3527 GL_ActiveTexture(0);CHECKGLERROR
3528 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
3529 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3532 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3534 unsigned int permutation =
3535 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3536 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0)
3537 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
3538 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0);
3540 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3542 // render simple bloom effect
3543 // copy the screen and shrink it and darken it for the bloom process
3544 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3545 // make the bloom texture
3546 R_Bloom_MakeTexture();
3549 R_ResetViewRendering2D();
3550 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3551 R_Mesh_ColorPointer(NULL, 0, 0);
3552 GL_Color(1, 1, 1, 1);
3553 GL_BlendFunc(GL_ONE, GL_ZERO);
3554 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3555 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3556 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3557 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3558 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3559 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
3560 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
3561 if (r_glsl_permutation->loc_TintColor >= 0)
3562 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3563 if (r_glsl_permutation->loc_ClientTime >= 0)
3564 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3565 if (r_glsl_permutation->loc_PixelSize >= 0)
3566 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
3567 if (r_glsl_permutation->loc_UserVec1 >= 0)
3569 float a=0, b=0, c=0, d=0;
3570 #if _MSC_VER >= 1400
3571 #define sscanf sscanf_s
3573 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3574 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3576 if (r_glsl_permutation->loc_UserVec2 >= 0)
3578 float a=0, b=0, c=0, d=0;
3579 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3580 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3582 if (r_glsl_permutation->loc_UserVec3 >= 0)
3584 float a=0, b=0, c=0, d=0;
3585 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3586 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3588 if (r_glsl_permutation->loc_UserVec4 >= 0)
3590 float a=0, b=0, c=0, d=0;
3591 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3592 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3594 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3595 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3601 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3603 // render high dynamic range bloom effect
3604 // the bloom texture was made earlier this render, so we just need to
3605 // blend it onto the screen...
3606 R_ResetViewRendering2D();
3607 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3608 R_Mesh_ColorPointer(NULL, 0, 0);
3609 R_SetupGenericShader(true);
3610 GL_Color(1, 1, 1, 1);
3611 GL_BlendFunc(GL_ONE, GL_ONE);
3612 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3613 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3614 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3615 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3617 else if (r_bloomstate.texture_bloom)
3619 // render simple bloom effect
3620 // copy the screen and shrink it and darken it for the bloom process
3621 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3622 // make the bloom texture
3623 R_Bloom_MakeTexture();
3624 // put the original screen image back in place and blend the bloom
3626 R_ResetViewRendering2D();
3627 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3628 R_Mesh_ColorPointer(NULL, 0, 0);
3629 GL_Color(1, 1, 1, 1);
3630 GL_BlendFunc(GL_ONE, GL_ZERO);
3631 // do both in one pass if possible
3632 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3633 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3634 if (r_textureunits.integer >= 2 && gl_combine.integer)
3636 R_SetupGenericTwoTextureShader(GL_ADD);
3637 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3638 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3642 R_SetupGenericShader(true);
3643 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3644 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3645 // now blend on the bloom texture
3646 GL_BlendFunc(GL_ONE, GL_ONE);
3647 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3648 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3650 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3651 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3653 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3655 // apply a color tint to the whole view
3656 R_ResetViewRendering2D();
3657 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3658 R_Mesh_ColorPointer(NULL, 0, 0);
3659 R_SetupGenericShader(false);
3660 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3661 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3662 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3666 void R_RenderScene(qboolean addwaterplanes);
3668 matrix4x4_t r_waterscrollmatrix;
3670 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3672 if (r_refdef.fog_density)
3674 r_refdef.fogcolor[0] = r_refdef.fog_red;
3675 r_refdef.fogcolor[1] = r_refdef.fog_green;
3676 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3680 VectorCopy(r_refdef.fogcolor, fogvec);
3681 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3683 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3684 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3685 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3686 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3688 // color.rgb *= ContrastBoost * SceneBrightness;
3689 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3690 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3691 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3692 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3697 void R_UpdateVariables(void)
3701 r_refdef.scene.ambient = r_ambient.value;
3703 r_refdef.farclip = 4096;
3704 if (r_refdef.scene.worldmodel)
3705 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
3706 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3708 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3709 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3710 r_refdef.polygonfactor = 0;
3711 r_refdef.polygonoffset = 0;
3712 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3713 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3715 r_refdef.scene.rtworld = r_shadow_realtime_world.integer;
3716 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3717 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3718 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3719 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3720 if (r_showsurfaces.integer)
3722 r_refdef.scene.rtworld = false;
3723 r_refdef.scene.rtworldshadows = false;
3724 r_refdef.scene.rtdlight = false;
3725 r_refdef.scene.rtdlightshadows = false;
3726 r_refdef.lightmapintensity = 0;
3729 if (gamemode == GAME_NEHAHRA)
3731 if (gl_fogenable.integer)
3733 r_refdef.oldgl_fogenable = true;
3734 r_refdef.fog_density = gl_fogdensity.value;
3735 r_refdef.fog_red = gl_fogred.value;
3736 r_refdef.fog_green = gl_foggreen.value;
3737 r_refdef.fog_blue = gl_fogblue.value;
3738 r_refdef.fog_alpha = 1;
3739 r_refdef.fog_start = 0;
3740 r_refdef.fog_end = gl_skyclip.value;
3742 else if (r_refdef.oldgl_fogenable)
3744 r_refdef.oldgl_fogenable = false;
3745 r_refdef.fog_density = 0;
3746 r_refdef.fog_red = 0;
3747 r_refdef.fog_green = 0;
3748 r_refdef.fog_blue = 0;
3749 r_refdef.fog_alpha = 0;
3750 r_refdef.fog_start = 0;
3751 r_refdef.fog_end = 0;
3755 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3756 r_refdef.fog_start = max(0, r_refdef.fog_start);
3757 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3759 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3761 if (r_refdef.fog_density && r_drawfog.integer)
3763 r_refdef.fogenabled = true;
3764 // this is the point where the fog reaches 0.9986 alpha, which we
3765 // consider a good enough cutoff point for the texture
3766 // (0.9986 * 256 == 255.6)
3767 if (r_fog_exp2.integer)
3768 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3770 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3771 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3772 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3773 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3774 // fog color was already set
3775 // update the fog texture
3776 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)
3777 R_BuildFogTexture();
3780 r_refdef.fogenabled = false;
3782 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
3784 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
3786 // build GLSL gamma texture
3787 #define RAMPWIDTH 256
3788 unsigned short ramp[RAMPWIDTH * 3];
3789 unsigned char ramprgb[RAMPWIDTH][4];
3792 r_texture_gammaramps_serial = vid_gammatables_serial;
3794 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
3795 for(i = 0; i < RAMPWIDTH; ++i)
3797 ramprgb[i][0] = ramp[i] >> 8;
3798 ramprgb[i][1] = ramp[i + RAMPWIDTH] >> 8;
3799 ramprgb[i][2] = ramp[i + 2 * RAMPWIDTH] >> 8;
3802 if (r_texture_gammaramps)
3804 R_UpdateTexture(r_texture_gammaramps, &ramprgb[0][0], 0, 0, RAMPWIDTH, 1);
3808 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &ramprgb[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
3814 // remove GLSL gamma texture
3818 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3819 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3825 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3826 if( scenetype != r_currentscenetype ) {
3827 // store the old scenetype
3828 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3829 r_currentscenetype = scenetype;
3830 // move in the new scene
3831 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3840 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3842 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3843 if( scenetype == r_currentscenetype ) {
3844 return &r_refdef.scene;
3846 return &r_scenes_store[ scenetype ];
3855 void R_RenderView(void)
3857 if (r_refdef.view.isoverlay)
3859 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
3860 GL_Clear( GL_DEPTH_BUFFER_BIT );
3861 R_TimeReport("depthclear");
3863 r_refdef.view.showdebug = false;
3865 r_waterstate.enabled = false;
3866 r_waterstate.numwaterplanes = 0;
3868 R_RenderScene(false);
3874 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
3875 return; //Host_Error ("R_RenderView: NULL worldmodel");
3877 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3879 // break apart the view matrix into vectors for various purposes
3880 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3881 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3882 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3883 VectorNegate(r_refdef.view.left, r_refdef.view.right);
3884 // make an inverted copy of the view matrix for tracking sprites
3885 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3887 R_Shadow_UpdateWorldLightSelection();
3889 R_Bloom_StartFrame();
3890 R_Water_StartFrame();
3893 if (r_timereport_active)
3894 R_TimeReport("viewsetup");
3896 R_ResetViewRendering3D();
3898 if (r_refdef.view.clear || r_refdef.fogenabled)
3900 R_ClearScreen(r_refdef.fogenabled);
3901 if (r_timereport_active)
3902 R_TimeReport("viewclear");
3904 r_refdef.view.clear = true;
3906 r_refdef.view.showdebug = true;
3908 // this produces a bloom texture to be used in R_BlendView() later
3910 R_HDR_RenderBloomTexture();
3912 r_waterstate.numwaterplanes = 0;
3913 R_RenderScene(r_waterstate.enabled);
3916 if (r_timereport_active)
3917 R_TimeReport("blendview");
3919 GL_Scissor(0, 0, vid.width, vid.height);
3920 GL_ScissorTest(false);
3924 extern void R_DrawLightningBeams (void);
3925 extern void VM_CL_AddPolygonsToMeshQueue (void);
3926 extern void R_DrawPortals (void);
3927 extern cvar_t cl_locs_show;
3928 static void R_DrawLocs(void);
3929 static void R_DrawEntityBBoxes(void);
3930 void R_RenderScene(qboolean addwaterplanes)
3932 r_refdef.stats.renders++;
3938 R_ResetViewRendering3D();
3941 if (r_timereport_active)
3942 R_TimeReport("watervis");
3944 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3946 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3947 if (r_timereport_active)
3948 R_TimeReport("waterworld");
3951 // don't let sound skip if going slow
3952 if (r_refdef.scene.extraupdate)
3955 R_DrawModelsAddWaterPlanes();
3956 if (r_timereport_active)
3957 R_TimeReport("watermodels");
3959 R_Water_ProcessPlanes();
3960 if (r_timereport_active)
3961 R_TimeReport("waterscenes");
3964 R_ResetViewRendering3D();
3966 // don't let sound skip if going slow
3967 if (r_refdef.scene.extraupdate)
3970 R_MeshQueue_BeginScene();
3975 if (r_timereport_active)
3976 R_TimeReport("visibility");
3978 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);
3980 if (cl.csqc_vidvars.drawworld)
3982 // don't let sound skip if going slow
3983 if (r_refdef.scene.extraupdate)
3986 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
3988 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
3989 if (r_timereport_active)
3990 R_TimeReport("worldsky");
3993 if (R_DrawBrushModelsSky() && r_timereport_active)
3994 R_TimeReport("bmodelsky");
3997 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
3999 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4000 if (r_timereport_active)
4001 R_TimeReport("worlddepth");
4003 if (r_depthfirst.integer >= 2)
4005 R_DrawModelsDepth();
4006 if (r_timereport_active)
4007 R_TimeReport("modeldepth");
4010 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4012 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4013 if (r_timereport_active)
4014 R_TimeReport("world");
4017 // don't let sound skip if going slow
4018 if (r_refdef.scene.extraupdate)
4022 if (r_timereport_active)
4023 R_TimeReport("models");
4025 // don't let sound skip if going slow
4026 if (r_refdef.scene.extraupdate)
4029 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
4031 R_DrawModelShadows();
4033 R_ResetViewRendering3D();
4035 // don't let sound skip if going slow
4036 if (r_refdef.scene.extraupdate)
4040 R_ShadowVolumeLighting(false);
4041 if (r_timereport_active)
4042 R_TimeReport("rtlights");
4044 // don't let sound skip if going slow
4045 if (r_refdef.scene.extraupdate)
4048 if (cl.csqc_vidvars.drawworld)
4050 R_DrawLightningBeams();
4051 if (r_timereport_active)
4052 R_TimeReport("lightning");
4055 if (r_timereport_active)
4056 R_TimeReport("decals");
4059 if (r_timereport_active)
4060 R_TimeReport("particles");
4063 if (r_timereport_active)
4064 R_TimeReport("explosions");
4067 R_SetupGenericShader(true);
4068 VM_CL_AddPolygonsToMeshQueue();
4070 if (r_refdef.view.showdebug)
4072 if (cl_locs_show.integer)
4075 if (r_timereport_active)
4076 R_TimeReport("showlocs");
4079 if (r_drawportals.integer)
4082 if (r_timereport_active)
4083 R_TimeReport("portals");
4086 if (r_showbboxes.value > 0)
4088 R_DrawEntityBBoxes();
4089 if (r_timereport_active)
4090 R_TimeReport("bboxes");
4094 R_SetupGenericShader(true);
4095 R_MeshQueue_RenderTransparent();
4096 if (r_timereport_active)
4097 R_TimeReport("drawtrans");
4099 R_SetupGenericShader(true);
4101 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))
4103 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4104 if (r_timereport_active)
4105 R_TimeReport("worlddebug");
4106 R_DrawModelsDebug();
4107 if (r_timereport_active)
4108 R_TimeReport("modeldebug");
4111 R_SetupGenericShader(true);
4113 if (cl.csqc_vidvars.drawworld)
4116 if (r_timereport_active)
4117 R_TimeReport("coronas");
4120 // don't let sound skip if going slow
4121 if (r_refdef.scene.extraupdate)
4124 R_ResetViewRendering2D();
4127 static const unsigned short bboxelements[36] =
4137 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4140 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4141 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4142 GL_DepthMask(false);
4143 GL_DepthRange(0, 1);
4144 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4145 R_Mesh_Matrix(&identitymatrix);
4146 R_Mesh_ResetTextureState();
4148 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4149 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4150 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4151 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4152 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4153 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4154 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4155 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4156 R_FillColors(color4f, 8, cr, cg, cb, ca);
4157 if (r_refdef.fogenabled)
4159 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4161 f1 = FogPoint_World(v);
4163 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4164 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4165 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4168 R_Mesh_VertexPointer(vertex3f, 0, 0);
4169 R_Mesh_ColorPointer(color4f, 0, 0);
4170 R_Mesh_ResetTextureState();
4171 R_SetupGenericShader(false);
4172 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4175 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4179 prvm_edict_t *edict;
4180 prvm_prog_t *prog_save = prog;
4182 // this function draws bounding boxes of server entities
4186 GL_CullFace(GL_NONE);
4187 R_SetupGenericShader(false);
4191 for (i = 0;i < numsurfaces;i++)
4193 edict = PRVM_EDICT_NUM(surfacelist[i]);
4194 switch ((int)edict->fields.server->solid)
4196 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4197 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4198 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4199 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4200 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4201 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4203 color[3] *= r_showbboxes.value;
4204 color[3] = bound(0, color[3], 1);
4205 GL_DepthTest(!r_showdisabledepthtest.integer);
4206 GL_CullFace(r_refdef.view.cullface_front);
4207 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4213 static void R_DrawEntityBBoxes(void)
4216 prvm_edict_t *edict;
4218 prvm_prog_t *prog_save = prog;
4220 // this function draws bounding boxes of server entities
4226 for (i = 0;i < prog->num_edicts;i++)
4228 edict = PRVM_EDICT_NUM(i);
4229 if (edict->priv.server->free)
4231 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4232 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4234 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4236 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4237 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4243 unsigned short nomodelelements[24] =
4255 float nomodelvertex3f[6*3] =
4265 float nomodelcolor4f[6*4] =
4267 0.0f, 0.0f, 0.5f, 1.0f,
4268 0.0f, 0.0f, 0.5f, 1.0f,
4269 0.0f, 0.5f, 0.0f, 1.0f,
4270 0.0f, 0.5f, 0.0f, 1.0f,
4271 0.5f, 0.0f, 0.0f, 1.0f,
4272 0.5f, 0.0f, 0.0f, 1.0f
4275 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4280 // this is only called once per entity so numsurfaces is always 1, and
4281 // surfacelist is always {0}, so this code does not handle batches
4282 R_Mesh_Matrix(&ent->matrix);
4284 if (ent->flags & EF_ADDITIVE)
4286 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4287 GL_DepthMask(false);
4289 else if (ent->alpha < 1)
4291 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4292 GL_DepthMask(false);
4296 GL_BlendFunc(GL_ONE, GL_ZERO);
4299 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4300 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4301 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4302 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4303 R_SetupGenericShader(false);
4304 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4305 if (r_refdef.fogenabled)
4308 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4309 R_Mesh_ColorPointer(color4f, 0, 0);
4310 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4311 f1 = FogPoint_World(org);
4313 for (i = 0, c = color4f;i < 6;i++, c += 4)
4315 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4316 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4317 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4321 else if (ent->alpha != 1)
4323 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4324 R_Mesh_ColorPointer(color4f, 0, 0);
4325 for (i = 0, c = color4f;i < 6;i++, c += 4)
4329 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4330 R_Mesh_ResetTextureState();
4331 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4334 void R_DrawNoModel(entity_render_t *ent)
4337 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4338 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4339 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4341 // R_DrawNoModelCallback(ent, 0);
4344 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4346 vec3_t right1, right2, diff, normal;
4348 VectorSubtract (org2, org1, normal);
4350 // calculate 'right' vector for start
4351 VectorSubtract (r_refdef.view.origin, org1, diff);
4352 CrossProduct (normal, diff, right1);
4353 VectorNormalize (right1);
4355 // calculate 'right' vector for end
4356 VectorSubtract (r_refdef.view.origin, org2, diff);
4357 CrossProduct (normal, diff, right2);
4358 VectorNormalize (right2);
4360 vert[ 0] = org1[0] + width * right1[0];
4361 vert[ 1] = org1[1] + width * right1[1];
4362 vert[ 2] = org1[2] + width * right1[2];
4363 vert[ 3] = org1[0] - width * right1[0];
4364 vert[ 4] = org1[1] - width * right1[1];
4365 vert[ 5] = org1[2] - width * right1[2];
4366 vert[ 6] = org2[0] - width * right2[0];
4367 vert[ 7] = org2[1] - width * right2[1];
4368 vert[ 8] = org2[2] - width * right2[2];
4369 vert[ 9] = org2[0] + width * right2[0];
4370 vert[10] = org2[1] + width * right2[1];
4371 vert[11] = org2[2] + width * right2[2];
4374 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4376 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)
4381 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4382 fog = FogPoint_World(origin);
4384 R_Mesh_Matrix(&identitymatrix);
4385 GL_BlendFunc(blendfunc1, blendfunc2);
4391 GL_CullFace(r_refdef.view.cullface_front);
4394 GL_CullFace(r_refdef.view.cullface_back);
4395 GL_CullFace(GL_NONE);
4397 GL_DepthMask(false);
4398 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4399 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4400 GL_DepthTest(!depthdisable);
4402 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4403 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4404 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4405 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4406 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4407 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4408 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4409 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4410 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4411 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4412 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4413 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4415 R_Mesh_VertexPointer(vertex3f, 0, 0);
4416 R_Mesh_ColorPointer(NULL, 0, 0);
4417 R_Mesh_ResetTextureState();
4418 R_SetupGenericShader(true);
4419 R_Mesh_TexBind(0, R_GetTexture(texture));
4420 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4421 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4422 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4423 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4425 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4427 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4428 GL_BlendFunc(blendfunc1, GL_ONE);
4430 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4431 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4435 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4440 VectorSet(v, x, y, z);
4441 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4442 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4444 if (i == mesh->numvertices)
4446 if (mesh->numvertices < mesh->maxvertices)
4448 VectorCopy(v, vertex3f);
4449 mesh->numvertices++;
4451 return mesh->numvertices;
4457 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4461 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4462 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4463 e = mesh->element3i + mesh->numtriangles * 3;
4464 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4466 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4467 if (mesh->numtriangles < mesh->maxtriangles)
4472 mesh->numtriangles++;
4474 element[1] = element[2];
4478 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4482 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4483 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4484 e = mesh->element3i + mesh->numtriangles * 3;
4485 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4487 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4488 if (mesh->numtriangles < mesh->maxtriangles)
4493 mesh->numtriangles++;
4495 element[1] = element[2];
4499 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4500 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4502 int planenum, planenum2;
4505 mplane_t *plane, *plane2;
4507 double temppoints[2][256*3];
4508 // figure out how large a bounding box we need to properly compute this brush
4510 for (w = 0;w < numplanes;w++)
4511 maxdist = max(maxdist, planes[w].dist);
4512 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4513 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4514 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4518 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4519 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4521 if (planenum2 == planenum)
4523 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);
4526 if (tempnumpoints < 3)
4528 // generate elements forming a triangle fan for this polygon
4529 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4533 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)
4535 texturelayer_t *layer;
4536 layer = t->currentlayers + t->currentnumlayers++;
4538 layer->depthmask = depthmask;
4539 layer->blendfunc1 = blendfunc1;
4540 layer->blendfunc2 = blendfunc2;
4541 layer->texture = texture;
4542 layer->texmatrix = *matrix;
4543 layer->color[0] = r * r_refdef.view.colorscale;
4544 layer->color[1] = g * r_refdef.view.colorscale;
4545 layer->color[2] = b * r_refdef.view.colorscale;
4546 layer->color[3] = a;
4549 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4552 index = parms[2] + r_refdef.scene.time * parms[3];
4553 index -= floor(index);
4557 case Q3WAVEFUNC_NONE:
4558 case Q3WAVEFUNC_NOISE:
4559 case Q3WAVEFUNC_COUNT:
4562 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4563 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4564 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4565 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4566 case Q3WAVEFUNC_TRIANGLE:
4568 f = index - floor(index);
4579 return (float)(parms[0] + parms[1] * f);
4582 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4586 dp_model_t *model = ent->model;
4589 q3shaderinfo_layer_tcmod_t *tcmod;
4591 if (t->basematerialflags & MATERIALFLAG_NODRAW)
4593 t->currentmaterialflags = MATERIALFLAG_NODRAW;
4597 // switch to an alternate material if this is a q1bsp animated material
4599 texture_t *texture = t;
4600 int s = ent->skinnum;
4601 if ((unsigned int)s >= (unsigned int)model->numskins)
4603 if (model->skinscenes)
4605 if (model->skinscenes[s].framecount > 1)
4606 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4608 s = model->skinscenes[s].firstframe;
4611 t = t + s * model->num_surfaces;
4614 // use an alternate animation if the entity's frame is not 0,
4615 // and only if the texture has an alternate animation
4616 if (ent->frame2 != 0 && t->anim_total[1])
4617 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4619 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4621 texture->currentframe = t;
4624 // update currentskinframe to be a qw skin or animation frame
4625 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"))
4627 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4629 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4630 if (developer_loading.integer)
4631 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
4632 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);
4634 t->currentskinframe = r_qwskincache_skinframe[i];
4635 if (t->currentskinframe == NULL)
4636 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4638 else if (t->numskinframes >= 2)
4639 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4640 if (t->backgroundnumskinframes >= 2)
4641 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4643 t->currentmaterialflags = t->basematerialflags;
4644 t->currentalpha = ent->alpha;
4645 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4646 t->currentalpha *= r_wateralpha.value;
4647 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
4648 t->currentalpha *= t->r_water_wateralpha;
4649 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
4650 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4651 if (!(ent->flags & RENDER_LIGHT))
4652 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4653 else if (rsurface.modeltexcoordlightmap2f == NULL)
4655 // pick a model lighting mode
4656 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4657 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4659 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4661 if (ent->effects & EF_ADDITIVE)
4662 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4663 else if (t->currentalpha < 1)
4664 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4665 if (ent->effects & EF_DOUBLESIDED)
4666 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4667 if (ent->effects & EF_NODEPTHTEST)
4668 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4669 if (ent->flags & RENDER_VIEWMODEL)
4670 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4671 if (t->backgroundnumskinframes)
4672 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4673 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4675 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4676 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4679 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4681 // there is no tcmod
4682 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4683 t->currenttexmatrix = r_waterscrollmatrix;
4685 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4688 switch(tcmod->tcmod)
4692 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
4693 matrix = r_waterscrollmatrix;
4695 matrix = identitymatrix;
4697 case Q3TCMOD_ENTITYTRANSLATE:
4698 // this is used in Q3 to allow the gamecode to control texcoord
4699 // scrolling on the entity, which is not supported in darkplaces yet.
4700 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4702 case Q3TCMOD_ROTATE:
4703 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4704 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4705 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4708 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4710 case Q3TCMOD_SCROLL:
4711 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4713 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
4714 w = tcmod->parms[0];
4715 h = tcmod->parms[1];
4716 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
4718 idx = floor(f * w * h);
4719 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
4721 case Q3TCMOD_STRETCH:
4722 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4723 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4725 case Q3TCMOD_TRANSFORM:
4726 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4727 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4728 VectorSet(tcmat + 6, 0 , 0 , 1);
4729 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4730 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4732 case Q3TCMOD_TURBULENT:
4733 // this is handled in the RSurf_PrepareVertices function
4734 matrix = identitymatrix;
4737 // either replace or concatenate the transformation
4739 t->currenttexmatrix = matrix;
4742 matrix4x4_t temp = t->currenttexmatrix;
4743 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4747 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4748 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4749 t->glosstexture = r_texture_black;
4750 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4751 t->backgroundglosstexture = r_texture_black;
4752 t->specularpower = r_shadow_glossexponent.value;
4753 // TODO: store reference values for these in the texture?
4754 t->specularscale = 0;
4755 if (r_shadow_gloss.integer > 0)
4757 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4759 if (r_shadow_glossintensity.value > 0)
4761 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4762 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4763 t->specularscale = r_shadow_glossintensity.value;
4766 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4768 t->glosstexture = r_texture_white;
4769 t->backgroundglosstexture = r_texture_white;
4770 t->specularscale = r_shadow_gloss2intensity.value;
4774 // lightmaps mode looks bad with dlights using actual texturing, so turn
4775 // off the colormap and glossmap, but leave the normalmap on as it still
4776 // accurately represents the shading involved
4777 if (gl_lightmaps.integer)
4779 t->basetexture = r_texture_grey128;
4780 t->backgroundbasetexture = NULL;
4781 t->specularscale = 0;
4782 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
4785 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4786 VectorClear(t->dlightcolor);
4787 t->currentnumlayers = 0;
4788 if (t->currentmaterialflags & MATERIALFLAG_WALL)
4791 int blendfunc1, blendfunc2, depthmask;
4792 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4794 blendfunc1 = GL_SRC_ALPHA;
4795 blendfunc2 = GL_ONE;
4797 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4799 blendfunc1 = GL_SRC_ALPHA;
4800 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4802 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4804 blendfunc1 = t->customblendfunc[0];
4805 blendfunc2 = t->customblendfunc[1];
4809 blendfunc1 = GL_ONE;
4810 blendfunc2 = GL_ZERO;
4812 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4813 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4814 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4815 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4817 // fullbright is not affected by r_refdef.lightmapintensity
4818 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]);
4819 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4820 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]);
4821 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4822 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]);
4826 vec3_t ambientcolor;
4828 // set the color tint used for lights affecting this surface
4829 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4831 // q3bsp has no lightmap updates, so the lightstylevalue that
4832 // would normally be baked into the lightmap must be
4833 // applied to the color
4834 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4835 if (ent->model->type == mod_brushq3)
4836 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4837 colorscale *= r_refdef.lightmapintensity;
4838 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
4839 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4840 // basic lit geometry
4841 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]);
4842 // add pants/shirt if needed
4843 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4844 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]);
4845 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4846 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]);
4847 // now add ambient passes if needed
4848 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4850 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]);
4851 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4852 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]);
4853 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4854 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]);
4857 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4858 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]);
4859 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4861 // if this is opaque use alpha blend which will darken the earlier
4864 // if this is an alpha blended material, all the earlier passes
4865 // were darkened by fog already, so we only need to add the fog
4866 // color ontop through the fog mask texture
4868 // if this is an additive blended material, all the earlier passes
4869 // were darkened by fog already, and we should not add fog color
4870 // (because the background was not darkened, there is no fog color
4871 // that was lost behind it).
4872 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]);
4877 void R_UpdateAllTextureInfo(entity_render_t *ent)
4881 for (i = 0;i < ent->model->num_texturesperskin;i++)
4882 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4885 rsurfacestate_t rsurface;
4887 void R_Mesh_ResizeArrays(int newvertices)
4890 if (rsurface.array_size >= newvertices)
4892 if (rsurface.array_modelvertex3f)
4893 Mem_Free(rsurface.array_modelvertex3f);
4894 rsurface.array_size = (newvertices + 1023) & ~1023;
4895 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4896 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4897 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4898 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4899 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4900 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4901 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4902 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4903 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4904 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4905 rsurface.array_color4f = base + rsurface.array_size * 27;
4906 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4909 void RSurf_ActiveWorldEntity(void)
4911 dp_model_t *model = r_refdef.scene.worldmodel;
4912 if (rsurface.array_size < model->surfmesh.num_vertices)
4913 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4914 rsurface.matrix = identitymatrix;
4915 rsurface.inversematrix = identitymatrix;
4916 R_Mesh_Matrix(&identitymatrix);
4917 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4918 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4919 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4920 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4921 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4922 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4923 rsurface.frameblend[0].frame = 0;
4924 rsurface.frameblend[0].lerp = 1;
4925 rsurface.frameblend[1].frame = 0;
4926 rsurface.frameblend[1].lerp = 0;
4927 rsurface.frameblend[2].frame = 0;
4928 rsurface.frameblend[2].lerp = 0;
4929 rsurface.frameblend[3].frame = 0;
4930 rsurface.frameblend[3].lerp = 0;
4931 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4932 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4933 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4934 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4935 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4936 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4937 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4938 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4939 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4940 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4941 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4942 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4943 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4944 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4945 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4946 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4947 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4948 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4949 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4950 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4951 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4952 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4953 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4954 rsurface.modelelement3i = model->surfmesh.data_element3i;
4955 rsurface.modelelement3s = model->surfmesh.data_element3s;
4956 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
4957 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
4958 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4959 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4960 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4961 rsurface.modelsurfaces = model->data_surfaces;
4962 rsurface.generatedvertex = false;
4963 rsurface.vertex3f = rsurface.modelvertex3f;
4964 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4965 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4966 rsurface.svector3f = rsurface.modelsvector3f;
4967 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4968 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4969 rsurface.tvector3f = rsurface.modeltvector3f;
4970 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4971 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4972 rsurface.normal3f = rsurface.modelnormal3f;
4973 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4974 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4975 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4978 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4980 dp_model_t *model = ent->model;
4981 if (rsurface.array_size < model->surfmesh.num_vertices)
4982 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4983 rsurface.matrix = ent->matrix;
4984 rsurface.inversematrix = ent->inversematrix;
4985 R_Mesh_Matrix(&rsurface.matrix);
4986 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
4987 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4988 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4989 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4990 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4991 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4992 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4993 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4994 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4995 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4996 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4997 rsurface.frameblend[0] = ent->frameblend[0];
4998 rsurface.frameblend[1] = ent->frameblend[1];
4999 rsurface.frameblend[2] = ent->frameblend[2];
5000 rsurface.frameblend[3] = ent->frameblend[3];
5001 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5002 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5003 if (ent->model->brush.submodel)
5005 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5006 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5008 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
5012 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5013 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5014 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5015 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5016 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5018 else if (wantnormals)
5020 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5021 rsurface.modelsvector3f = NULL;
5022 rsurface.modeltvector3f = NULL;
5023 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5024 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5028 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5029 rsurface.modelsvector3f = NULL;
5030 rsurface.modeltvector3f = NULL;
5031 rsurface.modelnormal3f = NULL;
5032 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5034 rsurface.modelvertex3f_bufferobject = 0;
5035 rsurface.modelvertex3f_bufferoffset = 0;
5036 rsurface.modelsvector3f_bufferobject = 0;
5037 rsurface.modelsvector3f_bufferoffset = 0;
5038 rsurface.modeltvector3f_bufferobject = 0;
5039 rsurface.modeltvector3f_bufferoffset = 0;
5040 rsurface.modelnormal3f_bufferobject = 0;
5041 rsurface.modelnormal3f_bufferoffset = 0;
5042 rsurface.generatedvertex = true;
5046 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5047 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5048 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5049 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5050 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5051 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5052 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5053 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5054 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5055 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5056 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5057 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5058 rsurface.generatedvertex = false;
5060 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5061 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5062 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5063 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5064 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5065 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5066 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5067 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5068 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5069 rsurface.modelelement3i = model->surfmesh.data_element3i;
5070 rsurface.modelelement3s = model->surfmesh.data_element3s;
5071 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5072 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5073 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5074 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5075 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5076 rsurface.modelsurfaces = model->data_surfaces;
5077 rsurface.vertex3f = rsurface.modelvertex3f;
5078 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5079 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5080 rsurface.svector3f = rsurface.modelsvector3f;
5081 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5082 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5083 rsurface.tvector3f = rsurface.modeltvector3f;
5084 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5085 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5086 rsurface.normal3f = rsurface.modelnormal3f;
5087 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5088 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5089 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5092 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5093 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5096 int texturesurfaceindex;
5101 const float *v1, *in_tc;
5103 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5105 q3shaderinfo_deform_t *deform;
5106 // 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
5107 if (rsurface.generatedvertex)
5109 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5110 generatenormals = true;
5111 for (i = 0;i < Q3MAXDEFORMS;i++)
5113 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5115 generatetangents = true;
5116 generatenormals = true;
5118 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5119 generatenormals = true;
5121 if (generatenormals && !rsurface.modelnormal3f)
5123 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5124 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5125 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5126 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
5128 if (generatetangents && !rsurface.modelsvector3f)
5130 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5131 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5132 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5133 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5134 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5135 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5136 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);
5139 rsurface.vertex3f = rsurface.modelvertex3f;
5140 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5141 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5142 rsurface.svector3f = rsurface.modelsvector3f;
5143 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5144 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5145 rsurface.tvector3f = rsurface.modeltvector3f;
5146 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5147 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5148 rsurface.normal3f = rsurface.modelnormal3f;
5149 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5150 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5151 // if vertices are deformed (sprite flares and things in maps, possibly
5152 // water waves, bulges and other deformations), generate them into
5153 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5154 // (may be static model data or generated data for an animated model, or
5155 // the previous deform pass)
5156 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5158 switch (deform->deform)
5161 case Q3DEFORM_PROJECTIONSHADOW:
5162 case Q3DEFORM_TEXT0:
5163 case Q3DEFORM_TEXT1:
5164 case Q3DEFORM_TEXT2:
5165 case Q3DEFORM_TEXT3:
5166 case Q3DEFORM_TEXT4:
5167 case Q3DEFORM_TEXT5:
5168 case Q3DEFORM_TEXT6:
5169 case Q3DEFORM_TEXT7:
5172 case Q3DEFORM_AUTOSPRITE:
5173 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5174 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5175 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5176 VectorNormalize(newforward);
5177 VectorNormalize(newright);
5178 VectorNormalize(newup);
5179 // make deformed versions of only the model vertices used by the specified surfaces
5180 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5182 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5183 // a single autosprite surface can contain multiple sprites...
5184 for (j = 0;j < surface->num_vertices - 3;j += 4)
5186 VectorClear(center);
5187 for (i = 0;i < 4;i++)
5188 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5189 VectorScale(center, 0.25f, center);
5190 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5191 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5192 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5193 for (i = 0;i < 4;i++)
5195 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5196 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5199 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);
5200 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);
5202 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5203 rsurface.vertex3f_bufferobject = 0;
5204 rsurface.vertex3f_bufferoffset = 0;
5205 rsurface.svector3f = rsurface.array_deformedsvector3f;
5206 rsurface.svector3f_bufferobject = 0;
5207 rsurface.svector3f_bufferoffset = 0;
5208 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5209 rsurface.tvector3f_bufferobject = 0;
5210 rsurface.tvector3f_bufferoffset = 0;
5211 rsurface.normal3f = rsurface.array_deformednormal3f;
5212 rsurface.normal3f_bufferobject = 0;
5213 rsurface.normal3f_bufferoffset = 0;
5215 case Q3DEFORM_AUTOSPRITE2:
5216 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5217 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5218 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5219 VectorNormalize(newforward);
5220 VectorNormalize(newright);
5221 VectorNormalize(newup);
5222 // make deformed versions of only the model vertices used by the specified surfaces
5223 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5225 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5226 const float *v1, *v2;
5236 memset(shortest, 0, sizeof(shortest));
5237 // a single autosprite surface can contain multiple sprites...
5238 for (j = 0;j < surface->num_vertices - 3;j += 4)
5240 VectorClear(center);
5241 for (i = 0;i < 4;i++)
5242 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5243 VectorScale(center, 0.25f, center);
5244 // find the two shortest edges, then use them to define the
5245 // axis vectors for rotating around the central axis
5246 for (i = 0;i < 6;i++)
5248 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5249 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5251 Debug_PolygonBegin(NULL, 0);
5252 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5253 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);
5254 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5257 l = VectorDistance2(v1, v2);
5258 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5260 l += (1.0f / 1024.0f);
5261 if (shortest[0].length2 > l || i == 0)
5263 shortest[1] = shortest[0];
5264 shortest[0].length2 = l;
5265 shortest[0].v1 = v1;
5266 shortest[0].v2 = v2;
5268 else if (shortest[1].length2 > l || i == 1)
5270 shortest[1].length2 = l;
5271 shortest[1].v1 = v1;
5272 shortest[1].v2 = v2;
5275 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5276 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5278 Debug_PolygonBegin(NULL, 0);
5279 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5280 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);
5281 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5284 // this calculates the right vector from the shortest edge
5285 // and the up vector from the edge midpoints
5286 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5287 VectorNormalize(right);
5288 VectorSubtract(end, start, up);
5289 VectorNormalize(up);
5290 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5291 //VectorSubtract(rsurface.modelorg, center, forward);
5292 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5293 VectorNegate(forward, forward);
5294 VectorReflect(forward, 0, up, forward);
5295 VectorNormalize(forward);
5296 CrossProduct(up, forward, newright);
5297 VectorNormalize(newright);
5299 Debug_PolygonBegin(NULL, 0);
5300 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);
5301 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5302 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5306 Debug_PolygonBegin(NULL, 0);
5307 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5308 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5309 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5312 // rotate the quad around the up axis vector, this is made
5313 // especially easy by the fact we know the quad is flat,
5314 // so we only have to subtract the center position and
5315 // measure distance along the right vector, and then
5316 // multiply that by the newright vector and add back the
5318 // we also need to subtract the old position to undo the
5319 // displacement from the center, which we do with a
5320 // DotProduct, the subtraction/addition of center is also
5321 // optimized into DotProducts here
5322 l = DotProduct(right, center);
5323 for (i = 0;i < 4;i++)
5325 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5326 f = DotProduct(right, v1) - l;
5327 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5330 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);
5331 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);
5333 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5334 rsurface.vertex3f_bufferobject = 0;
5335 rsurface.vertex3f_bufferoffset = 0;
5336 rsurface.svector3f = rsurface.array_deformedsvector3f;
5337 rsurface.svector3f_bufferobject = 0;
5338 rsurface.svector3f_bufferoffset = 0;
5339 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5340 rsurface.tvector3f_bufferobject = 0;
5341 rsurface.tvector3f_bufferoffset = 0;
5342 rsurface.normal3f = rsurface.array_deformednormal3f;
5343 rsurface.normal3f_bufferobject = 0;
5344 rsurface.normal3f_bufferoffset = 0;
5346 case Q3DEFORM_NORMAL:
5347 // deform the normals to make reflections wavey
5348 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5350 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5351 for (j = 0;j < surface->num_vertices;j++)
5354 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5355 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5356 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5357 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5358 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5359 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5360 VectorNormalize(normal);
5362 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);
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;
5375 // deform vertex array to make wavey water and flags and such
5376 waveparms[0] = deform->waveparms[0];
5377 waveparms[1] = deform->waveparms[1];
5378 waveparms[2] = deform->waveparms[2];
5379 waveparms[3] = deform->waveparms[3];
5380 // this is how a divisor of vertex influence on deformation
5381 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5382 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5383 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5385 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5386 for (j = 0;j < surface->num_vertices;j++)
5388 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5389 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5390 // if the wavefunc depends on time, evaluate it per-vertex
5393 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5394 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5396 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5399 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5400 rsurface.vertex3f_bufferobject = 0;
5401 rsurface.vertex3f_bufferoffset = 0;
5403 case Q3DEFORM_BULGE:
5404 // deform vertex array to make the surface have moving bulges
5405 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5407 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5408 for (j = 0;j < surface->num_vertices;j++)
5410 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5411 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5414 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5415 rsurface.vertex3f_bufferobject = 0;
5416 rsurface.vertex3f_bufferoffset = 0;
5419 // deform vertex array
5420 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5421 VectorScale(deform->parms, scale, waveparms);
5422 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5424 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5425 for (j = 0;j < surface->num_vertices;j++)
5426 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5428 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5429 rsurface.vertex3f_bufferobject = 0;
5430 rsurface.vertex3f_bufferoffset = 0;
5434 // generate texcoords based on the chosen texcoord source
5435 switch(rsurface.texture->tcgen.tcgen)
5438 case Q3TCGEN_TEXTURE:
5439 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5440 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5441 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5443 case Q3TCGEN_LIGHTMAP:
5444 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5445 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5446 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5448 case Q3TCGEN_VECTOR:
5449 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5451 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5452 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)
5454 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5455 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5458 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5459 rsurface.texcoordtexture2f_bufferobject = 0;
5460 rsurface.texcoordtexture2f_bufferoffset = 0;
5462 case Q3TCGEN_ENVIRONMENT:
5463 // make environment reflections using a spheremap
5464 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5466 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5467 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5468 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5469 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5470 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5472 float l, d, eyedir[3];
5473 VectorSubtract(rsurface.modelorg, vertex, eyedir);
5474 l = 0.5f / VectorLength(eyedir);
5475 d = DotProduct(normal, eyedir)*2;
5476 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
5477 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
5480 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5481 rsurface.texcoordtexture2f_bufferobject = 0;
5482 rsurface.texcoordtexture2f_bufferoffset = 0;
5485 // the only tcmod that needs software vertex processing is turbulent, so
5486 // check for it here and apply the changes if needed
5487 // and we only support that as the first one
5488 // (handling a mixture of turbulent and other tcmods would be problematic
5489 // without punting it entirely to a software path)
5490 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5492 amplitude = rsurface.texture->tcmods[0].parms[1];
5493 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5494 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5496 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5497 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)
5499 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5500 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5503 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5504 rsurface.texcoordtexture2f_bufferobject = 0;
5505 rsurface.texcoordtexture2f_bufferoffset = 0;
5507 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5508 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5509 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5510 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5513 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5516 const msurface_t *surface = texturesurfacelist[0];
5517 const msurface_t *surface2;
5522 // TODO: lock all array ranges before render, rather than on each surface
5523 if (texturenumsurfaces == 1)
5525 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5526 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);
5528 else if (r_batchmode.integer == 2)
5530 #define MAXBATCHTRIANGLES 4096
5531 int batchtriangles = 0;
5532 int batchelements[MAXBATCHTRIANGLES*3];
5533 for (i = 0;i < texturenumsurfaces;i = j)
5535 surface = texturesurfacelist[i];
5537 if (surface->num_triangles > MAXBATCHTRIANGLES)
5539 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);
5542 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5543 batchtriangles = surface->num_triangles;
5544 firstvertex = surface->num_firstvertex;
5545 endvertex = surface->num_firstvertex + surface->num_vertices;
5546 for (;j < texturenumsurfaces;j++)
5548 surface2 = texturesurfacelist[j];
5549 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5551 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5552 batchtriangles += surface2->num_triangles;
5553 firstvertex = min(firstvertex, surface2->num_firstvertex);
5554 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5556 surface2 = texturesurfacelist[j-1];
5557 numvertices = endvertex - firstvertex;
5558 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5561 else if (r_batchmode.integer == 1)
5563 for (i = 0;i < texturenumsurfaces;i = j)
5565 surface = texturesurfacelist[i];
5566 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5567 if (texturesurfacelist[j] != surface2)
5569 surface2 = texturesurfacelist[j-1];
5570 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5571 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5572 GL_LockArrays(surface->num_firstvertex, numvertices);
5573 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5578 for (i = 0;i < texturenumsurfaces;i++)
5580 surface = texturesurfacelist[i];
5581 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5582 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);
5587 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5589 int i, planeindex, vertexindex;
5593 r_waterstate_waterplane_t *p, *bestp;
5594 msurface_t *surface;
5595 if (r_waterstate.renderingscene)
5597 for (i = 0;i < texturenumsurfaces;i++)
5599 surface = texturesurfacelist[i];
5600 if (lightmaptexunit >= 0)
5601 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5602 if (deluxemaptexunit >= 0)
5603 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5604 // pick the closest matching water plane
5607 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5610 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5612 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5613 d += fabs(PlaneDiff(vert, &p->plane));
5615 if (bestd > d || !bestp)
5623 if (refractiontexunit >= 0)
5624 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5625 if (reflectiontexunit >= 0)
5626 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5630 if (refractiontexunit >= 0)
5631 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5632 if (reflectiontexunit >= 0)
5633 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5635 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5636 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);
5640 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5644 const msurface_t *surface = texturesurfacelist[0];
5645 const msurface_t *surface2;
5650 // TODO: lock all array ranges before render, rather than on each surface
5651 if (texturenumsurfaces == 1)
5653 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5654 if (deluxemaptexunit >= 0)
5655 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5656 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5657 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);
5659 else if (r_batchmode.integer == 2)
5661 #define MAXBATCHTRIANGLES 4096
5662 int batchtriangles = 0;
5663 int batchelements[MAXBATCHTRIANGLES*3];
5664 for (i = 0;i < texturenumsurfaces;i = j)
5666 surface = texturesurfacelist[i];
5667 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5668 if (deluxemaptexunit >= 0)
5669 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5671 if (surface->num_triangles > MAXBATCHTRIANGLES)
5673 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);
5676 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5677 batchtriangles = surface->num_triangles;
5678 firstvertex = surface->num_firstvertex;
5679 endvertex = surface->num_firstvertex + surface->num_vertices;
5680 for (;j < texturenumsurfaces;j++)
5682 surface2 = texturesurfacelist[j];
5683 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5685 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5686 batchtriangles += surface2->num_triangles;
5687 firstvertex = min(firstvertex, surface2->num_firstvertex);
5688 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5690 surface2 = texturesurfacelist[j-1];
5691 numvertices = endvertex - firstvertex;
5692 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
5695 else if (r_batchmode.integer == 1)
5698 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5699 for (i = 0;i < texturenumsurfaces;i = j)
5701 surface = texturesurfacelist[i];
5702 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5703 if (texturesurfacelist[j] != surface2)
5705 Con_Printf(" %i", j - i);
5708 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5710 for (i = 0;i < texturenumsurfaces;i = j)
5712 surface = texturesurfacelist[i];
5713 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5714 if (deluxemaptexunit >= 0)
5715 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5716 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5717 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5720 Con_Printf(" %i", j - i);
5722 surface2 = texturesurfacelist[j-1];
5723 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5724 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5725 GL_LockArrays(surface->num_firstvertex, numvertices);
5726 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5734 for (i = 0;i < texturenumsurfaces;i++)
5736 surface = texturesurfacelist[i];
5737 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5738 if (deluxemaptexunit >= 0)
5739 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5740 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5741 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);
5746 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5749 int texturesurfaceindex;
5750 if (r_showsurfaces.integer == 2)
5752 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5754 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5755 for (j = 0;j < surface->num_triangles;j++)
5757 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5758 GL_Color(f, f, f, 1);
5759 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
5765 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5767 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5768 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5769 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);
5770 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5771 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);
5776 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5778 int texturesurfaceindex;
5782 if (rsurface.lightmapcolor4f)
5784 // generate color arrays for the surfaces in this list
5785 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5787 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5788 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)
5790 f = FogPoint_Model(v);
5800 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5802 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5803 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)
5805 f = FogPoint_Model(v);
5813 rsurface.lightmapcolor4f = rsurface.array_color4f;
5814 rsurface.lightmapcolor4f_bufferobject = 0;
5815 rsurface.lightmapcolor4f_bufferoffset = 0;
5818 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5820 int texturesurfaceindex;
5823 if (!rsurface.lightmapcolor4f)
5825 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5827 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5828 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)
5836 rsurface.lightmapcolor4f = rsurface.array_color4f;
5837 rsurface.lightmapcolor4f_bufferobject = 0;
5838 rsurface.lightmapcolor4f_bufferoffset = 0;
5841 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5844 rsurface.lightmapcolor4f = NULL;
5845 rsurface.lightmapcolor4f_bufferobject = 0;
5846 rsurface.lightmapcolor4f_bufferoffset = 0;
5847 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5848 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5849 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5850 GL_Color(r, g, b, a);
5851 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5854 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5856 // TODO: optimize applyfog && applycolor case
5857 // just apply fog if necessary, and tint the fog color array if necessary
5858 rsurface.lightmapcolor4f = NULL;
5859 rsurface.lightmapcolor4f_bufferobject = 0;
5860 rsurface.lightmapcolor4f_bufferoffset = 0;
5861 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5862 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5863 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5864 GL_Color(r, g, b, a);
5865 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5868 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5870 int texturesurfaceindex;
5874 if (texturesurfacelist[0]->lightmapinfo)
5876 // generate color arrays for the surfaces in this list
5877 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5879 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5880 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5882 if (surface->lightmapinfo->samples)
5884 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5885 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5886 VectorScale(lm, scale, c);
5887 if (surface->lightmapinfo->styles[1] != 255)
5889 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5891 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5892 VectorMA(c, scale, lm, c);
5893 if (surface->lightmapinfo->styles[2] != 255)
5896 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5897 VectorMA(c, scale, lm, c);
5898 if (surface->lightmapinfo->styles[3] != 255)
5901 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5902 VectorMA(c, scale, lm, c);
5912 rsurface.lightmapcolor4f = rsurface.array_color4f;
5913 rsurface.lightmapcolor4f_bufferobject = 0;
5914 rsurface.lightmapcolor4f_bufferoffset = 0;
5918 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5919 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5920 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5922 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5923 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5924 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5925 GL_Color(r, g, b, a);
5926 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5929 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5931 int texturesurfaceindex;
5935 vec3_t ambientcolor;
5936 vec3_t diffusecolor;
5940 VectorCopy(rsurface.modellight_lightdir, lightdir);
5941 f = 0.5f * r_refdef.lightmapintensity;
5942 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5943 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5944 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5945 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5946 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5947 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5948 if (VectorLength2(diffusecolor) > 0)
5950 // generate color arrays for the surfaces in this list
5951 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5953 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5954 int numverts = surface->num_vertices;
5955 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5956 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5957 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5958 // q3-style directional shading
5959 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5961 if ((f = DotProduct(c2, lightdir)) > 0)
5962 VectorMA(ambientcolor, f, diffusecolor, c);
5964 VectorCopy(ambientcolor, c);
5973 rsurface.lightmapcolor4f = rsurface.array_color4f;
5974 rsurface.lightmapcolor4f_bufferobject = 0;
5975 rsurface.lightmapcolor4f_bufferoffset = 0;
5979 r = ambientcolor[0];
5980 g = ambientcolor[1];
5981 b = ambientcolor[2];
5982 rsurface.lightmapcolor4f = NULL;
5983 rsurface.lightmapcolor4f_bufferobject = 0;
5984 rsurface.lightmapcolor4f_bufferoffset = 0;
5986 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5987 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5988 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5989 GL_Color(r, g, b, a);
5990 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5993 void RSurf_SetupDepthAndCulling(void)
5995 // submodels are biased to avoid z-fighting with world surfaces that they
5996 // may be exactly overlapping (avoids z-fighting artifacts on certain
5997 // doors and things in Quake maps)
5998 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5999 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6000 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6001 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6004 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6006 // transparent sky would be ridiculous
6007 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6009 R_SetupGenericShader(false);
6012 skyrendernow = false;
6013 // we have to force off the water clipping plane while rendering sky
6017 // restore entity matrix
6018 R_Mesh_Matrix(&rsurface.matrix);
6020 RSurf_SetupDepthAndCulling();
6022 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6023 // skymasking on them, and Quake3 never did sky masking (unlike
6024 // software Quake and software Quake2), so disable the sky masking
6025 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6026 // and skymasking also looks very bad when noclipping outside the
6027 // level, so don't use it then either.
6028 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6030 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6031 R_Mesh_ColorPointer(NULL, 0, 0);
6032 R_Mesh_ResetTextureState();
6033 if (skyrendermasked)
6035 R_SetupDepthOrShadowShader();
6036 // depth-only (masking)
6037 GL_ColorMask(0,0,0,0);
6038 // just to make sure that braindead drivers don't draw
6039 // anything despite that colormask...
6040 GL_BlendFunc(GL_ZERO, GL_ONE);
6044 R_SetupGenericShader(false);
6046 GL_BlendFunc(GL_ONE, GL_ZERO);
6048 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6049 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6050 if (skyrendermasked)
6051 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6053 R_Mesh_ResetTextureState();
6054 GL_Color(1, 1, 1, 1);
6057 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6059 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6062 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6063 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6064 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6065 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6066 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6067 if (rsurface.texture->backgroundcurrentskinframe)
6069 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6070 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6071 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6072 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6074 if(rsurface.texture->colormapping)
6076 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6077 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6079 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6080 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6081 R_Mesh_ColorPointer(NULL, 0, 0);
6083 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6085 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6087 // render background
6088 GL_BlendFunc(GL_ONE, GL_ZERO);
6090 GL_AlphaTest(false);
6092 GL_Color(1, 1, 1, 1);
6093 R_Mesh_ColorPointer(NULL, 0, 0);
6095 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6096 if (r_glsl_permutation)
6098 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6099 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6100 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6101 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6102 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6103 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6104 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);
6106 GL_LockArrays(0, 0);
6108 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6109 GL_DepthMask(false);
6110 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6111 R_Mesh_ColorPointer(NULL, 0, 0);
6113 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6114 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6115 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6118 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6119 if (!r_glsl_permutation)
6122 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6123 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6124 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6125 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6126 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6127 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6129 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6131 GL_BlendFunc(GL_ONE, GL_ZERO);
6133 GL_AlphaTest(false);
6137 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6138 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6139 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6142 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6144 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6145 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);
6147 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6151 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6152 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);
6154 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6156 GL_LockArrays(0, 0);
6159 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6161 // OpenGL 1.3 path - anything not completely ancient
6162 int texturesurfaceindex;
6163 qboolean applycolor;
6167 const texturelayer_t *layer;
6168 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6170 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6173 int layertexrgbscale;
6174 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6176 if (layerindex == 0)
6180 GL_AlphaTest(false);
6181 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6184 GL_DepthMask(layer->depthmask && writedepth);
6185 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6186 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6188 layertexrgbscale = 4;
6189 VectorScale(layer->color, 0.25f, layercolor);
6191 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6193 layertexrgbscale = 2;
6194 VectorScale(layer->color, 0.5f, layercolor);
6198 layertexrgbscale = 1;
6199 VectorScale(layer->color, 1.0f, layercolor);
6201 layercolor[3] = layer->color[3];
6202 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6203 R_Mesh_ColorPointer(NULL, 0, 0);
6204 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6205 switch (layer->type)
6207 case TEXTURELAYERTYPE_LITTEXTURE:
6208 memset(&m, 0, sizeof(m));
6209 m.tex[0] = R_GetTexture(r_texture_white);
6210 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6211 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6212 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6213 m.tex[1] = R_GetTexture(layer->texture);
6214 m.texmatrix[1] = layer->texmatrix;
6215 m.texrgbscale[1] = layertexrgbscale;
6216 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6217 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6218 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6219 R_Mesh_TextureState(&m);
6220 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6221 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6222 else if (rsurface.uselightmaptexture)
6223 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6225 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6227 case TEXTURELAYERTYPE_TEXTURE:
6228 memset(&m, 0, sizeof(m));
6229 m.tex[0] = R_GetTexture(layer->texture);
6230 m.texmatrix[0] = layer->texmatrix;
6231 m.texrgbscale[0] = layertexrgbscale;
6232 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6233 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6234 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6235 R_Mesh_TextureState(&m);
6236 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6238 case TEXTURELAYERTYPE_FOG:
6239 memset(&m, 0, sizeof(m));
6240 m.texrgbscale[0] = layertexrgbscale;
6243 m.tex[0] = R_GetTexture(layer->texture);
6244 m.texmatrix[0] = layer->texmatrix;
6245 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6246 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6247 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6249 R_Mesh_TextureState(&m);
6250 // generate a color array for the fog pass
6251 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6252 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6256 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6257 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)
6259 f = 1 - FogPoint_Model(v);
6260 c[0] = layercolor[0];
6261 c[1] = layercolor[1];
6262 c[2] = layercolor[2];
6263 c[3] = f * layercolor[3];
6266 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6269 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6271 GL_LockArrays(0, 0);
6274 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6276 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6277 GL_AlphaTest(false);
6281 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6283 // OpenGL 1.1 - crusty old voodoo path
6284 int texturesurfaceindex;
6288 const texturelayer_t *layer;
6289 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6291 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6293 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6295 if (layerindex == 0)
6299 GL_AlphaTest(false);
6300 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6303 GL_DepthMask(layer->depthmask && writedepth);
6304 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6305 R_Mesh_ColorPointer(NULL, 0, 0);
6306 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6307 switch (layer->type)
6309 case TEXTURELAYERTYPE_LITTEXTURE:
6310 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6312 // two-pass lit texture with 2x rgbscale
6313 // first the lightmap pass
6314 memset(&m, 0, sizeof(m));
6315 m.tex[0] = R_GetTexture(r_texture_white);
6316 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6317 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6318 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6319 R_Mesh_TextureState(&m);
6320 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6321 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6322 else if (rsurface.uselightmaptexture)
6323 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6325 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6326 GL_LockArrays(0, 0);
6327 // then apply the texture to it
6328 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6329 memset(&m, 0, sizeof(m));
6330 m.tex[0] = R_GetTexture(layer->texture);
6331 m.texmatrix[0] = layer->texmatrix;
6332 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6333 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6334 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6335 R_Mesh_TextureState(&m);
6336 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);
6340 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6341 memset(&m, 0, sizeof(m));
6342 m.tex[0] = R_GetTexture(layer->texture);
6343 m.texmatrix[0] = layer->texmatrix;
6344 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6345 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6346 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6347 R_Mesh_TextureState(&m);
6348 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6349 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);
6351 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);
6354 case TEXTURELAYERTYPE_TEXTURE:
6355 // singletexture unlit texture with transparency support
6356 memset(&m, 0, sizeof(m));
6357 m.tex[0] = R_GetTexture(layer->texture);
6358 m.texmatrix[0] = layer->texmatrix;
6359 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6360 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6361 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6362 R_Mesh_TextureState(&m);
6363 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);
6365 case TEXTURELAYERTYPE_FOG:
6366 // singletexture fogging
6367 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6370 memset(&m, 0, sizeof(m));
6371 m.tex[0] = R_GetTexture(layer->texture);
6372 m.texmatrix[0] = layer->texmatrix;
6373 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6374 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6375 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6376 R_Mesh_TextureState(&m);
6379 R_Mesh_ResetTextureState();
6380 // generate a color array for the fog pass
6381 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6385 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6386 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)
6388 f = 1 - FogPoint_Model(v);
6389 c[0] = layer->color[0];
6390 c[1] = layer->color[1];
6391 c[2] = layer->color[2];
6392 c[3] = f * layer->color[3];
6395 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6398 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6400 GL_LockArrays(0, 0);
6403 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6405 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6406 GL_AlphaTest(false);
6410 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6413 RSurf_SetupDepthAndCulling();
6414 if (r_glsl.integer && gl_support_fragment_shader)
6415 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6416 else if (gl_combine.integer && r_textureunits.integer >= 2)
6417 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6419 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6423 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6426 int texturenumsurfaces, endsurface;
6428 msurface_t *surface;
6429 msurface_t *texturesurfacelist[1024];
6431 // if the model is static it doesn't matter what value we give for
6432 // wantnormals and wanttangents, so this logic uses only rules applicable
6433 // to a model, knowing that they are meaningless otherwise
6434 if (ent == r_refdef.scene.worldentity)
6435 RSurf_ActiveWorldEntity();
6436 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6437 RSurf_ActiveModelEntity(ent, false, false);
6439 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6441 for (i = 0;i < numsurfaces;i = j)
6444 surface = rsurface.modelsurfaces + surfacelist[i];
6445 texture = surface->texture;
6446 R_UpdateTextureInfo(ent, texture);
6447 rsurface.texture = texture->currentframe;
6448 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6449 // scan ahead until we find a different texture
6450 endsurface = min(i + 1024, numsurfaces);
6451 texturenumsurfaces = 0;
6452 texturesurfacelist[texturenumsurfaces++] = surface;
6453 for (;j < endsurface;j++)
6455 surface = rsurface.modelsurfaces + surfacelist[j];
6456 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6458 texturesurfacelist[texturenumsurfaces++] = surface;
6460 // render the range of surfaces
6461 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6463 GL_AlphaTest(false);
6466 static void R_ProcessTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6471 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6473 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6475 RSurf_SetupDepthAndCulling();
6476 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6477 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6479 else if (r_showsurfaces.integer)
6481 RSurf_SetupDepthAndCulling();
6483 GL_BlendFunc(GL_ONE, GL_ZERO);
6485 GL_AlphaTest(false);
6486 R_Mesh_ColorPointer(NULL, 0, 0);
6487 R_Mesh_ResetTextureState();
6488 R_SetupGenericShader(false);
6489 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6490 if (!r_refdef.view.showdebug)
6492 GL_Color(0, 0, 0, 1);
6493 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6495 else if (r_showsurfaces.integer == 3)
6498 if(rsurface.texture && rsurface.texture->currentskinframe)
6499 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
6508 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
6510 c[0] = rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7;
6511 c[1] = rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7;
6512 c[2] = rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7;
6515 GL_Color(c[0], c[1], c[2], c[3]);
6517 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6518 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6519 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6521 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6523 r_refdef.lightmapintensity = 1;
6524 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3], false, false);
6525 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
6529 GL_Color(c[0], c[1], c[2], c[3]);
6530 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6531 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6535 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6537 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6538 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6539 else if (!rsurface.texture->currentnumlayers)
6541 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) && queueentity)
6543 // transparent surfaces get pushed off into the transparent queue
6544 int surfacelistindex;
6545 const msurface_t *surface;
6546 vec3_t tempcenter, center;
6547 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6549 surface = texturesurfacelist[surfacelistindex];
6550 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6551 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6552 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6553 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6554 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6559 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6560 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6565 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6569 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6572 for (i = 0;i < numsurfaces;i++)
6573 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6574 R_Water_AddWaterPlane(surfacelist[i]);
6577 // break the surface list down into batches by texture and use of lightmapping
6578 for (i = 0;i < numsurfaces;i = j)
6581 // texture is the base texture pointer, rsurface.texture is the
6582 // current frame/skin the texture is directing us to use (for example
6583 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6584 // use skin 1 instead)
6585 texture = surfacelist[i]->texture;
6586 rsurface.texture = texture->currentframe;
6587 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6588 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6590 // if this texture is not the kind we want, skip ahead to the next one
6591 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6595 // simply scan ahead until we find a different texture or lightmap state
6596 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6598 // render the range of surfaces
6599 R_ProcessTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6603 float locboxvertex3f[6*4*3] =
6605 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6606 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6607 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6608 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6609 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6610 1,0,0, 0,0,0, 0,1,0, 1,1,0
6613 unsigned short locboxelements[6*2*3] =
6623 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6626 cl_locnode_t *loc = (cl_locnode_t *)ent;
6628 float vertex3f[6*4*3];
6630 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6631 GL_DepthMask(false);
6632 GL_DepthRange(0, 1);
6633 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6635 GL_CullFace(GL_NONE);
6636 R_Mesh_Matrix(&identitymatrix);
6638 R_Mesh_VertexPointer(vertex3f, 0, 0);
6639 R_Mesh_ColorPointer(NULL, 0, 0);
6640 R_Mesh_ResetTextureState();
6641 R_SetupGenericShader(false);
6644 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6645 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6646 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6647 surfacelist[0] < 0 ? 0.5f : 0.125f);
6649 if (VectorCompare(loc->mins, loc->maxs))
6651 VectorSet(size, 2, 2, 2);
6652 VectorMA(loc->mins, -0.5f, size, mins);
6656 VectorCopy(loc->mins, mins);
6657 VectorSubtract(loc->maxs, loc->mins, size);
6660 for (i = 0;i < 6*4*3;)
6661 for (j = 0;j < 3;j++, i++)
6662 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6664 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
6667 void R_DrawLocs(void)
6670 cl_locnode_t *loc, *nearestloc;
6672 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6673 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6675 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6676 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6680 void R_DrawDebugModel(entity_render_t *ent)
6682 int i, j, k, l, flagsmask;
6683 const int *elements;
6685 msurface_t *surface;
6686 dp_model_t *model = ent->model;
6689 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
6691 R_Mesh_ColorPointer(NULL, 0, 0);
6692 R_Mesh_ResetTextureState();
6693 R_SetupGenericShader(false);
6694 GL_DepthRange(0, 1);
6695 GL_DepthTest(!r_showdisabledepthtest.integer);
6696 GL_DepthMask(false);
6697 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6699 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6701 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6702 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6704 if (brush->colbrushf && brush->colbrushf->numtriangles)
6706 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6707 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);
6708 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
6711 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6713 if (surface->num_collisiontriangles)
6715 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6716 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);
6717 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
6722 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6724 if (r_showtris.integer || r_shownormals.integer)
6726 if (r_showdisabledepthtest.integer)
6728 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6729 GL_DepthMask(false);
6733 GL_BlendFunc(GL_ONE, GL_ZERO);
6736 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6738 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
6740 rsurface.texture = surface->texture->currentframe;
6741 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6743 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6744 if (r_showtris.value > 0)
6746 if (!rsurface.texture->currentlayers->depthmask)
6747 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
6748 else if (ent == r_refdef.scene.worldentity)
6749 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
6751 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
6752 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6755 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6757 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6758 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6759 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6760 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6765 if (r_shownormals.value > 0)
6768 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6770 VectorCopy(rsurface.vertex3f + l * 3, v);
6771 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
6772 qglVertex3f(v[0], v[1], v[2]);
6773 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6774 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6775 qglVertex3f(v[0], v[1], v[2]);
6780 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6782 VectorCopy(rsurface.vertex3f + l * 3, v);
6783 GL_Color(0, r_refdef.view.colorscale, 0, 1);
6784 qglVertex3f(v[0], v[1], v[2]);
6785 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6786 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6787 qglVertex3f(v[0], v[1], v[2]);
6792 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6794 VectorCopy(rsurface.vertex3f + l * 3, v);
6795 GL_Color(0, 0, r_refdef.view.colorscale, 1);
6796 qglVertex3f(v[0], v[1], v[2]);
6797 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6798 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6799 qglVertex3f(v[0], v[1], v[2]);
6806 rsurface.texture = NULL;
6810 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6811 int r_maxsurfacelist = 0;
6812 msurface_t **r_surfacelist = NULL;
6813 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6815 int i, j, endj, f, flagsmask;
6817 dp_model_t *model = r_refdef.scene.worldmodel;
6818 msurface_t *surfaces;
6819 unsigned char *update;
6820 int numsurfacelist = 0;
6824 if (r_maxsurfacelist < model->num_surfaces)
6826 r_maxsurfacelist = model->num_surfaces;
6828 Mem_Free(r_surfacelist);
6829 r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
6832 RSurf_ActiveWorldEntity();
6834 surfaces = model->data_surfaces;
6835 update = model->brushq1.lightmapupdateflags;
6837 // update light styles on this submodel
6838 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6840 model_brush_lightstyleinfo_t *style;
6841 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6843 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6845 int *list = style->surfacelist;
6846 style->value = r_refdef.scene.lightstylevalue[style->style];
6847 for (j = 0;j < style->numsurfaces;j++)
6848 update[list[j]] = true;
6853 R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
6854 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL);
6858 R_DrawDebugModel(r_refdef.scene.worldentity);
6864 rsurface.uselightmaptexture = false;
6865 rsurface.texture = NULL;
6866 rsurface.rtlight = NULL;
6868 // add visible surfaces to draw list
6869 j = model->firstmodelsurface;
6870 endj = j + model->nummodelsurfaces;
6875 if (r_refdef.viewcache.world_surfacevisible[j])
6877 r_surfacelist[numsurfacelist++] = surfaces + j;
6878 // update lightmap if needed
6880 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
6886 if (r_refdef.viewcache.world_surfacevisible[j])
6887 r_surfacelist[numsurfacelist++] = surfaces + j;
6888 // don't do anything if there were no surfaces
6889 if (!numsurfacelist)
6891 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6892 GL_AlphaTest(false);
6894 // add to stats if desired
6895 if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes)
6897 r_refdef.stats.world_surfaces += numsurfacelist;
6898 for (j = 0;j < numsurfacelist;j++)
6899 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
6903 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6905 int i, j, endj, f, flagsmask;
6907 dp_model_t *model = ent->model;
6908 msurface_t *surfaces;
6909 unsigned char *update;
6910 int numsurfacelist = 0;
6914 if (r_maxsurfacelist < model->num_surfaces)
6916 r_maxsurfacelist = model->num_surfaces;
6918 Mem_Free(r_surfacelist);
6919 r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
6922 // if the model is static it doesn't matter what value we give for
6923 // wantnormals and wanttangents, so this logic uses only rules applicable
6924 // to a model, knowing that they are meaningless otherwise
6925 if (ent == r_refdef.scene.worldentity)
6926 RSurf_ActiveWorldEntity();
6927 else if ((ent->effects & EF_FULLBRIGHT) || (r_showsurfaces.integer && r_showsurfaces.integer != 3) || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6928 RSurf_ActiveModelEntity(ent, false, false);
6930 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6932 surfaces = model->data_surfaces;
6933 update = model->brushq1.lightmapupdateflags;
6935 // update light styles
6936 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6938 model_brush_lightstyleinfo_t *style;
6939 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6941 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6943 int *list = style->surfacelist;
6944 style->value = r_refdef.scene.lightstylevalue[style->style];
6945 for (j = 0;j < style->numsurfaces;j++)
6946 update[list[j]] = true;
6951 R_UpdateAllTextureInfo(ent);
6952 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL);
6956 R_DrawDebugModel(ent);
6962 rsurface.uselightmaptexture = false;
6963 rsurface.texture = NULL;
6964 rsurface.rtlight = NULL;
6966 // add visible surfaces to draw list
6967 j = model->firstmodelsurface;
6968 endj = j + model->nummodelsurfaces;
6970 r_surfacelist[numsurfacelist++] = surfaces + j;
6971 // don't do anything if there were no surfaces
6972 if (!numsurfacelist)
6974 // update lightmaps if needed
6976 for (j = model->firstmodelsurface;j < endj;j++)
6978 R_BuildLightMap(ent, surfaces + j);
6979 R_QueueSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6980 GL_AlphaTest(false);
6982 // add to stats if desired
6983 if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes)
6985 r_refdef.stats.entities++;
6986 r_refdef.stats.entities_surfaces += numsurfacelist;
6987 for (j = 0;j < numsurfacelist;j++)
6988 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;